cjk-number 0.1.0 → 0.2.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 +138 -20
- package/dist/index.d.ts +36 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +268 -29
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# cjk-number
|
|
2
2
|
|
|
3
|
-
Convert numbers
|
|
3
|
+
Convert numbers between Arabic values and CJK numeral systems.
|
|
4
|
+
|
|
5
|
+
Supported domains include:
|
|
6
|
+
|
|
7
|
+
- Traditional and simplified Chinese numerals
|
|
8
|
+
- Formal and informal variants
|
|
9
|
+
- Heavenly stems and earthly branches
|
|
10
|
+
- Korean and Japanese numeric kanji/hanja styles
|
|
11
|
+
- Kana sequence systems (gojuon and iroha)
|
|
12
|
+
- Negative numbers, decimals, and very large BigInt values
|
|
4
13
|
|
|
5
14
|
## Install
|
|
6
15
|
|
|
@@ -8,39 +17,56 @@ Convert numbers to and from CJK numeral systems, including traditional/simplifie
|
|
|
8
17
|
npm install cjk-number
|
|
9
18
|
```
|
|
10
19
|
|
|
20
|
+
## Runtime
|
|
21
|
+
|
|
22
|
+
- Node.js 18+
|
|
23
|
+
- ESM package
|
|
24
|
+
|
|
11
25
|
## Quick Start
|
|
12
26
|
|
|
13
27
|
```js
|
|
14
28
|
import {
|
|
29
|
+
integer,
|
|
15
30
|
cjkIdeographic,
|
|
16
|
-
cjkHeavenlyStem,
|
|
17
|
-
cjkEarthlyBranch,
|
|
18
|
-
tradChineseFormal,
|
|
19
31
|
tradChineseInformal,
|
|
32
|
+
tradChineseFormal,
|
|
20
33
|
simpChineseInformal,
|
|
21
34
|
simpChineseFormal,
|
|
22
|
-
|
|
23
|
-
|
|
35
|
+
cjkHeavenlyStem,
|
|
36
|
+
cjkEarthlyBranch,
|
|
37
|
+
koreanHangulFormal,
|
|
38
|
+
japaneseFormal,
|
|
39
|
+
hiragana
|
|
24
40
|
} from "cjk-number";
|
|
25
41
|
|
|
42
|
+
// parse string -> number/bigint
|
|
26
43
|
integer.parseInt("一千零二十三"); // 1023
|
|
27
44
|
integer.parseInt("壹仟零貳拾參"); // 1023
|
|
28
|
-
integer.parseInt("
|
|
29
|
-
integer.parseInt("
|
|
45
|
+
integer.parseInt("負一百零二"); // -102
|
|
46
|
+
integer.parseInt("一點二三"); // 1.23
|
|
47
|
+
integer.parseInt("一無量大數", { preferBigInt: true }); // 10n ** 68n
|
|
30
48
|
|
|
49
|
+
// format number/bigint -> string
|
|
50
|
+
cjkIdeographic.parse(1023); // "一千零二十三"
|
|
31
51
|
tradChineseFormal.parse(1023); // "壹仟零貳拾參"
|
|
32
52
|
simpChineseFormal.parse(1023); // "壹仟零贰拾叁"
|
|
53
|
+
koreanHangulFormal.parse(10n ** 68n); // "일무량대수"
|
|
54
|
+
japaneseFormal.parse(10n ** 68n); // "壱無量大数"
|
|
55
|
+
|
|
56
|
+
// stem/branch
|
|
33
57
|
cjkHeavenlyStem.parse(10); // "癸"
|
|
34
58
|
cjkEarthlyBranch.parse(12); // "亥"
|
|
35
59
|
|
|
36
|
-
|
|
60
|
+
// sequence systems
|
|
61
|
+
hiragana.parse(1); // "あ"
|
|
62
|
+
hiragana.parse(46); // "ん"
|
|
37
63
|
```
|
|
38
64
|
|
|
39
65
|
## API
|
|
40
66
|
|
|
41
67
|
### integer.parseInt(input, options?)
|
|
42
68
|
|
|
43
|
-
Parses CJK
|
|
69
|
+
Parses CJK text into number or bigint.
|
|
44
70
|
|
|
45
71
|
Options:
|
|
46
72
|
|
|
@@ -49,16 +75,26 @@ Options:
|
|
|
49
75
|
- heavenlyStemMode?: "fixed" | "cyclic"
|
|
50
76
|
- earthlyBranchMode?: "fixed" | "cyclic"
|
|
51
77
|
|
|
78
|
+
Behavior summary:
|
|
79
|
+
|
|
80
|
+
- If the value fits safely, returns number by default.
|
|
81
|
+
- If out of Number safe range, returns bigint automatically.
|
|
82
|
+
- If preferBigInt is true, always returns bigint for integer parse paths.
|
|
83
|
+
- Decimal parse returns number.
|
|
84
|
+
|
|
52
85
|
Examples:
|
|
53
86
|
|
|
54
87
|
```js
|
|
55
|
-
integer.parseInt("負一百零二"); // -102
|
|
56
|
-
integer.parseInt("一點二三"); // 1.23
|
|
57
88
|
integer.parseInt("九千零七兆一", { preferBigInt: true }); // 9007000000000001n
|
|
58
|
-
integer.parseInt("
|
|
89
|
+
integer.parseInt("癸"); // 10
|
|
90
|
+
integer.parseInt("亥"); // 12
|
|
91
|
+
integer.parseInt("壱京", { preferBigInt: true }); // 10n ** 16n
|
|
92
|
+
integer.parseInt("ぬ"); // 10 (iroha sequence symbol)
|
|
59
93
|
```
|
|
60
94
|
|
|
61
|
-
###
|
|
95
|
+
### Formatters
|
|
96
|
+
|
|
97
|
+
All formatters expose parse(value).
|
|
62
98
|
|
|
63
99
|
Available formatters:
|
|
64
100
|
|
|
@@ -69,6 +105,15 @@ Available formatters:
|
|
|
69
105
|
- simpChineseFormal
|
|
70
106
|
- cjkHeavenlyStem
|
|
71
107
|
- cjkEarthlyBranch
|
|
108
|
+
- koreanHangulFormal
|
|
109
|
+
- koreanHanjaFormal
|
|
110
|
+
- koreanHanjaInformal
|
|
111
|
+
- japaneseFormal
|
|
112
|
+
- japaneseInformal
|
|
113
|
+
- hiragana
|
|
114
|
+
- hiraganaIroha
|
|
115
|
+
- katakana
|
|
116
|
+
- katakanaIroha
|
|
72
117
|
|
|
73
118
|
Examples:
|
|
74
119
|
|
|
@@ -82,6 +127,38 @@ cjkHeavenlyStem.parse(11, { mode: "cyclic" }); // "甲"
|
|
|
82
127
|
cjkEarthlyBranch.parse(13, { mode: "cyclic" }); // "子"
|
|
83
128
|
```
|
|
84
129
|
|
|
130
|
+
## System Coverage
|
|
131
|
+
|
|
132
|
+
### Full numeric systems (large-unit aware)
|
|
133
|
+
|
|
134
|
+
These support complete number formatting/parsing and large units up to 無量大數 / 无量大数:
|
|
135
|
+
|
|
136
|
+
- tradChineseInformal
|
|
137
|
+
- tradChineseFormal
|
|
138
|
+
- simpChineseInformal
|
|
139
|
+
- simpChineseFormal
|
|
140
|
+
- koreanHangulFormal
|
|
141
|
+
- koreanHanjaFormal
|
|
142
|
+
- koreanHanjaInformal
|
|
143
|
+
- japaneseFormal
|
|
144
|
+
- japaneseInformal
|
|
145
|
+
|
|
146
|
+
### Sequence systems
|
|
147
|
+
|
|
148
|
+
These are order-based symbol sequences, not positional decimal numerals:
|
|
149
|
+
|
|
150
|
+
- cjkHeavenlyStem: 10 symbols
|
|
151
|
+
- cjkEarthlyBranch: 12 symbols
|
|
152
|
+
- hiragana: modern gojuon sequence (46 symbols)
|
|
153
|
+
- katakana: modern gojuon sequence (46 symbols)
|
|
154
|
+
- hiraganaIroha: traditional iroha sequence (47 symbols, includes ゐ and ゑ)
|
|
155
|
+
- katakanaIroha: traditional iroha sequence (47 symbols, includes ヰ and ヱ)
|
|
156
|
+
|
|
157
|
+
For sequence formatters:
|
|
158
|
+
|
|
159
|
+
- fixed mode: only accepts 1..length
|
|
160
|
+
- cyclic mode: wraps by sequence length
|
|
161
|
+
|
|
85
162
|
## Supported Large Units
|
|
86
163
|
|
|
87
164
|
Traditional:
|
|
@@ -92,8 +169,43 @@ Simplified:
|
|
|
92
169
|
|
|
93
170
|
万, 亿, 兆, 京, 垓, 秭, 穰, 沟, 涧, 正, 载, 极, 恒河沙, 阿僧祇, 那由他, 不可思议, 无量大数
|
|
94
171
|
|
|
172
|
+
Korean naming set:
|
|
173
|
+
|
|
174
|
+
만, 억, 조, 경, 해, 자, 양, 구, 간, 정, 재, 극, 항하사, 아승기, 나유타, 불가사의, 무량대수
|
|
175
|
+
|
|
176
|
+
Japanese naming set:
|
|
177
|
+
|
|
178
|
+
万, 億, 兆, 京, 垓, 秭, 穣, 溝, 澗, 正, 載, 極, 恒河沙, 阿僧祇, 那由他, 不可思議, 無量大数
|
|
179
|
+
|
|
180
|
+
Note:
|
|
181
|
+
|
|
182
|
+
- Historical texts may assign different powers for some high-order names.
|
|
183
|
+
- This package uses a fixed modern 10^4-step progression across supported large-unit systems.
|
|
184
|
+
|
|
185
|
+
## Strict Mode
|
|
186
|
+
|
|
187
|
+
strict: true validates input characters against an allowed set.
|
|
188
|
+
|
|
189
|
+
Use it when you want to reject unexpected symbols early.
|
|
190
|
+
|
|
191
|
+
```js
|
|
192
|
+
integer.parseInt("一億", { strict: true }); // ok
|
|
193
|
+
integer.parseInt("abc", { strict: true }); // throws SyntaxError
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Error Cases
|
|
197
|
+
|
|
198
|
+
Common thrown errors:
|
|
199
|
+
|
|
200
|
+
- SyntaxError: unsupported/invalid text shape
|
|
201
|
+
- RangeError: invalid formatter range in fixed sequence mode
|
|
202
|
+
- RangeError: non-integer passed to integer-only paths
|
|
203
|
+
- RangeError: decimal parse integer part exceeds Number.MAX_SAFE_INTEGER
|
|
204
|
+
|
|
95
205
|
## Development
|
|
96
206
|
|
|
207
|
+
Install and verify:
|
|
208
|
+
|
|
97
209
|
```sh
|
|
98
210
|
npm install
|
|
99
211
|
npm run typecheck
|
|
@@ -101,6 +213,18 @@ npm test
|
|
|
101
213
|
npm run build
|
|
102
214
|
```
|
|
103
215
|
|
|
216
|
+
Release preflight:
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
npm run release:check
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Dry-run package content:
|
|
223
|
+
|
|
224
|
+
```sh
|
|
225
|
+
npm run pack:check
|
|
226
|
+
```
|
|
227
|
+
|
|
104
228
|
Property-style test environment variables:
|
|
105
229
|
|
|
106
230
|
- CJK_TEST_SEED (default: 20260327)
|
|
@@ -113,12 +237,6 @@ Example:
|
|
|
113
237
|
CJK_TEST_SEED=42 CJK_TEST_SAMPLES=1000 CJK_TEST_MAX_DIGITS=69 npm test
|
|
114
238
|
```
|
|
115
239
|
|
|
116
|
-
## Notes
|
|
117
|
-
|
|
118
|
-
- Decimal parsing currently returns number.
|
|
119
|
-
- Very large integers can return bigint when preferBigInt is enabled.
|
|
120
|
-
- Heavenly stem and earthly branch parsing is auto-detected by symbol.
|
|
121
|
-
|
|
122
240
|
## License
|
|
123
241
|
|
|
124
242
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ export interface IntegerParseOptions {
|
|
|
9
9
|
earthlyBranchMode?: CyclicMode;
|
|
10
10
|
}
|
|
11
11
|
type IntegerLike = number | bigint;
|
|
12
|
-
export declare const tradFormalPositionalUnits: string[];
|
|
13
12
|
export declare const integer: {
|
|
14
13
|
parseInt(input: string, options?: IntegerParseOptions): number | bigint;
|
|
15
14
|
};
|
|
@@ -34,9 +33,45 @@ export declare const cjkHeavenlyStem: {
|
|
|
34
33
|
export declare const cjkEarthlyBranch: {
|
|
35
34
|
parse(value: IntegerLike, options?: SystemParseOptions): string;
|
|
36
35
|
};
|
|
36
|
+
export declare const koreanHangulFormal: {
|
|
37
|
+
parse(value: IntegerLike): string;
|
|
38
|
+
};
|
|
39
|
+
export declare const koreanHanjaFormal: {
|
|
40
|
+
parse(value: IntegerLike): string;
|
|
41
|
+
};
|
|
42
|
+
export declare const koreanHanjaInformal: {
|
|
43
|
+
parse(value: IntegerLike): string;
|
|
44
|
+
};
|
|
45
|
+
export declare const japaneseFormal: {
|
|
46
|
+
parse(value: IntegerLike): string;
|
|
47
|
+
};
|
|
48
|
+
export declare const japaneseInformal: {
|
|
49
|
+
parse(value: IntegerLike): string;
|
|
50
|
+
};
|
|
51
|
+
export declare const hiragana: {
|
|
52
|
+
parse(value: IntegerLike, options?: SystemParseOptions): string;
|
|
53
|
+
};
|
|
54
|
+
export declare const hiraganaIroha: {
|
|
55
|
+
parse(value: IntegerLike, options?: SystemParseOptions): string;
|
|
56
|
+
};
|
|
57
|
+
export declare const katakana: {
|
|
58
|
+
parse(value: IntegerLike, options?: SystemParseOptions): string;
|
|
59
|
+
};
|
|
60
|
+
export declare const katakanaIroha: {
|
|
61
|
+
parse(value: IntegerLike, options?: SystemParseOptions): string;
|
|
62
|
+
};
|
|
37
63
|
export declare const systems: {
|
|
38
64
|
heavenlyStem: readonly ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];
|
|
39
65
|
earthlyBranch: readonly ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"];
|
|
66
|
+
koreanHangulFormal: readonly ["일", "이", "삼", "사", "오", "육", "칠", "팔", "구"];
|
|
67
|
+
koreanHanjaFormal: readonly ["壹", "貳", "參", "四", "五", "六", "七", "八", "九"];
|
|
68
|
+
koreanHanjaInformal: readonly ["一", "二", "三", "四", "五", "六", "七", "八", "九"];
|
|
69
|
+
japaneseFormal: readonly ["壱", "弐", "参", "四", "五", "六", "七", "八", "九"];
|
|
70
|
+
japaneseInformal: readonly ["一", "二", "三", "四", "五", "六", "七", "八", "九"];
|
|
71
|
+
hiragana: readonly ["あ", "い", "う", "え", "お", "か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "つ", "て", "と", "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ", "ま", "み", "む", "め", "も", "や", "ゆ", "よ", "ら", "り", "る", "れ", "ろ", "わ", "を", "ん"];
|
|
72
|
+
hiraganaIroha: readonly ["い", "ろ", "は", "に", "ほ", "へ", "と", "ち", "り", "ぬ", "る", "を", "わ", "か", "よ", "た", "れ", "そ", "つ", "ね", "な", "ら", "む", "う", "ゐ", "の", "お", "く", "や", "ま", "け", "ふ", "こ", "え", "て", "あ", "さ", "き", "ゆ", "め", "み", "し", "ゑ", "ひ", "も", "せ", "す"];
|
|
73
|
+
katakana: readonly ["ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ヤ", "ユ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ヲ", "ン"];
|
|
74
|
+
katakanaIroha: readonly ["イ", "ロ", "ハ", "ニ", "ホ", "ヘ", "ト", "チ", "リ", "ヌ", "ル", "ヲ", "ワ", "カ", "ヨ", "タ", "レ", "ソ", "ツ", "ネ", "ナ", "ラ", "ム", "ウ", "ヰ", "ノ", "オ", "ク", "ヤ", "マ", "ケ", "フ", "コ", "エ", "テ", "ア", "サ", "キ", "ユ", "メ", "ミ", "シ", "ヱ", "ヒ", "モ", "セ", "ス"];
|
|
40
75
|
};
|
|
41
76
|
export {};
|
|
42
77
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,iBAAiB,CAAC,EAAE,UAAU,CAAC;CAChC;AAED,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,iBAAiB,CAAC,EAAE,UAAU,CAAC;CAChC;AAED,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AA8oBnC,eAAO,MAAM,OAAO;oBACF,MAAM,YAAY,mBAAmB,GAAG,MAAM,GAAG,MAAM;CAGxE,CAAC;AAEF,eAAO,MAAM,cAAc;iBACZ,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,mBAAmB;iBACjB,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,iBAAiB;iBACf,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,mBAAmB;iBACjB,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,iBAAiB;iBACf,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,eAAe;iBACb,WAAW,YAAW,kBAAkB,GAAQ,MAAM;CAGpE,CAAC;AAEF,eAAO,MAAM,gBAAgB;iBACd,WAAW,YAAW,kBAAkB,GAAQ,MAAM;CAGpE,CAAC;AAEF,eAAO,MAAM,kBAAkB;iBAChB,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,iBAAiB;iBACf,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,mBAAmB;iBACjB,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,cAAc;iBACZ,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,gBAAgB;iBACd,WAAW,GAAG,MAAM;CAMlC,CAAC;AAEF,eAAO,MAAM,QAAQ;iBACN,WAAW,YAAW,kBAAkB,GAAQ,MAAM;CAGpE,CAAC;AAEF,eAAO,MAAM,aAAa;iBACX,WAAW,YAAW,kBAAkB,GAAQ,MAAM;CAGpE,CAAC;AAEF,eAAO,MAAM,QAAQ;iBACN,WAAW,YAAW,kBAAkB,GAAQ,MAAM;CAGpE,CAAC;AAEF,eAAO,MAAM,aAAa;iBACX,WAAW,YAAW,kBAAkB,GAAQ,MAAM;CAGpE,CAAC;AAEF,eAAO,MAAM,OAAO;;;;;;;;;;;;CAYnB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,109 @@
|
|
|
1
1
|
const STEMS = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];
|
|
2
2
|
const BRANCHES = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"];
|
|
3
|
+
const KOREAN_HANGUL_DIGITS = ["일", "이", "삼", "사", "오", "육", "칠", "팔", "구"];
|
|
4
|
+
const KOREAN_HANJA_FORMAL_DIGITS = ["壹", "貳", "參", "四", "五", "六", "七", "八", "九"];
|
|
5
|
+
const KOREAN_HANJA_INFORMAL_DIGITS = ["一", "二", "三", "四", "五", "六", "七", "八", "九"];
|
|
6
|
+
const JAPANESE_FORMAL_DIGITS = ["壱", "弐", "参", "四", "五", "六", "七", "八", "九"];
|
|
7
|
+
const JAPANESE_INFORMAL_DIGITS = ["一", "二", "三", "四", "五", "六", "七", "八", "九"];
|
|
8
|
+
const HIRAGANA = [
|
|
9
|
+
"あ", "い", "う", "え", "お",
|
|
10
|
+
"か", "き", "く", "け", "こ",
|
|
11
|
+
"さ", "し", "す", "せ", "そ",
|
|
12
|
+
"た", "ち", "つ", "て", "と",
|
|
13
|
+
"な", "に", "ぬ", "ね", "の",
|
|
14
|
+
"は", "ひ", "ふ", "へ", "ほ",
|
|
15
|
+
"ま", "み", "む", "め", "も",
|
|
16
|
+
"や", "ゆ", "よ",
|
|
17
|
+
"ら", "り", "る", "れ", "ろ",
|
|
18
|
+
"わ", "を", "ん"
|
|
19
|
+
];
|
|
20
|
+
const HIRAGANA_IROHA = [
|
|
21
|
+
"い", "ろ", "は", "に", "ほ", "へ", "と",
|
|
22
|
+
"ち", "り", "ぬ", "る", "を", "わ", "か",
|
|
23
|
+
"よ", "た", "れ", "そ", "つ", "ね", "な",
|
|
24
|
+
"ら", "む", "う", "ゐ", "の", "お", "く",
|
|
25
|
+
"や", "ま", "け", "ふ", "こ", "え", "て",
|
|
26
|
+
"あ", "さ", "き", "ゆ", "め", "み", "し",
|
|
27
|
+
"ゑ", "ひ", "も", "せ", "す"
|
|
28
|
+
];
|
|
29
|
+
const KATAKANA = [
|
|
30
|
+
"ア", "イ", "ウ", "エ", "オ",
|
|
31
|
+
"カ", "キ", "ク", "ケ", "コ",
|
|
32
|
+
"サ", "シ", "ス", "セ", "ソ",
|
|
33
|
+
"タ", "チ", "ツ", "テ", "ト",
|
|
34
|
+
"ナ", "ニ", "ヌ", "ネ", "ノ",
|
|
35
|
+
"ハ", "ヒ", "フ", "ヘ", "ホ",
|
|
36
|
+
"マ", "ミ", "ム", "メ", "モ",
|
|
37
|
+
"ヤ", "ユ", "ヨ",
|
|
38
|
+
"ラ", "リ", "ル", "レ", "ロ",
|
|
39
|
+
"ワ", "ヲ", "ン"
|
|
40
|
+
];
|
|
41
|
+
const KATAKANA_IROHA = [
|
|
42
|
+
"イ", "ロ", "ハ", "ニ", "ホ", "ヘ", "ト",
|
|
43
|
+
"チ", "リ", "ヌ", "ル", "ヲ", "ワ", "カ",
|
|
44
|
+
"ヨ", "タ", "レ", "ソ", "ツ", "ネ", "ナ",
|
|
45
|
+
"ラ", "ム", "ウ", "ヰ", "ノ", "オ", "ク",
|
|
46
|
+
"ヤ", "マ", "ケ", "フ", "コ", "エ", "テ",
|
|
47
|
+
"ア", "サ", "キ", "ユ", "メ", "ミ", "シ",
|
|
48
|
+
"ヱ", "ヒ", "モ", "セ", "ス"
|
|
49
|
+
];
|
|
50
|
+
const KOREAN_BIG_UNITS = [
|
|
51
|
+
"만",
|
|
52
|
+
"억",
|
|
53
|
+
"조",
|
|
54
|
+
"경",
|
|
55
|
+
"해",
|
|
56
|
+
"자",
|
|
57
|
+
"양",
|
|
58
|
+
"구",
|
|
59
|
+
"간",
|
|
60
|
+
"정",
|
|
61
|
+
"재",
|
|
62
|
+
"극",
|
|
63
|
+
"항하사",
|
|
64
|
+
"아승기",
|
|
65
|
+
"나유타",
|
|
66
|
+
"불가사의",
|
|
67
|
+
"무량대수"
|
|
68
|
+
];
|
|
69
|
+
const JAPANESE_BIG_UNITS = [
|
|
70
|
+
"万",
|
|
71
|
+
"億",
|
|
72
|
+
"兆",
|
|
73
|
+
"京",
|
|
74
|
+
"垓",
|
|
75
|
+
"秭",
|
|
76
|
+
"穣",
|
|
77
|
+
"溝",
|
|
78
|
+
"澗",
|
|
79
|
+
"正",
|
|
80
|
+
"載",
|
|
81
|
+
"極",
|
|
82
|
+
"恒河沙",
|
|
83
|
+
"阿僧祇",
|
|
84
|
+
"那由他",
|
|
85
|
+
"不可思議",
|
|
86
|
+
"無量大数"
|
|
87
|
+
];
|
|
88
|
+
const SEQUENCE_SYMBOL_TO_NUMBER = (() => {
|
|
89
|
+
const map = {};
|
|
90
|
+
const put = (chars) => {
|
|
91
|
+
chars.forEach((char, index) => {
|
|
92
|
+
map[char] = index + 1;
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
put(STEMS);
|
|
96
|
+
put(BRANCHES);
|
|
97
|
+
put(HIRAGANA);
|
|
98
|
+
put(HIRAGANA_IROHA);
|
|
99
|
+
put(KATAKANA);
|
|
100
|
+
put(KATAKANA_IROHA);
|
|
101
|
+
return map;
|
|
102
|
+
})();
|
|
3
103
|
const CANONICAL_DIGITS = {
|
|
4
104
|
"零": 0,
|
|
105
|
+
"영": 0,
|
|
106
|
+
"령": 0,
|
|
5
107
|
"〇": 0,
|
|
6
108
|
"○": 0,
|
|
7
109
|
"一": 1,
|
|
@@ -74,43 +176,74 @@ const SIMP_BIG_UNITS = [
|
|
|
74
176
|
"不可思议",
|
|
75
177
|
"无量大数"
|
|
76
178
|
];
|
|
77
|
-
function buildFormalPositionalUnits(bigUnits) {
|
|
78
|
-
const result = [""];
|
|
79
|
-
for (const unit of bigUnits) {
|
|
80
|
-
result.push("拾", "佰", "仟", unit);
|
|
81
|
-
}
|
|
82
|
-
return result;
|
|
83
|
-
}
|
|
84
179
|
function createBigUnitOrder(units) {
|
|
85
180
|
return units
|
|
86
181
|
.map((unit, index) => [unit, 10n ** BigInt((index + 1) * 4)])
|
|
87
182
|
.reverse();
|
|
88
183
|
}
|
|
89
|
-
export const tradFormalPositionalUnits = buildFormalPositionalUnits(TRAD_BIG_UNITS);
|
|
90
184
|
const TRAD_INFORMAL_SET = {
|
|
91
185
|
zero: "零",
|
|
186
|
+
point: "點",
|
|
92
187
|
digits: ["一", "二", "三", "四", "五", "六", "七", "八", "九"],
|
|
93
188
|
smallUnits: ["十", "百", "千"],
|
|
94
189
|
bigUnits: [...TRAD_BIG_UNITS]
|
|
95
190
|
};
|
|
96
191
|
const TRAD_FORMAL_SET = {
|
|
97
192
|
zero: "零",
|
|
193
|
+
point: "點",
|
|
98
194
|
digits: ["壹", "貳", "參", "肆", "伍", "陸", "柒", "捌", "玖"],
|
|
99
195
|
smallUnits: ["拾", "佰", "仟"],
|
|
100
196
|
bigUnits: [...TRAD_BIG_UNITS]
|
|
101
197
|
};
|
|
102
198
|
const SIMP_INFORMAL_SET = {
|
|
103
199
|
zero: "零",
|
|
200
|
+
point: "点",
|
|
104
201
|
digits: ["一", "二", "三", "四", "五", "六", "七", "八", "九"],
|
|
105
202
|
smallUnits: ["十", "百", "千"],
|
|
106
203
|
bigUnits: [...SIMP_BIG_UNITS]
|
|
107
204
|
};
|
|
108
205
|
const SIMP_FORMAL_SET = {
|
|
109
206
|
zero: "零",
|
|
207
|
+
point: "点",
|
|
110
208
|
digits: ["壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"],
|
|
111
209
|
smallUnits: ["拾", "佰", "仟"],
|
|
112
210
|
bigUnits: [...SIMP_BIG_UNITS]
|
|
113
211
|
};
|
|
212
|
+
const KOREAN_HANGUL_SET = {
|
|
213
|
+
zero: "영",
|
|
214
|
+
point: "점",
|
|
215
|
+
digits: [...KOREAN_HANGUL_DIGITS],
|
|
216
|
+
smallUnits: ["십", "백", "천"],
|
|
217
|
+
bigUnits: [...KOREAN_BIG_UNITS]
|
|
218
|
+
};
|
|
219
|
+
const KOREAN_HANJA_FORMAL_SET = {
|
|
220
|
+
zero: "零",
|
|
221
|
+
point: "점",
|
|
222
|
+
digits: [...KOREAN_HANJA_FORMAL_DIGITS],
|
|
223
|
+
smallUnits: ["拾", "佰", "仟"],
|
|
224
|
+
bigUnits: [...TRAD_BIG_UNITS]
|
|
225
|
+
};
|
|
226
|
+
const KOREAN_HANJA_INFORMAL_SET = {
|
|
227
|
+
zero: "零",
|
|
228
|
+
point: "점",
|
|
229
|
+
digits: [...KOREAN_HANJA_INFORMAL_DIGITS],
|
|
230
|
+
smallUnits: ["十", "百", "千"],
|
|
231
|
+
bigUnits: [...TRAD_BIG_UNITS]
|
|
232
|
+
};
|
|
233
|
+
const JAPANESE_FORMAL_SET = {
|
|
234
|
+
zero: "零",
|
|
235
|
+
point: "点",
|
|
236
|
+
digits: [...JAPANESE_FORMAL_DIGITS],
|
|
237
|
+
smallUnits: ["拾", "百", "千"],
|
|
238
|
+
bigUnits: [...JAPANESE_BIG_UNITS]
|
|
239
|
+
};
|
|
240
|
+
const JAPANESE_INFORMAL_SET = {
|
|
241
|
+
zero: "零",
|
|
242
|
+
point: "点",
|
|
243
|
+
digits: [...JAPANESE_INFORMAL_DIGITS],
|
|
244
|
+
smallUnits: ["十", "百", "千"],
|
|
245
|
+
bigUnits: [...JAPANESE_BIG_UNITS]
|
|
246
|
+
};
|
|
114
247
|
const BIG_UNIT_ORDER = createBigUnitOrder(SIMP_BIG_UNITS);
|
|
115
248
|
function normalizeInput(raw) {
|
|
116
249
|
const trimmed = raw.trim();
|
|
@@ -119,9 +252,43 @@ function normalizeInput(raw) {
|
|
|
119
252
|
}
|
|
120
253
|
return trimmed
|
|
121
254
|
.replace(/負|负/g, "-")
|
|
255
|
+
.replace(/점/g, ".")
|
|
122
256
|
.replace(/點|点/g, ".")
|
|
257
|
+
.replace(/무량대수/g, "无量大数")
|
|
258
|
+
.replace(/불가사의/g, "不可思议")
|
|
259
|
+
.replace(/나유타/g, "那由他")
|
|
260
|
+
.replace(/아승기/g, "阿僧祇")
|
|
261
|
+
.replace(/항하사/g, "恒河沙")
|
|
262
|
+
.replace(/재/g, "载")
|
|
263
|
+
.replace(/정/g, "正")
|
|
264
|
+
.replace(/간/g, "涧")
|
|
265
|
+
.replace(/구/g, "沟")
|
|
266
|
+
.replace(/양/g, "穰")
|
|
267
|
+
.replace(/자/g, "秭")
|
|
268
|
+
.replace(/해/g, "垓")
|
|
269
|
+
.replace(/경/g, "京")
|
|
270
|
+
.replace(/조/g, "兆")
|
|
271
|
+
.replace(/억/g, "亿")
|
|
272
|
+
.replace(/만/g, "万")
|
|
273
|
+
.replace(/천/g, "千")
|
|
274
|
+
.replace(/백/g, "百")
|
|
275
|
+
.replace(/십/g, "十")
|
|
276
|
+
.replace(/일/g, "一")
|
|
277
|
+
.replace(/이/g, "二")
|
|
278
|
+
.replace(/삼/g, "三")
|
|
279
|
+
.replace(/사/g, "四")
|
|
280
|
+
.replace(/오/g, "五")
|
|
281
|
+
.replace(/육/g, "六")
|
|
282
|
+
.replace(/칠/g, "七")
|
|
283
|
+
.replace(/팔/g, "八")
|
|
284
|
+
.replace(/구/g, "九")
|
|
285
|
+
.replace(/壱/g, "一")
|
|
286
|
+
.replace(/弐/g, "二")
|
|
287
|
+
.replace(/参/g, "三")
|
|
123
288
|
.replace(/無量大數/g, "无量大数")
|
|
289
|
+
.replace(/無量大数/g, "无量大数")
|
|
124
290
|
.replace(/不可思議/g, "不可思议")
|
|
291
|
+
.replace(/穣/g, "穰")
|
|
125
292
|
.replace(/恆河沙/g, "恒河沙")
|
|
126
293
|
.replace(/載/g, "载")
|
|
127
294
|
.replace(/極/g, "极")
|
|
@@ -151,7 +318,7 @@ function parseDigitsOnly(input) {
|
|
|
151
318
|
}
|
|
152
319
|
result += String(digit);
|
|
153
320
|
}
|
|
154
|
-
return BigInt(result
|
|
321
|
+
return BigInt(result);
|
|
155
322
|
}
|
|
156
323
|
function parseSection(section) {
|
|
157
324
|
if (!section) {
|
|
@@ -232,7 +399,7 @@ function toBestNumeric(value, preferBigInt) {
|
|
|
232
399
|
return Number(value);
|
|
233
400
|
}
|
|
234
401
|
function validateStrictCharacters(input) {
|
|
235
|
-
const allowed = /^[0-9
|
|
402
|
+
const allowed = /^[0-9零〇○一二三四五六七八九十百千萬万億亿兆京垓秭穰溝沟澗涧正載载極极恆恒河沙阿僧祇那由他不思議议可無无量大數数點点점壹貳贰參叁肆伍陸陆柒捌玖兩两拾佰仟負负壱弐参ぁ-ゟ゠-ヿ가-힣.-]+$/;
|
|
236
403
|
if (!allowed.test(input)) {
|
|
237
404
|
throw new SyntaxError("Input contains unsupported characters in strict mode");
|
|
238
405
|
}
|
|
@@ -261,9 +428,6 @@ function parseCycle(input, chars, mode) {
|
|
|
261
428
|
return value;
|
|
262
429
|
}
|
|
263
430
|
function formatSection(section, set) {
|
|
264
|
-
if (section === 0) {
|
|
265
|
-
return "";
|
|
266
|
-
}
|
|
267
431
|
const values = [1000, 100, 10, 1];
|
|
268
432
|
const units = [set.smallUnits[2], set.smallUnits[1], set.smallUnits[0], ""];
|
|
269
433
|
let output = "";
|
|
@@ -307,9 +471,7 @@ function formatChineseInteger(value, set) {
|
|
|
307
471
|
for (let i = sections.length - 1; i >= 0; i -= 1) {
|
|
308
472
|
const section = sections[i];
|
|
309
473
|
if (section === 0) {
|
|
310
|
-
|
|
311
|
-
pendingZero = true;
|
|
312
|
-
}
|
|
474
|
+
pendingZero = Boolean(output);
|
|
313
475
|
continue;
|
|
314
476
|
}
|
|
315
477
|
if (output && (pendingZero || section < 1000)) {
|
|
@@ -346,20 +508,28 @@ function formatDecimal(value, set) {
|
|
|
346
508
|
const digit = Number(ch);
|
|
347
509
|
fracText += digit === 0 ? set.zero : set.digits[digit - 1];
|
|
348
510
|
}
|
|
349
|
-
const withSign = `${intText}
|
|
511
|
+
const withSign = `${intText}${set.point}${fracText}`;
|
|
350
512
|
return negative ? `負${withSign}` : withSign;
|
|
351
513
|
}
|
|
352
514
|
function parseValue(input, options = {}) {
|
|
353
515
|
const modeStem = options.heavenlyStemMode ?? "fixed";
|
|
354
516
|
const modeBranch = options.earthlyBranchMode ?? "fixed";
|
|
355
|
-
|
|
356
|
-
if (stemIndex >= 0) {
|
|
517
|
+
try {
|
|
357
518
|
return parseCycle(input, STEMS, modeStem);
|
|
358
519
|
}
|
|
359
|
-
|
|
360
|
-
|
|
520
|
+
catch {
|
|
521
|
+
// Not a heavenly stem, continue to next parser.
|
|
522
|
+
}
|
|
523
|
+
try {
|
|
361
524
|
return parseCycle(input, BRANCHES, modeBranch);
|
|
362
525
|
}
|
|
526
|
+
catch {
|
|
527
|
+
// Not an earthly branch, continue to sequence/numeric parsing.
|
|
528
|
+
}
|
|
529
|
+
const sequenceValue = SEQUENCE_SYMBOL_TO_NUMBER[input];
|
|
530
|
+
if (sequenceValue !== undefined) {
|
|
531
|
+
return sequenceValue;
|
|
532
|
+
}
|
|
363
533
|
const normalized = normalizeInput(input);
|
|
364
534
|
if (options.strict) {
|
|
365
535
|
validateStrictCharacters(normalized);
|
|
@@ -370,9 +540,9 @@ function parseValue(input, options = {}) {
|
|
|
370
540
|
throw new SyntaxError("Missing numeric content");
|
|
371
541
|
}
|
|
372
542
|
if (body.includes(".")) {
|
|
373
|
-
const [intRaw, fracRaw] = body.split(".");
|
|
543
|
+
const [intRaw, fracRaw = ""] = body.split(".");
|
|
374
544
|
const intValue = intRaw ? parseChineseInteger(intRaw) : 0n;
|
|
375
|
-
const fracValue = parseFractionDigits(fracRaw
|
|
545
|
+
const fracValue = parseFractionDigits(fracRaw);
|
|
376
546
|
if (intValue > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
377
547
|
throw new RangeError("Decimal parse does not support integer part above MAX_SAFE_INTEGER");
|
|
378
548
|
}
|
|
@@ -390,7 +560,7 @@ export const integer = {
|
|
|
390
560
|
};
|
|
391
561
|
export const cjkIdeographic = {
|
|
392
562
|
parse(value) {
|
|
393
|
-
if (typeof value === "number"
|
|
563
|
+
if (typeof value === "number") {
|
|
394
564
|
return formatDecimal(value, TRAD_INFORMAL_SET);
|
|
395
565
|
}
|
|
396
566
|
return formatChineseInteger(value, TRAD_INFORMAL_SET);
|
|
@@ -398,7 +568,7 @@ export const cjkIdeographic = {
|
|
|
398
568
|
};
|
|
399
569
|
export const tradChineseInformal = {
|
|
400
570
|
parse(value) {
|
|
401
|
-
if (typeof value === "number"
|
|
571
|
+
if (typeof value === "number") {
|
|
402
572
|
return formatDecimal(value, TRAD_INFORMAL_SET);
|
|
403
573
|
}
|
|
404
574
|
return formatChineseInteger(value, TRAD_INFORMAL_SET);
|
|
@@ -406,7 +576,7 @@ export const tradChineseInformal = {
|
|
|
406
576
|
};
|
|
407
577
|
export const tradChineseFormal = {
|
|
408
578
|
parse(value) {
|
|
409
|
-
if (typeof value === "number"
|
|
579
|
+
if (typeof value === "number") {
|
|
410
580
|
return formatDecimal(value, TRAD_FORMAL_SET);
|
|
411
581
|
}
|
|
412
582
|
return formatChineseInteger(value, TRAD_FORMAL_SET);
|
|
@@ -414,7 +584,7 @@ export const tradChineseFormal = {
|
|
|
414
584
|
};
|
|
415
585
|
export const simpChineseInformal = {
|
|
416
586
|
parse(value) {
|
|
417
|
-
if (typeof value === "number"
|
|
587
|
+
if (typeof value === "number") {
|
|
418
588
|
return formatDecimal(value, SIMP_INFORMAL_SET);
|
|
419
589
|
}
|
|
420
590
|
return formatChineseInteger(value, SIMP_INFORMAL_SET);
|
|
@@ -422,7 +592,7 @@ export const simpChineseInformal = {
|
|
|
422
592
|
};
|
|
423
593
|
export const simpChineseFormal = {
|
|
424
594
|
parse(value) {
|
|
425
|
-
if (typeof value === "number"
|
|
595
|
+
if (typeof value === "number") {
|
|
426
596
|
return formatDecimal(value, SIMP_FORMAL_SET);
|
|
427
597
|
}
|
|
428
598
|
return formatChineseInteger(value, SIMP_FORMAL_SET);
|
|
@@ -438,7 +608,76 @@ export const cjkEarthlyBranch = {
|
|
|
438
608
|
return fromCycle(value, BRANCHES, options.mode ?? "fixed");
|
|
439
609
|
}
|
|
440
610
|
};
|
|
611
|
+
export const koreanHangulFormal = {
|
|
612
|
+
parse(value) {
|
|
613
|
+
if (typeof value === "number") {
|
|
614
|
+
return formatDecimal(value, KOREAN_HANGUL_SET);
|
|
615
|
+
}
|
|
616
|
+
return formatChineseInteger(value, KOREAN_HANGUL_SET);
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
export const koreanHanjaFormal = {
|
|
620
|
+
parse(value) {
|
|
621
|
+
if (typeof value === "number") {
|
|
622
|
+
return formatDecimal(value, KOREAN_HANJA_FORMAL_SET);
|
|
623
|
+
}
|
|
624
|
+
return formatChineseInteger(value, KOREAN_HANJA_FORMAL_SET);
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
export const koreanHanjaInformal = {
|
|
628
|
+
parse(value) {
|
|
629
|
+
if (typeof value === "number") {
|
|
630
|
+
return formatDecimal(value, KOREAN_HANJA_INFORMAL_SET);
|
|
631
|
+
}
|
|
632
|
+
return formatChineseInteger(value, KOREAN_HANJA_INFORMAL_SET);
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
export const japaneseFormal = {
|
|
636
|
+
parse(value) {
|
|
637
|
+
if (typeof value === "number") {
|
|
638
|
+
return formatDecimal(value, JAPANESE_FORMAL_SET);
|
|
639
|
+
}
|
|
640
|
+
return formatChineseInteger(value, JAPANESE_FORMAL_SET);
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
export const japaneseInformal = {
|
|
644
|
+
parse(value) {
|
|
645
|
+
if (typeof value === "number") {
|
|
646
|
+
return formatDecimal(value, JAPANESE_INFORMAL_SET);
|
|
647
|
+
}
|
|
648
|
+
return formatChineseInteger(value, JAPANESE_INFORMAL_SET);
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
export const hiragana = {
|
|
652
|
+
parse(value, options = {}) {
|
|
653
|
+
return fromCycle(value, HIRAGANA, options.mode ?? "fixed");
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
export const hiraganaIroha = {
|
|
657
|
+
parse(value, options = {}) {
|
|
658
|
+
return fromCycle(value, HIRAGANA_IROHA, options.mode ?? "fixed");
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
export const katakana = {
|
|
662
|
+
parse(value, options = {}) {
|
|
663
|
+
return fromCycle(value, KATAKANA, options.mode ?? "fixed");
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
export const katakanaIroha = {
|
|
667
|
+
parse(value, options = {}) {
|
|
668
|
+
return fromCycle(value, KATAKANA_IROHA, options.mode ?? "fixed");
|
|
669
|
+
}
|
|
670
|
+
};
|
|
441
671
|
export const systems = {
|
|
442
672
|
heavenlyStem: STEMS,
|
|
443
|
-
earthlyBranch: BRANCHES
|
|
673
|
+
earthlyBranch: BRANCHES,
|
|
674
|
+
koreanHangulFormal: KOREAN_HANGUL_DIGITS,
|
|
675
|
+
koreanHanjaFormal: KOREAN_HANJA_FORMAL_DIGITS,
|
|
676
|
+
koreanHanjaInformal: KOREAN_HANJA_INFORMAL_DIGITS,
|
|
677
|
+
japaneseFormal: JAPANESE_FORMAL_DIGITS,
|
|
678
|
+
japaneseInformal: JAPANESE_INFORMAL_DIGITS,
|
|
679
|
+
hiragana: HIRAGANA,
|
|
680
|
+
hiraganaIroha: HIRAGANA_IROHA,
|
|
681
|
+
katakana: KATAKANA,
|
|
682
|
+
katakanaIroha: KATAKANA_IROHA
|
|
444
683
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cjk-number",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Convert between numbers and CJK number systems",
|
|
5
5
|
"author": "gary2",
|
|
6
6
|
"repository": {
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"build": "tsc -p tsconfig.json",
|
|
28
28
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
29
29
|
"test": "vitest run",
|
|
30
|
+
"coverage": "vitest run --coverage",
|
|
30
31
|
"dev:test": "vitest",
|
|
31
32
|
"pack:check": "npm pack --dry-run",
|
|
32
33
|
"release:check": "npm run typecheck && npm run test && npm run build && npm run pack:check",
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"license": "MIT",
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@types/node": "^25.5.0",
|
|
47
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
46
48
|
"typescript": "^5.8.3",
|
|
47
49
|
"vitest": "^4.1.2"
|
|
48
50
|
}
|