Skip to content

Commit b1c5a5b

Browse files
JLHwungmathiasbynens
authored andcommitted
Ignore diagnostic comparisons in legacy Unicode property dumps
Stop collecting property members at Discrepancy sections and resume at the next property heading. This removes diagnostic-only code points from Unicode 2.1.8 Math, Alphabetic, and Diacritic sets. Assisted-By: GPT-6 Issue: #110
1 parent dc18217 commit b1c5a5b

3 files changed

Lines changed: 73 additions & 3 deletions

File tree

‎scripts/parse-blocks-scripts-properties.mjs‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,7 @@ const parseProperties = async (version) => {
348348
// Unassigned code points are already available as General_Category=Cn.
349349
currentProperty === 'Unassigned Code Value'
350350
) {
351-
// Skip contents.
352-
i++;
353-
while (++i < lines.length && lines[i].trim() !== '');
351+
currentProperty = undefined;
354352
continue;
355353
}
356354
if (currentProperty === 'Not a Character') {
@@ -359,7 +357,12 @@ const parseProperties = async (version) => {
359357
currentProperty = currentProperty.replaceAll(' ', '_');
360358
currentProperty = findCanonicalName(currentProperty) ?? currentProperty;
361359
map[currentProperty] = regenerate();
360+
} else if (line.startsWith('Discrepancy ')) {
361+
// Unicode 2.1.8 includes comparisons with UnicodeData after each
362+
// record list. Those ranges are diagnostics, not property members.
363+
currentProperty = undefined;
362364
} else if (
365+
currentProperty &&
363366
(maybeRange = /^([A-F\d]{4,6})(?:\.\.([A-F\d]{4,6}))?(?=\s|$)/.exec(
364367
line,
365368
)) != null

‎tests/parser-formats.mjs‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,61 @@ import parseScriptExtensions from '../scripts/parse-script-extensions.mjs';
1111
import {
1212
parseBlocks,
1313
parseDerivedCoreProperties,
14+
parseProperties,
1415
parseScripts,
1516
} from '../scripts/parse-blocks-scripts-properties.mjs';
1617
import utils from '../scripts/utils.mjs';
1718

19+
test('Legacy property diagnostics end a record section until the next heading', async (t) => {
20+
t.mock.method(
21+
utils,
22+
'readDataFile',
23+
() => `
24+
Property dump for: 0x20000001 (Alphabetic)
25+
26+
0041..005A (26 chars)
27+
Discrepancy A: Unilib but not UnicodeData
28+
29+
0041
30+
Discrepancy B: UnicodeData but not Unilib
31+
32+
4E00..9FA5 (20902 chars)
33+
Property dump for: 0x20010000 (Diacritic)
34+
35+
0300
36+
Discrepancy B: UnicodeData but not Unilib
37+
0640
38+
Property dump for: 0x01000000 (Bidi: Left-to-Right)
39+
40+
0041
41+
42+
Discrepancy B: UnicodeData but not Unilib
43+
44+
0042
45+
46+
Property dump for: 0x00000000 (Unassigned Code Value)
47+
48+
0378
49+
50+
Property dump for: 0x10000004 (White space)
51+
52+
0020
53+
`,
54+
);
55+
const properties = await parseProperties('2.1.8');
56+
t.assert.deepEqual(Object.keys(properties), [
57+
'Alphabetic',
58+
'Diacritic',
59+
'White_Space',
60+
]);
61+
t.assert.deepEqual(
62+
properties.Alphabetic.toArray(),
63+
Array.from({ length: 26 }, (_, i) => 0x41 + i),
64+
);
65+
t.assert.deepEqual(properties.Diacritic.toArray(), [0x300]);
66+
t.assert.deepEqual(properties.White_Space.toArray(), [0x20]);
67+
});
68+
1869
test('Simple case mappings ignore comments after empty and explicit titlecase fields', async (t) => {
1970
t.mock.method(utils, 'readDataFile', () =>
2071
[

‎tests/parsers.mjs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ import {
1717
parseScripts,
1818
} from '../scripts/parse-blocks-scripts-properties.mjs';
1919

20+
test('Unicode 2.1.8 property values exclude discrepancy diagnostics', async (t) => {
21+
const properties = await parseProperties('2.1.8');
22+
t.assert.equal(properties.Math.toArray().length, 345);
23+
t.assert.equal(properties.Alphabetic.toArray().length, 15181);
24+
t.assert.equal(properties.Diacritic.toArray().length, 274);
25+
t.assert.ok(properties.Math.contains(0xffe9));
26+
t.assert.ok(!properties.Math.contains(0xffe8));
27+
t.assert.ok(properties.Alphabetic.contains(0x41));
28+
t.assert.ok(!properties.Alphabetic.contains(0x2d0));
29+
t.assert.ok(!properties.Alphabetic.contains(0x4e00));
30+
t.assert.ok(properties.Diacritic.contains(0x300));
31+
t.assert.ok(!properties.Diacritic.contains(0x640));
32+
// The next property's real records still include the ideograph.
33+
t.assert.ok(properties.Ideographic.contains(0x4e00));
34+
});
35+
2036
test('Unicode 5.0 through 6.0 provide their historical correction aliases', async (t) => {
2137
for (const version of ['5.0.0', '5.1.0', '5.2.0', '6.0.0']) {
2238
const aliases = await parseNameAliases(version);

0 commit comments

Comments
 (0)