numberstring 0.2.0 → 1.0.1
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/CONTRIBUTING.md +49 -0
- package/LICENSE +21 -21
- package/README.md +349 -27
- package/index.js +700 -196
- package/languages/ar.js +128 -0
- package/languages/da.js +103 -0
- package/languages/de.js +103 -0
- package/languages/en.js +73 -0
- package/languages/es.js +106 -0
- package/languages/fi.js +103 -0
- package/languages/fr.js +99 -0
- package/languages/hi.js +124 -0
- package/languages/id.js +105 -0
- package/languages/index.js +131 -0
- package/languages/is.js +103 -0
- package/languages/it.js +129 -0
- package/languages/ja.js +122 -0
- package/languages/ko.js +122 -0
- package/languages/nl.js +112 -0
- package/languages/no.js +103 -0
- package/languages/pl.js +146 -0
- package/languages/pt.js +145 -0
- package/languages/ru.js +125 -0
- package/languages/sv.js +103 -0
- package/languages/th.js +123 -0
- package/languages/tr.js +102 -0
- package/languages/zh.js +116 -0
- package/package.json +27 -11
- package/.npmignore +0 -42
- package/npm-shrinkwrap.json +0 -1466
package/languages/zh.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mandarin Chinese number-to-words converter
|
|
3
|
+
* Uses the wan (万) system for grouping by 10,000
|
|
4
|
+
* @module languages/zh
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const ZH_ONES = Object.freeze(['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']);
|
|
8
|
+
const ZH_UNITS = Object.freeze(['', '十', '百', '千']);
|
|
9
|
+
const ZH_ILLIONS = Object.freeze(['', '万', '亿', '兆', '京', '垓', '秭', '穰', '沟', '涧', '正', '载']);
|
|
10
|
+
|
|
11
|
+
const MAX_VALUE = 10n ** 36n - 1n;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Convert a number to Mandarin Chinese words
|
|
15
|
+
* @param {number|bigint} n - The number to convert
|
|
16
|
+
* @returns {string|false} The Mandarin word representation
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* chinese(42) // '四十二'
|
|
20
|
+
* chinese(1000) // '一千'
|
|
21
|
+
* chinese(10000) // '一万'
|
|
22
|
+
*/
|
|
23
|
+
const chinese = (n) => {
|
|
24
|
+
let num;
|
|
25
|
+
|
|
26
|
+
if (typeof n === 'bigint') {
|
|
27
|
+
if (n < 0n || n > MAX_VALUE) return false;
|
|
28
|
+
num = n;
|
|
29
|
+
} else if (typeof n === 'number') {
|
|
30
|
+
if (isNaN(n) || n < 0 || !Number.isInteger(n)) return false;
|
|
31
|
+
if (n > Number.MAX_SAFE_INTEGER) return false;
|
|
32
|
+
num = BigInt(n);
|
|
33
|
+
} else {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (num === 0n) return '零';
|
|
38
|
+
|
|
39
|
+
const str = num.toString();
|
|
40
|
+
let result = '';
|
|
41
|
+
let needZero = false;
|
|
42
|
+
|
|
43
|
+
// Process in groups of 4 (wan system)
|
|
44
|
+
const len = str.length;
|
|
45
|
+
const groups = [];
|
|
46
|
+
for (let i = len; i > 0; i -= 4) {
|
|
47
|
+
const start = Math.max(0, i - 4);
|
|
48
|
+
groups.unshift(str.slice(start, i));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < groups.length; i++) {
|
|
52
|
+
const grp = parseInt(groups[i], 10);
|
|
53
|
+
const grpIdx = groups.length - 1 - i;
|
|
54
|
+
|
|
55
|
+
if (grp === 0) {
|
|
56
|
+
needZero = true;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (needZero && result) {
|
|
61
|
+
result += '零';
|
|
62
|
+
}
|
|
63
|
+
needZero = false;
|
|
64
|
+
|
|
65
|
+
const thousands = Math.floor(grp / 1000);
|
|
66
|
+
const hundreds = Math.floor((grp % 1000) / 100);
|
|
67
|
+
const tens = Math.floor((grp % 100) / 10);
|
|
68
|
+
const ones = grp % 10;
|
|
69
|
+
|
|
70
|
+
let grpStr = '';
|
|
71
|
+
let innerZero = false;
|
|
72
|
+
|
|
73
|
+
if (thousands > 0) {
|
|
74
|
+
grpStr += ZH_ONES[thousands] + ZH_UNITS[3];
|
|
75
|
+
innerZero = false;
|
|
76
|
+
} else if (result || i > 0) {
|
|
77
|
+
innerZero = true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (hundreds > 0) {
|
|
81
|
+
if (innerZero && grpStr) grpStr += '零';
|
|
82
|
+
grpStr += ZH_ONES[hundreds] + ZH_UNITS[2];
|
|
83
|
+
innerZero = false;
|
|
84
|
+
} else if (thousands > 0) {
|
|
85
|
+
innerZero = true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (tens > 0) {
|
|
89
|
+
if (innerZero && grpStr) grpStr += '零';
|
|
90
|
+
// Special: 10-19 at start is just 十X, not 一十X
|
|
91
|
+
if (tens === 1 && !result && thousands === 0 && hundreds === 0) {
|
|
92
|
+
grpStr += ZH_UNITS[1];
|
|
93
|
+
} else {
|
|
94
|
+
grpStr += ZH_ONES[tens] + ZH_UNITS[1];
|
|
95
|
+
}
|
|
96
|
+
innerZero = false;
|
|
97
|
+
} else if (hundreds > 0 || thousands > 0) {
|
|
98
|
+
innerZero = true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (ones > 0) {
|
|
102
|
+
if (innerZero && grpStr) grpStr += '零';
|
|
103
|
+
grpStr += ZH_ONES[ones];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
result += grpStr;
|
|
107
|
+
if (grpIdx > 0) {
|
|
108
|
+
result += ZH_ILLIONS[grpIdx];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export default chinese;
|
|
116
|
+
export { chinese };
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "numberstring",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Number One Way to Makes Words from Numbers",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
6
12
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
13
|
+
"demo": "node demo.js",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
16
|
+
"test:coverage": "vitest run --coverage",
|
|
17
|
+
"lint": "eslint . --format stylish",
|
|
18
|
+
"lint:report": "eslint . --format html -o coverage/lint-report.html"
|
|
10
19
|
},
|
|
11
20
|
"repository": {
|
|
12
21
|
"type": "git",
|
|
@@ -16,10 +25,14 @@
|
|
|
16
25
|
"number",
|
|
17
26
|
"string",
|
|
18
27
|
"word",
|
|
19
|
-
"
|
|
28
|
+
"words",
|
|
20
29
|
"integer",
|
|
30
|
+
"bigint",
|
|
21
31
|
"text",
|
|
22
|
-
"
|
|
32
|
+
"convert",
|
|
33
|
+
"english",
|
|
34
|
+
"quintillion",
|
|
35
|
+
"decillion"
|
|
23
36
|
],
|
|
24
37
|
"author": "Brian Funk",
|
|
25
38
|
"license": "MIT",
|
|
@@ -27,11 +40,14 @@
|
|
|
27
40
|
"url": "https://github.com/brianfunk/numberstring/issues"
|
|
28
41
|
},
|
|
29
42
|
"homepage": "https://github.com/brianfunk/numberstring#readme",
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
30
46
|
"devDependencies": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
47
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
48
|
+
"eslint": "^9.17.0",
|
|
49
|
+
"express": "^4.21.2",
|
|
50
|
+
"supertest": "^7.0.0",
|
|
51
|
+
"vitest": "^4.0.18"
|
|
36
52
|
}
|
|
37
53
|
}
|
package/.npmignore
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# Tests
|
|
2
|
-
test
|
|
3
|
-
tests
|
|
4
|
-
testing
|
|
5
|
-
|
|
6
|
-
# Services
|
|
7
|
-
.codeclimate.yml
|
|
8
|
-
.travis.yml
|
|
9
|
-
codecov.yml
|
|
10
|
-
.gitignore
|
|
11
|
-
|
|
12
|
-
# Logs
|
|
13
|
-
logs
|
|
14
|
-
*.log
|
|
15
|
-
npm-debug.log*
|
|
16
|
-
|
|
17
|
-
# Runtime data
|
|
18
|
-
pids
|
|
19
|
-
*.pid
|
|
20
|
-
*.seed
|
|
21
|
-
|
|
22
|
-
# Coverage directory used by tools like istanbul
|
|
23
|
-
coverage
|
|
24
|
-
|
|
25
|
-
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
|
26
|
-
.grunt
|
|
27
|
-
|
|
28
|
-
# node-waf configuration
|
|
29
|
-
.lock-wscript
|
|
30
|
-
|
|
31
|
-
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
|
32
|
-
build/Release
|
|
33
|
-
|
|
34
|
-
# Dependency directories
|
|
35
|
-
node_modules
|
|
36
|
-
jspm_packages
|
|
37
|
-
|
|
38
|
-
# Optional npm cache directory
|
|
39
|
-
.npm
|
|
40
|
-
|
|
41
|
-
# Optional REPL history
|
|
42
|
-
.node_repl_history
|