@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 ADDED
@@ -0,0 +1,5 @@
1
+ # @sequencemedia/number-parser
2
+
3
+ A version of [Localized Number Parsing](https://observablehq.com/@mbostock/localized-number-parsing) by Mike Bostock
4
+
5
+ Parse a _number_ from a localised _string_
@@ -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
+ }