@sequencemedia/number-parser 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/babel.config.cjs +39 -0
- package/index.mjs +78 -0
- package/package.json +33 -0
package/README.md
ADDED
package/babel.config.cjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const debug = require('debug')
|
|
2
|
+
|
|
3
|
+
const log = debug('@sequencemedia/number-parser')
|
|
4
|
+
|
|
5
|
+
log('`number-parser` is awake')
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
env: {
|
|
9
|
+
NODE_ENV = 'development'
|
|
10
|
+
}
|
|
11
|
+
} = process
|
|
12
|
+
|
|
13
|
+
function env () {
|
|
14
|
+
log({ NODE_ENV })
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
NODE_ENV === 'production'
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const presets = [
|
|
22
|
+
[
|
|
23
|
+
'@babel/env', {
|
|
24
|
+
targets: {
|
|
25
|
+
node: 'current'
|
|
26
|
+
},
|
|
27
|
+
useBuiltIns: 'usage',
|
|
28
|
+
corejs: 3
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
module.exports = (api) => {
|
|
34
|
+
if (api) api.cache.using(env)
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
presets
|
|
38
|
+
}
|
|
39
|
+
}
|
package/index.mjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://observablehq.com/@mbostock/localized-number-parsing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
function findGroup ({ type }) {
|
|
6
|
+
return type === 'group'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function findDecimal ({ type }) {
|
|
10
|
+
return type === 'decimal'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default class NumberParser {
|
|
14
|
+
constructor (locale = 'en-GB') {
|
|
15
|
+
const PARTS = (
|
|
16
|
+
new Intl.NumberFormat(locale) // `{ useGrouping: true }` is default
|
|
17
|
+
).formatToParts(12345.6)
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
value: GROUP
|
|
21
|
+
} = PARTS.find(findGroup)
|
|
22
|
+
|
|
23
|
+
const {
|
|
24
|
+
value: DECIMAL
|
|
25
|
+
} = PARTS.find(findDecimal)
|
|
26
|
+
|
|
27
|
+
const CHARS = (
|
|
28
|
+
new Intl.NumberFormat(locale, { useGrouping: false })
|
|
29
|
+
).format(9876543210).split('').reverse()
|
|
30
|
+
|
|
31
|
+
const group = new RegExp(`[${GROUP}]`, 'g')
|
|
32
|
+
const decimal = new RegExp(`[${DECIMAL}]`)
|
|
33
|
+
const chars = new RegExp(`[${CHARS.join('')}]`, 'g')
|
|
34
|
+
const charNumberMap = new Map(CHARS.map((d, n) => [d, n]))
|
|
35
|
+
|
|
36
|
+
function getNumberFor (char) {
|
|
37
|
+
return (
|
|
38
|
+
charNumberMap.get(char)
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function fromString (string) {
|
|
43
|
+
return (
|
|
44
|
+
string.trim()
|
|
45
|
+
.replace(group, '')
|
|
46
|
+
.replace(decimal, '.')
|
|
47
|
+
.replace(chars, getNumberFor)
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function toNumber (string) {
|
|
52
|
+
return (
|
|
53
|
+
string
|
|
54
|
+
? Number(string)
|
|
55
|
+
: NaN
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Parse `value` to a number or NaN
|
|
61
|
+
*
|
|
62
|
+
* @param {any} value
|
|
63
|
+
* @returns {number} A number or NaN
|
|
64
|
+
*/
|
|
65
|
+
function parse (value) {
|
|
66
|
+
return toNumber(fromString(String(value)))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.parse = parse
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function parse (value, locale) {
|
|
74
|
+
const numberParser = new NumberParser(locale)
|
|
75
|
+
return (
|
|
76
|
+
numberParser.parse(value)
|
|
77
|
+
)
|
|
78
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sequencemedia/number-parser",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Implements https://observablehq.com/@mbostock/localized-number-parsing",
|
|
5
|
+
"main": "./index.mjs",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Jonathan Perry for Sequence Media Limited",
|
|
9
|
+
"email": "sequencemedia@sequencemedia.net",
|
|
10
|
+
"url": "https://sequencemedia.net"
|
|
11
|
+
},
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git://github.com/sequencemedia/number-parser.git"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"lint": "eslint . --ext .mjs,.cjs",
|
|
19
|
+
"lint:fix": "npm run lint -- --fix",
|
|
20
|
+
"prepare": "husky install"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@babel/core": "^7.23.7",
|
|
24
|
+
"@babel/eslint-parser": "^7.23.3",
|
|
25
|
+
"@babel/preset-env": "^7.23.8",
|
|
26
|
+
"@sequencemedia/hooks": "^1.0.472",
|
|
27
|
+
"@types/node": "^20.11.0",
|
|
28
|
+
"core-js": "^3.35.0",
|
|
29
|
+
"eslint": "^8.56.0",
|
|
30
|
+
"eslint-config-standard": "^17.1.0",
|
|
31
|
+
"husky": "^8.0.3"
|
|
32
|
+
}
|
|
33
|
+
}
|