n2words 1.13.0 → 1.14.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/lib/i18n/TR.mjs CHANGED
@@ -1,45 +1,40 @@
1
- import N2WordsBase from '../classes/N2WordsBase.mjs';
1
+ import BaseLanguage from '../classes/BaseLanguage.mjs';
2
2
 
3
- export class N2WordsTR extends N2WordsBase {
3
+ export class N2WordsTR extends BaseLanguage {
4
4
  constructor(options) {
5
- super();
6
-
7
- this.options = Object.assign({
8
- dropSpaces: false,
9
- }, options);
10
-
11
- this.negativeWord = 'eksi';
12
- this.separatorWord = 'virgül';
13
- this.zero = 'sıfır';
14
- this.spaceSeparator = (this.options.dropSpaces) ? '' : ' ';
15
- this.cards = [
16
- { '1000000000000000000': 'kentilyon' },
17
- { '1000000000000000': 'katrilyon' },
18
- { '1000000000000': 'trilyon' },
19
- { '1000000000': 'milyar' },
20
- { '1000000': 'milyon' },
21
- { '1000': 'bin' },
22
- { '100': 'yüz' },
23
- { '90': 'doksan' },
24
- { '80': 'seksen' },
25
- { '70': 'yetmiş' },
26
- { '60': 'altmış' },
27
- { '50': 'elli' },
28
- { '40': 'kırk' },
29
- { '30': 'otuz' },
30
- { '20': 'yirmi' },
31
- { '10': 'on' },
32
- { '9': 'dokuz' },
33
- { '8': 'sekiz' },
34
- { '7': 'yedi' },
35
- { '6': 'altı' },
36
- { '5': 'beş' },
37
- { '4': 'dört' },
38
- { '3': 'üç' },
39
- { '2': 'iki' },
40
- { '1': 'bir' },
41
- { '0': 'sıfır' }
42
- ];
5
+ super({
6
+ negativeWord: 'eksi',
7
+ separatorWord: 'virgül',
8
+ zero: 'sıfır',
9
+ spaceSeparator: (options.dropSpaces === true ? '' : ' '),
10
+ },[
11
+ [1000000000000000000n, 'kentilyon'],
12
+ [1000000000000000n, 'katrilyon'],
13
+ [1000000000000n, 'trilyon'],
14
+ [1000000000n, 'milyar'],
15
+ [1000000n, 'milyon'],
16
+ [1000n, 'bin'],
17
+ [100n, 'yüz'],
18
+ [90n, 'doksan'],
19
+ [80n, 'seksen'],
20
+ [70n, 'yetmiş'],
21
+ [60n, 'altmış'],
22
+ [50n, 'elli'],
23
+ [40n, 'kırk'],
24
+ [30n, 'otuz'],
25
+ [20n, 'yirmi'],
26
+ [10n, 'on'],
27
+ [9n, 'dokuz'],
28
+ [8n, 'sekiz'],
29
+ [7n, 'yedi'],
30
+ [6n, 'altı'],
31
+ [5n, 'beş'],
32
+ [4n, 'dört'],
33
+ [3n, 'üç'],
34
+ [2n, 'iki'],
35
+ [1n, 'bir'],
36
+ [0n, 'sıfır']
37
+ ]);
43
38
  }
44
39
 
45
40
  merge(lPair, rPair) {
@@ -57,6 +52,13 @@ export class N2WordsTR extends N2WordsBase {
57
52
  }
58
53
  }
59
54
 
60
- export default function(n, options = {}) {
61
- return new N2WordsTR(options).floatToCardinal(n);
55
+ /**
56
+ * Converts a value to cardinal (written) form.
57
+ * @param {number|string} value Number to be convert.
58
+ * @param {object} options Options for class.
59
+ * @throws {Error} Value cannot be invalid.
60
+ * @returns {string} Value in cardinal (written) format.
61
+ */
62
+ export default function(value, options = {}) {
63
+ return new N2WordsTR(options).floatToCardinal(value);
62
64
  }
package/lib/i18n/UK.mjs CHANGED
@@ -2,11 +2,12 @@ import {N2WordsRU} from './RU.mjs';
2
2
 
3
3
  export class N2WordsUK extends N2WordsRU {
4
4
  constructor() {
5
- super();
5
+ super({
6
+ negativeWord: 'мiнус',
7
+ separatorWord: 'кома',
8
+ zero: 'нуль'
9
+ });
6
10
 
7
- this.negativeWord = 'мiнус';
8
- this.separatorWord = 'кома';
9
- this.zero = 'нуль';
10
11
  this.feminine = false;
11
12
  this.ones = {
12
13
  1: 'один',
@@ -78,6 +79,12 @@ export class N2WordsUK extends N2WordsRU {
78
79
  }
79
80
  }
80
81
 
81
- export default function(n) {
82
- return new N2WordsUK().floatToCardinal(n);
82
+ /**
83
+ * Converts a value to cardinal (written) form.
84
+ * @param {number|string} value Number to be convert.
85
+ * @throws {Error} Value cannot be invalid.
86
+ * @returns {string} Value in cardinal (written) format.
87
+ */
88
+ export default function(value) {
89
+ return new N2WordsUK().floatToCardinal(value);
83
90
  }
package/lib/i18n/VI.mjs CHANGED
@@ -1,12 +1,13 @@
1
- import N2WordsAbs from '../classes/N2WordsAbs.mjs';
1
+ import AbstractLanguage from '../classes/AbstractLanguage.mjs';
2
2
 
3
- export class N2WordsID extends N2WordsAbs {
3
+ export class N2WordsID extends AbstractLanguage {
4
4
  constructor() {
5
- super();
5
+ super({
6
+ negativeWord: 'âm',
7
+ separatorWord: 'phẩy',
8
+ zero: 'không'
9
+ });
6
10
 
7
- this.negativeWord = 'âm';
8
- this.separatorWord = 'phẩy';
9
- this.zero = 'không';
10
11
  this.base = {
11
12
  0: 'không',
12
13
  1: 'một',
@@ -67,15 +68,15 @@ export class N2WordsID extends N2WordsAbs {
67
68
  let unitsPart = number % 10;
68
69
  let tensPart = number - unitsPart;
69
70
  let tensPartText = this.tens[tensPart];
70
- if (unitsPart === 0) {
71
+ if (unitsPart == 0) {
71
72
  return tensPartText;
72
73
  }
73
74
  let unitsPartText = this.base[unitsPart];
74
75
  let suffix = unitsPartText;
75
- if (unitsPart === 1) {
76
+ if (unitsPart == 1) {
76
77
  suffix = 'mốt';
77
78
  }
78
- if (unitsPart === 5) {
79
+ if (unitsPart == 5) {
79
80
  suffix = 'lăm';
80
81
  }
81
82
  return tensPartText + ' ' + suffix;
@@ -92,7 +93,7 @@ export class N2WordsID extends N2WordsAbs {
92
93
  if (words.length > 0) {
93
94
  words.push('lẻ');
94
95
  }
95
- if (tensUnitsPart === 5) {
96
+ if (tensUnitsPart == 5) {
96
97
  words.push('năm');
97
98
  } else {
98
99
  words.push(this.base[tensUnitsPart]);
@@ -106,16 +107,16 @@ export class N2WordsID extends N2WordsAbs {
106
107
 
107
108
  convertMore1000(number) {
108
109
  let words = [];
109
- let division = Math.floor(number / 1000);
110
+ let division = number / 1000n;
110
111
  let power = 1;
111
- while (division >= 1000) {
112
- division = Math.floor(division / 1000);
112
+ while (division >= 1000n) {
113
+ division = division / 1000n;
113
114
  power = power + 1;
114
115
  }
115
- let r = number - (division * Math.pow(1000, power));
116
+ let r = number - (division * BigInt(Math.pow(1000, power)));
116
117
  words.push(this.toCardinal(division), this.thousands[power]);
117
- if (r > 0) {
118
- if (r <= 99) {
118
+ if (r > 0n) {
119
+ if (r <= 99n) {
119
120
  words.push('lẻ');
120
121
  }
121
122
  words.push(this.toCardinal(r));
@@ -124,14 +125,14 @@ export class N2WordsID extends N2WordsAbs {
124
125
  }
125
126
 
126
127
  toCardinal(number) {
127
- if (number < 20) {
128
- return this.base[number];
128
+ if (number < 20n) {
129
+ return this.base[Number(number)];
129
130
  } else {
130
- if (number < 100) {
131
- return this.convertLess100(number);
131
+ if (number < 100n) {
132
+ return this.convertLess100(Number(number));
132
133
  } else {
133
- if (number < 1000) {
134
- return this.convertLess1000(number);
134
+ if (number < 1000n) {
135
+ return this.convertLess1000(Number(number));
135
136
  } else { // number >= 1000
136
137
  return this.convertMore1000(number);
137
138
  }
@@ -140,6 +141,12 @@ export class N2WordsID extends N2WordsAbs {
140
141
  }
141
142
  }
142
143
 
143
- export default function (n) {
144
- return new N2WordsID().floatToCardinal(n);
144
+ /**
145
+ * Converts a value to cardinal (written) form.
146
+ * @param {number|string} value Number to be convert.
147
+ * @throws {Error} Value cannot be invalid.
148
+ * @returns {string} Value in cardinal (written) format.
149
+ */
150
+ export default function (value) {
151
+ return new N2WordsID().floatToCardinal(value);
145
152
  }
package/lib/i18n/ZH.mjs CHANGED
@@ -1,31 +1,30 @@
1
- import N2WordsBase from '../classes/N2WordsBase.mjs';
1
+ import BaseLanguage from '../classes/BaseLanguage.mjs';
2
2
 
3
- export class N2WordsZH extends N2WordsBase {
3
+ export class N2WordsZH extends BaseLanguage {
4
4
  constructor() {
5
- super();
6
-
7
- this.negativeWord = '';
8
- this.separatorWord = '';
9
- this.zero = '';
10
- this.spaceSeparator = ''; // no
11
- this.cards = [
12
- { 1000000000000: '' },
13
- { 100000000: '亿' },
14
- { 10000: '' },
15
- { 1000: '' },
16
- { 100: '' },
17
- { 10: '' },
18
- { 9: '' },
19
- { 8: '' },
20
- { 7: '' },
21
- { 6: '' },
22
- { 5: '' },
23
- { 4: '' },
24
- { 3: '' },
25
- { 2: '' },
26
- { 1: '' },
27
- { 0: '零' },
28
- ];
5
+ super({
6
+ negativeWord: '负',
7
+ separatorWord: '',
8
+ zero: '',
9
+ spaceSeparator: ''
10
+ },[
11
+ [1000000000000n, '万'],
12
+ [100000000n, '亿'],
13
+ [10000n, ''],
14
+ [1000n, ''],
15
+ [100n, ''],
16
+ [10n, ''],
17
+ [9n, ''],
18
+ [8n, ''],
19
+ [7n, ''],
20
+ [6n, ''],
21
+ [5n, ''],
22
+ [4n, ''],
23
+ [3n, ''],
24
+ [2n, ''],
25
+ [1n, ''],
26
+ [0n, '']
27
+ ]);
29
28
  }
30
29
 
31
30
  merge(lPair, rPair) {
@@ -48,10 +47,11 @@ export class N2WordsZH extends N2WordsBase {
48
47
  return result;
49
48
  }
50
49
 
51
- toDecimal(decimalPart) {
52
- const decimalPartArray = Array.from(decimalPart);
50
+ decimalToCardinal(decimal) {
51
+ const decimalPartArray = decimal.split('');
52
+
53
53
  const decimalPartWordsArray = decimalPartArray.map(decimal =>
54
- this.getValueFromCards(decimal)
54
+ this.getCardWord(decimal)
55
55
  );
56
56
 
57
57
  return decimalPartWordsArray.join(this.spaceSeparator);
@@ -62,10 +62,16 @@ export class N2WordsZH extends N2WordsBase {
62
62
  }
63
63
 
64
64
  zeroDigit(num) {
65
- return Array.from(num.toString()).filter(c => c === '0').length;
65
+ return Array.from(num.toString()).filter(c => c == '0').length;
66
66
  }
67
67
  }
68
68
 
69
- export default function(n) {
70
- return new N2WordsZH().floatToCardinal(n);
69
+ /**
70
+ * Converts a value to cardinal (written) form.
71
+ * @param {number|string} value Number to be convert.
72
+ * @throws {Error} Value cannot be invalid.
73
+ * @returns {string} Value in cardinal (written) format.
74
+ */
75
+ export default function(value) {
76
+ return new N2WordsZH().floatToCardinal(value);
71
77
  }
package/lib/n2words.mjs CHANGED
@@ -27,115 +27,41 @@ import n2wordsUK from './i18n/UK.mjs';
27
27
  import n2wordsVI from './i18n/VI.mjs';
28
28
  import n2wordsZH from './i18n/ZH.mjs';
29
29
 
30
- const supportedLanguages = [
31
- 'en',
32
- 'fr',
33
- 'es',
34
- 'de',
35
- 'pt',
36
- 'it',
37
- 'tr',
38
- 'ru',
39
- 'cz',
40
- 'no',
41
- 'dk',
42
- 'pl',
43
- 'uk',
44
- 'lt',
45
- 'lv',
46
- 'ar',
47
- 'he',
48
- 'ko',
49
- 'nl',
50
- 'sr',
51
- 'fa',
52
- 'zh',
53
- 'hu',
54
- 'id',
55
- 'hr',
56
- 'vi',
57
- 'az',
58
- ];
59
-
60
30
  /**
61
31
  * Converts a number to written form.
62
- *
63
- * @param {number} n The number to convert.
32
+ * @param {number|string} value The number to convert.
64
33
  * @param {object} [options={lang: "en"}] User options.
65
- * @returns {string} Resulting text value.
34
+ * @returns {string} Value in written format.
66
35
  */
67
- export default function(n, options = {lang: 'en'}) {
68
- let lang = 'EN'; // default language
69
-
70
- if (options) {
71
- if (options.lang) {
72
- // lang is given in options
73
- if (supportedLanguages.indexOf(options.lang) !== -1)
74
- lang = options.lang.toUpperCase();
75
- else
76
- throw Error(
77
- 'ERROR: Unsupported language. Supported languages are: ' +
78
- supportedLanguages.sort().join(', ')
79
- );
80
- }
81
- }
82
-
83
- if (lang === 'EN') {
84
- return n2wordsEN(n);
85
- } else if (lang === 'FR') {
86
- return n2wordsFR(n);
87
- } else if (lang === 'ES') {
88
- return n2wordsES(n);
89
- } else if (lang === 'DE') {
90
- return n2wordsDE(n);
91
- } else if (lang === 'PT') {
92
- return n2wordsPT(n);
93
- } else if (lang === 'ID') {
94
- return n2wordsID(n);
95
- } else if (lang === 'IT') {
96
- return n2wordsIT(n);
97
- } else if (lang === 'TR') {
98
- return n2wordsTR(n, options);
99
- } else if (lang === 'RU') {
100
- return n2wordsRU(n);
101
- } else if (lang === 'CZ') {
102
- return n2wordsCZ(n);
103
- } else if (lang === 'NO') {
104
- return n2wordsNO(n);
105
- } else if (lang === 'DK') {
106
- return n2wordsDK(n);
107
- } else if (lang === 'PL') {
108
- return n2wordsPL(n);
109
- } else if (lang === 'UK') {
110
- return n2wordsUK(n);
111
- } else if (lang === 'LT') {
112
- return n2wordsLT(n);
113
- } else if (lang === 'LV') {
114
- return n2wordsLV(n);
115
- } else if (lang === 'AR') {
116
- return n2wordsAR(n);
117
- } else if (lang === 'HE') {
118
- // only for numbers <= 9999
119
- return n2wordsHE(n);
120
- } else if (lang === 'HR') {
121
- return n2wordsHR(n);
122
- } else if (lang === 'HU') {
123
- return n2wordsHU(n);
124
- } else if (lang === 'KO') {
125
- return n2wordsKO(n);
126
- } else if (lang === 'NL') {
127
- return n2wordsNL(n, options);
128
- } else if (lang === 'SR') {
129
- return n2wordsSR(n);
130
- } else if (lang === 'FA') {
131
- return n2wordsFA(n);
132
- } else if (lang === 'ZH') {
133
- return n2wordsZH(n);
134
- } else if (lang === 'VI') {
135
- return n2wordsVI(n);
136
- } else if (lang === 'AZ') {
137
- return n2wordsAZ(n);
138
- } else {
139
- return n2wordsEN(n);
36
+ export default function(value, options = {lang: 'en'}) {
37
+ switch (options.lang) {
38
+ case 'en': return n2wordsEN(value);
39
+ case 'fr': return n2wordsFR(value);
40
+ case 'es': return n2wordsES(value);
41
+ case 'de': return n2wordsDE(value);
42
+ case 'pt': return n2wordsPT(value);
43
+ case 'it': return n2wordsIT(value);
44
+ case 'tr': return n2wordsTR(value, options);
45
+ case 'ru': return n2wordsRU(value);
46
+ case 'cz': return n2wordsCZ(value);
47
+ case 'no': return n2wordsNO(value);
48
+ case 'dk': return n2wordsDK(value);
49
+ case 'pl': return n2wordsPL(value);
50
+ case 'uk': return n2wordsUK(value);
51
+ case 'lt': return n2wordsLT(value);
52
+ case 'lv': return n2wordsLV(value);
53
+ case 'ar': return n2wordsAR(value);
54
+ case 'he': return n2wordsHE(value); // only for numbers <= 9999
55
+ case 'ko': return n2wordsKO(value);
56
+ case 'nl': return n2wordsNL(value, options);
57
+ case 'sr': return n2wordsSR(value);
58
+ case 'fa': return n2wordsFA(value);
59
+ case 'zh': return n2wordsZH(value);
60
+ case 'hu': return n2wordsHU(value);
61
+ case 'id': return n2wordsID(value);
62
+ case 'hr': return n2wordsHR(value);
63
+ case 'vi': return n2wordsVI(value);
64
+ case 'az': return n2wordsAZ(value);
65
+ default: throw Error('Unsupported language: ' + value + '.');
140
66
  }
141
67
  }
package/package.json CHANGED
@@ -1,18 +1,22 @@
1
1
  {
2
2
  "name": "n2words",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "Convert numbers to words, in multiple languages",
5
5
  "main": "dist/n2words.js",
6
6
  "scripts": {
7
7
  "lint": "eslint --config .eslintrc.json lib/ test/",
8
8
  "test": "ava --verbose",
9
9
  "coverage": "c8 ava",
10
- "build": "webpack --config webpack.config.js --progress"
10
+ "build": "webpack --config webpack.config.js --progress",
11
+ "bench": "node bench.mjs"
11
12
  },
12
13
  "repository": {
13
14
  "type": "git",
14
15
  "url": "git+https://github.com/forzagreen/n2words.git"
15
16
  },
17
+ "engines": {
18
+ "node": "16 || >=18"
19
+ },
16
20
  "keywords": [
17
21
  "n2words",
18
22
  "convert",
@@ -57,19 +61,21 @@
57
61
  },
58
62
  "homepage": "https://github.com/forzagreen/n2words#readme",
59
63
  "devDependencies": {
60
- "@babel/core": "^7.20.12",
61
- "@babel/preset-env": "^7.20.2",
64
+ "@babel/core": "^7.21.8",
65
+ "@babel/preset-env": "^7.21.5",
62
66
  "ava": "^5.2.0",
63
67
  "babel-loader": "^9.1.2",
64
- "c8": "^7.12.0",
65
- "core-js": "^3.27.2",
66
- "eslint": "^8.33.0",
68
+ "benchmark": "^2.1.4",
69
+ "c8": "^7.13.0",
70
+ "core-js": "^3.30.2",
71
+ "eslint": "^8.40.0",
67
72
  "eslint-plugin-ava": "^14.0.0",
68
73
  "eslint-plugin-import": "^2.27.5",
69
- "eslint-plugin-jsdoc": "^39.8.0",
74
+ "eslint-plugin-jsdoc": "^44.2.3",
70
75
  "eslint-plugin-node": "^11.1.0",
71
- "webpack": "^5.75.0",
72
- "webpack-cli": "^5.0.1"
76
+ "microtime": "^3.1.1",
77
+ "webpack": "^5.82.1",
78
+ "webpack-cli": "^5.1.1"
73
79
  },
74
80
  "ava": {
75
81
  "files": [
package/webpack.config.js CHANGED
@@ -20,7 +20,7 @@ module.exports = {
20
20
  '@babel/preset-env',
21
21
  {
22
22
  useBuiltIns: 'usage',
23
- corejs: '3.27.2',
23
+ corejs: '3.30.1',
24
24
  },
25
25
  ],
26
26
  ],
@@ -1,72 +0,0 @@
1
- /**
2
- * Abstract class that must be inherited by all languages.
3
- */
4
- export default class {
5
- constructor() {
6
- this.negativeWord = '';
7
- this.separatorWord;
8
- this.zero;
9
- this.spaceSeparator = ' ';
10
- }
11
-
12
- /**
13
- * Convert a number to cardinal (written) format.
14
- *
15
- * @param {number} value The number value to convert to cardinal form.
16
- * @returns {string} Cardinal representation of number value.
17
- */
18
- toCardinal(value) {
19
- return value;
20
- }
21
-
22
- /**
23
- *
24
- * @param {number} decimalPart Decimal part of the number to convert.
25
- * @returns {string} Decimal part in written format.
26
- */
27
- toDecimal(decimalPart) {
28
- let decimalPartArray = Array.from(decimalPart);
29
- let decimalPartWordsArray = [];
30
- while (decimalPartArray[0] === '0') {
31
- // Leading zeros
32
- decimalPartArray.shift();
33
- decimalPartWordsArray.push(this.zero);
34
- }
35
- decimalPartWordsArray.push(this.toCardinal(parseInt(decimalPart, 10)));
36
-
37
- return decimalPartWordsArray.join(this.spaceSeparator);
38
- }
39
-
40
- /**
41
- *
42
- * @param {number} value Float number.
43
- * @throws {TypeError} Value must be a valid number.
44
- * @returns {string|undefined} Cardinal number in written format.
45
- */
46
- floatToCardinal(value) {
47
- if (isNaN(Number(value))) {
48
- throw new TypeError(`Invalid number: ${value}, of type: ${typeof value}`);
49
- }
50
- value = Number(value);
51
- let words = [];
52
- let positiveValue = Math.abs(value);
53
- if (value % 1 === 0 || typeof this.separatorWord === 'undefined') {
54
- // if value is integer or if separatorWord is not defined
55
- words = [this.toCardinal(positiveValue)];
56
- } else {
57
- const splittedValue = positiveValue.toString().split('.');
58
- const wholeNumberStr = this.toCardinal(parseInt(splittedValue[0], 10));
59
- this.wholeNumberInt = parseInt(splittedValue[0]);
60
-
61
- let decimalPart = splittedValue[1];
62
-
63
- const decimalPartStr = this.toDecimal(decimalPart);
64
- words = [wholeNumberStr, this.separatorWord, decimalPartStr];
65
- }
66
- if (value < 0) {
67
- // negative numbers
68
- words = [this.negativeWord].concat(words);
69
- }
70
- return words.join(this.spaceSeparator);
71
- }
72
- }