grapheme-conformance 0.1.3 → 0.1.5
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 +32 -20
- package/VERIFY.md +14 -7
- package/dist/cli.cjs +1 -1
- package/dist/cli.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,10 +45,22 @@ Cases passed:
|
|
|
45
45
|
| `grapheme-splitter@1.0.4` | 1175 | 1081 |
|
|
46
46
|
| `runes2@1.1.4` | 730 | 695 |
|
|
47
47
|
|
|
48
|
-
`Intl.Segmenter`
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
The one case `Intl.Segmenter` misses in both columns is `2701 200D 2701`, and
|
|
49
|
+
it is an artefact of the answer key, not a bug in ICU. Unicode 17.0 removed
|
|
50
|
+
U+2701 from `Extended_Pictographic`, so GB11 no longer applies and the correct
|
|
51
|
+
result became **two** clusters. Scored against the `17.0.0` key, ICU on Node 22
|
|
52
|
+
passes every case:
|
|
53
|
+
|
|
54
|
+
| implementation | U17.0.0 (766) |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `Intl.Segmenter` (ICU, Node 22) | 766 |
|
|
57
|
+
| `unicode-segmenter@0.17.3` | 766 |
|
|
58
|
+
| `graphemer@1.4.0` | 749 |
|
|
59
|
+
| `grapheme-splitter@1.0.4` | 746 |
|
|
60
|
+
| `runes2@1.1.4` | 501 |
|
|
61
|
+
|
|
62
|
+
Score an implementation against the key it targets. A current segmenter judged
|
|
63
|
+
by a superseded key reports failures it does not have.
|
|
52
64
|
|
|
53
65
|
## Install
|
|
54
66
|
|
|
@@ -62,23 +74,20 @@ Zero runtime dependencies. Dual ESM/CJS. Node 18+.
|
|
|
62
74
|
|
|
63
75
|
```sh
|
|
64
76
|
npx grapheme-conformance --module unicode-segmenter/grapheme \
|
|
65
|
-
--export splitGraphemes
|
|
77
|
+
--export splitGraphemes
|
|
66
78
|
```
|
|
67
79
|
|
|
68
80
|
```
|
|
69
|
-
unicode-segmenter/grapheme (splitGraphemes) GraphemeBreakTest
|
|
70
|
-
passed
|
|
71
|
-
failed
|
|
72
|
-
|
|
73
|
-
line input want got rule
|
|
74
|
-
1105 2701 200D 2701 1 2 -
|
|
81
|
+
unicode-segmenter/grapheme (splitGraphemes) GraphemeBreakTest 17.0.0
|
|
82
|
+
passed 766/766 100.00%
|
|
83
|
+
failed 0
|
|
75
84
|
```
|
|
76
85
|
|
|
77
86
|
| flag | default | meaning |
|
|
78
87
|
|---|---|---|
|
|
79
88
|
| `--module` | required | module to load: a bare name, or a path relative to cwd |
|
|
80
89
|
| `--export` | `default` | the export to score |
|
|
81
|
-
| `--version` | `
|
|
90
|
+
| `--version` | `17.0.0` | vendored vectors: `15.0.0`, `15.1.0`, `16.0.0`, `17.0.0` |
|
|
82
91
|
| `--min` | `1.0` | minimum pass rate before exiting non-zero |
|
|
83
92
|
| `--limit` | `10` | failing cases to print |
|
|
84
93
|
|
|
@@ -94,13 +103,13 @@ import { parseBreakTest, score, vectors } from 'grapheme-conformance';
|
|
|
94
103
|
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
|
|
95
104
|
const report = score(
|
|
96
105
|
(s) => [...segmenter.segment(s)].map((part) => part.segment),
|
|
97
|
-
vectors['
|
|
106
|
+
vectors['17.0.0'],
|
|
98
107
|
);
|
|
99
108
|
|
|
100
|
-
report.passed; //
|
|
101
|
-
report.total; //
|
|
102
|
-
report.rate; //
|
|
103
|
-
report.failures
|
|
109
|
+
report.passed; // 766
|
|
110
|
+
report.total; // 766
|
|
111
|
+
report.rate; // 1
|
|
112
|
+
report.failures; // []
|
|
104
113
|
```
|
|
105
114
|
|
|
106
115
|
```ts
|
|
@@ -149,9 +158,12 @@ UAX #29 and does not prove which rule an implementation actually got wrong.
|
|
|
149
158
|
## Intl.Segmenter and the host ICU
|
|
150
159
|
|
|
151
160
|
`Intl.Segmenter` is scored against whatever ICU the host Node ships, so its row
|
|
152
|
-
moves with the runtime
|
|
153
|
-
Node
|
|
154
|
-
|
|
161
|
+
moves with the runtime. Against the older keys the movement is not even
|
|
162
|
+
monotonic: Node 18.20.8 scores `1187` and `1093` where Node 20 and 22 score
|
|
163
|
+
`1186` and `1092`, because newer ICU implements the Unicode 17.0 property
|
|
164
|
+
change that those keys predate. Against the `17.0.0` key every one of them is
|
|
165
|
+
correct. The pure-JS libraries are pinned to exact versions and score
|
|
166
|
+
identically everywhere.
|
|
155
167
|
|
|
156
168
|
## Verifying this build
|
|
157
169
|
|
package/VERIFY.md
CHANGED
|
@@ -50,18 +50,25 @@ Expected output:
|
|
|
50
50
|
|
|
51
51
|
`Intl.Segmenter` is not a fixed library. It is scored against whatever ICU the
|
|
52
52
|
host Node ships, so its row moves with the runtime. Measured across the CI
|
|
53
|
-
matrix:
|
|
53
|
+
matrix, against these two older keys:
|
|
54
54
|
|
|
55
55
|
| runtime | 15.1.0 | 16.0.0 | `2701 200D 2701` |
|
|
56
56
|
|---|---|---|---|
|
|
57
|
-
| Node 22.22.2 (ICU 78.2) | 1186 | 1092 |
|
|
58
|
-
| Node 20.x | 1186 | 1092 |
|
|
59
|
-
| Node 18.20.8 | 1187 | 1093 |
|
|
57
|
+
| Node 22.22.2 (ICU 78.2) | 1186 | 1092 | two clusters |
|
|
58
|
+
| Node 20.x | 1186 | 1092 | two clusters |
|
|
59
|
+
| Node 18.20.8 | 1187 | 1093 | one cluster |
|
|
60
60
|
|
|
61
61
|
Run the command above on Node 22 or 20 to get the expected output above. On
|
|
62
|
-
Node 18 the `Intl.Segmenter` value reads `1187` and `1093` instead
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
Node 18 the `Intl.Segmenter` value reads `1187` and `1093` instead. The other
|
|
63
|
+
four values are pinned to exact library versions and hold identically on
|
|
64
|
+
every Node.
|
|
65
|
+
|
|
66
|
+
That single differing case is not an ICU bug. Unicode 17.0 removed U+2701
|
|
67
|
+
from `Extended_Pictographic`, so GB11 stopped applying and two clusters became
|
|
68
|
+
the correct answer; newer ICU implements that change and these two older keys
|
|
69
|
+
predate it. Scored against `17.0.0`, which is what the CLI uses by default,
|
|
70
|
+
ICU on Node 22 passes all 766 cases. Score an implementation against the key
|
|
71
|
+
it targets.
|
|
65
72
|
|
|
66
73
|
The baseline was verified on Node 22.22.2 (ICU 78.2, Unicode 17.0).
|
|
67
74
|
|
package/dist/cli.cjs
CHANGED
|
@@ -212,7 +212,7 @@ async function main() {
|
|
|
212
212
|
console.log(USAGE);
|
|
213
213
|
process.exit(args.module ? 0 : 2);
|
|
214
214
|
}
|
|
215
|
-
const version = args.version ?? "
|
|
215
|
+
const version = args.version ?? "17.0.0";
|
|
216
216
|
const cases = vectors[version];
|
|
217
217
|
if (!cases) fail(`Unknown version '${version}'. Have: ${Object.keys(vectors).join(", ")}`);
|
|
218
218
|
const min = args.min === void 0 ? 1 : Number(args.min);
|
package/dist/cli.js
CHANGED
|
@@ -207,7 +207,7 @@ async function main() {
|
|
|
207
207
|
console.log(USAGE);
|
|
208
208
|
process.exit(args.module ? 0 : 2);
|
|
209
209
|
}
|
|
210
|
-
const version = args.version ?? "
|
|
210
|
+
const version = args.version ?? "17.0.0";
|
|
211
211
|
const cases = vectors[version];
|
|
212
212
|
if (!cases) fail(`Unknown version '${version}'. Have: ${Object.keys(vectors).join(", ")}`);
|
|
213
213
|
const min = args.min === void 0 ? 1 : Number(args.min);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grapheme-conformance",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Score any JavaScript grapheme segmenter against Unicode's official GraphemeBreakTest.txt. Find out which string splitters are wrong, and about what.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unicode",
|