@weasel-js/bidi 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 orochi235
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @weasel-js/bidi
2
+
3
+ The Unicode Bidirectional Algorithm ([UAX #9](https://www.unicode.org/reports/tr9/)), as a
4
+ standalone leaf: code points and a direction in, embedding levels and a visual order out.
5
+
6
+ No fonts, no glyphs, no canvas, no DOM, and no dependencies. Nothing else in weasel depends
7
+ on this package — a text layout that wants bidi is handed an implementation of `BidiEngine`,
8
+ and one that isn't lays out in logical order.
9
+
10
+ ```ts
11
+ import { analyze, reorder } from '@weasel-js/bidi';
12
+
13
+ const codePoints = [...'שלום 25'].map((c) => c.codePointAt(0)!);
14
+ const paragraph = analyze(codePoints); // 'auto' — first-strong, so RTL here
15
+ const { order } = reorder(paragraph, 0, codePoints.length);
16
+ // `order` indexes codePoints in display order; the digits stay 2 then 5.
17
+ ```
18
+
19
+ Two calls because the algorithm splits at exactly one place. `analyze` is per paragraph;
20
+ `reorder` is per **line**, because L1 resets trailing whitespace against the end of a line
21
+ rather than the end of a paragraph. Wrap between them, and one analysis serves every line.
22
+
23
+ `mirror(cp)` is L4, applied at paint time against a character's resolved level — the same
24
+ code point mirrors in one run and not in another.
25
+
26
+ ## What this does not do
27
+
28
+ Ordering only. Arabic still renders unjoined: joining forms are OpenType `GSUB`
29
+ substitutions, not a reordering, and belong to a shaping engine. Hebrew, Divehi and the other
30
+ non-joining right-to-left scripts are complete with bidi alone.
31
+
32
+ ## Conformance
33
+
34
+ Verified against Unicode's own data, in full — all 91,707 cases of `BidiCharacterTest.txt`
35
+ and all 490,846 of `BidiTest.txt`. Character data is generated by `npm run gen:bidi-tables`;
36
+ the Unicode version it was built from is exported as `UNICODE_VERSION`.
@@ -0,0 +1,165 @@
1
+ /**
2
+ * The Unicode Bidirectional Algorithm's character data, as three lookups.
3
+ *
4
+ * Split from the algorithm so the generated tables and the rules that consume
5
+ * them can be tested apart — the rules are checkable against handwritten cases,
6
+ * the tables only against Unicode's own files.
7
+ */
8
+ /**
9
+ * `Bidi_Class`, the property every rule in UAX #9 dispatches on.
10
+ *
11
+ * Grouped as the spec groups them: strong types decide direction outright, weak
12
+ * types take it from context, neutrals take it from both sides, and the
13
+ * explicit formatting codes drive the X rules.
14
+ */
15
+ type BidiClass = 'L' | 'R' | 'AL' | 'EN' | 'ES' | 'ET' | 'AN' | 'CS' | 'NSM' | 'BN' | 'B' | 'S' | 'WS' | 'ON' | 'LRE' | 'RLE' | 'LRO' | 'RLO' | 'PDF' | 'LRI' | 'RLI' | 'FSI' | 'PDI';
16
+ /** One half of a bracket pair, for the `N0` rule via `BD16`. */
17
+ interface PairedBracket {
18
+ /** The code point that closes this one, or opens it. */
19
+ pair: number;
20
+ kind: 'open' | 'close';
21
+ }
22
+
23
+ /**
24
+ * The Unicode Bidirectional Algorithm, rules P through I.
25
+ *
26
+ * This is the analysis half: text in, an embedding level per character out.
27
+ * Turning those levels into a visual order is L1–L2, which is per *line* and
28
+ * therefore cannot happen here — the caller wraps first and reorders after.
29
+ */
30
+
31
+ /** How the paragraph's own direction is decided. */
32
+ type BidiDirection = 'ltr' | 'rtl' | 'auto';
33
+ interface BidiResult {
34
+ /** Embedding level per input character. */
35
+ levels: Uint8Array;
36
+ /** Class per character after the W and N rules resolved it. */
37
+ classes: BidiClass[];
38
+ /** X9 — true where the character is a formatting code the output drops. */
39
+ removed: boolean[];
40
+ paragraphLevel: 0 | 1;
41
+ }
42
+ /**
43
+ * Resolve embedding levels for one paragraph.
44
+ *
45
+ * `codePoints` is optional and only feeds `N0`'s bracket pairing. Omitting it
46
+ * costs nothing else: every other rule reads classes alone, which is how the
47
+ * class-only half of Unicode's conformance data can drive this at all.
48
+ */
49
+ declare function resolveLevels(classes: readonly BidiClass[], direction?: BidiDirection, codePoints?: readonly number[]): BidiResult;
50
+
51
+ /**
52
+ * L1 and L2 — turning embedding levels into a visual order, one line at a time.
53
+ *
54
+ * These are the only rules that know about lines, which is why they are split
55
+ * from `resolveLevels`: a caller wraps text into lines *after* the paragraph is
56
+ * analysed, and the same paragraph analysis then serves every line it broke
57
+ * into. Running L1 during the analysis would reset whitespace against the
58
+ * paragraph's end rather than each line's.
59
+ */
60
+
61
+ interface ReorderedLine {
62
+ /**
63
+ * Original indices in visual order, left to right, with the characters X9
64
+ * removed omitted.
65
+ */
66
+ order: number[];
67
+ /**
68
+ * Level per original index over the line, after L1. `-1` where X9 removed
69
+ * the character.
70
+ */
71
+ levels: Int16Array;
72
+ }
73
+ /**
74
+ * Reorder `[start, end)` of an analysed paragraph.
75
+ *
76
+ * `original` must be the classes as they were *before* analysis: L1 is defined
77
+ * against them, and by this point `resolved.classes` has rewritten the very
78
+ * whitespace L1 is looking for.
79
+ */
80
+ declare function reorderLine(original: readonly BidiClass[], resolved: BidiResult, start: number, end: number): ReorderedLine;
81
+
82
+ /**
83
+ * GENERATED FILE -- DO NOT EDIT BY HAND.
84
+ *
85
+ * Emitted by `packages/bidi/scripts/gen-bidi-tables.mjs` from the Unicode
86
+ * Character Database. Regenerate with `npm run gen:bidi-tables`.
87
+ */
88
+
89
+ /** The Unicode release these tables were generated from. */
90
+ declare const UNICODE_VERSION = "16.0.0";
91
+ /**
92
+ * The `Bidi_Class` of a code point.
93
+ *
94
+ * Unassigned code points resolve to the default their block declares, which is
95
+ * `R` or `AL` inside the right-to-left blocks and `L` elsewhere.
96
+ */
97
+ declare function bidiClassOf(cp: number): BidiClass;
98
+ /**
99
+ * The `Bidi_Paired_Bracket` of a code point, for BD16 and rule N0, or `null`
100
+ * where the code point is not one half of a pair.
101
+ */
102
+ declare function pairedBracket(cp: number): PairedBracket | null;
103
+ /**
104
+ * The `Bidi_Mirroring_Glyph` of a code point, or `null` where it has none.
105
+ *
106
+ * This is the mapping rule L4 applies, and only that: it is a hint for
107
+ * selecting a mirrored glyph, not a character transformation, and a font's own
108
+ * `rtlm` feature supersedes it where one exists.
109
+ */
110
+ declare function mirrorOf(cp: number): number | null;
111
+
112
+ /**
113
+ * The Unicode Bidirectional Algorithm (UAX #9).
114
+ *
115
+ * Plain data in, plain data out: code points and a direction go in, embedding
116
+ * levels and a visual order come out. Nothing here knows about fonts, glyphs,
117
+ * canvases or the DOM, and nothing in weasel depends on this package — a text
118
+ * layout that wants bidi is handed an implementation of this shape, and one
119
+ * that is not handed one lays out in logical order.
120
+ *
121
+ * Two calls, because the algorithm splits at exactly one place: `analyze` is
122
+ * per paragraph, `reorder` is per *line*. A caller wraps between them, and one
123
+ * analysis serves every line the wrap produced.
124
+ *
125
+ * Verified against Unicode's own conformance data — all 91,707 cases of
126
+ * `BidiCharacterTest.txt` and all 490,846 of `BidiTest.txt`.
127
+ */
128
+
129
+ /** One analysed paragraph, and the classes it was analysed from. */
130
+ interface BidiAnalysis extends BidiResult {
131
+ /** `Bidi_Class` per code point, before the W and N rules rewrote anything.
132
+ * L1 is specified against these, so `reorder` needs them kept. */
133
+ original: BidiClass[];
134
+ }
135
+ /**
136
+ * Analyse one paragraph of text.
137
+ *
138
+ * `direction` defaults to `'auto'`, which is P2/P3's first-strong rule — the
139
+ * right default for text whose language is not known up front.
140
+ */
141
+ declare function analyze(codePoints: readonly number[], direction?: BidiDirection): BidiAnalysis;
142
+ /**
143
+ * Order one line of an analysed paragraph for display, left to right.
144
+ *
145
+ * `start` and `end` index the same code point array `analyze` was given.
146
+ */
147
+ declare function reorder(analysis: BidiAnalysis, start: number, end: number): ReorderedLine;
148
+ /**
149
+ * L4 — the glyph to paint in place of `cp` when it sits in a right-to-left
150
+ * run, or `null` when it is not mirrored.
151
+ *
152
+ * Applied at paint time against a character's resolved level, not during
153
+ * analysis: the same code point mirrors in one run and not in another.
154
+ */
155
+ declare function mirror(cp: number): number | null;
156
+ /** The whole seam a text layout needs, and all this package is used through. */
157
+ interface BidiEngine {
158
+ analyze(codePoints: readonly number[], direction?: BidiDirection): BidiAnalysis;
159
+ reorder(analysis: BidiAnalysis, start: number, end: number): ReorderedLine;
160
+ mirror(cp: number): number | null;
161
+ }
162
+ /** The default engine — pass this where a `BidiEngine` is wanted. */
163
+ declare const bidi: BidiEngine;
164
+
165
+ export { UNICODE_VERSION as BIDI_UNICODE_VERSION, type BidiAnalysis, type BidiClass, type BidiDirection, type BidiEngine, type BidiResult, type PairedBracket, type ReorderedLine, UNICODE_VERSION, analyze, bidi, bidiClassOf, mirror, mirrorOf, pairedBracket, reorder, reorderLine, resolveLevels };
package/dist/index.js ADDED
@@ -0,0 +1,535 @@
1
+ // src/paragraph.ts
2
+ function isIsolateInitiator(c) {
3
+ return c === "LRI" || c === "RLI" || c === "FSI";
4
+ }
5
+ function matchingPDI(classes, start, end = classes.length) {
6
+ let depth = 1;
7
+ for (let i = start + 1; i < end; i++) {
8
+ const c = classes[i];
9
+ if (isIsolateInitiator(c)) depth++;
10
+ else if (c === "PDI" && --depth === 0) return i;
11
+ }
12
+ return end;
13
+ }
14
+ function paragraphLevelOf(classes, start = 0, end = classes.length) {
15
+ for (let i = start; i < end; i++) {
16
+ const c = classes[i];
17
+ if (isIsolateInitiator(c)) {
18
+ i = matchingPDI(classes, i, end);
19
+ continue;
20
+ }
21
+ if (c === "L") return 0;
22
+ if (c === "R" || c === "AL") return 1;
23
+ }
24
+ return 0;
25
+ }
26
+
27
+ // src/explicit.ts
28
+ var MAX_DEPTH = 125;
29
+ function nextOdd(level) {
30
+ return level + 1 + ((level + 1) % 2 === 0 ? 1 : 0);
31
+ }
32
+ function nextEven(level) {
33
+ return level + 1 + ((level + 1) % 2 === 0 ? 0 : 1);
34
+ }
35
+ function resolveExplicit(input, paragraphLevel) {
36
+ const n = input.length;
37
+ const classes = input.slice();
38
+ const levels = new Uint8Array(n);
39
+ const removed = new Array(n).fill(false);
40
+ const stack = [
41
+ { level: paragraphLevel, override: "neutral", isolate: false }
42
+ ];
43
+ let overflowIsolate = 0;
44
+ let overflowEmbedding = 0;
45
+ let validIsolate = 0;
46
+ const top = () => stack[stack.length - 1];
47
+ for (let i = 0; i < n; i++) {
48
+ const c = classes[i];
49
+ switch (c) {
50
+ // X2–X5: embeddings and overrides.
51
+ case "RLE":
52
+ case "LRE":
53
+ case "RLO":
54
+ case "LRO": {
55
+ levels[i] = top().level;
56
+ removed[i] = true;
57
+ const rtl = c === "RLE" || c === "RLO";
58
+ const level = rtl ? nextOdd(top().level) : nextEven(top().level);
59
+ const override = c === "RLO" ? "R" : c === "LRO" ? "L" : "neutral";
60
+ if (level <= MAX_DEPTH && overflowIsolate === 0 && overflowEmbedding === 0) {
61
+ stack.push({ level, override, isolate: false });
62
+ } else if (overflowIsolate === 0) {
63
+ overflowEmbedding++;
64
+ }
65
+ break;
66
+ }
67
+ // X5a–X5c: isolates. The initiator is kept and sits outside.
68
+ case "RLI":
69
+ case "LRI":
70
+ case "FSI": {
71
+ let rtl = c === "RLI";
72
+ if (c === "FSI") {
73
+ rtl = paragraphLevelOf(classes, i + 1, matchingPDI(classes, i, n)) === 1;
74
+ }
75
+ levels[i] = top().level;
76
+ if (top().override !== "neutral") classes[i] = top().override;
77
+ const level = rtl ? nextOdd(top().level) : nextEven(top().level);
78
+ if (level <= MAX_DEPTH && overflowIsolate === 0 && overflowEmbedding === 0) {
79
+ validIsolate++;
80
+ stack.push({ level, override: "neutral", isolate: true });
81
+ } else {
82
+ overflowIsolate++;
83
+ }
84
+ break;
85
+ }
86
+ // X6a.
87
+ case "PDI": {
88
+ if (overflowIsolate > 0) {
89
+ overflowIsolate--;
90
+ } else if (validIsolate > 0) {
91
+ overflowEmbedding = 0;
92
+ while (!top().isolate) stack.pop();
93
+ stack.pop();
94
+ validIsolate--;
95
+ }
96
+ levels[i] = top().level;
97
+ if (top().override !== "neutral") classes[i] = top().override;
98
+ break;
99
+ }
100
+ // X7.
101
+ case "PDF": {
102
+ levels[i] = top().level;
103
+ removed[i] = true;
104
+ if (overflowIsolate > 0) ; else if (overflowEmbedding > 0) {
105
+ overflowEmbedding--;
106
+ } else if (!top().isolate && stack.length >= 2) {
107
+ stack.pop();
108
+ }
109
+ break;
110
+ }
111
+ // X8 — a paragraph separator always returns to the paragraph level.
112
+ case "B": {
113
+ levels[i] = paragraphLevel;
114
+ break;
115
+ }
116
+ case "BN": {
117
+ levels[i] = top().level;
118
+ removed[i] = true;
119
+ break;
120
+ }
121
+ // X6 — everything else.
122
+ default: {
123
+ levels[i] = top().level;
124
+ if (top().override !== "neutral") classes[i] = top().override;
125
+ break;
126
+ }
127
+ }
128
+ }
129
+ return { levels, classes, removed, paragraphLevel };
130
+ }
131
+
132
+ // src/sequences.ts
133
+ function isIsolateInitiator2(c) {
134
+ return c === "LRI" || c === "RLI" || c === "FSI";
135
+ }
136
+ function boundaryOf(a, b) {
137
+ return Math.max(a, b) % 2 === 1 ? "R" : "L";
138
+ }
139
+ function buildSequences(r) {
140
+ const { classes, levels, removed, paragraphLevel } = r;
141
+ const n = classes.length;
142
+ const kept = [];
143
+ for (let i = 0; i < n; i++) if (!removed[i]) kept.push(i);
144
+ if (kept.length === 0) return [];
145
+ const pdiOf = /* @__PURE__ */ new Map();
146
+ const initiatorOf = /* @__PURE__ */ new Map();
147
+ for (let i = 0; i < n; i++) {
148
+ if (!isIsolateInitiator2(classes[i])) continue;
149
+ const m = matchingPDI(classes, i, n);
150
+ if (m < n) {
151
+ pdiOf.set(i, m);
152
+ initiatorOf.set(m, i);
153
+ }
154
+ }
155
+ const runs = [];
156
+ for (const i of kept) {
157
+ const last = runs[runs.length - 1];
158
+ if (last && last.level === levels[i]) last.indices.push(i);
159
+ else runs.push({ level: levels[i], indices: [i] });
160
+ }
161
+ const runStartingAt = /* @__PURE__ */ new Map();
162
+ runs.forEach((run, k) => runStartingAt.set(run.indices[0], k));
163
+ const out = [];
164
+ const consumed = new Array(runs.length).fill(false);
165
+ for (let k = 0; k < runs.length; k++) {
166
+ if (consumed[k]) continue;
167
+ const first = runs[k].indices[0];
168
+ if (classes[first] === "PDI" && initiatorOf.has(first)) continue;
169
+ const indices = [];
170
+ let cur = k;
171
+ for (; ; ) {
172
+ consumed[cur] = true;
173
+ indices.push(...runs[cur].indices);
174
+ const lastIdx = runs[cur].indices[runs[cur].indices.length - 1];
175
+ if (!isIsolateInitiator2(classes[lastIdx])) break;
176
+ const pdi = pdiOf.get(lastIdx);
177
+ if (pdi === void 0) break;
178
+ const next = runStartingAt.get(pdi);
179
+ if (next === void 0 || consumed[next]) break;
180
+ cur = next;
181
+ }
182
+ const level = runs[k].level;
183
+ const start = indices[0];
184
+ const end = indices[indices.length - 1];
185
+ let before = paragraphLevel;
186
+ for (let i = start - 1; i >= 0; i--) {
187
+ if (!removed[i]) {
188
+ before = levels[i];
189
+ break;
190
+ }
191
+ }
192
+ let after = paragraphLevel;
193
+ if (!(isIsolateInitiator2(classes[end]) && !pdiOf.has(end))) {
194
+ for (let i = end + 1; i < n; i++) {
195
+ if (!removed[i]) {
196
+ after = levels[i];
197
+ break;
198
+ }
199
+ }
200
+ }
201
+ out.push({
202
+ indices,
203
+ level,
204
+ sos: boundaryOf(level, before),
205
+ eos: boundaryOf(level, after)
206
+ });
207
+ }
208
+ return out;
209
+ }
210
+
211
+ // src/tables.ts
212
+ var UNICODE_VERSION = "16.0.0";
213
+ var CLASSES = [
214
+ "L",
215
+ "R",
216
+ "AL",
217
+ "EN",
218
+ "ES",
219
+ "ET",
220
+ "AN",
221
+ "CS",
222
+ "NSM",
223
+ "BN",
224
+ "B",
225
+ "S",
226
+ "WS",
227
+ "ON",
228
+ "LRE",
229
+ "RLE",
230
+ "LRO",
231
+ "RLO",
232
+ "PDF",
233
+ "LRI",
234
+ "RLI",
235
+ "FSI",
236
+ "PDI"
237
+ ];
238
+ var CLASS_RUNS = 1239;
239
+ var CLASS_PACKED = "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";
240
+ var BRACKETS = "14o15,15c14,2Jo2L,2Lc2J,3Fo3H,3Hc3F,30Ao30B,30Bc30A,30Co30D,30Dc30C,4GRo4GS,4GSc4GR,6DHo6DI,6DIc6DH,6F1o6F2,6F2c6F1,6FHo6FI,6FIc6FH,6X4o6X5,6X5c6X4,6X6o6X7,6X7c6X6,6Y1o6Y2,6Y2c6Y1,7S8o7S9,7S9c7S8,7SAo7SB,7SBc7SA,7SCo7SD,7SDc7SC,7SEo7SF,7SFc7SE,7SGo7SH,7SHc7SG,7SIo7SJ,7SJc7SI,7SKo7SL,7SLc7SK,7UTo7UU,7UUc7UT,7VQo7VR,7VRc7VQ,7VSo7VT,7VTc7VS,7VUo7VV,7VVc7VU,7VWo7VX,7VXc7VW,7VYo7VZ,7VZc7VY,877o878,878c877,879o87A,87Ac879,87Bo87C,87Cc87B,87Do87E,87Ec87D,87Fo87G,87Gc87F,87Ho87K,87Ic87J,87Jo87I,87Kc87H,87Lo87M,87Mc87L,87No87O,87Oc87N,87Po87Q,87Qc87P,87Ro87S,87Sc87R,89Ko89L,89Lc89K,89Mo89N,89Nc89M,8AKo8AL,8ALc8AK,942o943,943c942,944o945,945c944,946o947,947c946,948o949,949c948,95Ho95I,95Ic95H,95Jo95K,95Kc95J,95Lo95M,95Mc95L,95No95O,95Oc95N,9HKo9HL,9HLc9HK,9HMo9HN,9HNc9HM,9HOo9HP,9HPc9HO,9HQo9HR,9HRc9HQ,9HSo9HT,9HTc9HS,9HWo9HX,9HXc9HW,9HYo9HZ,9HZc9HY,9I0o9I1,9I1c9I0,9I2o9I3,9I3c9I2,1E8Po1E8Q,1E8Qc1E8P,1E8Ro1E8S,1E8Sc1E8R,1E8To1E8U,1E8Uc1E8T,1EDKo1EDL,1EDLc1EDK,1EEZo1EF1,1EF1c1EEZ,1EFVo1EFX,1EFXc1EFV,1EFZo1EG0,1EG0c1EFZ,1EG2o1EG3,1EG3c1EG2";
241
+ var MIRRORING = "14:15,15:14,1O:1Q,1Q:1O,2J:2L,2L:2J,3F:3H,3H:3F,4R:57,57:4R,30A:30B,30B:30A,30C:30D,30D:30C,4GR:4GS,4GS:4GR,6D5:6D6,6D6:6D5,6DH:6DI,6DI:6DH,6F1:6F2,6F2:6F1,6FH:6FI,6FI:6FH,6Q0:6Q3,6Q1:6Q4,6Q2:6Q5,6Q3:6Q0,6Q4:6Q1,6Q5:6Q2,6QD:8AD,6QN:8OU,6QO:883,6QP:87V,6QQ:880,6QS:8HA,6RG:6RH,6RH:6RG,6RN:6VH,6RP:6RW,6RW:6RP,6S2:6S3,6S3:6S2,6S4:6S5,6S5:6S4,6SK:6SL,6SL:6SK,6SM:6SN,6SN:6SM,6SO:6SP,6SP:6SO,6SQ:6SR,6SR:6SQ,6SU:6SV,6SV:6SU,6SW:6SX,6SX:6SW,6SY:6SZ,6SZ:6SY,6T0:6T1,6T1:6T0,6T2:6T3,6T3:6T2,6T4:6T5,6T5:6T4,6T6:6T7,6T7:6T6,6T8:6T9,6T9:6T8,6TA:6TB,6TB:6TA,6TC:6TD,6TD:6TC,6TE:6TF,6TF:6TE,6TG:6TH,6TH:6TG,6TI:6TJ,6TJ:6TI,6TK:6TL,6TL:6TK,6TM:6TN,6TN:6TM,6TR:6TS,6TS:6TR,6TT:6TU,6TU:6TT,6U0:88O,6UA:6UB,6UB:6UA,6UE:8GU,6UG:8H0,6UH:8GZ,6UJ:8H1,6UO:6UP,6UP:6UO,6UQ:6UR,6UR:6UQ,6US:6UT,6UT:6US,6UU:6UV,6UV:6UU,6UW:7VG,6VD:6VE,6VE:6VD,6VF:6VG,6VG:6VF,6VH:6RN,6VK:6VL,6VL:6VK,6VQ:6VR,6VR:6VQ,6VS:6VT,6VT:6VS,6VU:6VV,6VV:6VU,6VW:6VX,6VX:6VW,6VY:6VZ,6VZ:6VY,6W0:6W1,6W1:6W0,6W2:6W3,6W3:6W2,6W4:6W5,6W5:6W4,6W6:6W7,6W7:6W6,6W8:6W9,6W9:6W8,6WA:6WB,6WB:6WA,6WC:6WD,6WD:6WC,6WG:6WH,6WH:6WG,6WI:6WQ,6WJ:6WR,6WK:6WS,6WM:6WT,6WN:6WU,6WQ:6WI,6WR:6WJ,6WS:6WK,6WT:6WM,6WU:6WN,6X4:6X5,6X5:6X4,6X6:6X7,6X7:6X6,6Y1:6Y2,6Y2:6Y1,7S8:7S9,7S9:7S8,7SA:7SB,7SB:7SA,7SC:7SD,7SD:7SC,7SE:7SF,7SF:7SE,7SG:7SH,7SH:7SG,7SI:7SJ,7SJ:7SI,7SK:7SL,7SL:7SK,7UR:7US,7US:7UR,7UT:7UU,7UU:7UT,7UW:7UX,7UX:7UW,7UZ:7V1,7V1:7UZ,7V9:7VA,7VA:7V9,7VG:6UW,7VH:7VI,7VI:7VH,7VM:7VN,7VN:7VM,7VO:7VP,7VP:7VO,7VQ:7VR,7VR:7VQ,7VS:7VT,7VT:7VS,7VU:7VV,7VV:7VU,7VW:7VX,7VX:7VW,7VY:7VZ,7VZ:7VY,877:878,878:877,879:87A,87A:879,87B:87C,87C:87B,87D:87E,87E:87D,87F:87G,87G:87F,87H:87K,87I:87J,87J:87I,87K:87H,87L:87M,87M:87L,87N:87O,87O:87N,87P:87Q,87Q:87P,87R:87S,87S:87R,87V:6QP,880:6QQ,883:6QO,884:885,885:884,888:889,889:888,88A:88B,88B:88A,88C:88D,88D:88C,88E:88F,88F:88E,88O:6U0,88W:88X,88X:88W,890:891,891:890,89B:89C,89C:89B,89D:89E,89E:89D,89G:89H,89H:89G,89K:89L,89L:89K,89M:89N,89N:89M,8A0:8A1,8A1:8A0,8AD:6QD,8AG:8AH,8AH:8AG,8AK:8AL,8AL:8AK,8BV:8BW,8BW:8BV,8BX:8BY,8BY:8BX,8C4:8C5,8C5:8C4,8CC:8CD,8CD:8CC,8DG:8DH,8DH:8DG,8E1:8E2,8E2:8E1,8E3:8E4,8E4:8E3,8E5:8E6,8E6:8E5,8E7:8E8,8E8:8E7,8E9:8EA,8EA:8E9,8EB:8EC,8EC:8EB,8ED:8EE,8EE:8ED,8EF:8EG,8EG:8EF,8EH:8EI,8EI:8EH,8EJ:8EK,8EK:8EJ,8EL:8EM,8EM:8EL,8EN:8EO,8EO:8EN,8EP:8EQ,8EQ:8EP,8ER:8ES,8ES:8ER,8ET:8EU,8EU:8ET,8EV:8EW,8EW:8EV,8EX:8EY,8EY:8EX,8EZ:8F0,8F0:8EZ,8F1:8F2,8F2:8F1,8F3:8F4,8F4:8F3,8F5:8F6,8F6:8F5,8FA:8FB,8FB:8FA,8FC:8FD,8FD:8FC,8FE:8FF,8FF:8FE,8FG:8FH,8FH:8FG,8FJ:8FK,8FK:8FJ,8FL:8FM,8FM:8FL,8FN:8FO,8FO:8FN,8FP:8FQ,8FQ:8FP,8FR:8FS,8FS:8FR,8FT:8FU,8FU:8FT,8FV:8FW,8FW:8FV,8FX:8FY,8FY:8FX,8FZ:8G0,8G0:8FZ,8G1:8G2,8G2:8G1,8G3:8G4,8G4:8G3,8G5:8G6,8G6:8G5,8G7:8G8,8G8:8G7,8G9:8GA,8GA:8G9,8GB:8GC,8GC:8GB,8GD:8GE,8GE:8GD,8GF:8GG,8GG:8GF,8GH:8GI,8GI:8GH,8GJ:8GK,8GK:8GJ,8GL:8GM,8GM:8GL,8GU:6UE,8GZ:6UH,8H0:6UG,8H1:6UJ,8H8:8H9,8H9:8H8,8HA:6QS,8HJ:8HK,8HK:8HJ,8HL:8HM,8HM:8HL,8OU:6QN,936:937,937:936,938:939,939:938,93D:93E,93E:93D,93G:93H,93H:93G,93W:93X,93X:93W,940:941,941:940,942:943,943:942,944:945,945:944,946:947,947:946,948:949,949:948,95H:95I,95I:95H,95J:95K,95K:95J,95L:95M,95M:95L,95N:95O,95O:95N,9HK:9HL,9HL:9HK,9HM:9HN,9HN:9HM,9HO:9HP,9HP:9HO,9HQ:9HR,9HR:9HQ,9HS:9HT,9HT:9HS,9HW:9HX,9HX:9HW,9HY:9HZ,9HZ:9HY,9I0:9I1,9I1:9I0,9I2:9I3,9I3:9I2,1E8P:1E8Q,1E8Q:1E8P,1E8R:1E8S,1E8S:1E8R,1E8T:1E8U,1E8U:1E8T,1E90:1E91,1E91:1E90,1EDK:1EDL,1EDL:1EDK,1EE4:1EE6,1EE6:1EE4,1EEZ:1EF1,1EF1:1EEZ,1EFV:1EFX,1EFX:1EFV,1EFZ:1EG0,1EG0:1EFZ,1EG2:1EG3,1EG3:1EG2";
242
+ var starts = null;
243
+ var values = null;
244
+ function classTable() {
245
+ if (starts === null || values === null) {
246
+ const s = new Int32Array(CLASS_RUNS);
247
+ const v = new Uint8Array(CLASS_RUNS);
248
+ let cp = 0;
249
+ let run = 0;
250
+ let len = 0;
251
+ for (let i = 0; i < CLASS_PACKED.length; i++) {
252
+ const code = CLASS_PACKED.charCodeAt(i);
253
+ if (code >= 97) {
254
+ s[run] = cp;
255
+ v[run] = code - 97;
256
+ run++;
257
+ cp += len;
258
+ len = 0;
259
+ } else {
260
+ len = len * 36 + (code <= 57 ? code - 48 : code - 55);
261
+ }
262
+ }
263
+ starts = s;
264
+ values = v;
265
+ }
266
+ return { starts, values };
267
+ }
268
+ var brackets = null;
269
+ var mirrors = null;
270
+ function bidiClassOf(cp) {
271
+ if (!Number.isInteger(cp) || cp < 0 || cp > 1114111) return "L";
272
+ const table = classTable();
273
+ let lo = 0;
274
+ let hi = table.starts.length - 1;
275
+ while (lo < hi) {
276
+ const mid = lo + hi + 1 >> 1;
277
+ if (table.starts[mid] <= cp) lo = mid;
278
+ else hi = mid - 1;
279
+ }
280
+ return CLASSES[table.values[lo]];
281
+ }
282
+ function pairedBracket(cp) {
283
+ if (brackets === null) {
284
+ brackets = /* @__PURE__ */ new Map();
285
+ for (const record of BRACKETS.split(",")) {
286
+ const at = record.search(/[oc]/);
287
+ brackets.set(parseInt(record.slice(0, at), 36), {
288
+ pair: parseInt(record.slice(at + 1), 36),
289
+ kind: record[at] === "o" ? "open" : "close"
290
+ });
291
+ }
292
+ }
293
+ return brackets.get(cp) ?? null;
294
+ }
295
+ function mirrorOf(cp) {
296
+ if (mirrors === null) {
297
+ mirrors = /* @__PURE__ */ new Map();
298
+ for (const record of MIRRORING.split(",")) {
299
+ const at = record.indexOf(":");
300
+ mirrors.set(parseInt(record.slice(0, at), 36), parseInt(record.slice(at + 1), 36));
301
+ }
302
+ }
303
+ return mirrors.get(cp) ?? null;
304
+ }
305
+
306
+ // src/implicit.ts
307
+ var MAX_PAIRING_DEPTH = 63;
308
+ function canonicalBracket(cp) {
309
+ if (cp === 12296) return 9001;
310
+ if (cp === 12297) return 9002;
311
+ return cp;
312
+ }
313
+ function isNI(c) {
314
+ return c === "B" || c === "S" || c === "WS" || c === "ON" || c === "FSI" || c === "LRI" || c === "RLI" || c === "PDI";
315
+ }
316
+ function n1Direction(c) {
317
+ if (c === "L") return "L";
318
+ if (c === "R" || c === "EN" || c === "AN") return "R";
319
+ return null;
320
+ }
321
+ function resolveImplicit(seq, classes, levels, codePoints) {
322
+ const idx = seq.indices;
323
+ const n = idx.length;
324
+ if (n === 0) return;
325
+ const t = idx.map((i) => classes[i]);
326
+ const beforeW1 = t.slice();
327
+ const e = seq.level % 2 === 1 ? "R" : "L";
328
+ for (let i = 0; i < n; i++) {
329
+ if (t[i] !== "NSM") continue;
330
+ if (i === 0) {
331
+ t[i] = seq.sos;
332
+ continue;
333
+ }
334
+ const prev = t[i - 1];
335
+ t[i] = prev === "LRI" || prev === "RLI" || prev === "FSI" || prev === "PDI" ? "ON" : prev;
336
+ }
337
+ let strong = seq.sos;
338
+ for (let i = 0; i < n; i++) {
339
+ const c = t[i];
340
+ if (c === "L" || c === "R" || c === "AL") strong = c;
341
+ else if (c === "EN" && strong === "AL") t[i] = "AN";
342
+ }
343
+ for (let i = 0; i < n; i++) if (t[i] === "AL") t[i] = "R";
344
+ for (let i = 1; i < n - 1; i++) {
345
+ const c = t[i];
346
+ if (c === "ES" && t[i - 1] === "EN" && t[i + 1] === "EN") t[i] = "EN";
347
+ else if (c === "CS" && t[i - 1] === "EN" && t[i + 1] === "EN") t[i] = "EN";
348
+ else if (c === "CS" && t[i - 1] === "AN" && t[i + 1] === "AN") t[i] = "AN";
349
+ }
350
+ for (let i = 0; i < n; i++) {
351
+ if (t[i] !== "ET") continue;
352
+ let j = i;
353
+ while (j < n && t[j] === "ET") j++;
354
+ const before = i > 0 && t[i - 1] === "EN";
355
+ const after = j < n && t[j] === "EN";
356
+ if (before || after) for (let k = i; k < j; k++) t[k] = "EN";
357
+ i = j - 1;
358
+ }
359
+ for (let i = 0; i < n; i++) {
360
+ if (t[i] === "ET" || t[i] === "ES" || t[i] === "CS") t[i] = "ON";
361
+ }
362
+ strong = seq.sos;
363
+ for (let i = 0; i < n; i++) {
364
+ const c = t[i];
365
+ if (c === "L" || c === "R") strong = c;
366
+ else if (c === "EN" && strong === "L") t[i] = "L";
367
+ }
368
+ if (codePoints) resolveBracketPairs(t, beforeW1, idx, codePoints, e, seq.sos);
369
+ for (let i = 0; i < n; i++) {
370
+ if (!isNI(t[i])) continue;
371
+ let j = i;
372
+ while (j < n && isNI(t[j])) j++;
373
+ const before = i === 0 ? seq.sos : n1Direction(t[i - 1]);
374
+ const after = j === n ? seq.eos : n1Direction(t[j]);
375
+ const fill = before !== null && before === after ? before : e;
376
+ for (let k = i; k < j; k++) t[k] = fill;
377
+ i = j - 1;
378
+ }
379
+ for (let i = 0; i < n; i++) {
380
+ const level = levels[idx[i]];
381
+ const c = t[i];
382
+ if (level % 2 === 0) {
383
+ if (c === "R") levels[idx[i]] = level + 1;
384
+ else if (c === "AN" || c === "EN") levels[idx[i]] = level + 2;
385
+ } else if (c === "L" || c === "AN" || c === "EN") {
386
+ levels[idx[i]] = level + 1;
387
+ }
388
+ }
389
+ for (let i = 0; i < n; i++) classes[idx[i]] = t[i];
390
+ }
391
+ function resolveBracketPairs(t, beforeW1, idx, codePoints, e, sos) {
392
+ const n = t.length;
393
+ const stack = [];
394
+ const pairs = [];
395
+ for (let i = 0; i < n; i++) {
396
+ if (t[i] !== "ON") continue;
397
+ const b = pairedBracket(codePoints[idx[i]]);
398
+ if (!b) continue;
399
+ if (b.kind === "open") {
400
+ if (stack.length === MAX_PAIRING_DEPTH) return;
401
+ stack.push({ closer: canonicalBracket(b.pair), pos: i });
402
+ } else {
403
+ const closing = canonicalBracket(codePoints[idx[i]]);
404
+ for (let s = stack.length - 1; s >= 0; s--) {
405
+ if (stack[s].closer !== closing) continue;
406
+ pairs.push([stack[s].pos, i]);
407
+ stack.length = s;
408
+ break;
409
+ }
410
+ }
411
+ }
412
+ pairs.sort((a, b) => a[0] - b[0]);
413
+ const opposite = e === "L" ? "R" : "L";
414
+ for (const [open, close] of pairs) {
415
+ let found = null;
416
+ for (let i = open + 1; i < close; i++) {
417
+ const d = n1Direction(t[i]);
418
+ if (d === null) continue;
419
+ if (d === e) {
420
+ found = e;
421
+ break;
422
+ }
423
+ found = opposite;
424
+ }
425
+ if (found === null) continue;
426
+ let set;
427
+ if (found === e) {
428
+ set = e;
429
+ } else {
430
+ let prior = sos;
431
+ for (let i = open - 1; i >= 0; i--) {
432
+ const d = n1Direction(t[i]);
433
+ if (d !== null) {
434
+ prior = d;
435
+ break;
436
+ }
437
+ }
438
+ set = prior === opposite ? opposite : e;
439
+ }
440
+ t[open] = set;
441
+ t[close] = set;
442
+ for (const at of [open, close]) {
443
+ for (let i = at + 1; i < n; i++) {
444
+ if (beforeW1[i] !== "NSM") break;
445
+ t[i] = set;
446
+ }
447
+ }
448
+ }
449
+ }
450
+
451
+ // src/resolve.ts
452
+ function resolveLevels(classes, direction = "auto", codePoints) {
453
+ const paragraphLevel = direction === "ltr" ? 0 : direction === "rtl" ? 1 : paragraphLevelOf(classes);
454
+ const explicit = resolveExplicit(classes, paragraphLevel);
455
+ for (const seq of buildSequences(explicit)) {
456
+ resolveImplicit(seq, explicit.classes, explicit.levels, codePoints ?? null);
457
+ }
458
+ return {
459
+ levels: explicit.levels,
460
+ classes: explicit.classes,
461
+ removed: explicit.removed,
462
+ paragraphLevel
463
+ };
464
+ }
465
+
466
+ // src/reorder.ts
467
+ function isResettable(c) {
468
+ return c === "WS" || c === "FSI" || c === "LRI" || c === "RLI" || c === "PDI";
469
+ }
470
+ function reorderLine(original, resolved, start, end) {
471
+ const { levels: paraLevels, removed, paragraphLevel } = resolved;
472
+ const levels = new Int16Array(end - start).fill(-1);
473
+ const kept = [];
474
+ for (let i = start; i < end; i++) {
475
+ if (removed[i]) continue;
476
+ levels[i - start] = paraLevels[i];
477
+ kept.push(i);
478
+ }
479
+ if (kept.length === 0) return { order: [], levels };
480
+ for (const i of kept) {
481
+ const c = original[i];
482
+ if (c !== "S" && c !== "B") continue;
483
+ levels[i - start] = paragraphLevel;
484
+ for (let k = kept.indexOf(i) - 1; k >= 0; k--) {
485
+ const j = kept[k];
486
+ if (!isResettable(original[j])) break;
487
+ levels[j - start] = paragraphLevel;
488
+ }
489
+ }
490
+ for (let k = kept.length - 1; k >= 0; k--) {
491
+ const j = kept[k];
492
+ if (!isResettable(original[j])) break;
493
+ levels[j - start] = paragraphLevel;
494
+ }
495
+ const order = kept.slice();
496
+ let highest = 0;
497
+ let lowestOdd = Number.MAX_SAFE_INTEGER;
498
+ for (const i of kept) {
499
+ const l = levels[i - start];
500
+ if (l > highest) highest = l;
501
+ if (l % 2 === 1 && l < lowestOdd) lowestOdd = l;
502
+ }
503
+ for (let level = highest; level >= lowestOdd; level--) {
504
+ for (let a = 0; a < order.length; a++) {
505
+ if (levels[order[a] - start] < level) continue;
506
+ let b = a;
507
+ while (b + 1 < order.length && levels[order[b + 1] - start] >= level) b++;
508
+ for (let lo = a, hi = b; lo < hi; lo++, hi--) {
509
+ const t = order[lo];
510
+ order[lo] = order[hi];
511
+ order[hi] = t;
512
+ }
513
+ a = b;
514
+ }
515
+ }
516
+ return { order, levels };
517
+ }
518
+
519
+ // src/index.ts
520
+ function analyze(codePoints, direction = "auto") {
521
+ const original = Array.from(codePoints, bidiClassOf);
522
+ const resolved = resolveLevels(original, direction, codePoints);
523
+ return { ...resolved, original };
524
+ }
525
+ function reorder(analysis, start, end) {
526
+ return reorderLine(analysis.original, analysis, start, end);
527
+ }
528
+ function mirror(cp) {
529
+ return mirrorOf(cp);
530
+ }
531
+ var bidi = { analyze, reorder, mirror };
532
+
533
+ export { UNICODE_VERSION as BIDI_UNICODE_VERSION, UNICODE_VERSION, analyze, bidi, bidiClassOf, mirror, mirrorOf, pairedBracket, reorder, reorderLine, resolveLevels };
534
+ //# sourceMappingURL=index.js.map
535
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/paragraph.ts","../src/explicit.ts","../src/sequences.ts","../src/tables.ts","../src/implicit.ts","../src/resolve.ts","../src/reorder.ts","../src/index.ts"],"names":["isIsolateInitiator"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * P2/P3 and BD9 — deciding which way a paragraph reads.\n *\n * Split out because `X5c` reruns exactly this over the inside of an `FSI`:\n * a first-strong scan is the paragraph rule and the auto-direction isolate\n * rule at once, so it takes a range rather than assuming the whole text.\n */\n\nimport type { BidiClass } from './types';\n\n/** Isolate initiators, per BD8. */\nfunction isIsolateInitiator(c: BidiClass): boolean {\n return c === 'LRI' || c === 'RLI' || c === 'FSI';\n}\n\n/**\n * BD9 — the index of the PDI matching the initiator at `start`, or `end` when\n * it has none.\n *\n * Depth-counted rather than nearest-match: a nested isolate consumes its own\n * PDI, so the first PDI encountered is usually not the answer.\n */\nexport function matchingPDI(\n classes: readonly BidiClass[],\n start: number,\n end: number = classes.length,\n): number {\n let depth = 1;\n for (let i = start + 1; i < end; i++) {\n const c = classes[i];\n if (isIsolateInitiator(c)) depth++;\n else if (c === 'PDI' && --depth === 0) return i;\n }\n return end;\n}\n\n/**\n * P2/P3 — the embedding level a range reads at: 0 for left-to-right, 1 for\n * right-to-left.\n *\n * P2 skips the *contents* of an isolate: an isolate is opaque to the search by\n * definition, so a Latin word quoted inside a Hebrew paragraph cannot flip the\n * paragraph. An unmatched initiator therefore swallows everything after it,\n * which is why an all-RTL text opening with a stray `LRI` still reports 0 —\n * no strong character was ever reached, and P3's default is 0.\n */\nexport function paragraphLevelOf(\n classes: readonly BidiClass[],\n start = 0,\n end: number = classes.length,\n): 0 | 1 {\n for (let i = start; i < end; i++) {\n const c = classes[i];\n if (isIsolateInitiator(c)) {\n i = matchingPDI(classes, i, end);\n continue;\n }\n if (c === 'L') return 0;\n if (c === 'R' || c === 'AL') return 1;\n }\n return 0;\n}\n","/**\n * X1–X8 — explicit embeddings, overrides and isolates.\n *\n * This is the pass that turns formatting codes into a level per character. It\n * is stack machinery rather than text analysis: nothing here looks at what the\n * characters *are* beyond their class, and the weak/neutral rules that follow\n * run over the levels this produces.\n *\n * Two asymmetries in the spec are easy to implement wrongly and are the reason\n * this file exists on its own:\n *\n * - An embedding code (`RLE`/`LRE`/`RLO`/`LRO`/`PDF`) is *removed* by X9, while\n * an isolate initiator and its `PDI` are kept and take the level of the text\n * *outside* the isolate. Removed characters keep their slot here, flagged in\n * `removed`, so every array stays index-aligned with the input.\n * - Overflow is counted in two separate registers, and a `PDF` or `PDI` has to\n * unwind overflow before it is allowed to pop anything real. Collapsing them\n * into one counter passes simple cases and fails the conformance file.\n */\n\nimport type { BidiClass } from './types';\nimport { paragraphLevelOf, matchingPDI } from './paragraph';\n\n/** BD2 — the deepest embedding level the algorithm tracks. */\nexport const MAX_DEPTH = 125;\n\nexport interface ExplicitResult {\n /** Embedding level per input character. */\n levels: Uint8Array;\n /** Class per input character, rewritten where an override applied. */\n classes: BidiClass[];\n /** X9 — true where the character is an embedding or pop code, or `BN`. */\n removed: boolean[];\n paragraphLevel: 0 | 1;\n}\n\ntype Override = 'neutral' | 'L' | 'R';\n\ninterface StackEntry {\n level: number;\n override: Override;\n isolate: boolean;\n}\n\nfunction nextOdd(level: number): number {\n return level + 1 + ((level + 1) % 2 === 0 ? 1 : 0);\n}\nfunction nextEven(level: number): number {\n return level + 1 + ((level + 1) % 2 === 0 ? 0 : 1);\n}\n\nfunction isRemovedByX9(c: BidiClass): boolean {\n return c === 'RLE' || c === 'LRE' || c === 'RLO' || c === 'LRO'\n || c === 'PDF' || c === 'BN';\n}\n\nexport function resolveExplicit(\n input: readonly BidiClass[],\n paragraphLevel: 0 | 1,\n): ExplicitResult {\n const n = input.length;\n const classes = input.slice();\n const levels = new Uint8Array(n);\n const removed = new Array<boolean>(n).fill(false);\n\n // X1.\n const stack: StackEntry[] = [\n { level: paragraphLevel, override: 'neutral', isolate: false },\n ];\n let overflowIsolate = 0;\n let overflowEmbedding = 0;\n let validIsolate = 0;\n const top = (): StackEntry => stack[stack.length - 1];\n\n for (let i = 0; i < n; i++) {\n const c = classes[i];\n\n switch (c) {\n // X2–X5: embeddings and overrides.\n case 'RLE': case 'LRE': case 'RLO': case 'LRO': {\n // The code itself takes the level in force *before* it, then is\n // removed; the level it computes applies to what follows.\n levels[i] = top().level;\n removed[i] = true;\n const rtl = c === 'RLE' || c === 'RLO';\n const level = rtl ? nextOdd(top().level) : nextEven(top().level);\n const override: Override = c === 'RLO' ? 'R' : c === 'LRO' ? 'L' : 'neutral';\n if (level <= MAX_DEPTH && overflowIsolate === 0 && overflowEmbedding === 0) {\n stack.push({ level, override, isolate: false });\n } else if (overflowIsolate === 0) {\n overflowEmbedding++;\n }\n break;\n }\n\n // X5a–X5c: isolates. The initiator is kept and sits outside.\n case 'RLI': case 'LRI': case 'FSI': {\n let rtl = c === 'RLI';\n if (c === 'FSI') {\n // X5c — first-strong over the contents, which is P2/P3 again.\n rtl = paragraphLevelOf(classes, i + 1, matchingPDI(classes, i, n)) === 1;\n }\n levels[i] = top().level;\n if (top().override !== 'neutral') classes[i] = top().override as BidiClass;\n const level = rtl ? nextOdd(top().level) : nextEven(top().level);\n if (level <= MAX_DEPTH && overflowIsolate === 0 && overflowEmbedding === 0) {\n validIsolate++;\n stack.push({ level, override: 'neutral', isolate: true });\n } else {\n overflowIsolate++;\n }\n break;\n }\n\n // X6a.\n case 'PDI': {\n if (overflowIsolate > 0) {\n overflowIsolate--;\n } else if (validIsolate > 0) {\n // An unmatched embedding inside the isolate dies with it, so the\n // embedding overflow register resets rather than surviving the pop.\n overflowEmbedding = 0;\n while (!top().isolate) stack.pop();\n stack.pop();\n validIsolate--;\n }\n // Whether or not it popped, a PDI takes the level now in force.\n levels[i] = top().level;\n if (top().override !== 'neutral') classes[i] = top().override as BidiClass;\n break;\n }\n\n // X7.\n case 'PDF': {\n levels[i] = top().level;\n removed[i] = true;\n if (overflowIsolate > 0) {\n // An isolate outranks it: the PDF belongs to text already discarded.\n } else if (overflowEmbedding > 0) {\n overflowEmbedding--;\n } else if (!top().isolate && stack.length >= 2) {\n stack.pop();\n }\n break;\n }\n\n // X8 — a paragraph separator always returns to the paragraph level.\n case 'B': {\n levels[i] = paragraphLevel;\n break;\n }\n\n case 'BN': {\n levels[i] = top().level;\n removed[i] = true;\n break;\n }\n\n // X6 — everything else.\n default: {\n levels[i] = top().level;\n if (top().override !== 'neutral') classes[i] = top().override as BidiClass;\n break;\n }\n }\n }\n\n return { levels, classes, removed, paragraphLevel };\n}\n\n/** Convenience for callers that want X9's removals applied as a filter. */\nexport function keptIndices(r: ExplicitResult): number[] {\n const out: number[] = [];\n for (let i = 0; i < r.removed.length; i++) if (!r.removed[i]) out.push(i);\n return out;\n}\n\nexport { isRemovedByX9 };\n","/**\n * BD13 and X10 — grouping characters into the units the W/N/I rules run over.\n *\n * The unit is not the level run. An isolate is meant to be transparent to the\n * text around it, so a run ending in an isolate initiator continues at the run\n * beginning with that initiator's matching `PDI`, and the two are one sequence\n * with the isolate's contents excluded. An *embedding* does break the sequence.\n * That asymmetry is the whole of BD13, and getting it wrong turns every rule\n * downstream into \"nearly right\".\n */\n\nimport type { BidiClass } from './types';\nimport type { ExplicitResult } from './explicit';\nimport { matchingPDI } from './paragraph';\n\n/** Direction a boundary is treated as having, per X10. */\nexport type Boundary = 'L' | 'R';\n\nexport interface IsolatingRunSequence {\n /** Indices into the original text, in logical order, X9-removals excluded. */\n indices: number[];\n level: number;\n sos: Boundary;\n eos: Boundary;\n}\n\nfunction isIsolateInitiator(c: BidiClass): boolean {\n return c === 'LRI' || c === 'RLI' || c === 'FSI';\n}\n\n/** Higher of two levels decides the boundary: odd reads right-to-left. */\nfunction boundaryOf(a: number, b: number): Boundary {\n return Math.max(a, b) % 2 === 1 ? 'R' : 'L';\n}\n\nexport function buildSequences(r: ExplicitResult): IsolatingRunSequence[] {\n const { classes, levels, removed, paragraphLevel } = r;\n const n = classes.length;\n\n const kept: number[] = [];\n for (let i = 0; i < n; i++) if (!removed[i]) kept.push(i);\n if (kept.length === 0) return [];\n\n // Match initiators to their PDIs once, over the original text — the pairing\n // is positional and does not care which characters X9 dropped.\n const pdiOf = new Map<number, number>();\n const initiatorOf = new Map<number, number>();\n for (let i = 0; i < n; i++) {\n if (!isIsolateInitiator(classes[i])) continue;\n const m = matchingPDI(classes, i, n);\n if (m < n) {\n pdiOf.set(i, m);\n initiatorOf.set(m, i);\n }\n }\n\n // Level runs over the kept characters.\n interface Run { level: number; indices: number[] }\n const runs: Run[] = [];\n for (const i of kept) {\n const last = runs[runs.length - 1];\n if (last && last.level === levels[i]) last.indices.push(i);\n else runs.push({ level: levels[i], indices: [i] });\n }\n const runStartingAt = new Map<number, number>();\n runs.forEach((run, k) => runStartingAt.set(run.indices[0], k));\n\n const out: IsolatingRunSequence[] = [];\n const consumed = new Array<boolean>(runs.length).fill(false);\n\n for (let k = 0; k < runs.length; k++) {\n if (consumed[k]) continue;\n // A run opening with a PDI that closes an isolate is a continuation of an\n // earlier sequence, never the start of one.\n const first = runs[k].indices[0];\n if (classes[first] === 'PDI' && initiatorOf.has(first)) continue;\n\n const indices: number[] = [];\n let cur = k;\n for (;;) {\n consumed[cur] = true;\n indices.push(...runs[cur].indices);\n const lastIdx = runs[cur].indices[runs[cur].indices.length - 1];\n if (!isIsolateInitiator(classes[lastIdx])) break;\n const pdi = pdiOf.get(lastIdx);\n if (pdi === undefined) break;\n const next = runStartingAt.get(pdi);\n if (next === undefined || consumed[next]) break;\n cur = next;\n }\n\n const level = runs[k].level;\n const start = indices[0];\n const end = indices[indices.length - 1];\n\n let before: number = paragraphLevel;\n for (let i = start - 1; i >= 0; i--) {\n if (!removed[i]) { before = levels[i]; break; }\n }\n\n // An unmatched initiator ends its sequence against the paragraph rather\n // than against whatever text happens to follow it.\n let after: number = paragraphLevel;\n if (!(isIsolateInitiator(classes[end]) && !pdiOf.has(end))) {\n for (let i = end + 1; i < n; i++) {\n if (!removed[i]) { after = levels[i]; break; }\n }\n }\n\n out.push({\n indices,\n level,\n sos: boundaryOf(level, before),\n eos: boundaryOf(level, after),\n });\n }\n\n return out;\n}\n","/**\n * GENERATED FILE -- DO NOT EDIT BY HAND.\n *\n * Emitted by `packages/bidi/scripts/gen-bidi-tables.mjs` from the Unicode\n * Character Database. Regenerate with `npm run gen:bidi-tables`.\n */\n\nimport type { BidiClass, PairedBracket } from './types';\n\n/** The Unicode release these tables were generated from. */\nexport const UNICODE_VERSION = '16.0.0';\n\nconst CLASSES: readonly BidiClass[] = [\n 'L',\n 'R',\n 'AL',\n 'EN',\n 'ES',\n 'ET',\n 'AN',\n 'CS',\n 'NSM',\n 'BN',\n 'B',\n 'S',\n 'WS',\n 'ON',\n 'LRE',\n 'RLE',\n 'LRO',\n 'RLO',\n 'PDF',\n 'LRI',\n 'RLI',\n 'FSI',\n 'PDI',\n];\n\n// Run-length encoding of Bidi_Class over the whole code space, defaults from\n// DerivedBidiClass.txt's `@missing` lines included. Each record is a run\n// length in uppercase base 36 followed by one lowercase letter indexing\n// CLASSES; coverage is total, so each run starts where the last one ended.\nconst CLASS_RUNS = 1239;\nconst CLASS_PACKED =\n '9j1l1k1l1m1kEj3k1l1m2n3f5n1e1h1e2hAd1h6nQa6nQa4n6j1kQj1h1n4f4n1a2n1j2n2f2d1n1a3n1d1a5nNa1nVa1nCH' +\n 'a2n7aEn2aEn5a9n1aHn34i4a2n8a1n5a2n1a1n32a1n3Wa7i74a1n2a2n1f1b19i1b1i1b2i1b2i1b1i1Kb6g2n1c2f1c1h1' +\n 'c2nBi1CcLiAg1f2g3c1i2Tc7i1g1n6i2c2i1n4i2cAdNc1iUcRi2JcBiFc17b9i2b4n3b1iOb4i1b9i1b3i1b5i17b3i4b1C' +\n 'c2g5c9i16cOi1gWi1Ja1i1a1i4a8i4a1i3a7iAa2iTa1i1Ma1i4a4i8a1iKa2iEa2f7a1f2a1i2a2i1La1i4a2i4a2i2a3i3' +\n 'a1iUa2i3a1iBa2i1La1i4a5i1a2i4a1iKa2iDa1f8a6i1a1i1Ma1i2a1i1a4i8a1i7a2iBa2iUa1i1Pa1iCa1i11a6n1f1n5' +\n 'a1i3a1i1Ja1i1a3i5a3i1a4i7a2iBa2iKa7n2a1i1Ma1iFa2iKa2iSa2i1La2i4a4i8a1iKa2iTa1i20a1i7a3i1a1i2Ia1i' +\n '2a7i4a1f7a8i2Qa1i2a9iBa7i21a2iRa1i1a1i1a1i4n1FaEi1a5i1a2i5aBi1a10i9a1i2Ua4i1a6i1a2i2a2iPa2i4a3iG' +\n 'a4iDa1i2a2i6a1iFa1iJJa3i1CaAn2Ua1nHRa1mQa2n39a3iTa2iUa2iUa2i1Sa2i1a7i8a1i2aBi7a1f1a1iIaAn6aBn3i1' +\n 'j1i39a2iYa1i3Aa3i4a2i9a1i6a3i4a1n3a2n48aYnNa2i2a1i1Ma1i1a7i1a1i1a1i2a8i6aAi2a1i1CaVi1Da4i1Ca1i1a' +\n '5i1a1i5a1i14a9iCa2iWa4i2a2i1a3i1Ka1i1a2i3a1i1a3i1Ma8i2a2i48a3i1aDi1a7i4a1i6a1i3a2i5Ia1SiCDa1n1a3' +\n 'nBa3nDa3nDa3nDa2n1aBm3j1a1bOn1m1k1o1p1s1q1r1h5fFn1hQn1m6j1t1u1v1w6j1d3a6d2e3n1aAd2e3nHa1CfXiFa2n' +\n '1a4n1a2nAa1n1a3n5a6n1a1n1a1n1a1n4a1fBa2n4a5n5a4n2aGn15a3n4a3Mn1e1f82n1XaQn1a44nMaBnLa14nKd26aCIn' +\n '1a9Fn74aHGn2aWn1a2Xn6Da6n4a3i7a7n3Ja1i2OaWi2MnYaQn1a2HnCa5YnQaGn1m4n3aPn9a4i2a1n5a2n5a3n2Ha2i2n3' +\n 'a1n2Ia1n5Ga12n9a1n19a2n1DaGnSa3n1EaFnCa4n4Na4n2Ra2nVa1n534a1SnH3Ka1Jn92a3n2Na4i1nAi2nUa2i28a2iEa' +\n 'Yn2Ua1n3Da1i3a1i4a1iPa2i1a4n1iBa2f1Ma4n24a2iQaIiDa1i12a8iPaBi1Aa3i1Ca1i2a4i2a2i13a1i1Va6i2a2i2a2' +\n 'iCa1i8a1i1Ba1i1Fa1i1a3i2a2i5a2i1a1i16a2i8a1i37a2n3Da1i2a1i4a1iFN3a1b1iAb1e12bDQcIn3Jc1nWjDc3nGiA' +\n 'n6aGiWn1h1n1h1a1n1h9n1f2n2e3n1a1n2f1n4a3Zc1j1a2n3f5n1e1h1e2hAd1h6nQa6nQaBn3Ea2f3n2f1a7n1a9j5n2j7' +\n '5a1n1Qa25n3aDn3a1n2Ka1i6Aa1iRd3Ea5iW5a7Zb1n69b3i1b2i5b4i14b3i4b1i4Lb2i2Ab7nCGb10c4i8cAg6cAgVb5i1' +\n 'n6PbVg18b2iJb1Oc4i1CbMcBiVcIb4i3Eb1a1i1IaFiBaKnAa1i2a2iAa3i1Da4i2a2i7a1i1Pa3i10a5i1a8i1Qa1iCa2i1' +\n 'Ga9iAa4i2a1i2Na3i2a1i1a2i6a1i2a1i4Da1i3a8iLa2i1La2i3a1i11a7i3a5i1Ya6iDa1i1a1i1a1iEa2i2Da8i2a3i1a' +\n '1iNa1i2Ca6i1a1i4a2i1a2i6Ma4i6a2i1a2iRa2i2Da8i2a1i1a2iVaDn1Qa1i1a1i2a6i1a1i2Ta1i1a1i2a4i1a5i77a9i' +\n '1a2i74a2i1a1i4a1i40a4i2a2i4a1iWa6i2a2i14a6i2a4i8a1i9a6i2a3i1AaDi1a2iBAa7i1a6i2CaMi2a7i1a2i1a2i3E' +\n 'a6i3a1i1a2i1a7i1a1i20a2i3a1i1a1i9Na2iBa2i1Ga5i5a1i1a1iNa1i3Ea8n4fHn40Ea1i6aFi8UGaCi3a3i1XCa5i1Na' +\n '7iT4a1i1Ra4i27a1n1a1iF5Ka2i1a4j318a5YnQaAd6aC4n24a1Ai2aNiF4a3i9a8j8i2a7iUa4i1Na2nLa1Un3i1n56a2Fn' +\n 'OAa1nPa1nVa1nPa1nVa1nPa1nVa1nPa1nVa1nPa1nAa1EdE8a1Ji4a1Ei8a1iEa1iMa5i1aFi11Sa7i1aHi2a7i1a2i1a5i2' +\n 'Sa1i4Ga7iAFa1i1Pa4iFa1fDOa4i72a2iEOa5Sb7i31b7iMDb28c1Sb28c4Wb6Oc2nEc74b18n4a2SnCaFn2aFn1aFn1a11n' +\n 'AaBd5nVa1n1Ma6n1Pa1n4Ya6n4AaRCn4aHn3aDn3a3Bn4a2Nn6aCn4a1nFaCn4a1Kn8aAn6a14n8aUn2aCn4a2n1Qa9GnCaE' +\n 'n2aDn3aAn5a1Kn7aFn2aBn6a9n7a43n1a2KnAdSKa2j1EKEa2j1EKEa2j1EKEa2j1EKEa2j1EKEa2j1EKEa2j1EKEa2j1EKE' +\n 'a2j1EKEa2j1EKEa2j1EKEa2j1EKEa76j6Oi2S0j1BEMa2j1EKEa2j1EKEa2j';\n\n// `<code point>[oc]<pair>` per entry, base 36, ascending by code point.\nconst BRACKETS =\n '14o15,15c14,2Jo2L,2Lc2J,3Fo3H,3Hc3F,30Ao30B,30Bc30A,30Co30D,30Dc30C,4GRo4GS,4GSc4GR,6DHo6DI,6DIc' +\n '6DH,6F1o6F2,6F2c6F1,6FHo6FI,6FIc6FH,6X4o6X5,6X5c6X4,6X6o6X7,6X7c6X6,6Y1o6Y2,6Y2c6Y1,7S8o7S9,7S9c' +\n '7S8,7SAo7SB,7SBc7SA,7SCo7SD,7SDc7SC,7SEo7SF,7SFc7SE,7SGo7SH,7SHc7SG,7SIo7SJ,7SJc7SI,7SKo7SL,7SLc' +\n '7SK,7UTo7UU,7UUc7UT,7VQo7VR,7VRc7VQ,7VSo7VT,7VTc7VS,7VUo7VV,7VVc7VU,7VWo7VX,7VXc7VW,7VYo7VZ,7VZc' +\n '7VY,877o878,878c877,879o87A,87Ac879,87Bo87C,87Cc87B,87Do87E,87Ec87D,87Fo87G,87Gc87F,87Ho87K,87Ic' +\n '87J,87Jo87I,87Kc87H,87Lo87M,87Mc87L,87No87O,87Oc87N,87Po87Q,87Qc87P,87Ro87S,87Sc87R,89Ko89L,89Lc' +\n '89K,89Mo89N,89Nc89M,8AKo8AL,8ALc8AK,942o943,943c942,944o945,945c944,946o947,947c946,948o949,949c' +\n '948,95Ho95I,95Ic95H,95Jo95K,95Kc95J,95Lo95M,95Mc95L,95No95O,95Oc95N,9HKo9HL,9HLc9HK,9HMo9HN,9HNc' +\n '9HM,9HOo9HP,9HPc9HO,9HQo9HR,9HRc9HQ,9HSo9HT,9HTc9HS,9HWo9HX,9HXc9HW,9HYo9HZ,9HZc9HY,9I0o9I1,9I1c' +\n '9I0,9I2o9I3,9I3c9I2,1E8Po1E8Q,1E8Qc1E8P,1E8Ro1E8S,1E8Sc1E8R,1E8To1E8U,1E8Uc1E8T,1EDKo1EDL,1EDLc1' +\n 'EDK,1EEZo1EF1,1EF1c1EEZ,1EFVo1EFX,1EFXc1EFV,1EFZo1EG0,1EG0c1EFZ,1EG2o1EG3,1EG3c1EG2';\n\n// `<code point>:<mirror>` per entry, base 36, ascending by code point.\nconst MIRRORING =\n '14:15,15:14,1O:1Q,1Q:1O,2J:2L,2L:2J,3F:3H,3H:3F,4R:57,57:4R,30A:30B,30B:30A,30C:30D,30D:30C,4GR:' +\n '4GS,4GS:4GR,6D5:6D6,6D6:6D5,6DH:6DI,6DI:6DH,6F1:6F2,6F2:6F1,6FH:6FI,6FI:6FH,6Q0:6Q3,6Q1:6Q4,6Q2:' +\n '6Q5,6Q3:6Q0,6Q4:6Q1,6Q5:6Q2,6QD:8AD,6QN:8OU,6QO:883,6QP:87V,6QQ:880,6QS:8HA,6RG:6RH,6RH:6RG,6RN:' +\n '6VH,6RP:6RW,6RW:6RP,6S2:6S3,6S3:6S2,6S4:6S5,6S5:6S4,6SK:6SL,6SL:6SK,6SM:6SN,6SN:6SM,6SO:6SP,6SP:' +\n '6SO,6SQ:6SR,6SR:6SQ,6SU:6SV,6SV:6SU,6SW:6SX,6SX:6SW,6SY:6SZ,6SZ:6SY,6T0:6T1,6T1:6T0,6T2:6T3,6T3:' +\n '6T2,6T4:6T5,6T5:6T4,6T6:6T7,6T7:6T6,6T8:6T9,6T9:6T8,6TA:6TB,6TB:6TA,6TC:6TD,6TD:6TC,6TE:6TF,6TF:' +\n '6TE,6TG:6TH,6TH:6TG,6TI:6TJ,6TJ:6TI,6TK:6TL,6TL:6TK,6TM:6TN,6TN:6TM,6TR:6TS,6TS:6TR,6TT:6TU,6TU:' +\n '6TT,6U0:88O,6UA:6UB,6UB:6UA,6UE:8GU,6UG:8H0,6UH:8GZ,6UJ:8H1,6UO:6UP,6UP:6UO,6UQ:6UR,6UR:6UQ,6US:' +\n '6UT,6UT:6US,6UU:6UV,6UV:6UU,6UW:7VG,6VD:6VE,6VE:6VD,6VF:6VG,6VG:6VF,6VH:6RN,6VK:6VL,6VL:6VK,6VQ:' +\n '6VR,6VR:6VQ,6VS:6VT,6VT:6VS,6VU:6VV,6VV:6VU,6VW:6VX,6VX:6VW,6VY:6VZ,6VZ:6VY,6W0:6W1,6W1:6W0,6W2:' +\n '6W3,6W3:6W2,6W4:6W5,6W5:6W4,6W6:6W7,6W7:6W6,6W8:6W9,6W9:6W8,6WA:6WB,6WB:6WA,6WC:6WD,6WD:6WC,6WG:' +\n '6WH,6WH:6WG,6WI:6WQ,6WJ:6WR,6WK:6WS,6WM:6WT,6WN:6WU,6WQ:6WI,6WR:6WJ,6WS:6WK,6WT:6WM,6WU:6WN,6X4:' +\n '6X5,6X5:6X4,6X6:6X7,6X7:6X6,6Y1:6Y2,6Y2:6Y1,7S8:7S9,7S9:7S8,7SA:7SB,7SB:7SA,7SC:7SD,7SD:7SC,7SE:' +\n '7SF,7SF:7SE,7SG:7SH,7SH:7SG,7SI:7SJ,7SJ:7SI,7SK:7SL,7SL:7SK,7UR:7US,7US:7UR,7UT:7UU,7UU:7UT,7UW:' +\n '7UX,7UX:7UW,7UZ:7V1,7V1:7UZ,7V9:7VA,7VA:7V9,7VG:6UW,7VH:7VI,7VI:7VH,7VM:7VN,7VN:7VM,7VO:7VP,7VP:' +\n '7VO,7VQ:7VR,7VR:7VQ,7VS:7VT,7VT:7VS,7VU:7VV,7VV:7VU,7VW:7VX,7VX:7VW,7VY:7VZ,7VZ:7VY,877:878,878:' +\n '877,879:87A,87A:879,87B:87C,87C:87B,87D:87E,87E:87D,87F:87G,87G:87F,87H:87K,87I:87J,87J:87I,87K:' +\n '87H,87L:87M,87M:87L,87N:87O,87O:87N,87P:87Q,87Q:87P,87R:87S,87S:87R,87V:6QP,880:6QQ,883:6QO,884:' +\n '885,885:884,888:889,889:888,88A:88B,88B:88A,88C:88D,88D:88C,88E:88F,88F:88E,88O:6U0,88W:88X,88X:' +\n '88W,890:891,891:890,89B:89C,89C:89B,89D:89E,89E:89D,89G:89H,89H:89G,89K:89L,89L:89K,89M:89N,89N:' +\n '89M,8A0:8A1,8A1:8A0,8AD:6QD,8AG:8AH,8AH:8AG,8AK:8AL,8AL:8AK,8BV:8BW,8BW:8BV,8BX:8BY,8BY:8BX,8C4:' +\n '8C5,8C5:8C4,8CC:8CD,8CD:8CC,8DG:8DH,8DH:8DG,8E1:8E2,8E2:8E1,8E3:8E4,8E4:8E3,8E5:8E6,8E6:8E5,8E7:' +\n '8E8,8E8:8E7,8E9:8EA,8EA:8E9,8EB:8EC,8EC:8EB,8ED:8EE,8EE:8ED,8EF:8EG,8EG:8EF,8EH:8EI,8EI:8EH,8EJ:' +\n '8EK,8EK:8EJ,8EL:8EM,8EM:8EL,8EN:8EO,8EO:8EN,8EP:8EQ,8EQ:8EP,8ER:8ES,8ES:8ER,8ET:8EU,8EU:8ET,8EV:' +\n '8EW,8EW:8EV,8EX:8EY,8EY:8EX,8EZ:8F0,8F0:8EZ,8F1:8F2,8F2:8F1,8F3:8F4,8F4:8F3,8F5:8F6,8F6:8F5,8FA:' +\n '8FB,8FB:8FA,8FC:8FD,8FD:8FC,8FE:8FF,8FF:8FE,8FG:8FH,8FH:8FG,8FJ:8FK,8FK:8FJ,8FL:8FM,8FM:8FL,8FN:' +\n '8FO,8FO:8FN,8FP:8FQ,8FQ:8FP,8FR:8FS,8FS:8FR,8FT:8FU,8FU:8FT,8FV:8FW,8FW:8FV,8FX:8FY,8FY:8FX,8FZ:' +\n '8G0,8G0:8FZ,8G1:8G2,8G2:8G1,8G3:8G4,8G4:8G3,8G5:8G6,8G6:8G5,8G7:8G8,8G8:8G7,8G9:8GA,8GA:8G9,8GB:' +\n '8GC,8GC:8GB,8GD:8GE,8GE:8GD,8GF:8GG,8GG:8GF,8GH:8GI,8GI:8GH,8GJ:8GK,8GK:8GJ,8GL:8GM,8GM:8GL,8GU:' +\n '6UE,8GZ:6UH,8H0:6UG,8H1:6UJ,8H8:8H9,8H9:8H8,8HA:6QS,8HJ:8HK,8HK:8HJ,8HL:8HM,8HM:8HL,8OU:6QN,936:' +\n '937,937:936,938:939,939:938,93D:93E,93E:93D,93G:93H,93H:93G,93W:93X,93X:93W,940:941,941:940,942:' +\n '943,943:942,944:945,945:944,946:947,947:946,948:949,949:948,95H:95I,95I:95H,95J:95K,95K:95J,95L:' +\n '95M,95M:95L,95N:95O,95O:95N,9HK:9HL,9HL:9HK,9HM:9HN,9HN:9HM,9HO:9HP,9HP:9HO,9HQ:9HR,9HR:9HQ,9HS:' +\n '9HT,9HT:9HS,9HW:9HX,9HX:9HW,9HY:9HZ,9HZ:9HY,9I0:9I1,9I1:9I0,9I2:9I3,9I3:9I2,1E8P:1E8Q,1E8Q:1E8P,' +\n '1E8R:1E8S,1E8S:1E8R,1E8T:1E8U,1E8U:1E8T,1E90:1E91,1E91:1E90,1EDK:1EDL,1EDL:1EDK,1EE4:1EE6,1EE6:1' +\n 'EE4,1EEZ:1EF1,1EF1:1EEZ,1EFV:1EFX,1EFX:1EFV,1EFZ:1EG0,1EG0:1EFZ,1EG2:1EG3,1EG3:1EG2';\n\nlet starts: Int32Array | null = null;\nlet values: Uint8Array | null = null;\n\nfunction classTable(): { starts: Int32Array; values: Uint8Array } {\n if (starts === null || values === null) {\n const s = new Int32Array(CLASS_RUNS);\n const v = new Uint8Array(CLASS_RUNS);\n let cp = 0;\n let run = 0;\n let len = 0;\n for (let i = 0; i < CLASS_PACKED.length; i++) {\n const code = CLASS_PACKED.charCodeAt(i);\n if (code >= 97) {\n s[run] = cp;\n v[run] = code - 97;\n run++;\n cp += len;\n len = 0;\n } else {\n len = len * 36 + (code <= 57 ? code - 48 : code - 55);\n }\n }\n starts = s;\n values = v;\n }\n return { starts, values };\n}\n\nlet brackets: Map<number, PairedBracket> | null = null;\nlet mirrors: Map<number, number> | null = null;\n\n/**\n * The `Bidi_Class` of a code point.\n *\n * Unassigned code points resolve to the default their block declares, which is\n * `R` or `AL` inside the right-to-left blocks and `L` elsewhere.\n */\nexport function bidiClassOf(cp: number): BidiClass {\n if (!Number.isInteger(cp) || cp < 0 || cp > 0x10ffff) return 'L';\n const table = classTable();\n let lo = 0;\n let hi = table.starts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (table.starts[mid] <= cp) lo = mid;\n else hi = mid - 1;\n }\n return CLASSES[table.values[lo]];\n}\n\n/**\n * The `Bidi_Paired_Bracket` of a code point, for BD16 and rule N0, or `null`\n * where the code point is not one half of a pair.\n */\nexport function pairedBracket(cp: number): PairedBracket | null {\n if (brackets === null) {\n brackets = new Map();\n for (const record of BRACKETS.split(',')) {\n const at = record.search(/[oc]/);\n brackets.set(parseInt(record.slice(0, at), 36), {\n pair: parseInt(record.slice(at + 1), 36),\n kind: record[at] === 'o' ? 'open' : 'close',\n });\n }\n }\n return brackets.get(cp) ?? null;\n}\n\n/**\n * The `Bidi_Mirroring_Glyph` of a code point, or `null` where it has none.\n *\n * This is the mapping rule L4 applies, and only that: it is a hint for\n * selecting a mirrored glyph, not a character transformation, and a font's own\n * `rtlm` feature supersedes it where one exists.\n */\nexport function mirrorOf(cp: number): number | null {\n if (mirrors === null) {\n mirrors = new Map();\n for (const record of MIRRORING.split(',')) {\n const at = record.indexOf(':');\n mirrors.set(parseInt(record.slice(0, at), 36), parseInt(record.slice(at + 1), 36));\n }\n }\n return mirrors.get(cp) ?? null;\n}\n","/**\n * W1–W7, N0–N2 and I1–I2 — resolving weak and neutral types to a direction.\n *\n * Every rule here runs over one isolating run sequence, in order, each seeing\n * what the previous left behind. The ordering is load-bearing in ways that are\n * invisible from any single rule: W2 reads the last strong type while `AL` is\n * still `AL`, and W3 then erases `AL` — swap them and Arabic-Indic digits stop\n * being recognised.\n */\n\nimport type { BidiClass } from './types';\nimport type { IsolatingRunSequence } from './sequences';\nimport { pairedBracket } from './tables';\n\n/** BD16 — the pairing stack is capped, and overflow abandons N0 entirely. */\nconst MAX_PAIRING_DEPTH = 63;\n\n/**\n * BD16 requires canonical equivalents to pair with each other, and there is\n * exactly one such case in the data: the angle brackets U+2329/U+232A are\n * canonically equivalent to U+3008/U+3009. `a⟨b.1〉` is a real pair and matching\n * raw code points misses it.\n */\nfunction canonicalBracket(cp: number): number {\n if (cp === 0x3008) return 0x2329;\n if (cp === 0x3009) return 0x232a;\n return cp;\n}\n\n/** \"NI\" in the spec: neutral or isolate formatting. */\nfunction isNI(c: BidiClass): boolean {\n return c === 'B' || c === 'S' || c === 'WS' || c === 'ON'\n || c === 'FSI' || c === 'LRI' || c === 'RLI' || c === 'PDI';\n}\n\n/** N1 treats both number classes as right-to-left. */\nfunction n1Direction(c: BidiClass): 'L' | 'R' | null {\n if (c === 'L') return 'L';\n if (c === 'R' || c === 'EN' || c === 'AN') return 'R';\n return null;\n}\n\nexport function resolveImplicit(\n seq: IsolatingRunSequence,\n classes: BidiClass[],\n levels: Uint8Array,\n codePoints: readonly number[] | null,\n): void {\n const idx = seq.indices;\n const n = idx.length;\n if (n === 0) return;\n\n // Work on a dense copy so the rules read neighbours by sequence position\n // rather than by text position — the two differ wherever an isolate or an\n // X9 removal sits between them.\n const t: BidiClass[] = idx.map((i) => classes[i]);\n // N0's last clause is specified against the types *before* W1, and W1 is\n // about to overwrite exactly the NSMs it asks about.\n const beforeW1: BidiClass[] = t.slice();\n const e: 'L' | 'R' = seq.level % 2 === 1 ? 'R' : 'L';\n\n // W1 — a combining mark takes the type of what it attaches to. It attaches\n // to nothing across an isolate boundary, so those give ON rather than their\n // own class.\n for (let i = 0; i < n; i++) {\n if (t[i] !== 'NSM') continue;\n if (i === 0) { t[i] = seq.sos; continue; }\n const prev = t[i - 1];\n t[i] = (prev === 'LRI' || prev === 'RLI' || prev === 'FSI' || prev === 'PDI')\n ? 'ON'\n : prev;\n }\n\n // W2 — read against the last strong type, while AL is still AL.\n let strong: BidiClass = seq.sos;\n for (let i = 0; i < n; i++) {\n const c = t[i];\n if (c === 'L' || c === 'R' || c === 'AL') strong = c;\n else if (c === 'EN' && strong === 'AL') t[i] = 'AN';\n }\n\n // W3.\n for (let i = 0; i < n; i++) if (t[i] === 'AL') t[i] = 'R';\n\n // W4 — a single separator between two numbers of the same kind joins them.\n for (let i = 1; i < n - 1; i++) {\n const c = t[i];\n if (c === 'ES' && t[i - 1] === 'EN' && t[i + 1] === 'EN') t[i] = 'EN';\n else if (c === 'CS' && t[i - 1] === 'EN' && t[i + 1] === 'EN') t[i] = 'EN';\n else if (c === 'CS' && t[i - 1] === 'AN' && t[i + 1] === 'AN') t[i] = 'AN';\n }\n\n // W5 — a whole run of terminators joins an adjacent European number, from\n // either side, which is why it is a run scan rather than a neighbour test.\n for (let i = 0; i < n; i++) {\n if (t[i] !== 'ET') continue;\n let j = i;\n while (j < n && t[j] === 'ET') j++;\n const before = i > 0 && t[i - 1] === 'EN';\n const after = j < n && t[j] === 'EN';\n if (before || after) for (let k = i; k < j; k++) t[k] = 'EN';\n i = j - 1;\n }\n\n // W6.\n for (let i = 0; i < n; i++) {\n if (t[i] === 'ET' || t[i] === 'ES' || t[i] === 'CS') t[i] = 'ON';\n }\n\n // W7 — unlike W2 this rewrites to L, so it must follow W6's neutralisation.\n strong = seq.sos;\n for (let i = 0; i < n; i++) {\n const c = t[i];\n if (c === 'L' || c === 'R') strong = c;\n else if (c === 'EN' && strong === 'L') t[i] = 'L';\n }\n\n // N0 — bracket pairs, when the caller gave us code points to pair with.\n if (codePoints) resolveBracketPairs(t, beforeW1, idx, codePoints, e, seq.sos);\n\n // N1 — a run of neutrals between two of the same direction takes it.\n for (let i = 0; i < n; i++) {\n if (!isNI(t[i])) continue;\n let j = i;\n while (j < n && isNI(t[j])) j++;\n const before = i === 0 ? seq.sos : n1Direction(t[i - 1]);\n const after = j === n ? seq.eos : n1Direction(t[j]);\n // N2 is the fallback for everything N1 leaves: differing sides, or a side\n // that is not a direction at all.\n const fill = before !== null && before === after ? before : e;\n for (let k = i; k < j; k++) t[k] = fill;\n i = j - 1;\n }\n\n // I1 / I2.\n for (let i = 0; i < n; i++) {\n const level = levels[idx[i]];\n const c = t[i];\n if (level % 2 === 0) {\n if (c === 'R') levels[idx[i]] = level + 1;\n else if (c === 'AN' || c === 'EN') levels[idx[i]] = level + 2;\n } else if (c === 'L' || c === 'AN' || c === 'EN') {\n levels[idx[i]] = level + 1;\n }\n }\n\n for (let i = 0; i < n; i++) classes[idx[i]] = t[i];\n}\n\n/**\n * N0 with BD16 — a bracket pair takes one direction, decided by what it\n * encloses rather than by each bracket's own neighbours.\n *\n * The rule exists because N1/N2 treat the two brackets independently and will\n * happily send them opposite ways, which renders as mismatched parentheses.\n */\nfunction resolveBracketPairs(\n t: BidiClass[],\n beforeW1: readonly BidiClass[],\n idx: readonly number[],\n codePoints: readonly number[],\n e: 'L' | 'R',\n sos: 'L' | 'R',\n): void {\n const n = t.length;\n const stack: Array<{ closer: number; pos: number }> = [];\n const pairs: Array<[number, number]> = [];\n\n for (let i = 0; i < n; i++) {\n // Only characters still ON after the W rules can be brackets.\n if (t[i] !== 'ON') continue;\n const b = pairedBracket(codePoints[idx[i]]);\n if (!b) continue;\n if (b.kind === 'open') {\n if (stack.length === MAX_PAIRING_DEPTH) return;\n stack.push({ closer: canonicalBracket(b.pair), pos: i });\n } else {\n const closing = canonicalBracket(codePoints[idx[i]]);\n for (let s = stack.length - 1; s >= 0; s--) {\n if (stack[s].closer !== closing) continue;\n pairs.push([stack[s].pos, i]);\n stack.length = s;\n break;\n }\n }\n }\n pairs.sort((a, b) => a[0] - b[0]);\n\n const opposite = e === 'L' ? 'R' : 'L';\n for (const [open, close] of pairs) {\n let found: 'L' | 'R' | null = null;\n for (let i = open + 1; i < close; i++) {\n const d = n1Direction(t[i]);\n if (d === null) continue;\n if (d === e) { found = e; break; }\n found = opposite;\n }\n if (found === null) continue;\n\n let set: 'L' | 'R';\n if (found === e) {\n set = e;\n } else {\n // Enclosed text opposes the embedding: it only wins if the text leading\n // into the bracket opposed it too, otherwise the pair follows context.\n let prior: 'L' | 'R' = sos;\n for (let i = open - 1; i >= 0; i--) {\n const d = n1Direction(t[i]);\n if (d !== null) { prior = d; break; }\n }\n set = prior === opposite ? opposite : e;\n }\n t[open] = set;\n t[close] = set;\n // A combining mark on a bracket follows the bracket, not W1's answer —\n // and \"combining mark\" means what it was before W1 rewrote it.\n for (const at of [open, close]) {\n for (let i = at + 1; i < n; i++) {\n if (beforeW1[i] !== 'NSM') break;\n t[i] = set;\n }\n }\n }\n}\n","/**\n * The Unicode Bidirectional Algorithm, rules P through I.\n *\n * This is the analysis half: text in, an embedding level per character out.\n * Turning those levels into a visual order is L1–L2, which is per *line* and\n * therefore cannot happen here — the caller wraps first and reorders after.\n */\n\nimport type { BidiClass } from './types';\nimport { paragraphLevelOf } from './paragraph';\nimport { resolveExplicit } from './explicit';\nimport { buildSequences } from './sequences';\nimport { resolveImplicit } from './implicit';\n\n/** How the paragraph's own direction is decided. */\nexport type BidiDirection = 'ltr' | 'rtl' | 'auto';\n\nexport interface BidiResult {\n /** Embedding level per input character. */\n levels: Uint8Array;\n /** Class per character after the W and N rules resolved it. */\n classes: BidiClass[];\n /** X9 — true where the character is a formatting code the output drops. */\n removed: boolean[];\n paragraphLevel: 0 | 1;\n}\n\n/**\n * Resolve embedding levels for one paragraph.\n *\n * `codePoints` is optional and only feeds `N0`'s bracket pairing. Omitting it\n * costs nothing else: every other rule reads classes alone, which is how the\n * class-only half of Unicode's conformance data can drive this at all.\n */\nexport function resolveLevels(\n classes: readonly BidiClass[],\n direction: BidiDirection = 'auto',\n codePoints?: readonly number[],\n): BidiResult {\n const paragraphLevel: 0 | 1 = direction === 'ltr' ? 0\n : direction === 'rtl' ? 1\n : paragraphLevelOf(classes);\n\n const explicit = resolveExplicit(classes, paragraphLevel);\n for (const seq of buildSequences(explicit)) {\n resolveImplicit(seq, explicit.classes, explicit.levels, codePoints ?? null);\n }\n\n return {\n levels: explicit.levels,\n classes: explicit.classes,\n removed: explicit.removed,\n paragraphLevel,\n };\n}\n","/**\n * L1 and L2 — turning embedding levels into a visual order, one line at a time.\n *\n * These are the only rules that know about lines, which is why they are split\n * from `resolveLevels`: a caller wraps text into lines *after* the paragraph is\n * analysed, and the same paragraph analysis then serves every line it broke\n * into. Running L1 during the analysis would reset whitespace against the\n * paragraph's end rather than each line's.\n */\n\nimport type { BidiClass } from './types';\nimport type { BidiResult } from './resolve';\n\nexport interface ReorderedLine {\n /**\n * Original indices in visual order, left to right, with the characters X9\n * removed omitted.\n */\n order: number[];\n /**\n * Level per original index over the line, after L1. `-1` where X9 removed\n * the character.\n */\n levels: Int16Array;\n}\n\n/** Whitespace and isolate formatting — what L1 sweeps up alongside a reset. */\nfunction isResettable(c: BidiClass): boolean {\n return c === 'WS' || c === 'FSI' || c === 'LRI' || c === 'RLI' || c === 'PDI';\n}\n\n/**\n * Reorder `[start, end)` of an analysed paragraph.\n *\n * `original` must be the classes as they were *before* analysis: L1 is defined\n * against them, and by this point `resolved.classes` has rewritten the very\n * whitespace L1 is looking for.\n */\nexport function reorderLine(\n original: readonly BidiClass[],\n resolved: BidiResult,\n start: number,\n end: number,\n): ReorderedLine {\n const { levels: paraLevels, removed, paragraphLevel } = resolved;\n\n const levels = new Int16Array(end - start).fill(-1);\n const kept: number[] = [];\n for (let i = start; i < end; i++) {\n if (removed[i]) continue;\n levels[i - start] = paraLevels[i];\n kept.push(i);\n }\n if (kept.length === 0) return { order: [], levels };\n\n // L1, clauses 1 and 2: separators themselves. Clause 3 then walks back over\n // any whitespace leading into one.\n for (const i of kept) {\n const c = original[i];\n if (c !== 'S' && c !== 'B') continue;\n levels[i - start] = paragraphLevel;\n for (let k = kept.indexOf(i) - 1; k >= 0; k--) {\n const j = kept[k];\n if (!isResettable(original[j])) break;\n levels[j - start] = paragraphLevel;\n }\n }\n\n // L1 clause 4: a trailing run of whitespace ends against the paragraph, not\n // against whatever the neutral rules made of it mid-paragraph.\n for (let k = kept.length - 1; k >= 0; k--) {\n const j = kept[k];\n if (!isResettable(original[j])) break;\n levels[j - start] = paragraphLevel;\n }\n\n // L2: from the highest level down to the lowest odd one, reverse every\n // contiguous stretch at or above that level. Reversing repeatedly rather\n // than sorting is what nests correctly — an inner run reversed twice comes\n // back to its own reading order.\n const order = kept.slice();\n let highest = 0;\n let lowestOdd = Number.MAX_SAFE_INTEGER;\n for (const i of kept) {\n const l = levels[i - start];\n if (l > highest) highest = l;\n if (l % 2 === 1 && l < lowestOdd) lowestOdd = l;\n }\n\n for (let level = highest; level >= lowestOdd; level--) {\n for (let a = 0; a < order.length; a++) {\n if (levels[order[a] - start] < level) continue;\n let b = a;\n while (b + 1 < order.length && levels[order[b + 1] - start] >= level) b++;\n for (let lo = a, hi = b; lo < hi; lo++, hi--) {\n const t = order[lo];\n order[lo] = order[hi];\n order[hi] = t;\n }\n a = b;\n }\n }\n\n return { order, levels };\n}\n","/**\n * The Unicode Bidirectional Algorithm (UAX #9).\n *\n * Plain data in, plain data out: code points and a direction go in, embedding\n * levels and a visual order come out. Nothing here knows about fonts, glyphs,\n * canvases or the DOM, and nothing in weasel depends on this package — a text\n * layout that wants bidi is handed an implementation of this shape, and one\n * that is not handed one lays out in logical order.\n *\n * Two calls, because the algorithm splits at exactly one place: `analyze` is\n * per paragraph, `reorder` is per *line*. A caller wraps between them, and one\n * analysis serves every line the wrap produced.\n *\n * Verified against Unicode's own conformance data — all 91,707 cases of\n * `BidiCharacterTest.txt` and all 490,846 of `BidiTest.txt`.\n */\n\nimport type { BidiClass } from './types';\nimport { resolveLevels, type BidiDirection, type BidiResult } from './resolve';\nimport { reorderLine, type ReorderedLine } from './reorder';\nimport { bidiClassOf, mirrorOf, UNICODE_VERSION } from './tables';\n\nexport type { BidiClass, PairedBracket } from './types';\nexport type { BidiDirection, BidiResult } from './resolve';\nexport type { ReorderedLine } from './reorder';\nexport { bidiClassOf, mirrorOf, pairedBracket, UNICODE_VERSION } from './tables';\nexport { resolveLevels } from './resolve';\nexport { reorderLine } from './reorder';\n\n/** One analysed paragraph, and the classes it was analysed from. */\nexport interface BidiAnalysis extends BidiResult {\n /** `Bidi_Class` per code point, before the W and N rules rewrote anything.\n * L1 is specified against these, so `reorder` needs them kept. */\n original: BidiClass[];\n}\n\n/**\n * Analyse one paragraph of text.\n *\n * `direction` defaults to `'auto'`, which is P2/P3's first-strong rule — the\n * right default for text whose language is not known up front.\n */\nexport function analyze(\n codePoints: readonly number[],\n direction: BidiDirection = 'auto',\n): BidiAnalysis {\n const original = Array.from(codePoints, bidiClassOf);\n const resolved = resolveLevels(original, direction, codePoints);\n return { ...resolved, original };\n}\n\n/**\n * Order one line of an analysed paragraph for display, left to right.\n *\n * `start` and `end` index the same code point array `analyze` was given.\n */\nexport function reorder(\n analysis: BidiAnalysis,\n start: number,\n end: number,\n): ReorderedLine {\n return reorderLine(analysis.original, analysis, start, end);\n}\n\n/**\n * L4 — the glyph to paint in place of `cp` when it sits in a right-to-left\n * run, or `null` when it is not mirrored.\n *\n * Applied at paint time against a character's resolved level, not during\n * analysis: the same code point mirrors in one run and not in another.\n */\nexport function mirror(cp: number): number | null {\n return mirrorOf(cp);\n}\n\n/** The whole seam a text layout needs, and all this package is used through. */\nexport interface BidiEngine {\n analyze(codePoints: readonly number[], direction?: BidiDirection): BidiAnalysis;\n reorder(analysis: BidiAnalysis, start: number, end: number): ReorderedLine;\n mirror(cp: number): number | null;\n}\n\n/** The default engine — pass this where a `BidiEngine` is wanted. */\nexport const bidi: BidiEngine = { analyze, reorder, mirror };\n\nexport { UNICODE_VERSION as BIDI_UNICODE_VERSION };\n"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@weasel-js/bidi",
3
+ "version": "1.2.0",
4
+ "description": "The Unicode Bidirectional Algorithm (UAX #9) for weasel: embedding levels, reordering and mirroring. Plain data in, plain data out; no renderer and no scene graph.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "scripts": {
19
+ "test": "vitest run",
20
+ "build": "tsup"
21
+ },
22
+ "author": "orochi235",
23
+ "homepage": "https://orochi235.github.io/weasel/",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/orochi235/weasel.git",
27
+ "directory": "packages/bidi"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/orochi235/weasel/issues"
31
+ },
32
+ "engines": {
33
+ "node": ">=22"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "provenance": true
43
+ }
44
+ }