-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0a1bc33
Showing
18 changed files
with
456 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"presets": ["env"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# editorconfig.org | ||
root = true | ||
|
||
[*] | ||
indent_style = space | ||
indent_size = 4 | ||
end_of_line = lf | ||
charset = utf-8 | ||
trim_trailing_whitespace = true | ||
insert_final_newline = true | ||
|
||
[{.babelrc,.stylelintrc,.eslintrc*,jest.config,*.json,*.jsb3,*.jsb2,*.bowerrc,*.yaml,*.yml}] | ||
indent_size = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// http://eslint.org/docs/user-guide/configuring | ||
|
||
module.exports = { | ||
root: true, | ||
// parser: 'babel-eslint', | ||
// parserOptions: { | ||
// sourceType: 'module' | ||
// }, | ||
env: { | ||
browser: true, | ||
jest: true, | ||
}, | ||
// https://github.com/standard/standard/blob/master/docs/RULES-en.md | ||
extends: 'airbnb-base', | ||
// required to lint *.vue files | ||
// plugins: [ | ||
// 'html' | ||
// ], | ||
// // add your custom rules here | ||
rules: { | ||
'indent': ["error", 4], | ||
// allow paren-less arrow functions | ||
'arrow-parens': 0, | ||
// allow async-await | ||
'generator-star-spacing': 0, | ||
// allow debugger during development | ||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, | ||
'object-curly-spacing': 0, | ||
// disable length limit | ||
'max-len': 0, | ||
// allow `new Buffer()` | ||
'no-buffer-constructor': 0, | ||
// allow assigning to function parameter | ||
'no-param-reassign': 0, | ||
'no-underscore-dangle': 0, | ||
'no-else-return': 0, | ||
"no-unused-vars": ["warn", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }], | ||
'no-use-before-define' : 0, | ||
'object-curly-newline': 0, | ||
'import/prefer-default-export': 1, | ||
}, | ||
overrides: [ | ||
{ | ||
files: ['examples/*'], | ||
rules: { | ||
"import/no-extraneous-dependencies": 0, | ||
'no-console': 0, | ||
} | ||
} | ||
] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
|
||
# dependencies | ||
node_modules | ||
package-lock.json | ||
|
||
/coverage/ | ||
|
||
# logs | ||
npm-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
language: node_js | ||
node_js: | ||
- stable | ||
- lts/* | ||
jobs: | ||
include: | ||
- stage: Produce Coverage | ||
node_js: stable | ||
script: jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Copyright (c) 2018, Respective Authors all rights reserved. | ||
|
||
The MIT License | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module.exports = { | ||
moduleNameMapper: { | ||
'~(.*)$': '<rootDir>/$1', | ||
}, | ||
transform: { | ||
'^.+\\.jsx?$': 'babel-jest', | ||
}, | ||
transformIgnorePatterns: [ | ||
'node_modules/(?!(minterjs-util|other-module)/)', | ||
], | ||
/** fix jest bug @see https://github.com/facebook/jest/issues/6766 */ | ||
testURL: 'http://localhost' | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{ | ||
"name": "pretty-num", | ||
"version": "0.0.1", | ||
"description": "Lightweight module for formatting numbers to a human readable string", | ||
"main": "src/index.js", | ||
"files": [ | ||
"/src/" | ||
], | ||
"scripts": { | ||
"prepublishOnly": "npm run lint && npm run test", | ||
"lint": "eslint --ext .js ./src ./test", | ||
"lint:fix": "eslint --ext .js ./src ./test --fix", | ||
"test": "jest", | ||
"coverage": "jest --coverage" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/shrpne/pretty-num.git" | ||
}, | ||
"keywords": [ | ||
"format", | ||
"pretty", | ||
"number", | ||
"human", | ||
"readable", | ||
"string", | ||
"text" | ||
], | ||
"author": "shrpne <[email protected]>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/shrpne/pretty-num/issues" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"babel-core": "^6.26.3", | ||
"babel-jest": "^23.4.0", | ||
"babel-preset-env": "^1.7.0", | ||
"eslint": "^5.2.0", | ||
"eslint-config-airbnb-base": "^13.0.0", | ||
"eslint-plugin-import": "^2.13.0", | ||
"jest": "^23.4.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/** | ||
* | ||
* @param {number|string|Array} num - number or array of its parts | ||
* @return {string} | ||
*/ | ||
|
||
export default function fromExponential(num) { | ||
const eParts = getExponentialParts(num); | ||
if (!isExponential(eParts)) { | ||
throw new Error('Only exponential numbers can be converted properly'); | ||
} | ||
|
||
const sign = eParts[0][0] === '-' ? '-' : ''; | ||
const digits = eParts[0].replace(/^-/, ''); | ||
const digitsParts = digits.split('.'); | ||
const wholeDigits = digitsParts[0]; | ||
const fractionDigits = digitsParts[1] || ''; | ||
let e = Number(eParts[1]); | ||
|
||
if (e === 0) { | ||
return `${sign + wholeDigits}.${fractionDigits}`; | ||
} else if (e < 0) { | ||
// move dot to the left | ||
const countWholeAfterTransform = wholeDigits.length + e; | ||
if (countWholeAfterTransform > 0) { | ||
// transform whole to fraction | ||
const wholeDigitsAfterTransform = wholeDigits.substr(0, countWholeAfterTransform); | ||
const wholeDigitsTransformedToFracton = wholeDigits.substr(countWholeAfterTransform); | ||
return `${sign + wholeDigitsAfterTransform}.${wholeDigitsTransformedToFracton}${fractionDigits}`; | ||
} else { | ||
// not enough whole digits: prepend with fractional zeros | ||
|
||
// first e goes to dotted zero | ||
let zeros = '0.'; | ||
e += 1; | ||
while (e) { | ||
zeros += '0'; | ||
e += 1; | ||
} | ||
return sign + zeros + wholeDigits + fractionDigits; | ||
} | ||
} else { | ||
// move dot to the right | ||
const countFractionAfterTransform = fractionDigits.length - e; | ||
if (countFractionAfterTransform > 0) { | ||
// transform fraction to whole | ||
// countTransformedFractionToWhole = e | ||
const fractionDigitsAfterTransform = fractionDigits.substr(e); | ||
const fractionDigitsTransformedToWhole = fractionDigits.substr(0, e); | ||
return `${sign + wholeDigits + fractionDigitsTransformedToWhole}.${fractionDigitsAfterTransform}`; | ||
} else { | ||
// not enough fractions: append whole zeros | ||
let zerosCount = -countFractionAfterTransform; | ||
let zeros = ''; | ||
while (zerosCount) { | ||
zeros += '0'; | ||
zerosCount -= 1; | ||
} | ||
return sign + wholeDigits + fractionDigits + zeros; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Return two parts array of exponential number | ||
* @param {number|string|Array} num | ||
* @return {string[]} | ||
*/ | ||
export function getExponentialParts(num) { | ||
return Array.isArray(num) ? num : String(num).split(/[eE]/); | ||
} | ||
|
||
/** | ||
* | ||
* @param {number|string|Array} num - number or array of its parts | ||
*/ | ||
export function isExponential(num) { | ||
const eParts = getExponentialParts(num); | ||
return !Number.isNaN(Number(eParts[1])); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import stripZeros from './strip-zeros'; | ||
import reducePrecision from './reduce-precision'; | ||
import fromExponential from './from-exponential'; | ||
|
||
/** | ||
* @param {number|string} num | ||
* @param {number} [precision] | ||
* @return {string} | ||
*/ | ||
export default function prettyNum(num, precision) { | ||
num = stripZeros(num); | ||
const eParts = String(num).split(/[eE]/); | ||
|
||
if (eParts.length === 2) { | ||
num = fromExponential(num); | ||
} | ||
|
||
return reducePrecision(num, precision); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
* @param {string|number} num | ||
* @param {number} precision | ||
* @return {string} | ||
*/ | ||
export default function reducePrecision(num, precision) { | ||
const numString = num.toString(); | ||
|
||
// decimal exponential number | ||
if ((/e-/i).test(numString)) { | ||
return num.toPrecision(precision); | ||
} | ||
// integer exponential number | ||
if ((/e/i).test(numString)) { | ||
return numString; | ||
} | ||
|
||
|
||
const notMeaningfulFraction = numString.match(/\.0*/); | ||
if (notMeaningfulFraction) { | ||
const MeaningfulFractionIndex = notMeaningfulFraction.index + notMeaningfulFraction[0].length; | ||
return numString.substr(0, MeaningfulFractionIndex + precision); | ||
} | ||
|
||
return numString; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* Round `value` to `fractionDigitNumber` digits after dot | ||
* @param {number} value | ||
* @param {number} fractionDigitNumber - number of fraction digits after dot | ||
* @return {number} | ||
*/ | ||
export default function round(value, fractionDigitNumber) { | ||
if (fractionDigitNumber < 0) { | ||
throw new Error('Number of fraction digits should be positive'); | ||
} | ||
const tenPower = 10 ** fractionDigitNumber; | ||
return Math.round(value * tenPower) / tenPower; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Strip unnecessary last zeros after dot | ||
* @param num | ||
* @return {string|number} | ||
*/ | ||
export default function stripZeros(num) { | ||
if (typeof num === 'string') { | ||
// strip ending zeros | ||
if (num.indexOf('.') !== -1) { | ||
num = num.replace(/\.?0+$/, ''); | ||
} | ||
// strip leading zeros | ||
num = num.replace(/^0+(?!\.)(?!$)/, ''); | ||
} | ||
return num; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import fromExponential from '../src/from-exponential'; | ||
|
||
describe('prettyNum', () => { | ||
test('positive exponential', () => { | ||
expect(fromExponential(0.123e-10)).toEqual('0.0000000000123'); | ||
expect(fromExponential(1.123e-10)).toEqual('0.0000000001123'); | ||
expect(fromExponential(12.123e-10)).toEqual('0.0000000012123'); | ||
expect(fromExponential(123.123e-10)).toEqual('0.0000000123123'); | ||
expect(fromExponential(123.123e+20)).toEqual('12312300000000000000000'); | ||
expect(Number.MAX_VALUE).toEqual(1.7976931348623157e+308); | ||
expect(fromExponential(Number.MAX_VALUE)).toEqual('179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'); | ||
expect(Number.MIN_VALUE).toEqual(5e-324); | ||
expect(fromExponential(Number.MIN_VALUE)).toEqual('0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005'); | ||
}); | ||
|
||
test('negative exponential', () => { | ||
expect(fromExponential(-0.123e-10)).toEqual('-0.0000000000123'); | ||
expect(fromExponential(-1.123e-10)).toEqual('-0.0000000001123'); | ||
expect(fromExponential(-12.123e-10)).toEqual('-0.0000000012123'); | ||
expect(fromExponential(-123.123e-10)).toEqual('-0.0000000123123'); | ||
expect(fromExponential(-123.123e+20)).toEqual('-12312300000000000000000'); | ||
}); | ||
|
||
test('positive exponential-like strings', () => { | ||
expect(fromExponential('0.123e-1')).toEqual('0.0123'); | ||
expect(fromExponential('1.123e-1')).toEqual('0.1123'); | ||
expect(fromExponential('12.123e-1')).toEqual('1.2123'); | ||
expect(fromExponential('123.123e-1')).toEqual('12.3123'); | ||
expect(fromExponential('123.123e+4')).toEqual('1231230'); | ||
expect(fromExponential('123.123e+0')).toEqual('123.123'); | ||
}); | ||
|
||
test('negative exponential-like strings', () => { | ||
expect(fromExponential('-0.123e-1')).toEqual('-0.0123'); | ||
expect(fromExponential('-1.123e-1')).toEqual('-0.1123'); | ||
expect(fromExponential('-12.123e-1')).toEqual('-1.2123'); | ||
expect(fromExponential('-123.123e-1')).toEqual('-12.3123'); | ||
expect(fromExponential('-123.123e+4')).toEqual('-1231230'); | ||
expect(fromExponential('-123.123e+0')).toEqual('-123.123'); | ||
}); | ||
|
||
test('not exponential', () => { | ||
expect(() => fromExponential(0)).toThrow(); | ||
expect(() => fromExponential(0.0012, 3)).toThrow(); | ||
expect(() => fromExponential(123)).toThrow(); | ||
expect(() => fromExponential(123e+14)).toThrow(); // 12300000000000000 is not exponential | ||
expect(() => fromExponential(0.123e-4)).toThrow(); // 0.0000123 is not exponential | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import prettyNum from '../src/index'; | ||
|
||
describe('prettyNum', () => { | ||
test('exponential', () => { | ||
expect(prettyNum(1.123e-10, 3)).toEqual('0.000000000112'); | ||
expect(prettyNum(12.123e-10, 3)).toEqual('0.00000000121'); | ||
expect(prettyNum(123.123e-10, 3)).toEqual('0.0000000123'); | ||
expect(prettyNum(123.123e+4, 3)).toEqual('1231230'); | ||
}); | ||
|
||
test('exponential', () => { | ||
expect(prettyNum(0.00123456, 3)).toEqual('0.00123'); | ||
}); | ||
}); |
Oops, something went wrong.