@quartzds/core 1.0.0-beta.123 → 1.0.0-beta.125
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/CHANGELOG.md +43 -0
- package/components/index.js +1 -1
- package/components/{p-BvRd7jA2.js → p-2tdMcXmA.js} +5 -5
- package/components/{p-BvRd7jA2.js.map → p-2tdMcXmA.js.map} +1 -1
- package/components/{p-CVuTVnQo.js → p-B6ToH-uM.js} +4 -4
- package/components/p-B6ToH-uM.js.map +1 -0
- package/components/{p-C93kOEAe.js → p-BRpaYGSM.js} +5 -5
- package/components/{p-C93kOEAe.js.map → p-BRpaYGSM.js.map} +1 -1
- package/components/{p-CbY4T0d2.js → p-B_CYrw-t.js} +3 -3
- package/components/{p-CbY4T0d2.js.map → p-B_CYrw-t.js.map} +1 -1
- package/components/{p-BoSYRCNp.js → p-BceRDckL.js} +4 -4
- package/components/{p-BoSYRCNp.js.map → p-BceRDckL.js.map} +1 -1
- package/components/{p-BZlKeCFb.js → p-BuCcV5P1.js} +9 -9
- package/components/p-BuCcV5P1.js.map +1 -0
- package/components/{p-B7s906mS.js → p-CG_jPYOl.js} +5 -5
- package/components/{p-B7s906mS.js.map → p-CG_jPYOl.js.map} +1 -1
- package/components/p-CaibVX_2.js +3539 -0
- package/components/p-CaibVX_2.js.map +1 -0
- package/components/{p-CowZ-pDD.js → p-CgQQYnEy.js} +75 -39
- package/components/p-CgQQYnEy.js.map +1 -0
- package/components/{p-yb0Kv4Y6.js → p-DTMrBXCl.js} +24 -9
- package/components/p-DTMrBXCl.js.map +1 -0
- package/components/{p-C9R8N06B.js → p-EjoVBa5a.js} +3 -3
- package/components/{p-C9R8N06B.js.map → p-EjoVBa5a.js.map} +1 -1
- package/components/{p-CKp062X8.js → p-ox2syNht.js} +6 -6
- package/components/{p-CKp062X8.js.map → p-ox2syNht.js.map} +1 -1
- package/components/qds-action-item.js +3 -3
- package/components/qds-avatar-media.js +1 -1
- package/components/qds-breadcrumb-item.js +11 -6
- package/components/qds-breadcrumb-item.js.map +1 -1
- package/components/qds-button.js +9 -9
- package/components/qds-button.js.map +1 -1
- package/components/qds-checkbox.js +1 -1
- package/components/qds-chip.js +5 -5
- package/components/qds-chip.js.map +1 -1
- package/components/qds-dialog.js +5 -5
- package/components/qds-dialog.js.map +1 -1
- package/components/qds-divider.js +1 -1
- package/components/qds-dropdown.js +1 -1
- package/components/qds-form-message.js +23 -17
- package/components/qds-form-message.js.map +1 -1
- package/components/qds-icon-button.js +1 -1
- package/components/qds-icon-tab.js +4 -4
- package/components/qds-icon.js +1 -1
- package/components/qds-inline-link.js +5 -5
- package/components/qds-inline-link.js.map +1 -1
- package/components/qds-input.js +3 -3
- package/components/qds-label.js +2 -2
- package/components/qds-list-item.js +16 -13
- package/components/qds-list-item.js.map +1 -1
- package/components/qds-loader.js +1 -1
- package/components/qds-menu-item.js +38 -12
- package/components/qds-menu-item.js.map +1 -1
- package/components/qds-mini-button.js +1 -1
- package/components/qds-progress-bar.js +1 -1
- package/components/qds-radio.js +1 -1
- package/components/qds-select.js +3 -3
- package/components/qds-standalone-link.js +4 -4
- package/components/qds-switch.js +6 -6
- package/components/qds-switch.js.map +1 -1
- package/components/qds-tab.js +7 -7
- package/components/qds-tabbar.js +59 -38
- package/components/qds-tabbar.js.map +1 -1
- package/components/qds-table-cell.js +2 -2
- package/components/qds-table-head-cell.js +2 -2
- package/components/qds-table-row.js +1 -1
- package/components/qds-table.js +1 -1
- package/components/qds-tag.js +1 -1
- package/components/qds-textarea.js +3 -3
- package/components/qds-title.js +1 -1
- package/components/qds-tooltip.js +1 -1
- package/dist/cjs/helpers-DjUgyTKn.js +3559 -0
- package/dist/cjs/helpers-DjUgyTKn.js.map +1 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/qds-action-item.cjs.entry.js +1 -1
- package/dist/cjs/qds-avatar-media.qds-checkbox.qds-radio.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-avatar-media_3.cjs.entry.js +72 -36
- package/dist/cjs/qds-breadcrumb-item.cjs.entry.js +9 -4
- package/dist/cjs/qds-breadcrumb-item.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-button.cjs.entry.js +7 -7
- package/dist/cjs/qds-button.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-chip.cjs.entry.js +2 -2
- package/dist/cjs/qds-chip.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-dialog.cjs.entry.js +2 -2
- package/dist/cjs/qds-dialog.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-divider.qds-icon-button.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-divider_2.cjs.entry.js +3 -3
- package/dist/cjs/qds-dropdown.cjs.entry.js +20 -6
- package/dist/cjs/qds-dropdown.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-form-message.cjs.entry.js +26 -16
- package/dist/cjs/qds-form-message.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-icon-tab.cjs.entry.js +1 -1
- package/dist/cjs/qds-icon.cjs.entry.js +1 -1
- package/dist/cjs/qds-inline-link.cjs.entry.js +4 -4
- package/dist/cjs/qds-inline-link.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-input.cjs.entry.js +1 -1
- package/dist/cjs/qds-label.cjs.entry.js +1 -1
- package/dist/cjs/qds-list-item.cjs.entry.js +8 -5
- package/dist/cjs/qds-list-item.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-menu-item.cjs.entry.js +34 -8
- package/dist/cjs/qds-menu-item.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-mini-button.cjs.entry.js +2 -2
- package/dist/cjs/qds-progress-bar.cjs.entry.js +1 -1
- package/dist/cjs/qds-select.cjs.entry.js +2 -2
- package/dist/cjs/qds-standalone-link.cjs.entry.js +3 -3
- package/dist/cjs/qds-switch.cjs.entry.js +5 -5
- package/dist/cjs/qds-switch.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-tab.cjs.entry.js +4 -4
- package/dist/cjs/qds-tabbar.cjs.entry.js +57 -33
- package/dist/cjs/qds-tabbar.entry.cjs.js.map +1 -1
- package/dist/cjs/qds-table-cell.cjs.entry.js +2 -2
- package/dist/cjs/qds-table-head-cell.cjs.entry.js +2 -2
- package/dist/cjs/qds-table-row.cjs.entry.js +1 -1
- package/dist/cjs/qds-table.cjs.entry.js +1 -1
- package/dist/cjs/qds-tag.cjs.entry.js +3 -3
- package/dist/cjs/qds-textarea.cjs.entry.js +3 -3
- package/dist/cjs/qds-title.cjs.entry.js +2 -2
- package/dist/cjs/qds-tooltip.cjs.entry.js +1 -1
- package/dist/cjs/qds.cjs.js +1 -1
- package/dist/custom-elements.json +224 -70
- package/dist/docs.json +48 -6
- package/dist/esm/helpers-mPQzhx-O.js +3539 -0
- package/dist/esm/helpers-mPQzhx-O.js.map +1 -0
- package/dist/esm/loader.js +1 -1
- package/dist/esm/qds-action-item.entry.js +1 -1
- package/dist/esm/qds-avatar-media.qds-checkbox.qds-radio.entry.js.map +1 -1
- package/dist/esm/qds-avatar-media_3.entry.js +72 -36
- package/dist/esm/qds-breadcrumb-item.entry.js +9 -4
- package/dist/esm/qds-breadcrumb-item.entry.js.map +1 -1
- package/dist/esm/qds-button.entry.js +7 -7
- package/dist/esm/qds-button.entry.js.map +1 -1
- package/dist/esm/qds-chip.entry.js +2 -2
- package/dist/esm/qds-chip.entry.js.map +1 -1
- package/dist/esm/qds-dialog.entry.js +2 -2
- package/dist/esm/qds-dialog.entry.js.map +1 -1
- package/dist/esm/qds-divider.qds-icon-button.entry.js.map +1 -1
- package/dist/esm/qds-divider_2.entry.js +3 -3
- package/dist/esm/qds-dropdown.entry.js +20 -6
- package/dist/esm/qds-dropdown.entry.js.map +1 -1
- package/dist/esm/qds-form-message.entry.js +26 -16
- package/dist/esm/qds-form-message.entry.js.map +1 -1
- package/dist/esm/qds-icon-tab.entry.js +1 -1
- package/dist/esm/qds-icon.entry.js +1 -1
- package/dist/esm/qds-inline-link.entry.js +4 -4
- package/dist/esm/qds-inline-link.entry.js.map +1 -1
- package/dist/esm/qds-input.entry.js +1 -1
- package/dist/esm/qds-label.entry.js +1 -1
- package/dist/esm/qds-list-item.entry.js +8 -5
- package/dist/esm/qds-list-item.entry.js.map +1 -1
- package/dist/esm/qds-menu-item.entry.js +34 -8
- package/dist/esm/qds-menu-item.entry.js.map +1 -1
- package/dist/esm/qds-mini-button.entry.js +2 -2
- package/dist/esm/qds-progress-bar.entry.js +1 -1
- package/dist/esm/qds-select.entry.js +2 -2
- package/dist/esm/qds-standalone-link.entry.js +3 -3
- package/dist/esm/qds-switch.entry.js +5 -5
- package/dist/esm/qds-switch.entry.js.map +1 -1
- package/dist/esm/qds-tab.entry.js +4 -4
- package/dist/esm/qds-tabbar.entry.js +57 -33
- package/dist/esm/qds-tabbar.entry.js.map +1 -1
- package/dist/esm/qds-table-cell.entry.js +2 -2
- package/dist/esm/qds-table-head-cell.entry.js +2 -2
- package/dist/esm/qds-table-row.entry.js +1 -1
- package/dist/esm/qds-table.entry.js +1 -1
- package/dist/esm/qds-tag.entry.js +3 -3
- package/dist/esm/qds-textarea.entry.js +3 -3
- package/dist/esm/qds-title.entry.js +2 -2
- package/dist/esm/qds-tooltip.entry.js +1 -1
- package/dist/esm/qds.js +1 -1
- package/dist/types/components/checkbox/checkbox.d.ts +9 -9
- package/dist/types/components/dropdown/dropdown.d.ts +1 -0
- package/dist/types/components/form-message/form-message.d.ts +2 -0
- package/dist/types/components/menu-item/menu-item.d.ts +1 -0
- package/dist/types/components/tabbar/tabbar.d.ts +2 -0
- package/dist/types/components.d.ts +3 -2
- package/dist/types/helpers.d.ts +6 -1
- package/dist/vscode.html-custom-data.json +1 -1
- package/hydrate/index.js +3560 -193
- package/hydrate/index.mjs +3560 -193
- package/package.json +2 -1
- package/components/p-BZlKeCFb.js.map +0 -1
- package/components/p-BalM52S_.js +0 -291
- package/components/p-BalM52S_.js.map +0 -1
- package/components/p-CVuTVnQo.js.map +0 -1
- package/components/p-CowZ-pDD.js.map +0 -1
- package/components/p-yb0Kv4Y6.js.map +0 -1
- package/dist/cjs/helpers-Qs3cpKiI.js +0 -308
- package/dist/cjs/helpers-Qs3cpKiI.js.map +0 -1
- package/dist/esm/helpers-Fe2AA6uo.js +0 -291
- package/dist/esm/helpers-Fe2AA6uo.js.map +0 -1
|
@@ -0,0 +1,3539 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* SPDX-FileCopyrightText: © 2026 Schneider Electric
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
// Generated by scripts/generate-bidi-data.ts from scripts/unicode/DerivedBidiClass-17.0.0.txt.
|
|
7
|
+
// Do not edit by hand. Regenerate with `bun run generate:bidi-data`.
|
|
8
|
+
// Formatting and isolate controls are projected onto `BN` because the rich
|
|
9
|
+
// bidi helper consumes a simplified class set and does not model UBA isolates.
|
|
10
|
+
const latin1BidiTypes = [
|
|
11
|
+
'BN',
|
|
12
|
+
'BN',
|
|
13
|
+
'BN',
|
|
14
|
+
'BN',
|
|
15
|
+
'BN',
|
|
16
|
+
'BN',
|
|
17
|
+
'BN',
|
|
18
|
+
'BN',
|
|
19
|
+
'BN',
|
|
20
|
+
'S',
|
|
21
|
+
'B',
|
|
22
|
+
'S',
|
|
23
|
+
'WS',
|
|
24
|
+
'B',
|
|
25
|
+
'BN',
|
|
26
|
+
'BN',
|
|
27
|
+
'BN',
|
|
28
|
+
'BN',
|
|
29
|
+
'BN',
|
|
30
|
+
'BN',
|
|
31
|
+
'BN',
|
|
32
|
+
'BN',
|
|
33
|
+
'BN',
|
|
34
|
+
'BN',
|
|
35
|
+
'BN',
|
|
36
|
+
'BN',
|
|
37
|
+
'BN',
|
|
38
|
+
'BN',
|
|
39
|
+
'B',
|
|
40
|
+
'B',
|
|
41
|
+
'B',
|
|
42
|
+
'S',
|
|
43
|
+
'WS',
|
|
44
|
+
'ON',
|
|
45
|
+
'ON',
|
|
46
|
+
'ET',
|
|
47
|
+
'ET',
|
|
48
|
+
'ET',
|
|
49
|
+
'ON',
|
|
50
|
+
'ON',
|
|
51
|
+
'ON',
|
|
52
|
+
'ON',
|
|
53
|
+
'ON',
|
|
54
|
+
'ES',
|
|
55
|
+
'CS',
|
|
56
|
+
'ES',
|
|
57
|
+
'CS',
|
|
58
|
+
'CS',
|
|
59
|
+
'EN',
|
|
60
|
+
'EN',
|
|
61
|
+
'EN',
|
|
62
|
+
'EN',
|
|
63
|
+
'EN',
|
|
64
|
+
'EN',
|
|
65
|
+
'EN',
|
|
66
|
+
'EN',
|
|
67
|
+
'EN',
|
|
68
|
+
'EN',
|
|
69
|
+
'CS',
|
|
70
|
+
'ON',
|
|
71
|
+
'ON',
|
|
72
|
+
'ON',
|
|
73
|
+
'ON',
|
|
74
|
+
'ON',
|
|
75
|
+
'ON',
|
|
76
|
+
'L',
|
|
77
|
+
'L',
|
|
78
|
+
'L',
|
|
79
|
+
'L',
|
|
80
|
+
'L',
|
|
81
|
+
'L',
|
|
82
|
+
'L',
|
|
83
|
+
'L',
|
|
84
|
+
'L',
|
|
85
|
+
'L',
|
|
86
|
+
'L',
|
|
87
|
+
'L',
|
|
88
|
+
'L',
|
|
89
|
+
'L',
|
|
90
|
+
'L',
|
|
91
|
+
'L',
|
|
92
|
+
'L',
|
|
93
|
+
'L',
|
|
94
|
+
'L',
|
|
95
|
+
'L',
|
|
96
|
+
'L',
|
|
97
|
+
'L',
|
|
98
|
+
'L',
|
|
99
|
+
'L',
|
|
100
|
+
'L',
|
|
101
|
+
'L',
|
|
102
|
+
'ON',
|
|
103
|
+
'ON',
|
|
104
|
+
'ON',
|
|
105
|
+
'ON',
|
|
106
|
+
'ON',
|
|
107
|
+
'ON',
|
|
108
|
+
'L',
|
|
109
|
+
'L',
|
|
110
|
+
'L',
|
|
111
|
+
'L',
|
|
112
|
+
'L',
|
|
113
|
+
'L',
|
|
114
|
+
'L',
|
|
115
|
+
'L',
|
|
116
|
+
'L',
|
|
117
|
+
'L',
|
|
118
|
+
'L',
|
|
119
|
+
'L',
|
|
120
|
+
'L',
|
|
121
|
+
'L',
|
|
122
|
+
'L',
|
|
123
|
+
'L',
|
|
124
|
+
'L',
|
|
125
|
+
'L',
|
|
126
|
+
'L',
|
|
127
|
+
'L',
|
|
128
|
+
'L',
|
|
129
|
+
'L',
|
|
130
|
+
'L',
|
|
131
|
+
'L',
|
|
132
|
+
'L',
|
|
133
|
+
'L',
|
|
134
|
+
'ON',
|
|
135
|
+
'ON',
|
|
136
|
+
'ON',
|
|
137
|
+
'ON',
|
|
138
|
+
'BN',
|
|
139
|
+
'BN',
|
|
140
|
+
'BN',
|
|
141
|
+
'BN',
|
|
142
|
+
'BN',
|
|
143
|
+
'BN',
|
|
144
|
+
'B',
|
|
145
|
+
'BN',
|
|
146
|
+
'BN',
|
|
147
|
+
'BN',
|
|
148
|
+
'BN',
|
|
149
|
+
'BN',
|
|
150
|
+
'BN',
|
|
151
|
+
'BN',
|
|
152
|
+
'BN',
|
|
153
|
+
'BN',
|
|
154
|
+
'BN',
|
|
155
|
+
'BN',
|
|
156
|
+
'BN',
|
|
157
|
+
'BN',
|
|
158
|
+
'BN',
|
|
159
|
+
'BN',
|
|
160
|
+
'BN',
|
|
161
|
+
'BN',
|
|
162
|
+
'BN',
|
|
163
|
+
'BN',
|
|
164
|
+
'BN',
|
|
165
|
+
'BN',
|
|
166
|
+
'BN',
|
|
167
|
+
'BN',
|
|
168
|
+
'BN',
|
|
169
|
+
'BN',
|
|
170
|
+
'BN',
|
|
171
|
+
'CS',
|
|
172
|
+
'ON',
|
|
173
|
+
'ET',
|
|
174
|
+
'ET',
|
|
175
|
+
'ET',
|
|
176
|
+
'ET',
|
|
177
|
+
'ON',
|
|
178
|
+
'ON',
|
|
179
|
+
'ON',
|
|
180
|
+
'ON',
|
|
181
|
+
'L',
|
|
182
|
+
'ON',
|
|
183
|
+
'ON',
|
|
184
|
+
'BN',
|
|
185
|
+
'ON',
|
|
186
|
+
'ON',
|
|
187
|
+
'ET',
|
|
188
|
+
'ET',
|
|
189
|
+
'EN',
|
|
190
|
+
'EN',
|
|
191
|
+
'ON',
|
|
192
|
+
'L',
|
|
193
|
+
'ON',
|
|
194
|
+
'ON',
|
|
195
|
+
'ON',
|
|
196
|
+
'EN',
|
|
197
|
+
'L',
|
|
198
|
+
'ON',
|
|
199
|
+
'ON',
|
|
200
|
+
'ON',
|
|
201
|
+
'ON',
|
|
202
|
+
'ON',
|
|
203
|
+
'L',
|
|
204
|
+
'L',
|
|
205
|
+
'L',
|
|
206
|
+
'L',
|
|
207
|
+
'L',
|
|
208
|
+
'L',
|
|
209
|
+
'L',
|
|
210
|
+
'L',
|
|
211
|
+
'L',
|
|
212
|
+
'L',
|
|
213
|
+
'L',
|
|
214
|
+
'L',
|
|
215
|
+
'L',
|
|
216
|
+
'L',
|
|
217
|
+
'L',
|
|
218
|
+
'L',
|
|
219
|
+
'L',
|
|
220
|
+
'L',
|
|
221
|
+
'L',
|
|
222
|
+
'L',
|
|
223
|
+
'L',
|
|
224
|
+
'L',
|
|
225
|
+
'L',
|
|
226
|
+
'ON',
|
|
227
|
+
'L',
|
|
228
|
+
'L',
|
|
229
|
+
'L',
|
|
230
|
+
'L',
|
|
231
|
+
'L',
|
|
232
|
+
'L',
|
|
233
|
+
'L',
|
|
234
|
+
'L',
|
|
235
|
+
'L',
|
|
236
|
+
'L',
|
|
237
|
+
'L',
|
|
238
|
+
'L',
|
|
239
|
+
'L',
|
|
240
|
+
'L',
|
|
241
|
+
'L',
|
|
242
|
+
'L',
|
|
243
|
+
'L',
|
|
244
|
+
'L',
|
|
245
|
+
'L',
|
|
246
|
+
'L',
|
|
247
|
+
'L',
|
|
248
|
+
'L',
|
|
249
|
+
'L',
|
|
250
|
+
'L',
|
|
251
|
+
'L',
|
|
252
|
+
'L',
|
|
253
|
+
'L',
|
|
254
|
+
'L',
|
|
255
|
+
'L',
|
|
256
|
+
'L',
|
|
257
|
+
'L',
|
|
258
|
+
'ON',
|
|
259
|
+
'L',
|
|
260
|
+
'L',
|
|
261
|
+
'L',
|
|
262
|
+
'L',
|
|
263
|
+
'L',
|
|
264
|
+
'L',
|
|
265
|
+
'L',
|
|
266
|
+
'L',
|
|
267
|
+
];
|
|
268
|
+
const nonLatin1BidiRanges = [
|
|
269
|
+
[0x2B9, 0x2BA, 'ON'],
|
|
270
|
+
[0x2C2, 0x2CF, 'ON'],
|
|
271
|
+
[0x2D2, 0x2DF, 'ON'],
|
|
272
|
+
[0x2E5, 0x2ED, 'ON'],
|
|
273
|
+
[0x2EF, 0x2FF, 'ON'],
|
|
274
|
+
[0x300, 0x36F, 'NSM'],
|
|
275
|
+
[0x374, 0x375, 'ON'],
|
|
276
|
+
[0x37E, 0x37E, 'ON'],
|
|
277
|
+
[0x384, 0x385, 'ON'],
|
|
278
|
+
[0x387, 0x387, 'ON'],
|
|
279
|
+
[0x3F6, 0x3F6, 'ON'],
|
|
280
|
+
[0x483, 0x489, 'NSM'],
|
|
281
|
+
[0x58A, 0x58A, 'ON'],
|
|
282
|
+
[0x58D, 0x58E, 'ON'],
|
|
283
|
+
[0x58F, 0x58F, 'ET'],
|
|
284
|
+
[0x590, 0x590, 'R'],
|
|
285
|
+
[0x591, 0x5BD, 'NSM'],
|
|
286
|
+
[0x5BE, 0x5BE, 'R'],
|
|
287
|
+
[0x5BF, 0x5BF, 'NSM'],
|
|
288
|
+
[0x5C0, 0x5C0, 'R'],
|
|
289
|
+
[0x5C1, 0x5C2, 'NSM'],
|
|
290
|
+
[0x5C3, 0x5C3, 'R'],
|
|
291
|
+
[0x5C4, 0x5C5, 'NSM'],
|
|
292
|
+
[0x5C6, 0x5C6, 'R'],
|
|
293
|
+
[0x5C7, 0x5C7, 'NSM'],
|
|
294
|
+
[0x5C8, 0x5FF, 'R'],
|
|
295
|
+
[0x600, 0x605, 'AN'],
|
|
296
|
+
[0x606, 0x607, 'ON'],
|
|
297
|
+
[0x608, 0x608, 'AL'],
|
|
298
|
+
[0x609, 0x60A, 'ET'],
|
|
299
|
+
[0x60B, 0x60B, 'AL'],
|
|
300
|
+
[0x60C, 0x60C, 'CS'],
|
|
301
|
+
[0x60D, 0x60D, 'AL'],
|
|
302
|
+
[0x60E, 0x60F, 'ON'],
|
|
303
|
+
[0x610, 0x61A, 'NSM'],
|
|
304
|
+
[0x61B, 0x64A, 'AL'],
|
|
305
|
+
[0x64B, 0x65F, 'NSM'],
|
|
306
|
+
[0x660, 0x669, 'AN'],
|
|
307
|
+
[0x66A, 0x66A, 'ET'],
|
|
308
|
+
[0x66B, 0x66C, 'AN'],
|
|
309
|
+
[0x66D, 0x66F, 'AL'],
|
|
310
|
+
[0x670, 0x670, 'NSM'],
|
|
311
|
+
[0x671, 0x6D5, 'AL'],
|
|
312
|
+
[0x6D6, 0x6DC, 'NSM'],
|
|
313
|
+
[0x6DD, 0x6DD, 'AN'],
|
|
314
|
+
[0x6DE, 0x6DE, 'ON'],
|
|
315
|
+
[0x6DF, 0x6E4, 'NSM'],
|
|
316
|
+
[0x6E5, 0x6E6, 'AL'],
|
|
317
|
+
[0x6E7, 0x6E8, 'NSM'],
|
|
318
|
+
[0x6E9, 0x6E9, 'ON'],
|
|
319
|
+
[0x6EA, 0x6ED, 'NSM'],
|
|
320
|
+
[0x6EE, 0x6EF, 'AL'],
|
|
321
|
+
[0x6F0, 0x6F9, 'EN'],
|
|
322
|
+
[0x6FA, 0x710, 'AL'],
|
|
323
|
+
[0x711, 0x711, 'NSM'],
|
|
324
|
+
[0x712, 0x72F, 'AL'],
|
|
325
|
+
[0x730, 0x74A, 'NSM'],
|
|
326
|
+
[0x74B, 0x7A5, 'AL'],
|
|
327
|
+
[0x7A6, 0x7B0, 'NSM'],
|
|
328
|
+
[0x7B1, 0x7BF, 'AL'],
|
|
329
|
+
[0x7C0, 0x7EA, 'R'],
|
|
330
|
+
[0x7EB, 0x7F3, 'NSM'],
|
|
331
|
+
[0x7F4, 0x7F5, 'R'],
|
|
332
|
+
[0x7F6, 0x7F9, 'ON'],
|
|
333
|
+
[0x7FA, 0x7FC, 'R'],
|
|
334
|
+
[0x7FD, 0x7FD, 'NSM'],
|
|
335
|
+
[0x7FE, 0x815, 'R'],
|
|
336
|
+
[0x816, 0x819, 'NSM'],
|
|
337
|
+
[0x81A, 0x81A, 'R'],
|
|
338
|
+
[0x81B, 0x823, 'NSM'],
|
|
339
|
+
[0x824, 0x824, 'R'],
|
|
340
|
+
[0x825, 0x827, 'NSM'],
|
|
341
|
+
[0x828, 0x828, 'R'],
|
|
342
|
+
[0x829, 0x82D, 'NSM'],
|
|
343
|
+
[0x82E, 0x858, 'R'],
|
|
344
|
+
[0x859, 0x85B, 'NSM'],
|
|
345
|
+
[0x85C, 0x85F, 'R'],
|
|
346
|
+
[0x860, 0x88F, 'AL'],
|
|
347
|
+
[0x890, 0x891, 'AN'],
|
|
348
|
+
[0x892, 0x896, 'AL'],
|
|
349
|
+
[0x897, 0x89F, 'NSM'],
|
|
350
|
+
[0x8A0, 0x8C9, 'AL'],
|
|
351
|
+
[0x8CA, 0x8E1, 'NSM'],
|
|
352
|
+
[0x8E2, 0x8E2, 'AN'],
|
|
353
|
+
[0x8E3, 0x902, 'NSM'],
|
|
354
|
+
[0x93A, 0x93A, 'NSM'],
|
|
355
|
+
[0x93C, 0x93C, 'NSM'],
|
|
356
|
+
[0x941, 0x948, 'NSM'],
|
|
357
|
+
[0x94D, 0x94D, 'NSM'],
|
|
358
|
+
[0x951, 0x957, 'NSM'],
|
|
359
|
+
[0x962, 0x963, 'NSM'],
|
|
360
|
+
[0x981, 0x981, 'NSM'],
|
|
361
|
+
[0x9BC, 0x9BC, 'NSM'],
|
|
362
|
+
[0x9C1, 0x9C4, 'NSM'],
|
|
363
|
+
[0x9CD, 0x9CD, 'NSM'],
|
|
364
|
+
[0x9E2, 0x9E3, 'NSM'],
|
|
365
|
+
[0x9F2, 0x9F3, 'ET'],
|
|
366
|
+
[0x9FB, 0x9FB, 'ET'],
|
|
367
|
+
[0x9FE, 0x9FE, 'NSM'],
|
|
368
|
+
[0xA01, 0xA02, 'NSM'],
|
|
369
|
+
[0xA3C, 0xA3C, 'NSM'],
|
|
370
|
+
[0xA41, 0xA42, 'NSM'],
|
|
371
|
+
[0xA47, 0xA48, 'NSM'],
|
|
372
|
+
[0xA4B, 0xA4D, 'NSM'],
|
|
373
|
+
[0xA51, 0xA51, 'NSM'],
|
|
374
|
+
[0xA70, 0xA71, 'NSM'],
|
|
375
|
+
[0xA75, 0xA75, 'NSM'],
|
|
376
|
+
[0xA81, 0xA82, 'NSM'],
|
|
377
|
+
[0xABC, 0xABC, 'NSM'],
|
|
378
|
+
[0xAC1, 0xAC5, 'NSM'],
|
|
379
|
+
[0xAC7, 0xAC8, 'NSM'],
|
|
380
|
+
[0xACD, 0xACD, 'NSM'],
|
|
381
|
+
[0xAE2, 0xAE3, 'NSM'],
|
|
382
|
+
[0xAF1, 0xAF1, 'ET'],
|
|
383
|
+
[0xAFA, 0xAFF, 'NSM'],
|
|
384
|
+
[0xB01, 0xB01, 'NSM'],
|
|
385
|
+
[0xB3C, 0xB3C, 'NSM'],
|
|
386
|
+
[0xB3F, 0xB3F, 'NSM'],
|
|
387
|
+
[0xB41, 0xB44, 'NSM'],
|
|
388
|
+
[0xB4D, 0xB4D, 'NSM'],
|
|
389
|
+
[0xB55, 0xB56, 'NSM'],
|
|
390
|
+
[0xB62, 0xB63, 'NSM'],
|
|
391
|
+
[0xB82, 0xB82, 'NSM'],
|
|
392
|
+
[0xBC0, 0xBC0, 'NSM'],
|
|
393
|
+
[0xBCD, 0xBCD, 'NSM'],
|
|
394
|
+
[0xBF3, 0xBF8, 'ON'],
|
|
395
|
+
[0xBF9, 0xBF9, 'ET'],
|
|
396
|
+
[0xBFA, 0xBFA, 'ON'],
|
|
397
|
+
[0xC00, 0xC00, 'NSM'],
|
|
398
|
+
[0xC04, 0xC04, 'NSM'],
|
|
399
|
+
[0xC3C, 0xC3C, 'NSM'],
|
|
400
|
+
[0xC3E, 0xC40, 'NSM'],
|
|
401
|
+
[0xC46, 0xC48, 'NSM'],
|
|
402
|
+
[0xC4A, 0xC4D, 'NSM'],
|
|
403
|
+
[0xC55, 0xC56, 'NSM'],
|
|
404
|
+
[0xC62, 0xC63, 'NSM'],
|
|
405
|
+
[0xC78, 0xC7E, 'ON'],
|
|
406
|
+
[0xC81, 0xC81, 'NSM'],
|
|
407
|
+
[0xCBC, 0xCBC, 'NSM'],
|
|
408
|
+
[0xCCC, 0xCCD, 'NSM'],
|
|
409
|
+
[0xCE2, 0xCE3, 'NSM'],
|
|
410
|
+
[0xD00, 0xD01, 'NSM'],
|
|
411
|
+
[0xD3B, 0xD3C, 'NSM'],
|
|
412
|
+
[0xD41, 0xD44, 'NSM'],
|
|
413
|
+
[0xD4D, 0xD4D, 'NSM'],
|
|
414
|
+
[0xD62, 0xD63, 'NSM'],
|
|
415
|
+
[0xD81, 0xD81, 'NSM'],
|
|
416
|
+
[0xDCA, 0xDCA, 'NSM'],
|
|
417
|
+
[0xDD2, 0xDD4, 'NSM'],
|
|
418
|
+
[0xDD6, 0xDD6, 'NSM'],
|
|
419
|
+
[0xE31, 0xE31, 'NSM'],
|
|
420
|
+
[0xE34, 0xE3A, 'NSM'],
|
|
421
|
+
[0xE3F, 0xE3F, 'ET'],
|
|
422
|
+
[0xE47, 0xE4E, 'NSM'],
|
|
423
|
+
[0xEB1, 0xEB1, 'NSM'],
|
|
424
|
+
[0xEB4, 0xEBC, 'NSM'],
|
|
425
|
+
[0xEC8, 0xECE, 'NSM'],
|
|
426
|
+
[0xF18, 0xF19, 'NSM'],
|
|
427
|
+
[0xF35, 0xF35, 'NSM'],
|
|
428
|
+
[0xF37, 0xF37, 'NSM'],
|
|
429
|
+
[0xF39, 0xF39, 'NSM'],
|
|
430
|
+
[0xF3A, 0xF3D, 'ON'],
|
|
431
|
+
[0xF71, 0xF7E, 'NSM'],
|
|
432
|
+
[0xF80, 0xF84, 'NSM'],
|
|
433
|
+
[0xF86, 0xF87, 'NSM'],
|
|
434
|
+
[0xF8D, 0xF97, 'NSM'],
|
|
435
|
+
[0xF99, 0xFBC, 'NSM'],
|
|
436
|
+
[0xFC6, 0xFC6, 'NSM'],
|
|
437
|
+
[0x102D, 0x1030, 'NSM'],
|
|
438
|
+
[0x1032, 0x1037, 'NSM'],
|
|
439
|
+
[0x1039, 0x103A, 'NSM'],
|
|
440
|
+
[0x103D, 0x103E, 'NSM'],
|
|
441
|
+
[0x1058, 0x1059, 'NSM'],
|
|
442
|
+
[0x105E, 0x1060, 'NSM'],
|
|
443
|
+
[0x1071, 0x1074, 'NSM'],
|
|
444
|
+
[0x1082, 0x1082, 'NSM'],
|
|
445
|
+
[0x1085, 0x1086, 'NSM'],
|
|
446
|
+
[0x108D, 0x108D, 'NSM'],
|
|
447
|
+
[0x109D, 0x109D, 'NSM'],
|
|
448
|
+
[0x135D, 0x135F, 'NSM'],
|
|
449
|
+
[0x1390, 0x1399, 'ON'],
|
|
450
|
+
[0x1400, 0x1400, 'ON'],
|
|
451
|
+
[0x1680, 0x1680, 'WS'],
|
|
452
|
+
[0x169B, 0x169C, 'ON'],
|
|
453
|
+
[0x1712, 0x1714, 'NSM'],
|
|
454
|
+
[0x1732, 0x1733, 'NSM'],
|
|
455
|
+
[0x1752, 0x1753, 'NSM'],
|
|
456
|
+
[0x1772, 0x1773, 'NSM'],
|
|
457
|
+
[0x17B4, 0x17B5, 'NSM'],
|
|
458
|
+
[0x17B7, 0x17BD, 'NSM'],
|
|
459
|
+
[0x17C6, 0x17C6, 'NSM'],
|
|
460
|
+
[0x17C9, 0x17D3, 'NSM'],
|
|
461
|
+
[0x17DB, 0x17DB, 'ET'],
|
|
462
|
+
[0x17DD, 0x17DD, 'NSM'],
|
|
463
|
+
[0x17F0, 0x17F9, 'ON'],
|
|
464
|
+
[0x1800, 0x180A, 'ON'],
|
|
465
|
+
[0x180B, 0x180D, 'NSM'],
|
|
466
|
+
[0x180E, 0x180E, 'BN'],
|
|
467
|
+
[0x180F, 0x180F, 'NSM'],
|
|
468
|
+
[0x1885, 0x1886, 'NSM'],
|
|
469
|
+
[0x18A9, 0x18A9, 'NSM'],
|
|
470
|
+
[0x1920, 0x1922, 'NSM'],
|
|
471
|
+
[0x1927, 0x1928, 'NSM'],
|
|
472
|
+
[0x1932, 0x1932, 'NSM'],
|
|
473
|
+
[0x1939, 0x193B, 'NSM'],
|
|
474
|
+
[0x1940, 0x1940, 'ON'],
|
|
475
|
+
[0x1944, 0x1945, 'ON'],
|
|
476
|
+
[0x19DE, 0x19FF, 'ON'],
|
|
477
|
+
[0x1A17, 0x1A18, 'NSM'],
|
|
478
|
+
[0x1A1B, 0x1A1B, 'NSM'],
|
|
479
|
+
[0x1A56, 0x1A56, 'NSM'],
|
|
480
|
+
[0x1A58, 0x1A5E, 'NSM'],
|
|
481
|
+
[0x1A60, 0x1A60, 'NSM'],
|
|
482
|
+
[0x1A62, 0x1A62, 'NSM'],
|
|
483
|
+
[0x1A65, 0x1A6C, 'NSM'],
|
|
484
|
+
[0x1A73, 0x1A7C, 'NSM'],
|
|
485
|
+
[0x1A7F, 0x1A7F, 'NSM'],
|
|
486
|
+
[0x1AB0, 0x1ADD, 'NSM'],
|
|
487
|
+
[0x1AE0, 0x1AEB, 'NSM'],
|
|
488
|
+
[0x1B00, 0x1B03, 'NSM'],
|
|
489
|
+
[0x1B34, 0x1B34, 'NSM'],
|
|
490
|
+
[0x1B36, 0x1B3A, 'NSM'],
|
|
491
|
+
[0x1B3C, 0x1B3C, 'NSM'],
|
|
492
|
+
[0x1B42, 0x1B42, 'NSM'],
|
|
493
|
+
[0x1B6B, 0x1B73, 'NSM'],
|
|
494
|
+
[0x1B80, 0x1B81, 'NSM'],
|
|
495
|
+
[0x1BA2, 0x1BA5, 'NSM'],
|
|
496
|
+
[0x1BA8, 0x1BA9, 'NSM'],
|
|
497
|
+
[0x1BAB, 0x1BAD, 'NSM'],
|
|
498
|
+
[0x1BE6, 0x1BE6, 'NSM'],
|
|
499
|
+
[0x1BE8, 0x1BE9, 'NSM'],
|
|
500
|
+
[0x1BED, 0x1BED, 'NSM'],
|
|
501
|
+
[0x1BEF, 0x1BF1, 'NSM'],
|
|
502
|
+
[0x1C2C, 0x1C33, 'NSM'],
|
|
503
|
+
[0x1C36, 0x1C37, 'NSM'],
|
|
504
|
+
[0x1CD0, 0x1CD2, 'NSM'],
|
|
505
|
+
[0x1CD4, 0x1CE0, 'NSM'],
|
|
506
|
+
[0x1CE2, 0x1CE8, 'NSM'],
|
|
507
|
+
[0x1CED, 0x1CED, 'NSM'],
|
|
508
|
+
[0x1CF4, 0x1CF4, 'NSM'],
|
|
509
|
+
[0x1CF8, 0x1CF9, 'NSM'],
|
|
510
|
+
[0x1DC0, 0x1DFF, 'NSM'],
|
|
511
|
+
[0x1FBD, 0x1FBD, 'ON'],
|
|
512
|
+
[0x1FBF, 0x1FC1, 'ON'],
|
|
513
|
+
[0x1FCD, 0x1FCF, 'ON'],
|
|
514
|
+
[0x1FDD, 0x1FDF, 'ON'],
|
|
515
|
+
[0x1FED, 0x1FEF, 'ON'],
|
|
516
|
+
[0x1FFD, 0x1FFE, 'ON'],
|
|
517
|
+
[0x2000, 0x200A, 'WS'],
|
|
518
|
+
[0x200B, 0x200D, 'BN'],
|
|
519
|
+
[0x200F, 0x200F, 'R'],
|
|
520
|
+
[0x2010, 0x2027, 'ON'],
|
|
521
|
+
[0x2028, 0x2028, 'WS'],
|
|
522
|
+
[0x2029, 0x2029, 'B'],
|
|
523
|
+
[0x202A, 0x202E, 'BN'],
|
|
524
|
+
[0x202F, 0x202F, 'CS'],
|
|
525
|
+
[0x2030, 0x2034, 'ET'],
|
|
526
|
+
[0x2035, 0x2043, 'ON'],
|
|
527
|
+
[0x2044, 0x2044, 'CS'],
|
|
528
|
+
[0x2045, 0x205E, 'ON'],
|
|
529
|
+
[0x205F, 0x205F, 'WS'],
|
|
530
|
+
[0x2060, 0x206F, 'BN'],
|
|
531
|
+
[0x2070, 0x2070, 'EN'],
|
|
532
|
+
[0x2074, 0x2079, 'EN'],
|
|
533
|
+
[0x207A, 0x207B, 'ES'],
|
|
534
|
+
[0x207C, 0x207E, 'ON'],
|
|
535
|
+
[0x2080, 0x2089, 'EN'],
|
|
536
|
+
[0x208A, 0x208B, 'ES'],
|
|
537
|
+
[0x208C, 0x208E, 'ON'],
|
|
538
|
+
[0x20A0, 0x20CF, 'ET'],
|
|
539
|
+
[0x20D0, 0x20F0, 'NSM'],
|
|
540
|
+
[0x2100, 0x2101, 'ON'],
|
|
541
|
+
[0x2103, 0x2106, 'ON'],
|
|
542
|
+
[0x2108, 0x2109, 'ON'],
|
|
543
|
+
[0x2114, 0x2114, 'ON'],
|
|
544
|
+
[0x2116, 0x2118, 'ON'],
|
|
545
|
+
[0x211E, 0x2123, 'ON'],
|
|
546
|
+
[0x2125, 0x2125, 'ON'],
|
|
547
|
+
[0x2127, 0x2127, 'ON'],
|
|
548
|
+
[0x2129, 0x2129, 'ON'],
|
|
549
|
+
[0x212E, 0x212E, 'ET'],
|
|
550
|
+
[0x213A, 0x213B, 'ON'],
|
|
551
|
+
[0x2140, 0x2144, 'ON'],
|
|
552
|
+
[0x214A, 0x214D, 'ON'],
|
|
553
|
+
[0x2150, 0x215F, 'ON'],
|
|
554
|
+
[0x2189, 0x218B, 'ON'],
|
|
555
|
+
[0x2190, 0x2211, 'ON'],
|
|
556
|
+
[0x2212, 0x2212, 'ES'],
|
|
557
|
+
[0x2213, 0x2213, 'ET'],
|
|
558
|
+
[0x2214, 0x2335, 'ON'],
|
|
559
|
+
[0x237B, 0x2394, 'ON'],
|
|
560
|
+
[0x2396, 0x2429, 'ON'],
|
|
561
|
+
[0x2440, 0x244A, 'ON'],
|
|
562
|
+
[0x2460, 0x2487, 'ON'],
|
|
563
|
+
[0x2488, 0x249B, 'EN'],
|
|
564
|
+
[0x24EA, 0x26AB, 'ON'],
|
|
565
|
+
[0x26AD, 0x27FF, 'ON'],
|
|
566
|
+
[0x2900, 0x2B73, 'ON'],
|
|
567
|
+
[0x2B76, 0x2BFF, 'ON'],
|
|
568
|
+
[0x2CE5, 0x2CEA, 'ON'],
|
|
569
|
+
[0x2CEF, 0x2CF1, 'NSM'],
|
|
570
|
+
[0x2CF9, 0x2CFF, 'ON'],
|
|
571
|
+
[0x2D7F, 0x2D7F, 'NSM'],
|
|
572
|
+
[0x2DE0, 0x2DFF, 'NSM'],
|
|
573
|
+
[0x2E00, 0x2E5D, 'ON'],
|
|
574
|
+
[0x2E80, 0x2E99, 'ON'],
|
|
575
|
+
[0x2E9B, 0x2EF3, 'ON'],
|
|
576
|
+
[0x2F00, 0x2FD5, 'ON'],
|
|
577
|
+
[0x2FF0, 0x2FFF, 'ON'],
|
|
578
|
+
[0x3000, 0x3000, 'WS'],
|
|
579
|
+
[0x3001, 0x3004, 'ON'],
|
|
580
|
+
[0x3008, 0x3020, 'ON'],
|
|
581
|
+
[0x302A, 0x302D, 'NSM'],
|
|
582
|
+
[0x3030, 0x3030, 'ON'],
|
|
583
|
+
[0x3036, 0x3037, 'ON'],
|
|
584
|
+
[0x303D, 0x303F, 'ON'],
|
|
585
|
+
[0x3099, 0x309A, 'NSM'],
|
|
586
|
+
[0x309B, 0x309C, 'ON'],
|
|
587
|
+
[0x30A0, 0x30A0, 'ON'],
|
|
588
|
+
[0x30FB, 0x30FB, 'ON'],
|
|
589
|
+
[0x31C0, 0x31E5, 'ON'],
|
|
590
|
+
[0x31EF, 0x31EF, 'ON'],
|
|
591
|
+
[0x321D, 0x321E, 'ON'],
|
|
592
|
+
[0x3250, 0x325F, 'ON'],
|
|
593
|
+
[0x327C, 0x327E, 'ON'],
|
|
594
|
+
[0x32B1, 0x32BF, 'ON'],
|
|
595
|
+
[0x32CC, 0x32CF, 'ON'],
|
|
596
|
+
[0x3377, 0x337A, 'ON'],
|
|
597
|
+
[0x33DE, 0x33DF, 'ON'],
|
|
598
|
+
[0x33FF, 0x33FF, 'ON'],
|
|
599
|
+
[0x4DC0, 0x4DFF, 'ON'],
|
|
600
|
+
[0xA490, 0xA4C6, 'ON'],
|
|
601
|
+
[0xA60D, 0xA60F, 'ON'],
|
|
602
|
+
[0xA66F, 0xA672, 'NSM'],
|
|
603
|
+
[0xA673, 0xA673, 'ON'],
|
|
604
|
+
[0xA674, 0xA67D, 'NSM'],
|
|
605
|
+
[0xA67E, 0xA67F, 'ON'],
|
|
606
|
+
[0xA69E, 0xA69F, 'NSM'],
|
|
607
|
+
[0xA6F0, 0xA6F1, 'NSM'],
|
|
608
|
+
[0xA700, 0xA721, 'ON'],
|
|
609
|
+
[0xA788, 0xA788, 'ON'],
|
|
610
|
+
[0xA802, 0xA802, 'NSM'],
|
|
611
|
+
[0xA806, 0xA806, 'NSM'],
|
|
612
|
+
[0xA80B, 0xA80B, 'NSM'],
|
|
613
|
+
[0xA825, 0xA826, 'NSM'],
|
|
614
|
+
[0xA828, 0xA82B, 'ON'],
|
|
615
|
+
[0xA82C, 0xA82C, 'NSM'],
|
|
616
|
+
[0xA838, 0xA839, 'ET'],
|
|
617
|
+
[0xA874, 0xA877, 'ON'],
|
|
618
|
+
[0xA8C4, 0xA8C5, 'NSM'],
|
|
619
|
+
[0xA8E0, 0xA8F1, 'NSM'],
|
|
620
|
+
[0xA8FF, 0xA8FF, 'NSM'],
|
|
621
|
+
[0xA926, 0xA92D, 'NSM'],
|
|
622
|
+
[0xA947, 0xA951, 'NSM'],
|
|
623
|
+
[0xA980, 0xA982, 'NSM'],
|
|
624
|
+
[0xA9B3, 0xA9B3, 'NSM'],
|
|
625
|
+
[0xA9B6, 0xA9B9, 'NSM'],
|
|
626
|
+
[0xA9BC, 0xA9BD, 'NSM'],
|
|
627
|
+
[0xA9E5, 0xA9E5, 'NSM'],
|
|
628
|
+
[0xAA29, 0xAA2E, 'NSM'],
|
|
629
|
+
[0xAA31, 0xAA32, 'NSM'],
|
|
630
|
+
[0xAA35, 0xAA36, 'NSM'],
|
|
631
|
+
[0xAA43, 0xAA43, 'NSM'],
|
|
632
|
+
[0xAA4C, 0xAA4C, 'NSM'],
|
|
633
|
+
[0xAA7C, 0xAA7C, 'NSM'],
|
|
634
|
+
[0xAAB0, 0xAAB0, 'NSM'],
|
|
635
|
+
[0xAAB2, 0xAAB4, 'NSM'],
|
|
636
|
+
[0xAAB7, 0xAAB8, 'NSM'],
|
|
637
|
+
[0xAABE, 0xAABF, 'NSM'],
|
|
638
|
+
[0xAAC1, 0xAAC1, 'NSM'],
|
|
639
|
+
[0xAAEC, 0xAAED, 'NSM'],
|
|
640
|
+
[0xAAF6, 0xAAF6, 'NSM'],
|
|
641
|
+
[0xAB6A, 0xAB6B, 'ON'],
|
|
642
|
+
[0xABE5, 0xABE5, 'NSM'],
|
|
643
|
+
[0xABE8, 0xABE8, 'NSM'],
|
|
644
|
+
[0xABED, 0xABED, 'NSM'],
|
|
645
|
+
[0xFB1D, 0xFB1D, 'R'],
|
|
646
|
+
[0xFB1E, 0xFB1E, 'NSM'],
|
|
647
|
+
[0xFB1F, 0xFB28, 'R'],
|
|
648
|
+
[0xFB29, 0xFB29, 'ES'],
|
|
649
|
+
[0xFB2A, 0xFB4F, 'R'],
|
|
650
|
+
[0xFB50, 0xFBC2, 'AL'],
|
|
651
|
+
[0xFBC3, 0xFBD2, 'ON'],
|
|
652
|
+
[0xFBD3, 0xFD3D, 'AL'],
|
|
653
|
+
[0xFD3E, 0xFD4F, 'ON'],
|
|
654
|
+
[0xFD50, 0xFD8F, 'AL'],
|
|
655
|
+
[0xFD90, 0xFD91, 'ON'],
|
|
656
|
+
[0xFD92, 0xFDC7, 'AL'],
|
|
657
|
+
[0xFDC8, 0xFDCF, 'ON'],
|
|
658
|
+
[0xFDD0, 0xFDEF, 'BN'],
|
|
659
|
+
[0xFDF0, 0xFDFC, 'AL'],
|
|
660
|
+
[0xFDFD, 0xFDFF, 'ON'],
|
|
661
|
+
[0xFE00, 0xFE0F, 'NSM'],
|
|
662
|
+
[0xFE10, 0xFE19, 'ON'],
|
|
663
|
+
[0xFE20, 0xFE2F, 'NSM'],
|
|
664
|
+
[0xFE30, 0xFE4F, 'ON'],
|
|
665
|
+
[0xFE50, 0xFE50, 'CS'],
|
|
666
|
+
[0xFE51, 0xFE51, 'ON'],
|
|
667
|
+
[0xFE52, 0xFE52, 'CS'],
|
|
668
|
+
[0xFE54, 0xFE54, 'ON'],
|
|
669
|
+
[0xFE55, 0xFE55, 'CS'],
|
|
670
|
+
[0xFE56, 0xFE5E, 'ON'],
|
|
671
|
+
[0xFE5F, 0xFE5F, 'ET'],
|
|
672
|
+
[0xFE60, 0xFE61, 'ON'],
|
|
673
|
+
[0xFE62, 0xFE63, 'ES'],
|
|
674
|
+
[0xFE64, 0xFE66, 'ON'],
|
|
675
|
+
[0xFE68, 0xFE68, 'ON'],
|
|
676
|
+
[0xFE69, 0xFE6A, 'ET'],
|
|
677
|
+
[0xFE6B, 0xFE6B, 'ON'],
|
|
678
|
+
[0xFE70, 0xFEFE, 'AL'],
|
|
679
|
+
[0xFEFF, 0xFEFF, 'BN'],
|
|
680
|
+
[0xFF01, 0xFF02, 'ON'],
|
|
681
|
+
[0xFF03, 0xFF05, 'ET'],
|
|
682
|
+
[0xFF06, 0xFF0A, 'ON'],
|
|
683
|
+
[0xFF0B, 0xFF0B, 'ES'],
|
|
684
|
+
[0xFF0C, 0xFF0C, 'CS'],
|
|
685
|
+
[0xFF0D, 0xFF0D, 'ES'],
|
|
686
|
+
[0xFF0E, 0xFF0F, 'CS'],
|
|
687
|
+
[0xFF10, 0xFF19, 'EN'],
|
|
688
|
+
[0xFF1A, 0xFF1A, 'CS'],
|
|
689
|
+
[0xFF1B, 0xFF20, 'ON'],
|
|
690
|
+
[0xFF3B, 0xFF40, 'ON'],
|
|
691
|
+
[0xFF5B, 0xFF65, 'ON'],
|
|
692
|
+
[0xFFE0, 0xFFE1, 'ET'],
|
|
693
|
+
[0xFFE2, 0xFFE4, 'ON'],
|
|
694
|
+
[0xFFE5, 0xFFE6, 'ET'],
|
|
695
|
+
[0xFFE8, 0xFFEE, 'ON'],
|
|
696
|
+
[0xFFF0, 0xFFF8, 'BN'],
|
|
697
|
+
[0xFFF9, 0xFFFD, 'ON'],
|
|
698
|
+
[0xFFFE, 0xFFFF, 'BN'],
|
|
699
|
+
[0x10101, 0x10101, 'ON'],
|
|
700
|
+
[0x10140, 0x1018C, 'ON'],
|
|
701
|
+
[0x10190, 0x1019C, 'ON'],
|
|
702
|
+
[0x101A0, 0x101A0, 'ON'],
|
|
703
|
+
[0x101FD, 0x101FD, 'NSM'],
|
|
704
|
+
[0x102E0, 0x102E0, 'NSM'],
|
|
705
|
+
[0x102E1, 0x102FB, 'EN'],
|
|
706
|
+
[0x10376, 0x1037A, 'NSM'],
|
|
707
|
+
[0x10800, 0x1091E, 'R'],
|
|
708
|
+
[0x1091F, 0x1091F, 'ON'],
|
|
709
|
+
[0x10920, 0x10A00, 'R'],
|
|
710
|
+
[0x10A01, 0x10A03, 'NSM'],
|
|
711
|
+
[0x10A04, 0x10A04, 'R'],
|
|
712
|
+
[0x10A05, 0x10A06, 'NSM'],
|
|
713
|
+
[0x10A07, 0x10A0B, 'R'],
|
|
714
|
+
[0x10A0C, 0x10A0F, 'NSM'],
|
|
715
|
+
[0x10A10, 0x10A37, 'R'],
|
|
716
|
+
[0x10A38, 0x10A3A, 'NSM'],
|
|
717
|
+
[0x10A3B, 0x10A3E, 'R'],
|
|
718
|
+
[0x10A3F, 0x10A3F, 'NSM'],
|
|
719
|
+
[0x10A40, 0x10AE4, 'R'],
|
|
720
|
+
[0x10AE5, 0x10AE6, 'NSM'],
|
|
721
|
+
[0x10AE7, 0x10B38, 'R'],
|
|
722
|
+
[0x10B39, 0x10B3F, 'ON'],
|
|
723
|
+
[0x10B40, 0x10CFF, 'R'],
|
|
724
|
+
[0x10D00, 0x10D23, 'AL'],
|
|
725
|
+
[0x10D24, 0x10D27, 'NSM'],
|
|
726
|
+
[0x10D28, 0x10D2F, 'AL'],
|
|
727
|
+
[0x10D30, 0x10D39, 'AN'],
|
|
728
|
+
[0x10D3A, 0x10D3F, 'AL'],
|
|
729
|
+
[0x10D40, 0x10D49, 'AN'],
|
|
730
|
+
[0x10D4A, 0x10D68, 'R'],
|
|
731
|
+
[0x10D69, 0x10D6D, 'NSM'],
|
|
732
|
+
[0x10D6E, 0x10D6E, 'ON'],
|
|
733
|
+
[0x10D6F, 0x10E5F, 'R'],
|
|
734
|
+
[0x10E60, 0x10E7E, 'AN'],
|
|
735
|
+
[0x10E7F, 0x10EAA, 'R'],
|
|
736
|
+
[0x10EAB, 0x10EAC, 'NSM'],
|
|
737
|
+
[0x10EAD, 0x10EBF, 'R'],
|
|
738
|
+
[0x10EC0, 0x10ECF, 'AL'],
|
|
739
|
+
[0x10ED0, 0x10ED8, 'ON'],
|
|
740
|
+
[0x10ED9, 0x10EF9, 'AL'],
|
|
741
|
+
[0x10EFA, 0x10EFF, 'NSM'],
|
|
742
|
+
[0x10F00, 0x10F2F, 'R'],
|
|
743
|
+
[0x10F30, 0x10F45, 'AL'],
|
|
744
|
+
[0x10F46, 0x10F50, 'NSM'],
|
|
745
|
+
[0x10F51, 0x10F6F, 'AL'],
|
|
746
|
+
[0x10F70, 0x10F81, 'R'],
|
|
747
|
+
[0x10F82, 0x10F85, 'NSM'],
|
|
748
|
+
[0x10F86, 0x10FFF, 'R'],
|
|
749
|
+
[0x11001, 0x11001, 'NSM'],
|
|
750
|
+
[0x11038, 0x11046, 'NSM'],
|
|
751
|
+
[0x11052, 0x11065, 'ON'],
|
|
752
|
+
[0x11070, 0x11070, 'NSM'],
|
|
753
|
+
[0x11073, 0x11074, 'NSM'],
|
|
754
|
+
[0x1107F, 0x11081, 'NSM'],
|
|
755
|
+
[0x110B3, 0x110B6, 'NSM'],
|
|
756
|
+
[0x110B9, 0x110BA, 'NSM'],
|
|
757
|
+
[0x110C2, 0x110C2, 'NSM'],
|
|
758
|
+
[0x11100, 0x11102, 'NSM'],
|
|
759
|
+
[0x11127, 0x1112B, 'NSM'],
|
|
760
|
+
[0x1112D, 0x11134, 'NSM'],
|
|
761
|
+
[0x11173, 0x11173, 'NSM'],
|
|
762
|
+
[0x11180, 0x11181, 'NSM'],
|
|
763
|
+
[0x111B6, 0x111BE, 'NSM'],
|
|
764
|
+
[0x111C9, 0x111CC, 'NSM'],
|
|
765
|
+
[0x111CF, 0x111CF, 'NSM'],
|
|
766
|
+
[0x1122F, 0x11231, 'NSM'],
|
|
767
|
+
[0x11234, 0x11234, 'NSM'],
|
|
768
|
+
[0x11236, 0x11237, 'NSM'],
|
|
769
|
+
[0x1123E, 0x1123E, 'NSM'],
|
|
770
|
+
[0x11241, 0x11241, 'NSM'],
|
|
771
|
+
[0x112DF, 0x112DF, 'NSM'],
|
|
772
|
+
[0x112E3, 0x112EA, 'NSM'],
|
|
773
|
+
[0x11300, 0x11301, 'NSM'],
|
|
774
|
+
[0x1133B, 0x1133C, 'NSM'],
|
|
775
|
+
[0x11340, 0x11340, 'NSM'],
|
|
776
|
+
[0x11366, 0x1136C, 'NSM'],
|
|
777
|
+
[0x11370, 0x11374, 'NSM'],
|
|
778
|
+
[0x113BB, 0x113C0, 'NSM'],
|
|
779
|
+
[0x113CE, 0x113CE, 'NSM'],
|
|
780
|
+
[0x113D0, 0x113D0, 'NSM'],
|
|
781
|
+
[0x113D2, 0x113D2, 'NSM'],
|
|
782
|
+
[0x113E1, 0x113E2, 'NSM'],
|
|
783
|
+
[0x11438, 0x1143F, 'NSM'],
|
|
784
|
+
[0x11442, 0x11444, 'NSM'],
|
|
785
|
+
[0x11446, 0x11446, 'NSM'],
|
|
786
|
+
[0x1145E, 0x1145E, 'NSM'],
|
|
787
|
+
[0x114B3, 0x114B8, 'NSM'],
|
|
788
|
+
[0x114BA, 0x114BA, 'NSM'],
|
|
789
|
+
[0x114BF, 0x114C0, 'NSM'],
|
|
790
|
+
[0x114C2, 0x114C3, 'NSM'],
|
|
791
|
+
[0x115B2, 0x115B5, 'NSM'],
|
|
792
|
+
[0x115BC, 0x115BD, 'NSM'],
|
|
793
|
+
[0x115BF, 0x115C0, 'NSM'],
|
|
794
|
+
[0x115DC, 0x115DD, 'NSM'],
|
|
795
|
+
[0x11633, 0x1163A, 'NSM'],
|
|
796
|
+
[0x1163D, 0x1163D, 'NSM'],
|
|
797
|
+
[0x1163F, 0x11640, 'NSM'],
|
|
798
|
+
[0x11660, 0x1166C, 'ON'],
|
|
799
|
+
[0x116AB, 0x116AB, 'NSM'],
|
|
800
|
+
[0x116AD, 0x116AD, 'NSM'],
|
|
801
|
+
[0x116B0, 0x116B5, 'NSM'],
|
|
802
|
+
[0x116B7, 0x116B7, 'NSM'],
|
|
803
|
+
[0x1171D, 0x1171D, 'NSM'],
|
|
804
|
+
[0x1171F, 0x1171F, 'NSM'],
|
|
805
|
+
[0x11722, 0x11725, 'NSM'],
|
|
806
|
+
[0x11727, 0x1172B, 'NSM'],
|
|
807
|
+
[0x1182F, 0x11837, 'NSM'],
|
|
808
|
+
[0x11839, 0x1183A, 'NSM'],
|
|
809
|
+
[0x1193B, 0x1193C, 'NSM'],
|
|
810
|
+
[0x1193E, 0x1193E, 'NSM'],
|
|
811
|
+
[0x11943, 0x11943, 'NSM'],
|
|
812
|
+
[0x119D4, 0x119D7, 'NSM'],
|
|
813
|
+
[0x119DA, 0x119DB, 'NSM'],
|
|
814
|
+
[0x119E0, 0x119E0, 'NSM'],
|
|
815
|
+
[0x11A01, 0x11A06, 'NSM'],
|
|
816
|
+
[0x11A09, 0x11A0A, 'NSM'],
|
|
817
|
+
[0x11A33, 0x11A38, 'NSM'],
|
|
818
|
+
[0x11A3B, 0x11A3E, 'NSM'],
|
|
819
|
+
[0x11A47, 0x11A47, 'NSM'],
|
|
820
|
+
[0x11A51, 0x11A56, 'NSM'],
|
|
821
|
+
[0x11A59, 0x11A5B, 'NSM'],
|
|
822
|
+
[0x11A8A, 0x11A96, 'NSM'],
|
|
823
|
+
[0x11A98, 0x11A99, 'NSM'],
|
|
824
|
+
[0x11B60, 0x11B60, 'NSM'],
|
|
825
|
+
[0x11B62, 0x11B64, 'NSM'],
|
|
826
|
+
[0x11B66, 0x11B66, 'NSM'],
|
|
827
|
+
[0x11C30, 0x11C36, 'NSM'],
|
|
828
|
+
[0x11C38, 0x11C3D, 'NSM'],
|
|
829
|
+
[0x11C92, 0x11CA7, 'NSM'],
|
|
830
|
+
[0x11CAA, 0x11CB0, 'NSM'],
|
|
831
|
+
[0x11CB2, 0x11CB3, 'NSM'],
|
|
832
|
+
[0x11CB5, 0x11CB6, 'NSM'],
|
|
833
|
+
[0x11D31, 0x11D36, 'NSM'],
|
|
834
|
+
[0x11D3A, 0x11D3A, 'NSM'],
|
|
835
|
+
[0x11D3C, 0x11D3D, 'NSM'],
|
|
836
|
+
[0x11D3F, 0x11D45, 'NSM'],
|
|
837
|
+
[0x11D47, 0x11D47, 'NSM'],
|
|
838
|
+
[0x11D90, 0x11D91, 'NSM'],
|
|
839
|
+
[0x11D95, 0x11D95, 'NSM'],
|
|
840
|
+
[0x11D97, 0x11D97, 'NSM'],
|
|
841
|
+
[0x11EF3, 0x11EF4, 'NSM'],
|
|
842
|
+
[0x11F00, 0x11F01, 'NSM'],
|
|
843
|
+
[0x11F36, 0x11F3A, 'NSM'],
|
|
844
|
+
[0x11F40, 0x11F40, 'NSM'],
|
|
845
|
+
[0x11F42, 0x11F42, 'NSM'],
|
|
846
|
+
[0x11F5A, 0x11F5A, 'NSM'],
|
|
847
|
+
[0x11FD5, 0x11FDC, 'ON'],
|
|
848
|
+
[0x11FDD, 0x11FE0, 'ET'],
|
|
849
|
+
[0x11FE1, 0x11FF1, 'ON'],
|
|
850
|
+
[0x13440, 0x13440, 'NSM'],
|
|
851
|
+
[0x13447, 0x13455, 'NSM'],
|
|
852
|
+
[0x1611E, 0x16129, 'NSM'],
|
|
853
|
+
[0x1612D, 0x1612F, 'NSM'],
|
|
854
|
+
[0x16AF0, 0x16AF4, 'NSM'],
|
|
855
|
+
[0x16B30, 0x16B36, 'NSM'],
|
|
856
|
+
[0x16F4F, 0x16F4F, 'NSM'],
|
|
857
|
+
[0x16F8F, 0x16F92, 'NSM'],
|
|
858
|
+
[0x16FE2, 0x16FE2, 'ON'],
|
|
859
|
+
[0x16FE4, 0x16FE4, 'NSM'],
|
|
860
|
+
[0x1BC9D, 0x1BC9E, 'NSM'],
|
|
861
|
+
[0x1BCA0, 0x1BCA3, 'BN'],
|
|
862
|
+
[0x1CC00, 0x1CCD5, 'ON'],
|
|
863
|
+
[0x1CCF0, 0x1CCF9, 'EN'],
|
|
864
|
+
[0x1CCFA, 0x1CCFC, 'ON'],
|
|
865
|
+
[0x1CD00, 0x1CEB3, 'ON'],
|
|
866
|
+
[0x1CEBA, 0x1CED0, 'ON'],
|
|
867
|
+
[0x1CEE0, 0x1CEF0, 'ON'],
|
|
868
|
+
[0x1CF00, 0x1CF2D, 'NSM'],
|
|
869
|
+
[0x1CF30, 0x1CF46, 'NSM'],
|
|
870
|
+
[0x1D167, 0x1D169, 'NSM'],
|
|
871
|
+
[0x1D173, 0x1D17A, 'BN'],
|
|
872
|
+
[0x1D17B, 0x1D182, 'NSM'],
|
|
873
|
+
[0x1D185, 0x1D18B, 'NSM'],
|
|
874
|
+
[0x1D1AA, 0x1D1AD, 'NSM'],
|
|
875
|
+
[0x1D1E9, 0x1D1EA, 'ON'],
|
|
876
|
+
[0x1D200, 0x1D241, 'ON'],
|
|
877
|
+
[0x1D242, 0x1D244, 'NSM'],
|
|
878
|
+
[0x1D245, 0x1D245, 'ON'],
|
|
879
|
+
[0x1D300, 0x1D356, 'ON'],
|
|
880
|
+
[0x1D6C1, 0x1D6C1, 'ON'],
|
|
881
|
+
[0x1D6DB, 0x1D6DB, 'ON'],
|
|
882
|
+
[0x1D6FB, 0x1D6FB, 'ON'],
|
|
883
|
+
[0x1D715, 0x1D715, 'ON'],
|
|
884
|
+
[0x1D735, 0x1D735, 'ON'],
|
|
885
|
+
[0x1D74F, 0x1D74F, 'ON'],
|
|
886
|
+
[0x1D76F, 0x1D76F, 'ON'],
|
|
887
|
+
[0x1D789, 0x1D789, 'ON'],
|
|
888
|
+
[0x1D7A9, 0x1D7A9, 'ON'],
|
|
889
|
+
[0x1D7C3, 0x1D7C3, 'ON'],
|
|
890
|
+
[0x1D7CE, 0x1D7FF, 'EN'],
|
|
891
|
+
[0x1DA00, 0x1DA36, 'NSM'],
|
|
892
|
+
[0x1DA3B, 0x1DA6C, 'NSM'],
|
|
893
|
+
[0x1DA75, 0x1DA75, 'NSM'],
|
|
894
|
+
[0x1DA84, 0x1DA84, 'NSM'],
|
|
895
|
+
[0x1DA9B, 0x1DA9F, 'NSM'],
|
|
896
|
+
[0x1DAA1, 0x1DAAF, 'NSM'],
|
|
897
|
+
[0x1E000, 0x1E006, 'NSM'],
|
|
898
|
+
[0x1E008, 0x1E018, 'NSM'],
|
|
899
|
+
[0x1E01B, 0x1E021, 'NSM'],
|
|
900
|
+
[0x1E023, 0x1E024, 'NSM'],
|
|
901
|
+
[0x1E026, 0x1E02A, 'NSM'],
|
|
902
|
+
[0x1E08F, 0x1E08F, 'NSM'],
|
|
903
|
+
[0x1E130, 0x1E136, 'NSM'],
|
|
904
|
+
[0x1E2AE, 0x1E2AE, 'NSM'],
|
|
905
|
+
[0x1E2EC, 0x1E2EF, 'NSM'],
|
|
906
|
+
[0x1E2FF, 0x1E2FF, 'ET'],
|
|
907
|
+
[0x1E4EC, 0x1E4EF, 'NSM'],
|
|
908
|
+
[0x1E5EE, 0x1E5EF, 'NSM'],
|
|
909
|
+
[0x1E6E3, 0x1E6E3, 'NSM'],
|
|
910
|
+
[0x1E6E6, 0x1E6E6, 'NSM'],
|
|
911
|
+
[0x1E6EE, 0x1E6EF, 'NSM'],
|
|
912
|
+
[0x1E6F5, 0x1E6F5, 'NSM'],
|
|
913
|
+
[0x1E800, 0x1E8CF, 'R'],
|
|
914
|
+
[0x1E8D0, 0x1E8D6, 'NSM'],
|
|
915
|
+
[0x1E8D7, 0x1E943, 'R'],
|
|
916
|
+
[0x1E944, 0x1E94A, 'NSM'],
|
|
917
|
+
[0x1E94B, 0x1EC6F, 'R'],
|
|
918
|
+
[0x1EC70, 0x1ECBF, 'AL'],
|
|
919
|
+
[0x1ECC0, 0x1ECFF, 'R'],
|
|
920
|
+
[0x1ED00, 0x1ED4F, 'AL'],
|
|
921
|
+
[0x1ED50, 0x1EDFF, 'R'],
|
|
922
|
+
[0x1EE00, 0x1EEEF, 'AL'],
|
|
923
|
+
[0x1EEF0, 0x1EEF1, 'ON'],
|
|
924
|
+
[0x1EEF2, 0x1EEFF, 'AL'],
|
|
925
|
+
[0x1EF00, 0x1EFFF, 'R'],
|
|
926
|
+
[0x1F000, 0x1F02B, 'ON'],
|
|
927
|
+
[0x1F030, 0x1F093, 'ON'],
|
|
928
|
+
[0x1F0A0, 0x1F0AE, 'ON'],
|
|
929
|
+
[0x1F0B1, 0x1F0BF, 'ON'],
|
|
930
|
+
[0x1F0C1, 0x1F0CF, 'ON'],
|
|
931
|
+
[0x1F0D1, 0x1F0F5, 'ON'],
|
|
932
|
+
[0x1F100, 0x1F10A, 'EN'],
|
|
933
|
+
[0x1F10B, 0x1F10F, 'ON'],
|
|
934
|
+
[0x1F12F, 0x1F12F, 'ON'],
|
|
935
|
+
[0x1F16A, 0x1F16F, 'ON'],
|
|
936
|
+
[0x1F1AD, 0x1F1AD, 'ON'],
|
|
937
|
+
[0x1F260, 0x1F265, 'ON'],
|
|
938
|
+
[0x1F300, 0x1F6D8, 'ON'],
|
|
939
|
+
[0x1F6DC, 0x1F6EC, 'ON'],
|
|
940
|
+
[0x1F6F0, 0x1F6FC, 'ON'],
|
|
941
|
+
[0x1F700, 0x1F7D9, 'ON'],
|
|
942
|
+
[0x1F7E0, 0x1F7EB, 'ON'],
|
|
943
|
+
[0x1F7F0, 0x1F7F0, 'ON'],
|
|
944
|
+
[0x1F800, 0x1F80B, 'ON'],
|
|
945
|
+
[0x1F810, 0x1F847, 'ON'],
|
|
946
|
+
[0x1F850, 0x1F859, 'ON'],
|
|
947
|
+
[0x1F860, 0x1F887, 'ON'],
|
|
948
|
+
[0x1F890, 0x1F8AD, 'ON'],
|
|
949
|
+
[0x1F8B0, 0x1F8BB, 'ON'],
|
|
950
|
+
[0x1F8C0, 0x1F8C1, 'ON'],
|
|
951
|
+
[0x1F8D0, 0x1F8D8, 'ON'],
|
|
952
|
+
[0x1F900, 0x1FA57, 'ON'],
|
|
953
|
+
[0x1FA60, 0x1FA6D, 'ON'],
|
|
954
|
+
[0x1FA70, 0x1FA7C, 'ON'],
|
|
955
|
+
[0x1FA80, 0x1FA8A, 'ON'],
|
|
956
|
+
[0x1FA8E, 0x1FAC6, 'ON'],
|
|
957
|
+
[0x1FAC8, 0x1FAC8, 'ON'],
|
|
958
|
+
[0x1FACD, 0x1FADC, 'ON'],
|
|
959
|
+
[0x1FADF, 0x1FAEA, 'ON'],
|
|
960
|
+
[0x1FAEF, 0x1FAF8, 'ON'],
|
|
961
|
+
[0x1FB00, 0x1FB92, 'ON'],
|
|
962
|
+
[0x1FB94, 0x1FBEF, 'ON'],
|
|
963
|
+
[0x1FBF0, 0x1FBF9, 'EN'],
|
|
964
|
+
[0x1FBFA, 0x1FBFA, 'ON'],
|
|
965
|
+
[0x1FFFE, 0x1FFFF, 'BN'],
|
|
966
|
+
[0x2FFFE, 0x2FFFF, 'BN'],
|
|
967
|
+
[0x3FFFE, 0x3FFFF, 'BN'],
|
|
968
|
+
[0x4FFFE, 0x4FFFF, 'BN'],
|
|
969
|
+
[0x5FFFE, 0x5FFFF, 'BN'],
|
|
970
|
+
[0x6FFFE, 0x6FFFF, 'BN'],
|
|
971
|
+
[0x7FFFE, 0x7FFFF, 'BN'],
|
|
972
|
+
[0x8FFFE, 0x8FFFF, 'BN'],
|
|
973
|
+
[0x9FFFE, 0x9FFFF, 'BN'],
|
|
974
|
+
[0xAFFFE, 0xAFFFF, 'BN'],
|
|
975
|
+
[0xBFFFE, 0xBFFFF, 'BN'],
|
|
976
|
+
[0xCFFFE, 0xCFFFF, 'BN'],
|
|
977
|
+
[0xDFFFE, 0xE00FF, 'BN'],
|
|
978
|
+
[0xE0100, 0xE01EF, 'NSM'],
|
|
979
|
+
[0xE01F0, 0xE0FFF, 'BN'],
|
|
980
|
+
[0xEFFFE, 0xEFFFF, 'BN'],
|
|
981
|
+
[0xFFFFE, 0xFFFFF, 'BN'],
|
|
982
|
+
[0x10FFFE, 0x10FFFF, 'BN'],
|
|
983
|
+
];
|
|
984
|
+
|
|
985
|
+
// Simplified bidi metadata helper for the rich prepareWithSegments() path,
|
|
986
|
+
// forked from pdf.js via Sebastian's text-layout. It classifies characters
|
|
987
|
+
// into bidi types, computes embedding levels, and maps them onto prepared
|
|
988
|
+
// segments for custom rendering. The line-breaking engine does not consume
|
|
989
|
+
// these levels.
|
|
990
|
+
function classifyCodePoint(codePoint) {
|
|
991
|
+
if (codePoint <= 0x00FF)
|
|
992
|
+
return latin1BidiTypes[codePoint];
|
|
993
|
+
let lo = 0;
|
|
994
|
+
let hi = nonLatin1BidiRanges.length - 1;
|
|
995
|
+
while (lo <= hi) {
|
|
996
|
+
const mid = (lo + hi) >> 1;
|
|
997
|
+
const range = nonLatin1BidiRanges[mid];
|
|
998
|
+
if (codePoint < range[0]) {
|
|
999
|
+
hi = mid - 1;
|
|
1000
|
+
continue;
|
|
1001
|
+
}
|
|
1002
|
+
if (codePoint > range[1]) {
|
|
1003
|
+
lo = mid + 1;
|
|
1004
|
+
continue;
|
|
1005
|
+
}
|
|
1006
|
+
return range[2];
|
|
1007
|
+
}
|
|
1008
|
+
return 'L';
|
|
1009
|
+
}
|
|
1010
|
+
function computeBidiLevels(str) {
|
|
1011
|
+
const len = str.length;
|
|
1012
|
+
if (len === 0)
|
|
1013
|
+
return null;
|
|
1014
|
+
// eslint-disable-next-line unicorn/no-new-array
|
|
1015
|
+
const types = new Array(len);
|
|
1016
|
+
let sawBidi = false;
|
|
1017
|
+
// Keep the resolved bidi classes aligned to UTF-16 code-unit offsets,
|
|
1018
|
+
// because the rich prepared segments index back into the normalized string
|
|
1019
|
+
// with JavaScript string offsets.
|
|
1020
|
+
for (let i = 0; i < len;) {
|
|
1021
|
+
const first = str.charCodeAt(i);
|
|
1022
|
+
let codePoint = first;
|
|
1023
|
+
let codeUnitLength = 1;
|
|
1024
|
+
if (first >= 0xD800 && first <= 0xDBFF && i + 1 < len) {
|
|
1025
|
+
const second = str.charCodeAt(i + 1);
|
|
1026
|
+
if (second >= 0xDC00 && second <= 0xDFFF) {
|
|
1027
|
+
codePoint = ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000;
|
|
1028
|
+
codeUnitLength = 2;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
const t = classifyCodePoint(codePoint);
|
|
1032
|
+
if (t === 'R' || t === 'AL' || t === 'AN')
|
|
1033
|
+
sawBidi = true;
|
|
1034
|
+
for (let j = 0; j < codeUnitLength; j++) {
|
|
1035
|
+
types[i + j] = t;
|
|
1036
|
+
}
|
|
1037
|
+
i += codeUnitLength;
|
|
1038
|
+
}
|
|
1039
|
+
if (!sawBidi)
|
|
1040
|
+
return null;
|
|
1041
|
+
// Use the first strong character to pick the paragraph base direction.
|
|
1042
|
+
// Rich-path bidi metadata is only an approximation, but this keeps mixed
|
|
1043
|
+
// LTR/RTL text aligned with the common UBA paragraph rule.
|
|
1044
|
+
let startLevel = 0;
|
|
1045
|
+
for (let i = 0; i < len; i++) {
|
|
1046
|
+
const t = types[i];
|
|
1047
|
+
if (t === 'L') {
|
|
1048
|
+
startLevel = 0;
|
|
1049
|
+
break;
|
|
1050
|
+
}
|
|
1051
|
+
if (t === 'R' || t === 'AL') {
|
|
1052
|
+
startLevel = 1;
|
|
1053
|
+
break;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
const levels = new Int8Array(len);
|
|
1057
|
+
for (let i = 0; i < len; i++)
|
|
1058
|
+
levels[i] = startLevel;
|
|
1059
|
+
const e = (startLevel & 1) ? 'R' : 'L';
|
|
1060
|
+
const sor = e;
|
|
1061
|
+
// W1-W7
|
|
1062
|
+
let lastType = sor;
|
|
1063
|
+
for (let i = 0; i < len; i++) {
|
|
1064
|
+
if (types[i] === 'NSM')
|
|
1065
|
+
types[i] = lastType;
|
|
1066
|
+
else
|
|
1067
|
+
lastType = types[i];
|
|
1068
|
+
}
|
|
1069
|
+
lastType = sor;
|
|
1070
|
+
for (let i = 0; i < len; i++) {
|
|
1071
|
+
const t = types[i];
|
|
1072
|
+
if (t === 'EN')
|
|
1073
|
+
types[i] = lastType === 'AL' ? 'AN' : 'EN';
|
|
1074
|
+
else if (t === 'R' || t === 'L' || t === 'AL')
|
|
1075
|
+
lastType = t;
|
|
1076
|
+
}
|
|
1077
|
+
for (let i = 0; i < len; i++) {
|
|
1078
|
+
if (types[i] === 'AL')
|
|
1079
|
+
types[i] = 'R';
|
|
1080
|
+
}
|
|
1081
|
+
for (let i = 1; i < len - 1; i++) {
|
|
1082
|
+
if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
|
|
1083
|
+
types[i] = 'EN';
|
|
1084
|
+
}
|
|
1085
|
+
if (types[i] === 'CS' &&
|
|
1086
|
+
(types[i - 1] === 'EN' || types[i - 1] === 'AN') &&
|
|
1087
|
+
types[i + 1] === types[i - 1]) {
|
|
1088
|
+
types[i] = types[i - 1];
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
for (let i = 0; i < len; i++) {
|
|
1092
|
+
if (types[i] !== 'EN')
|
|
1093
|
+
continue;
|
|
1094
|
+
let j;
|
|
1095
|
+
for (j = i - 1; j >= 0 && types[j] === 'ET'; j--)
|
|
1096
|
+
types[j] = 'EN';
|
|
1097
|
+
for (j = i + 1; j < len && types[j] === 'ET'; j++)
|
|
1098
|
+
types[j] = 'EN';
|
|
1099
|
+
}
|
|
1100
|
+
for (let i = 0; i < len; i++) {
|
|
1101
|
+
const t = types[i];
|
|
1102
|
+
if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS')
|
|
1103
|
+
types[i] = 'ON';
|
|
1104
|
+
}
|
|
1105
|
+
lastType = sor;
|
|
1106
|
+
for (let i = 0; i < len; i++) {
|
|
1107
|
+
const t = types[i];
|
|
1108
|
+
if (t === 'EN')
|
|
1109
|
+
types[i] = lastType === 'L' ? 'L' : 'EN';
|
|
1110
|
+
else if (t === 'R' || t === 'L')
|
|
1111
|
+
lastType = t;
|
|
1112
|
+
}
|
|
1113
|
+
// N1-N2
|
|
1114
|
+
for (let i = 0; i < len; i++) {
|
|
1115
|
+
if (types[i] !== 'ON')
|
|
1116
|
+
continue;
|
|
1117
|
+
let end = i + 1;
|
|
1118
|
+
while (end < len && types[end] === 'ON')
|
|
1119
|
+
end++;
|
|
1120
|
+
const before = i > 0 ? types[i - 1] : sor;
|
|
1121
|
+
const after = end < len ? types[end] : sor;
|
|
1122
|
+
const bDir = before !== 'L' ? 'R' : 'L';
|
|
1123
|
+
const aDir = after !== 'L' ? 'R' : 'L';
|
|
1124
|
+
if (bDir === aDir) {
|
|
1125
|
+
for (let j = i; j < end; j++)
|
|
1126
|
+
types[j] = bDir;
|
|
1127
|
+
}
|
|
1128
|
+
i = end - 1;
|
|
1129
|
+
}
|
|
1130
|
+
for (let i = 0; i < len; i++) {
|
|
1131
|
+
if (types[i] === 'ON')
|
|
1132
|
+
types[i] = e;
|
|
1133
|
+
}
|
|
1134
|
+
// I1-I2
|
|
1135
|
+
for (let i = 0; i < len; i++) {
|
|
1136
|
+
const t = types[i];
|
|
1137
|
+
if ((levels[i] & 1) === 0) {
|
|
1138
|
+
if (t === 'R')
|
|
1139
|
+
levels[i]++;
|
|
1140
|
+
else if (t === 'AN' || t === 'EN')
|
|
1141
|
+
levels[i] += 2;
|
|
1142
|
+
}
|
|
1143
|
+
else if (t === 'L' || t === 'AN' || t === 'EN') {
|
|
1144
|
+
levels[i]++;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
return levels;
|
|
1148
|
+
}
|
|
1149
|
+
function computeSegmentLevels(normalized, segStarts) {
|
|
1150
|
+
const bidiLevels = computeBidiLevels(normalized);
|
|
1151
|
+
if (bidiLevels === null)
|
|
1152
|
+
return null;
|
|
1153
|
+
const segLevels = new Int8Array(segStarts.length);
|
|
1154
|
+
for (let i = 0; i < segStarts.length; i++) {
|
|
1155
|
+
segLevels[i] = bidiLevels[segStarts[i]];
|
|
1156
|
+
}
|
|
1157
|
+
return segLevels;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
const collapsibleWhitespaceRunRe = /[ \t\n\r\f]+/g;
|
|
1161
|
+
const needsWhitespaceNormalizationRe = /[\t\n\r\f]| {2,}|^ | $/;
|
|
1162
|
+
function getWhiteSpaceProfile(whiteSpace) {
|
|
1163
|
+
const mode = whiteSpace ?? 'normal';
|
|
1164
|
+
return mode === 'pre-wrap'
|
|
1165
|
+
? { mode, preserveOrdinarySpaces: true, preserveHardBreaks: true }
|
|
1166
|
+
: { mode, preserveOrdinarySpaces: false, preserveHardBreaks: false };
|
|
1167
|
+
}
|
|
1168
|
+
function normalizeWhitespaceNormal(text) {
|
|
1169
|
+
if (!needsWhitespaceNormalizationRe.test(text))
|
|
1170
|
+
return text;
|
|
1171
|
+
let normalized = text.replace(collapsibleWhitespaceRunRe, ' ');
|
|
1172
|
+
if (normalized.charCodeAt(0) === 0x20) {
|
|
1173
|
+
normalized = normalized.slice(1);
|
|
1174
|
+
}
|
|
1175
|
+
if (normalized.length > 0 && normalized.charCodeAt(normalized.length - 1) === 0x20) {
|
|
1176
|
+
normalized = normalized.slice(0, -1);
|
|
1177
|
+
}
|
|
1178
|
+
return normalized;
|
|
1179
|
+
}
|
|
1180
|
+
function normalizeWhitespacePreWrap(text) {
|
|
1181
|
+
if (!/[\r\f]/.test(text))
|
|
1182
|
+
return text;
|
|
1183
|
+
return text
|
|
1184
|
+
.replace(/\r\n/g, '\n')
|
|
1185
|
+
.replace(/[\r\f]/g, '\n');
|
|
1186
|
+
}
|
|
1187
|
+
let sharedWordSegmenter = null;
|
|
1188
|
+
let segmenterLocale;
|
|
1189
|
+
function getSharedWordSegmenter() {
|
|
1190
|
+
if (sharedWordSegmenter === null) {
|
|
1191
|
+
sharedWordSegmenter = new Intl.Segmenter(segmenterLocale, { granularity: 'word' });
|
|
1192
|
+
}
|
|
1193
|
+
return sharedWordSegmenter;
|
|
1194
|
+
}
|
|
1195
|
+
const arabicScriptRe = /\p{Script=Arabic}/u;
|
|
1196
|
+
const combiningMarkRe = /\p{M}/u;
|
|
1197
|
+
const decimalDigitRe = /\p{Nd}/u;
|
|
1198
|
+
function containsArabicScript(text) {
|
|
1199
|
+
return arabicScriptRe.test(text);
|
|
1200
|
+
}
|
|
1201
|
+
function isCJKCodePoint(codePoint) {
|
|
1202
|
+
return ((codePoint >= 0x4E00 && codePoint <= 0x9FFF) ||
|
|
1203
|
+
(codePoint >= 0x3400 && codePoint <= 0x4DBF) ||
|
|
1204
|
+
(codePoint >= 0x20000 && codePoint <= 0x2A6DF) ||
|
|
1205
|
+
(codePoint >= 0x2A700 && codePoint <= 0x2B73F) ||
|
|
1206
|
+
(codePoint >= 0x2B740 && codePoint <= 0x2B81F) ||
|
|
1207
|
+
(codePoint >= 0x2B820 && codePoint <= 0x2CEAF) ||
|
|
1208
|
+
(codePoint >= 0x2CEB0 && codePoint <= 0x2EBEF) ||
|
|
1209
|
+
(codePoint >= 0x2EBF0 && codePoint <= 0x2EE5D) ||
|
|
1210
|
+
(codePoint >= 0x2F800 && codePoint <= 0x2FA1F) ||
|
|
1211
|
+
(codePoint >= 0x30000 && codePoint <= 0x3134F) ||
|
|
1212
|
+
(codePoint >= 0x31350 && codePoint <= 0x323AF) ||
|
|
1213
|
+
(codePoint >= 0x323B0 && codePoint <= 0x33479) ||
|
|
1214
|
+
(codePoint >= 0xF900 && codePoint <= 0xFAFF) ||
|
|
1215
|
+
(codePoint >= 0x3000 && codePoint <= 0x303F) ||
|
|
1216
|
+
(codePoint >= 0x3040 && codePoint <= 0x309F) ||
|
|
1217
|
+
(codePoint >= 0x30A0 && codePoint <= 0x30FF) ||
|
|
1218
|
+
(codePoint >= 0x3130 && codePoint <= 0x318F) ||
|
|
1219
|
+
(codePoint >= 0xAC00 && codePoint <= 0xD7AF) ||
|
|
1220
|
+
(codePoint >= 0xFF00 && codePoint <= 0xFFEF));
|
|
1221
|
+
}
|
|
1222
|
+
function isCJK(s) {
|
|
1223
|
+
for (let i = 0; i < s.length; i++) {
|
|
1224
|
+
const first = s.charCodeAt(i);
|
|
1225
|
+
if (first < 0x3000)
|
|
1226
|
+
continue;
|
|
1227
|
+
if (first >= 0xD800 && first <= 0xDBFF && i + 1 < s.length) {
|
|
1228
|
+
const second = s.charCodeAt(i + 1);
|
|
1229
|
+
if (second >= 0xDC00 && second <= 0xDFFF) {
|
|
1230
|
+
const codePoint = ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000;
|
|
1231
|
+
if (isCJKCodePoint(codePoint))
|
|
1232
|
+
return true;
|
|
1233
|
+
i++;
|
|
1234
|
+
continue;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
if (isCJKCodePoint(first))
|
|
1238
|
+
return true;
|
|
1239
|
+
}
|
|
1240
|
+
return false;
|
|
1241
|
+
}
|
|
1242
|
+
function endsWithLineStartProhibitedText(text) {
|
|
1243
|
+
const last = getLastCodePoint(text);
|
|
1244
|
+
return last !== null && (kinsokuStart.has(last) || leftStickyPunctuation.has(last));
|
|
1245
|
+
}
|
|
1246
|
+
const keepAllGlueChars = new Set([
|
|
1247
|
+
'\u00A0',
|
|
1248
|
+
'\u202F',
|
|
1249
|
+
'\u2060',
|
|
1250
|
+
'\uFEFF',
|
|
1251
|
+
]);
|
|
1252
|
+
function containsCJKText(text) {
|
|
1253
|
+
return isCJK(text);
|
|
1254
|
+
}
|
|
1255
|
+
function endsWithKeepAllGlueText(text) {
|
|
1256
|
+
const last = getLastCodePoint(text);
|
|
1257
|
+
return last !== null && keepAllGlueChars.has(last);
|
|
1258
|
+
}
|
|
1259
|
+
function canContinueKeepAllTextRun(previousText) {
|
|
1260
|
+
return (!endsWithLineStartProhibitedText(previousText) &&
|
|
1261
|
+
!endsWithKeepAllGlueText(previousText));
|
|
1262
|
+
}
|
|
1263
|
+
const kinsokuStart = new Set([
|
|
1264
|
+
'\uFF0C',
|
|
1265
|
+
'\uFF0E',
|
|
1266
|
+
'\uFF01',
|
|
1267
|
+
'\uFF1A',
|
|
1268
|
+
'\uFF1B',
|
|
1269
|
+
'\uFF1F',
|
|
1270
|
+
'\u3001',
|
|
1271
|
+
'\u3002',
|
|
1272
|
+
'\u30FB',
|
|
1273
|
+
'\uFF09',
|
|
1274
|
+
'\u3015',
|
|
1275
|
+
'\u3009',
|
|
1276
|
+
'\u300B',
|
|
1277
|
+
'\u300D',
|
|
1278
|
+
'\u300F',
|
|
1279
|
+
'\u3011',
|
|
1280
|
+
'\u3017',
|
|
1281
|
+
'\u3019',
|
|
1282
|
+
'\u301B',
|
|
1283
|
+
'\u30FC',
|
|
1284
|
+
'\u3005',
|
|
1285
|
+
'\u303B',
|
|
1286
|
+
'\u309D',
|
|
1287
|
+
'\u309E',
|
|
1288
|
+
'\u30FD',
|
|
1289
|
+
'\u30FE',
|
|
1290
|
+
]);
|
|
1291
|
+
const kinsokuEnd = new Set([
|
|
1292
|
+
'"',
|
|
1293
|
+
'(', '[', '{',
|
|
1294
|
+
'“', '‘', '«', '‹',
|
|
1295
|
+
'\uFF08',
|
|
1296
|
+
'\u3014',
|
|
1297
|
+
'\u3008',
|
|
1298
|
+
'\u300A',
|
|
1299
|
+
'\u300C',
|
|
1300
|
+
'\u300E',
|
|
1301
|
+
'\u3010',
|
|
1302
|
+
'\u3016',
|
|
1303
|
+
'\u3018',
|
|
1304
|
+
'\u301A',
|
|
1305
|
+
]);
|
|
1306
|
+
const forwardStickyGlue = new Set([
|
|
1307
|
+
"'", '’',
|
|
1308
|
+
]);
|
|
1309
|
+
const leftStickyPunctuation = new Set([
|
|
1310
|
+
'.', ',', '!', '?', ':', ';',
|
|
1311
|
+
'\u060C',
|
|
1312
|
+
'\u061B',
|
|
1313
|
+
'\u061F',
|
|
1314
|
+
'\u0964',
|
|
1315
|
+
'\u0965',
|
|
1316
|
+
'\u104A',
|
|
1317
|
+
'\u104B',
|
|
1318
|
+
'\u104C',
|
|
1319
|
+
'\u104D',
|
|
1320
|
+
'\u104F',
|
|
1321
|
+
')', ']', '}',
|
|
1322
|
+
'%',
|
|
1323
|
+
'"',
|
|
1324
|
+
'”', '’', '»', '›',
|
|
1325
|
+
'…',
|
|
1326
|
+
]);
|
|
1327
|
+
const arabicNoSpaceTrailingPunctuation = new Set([
|
|
1328
|
+
':',
|
|
1329
|
+
'.',
|
|
1330
|
+
'\u060C',
|
|
1331
|
+
'\u061B',
|
|
1332
|
+
]);
|
|
1333
|
+
const myanmarMedialGlue = new Set([
|
|
1334
|
+
'\u104F',
|
|
1335
|
+
]);
|
|
1336
|
+
const closingQuoteChars = new Set([
|
|
1337
|
+
'”', '’', '»', '›',
|
|
1338
|
+
'\u300D',
|
|
1339
|
+
'\u300F',
|
|
1340
|
+
'\u3011',
|
|
1341
|
+
'\u300B',
|
|
1342
|
+
'\u3009',
|
|
1343
|
+
'\u3015',
|
|
1344
|
+
'\uFF09',
|
|
1345
|
+
]);
|
|
1346
|
+
function isLeftStickyPunctuationSegment(segment) {
|
|
1347
|
+
if (isEscapedQuoteClusterSegment(segment))
|
|
1348
|
+
return true;
|
|
1349
|
+
let sawPunctuation = false;
|
|
1350
|
+
for (const ch of segment) {
|
|
1351
|
+
if (leftStickyPunctuation.has(ch)) {
|
|
1352
|
+
sawPunctuation = true;
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
if (sawPunctuation && combiningMarkRe.test(ch))
|
|
1356
|
+
continue;
|
|
1357
|
+
return false;
|
|
1358
|
+
}
|
|
1359
|
+
return sawPunctuation;
|
|
1360
|
+
}
|
|
1361
|
+
function isCJKLineStartProhibitedSegment(segment) {
|
|
1362
|
+
for (const ch of segment) {
|
|
1363
|
+
if (!kinsokuStart.has(ch) && !leftStickyPunctuation.has(ch))
|
|
1364
|
+
return false;
|
|
1365
|
+
}
|
|
1366
|
+
return segment.length > 0;
|
|
1367
|
+
}
|
|
1368
|
+
function isForwardStickyClusterSegment(segment) {
|
|
1369
|
+
if (isEscapedQuoteClusterSegment(segment))
|
|
1370
|
+
return true;
|
|
1371
|
+
for (const ch of segment) {
|
|
1372
|
+
if (!kinsokuEnd.has(ch) && !forwardStickyGlue.has(ch) && !combiningMarkRe.test(ch))
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
return segment.length > 0;
|
|
1376
|
+
}
|
|
1377
|
+
function isEscapedQuoteClusterSegment(segment) {
|
|
1378
|
+
let sawQuote = false;
|
|
1379
|
+
for (const ch of segment) {
|
|
1380
|
+
if (ch === '\\' || combiningMarkRe.test(ch))
|
|
1381
|
+
continue;
|
|
1382
|
+
if (kinsokuEnd.has(ch) || leftStickyPunctuation.has(ch) || forwardStickyGlue.has(ch)) {
|
|
1383
|
+
sawQuote = true;
|
|
1384
|
+
continue;
|
|
1385
|
+
}
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
return sawQuote;
|
|
1389
|
+
}
|
|
1390
|
+
function previousCodePointStart(text, end) {
|
|
1391
|
+
const last = end - 1;
|
|
1392
|
+
if (last <= 0)
|
|
1393
|
+
return Math.max(last, 0);
|
|
1394
|
+
const lastCodeUnit = text.charCodeAt(last);
|
|
1395
|
+
if (lastCodeUnit < 0xDC00 || lastCodeUnit > 0xDFFF)
|
|
1396
|
+
return last;
|
|
1397
|
+
const maybeHigh = last - 1;
|
|
1398
|
+
if (maybeHigh < 0)
|
|
1399
|
+
return last;
|
|
1400
|
+
const highCodeUnit = text.charCodeAt(maybeHigh);
|
|
1401
|
+
return highCodeUnit >= 0xD800 && highCodeUnit <= 0xDBFF ? maybeHigh : last;
|
|
1402
|
+
}
|
|
1403
|
+
function getLastCodePoint(text) {
|
|
1404
|
+
if (text.length === 0)
|
|
1405
|
+
return null;
|
|
1406
|
+
const start = previousCodePointStart(text, text.length);
|
|
1407
|
+
return text.slice(start);
|
|
1408
|
+
}
|
|
1409
|
+
function splitTrailingForwardStickyCluster(text) {
|
|
1410
|
+
const chars = Array.from(text);
|
|
1411
|
+
let splitIndex = chars.length;
|
|
1412
|
+
while (splitIndex > 0) {
|
|
1413
|
+
const ch = chars[splitIndex - 1];
|
|
1414
|
+
if (combiningMarkRe.test(ch)) {
|
|
1415
|
+
splitIndex--;
|
|
1416
|
+
continue;
|
|
1417
|
+
}
|
|
1418
|
+
if (kinsokuEnd.has(ch) || forwardStickyGlue.has(ch)) {
|
|
1419
|
+
splitIndex--;
|
|
1420
|
+
continue;
|
|
1421
|
+
}
|
|
1422
|
+
break;
|
|
1423
|
+
}
|
|
1424
|
+
if (splitIndex <= 0 || splitIndex === chars.length)
|
|
1425
|
+
return null;
|
|
1426
|
+
return {
|
|
1427
|
+
head: chars.slice(0, splitIndex).join(''),
|
|
1428
|
+
tail: chars.slice(splitIndex).join(''),
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
function getRepeatableSingleCharRunChar(text, isWordLike, kind) {
|
|
1432
|
+
return kind === 'text' && !isWordLike && text.length === 1 && text !== '-' && text !== '—'
|
|
1433
|
+
? text
|
|
1434
|
+
: null;
|
|
1435
|
+
}
|
|
1436
|
+
function materializeDeferredSingleCharRun(texts, chars, lengths, index) {
|
|
1437
|
+
const ch = chars[index];
|
|
1438
|
+
const text = texts[index];
|
|
1439
|
+
if (ch == null)
|
|
1440
|
+
return text;
|
|
1441
|
+
const length = lengths[index];
|
|
1442
|
+
if (text.length === length)
|
|
1443
|
+
return text;
|
|
1444
|
+
const materialized = ch.repeat(length);
|
|
1445
|
+
texts[index] = materialized;
|
|
1446
|
+
return materialized;
|
|
1447
|
+
}
|
|
1448
|
+
function hasArabicNoSpacePunctuation(containsArabic, lastCodePoint) {
|
|
1449
|
+
return containsArabic && lastCodePoint !== null && arabicNoSpaceTrailingPunctuation.has(lastCodePoint);
|
|
1450
|
+
}
|
|
1451
|
+
function endsWithMyanmarMedialGlue(segment) {
|
|
1452
|
+
const lastCodePoint = getLastCodePoint(segment);
|
|
1453
|
+
return lastCodePoint !== null && myanmarMedialGlue.has(lastCodePoint);
|
|
1454
|
+
}
|
|
1455
|
+
function splitLeadingSpaceAndMarks(segment) {
|
|
1456
|
+
if (segment.length < 2 || segment[0] !== ' ')
|
|
1457
|
+
return null;
|
|
1458
|
+
const marks = segment.slice(1);
|
|
1459
|
+
if (/^\p{M}+$/u.test(marks)) {
|
|
1460
|
+
return { space: ' ', marks };
|
|
1461
|
+
}
|
|
1462
|
+
return null;
|
|
1463
|
+
}
|
|
1464
|
+
function endsWithClosingQuote(text) {
|
|
1465
|
+
let end = text.length;
|
|
1466
|
+
while (end > 0) {
|
|
1467
|
+
const start = previousCodePointStart(text, end);
|
|
1468
|
+
const ch = text.slice(start, end);
|
|
1469
|
+
if (closingQuoteChars.has(ch))
|
|
1470
|
+
return true;
|
|
1471
|
+
if (!leftStickyPunctuation.has(ch))
|
|
1472
|
+
return false;
|
|
1473
|
+
end = start;
|
|
1474
|
+
}
|
|
1475
|
+
return false;
|
|
1476
|
+
}
|
|
1477
|
+
function classifySegmentBreakChar(ch, whiteSpaceProfile) {
|
|
1478
|
+
if (whiteSpaceProfile.preserveOrdinarySpaces || whiteSpaceProfile.preserveHardBreaks) {
|
|
1479
|
+
if (ch === ' ')
|
|
1480
|
+
return 'preserved-space';
|
|
1481
|
+
if (ch === '\t')
|
|
1482
|
+
return 'tab';
|
|
1483
|
+
if (whiteSpaceProfile.preserveHardBreaks && ch === '\n')
|
|
1484
|
+
return 'hard-break';
|
|
1485
|
+
}
|
|
1486
|
+
if (ch === ' ')
|
|
1487
|
+
return 'space';
|
|
1488
|
+
if (ch === '\u00A0' || ch === '\u202F' || ch === '\u2060' || ch === '\uFEFF') {
|
|
1489
|
+
return 'glue';
|
|
1490
|
+
}
|
|
1491
|
+
if (ch === '\u200B')
|
|
1492
|
+
return 'zero-width-break';
|
|
1493
|
+
if (ch === '\u00AD')
|
|
1494
|
+
return 'soft-hyphen';
|
|
1495
|
+
return 'text';
|
|
1496
|
+
}
|
|
1497
|
+
// All characters that classifySegmentBreakChar maps to a non-'text' kind.
|
|
1498
|
+
const breakCharRe = /[\x20\t\n\xA0\xAD\u200B\u202F\u2060\uFEFF]/;
|
|
1499
|
+
function joinTextParts(parts) {
|
|
1500
|
+
return parts.length === 1 ? parts[0] : parts.join('');
|
|
1501
|
+
}
|
|
1502
|
+
function joinReversedPrefixParts(prefixParts, tail) {
|
|
1503
|
+
const parts = [];
|
|
1504
|
+
for (let i = prefixParts.length - 1; i >= 0; i--) {
|
|
1505
|
+
parts.push(prefixParts[i]);
|
|
1506
|
+
}
|
|
1507
|
+
parts.push(tail);
|
|
1508
|
+
return joinTextParts(parts);
|
|
1509
|
+
}
|
|
1510
|
+
function splitSegmentByBreakKind(segment, isWordLike, start, whiteSpaceProfile) {
|
|
1511
|
+
if (!breakCharRe.test(segment)) {
|
|
1512
|
+
return [{ text: segment, isWordLike, kind: 'text', start }];
|
|
1513
|
+
}
|
|
1514
|
+
const pieces = [];
|
|
1515
|
+
let currentKind = null;
|
|
1516
|
+
let currentTextParts = [];
|
|
1517
|
+
let currentStart = start;
|
|
1518
|
+
let currentWordLike = false;
|
|
1519
|
+
let offset = 0;
|
|
1520
|
+
for (const ch of segment) {
|
|
1521
|
+
const kind = classifySegmentBreakChar(ch, whiteSpaceProfile);
|
|
1522
|
+
const wordLike = kind === 'text' && isWordLike;
|
|
1523
|
+
if (currentKind !== null && kind === currentKind && wordLike === currentWordLike) {
|
|
1524
|
+
currentTextParts.push(ch);
|
|
1525
|
+
offset += ch.length;
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
if (currentKind !== null) {
|
|
1529
|
+
pieces.push({
|
|
1530
|
+
text: joinTextParts(currentTextParts),
|
|
1531
|
+
isWordLike: currentWordLike,
|
|
1532
|
+
kind: currentKind,
|
|
1533
|
+
start: currentStart,
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
currentKind = kind;
|
|
1537
|
+
currentTextParts = [ch];
|
|
1538
|
+
currentStart = start + offset;
|
|
1539
|
+
currentWordLike = wordLike;
|
|
1540
|
+
offset += ch.length;
|
|
1541
|
+
}
|
|
1542
|
+
if (currentKind !== null) {
|
|
1543
|
+
pieces.push({
|
|
1544
|
+
text: joinTextParts(currentTextParts),
|
|
1545
|
+
isWordLike: currentWordLike,
|
|
1546
|
+
kind: currentKind,
|
|
1547
|
+
start: currentStart,
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
return pieces;
|
|
1551
|
+
}
|
|
1552
|
+
function isTextRunBoundary(kind) {
|
|
1553
|
+
return (kind === 'space' ||
|
|
1554
|
+
kind === 'preserved-space' ||
|
|
1555
|
+
kind === 'zero-width-break' ||
|
|
1556
|
+
kind === 'hard-break');
|
|
1557
|
+
}
|
|
1558
|
+
const urlSchemeSegmentRe = /^[A-Za-z][A-Za-z0-9+.-]*:$/;
|
|
1559
|
+
function isUrlLikeRunStart(segmentation, index) {
|
|
1560
|
+
const text = segmentation.texts[index];
|
|
1561
|
+
if (text.startsWith('www.'))
|
|
1562
|
+
return true;
|
|
1563
|
+
return (urlSchemeSegmentRe.test(text) &&
|
|
1564
|
+
index + 1 < segmentation.len &&
|
|
1565
|
+
segmentation.kinds[index + 1] === 'text' &&
|
|
1566
|
+
segmentation.texts[index + 1] === '//');
|
|
1567
|
+
}
|
|
1568
|
+
function isUrlQueryBoundarySegment(text) {
|
|
1569
|
+
return text.includes('?') && (text.includes('://') || text.startsWith('www.'));
|
|
1570
|
+
}
|
|
1571
|
+
function mergeUrlLikeRuns(segmentation) {
|
|
1572
|
+
const texts = segmentation.texts.slice();
|
|
1573
|
+
const isWordLike = segmentation.isWordLike.slice();
|
|
1574
|
+
const kinds = segmentation.kinds.slice();
|
|
1575
|
+
const starts = segmentation.starts.slice();
|
|
1576
|
+
for (let i = 0; i < segmentation.len; i++) {
|
|
1577
|
+
if (kinds[i] !== 'text' || !isUrlLikeRunStart(segmentation, i))
|
|
1578
|
+
continue;
|
|
1579
|
+
const mergedParts = [texts[i]];
|
|
1580
|
+
let j = i + 1;
|
|
1581
|
+
while (j < segmentation.len && !isTextRunBoundary(kinds[j])) {
|
|
1582
|
+
mergedParts.push(texts[j]);
|
|
1583
|
+
isWordLike[i] = true;
|
|
1584
|
+
const endsQueryPrefix = texts[j].includes('?');
|
|
1585
|
+
kinds[j] = 'text';
|
|
1586
|
+
texts[j] = '';
|
|
1587
|
+
j++;
|
|
1588
|
+
if (endsQueryPrefix)
|
|
1589
|
+
break;
|
|
1590
|
+
}
|
|
1591
|
+
texts[i] = joinTextParts(mergedParts);
|
|
1592
|
+
}
|
|
1593
|
+
let compactLen = 0;
|
|
1594
|
+
for (let read = 0; read < texts.length; read++) {
|
|
1595
|
+
const text = texts[read];
|
|
1596
|
+
if (text.length === 0)
|
|
1597
|
+
continue;
|
|
1598
|
+
if (compactLen !== read) {
|
|
1599
|
+
texts[compactLen] = text;
|
|
1600
|
+
isWordLike[compactLen] = isWordLike[read];
|
|
1601
|
+
kinds[compactLen] = kinds[read];
|
|
1602
|
+
starts[compactLen] = starts[read];
|
|
1603
|
+
}
|
|
1604
|
+
compactLen++;
|
|
1605
|
+
}
|
|
1606
|
+
texts.length = compactLen;
|
|
1607
|
+
isWordLike.length = compactLen;
|
|
1608
|
+
kinds.length = compactLen;
|
|
1609
|
+
starts.length = compactLen;
|
|
1610
|
+
return {
|
|
1611
|
+
len: compactLen,
|
|
1612
|
+
texts,
|
|
1613
|
+
isWordLike,
|
|
1614
|
+
kinds,
|
|
1615
|
+
starts,
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
function mergeUrlQueryRuns(segmentation) {
|
|
1619
|
+
const texts = [];
|
|
1620
|
+
const isWordLike = [];
|
|
1621
|
+
const kinds = [];
|
|
1622
|
+
const starts = [];
|
|
1623
|
+
for (let i = 0; i < segmentation.len; i++) {
|
|
1624
|
+
const text = segmentation.texts[i];
|
|
1625
|
+
texts.push(text);
|
|
1626
|
+
isWordLike.push(segmentation.isWordLike[i]);
|
|
1627
|
+
kinds.push(segmentation.kinds[i]);
|
|
1628
|
+
starts.push(segmentation.starts[i]);
|
|
1629
|
+
if (!isUrlQueryBoundarySegment(text))
|
|
1630
|
+
continue;
|
|
1631
|
+
const nextIndex = i + 1;
|
|
1632
|
+
if (nextIndex >= segmentation.len ||
|
|
1633
|
+
isTextRunBoundary(segmentation.kinds[nextIndex])) {
|
|
1634
|
+
continue;
|
|
1635
|
+
}
|
|
1636
|
+
const queryParts = [];
|
|
1637
|
+
const queryStart = segmentation.starts[nextIndex];
|
|
1638
|
+
let j = nextIndex;
|
|
1639
|
+
while (j < segmentation.len && !isTextRunBoundary(segmentation.kinds[j])) {
|
|
1640
|
+
queryParts.push(segmentation.texts[j]);
|
|
1641
|
+
j++;
|
|
1642
|
+
}
|
|
1643
|
+
if (queryParts.length > 0) {
|
|
1644
|
+
texts.push(joinTextParts(queryParts));
|
|
1645
|
+
isWordLike.push(true);
|
|
1646
|
+
kinds.push('text');
|
|
1647
|
+
starts.push(queryStart);
|
|
1648
|
+
i = j - 1;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
return {
|
|
1652
|
+
len: texts.length,
|
|
1653
|
+
texts,
|
|
1654
|
+
isWordLike,
|
|
1655
|
+
kinds,
|
|
1656
|
+
starts,
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
const numericJoinerChars = new Set([
|
|
1660
|
+
':', '-', '/', '×', ',', '.', '+',
|
|
1661
|
+
'\u2013',
|
|
1662
|
+
'\u2014',
|
|
1663
|
+
]);
|
|
1664
|
+
const asciiPunctuationChainSegmentRe = /^[A-Za-z0-9_]+[,:;]*$/;
|
|
1665
|
+
const asciiPunctuationChainTrailingJoinersRe = /[,:;]+$/;
|
|
1666
|
+
function segmentContainsDecimalDigit(text) {
|
|
1667
|
+
for (const ch of text) {
|
|
1668
|
+
if (decimalDigitRe.test(ch))
|
|
1669
|
+
return true;
|
|
1670
|
+
}
|
|
1671
|
+
return false;
|
|
1672
|
+
}
|
|
1673
|
+
function isNumericRunSegment(text) {
|
|
1674
|
+
if (text.length === 0)
|
|
1675
|
+
return false;
|
|
1676
|
+
for (const ch of text) {
|
|
1677
|
+
if (decimalDigitRe.test(ch) || numericJoinerChars.has(ch))
|
|
1678
|
+
continue;
|
|
1679
|
+
return false;
|
|
1680
|
+
}
|
|
1681
|
+
return true;
|
|
1682
|
+
}
|
|
1683
|
+
function mergeNumericRuns(segmentation) {
|
|
1684
|
+
const texts = [];
|
|
1685
|
+
const isWordLike = [];
|
|
1686
|
+
const kinds = [];
|
|
1687
|
+
const starts = [];
|
|
1688
|
+
for (let i = 0; i < segmentation.len; i++) {
|
|
1689
|
+
const text = segmentation.texts[i];
|
|
1690
|
+
const kind = segmentation.kinds[i];
|
|
1691
|
+
if (kind === 'text' && isNumericRunSegment(text) && segmentContainsDecimalDigit(text)) {
|
|
1692
|
+
const mergedParts = [text];
|
|
1693
|
+
let j = i + 1;
|
|
1694
|
+
while (j < segmentation.len &&
|
|
1695
|
+
segmentation.kinds[j] === 'text' &&
|
|
1696
|
+
isNumericRunSegment(segmentation.texts[j])) {
|
|
1697
|
+
mergedParts.push(segmentation.texts[j]);
|
|
1698
|
+
j++;
|
|
1699
|
+
}
|
|
1700
|
+
texts.push(joinTextParts(mergedParts));
|
|
1701
|
+
isWordLike.push(true);
|
|
1702
|
+
kinds.push('text');
|
|
1703
|
+
starts.push(segmentation.starts[i]);
|
|
1704
|
+
i = j - 1;
|
|
1705
|
+
continue;
|
|
1706
|
+
}
|
|
1707
|
+
texts.push(text);
|
|
1708
|
+
isWordLike.push(segmentation.isWordLike[i]);
|
|
1709
|
+
kinds.push(kind);
|
|
1710
|
+
starts.push(segmentation.starts[i]);
|
|
1711
|
+
}
|
|
1712
|
+
return {
|
|
1713
|
+
len: texts.length,
|
|
1714
|
+
texts,
|
|
1715
|
+
isWordLike,
|
|
1716
|
+
kinds,
|
|
1717
|
+
starts,
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
function mergeAsciiPunctuationChains(segmentation) {
|
|
1721
|
+
const texts = [];
|
|
1722
|
+
const isWordLike = [];
|
|
1723
|
+
const kinds = [];
|
|
1724
|
+
const starts = [];
|
|
1725
|
+
for (let i = 0; i < segmentation.len; i++) {
|
|
1726
|
+
const text = segmentation.texts[i];
|
|
1727
|
+
const kind = segmentation.kinds[i];
|
|
1728
|
+
const wordLike = segmentation.isWordLike[i];
|
|
1729
|
+
if (kind === 'text' && wordLike && asciiPunctuationChainSegmentRe.test(text)) {
|
|
1730
|
+
const mergedParts = [text];
|
|
1731
|
+
let endsWithJoiners = asciiPunctuationChainTrailingJoinersRe.test(text);
|
|
1732
|
+
let j = i + 1;
|
|
1733
|
+
while (endsWithJoiners &&
|
|
1734
|
+
j < segmentation.len &&
|
|
1735
|
+
segmentation.kinds[j] === 'text' &&
|
|
1736
|
+
segmentation.isWordLike[j] &&
|
|
1737
|
+
asciiPunctuationChainSegmentRe.test(segmentation.texts[j])) {
|
|
1738
|
+
const nextText = segmentation.texts[j];
|
|
1739
|
+
mergedParts.push(nextText);
|
|
1740
|
+
endsWithJoiners = asciiPunctuationChainTrailingJoinersRe.test(nextText);
|
|
1741
|
+
j++;
|
|
1742
|
+
}
|
|
1743
|
+
texts.push(joinTextParts(mergedParts));
|
|
1744
|
+
isWordLike.push(true);
|
|
1745
|
+
kinds.push('text');
|
|
1746
|
+
starts.push(segmentation.starts[i]);
|
|
1747
|
+
i = j - 1;
|
|
1748
|
+
continue;
|
|
1749
|
+
}
|
|
1750
|
+
texts.push(text);
|
|
1751
|
+
isWordLike.push(wordLike);
|
|
1752
|
+
kinds.push(kind);
|
|
1753
|
+
starts.push(segmentation.starts[i]);
|
|
1754
|
+
}
|
|
1755
|
+
return {
|
|
1756
|
+
len: texts.length,
|
|
1757
|
+
texts,
|
|
1758
|
+
isWordLike,
|
|
1759
|
+
kinds,
|
|
1760
|
+
starts,
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
function splitHyphenatedNumericRuns(segmentation) {
|
|
1764
|
+
const texts = [];
|
|
1765
|
+
const isWordLike = [];
|
|
1766
|
+
const kinds = [];
|
|
1767
|
+
const starts = [];
|
|
1768
|
+
for (let i = 0; i < segmentation.len; i++) {
|
|
1769
|
+
const text = segmentation.texts[i];
|
|
1770
|
+
if (segmentation.kinds[i] === 'text' && text.includes('-')) {
|
|
1771
|
+
const parts = text.split('-');
|
|
1772
|
+
let shouldSplit = parts.length > 1;
|
|
1773
|
+
for (let j = 0; j < parts.length; j++) {
|
|
1774
|
+
const part = parts[j];
|
|
1775
|
+
if (!shouldSplit)
|
|
1776
|
+
break;
|
|
1777
|
+
if (part.length === 0 ||
|
|
1778
|
+
!segmentContainsDecimalDigit(part) ||
|
|
1779
|
+
!isNumericRunSegment(part)) {
|
|
1780
|
+
shouldSplit = false;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
if (shouldSplit) {
|
|
1784
|
+
let offset = 0;
|
|
1785
|
+
for (let j = 0; j < parts.length; j++) {
|
|
1786
|
+
const part = parts[j];
|
|
1787
|
+
const splitText = j < parts.length - 1 ? `${part}-` : part;
|
|
1788
|
+
texts.push(splitText);
|
|
1789
|
+
isWordLike.push(true);
|
|
1790
|
+
kinds.push('text');
|
|
1791
|
+
starts.push(segmentation.starts[i] + offset);
|
|
1792
|
+
offset += splitText.length;
|
|
1793
|
+
}
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
texts.push(text);
|
|
1798
|
+
isWordLike.push(segmentation.isWordLike[i]);
|
|
1799
|
+
kinds.push(segmentation.kinds[i]);
|
|
1800
|
+
starts.push(segmentation.starts[i]);
|
|
1801
|
+
}
|
|
1802
|
+
return {
|
|
1803
|
+
len: texts.length,
|
|
1804
|
+
texts,
|
|
1805
|
+
isWordLike,
|
|
1806
|
+
kinds,
|
|
1807
|
+
starts,
|
|
1808
|
+
};
|
|
1809
|
+
}
|
|
1810
|
+
function mergeGlueConnectedTextRuns(segmentation) {
|
|
1811
|
+
const texts = [];
|
|
1812
|
+
const isWordLike = [];
|
|
1813
|
+
const kinds = [];
|
|
1814
|
+
const starts = [];
|
|
1815
|
+
let read = 0;
|
|
1816
|
+
while (read < segmentation.len) {
|
|
1817
|
+
const textParts = [segmentation.texts[read]];
|
|
1818
|
+
let wordLike = segmentation.isWordLike[read];
|
|
1819
|
+
let kind = segmentation.kinds[read];
|
|
1820
|
+
let start = segmentation.starts[read];
|
|
1821
|
+
if (kind === 'glue') {
|
|
1822
|
+
const glueParts = [textParts[0]];
|
|
1823
|
+
const glueStart = start;
|
|
1824
|
+
read++;
|
|
1825
|
+
while (read < segmentation.len && segmentation.kinds[read] === 'glue') {
|
|
1826
|
+
glueParts.push(segmentation.texts[read]);
|
|
1827
|
+
read++;
|
|
1828
|
+
}
|
|
1829
|
+
const glueText = joinTextParts(glueParts);
|
|
1830
|
+
if (read < segmentation.len && segmentation.kinds[read] === 'text') {
|
|
1831
|
+
textParts[0] = glueText;
|
|
1832
|
+
textParts.push(segmentation.texts[read]);
|
|
1833
|
+
wordLike = segmentation.isWordLike[read];
|
|
1834
|
+
kind = 'text';
|
|
1835
|
+
start = glueStart;
|
|
1836
|
+
read++;
|
|
1837
|
+
}
|
|
1838
|
+
else {
|
|
1839
|
+
texts.push(glueText);
|
|
1840
|
+
isWordLike.push(false);
|
|
1841
|
+
kinds.push('glue');
|
|
1842
|
+
starts.push(glueStart);
|
|
1843
|
+
continue;
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
else {
|
|
1847
|
+
read++;
|
|
1848
|
+
}
|
|
1849
|
+
if (kind === 'text') {
|
|
1850
|
+
while (read < segmentation.len && segmentation.kinds[read] === 'glue') {
|
|
1851
|
+
const glueParts = [];
|
|
1852
|
+
while (read < segmentation.len && segmentation.kinds[read] === 'glue') {
|
|
1853
|
+
glueParts.push(segmentation.texts[read]);
|
|
1854
|
+
read++;
|
|
1855
|
+
}
|
|
1856
|
+
const glueText = joinTextParts(glueParts);
|
|
1857
|
+
if (read < segmentation.len && segmentation.kinds[read] === 'text') {
|
|
1858
|
+
textParts.push(glueText, segmentation.texts[read]);
|
|
1859
|
+
wordLike = wordLike || segmentation.isWordLike[read];
|
|
1860
|
+
read++;
|
|
1861
|
+
continue;
|
|
1862
|
+
}
|
|
1863
|
+
textParts.push(glueText);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
texts.push(joinTextParts(textParts));
|
|
1867
|
+
isWordLike.push(wordLike);
|
|
1868
|
+
kinds.push(kind);
|
|
1869
|
+
starts.push(start);
|
|
1870
|
+
}
|
|
1871
|
+
return {
|
|
1872
|
+
len: texts.length,
|
|
1873
|
+
texts,
|
|
1874
|
+
isWordLike,
|
|
1875
|
+
kinds,
|
|
1876
|
+
starts,
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
function carryTrailingForwardStickyAcrossCJKBoundary(segmentation) {
|
|
1880
|
+
const texts = segmentation.texts.slice();
|
|
1881
|
+
const isWordLike = segmentation.isWordLike.slice();
|
|
1882
|
+
const kinds = segmentation.kinds.slice();
|
|
1883
|
+
const starts = segmentation.starts.slice();
|
|
1884
|
+
for (let i = 0; i < texts.length - 1; i++) {
|
|
1885
|
+
if (kinds[i] !== 'text' || kinds[i + 1] !== 'text')
|
|
1886
|
+
continue;
|
|
1887
|
+
if (!isCJK(texts[i]) || !isCJK(texts[i + 1]))
|
|
1888
|
+
continue;
|
|
1889
|
+
const split = splitTrailingForwardStickyCluster(texts[i]);
|
|
1890
|
+
if (split === null)
|
|
1891
|
+
continue;
|
|
1892
|
+
texts[i] = split.head;
|
|
1893
|
+
texts[i + 1] = split.tail + texts[i + 1];
|
|
1894
|
+
starts[i + 1] = starts[i] + split.head.length;
|
|
1895
|
+
}
|
|
1896
|
+
return {
|
|
1897
|
+
len: texts.length,
|
|
1898
|
+
texts,
|
|
1899
|
+
isWordLike,
|
|
1900
|
+
kinds,
|
|
1901
|
+
starts,
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
function buildMergedSegmentation(normalized, profile, whiteSpaceProfile) {
|
|
1905
|
+
const wordSegmenter = getSharedWordSegmenter();
|
|
1906
|
+
let mergedLen = 0;
|
|
1907
|
+
const mergedTexts = [];
|
|
1908
|
+
const mergedTextParts = [];
|
|
1909
|
+
const mergedWordLike = [];
|
|
1910
|
+
const mergedKinds = [];
|
|
1911
|
+
const mergedStarts = [];
|
|
1912
|
+
// Track repeatable single-char punctuation runs structurally so identical
|
|
1913
|
+
// merges stay O(1) instead of re-scanning the accumulated segment each time.
|
|
1914
|
+
const mergedSingleCharRunChars = [];
|
|
1915
|
+
const mergedSingleCharRunLengths = [];
|
|
1916
|
+
const mergedContainsCJK = [];
|
|
1917
|
+
const mergedContainsArabicScript = [];
|
|
1918
|
+
const mergedEndsWithClosingQuote = [];
|
|
1919
|
+
const mergedEndsWithMyanmarMedialGlue = [];
|
|
1920
|
+
const mergedHasArabicNoSpacePunctuation = [];
|
|
1921
|
+
for (const s of wordSegmenter.segment(normalized)) {
|
|
1922
|
+
for (const piece of splitSegmentByBreakKind(s.segment, s.isWordLike ?? false, s.index, whiteSpaceProfile)) {
|
|
1923
|
+
const isText = piece.kind === 'text';
|
|
1924
|
+
const repeatableSingleCharRunChar = getRepeatableSingleCharRunChar(piece.text, piece.isWordLike, piece.kind);
|
|
1925
|
+
const pieceContainsCJK = isCJK(piece.text);
|
|
1926
|
+
const pieceContainsArabicScript = containsArabicScript(piece.text);
|
|
1927
|
+
const pieceLastCodePoint = getLastCodePoint(piece.text);
|
|
1928
|
+
const pieceEndsWithClosingQuote = endsWithClosingQuote(piece.text);
|
|
1929
|
+
const pieceEndsWithMyanmarMedialGlue = endsWithMyanmarMedialGlue(piece.text);
|
|
1930
|
+
const prevIndex = mergedLen - 1;
|
|
1931
|
+
function appendPieceToPrevious() {
|
|
1932
|
+
if (mergedSingleCharRunChars[prevIndex] !== null) {
|
|
1933
|
+
mergedTextParts[prevIndex] = [
|
|
1934
|
+
materializeDeferredSingleCharRun(mergedTexts, mergedSingleCharRunChars, mergedSingleCharRunLengths, prevIndex),
|
|
1935
|
+
];
|
|
1936
|
+
mergedSingleCharRunChars[prevIndex] = null;
|
|
1937
|
+
}
|
|
1938
|
+
mergedTextParts[prevIndex].push(piece.text);
|
|
1939
|
+
mergedWordLike[prevIndex] = mergedWordLike[prevIndex] || piece.isWordLike;
|
|
1940
|
+
mergedContainsCJK[prevIndex] = mergedContainsCJK[prevIndex] || pieceContainsCJK;
|
|
1941
|
+
mergedContainsArabicScript[prevIndex] =
|
|
1942
|
+
mergedContainsArabicScript[prevIndex] || pieceContainsArabicScript;
|
|
1943
|
+
mergedEndsWithClosingQuote[prevIndex] = pieceEndsWithClosingQuote;
|
|
1944
|
+
mergedEndsWithMyanmarMedialGlue[prevIndex] = pieceEndsWithMyanmarMedialGlue;
|
|
1945
|
+
mergedHasArabicNoSpacePunctuation[prevIndex] = hasArabicNoSpacePunctuation(mergedContainsArabicScript[prevIndex], pieceLastCodePoint);
|
|
1946
|
+
}
|
|
1947
|
+
// First-pass keeps: no-space script-specific joins and punctuation glue
|
|
1948
|
+
// that depend on the immediately preceding text run.
|
|
1949
|
+
if (profile.carryCJKAfterClosingQuote &&
|
|
1950
|
+
isText &&
|
|
1951
|
+
mergedLen > 0 &&
|
|
1952
|
+
mergedKinds[prevIndex] === 'text' &&
|
|
1953
|
+
pieceContainsCJK &&
|
|
1954
|
+
mergedContainsCJK[prevIndex] &&
|
|
1955
|
+
mergedEndsWithClosingQuote[prevIndex]) {
|
|
1956
|
+
appendPieceToPrevious();
|
|
1957
|
+
}
|
|
1958
|
+
else if (isText &&
|
|
1959
|
+
mergedLen > 0 &&
|
|
1960
|
+
mergedKinds[prevIndex] === 'text' &&
|
|
1961
|
+
isCJKLineStartProhibitedSegment(piece.text) &&
|
|
1962
|
+
mergedContainsCJK[prevIndex]) {
|
|
1963
|
+
appendPieceToPrevious();
|
|
1964
|
+
}
|
|
1965
|
+
else if (isText &&
|
|
1966
|
+
mergedLen > 0 &&
|
|
1967
|
+
mergedKinds[prevIndex] === 'text' &&
|
|
1968
|
+
mergedEndsWithMyanmarMedialGlue[prevIndex]) {
|
|
1969
|
+
appendPieceToPrevious();
|
|
1970
|
+
}
|
|
1971
|
+
else if (isText &&
|
|
1972
|
+
mergedLen > 0 &&
|
|
1973
|
+
mergedKinds[prevIndex] === 'text' &&
|
|
1974
|
+
piece.isWordLike &&
|
|
1975
|
+
pieceContainsArabicScript &&
|
|
1976
|
+
mergedHasArabicNoSpacePunctuation[prevIndex]) {
|
|
1977
|
+
appendPieceToPrevious();
|
|
1978
|
+
mergedWordLike[prevIndex] = true;
|
|
1979
|
+
}
|
|
1980
|
+
else if (repeatableSingleCharRunChar !== null &&
|
|
1981
|
+
mergedLen > 0 &&
|
|
1982
|
+
mergedKinds[prevIndex] === 'text' &&
|
|
1983
|
+
mergedSingleCharRunChars[prevIndex] === repeatableSingleCharRunChar) {
|
|
1984
|
+
mergedSingleCharRunLengths[prevIndex] = (mergedSingleCharRunLengths[prevIndex] ?? 1) + 1;
|
|
1985
|
+
}
|
|
1986
|
+
else if (isText &&
|
|
1987
|
+
!piece.isWordLike &&
|
|
1988
|
+
mergedLen > 0 &&
|
|
1989
|
+
mergedKinds[prevIndex] === 'text' &&
|
|
1990
|
+
!mergedContainsCJK[prevIndex] &&
|
|
1991
|
+
(isLeftStickyPunctuationSegment(piece.text) ||
|
|
1992
|
+
(piece.text === '-' && mergedWordLike[prevIndex]))) {
|
|
1993
|
+
appendPieceToPrevious();
|
|
1994
|
+
}
|
|
1995
|
+
else {
|
|
1996
|
+
mergedTexts[mergedLen] = piece.text;
|
|
1997
|
+
mergedTextParts[mergedLen] = [piece.text];
|
|
1998
|
+
mergedWordLike[mergedLen] = piece.isWordLike;
|
|
1999
|
+
mergedKinds[mergedLen] = piece.kind;
|
|
2000
|
+
mergedStarts[mergedLen] = piece.start;
|
|
2001
|
+
mergedSingleCharRunChars[mergedLen] = repeatableSingleCharRunChar;
|
|
2002
|
+
mergedSingleCharRunLengths[mergedLen] = repeatableSingleCharRunChar === null ? 0 : 1;
|
|
2003
|
+
mergedContainsCJK[mergedLen] = pieceContainsCJK;
|
|
2004
|
+
mergedContainsArabicScript[mergedLen] = pieceContainsArabicScript;
|
|
2005
|
+
mergedEndsWithClosingQuote[mergedLen] = pieceEndsWithClosingQuote;
|
|
2006
|
+
mergedEndsWithMyanmarMedialGlue[mergedLen] = pieceEndsWithMyanmarMedialGlue;
|
|
2007
|
+
mergedHasArabicNoSpacePunctuation[mergedLen] = hasArabicNoSpacePunctuation(pieceContainsArabicScript, pieceLastCodePoint);
|
|
2008
|
+
mergedLen++;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
for (let i = 0; i < mergedLen; i++) {
|
|
2013
|
+
if (mergedSingleCharRunChars[i] !== null) {
|
|
2014
|
+
mergedTexts[i] = materializeDeferredSingleCharRun(mergedTexts, mergedSingleCharRunChars, mergedSingleCharRunLengths, i);
|
|
2015
|
+
continue;
|
|
2016
|
+
}
|
|
2017
|
+
mergedTexts[i] = joinTextParts(mergedTextParts[i]);
|
|
2018
|
+
}
|
|
2019
|
+
// Later passes operate on the merged text stream itself: contextual escaped
|
|
2020
|
+
// quote glue, forward-sticky carry, compaction, then the broader URL/numeric
|
|
2021
|
+
// and Arabic-leading-mark fixes.
|
|
2022
|
+
for (let i = 1; i < mergedLen; i++) {
|
|
2023
|
+
if (mergedKinds[i] === 'text' &&
|
|
2024
|
+
!mergedWordLike[i] &&
|
|
2025
|
+
isEscapedQuoteClusterSegment(mergedTexts[i]) &&
|
|
2026
|
+
mergedKinds[i - 1] === 'text' &&
|
|
2027
|
+
!mergedContainsCJK[i - 1]) {
|
|
2028
|
+
mergedTexts[i - 1] += mergedTexts[i];
|
|
2029
|
+
mergedWordLike[i - 1] = mergedWordLike[i - 1] || mergedWordLike[i];
|
|
2030
|
+
mergedTexts[i] = '';
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
const forwardStickyPrefixParts = Array.from({ length: mergedLen }, () => null);
|
|
2034
|
+
let nextLiveIndex = -1;
|
|
2035
|
+
for (let i = mergedLen - 1; i >= 0; i--) {
|
|
2036
|
+
const text = mergedTexts[i];
|
|
2037
|
+
if (text.length === 0)
|
|
2038
|
+
continue;
|
|
2039
|
+
if (mergedKinds[i] === 'text' &&
|
|
2040
|
+
!mergedWordLike[i] &&
|
|
2041
|
+
isForwardStickyClusterSegment(text) &&
|
|
2042
|
+
nextLiveIndex >= 0 &&
|
|
2043
|
+
mergedKinds[nextLiveIndex] === 'text') {
|
|
2044
|
+
const prefixParts = forwardStickyPrefixParts[nextLiveIndex] ?? [];
|
|
2045
|
+
prefixParts.push(text);
|
|
2046
|
+
forwardStickyPrefixParts[nextLiveIndex] = prefixParts;
|
|
2047
|
+
mergedStarts[nextLiveIndex] = mergedStarts[i];
|
|
2048
|
+
mergedTexts[i] = '';
|
|
2049
|
+
continue;
|
|
2050
|
+
}
|
|
2051
|
+
nextLiveIndex = i;
|
|
2052
|
+
}
|
|
2053
|
+
for (let i = 0; i < mergedLen; i++) {
|
|
2054
|
+
const prefixParts = forwardStickyPrefixParts[i];
|
|
2055
|
+
if (prefixParts == null)
|
|
2056
|
+
continue;
|
|
2057
|
+
mergedTexts[i] = joinReversedPrefixParts(prefixParts, mergedTexts[i]);
|
|
2058
|
+
}
|
|
2059
|
+
let compactLen = 0;
|
|
2060
|
+
for (let read = 0; read < mergedLen; read++) {
|
|
2061
|
+
const text = mergedTexts[read];
|
|
2062
|
+
if (text.length === 0)
|
|
2063
|
+
continue;
|
|
2064
|
+
if (compactLen !== read) {
|
|
2065
|
+
mergedTexts[compactLen] = text;
|
|
2066
|
+
mergedWordLike[compactLen] = mergedWordLike[read];
|
|
2067
|
+
mergedKinds[compactLen] = mergedKinds[read];
|
|
2068
|
+
mergedStarts[compactLen] = mergedStarts[read];
|
|
2069
|
+
}
|
|
2070
|
+
compactLen++;
|
|
2071
|
+
}
|
|
2072
|
+
mergedTexts.length = compactLen;
|
|
2073
|
+
mergedWordLike.length = compactLen;
|
|
2074
|
+
mergedKinds.length = compactLen;
|
|
2075
|
+
mergedStarts.length = compactLen;
|
|
2076
|
+
const compacted = mergeGlueConnectedTextRuns({
|
|
2077
|
+
len: compactLen,
|
|
2078
|
+
texts: mergedTexts,
|
|
2079
|
+
isWordLike: mergedWordLike,
|
|
2080
|
+
kinds: mergedKinds,
|
|
2081
|
+
starts: mergedStarts,
|
|
2082
|
+
});
|
|
2083
|
+
const withMergedUrls = carryTrailingForwardStickyAcrossCJKBoundary(mergeAsciiPunctuationChains(splitHyphenatedNumericRuns(mergeNumericRuns(mergeUrlQueryRuns(mergeUrlLikeRuns(compacted))))));
|
|
2084
|
+
for (let i = 0; i < withMergedUrls.len - 1; i++) {
|
|
2085
|
+
const split = splitLeadingSpaceAndMarks(withMergedUrls.texts[i]);
|
|
2086
|
+
if (split === null)
|
|
2087
|
+
continue;
|
|
2088
|
+
if ((withMergedUrls.kinds[i] !== 'space' && withMergedUrls.kinds[i] !== 'preserved-space') ||
|
|
2089
|
+
withMergedUrls.kinds[i + 1] !== 'text' ||
|
|
2090
|
+
!containsArabicScript(withMergedUrls.texts[i + 1])) {
|
|
2091
|
+
continue;
|
|
2092
|
+
}
|
|
2093
|
+
withMergedUrls.texts[i] = split.space;
|
|
2094
|
+
withMergedUrls.isWordLike[i] = false;
|
|
2095
|
+
withMergedUrls.kinds[i] = withMergedUrls.kinds[i] === 'preserved-space' ? 'preserved-space' : 'space';
|
|
2096
|
+
withMergedUrls.texts[i + 1] = split.marks + withMergedUrls.texts[i + 1];
|
|
2097
|
+
withMergedUrls.starts[i + 1] = withMergedUrls.starts[i] + split.space.length;
|
|
2098
|
+
}
|
|
2099
|
+
return withMergedUrls;
|
|
2100
|
+
}
|
|
2101
|
+
function compileAnalysisChunks(segmentation, whiteSpaceProfile) {
|
|
2102
|
+
if (segmentation.len === 0)
|
|
2103
|
+
return [];
|
|
2104
|
+
if (!whiteSpaceProfile.preserveHardBreaks) {
|
|
2105
|
+
return [{
|
|
2106
|
+
startSegmentIndex: 0,
|
|
2107
|
+
endSegmentIndex: segmentation.len,
|
|
2108
|
+
consumedEndSegmentIndex: segmentation.len,
|
|
2109
|
+
}];
|
|
2110
|
+
}
|
|
2111
|
+
const chunks = [];
|
|
2112
|
+
let startSegmentIndex = 0;
|
|
2113
|
+
for (let i = 0; i < segmentation.len; i++) {
|
|
2114
|
+
if (segmentation.kinds[i] !== 'hard-break')
|
|
2115
|
+
continue;
|
|
2116
|
+
chunks.push({
|
|
2117
|
+
startSegmentIndex,
|
|
2118
|
+
endSegmentIndex: i,
|
|
2119
|
+
consumedEndSegmentIndex: i + 1,
|
|
2120
|
+
});
|
|
2121
|
+
startSegmentIndex = i + 1;
|
|
2122
|
+
}
|
|
2123
|
+
if (startSegmentIndex < segmentation.len) {
|
|
2124
|
+
chunks.push({
|
|
2125
|
+
startSegmentIndex,
|
|
2126
|
+
endSegmentIndex: segmentation.len,
|
|
2127
|
+
consumedEndSegmentIndex: segmentation.len,
|
|
2128
|
+
});
|
|
2129
|
+
}
|
|
2130
|
+
return chunks;
|
|
2131
|
+
}
|
|
2132
|
+
function mergeKeepAllTextSegments(segmentation) {
|
|
2133
|
+
if (segmentation.len <= 1)
|
|
2134
|
+
return segmentation;
|
|
2135
|
+
const texts = [];
|
|
2136
|
+
const isWordLike = [];
|
|
2137
|
+
const kinds = [];
|
|
2138
|
+
const starts = [];
|
|
2139
|
+
let pendingTextParts = null;
|
|
2140
|
+
let pendingWordLike = false;
|
|
2141
|
+
let pendingStart = 0;
|
|
2142
|
+
let pendingContainsCJK = false;
|
|
2143
|
+
let pendingCanContinue = false;
|
|
2144
|
+
function flushPendingText() {
|
|
2145
|
+
if (pendingTextParts === null)
|
|
2146
|
+
return;
|
|
2147
|
+
texts.push(joinTextParts(pendingTextParts));
|
|
2148
|
+
isWordLike.push(pendingWordLike);
|
|
2149
|
+
kinds.push('text');
|
|
2150
|
+
starts.push(pendingStart);
|
|
2151
|
+
pendingTextParts = null;
|
|
2152
|
+
}
|
|
2153
|
+
for (let i = 0; i < segmentation.len; i++) {
|
|
2154
|
+
const text = segmentation.texts[i];
|
|
2155
|
+
const kind = segmentation.kinds[i];
|
|
2156
|
+
const wordLike = segmentation.isWordLike[i];
|
|
2157
|
+
const start = segmentation.starts[i];
|
|
2158
|
+
if (kind === 'text') {
|
|
2159
|
+
const textContainsCJK = containsCJKText(text);
|
|
2160
|
+
const textCanContinue = canContinueKeepAllTextRun(text);
|
|
2161
|
+
if (pendingTextParts !== null && pendingContainsCJK && pendingCanContinue) {
|
|
2162
|
+
pendingTextParts.push(text);
|
|
2163
|
+
pendingWordLike = pendingWordLike || wordLike;
|
|
2164
|
+
pendingContainsCJK = pendingContainsCJK || textContainsCJK;
|
|
2165
|
+
pendingCanContinue = textCanContinue;
|
|
2166
|
+
continue;
|
|
2167
|
+
}
|
|
2168
|
+
flushPendingText();
|
|
2169
|
+
pendingTextParts = [text];
|
|
2170
|
+
pendingWordLike = wordLike;
|
|
2171
|
+
pendingStart = start;
|
|
2172
|
+
pendingContainsCJK = textContainsCJK;
|
|
2173
|
+
pendingCanContinue = textCanContinue;
|
|
2174
|
+
continue;
|
|
2175
|
+
}
|
|
2176
|
+
flushPendingText();
|
|
2177
|
+
texts.push(text);
|
|
2178
|
+
isWordLike.push(wordLike);
|
|
2179
|
+
kinds.push(kind);
|
|
2180
|
+
starts.push(start);
|
|
2181
|
+
}
|
|
2182
|
+
flushPendingText();
|
|
2183
|
+
return {
|
|
2184
|
+
len: texts.length,
|
|
2185
|
+
texts,
|
|
2186
|
+
isWordLike,
|
|
2187
|
+
kinds,
|
|
2188
|
+
starts,
|
|
2189
|
+
};
|
|
2190
|
+
}
|
|
2191
|
+
function analyzeText(text, profile, whiteSpace = 'normal', wordBreak = 'normal') {
|
|
2192
|
+
const whiteSpaceProfile = getWhiteSpaceProfile(whiteSpace);
|
|
2193
|
+
const normalized = whiteSpaceProfile.mode === 'pre-wrap'
|
|
2194
|
+
? normalizeWhitespacePreWrap(text)
|
|
2195
|
+
: normalizeWhitespaceNormal(text);
|
|
2196
|
+
if (normalized.length === 0) {
|
|
2197
|
+
return {
|
|
2198
|
+
normalized,
|
|
2199
|
+
chunks: [],
|
|
2200
|
+
len: 0,
|
|
2201
|
+
texts: [],
|
|
2202
|
+
isWordLike: [],
|
|
2203
|
+
kinds: [],
|
|
2204
|
+
starts: [],
|
|
2205
|
+
};
|
|
2206
|
+
}
|
|
2207
|
+
const segmentation = wordBreak === 'keep-all'
|
|
2208
|
+
? mergeKeepAllTextSegments(buildMergedSegmentation(normalized, profile, whiteSpaceProfile))
|
|
2209
|
+
: buildMergedSegmentation(normalized, profile, whiteSpaceProfile);
|
|
2210
|
+
return {
|
|
2211
|
+
normalized,
|
|
2212
|
+
chunks: compileAnalysisChunks(segmentation, whiteSpaceProfile),
|
|
2213
|
+
...segmentation,
|
|
2214
|
+
};
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
let measureContext = null;
|
|
2218
|
+
const segmentMetricCaches = new Map();
|
|
2219
|
+
let cachedEngineProfile = null;
|
|
2220
|
+
// Safari's prefix-fit policy is useful for ordinary word-sized runs, but letting
|
|
2221
|
+
// it measure every growing prefix of a giant segment recreates a pathological
|
|
2222
|
+
// superlinear prepare-time path. Past this size, switch to the cheaper
|
|
2223
|
+
// pair-context model and keep the public behavior linear.
|
|
2224
|
+
const MAX_PREFIX_FIT_GRAPHEMES = 96;
|
|
2225
|
+
const emojiPresentationRe = /\p{Emoji_Presentation}/u;
|
|
2226
|
+
const maybeEmojiRe = /[\p{Emoji_Presentation}\p{Extended_Pictographic}\p{Regional_Indicator}\uFE0F\u20E3]/u;
|
|
2227
|
+
let sharedGraphemeSegmenter$1 = null;
|
|
2228
|
+
const emojiCorrectionCache = new Map();
|
|
2229
|
+
function getMeasureContext() {
|
|
2230
|
+
if (measureContext !== null)
|
|
2231
|
+
return measureContext;
|
|
2232
|
+
if (typeof OffscreenCanvas !== 'undefined') {
|
|
2233
|
+
measureContext = new OffscreenCanvas(1, 1).getContext('2d');
|
|
2234
|
+
return measureContext;
|
|
2235
|
+
}
|
|
2236
|
+
if (typeof document !== 'undefined') {
|
|
2237
|
+
measureContext = document.createElement('canvas').getContext('2d');
|
|
2238
|
+
return measureContext;
|
|
2239
|
+
}
|
|
2240
|
+
throw new Error('Text measurement requires OffscreenCanvas or a DOM canvas context.');
|
|
2241
|
+
}
|
|
2242
|
+
function getSegmentMetricCache(font) {
|
|
2243
|
+
let cache = segmentMetricCaches.get(font);
|
|
2244
|
+
if (!cache) {
|
|
2245
|
+
cache = new Map();
|
|
2246
|
+
segmentMetricCaches.set(font, cache);
|
|
2247
|
+
}
|
|
2248
|
+
return cache;
|
|
2249
|
+
}
|
|
2250
|
+
function getSegmentMetrics(seg, cache) {
|
|
2251
|
+
let metrics = cache.get(seg);
|
|
2252
|
+
if (metrics === undefined) {
|
|
2253
|
+
const ctx = getMeasureContext();
|
|
2254
|
+
metrics = {
|
|
2255
|
+
width: ctx.measureText(seg).width,
|
|
2256
|
+
containsCJK: isCJK(seg),
|
|
2257
|
+
};
|
|
2258
|
+
cache.set(seg, metrics);
|
|
2259
|
+
}
|
|
2260
|
+
return metrics;
|
|
2261
|
+
}
|
|
2262
|
+
function getEngineProfile() {
|
|
2263
|
+
if (cachedEngineProfile !== null)
|
|
2264
|
+
return cachedEngineProfile;
|
|
2265
|
+
if (typeof navigator === 'undefined') {
|
|
2266
|
+
cachedEngineProfile = {
|
|
2267
|
+
lineFitEpsilon: 0.005,
|
|
2268
|
+
carryCJKAfterClosingQuote: false,
|
|
2269
|
+
preferPrefixWidthsForBreakableRuns: false,
|
|
2270
|
+
preferEarlySoftHyphenBreak: false,
|
|
2271
|
+
};
|
|
2272
|
+
return cachedEngineProfile;
|
|
2273
|
+
}
|
|
2274
|
+
const ua = navigator.userAgent;
|
|
2275
|
+
const vendor = navigator.vendor;
|
|
2276
|
+
const isSafari = vendor === 'Apple Computer, Inc.' &&
|
|
2277
|
+
ua.includes('Safari/') &&
|
|
2278
|
+
!ua.includes('Chrome/') &&
|
|
2279
|
+
!ua.includes('Chromium/') &&
|
|
2280
|
+
!ua.includes('CriOS/') &&
|
|
2281
|
+
!ua.includes('FxiOS/') &&
|
|
2282
|
+
!ua.includes('EdgiOS/');
|
|
2283
|
+
const isChromium = ua.includes('Chrome/') ||
|
|
2284
|
+
ua.includes('Chromium/') ||
|
|
2285
|
+
ua.includes('CriOS/') ||
|
|
2286
|
+
ua.includes('Edg/');
|
|
2287
|
+
cachedEngineProfile = {
|
|
2288
|
+
lineFitEpsilon: isSafari ? 1 / 64 : 0.005,
|
|
2289
|
+
carryCJKAfterClosingQuote: isChromium,
|
|
2290
|
+
preferPrefixWidthsForBreakableRuns: isSafari,
|
|
2291
|
+
preferEarlySoftHyphenBreak: isSafari,
|
|
2292
|
+
};
|
|
2293
|
+
return cachedEngineProfile;
|
|
2294
|
+
}
|
|
2295
|
+
function parseFontSize(font) {
|
|
2296
|
+
const m = font.match(/(\d+(?:\.\d+)?)\s*px/);
|
|
2297
|
+
return m ? parseFloat(m[1]) : 16;
|
|
2298
|
+
}
|
|
2299
|
+
function getSharedGraphemeSegmenter$1() {
|
|
2300
|
+
if (sharedGraphemeSegmenter$1 === null) {
|
|
2301
|
+
sharedGraphemeSegmenter$1 = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
2302
|
+
}
|
|
2303
|
+
return sharedGraphemeSegmenter$1;
|
|
2304
|
+
}
|
|
2305
|
+
function isEmojiGrapheme(g) {
|
|
2306
|
+
return emojiPresentationRe.test(g) || g.includes('\uFE0F');
|
|
2307
|
+
}
|
|
2308
|
+
function textMayContainEmoji(text) {
|
|
2309
|
+
return maybeEmojiRe.test(text);
|
|
2310
|
+
}
|
|
2311
|
+
function getEmojiCorrection(font, fontSize) {
|
|
2312
|
+
let correction = emojiCorrectionCache.get(font);
|
|
2313
|
+
if (correction !== undefined)
|
|
2314
|
+
return correction;
|
|
2315
|
+
const ctx = getMeasureContext();
|
|
2316
|
+
ctx.font = font;
|
|
2317
|
+
const canvasW = ctx.measureText('\u{1F600}').width;
|
|
2318
|
+
correction = 0;
|
|
2319
|
+
if (canvasW > fontSize + 0.5 &&
|
|
2320
|
+
typeof document !== 'undefined' &&
|
|
2321
|
+
document.body !== null) {
|
|
2322
|
+
const span = document.createElement('span');
|
|
2323
|
+
span.style.font = font;
|
|
2324
|
+
span.style.display = 'inline-block';
|
|
2325
|
+
span.style.visibility = 'hidden';
|
|
2326
|
+
span.style.position = 'absolute';
|
|
2327
|
+
span.textContent = '\u{1F600}';
|
|
2328
|
+
document.body.appendChild(span);
|
|
2329
|
+
const domW = span.getBoundingClientRect().width;
|
|
2330
|
+
document.body.removeChild(span);
|
|
2331
|
+
if (canvasW - domW > 0.5) {
|
|
2332
|
+
correction = canvasW - domW;
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
emojiCorrectionCache.set(font, correction);
|
|
2336
|
+
return correction;
|
|
2337
|
+
}
|
|
2338
|
+
function countEmojiGraphemes(text) {
|
|
2339
|
+
let count = 0;
|
|
2340
|
+
const graphemeSegmenter = getSharedGraphemeSegmenter$1();
|
|
2341
|
+
for (const g of graphemeSegmenter.segment(text)) {
|
|
2342
|
+
if (isEmojiGrapheme(g.segment))
|
|
2343
|
+
count++;
|
|
2344
|
+
}
|
|
2345
|
+
return count;
|
|
2346
|
+
}
|
|
2347
|
+
function getEmojiCount(seg, metrics) {
|
|
2348
|
+
if (metrics.emojiCount === undefined) {
|
|
2349
|
+
metrics.emojiCount = countEmojiGraphemes(seg);
|
|
2350
|
+
}
|
|
2351
|
+
return metrics.emojiCount;
|
|
2352
|
+
}
|
|
2353
|
+
function getCorrectedSegmentWidth(seg, metrics, emojiCorrection) {
|
|
2354
|
+
if (emojiCorrection === 0)
|
|
2355
|
+
return metrics.width;
|
|
2356
|
+
return metrics.width - getEmojiCount(seg, metrics) * emojiCorrection;
|
|
2357
|
+
}
|
|
2358
|
+
function getSegmentBreakableFitAdvances(seg, metrics, cache, emojiCorrection, mode) {
|
|
2359
|
+
if (metrics.breakableFitAdvances !== undefined && metrics.breakableFitMode === mode) {
|
|
2360
|
+
return metrics.breakableFitAdvances;
|
|
2361
|
+
}
|
|
2362
|
+
metrics.breakableFitMode = mode;
|
|
2363
|
+
const graphemeSegmenter = getSharedGraphemeSegmenter$1();
|
|
2364
|
+
const graphemes = [];
|
|
2365
|
+
for (const gs of graphemeSegmenter.segment(seg)) {
|
|
2366
|
+
graphemes.push(gs.segment);
|
|
2367
|
+
}
|
|
2368
|
+
if (graphemes.length <= 1) {
|
|
2369
|
+
metrics.breakableFitAdvances = null;
|
|
2370
|
+
return metrics.breakableFitAdvances;
|
|
2371
|
+
}
|
|
2372
|
+
if (mode === 'sum-graphemes') {
|
|
2373
|
+
const advances = [];
|
|
2374
|
+
for (const grapheme of graphemes) {
|
|
2375
|
+
const graphemeMetrics = getSegmentMetrics(grapheme, cache);
|
|
2376
|
+
advances.push(getCorrectedSegmentWidth(grapheme, graphemeMetrics, emojiCorrection));
|
|
2377
|
+
}
|
|
2378
|
+
metrics.breakableFitAdvances = advances;
|
|
2379
|
+
return metrics.breakableFitAdvances;
|
|
2380
|
+
}
|
|
2381
|
+
if (mode === 'pair-context' || graphemes.length > MAX_PREFIX_FIT_GRAPHEMES) {
|
|
2382
|
+
const advances = [];
|
|
2383
|
+
let previousGrapheme = null;
|
|
2384
|
+
let previousWidth = 0;
|
|
2385
|
+
for (const grapheme of graphemes) {
|
|
2386
|
+
const graphemeMetrics = getSegmentMetrics(grapheme, cache);
|
|
2387
|
+
const currentWidth = getCorrectedSegmentWidth(grapheme, graphemeMetrics, emojiCorrection);
|
|
2388
|
+
if (previousGrapheme === null) {
|
|
2389
|
+
advances.push(currentWidth);
|
|
2390
|
+
}
|
|
2391
|
+
else {
|
|
2392
|
+
const pair = previousGrapheme + grapheme;
|
|
2393
|
+
const pairMetrics = getSegmentMetrics(pair, cache);
|
|
2394
|
+
advances.push(getCorrectedSegmentWidth(pair, pairMetrics, emojiCorrection) - previousWidth);
|
|
2395
|
+
}
|
|
2396
|
+
previousGrapheme = grapheme;
|
|
2397
|
+
previousWidth = currentWidth;
|
|
2398
|
+
}
|
|
2399
|
+
metrics.breakableFitAdvances = advances;
|
|
2400
|
+
return metrics.breakableFitAdvances;
|
|
2401
|
+
}
|
|
2402
|
+
const advances = [];
|
|
2403
|
+
let prefix = '';
|
|
2404
|
+
let prefixWidth = 0;
|
|
2405
|
+
for (const grapheme of graphemes) {
|
|
2406
|
+
prefix += grapheme;
|
|
2407
|
+
const prefixMetrics = getSegmentMetrics(prefix, cache);
|
|
2408
|
+
const nextPrefixWidth = getCorrectedSegmentWidth(prefix, prefixMetrics, emojiCorrection);
|
|
2409
|
+
advances.push(nextPrefixWidth - prefixWidth);
|
|
2410
|
+
prefixWidth = nextPrefixWidth;
|
|
2411
|
+
}
|
|
2412
|
+
metrics.breakableFitAdvances = advances;
|
|
2413
|
+
return metrics.breakableFitAdvances;
|
|
2414
|
+
}
|
|
2415
|
+
function getFontMeasurementState(font, needsEmojiCorrection) {
|
|
2416
|
+
const ctx = getMeasureContext();
|
|
2417
|
+
ctx.font = font;
|
|
2418
|
+
const cache = getSegmentMetricCache(font);
|
|
2419
|
+
const fontSize = parseFontSize(font);
|
|
2420
|
+
const emojiCorrection = needsEmojiCorrection ? getEmojiCorrection(font, fontSize) : 0;
|
|
2421
|
+
return { cache, fontSize, emojiCorrection };
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
function consumesAtLineStart(kind) {
|
|
2425
|
+
return kind === 'space' || kind === 'zero-width-break' || kind === 'soft-hyphen';
|
|
2426
|
+
}
|
|
2427
|
+
function breaksAfter(kind) {
|
|
2428
|
+
return (kind === 'space' ||
|
|
2429
|
+
kind === 'preserved-space' ||
|
|
2430
|
+
kind === 'tab' ||
|
|
2431
|
+
kind === 'zero-width-break' ||
|
|
2432
|
+
kind === 'soft-hyphen');
|
|
2433
|
+
}
|
|
2434
|
+
function normalizeLineStartSegmentIndex(prepared, segmentIndex, endSegmentIndex = prepared.widths.length) {
|
|
2435
|
+
while (segmentIndex < endSegmentIndex) {
|
|
2436
|
+
const kind = prepared.kinds[segmentIndex];
|
|
2437
|
+
if (!consumesAtLineStart(kind))
|
|
2438
|
+
break;
|
|
2439
|
+
segmentIndex++;
|
|
2440
|
+
}
|
|
2441
|
+
return segmentIndex;
|
|
2442
|
+
}
|
|
2443
|
+
function getTabAdvance(lineWidth, tabStopAdvance) {
|
|
2444
|
+
if (tabStopAdvance <= 0)
|
|
2445
|
+
return 0;
|
|
2446
|
+
const remainder = lineWidth % tabStopAdvance;
|
|
2447
|
+
if (Math.abs(remainder) <= 1e-6)
|
|
2448
|
+
return tabStopAdvance;
|
|
2449
|
+
return tabStopAdvance - remainder;
|
|
2450
|
+
}
|
|
2451
|
+
function getLeadingLetterSpacing(prepared, hasContent, segmentIndex) {
|
|
2452
|
+
return (prepared.letterSpacing !== 0 &&
|
|
2453
|
+
hasContent &&
|
|
2454
|
+
prepared.spacingGraphemeCounts[segmentIndex] > 0)
|
|
2455
|
+
? prepared.letterSpacing
|
|
2456
|
+
: 0;
|
|
2457
|
+
}
|
|
2458
|
+
function getLineEndContribution(leadingSpacing, segmentContribution) {
|
|
2459
|
+
return segmentContribution === 0 ? 0 : leadingSpacing + segmentContribution;
|
|
2460
|
+
}
|
|
2461
|
+
function getTabTrailingLetterSpacing(prepared, segmentIndex) {
|
|
2462
|
+
return (prepared.letterSpacing !== 0 &&
|
|
2463
|
+
prepared.spacingGraphemeCounts[segmentIndex] > 0)
|
|
2464
|
+
? prepared.letterSpacing
|
|
2465
|
+
: 0;
|
|
2466
|
+
}
|
|
2467
|
+
function getWholeSegmentFitContribution(prepared, kind, segmentIndex, leadingSpacing, segmentWidth) {
|
|
2468
|
+
const segmentContribution = kind === 'tab'
|
|
2469
|
+
? segmentWidth + getTabTrailingLetterSpacing(prepared, segmentIndex)
|
|
2470
|
+
: prepared.lineEndFitAdvances[segmentIndex];
|
|
2471
|
+
return getLineEndContribution(leadingSpacing, segmentContribution);
|
|
2472
|
+
}
|
|
2473
|
+
function getBreakOpportunityFitContribution(prepared, kind, segmentIndex, leadingSpacing) {
|
|
2474
|
+
const segmentContribution = kind === 'tab' ? 0 : prepared.lineEndFitAdvances[segmentIndex];
|
|
2475
|
+
return getLineEndContribution(leadingSpacing, segmentContribution);
|
|
2476
|
+
}
|
|
2477
|
+
function getLineEndPaintContribution(prepared, kind, segmentIndex, leadingSpacing, segmentWidth) {
|
|
2478
|
+
const segmentContribution = kind === 'tab' ? segmentWidth : prepared.lineEndPaintAdvances[segmentIndex];
|
|
2479
|
+
return getLineEndContribution(leadingSpacing, segmentContribution);
|
|
2480
|
+
}
|
|
2481
|
+
function getBreakableGraphemeAdvance(prepared, hasContent, baseAdvance) {
|
|
2482
|
+
return prepared.letterSpacing !== 0 && hasContent
|
|
2483
|
+
? baseAdvance + prepared.letterSpacing
|
|
2484
|
+
: baseAdvance;
|
|
2485
|
+
}
|
|
2486
|
+
function getBreakableCandidateFitWidth(prepared, candidatePaintWidth) {
|
|
2487
|
+
return prepared.letterSpacing === 0
|
|
2488
|
+
? candidatePaintWidth
|
|
2489
|
+
: candidatePaintWidth + prepared.letterSpacing;
|
|
2490
|
+
}
|
|
2491
|
+
function fitSoftHyphenBreak(graphemeFitAdvances, initialWidth, maxWidth, lineFitEpsilon, discretionaryHyphenWidth, letterSpacing) {
|
|
2492
|
+
let fitCount = 0;
|
|
2493
|
+
let fittedWidth = initialWidth;
|
|
2494
|
+
while (fitCount < graphemeFitAdvances.length) {
|
|
2495
|
+
const nextWidth = fittedWidth + graphemeFitAdvances[fitCount] + letterSpacing;
|
|
2496
|
+
const nextLineWidth = fitCount + 1 < graphemeFitAdvances.length
|
|
2497
|
+
? nextWidth + discretionaryHyphenWidth
|
|
2498
|
+
: nextWidth;
|
|
2499
|
+
if (nextLineWidth > maxWidth + lineFitEpsilon)
|
|
2500
|
+
break;
|
|
2501
|
+
fittedWidth = nextWidth;
|
|
2502
|
+
fitCount++;
|
|
2503
|
+
}
|
|
2504
|
+
return { fitCount, fittedWidth };
|
|
2505
|
+
}
|
|
2506
|
+
function countPreparedLines(prepared, maxWidth) {
|
|
2507
|
+
return walkPreparedLinesRaw(prepared, maxWidth);
|
|
2508
|
+
}
|
|
2509
|
+
function walkPreparedLinesSimple(prepared, maxWidth, onLine) {
|
|
2510
|
+
const { widths, kinds, breakableFitAdvances } = prepared;
|
|
2511
|
+
if (widths.length === 0)
|
|
2512
|
+
return 0;
|
|
2513
|
+
const engineProfile = getEngineProfile();
|
|
2514
|
+
const lineFitEpsilon = engineProfile.lineFitEpsilon;
|
|
2515
|
+
const fitLimit = maxWidth + lineFitEpsilon;
|
|
2516
|
+
let lineCount = 0;
|
|
2517
|
+
let lineW = 0;
|
|
2518
|
+
let hasContent = false;
|
|
2519
|
+
let lineEndSegmentIndex = 0;
|
|
2520
|
+
let lineEndGraphemeIndex = 0;
|
|
2521
|
+
let pendingBreakSegmentIndex = -1;
|
|
2522
|
+
let pendingBreakPaintWidth = 0;
|
|
2523
|
+
function clearPendingBreak() {
|
|
2524
|
+
pendingBreakSegmentIndex = -1;
|
|
2525
|
+
pendingBreakPaintWidth = 0;
|
|
2526
|
+
}
|
|
2527
|
+
function emitCurrentLine(endSegmentIndex = lineEndSegmentIndex, endGraphemeIndex = lineEndGraphemeIndex, width = lineW) {
|
|
2528
|
+
lineCount++;
|
|
2529
|
+
lineW = 0;
|
|
2530
|
+
hasContent = false;
|
|
2531
|
+
clearPendingBreak();
|
|
2532
|
+
}
|
|
2533
|
+
function startLineAtSegment(segmentIndex, width) {
|
|
2534
|
+
hasContent = true;
|
|
2535
|
+
lineEndSegmentIndex = segmentIndex + 1;
|
|
2536
|
+
lineEndGraphemeIndex = 0;
|
|
2537
|
+
lineW = width;
|
|
2538
|
+
}
|
|
2539
|
+
function startLineAtGrapheme(segmentIndex, graphemeIndex, width) {
|
|
2540
|
+
hasContent = true;
|
|
2541
|
+
lineEndSegmentIndex = segmentIndex;
|
|
2542
|
+
lineEndGraphemeIndex = graphemeIndex + 1;
|
|
2543
|
+
lineW = width;
|
|
2544
|
+
}
|
|
2545
|
+
function appendWholeSegment(segmentIndex, width) {
|
|
2546
|
+
if (!hasContent) {
|
|
2547
|
+
startLineAtSegment(segmentIndex, width);
|
|
2548
|
+
return;
|
|
2549
|
+
}
|
|
2550
|
+
lineW += width;
|
|
2551
|
+
lineEndSegmentIndex = segmentIndex + 1;
|
|
2552
|
+
lineEndGraphemeIndex = 0;
|
|
2553
|
+
}
|
|
2554
|
+
function appendBreakableSegmentFrom(segmentIndex, startGraphemeIndex) {
|
|
2555
|
+
const fitAdvances = breakableFitAdvances[segmentIndex];
|
|
2556
|
+
for (let g = startGraphemeIndex; g < fitAdvances.length; g++) {
|
|
2557
|
+
const gw = fitAdvances[g];
|
|
2558
|
+
if (!hasContent) {
|
|
2559
|
+
startLineAtGrapheme(segmentIndex, g, gw);
|
|
2560
|
+
}
|
|
2561
|
+
else if (lineW + gw > fitLimit) {
|
|
2562
|
+
emitCurrentLine();
|
|
2563
|
+
startLineAtGrapheme(segmentIndex, g, gw);
|
|
2564
|
+
}
|
|
2565
|
+
else {
|
|
2566
|
+
lineW += gw;
|
|
2567
|
+
lineEndSegmentIndex = segmentIndex;
|
|
2568
|
+
lineEndGraphemeIndex = g + 1;
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
if (hasContent && lineEndSegmentIndex === segmentIndex && lineEndGraphemeIndex === fitAdvances.length) {
|
|
2572
|
+
lineEndSegmentIndex = segmentIndex + 1;
|
|
2573
|
+
lineEndGraphemeIndex = 0;
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
let i = 0;
|
|
2577
|
+
while (i < widths.length) {
|
|
2578
|
+
if (!hasContent) {
|
|
2579
|
+
i = normalizeLineStartSegmentIndex(prepared, i);
|
|
2580
|
+
if (i >= widths.length)
|
|
2581
|
+
break;
|
|
2582
|
+
}
|
|
2583
|
+
const w = widths[i];
|
|
2584
|
+
const kind = kinds[i];
|
|
2585
|
+
const breakAfter = breaksAfter(kind);
|
|
2586
|
+
if (!hasContent) {
|
|
2587
|
+
if (w > fitLimit && breakableFitAdvances[i] !== null) {
|
|
2588
|
+
appendBreakableSegmentFrom(i, 0);
|
|
2589
|
+
}
|
|
2590
|
+
else {
|
|
2591
|
+
startLineAtSegment(i, w);
|
|
2592
|
+
}
|
|
2593
|
+
if (breakAfter) {
|
|
2594
|
+
pendingBreakSegmentIndex = i + 1;
|
|
2595
|
+
pendingBreakPaintWidth = lineW - w;
|
|
2596
|
+
}
|
|
2597
|
+
i++;
|
|
2598
|
+
continue;
|
|
2599
|
+
}
|
|
2600
|
+
const newW = lineW + w;
|
|
2601
|
+
if (newW > fitLimit) {
|
|
2602
|
+
if (breakAfter) {
|
|
2603
|
+
appendWholeSegment(i, w);
|
|
2604
|
+
emitCurrentLine(i + 1, 0, lineW - w);
|
|
2605
|
+
i++;
|
|
2606
|
+
continue;
|
|
2607
|
+
}
|
|
2608
|
+
if (pendingBreakSegmentIndex >= 0) {
|
|
2609
|
+
if (lineEndSegmentIndex > pendingBreakSegmentIndex ||
|
|
2610
|
+
(lineEndSegmentIndex === pendingBreakSegmentIndex && lineEndGraphemeIndex > 0)) {
|
|
2611
|
+
emitCurrentLine();
|
|
2612
|
+
continue;
|
|
2613
|
+
}
|
|
2614
|
+
emitCurrentLine(pendingBreakSegmentIndex, 0, pendingBreakPaintWidth);
|
|
2615
|
+
continue;
|
|
2616
|
+
}
|
|
2617
|
+
if (w > fitLimit && breakableFitAdvances[i] !== null) {
|
|
2618
|
+
emitCurrentLine();
|
|
2619
|
+
appendBreakableSegmentFrom(i, 0);
|
|
2620
|
+
i++;
|
|
2621
|
+
continue;
|
|
2622
|
+
}
|
|
2623
|
+
emitCurrentLine();
|
|
2624
|
+
continue;
|
|
2625
|
+
}
|
|
2626
|
+
appendWholeSegment(i, w);
|
|
2627
|
+
if (breakAfter) {
|
|
2628
|
+
pendingBreakSegmentIndex = i + 1;
|
|
2629
|
+
pendingBreakPaintWidth = lineW - w;
|
|
2630
|
+
}
|
|
2631
|
+
i++;
|
|
2632
|
+
}
|
|
2633
|
+
if (hasContent)
|
|
2634
|
+
emitCurrentLine();
|
|
2635
|
+
return lineCount;
|
|
2636
|
+
}
|
|
2637
|
+
function walkPreparedLinesRaw(prepared, maxWidth, onLine) {
|
|
2638
|
+
if (prepared.simpleLineWalkFastPath) {
|
|
2639
|
+
return walkPreparedLinesSimple(prepared, maxWidth);
|
|
2640
|
+
}
|
|
2641
|
+
const { widths, kinds, breakableFitAdvances, discretionaryHyphenWidth, chunks, } = prepared;
|
|
2642
|
+
if (widths.length === 0 || chunks.length === 0)
|
|
2643
|
+
return 0;
|
|
2644
|
+
const engineProfile = getEngineProfile();
|
|
2645
|
+
const lineFitEpsilon = engineProfile.lineFitEpsilon;
|
|
2646
|
+
const fitLimit = maxWidth + lineFitEpsilon;
|
|
2647
|
+
let lineCount = 0;
|
|
2648
|
+
let lineW = 0;
|
|
2649
|
+
let hasContent = false;
|
|
2650
|
+
let lineEndSegmentIndex = 0;
|
|
2651
|
+
let lineEndGraphemeIndex = 0;
|
|
2652
|
+
let pendingBreakSegmentIndex = -1;
|
|
2653
|
+
let pendingBreakFitWidth = 0;
|
|
2654
|
+
let pendingBreakPaintWidth = 0;
|
|
2655
|
+
let pendingBreakKind = null;
|
|
2656
|
+
function clearPendingBreak() {
|
|
2657
|
+
pendingBreakSegmentIndex = -1;
|
|
2658
|
+
pendingBreakFitWidth = 0;
|
|
2659
|
+
pendingBreakPaintWidth = 0;
|
|
2660
|
+
pendingBreakKind = null;
|
|
2661
|
+
}
|
|
2662
|
+
function emitCurrentLine(endSegmentIndex = lineEndSegmentIndex, endGraphemeIndex = lineEndGraphemeIndex, width = lineW) {
|
|
2663
|
+
lineCount++;
|
|
2664
|
+
lineW = 0;
|
|
2665
|
+
hasContent = false;
|
|
2666
|
+
clearPendingBreak();
|
|
2667
|
+
}
|
|
2668
|
+
function startLineAtSegment(segmentIndex, width) {
|
|
2669
|
+
hasContent = true;
|
|
2670
|
+
lineEndSegmentIndex = segmentIndex + 1;
|
|
2671
|
+
lineEndGraphemeIndex = 0;
|
|
2672
|
+
lineW = width;
|
|
2673
|
+
}
|
|
2674
|
+
function startLineAtGrapheme(segmentIndex, graphemeIndex, width) {
|
|
2675
|
+
hasContent = true;
|
|
2676
|
+
lineEndSegmentIndex = segmentIndex;
|
|
2677
|
+
lineEndGraphemeIndex = graphemeIndex + 1;
|
|
2678
|
+
lineW = width;
|
|
2679
|
+
}
|
|
2680
|
+
function appendWholeSegment(segmentIndex, advance) {
|
|
2681
|
+
if (!hasContent) {
|
|
2682
|
+
startLineAtSegment(segmentIndex, advance);
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
lineW += advance;
|
|
2686
|
+
lineEndSegmentIndex = segmentIndex + 1;
|
|
2687
|
+
lineEndGraphemeIndex = 0;
|
|
2688
|
+
}
|
|
2689
|
+
function updatePendingBreakForWholeSegment(kind, breakAfter, segmentIndex, segmentWidth, leadingSpacing, advance) {
|
|
2690
|
+
if (!breakAfter)
|
|
2691
|
+
return;
|
|
2692
|
+
const fitAdvance = getBreakOpportunityFitContribution(prepared, kind, segmentIndex, leadingSpacing);
|
|
2693
|
+
const paintAdvance = getLineEndPaintContribution(prepared, kind, segmentIndex, leadingSpacing, segmentWidth);
|
|
2694
|
+
pendingBreakSegmentIndex = segmentIndex + 1;
|
|
2695
|
+
pendingBreakFitWidth = lineW - advance + fitAdvance;
|
|
2696
|
+
pendingBreakPaintWidth = lineW - advance + paintAdvance;
|
|
2697
|
+
pendingBreakKind = kind;
|
|
2698
|
+
}
|
|
2699
|
+
function appendBreakableSegmentFrom(segmentIndex, startGraphemeIndex) {
|
|
2700
|
+
const fitAdvances = breakableFitAdvances[segmentIndex];
|
|
2701
|
+
for (let g = startGraphemeIndex; g < fitAdvances.length; g++) {
|
|
2702
|
+
const baseGw = fitAdvances[g];
|
|
2703
|
+
if (!hasContent) {
|
|
2704
|
+
startLineAtGrapheme(segmentIndex, g, baseGw);
|
|
2705
|
+
}
|
|
2706
|
+
else {
|
|
2707
|
+
const gw = getBreakableGraphemeAdvance(prepared, true, baseGw);
|
|
2708
|
+
const candidatePaintWidth = lineW + gw;
|
|
2709
|
+
if (getBreakableCandidateFitWidth(prepared, candidatePaintWidth) > fitLimit) {
|
|
2710
|
+
emitCurrentLine();
|
|
2711
|
+
startLineAtGrapheme(segmentIndex, g, baseGw);
|
|
2712
|
+
}
|
|
2713
|
+
else {
|
|
2714
|
+
lineW = candidatePaintWidth;
|
|
2715
|
+
lineEndSegmentIndex = segmentIndex;
|
|
2716
|
+
lineEndGraphemeIndex = g + 1;
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
if (hasContent && lineEndSegmentIndex === segmentIndex && lineEndGraphemeIndex === fitAdvances.length) {
|
|
2721
|
+
lineEndSegmentIndex = segmentIndex + 1;
|
|
2722
|
+
lineEndGraphemeIndex = 0;
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
function continueSoftHyphenBreakableSegment(segmentIndex) {
|
|
2726
|
+
if (pendingBreakKind !== 'soft-hyphen')
|
|
2727
|
+
return false;
|
|
2728
|
+
const fitWidths = breakableFitAdvances[segmentIndex];
|
|
2729
|
+
if (fitWidths == null)
|
|
2730
|
+
return false;
|
|
2731
|
+
const { fitCount, fittedWidth } = fitSoftHyphenBreak(fitWidths, lineW, maxWidth, lineFitEpsilon, discretionaryHyphenWidth, prepared.letterSpacing);
|
|
2732
|
+
if (fitCount === 0)
|
|
2733
|
+
return false;
|
|
2734
|
+
lineW = fittedWidth;
|
|
2735
|
+
lineEndSegmentIndex = segmentIndex;
|
|
2736
|
+
lineEndGraphemeIndex = fitCount;
|
|
2737
|
+
clearPendingBreak();
|
|
2738
|
+
if (fitCount === fitWidths.length) {
|
|
2739
|
+
lineEndSegmentIndex = segmentIndex + 1;
|
|
2740
|
+
lineEndGraphemeIndex = 0;
|
|
2741
|
+
return true;
|
|
2742
|
+
}
|
|
2743
|
+
emitCurrentLine(segmentIndex, fitCount, fittedWidth + discretionaryHyphenWidth);
|
|
2744
|
+
appendBreakableSegmentFrom(segmentIndex, fitCount);
|
|
2745
|
+
return true;
|
|
2746
|
+
}
|
|
2747
|
+
function emitEmptyChunk(chunk) {
|
|
2748
|
+
lineCount++;
|
|
2749
|
+
clearPendingBreak();
|
|
2750
|
+
}
|
|
2751
|
+
for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
|
|
2752
|
+
const chunk = chunks[chunkIndex];
|
|
2753
|
+
if (chunk.startSegmentIndex === chunk.endSegmentIndex) {
|
|
2754
|
+
emitEmptyChunk();
|
|
2755
|
+
continue;
|
|
2756
|
+
}
|
|
2757
|
+
hasContent = false;
|
|
2758
|
+
lineW = 0;
|
|
2759
|
+
lineEndSegmentIndex = chunk.startSegmentIndex;
|
|
2760
|
+
lineEndGraphemeIndex = 0;
|
|
2761
|
+
clearPendingBreak();
|
|
2762
|
+
let i = chunk.startSegmentIndex;
|
|
2763
|
+
while (i < chunk.endSegmentIndex) {
|
|
2764
|
+
if (!hasContent) {
|
|
2765
|
+
i = normalizeLineStartSegmentIndex(prepared, i, chunk.endSegmentIndex);
|
|
2766
|
+
if (i >= chunk.endSegmentIndex)
|
|
2767
|
+
break;
|
|
2768
|
+
}
|
|
2769
|
+
const kind = kinds[i];
|
|
2770
|
+
const breakAfter = breaksAfter(kind);
|
|
2771
|
+
const leadingSpacing = getLeadingLetterSpacing(prepared, hasContent, i);
|
|
2772
|
+
const w = kind === 'tab'
|
|
2773
|
+
? getTabAdvance(lineW + leadingSpacing, prepared.tabStopAdvance)
|
|
2774
|
+
: widths[i];
|
|
2775
|
+
const advance = leadingSpacing + w;
|
|
2776
|
+
const fitAdvance = getWholeSegmentFitContribution(prepared, kind, i, leadingSpacing, w);
|
|
2777
|
+
if (kind === 'soft-hyphen') {
|
|
2778
|
+
if (hasContent) {
|
|
2779
|
+
lineEndSegmentIndex = i + 1;
|
|
2780
|
+
lineEndGraphemeIndex = 0;
|
|
2781
|
+
pendingBreakSegmentIndex = i + 1;
|
|
2782
|
+
pendingBreakFitWidth = lineW + discretionaryHyphenWidth;
|
|
2783
|
+
pendingBreakPaintWidth = lineW + discretionaryHyphenWidth;
|
|
2784
|
+
pendingBreakKind = kind;
|
|
2785
|
+
}
|
|
2786
|
+
i++;
|
|
2787
|
+
continue;
|
|
2788
|
+
}
|
|
2789
|
+
if (!hasContent) {
|
|
2790
|
+
if (fitAdvance > fitLimit && breakableFitAdvances[i] !== null) {
|
|
2791
|
+
appendBreakableSegmentFrom(i, 0);
|
|
2792
|
+
}
|
|
2793
|
+
else {
|
|
2794
|
+
startLineAtSegment(i, w);
|
|
2795
|
+
}
|
|
2796
|
+
updatePendingBreakForWholeSegment(kind, breakAfter, i, w, leadingSpacing, advance);
|
|
2797
|
+
i++;
|
|
2798
|
+
continue;
|
|
2799
|
+
}
|
|
2800
|
+
const newFitW = lineW + fitAdvance;
|
|
2801
|
+
if (newFitW > fitLimit) {
|
|
2802
|
+
const currentBreakFitWidth = lineW + getBreakOpportunityFitContribution(prepared, kind, i, leadingSpacing);
|
|
2803
|
+
const currentBreakPaintWidth = lineW + getLineEndPaintContribution(prepared, kind, i, leadingSpacing, w);
|
|
2804
|
+
if (pendingBreakKind === 'soft-hyphen' &&
|
|
2805
|
+
engineProfile.preferEarlySoftHyphenBreak &&
|
|
2806
|
+
pendingBreakFitWidth <= fitLimit) {
|
|
2807
|
+
emitCurrentLine(pendingBreakSegmentIndex, 0, pendingBreakPaintWidth);
|
|
2808
|
+
continue;
|
|
2809
|
+
}
|
|
2810
|
+
if (pendingBreakKind === 'soft-hyphen' && continueSoftHyphenBreakableSegment(i)) {
|
|
2811
|
+
i++;
|
|
2812
|
+
continue;
|
|
2813
|
+
}
|
|
2814
|
+
if (breakAfter && currentBreakFitWidth <= fitLimit) {
|
|
2815
|
+
appendWholeSegment(i, advance);
|
|
2816
|
+
emitCurrentLine(i + 1, 0, currentBreakPaintWidth);
|
|
2817
|
+
i++;
|
|
2818
|
+
continue;
|
|
2819
|
+
}
|
|
2820
|
+
if (pendingBreakSegmentIndex >= 0 && pendingBreakFitWidth <= fitLimit) {
|
|
2821
|
+
if (lineEndSegmentIndex > pendingBreakSegmentIndex ||
|
|
2822
|
+
(lineEndSegmentIndex === pendingBreakSegmentIndex && lineEndGraphemeIndex > 0)) {
|
|
2823
|
+
emitCurrentLine();
|
|
2824
|
+
continue;
|
|
2825
|
+
}
|
|
2826
|
+
const nextSegmentIndex = pendingBreakSegmentIndex;
|
|
2827
|
+
emitCurrentLine(nextSegmentIndex, 0, pendingBreakPaintWidth);
|
|
2828
|
+
i = nextSegmentIndex;
|
|
2829
|
+
continue;
|
|
2830
|
+
}
|
|
2831
|
+
if (fitAdvance > fitLimit && breakableFitAdvances[i] !== null) {
|
|
2832
|
+
emitCurrentLine();
|
|
2833
|
+
appendBreakableSegmentFrom(i, 0);
|
|
2834
|
+
i++;
|
|
2835
|
+
continue;
|
|
2836
|
+
}
|
|
2837
|
+
emitCurrentLine();
|
|
2838
|
+
continue;
|
|
2839
|
+
}
|
|
2840
|
+
appendWholeSegment(i, advance);
|
|
2841
|
+
updatePendingBreakForWholeSegment(kind, breakAfter, i, w, leadingSpacing, advance);
|
|
2842
|
+
i++;
|
|
2843
|
+
}
|
|
2844
|
+
if (hasContent) {
|
|
2845
|
+
const finalPaintWidth = pendingBreakSegmentIndex === chunk.consumedEndSegmentIndex
|
|
2846
|
+
? pendingBreakPaintWidth
|
|
2847
|
+
: lineW;
|
|
2848
|
+
emitCurrentLine(chunk.consumedEndSegmentIndex, 0, finalPaintWidth);
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
return lineCount;
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2854
|
+
// Text measurement for browser environments using canvas measureText.
|
|
2855
|
+
//
|
|
2856
|
+
// Problem: DOM-based text measurement (getBoundingClientRect, offsetHeight)
|
|
2857
|
+
// forces synchronous layout reflow. When components independently measure text,
|
|
2858
|
+
// each measurement triggers a reflow of the entire document. This creates
|
|
2859
|
+
// read/write interleaving that can cost 30ms+ per frame for 500 text blocks.
|
|
2860
|
+
//
|
|
2861
|
+
// Solution: two-phase measurement centered around canvas measureText.
|
|
2862
|
+
// prepare(text, font) — segments text via Intl.Segmenter, measures each word
|
|
2863
|
+
// via canvas, caches widths, and does one cached DOM calibration read per
|
|
2864
|
+
// font when emoji correction is needed. Call once when text first appears.
|
|
2865
|
+
// layout(prepared, maxWidth, lineHeight) — walks cached word widths with pure
|
|
2866
|
+
// arithmetic to count lines and compute height. Call on every resize.
|
|
2867
|
+
// ~0.0002ms per text.
|
|
2868
|
+
//
|
|
2869
|
+
// i18n: Intl.Segmenter handles CJK (per-character breaking), Thai, Arabic, etc.
|
|
2870
|
+
// Bidi: simplified rich-path metadata for mixed LTR/RTL custom rendering.
|
|
2871
|
+
// Punctuation merging: "better." measured as one unit (matches CSS behavior).
|
|
2872
|
+
// Trailing whitespace: hangs past line edge without triggering breaks (CSS behavior).
|
|
2873
|
+
// overflow-wrap: pre-measured grapheme widths enable character-level word breaking.
|
|
2874
|
+
//
|
|
2875
|
+
// Emoji correction: Chrome/Firefox canvas measures emoji wider than DOM at font
|
|
2876
|
+
// sizes <24px on macOS (Apple Color Emoji). The inflation is constant per emoji
|
|
2877
|
+
// grapheme at a given size, font-independent. Auto-detected by comparing canvas
|
|
2878
|
+
// vs actual DOM emoji width (one cached DOM read per font). Safari canvas and
|
|
2879
|
+
// DOM agree (both wider than fontSize), so correction = 0 there.
|
|
2880
|
+
//
|
|
2881
|
+
// Limitations:
|
|
2882
|
+
// - system-ui font: canvas resolves to different optical variants than DOM on macOS.
|
|
2883
|
+
// Use named fonts (Helvetica, Inter, etc.) for guaranteed accuracy.
|
|
2884
|
+
// See RESEARCH.md "Discovery: system-ui font resolution mismatch".
|
|
2885
|
+
//
|
|
2886
|
+
// Based on Sebastian Markbage's text-layout research (github.com/chenglou/text-layout).
|
|
2887
|
+
let sharedGraphemeSegmenter = null;
|
|
2888
|
+
function getSharedGraphemeSegmenter() {
|
|
2889
|
+
if (sharedGraphemeSegmenter === null) {
|
|
2890
|
+
sharedGraphemeSegmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
2891
|
+
}
|
|
2892
|
+
return sharedGraphemeSegmenter;
|
|
2893
|
+
}
|
|
2894
|
+
// --- Public API ---
|
|
2895
|
+
function createEmptyPrepared(includeSegments) {
|
|
2896
|
+
return {
|
|
2897
|
+
widths: [],
|
|
2898
|
+
lineEndFitAdvances: [],
|
|
2899
|
+
lineEndPaintAdvances: [],
|
|
2900
|
+
kinds: [],
|
|
2901
|
+
simpleLineWalkFastPath: true,
|
|
2902
|
+
segLevels: null,
|
|
2903
|
+
breakableFitAdvances: [],
|
|
2904
|
+
letterSpacing: 0,
|
|
2905
|
+
spacingGraphemeCounts: [],
|
|
2906
|
+
discretionaryHyphenWidth: 0,
|
|
2907
|
+
tabStopAdvance: 0,
|
|
2908
|
+
chunks: [],
|
|
2909
|
+
};
|
|
2910
|
+
}
|
|
2911
|
+
function buildBaseCjkUnits(segText, engineProfile) {
|
|
2912
|
+
const units = [];
|
|
2913
|
+
let unitParts = [];
|
|
2914
|
+
let unitStart = 0;
|
|
2915
|
+
let unitContainsCJK = false;
|
|
2916
|
+
let unitEndsWithClosingQuote = false;
|
|
2917
|
+
let unitIsSingleKinsokuEnd = false;
|
|
2918
|
+
function pushUnit() {
|
|
2919
|
+
if (unitParts.length === 0)
|
|
2920
|
+
return;
|
|
2921
|
+
units.push({
|
|
2922
|
+
text: unitParts.length === 1 ? unitParts[0] : unitParts.join(''),
|
|
2923
|
+
start: unitStart,
|
|
2924
|
+
});
|
|
2925
|
+
unitParts = [];
|
|
2926
|
+
unitContainsCJK = false;
|
|
2927
|
+
unitEndsWithClosingQuote = false;
|
|
2928
|
+
unitIsSingleKinsokuEnd = false;
|
|
2929
|
+
}
|
|
2930
|
+
function startUnit(grapheme, start, graphemeContainsCJK) {
|
|
2931
|
+
unitParts = [grapheme];
|
|
2932
|
+
unitStart = start;
|
|
2933
|
+
unitContainsCJK = graphemeContainsCJK;
|
|
2934
|
+
unitEndsWithClosingQuote = endsWithClosingQuote(grapheme);
|
|
2935
|
+
unitIsSingleKinsokuEnd = kinsokuEnd.has(grapheme);
|
|
2936
|
+
}
|
|
2937
|
+
function appendToUnit(grapheme, graphemeContainsCJK) {
|
|
2938
|
+
unitParts.push(grapheme);
|
|
2939
|
+
unitContainsCJK = unitContainsCJK || graphemeContainsCJK;
|
|
2940
|
+
const graphemeEndsWithClosingQuote = endsWithClosingQuote(grapheme);
|
|
2941
|
+
if (grapheme.length === 1 && leftStickyPunctuation.has(grapheme)) {
|
|
2942
|
+
unitEndsWithClosingQuote = unitEndsWithClosingQuote || graphemeEndsWithClosingQuote;
|
|
2943
|
+
}
|
|
2944
|
+
else {
|
|
2945
|
+
unitEndsWithClosingQuote = graphemeEndsWithClosingQuote;
|
|
2946
|
+
}
|
|
2947
|
+
unitIsSingleKinsokuEnd = false;
|
|
2948
|
+
}
|
|
2949
|
+
for (const gs of getSharedGraphemeSegmenter().segment(segText)) {
|
|
2950
|
+
const grapheme = gs.segment;
|
|
2951
|
+
const graphemeContainsCJK = isCJK(grapheme);
|
|
2952
|
+
if (unitParts.length === 0) {
|
|
2953
|
+
startUnit(grapheme, gs.index, graphemeContainsCJK);
|
|
2954
|
+
continue;
|
|
2955
|
+
}
|
|
2956
|
+
if (unitIsSingleKinsokuEnd ||
|
|
2957
|
+
kinsokuStart.has(grapheme) ||
|
|
2958
|
+
leftStickyPunctuation.has(grapheme) ||
|
|
2959
|
+
(engineProfile.carryCJKAfterClosingQuote &&
|
|
2960
|
+
graphemeContainsCJK &&
|
|
2961
|
+
unitEndsWithClosingQuote)) {
|
|
2962
|
+
appendToUnit(grapheme, graphemeContainsCJK);
|
|
2963
|
+
continue;
|
|
2964
|
+
}
|
|
2965
|
+
if (!unitContainsCJK && !graphemeContainsCJK) {
|
|
2966
|
+
appendToUnit(grapheme, graphemeContainsCJK);
|
|
2967
|
+
continue;
|
|
2968
|
+
}
|
|
2969
|
+
pushUnit();
|
|
2970
|
+
startUnit(grapheme, gs.index, graphemeContainsCJK);
|
|
2971
|
+
}
|
|
2972
|
+
pushUnit();
|
|
2973
|
+
return units;
|
|
2974
|
+
}
|
|
2975
|
+
function mergeKeepAllTextUnits(units) {
|
|
2976
|
+
if (units.length <= 1)
|
|
2977
|
+
return units;
|
|
2978
|
+
const merged = [];
|
|
2979
|
+
let currentTextParts = [units[0].text];
|
|
2980
|
+
let currentStart = units[0].start;
|
|
2981
|
+
let currentContainsCJK = isCJK(units[0].text);
|
|
2982
|
+
let currentCanContinue = canContinueKeepAllTextRun(units[0].text);
|
|
2983
|
+
function flushCurrent() {
|
|
2984
|
+
merged.push({
|
|
2985
|
+
text: currentTextParts.length === 1 ? currentTextParts[0] : currentTextParts.join(''),
|
|
2986
|
+
start: currentStart,
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
2989
|
+
for (let i = 1; i < units.length; i++) {
|
|
2990
|
+
const next = units[i];
|
|
2991
|
+
const nextContainsCJK = isCJK(next.text);
|
|
2992
|
+
const nextCanContinue = canContinueKeepAllTextRun(next.text);
|
|
2993
|
+
if (currentContainsCJK && currentCanContinue) {
|
|
2994
|
+
currentTextParts.push(next.text);
|
|
2995
|
+
currentContainsCJK = currentContainsCJK || nextContainsCJK;
|
|
2996
|
+
currentCanContinue = nextCanContinue;
|
|
2997
|
+
continue;
|
|
2998
|
+
}
|
|
2999
|
+
flushCurrent();
|
|
3000
|
+
currentTextParts = [next.text];
|
|
3001
|
+
currentStart = next.start;
|
|
3002
|
+
currentContainsCJK = nextContainsCJK;
|
|
3003
|
+
currentCanContinue = nextCanContinue;
|
|
3004
|
+
}
|
|
3005
|
+
flushCurrent();
|
|
3006
|
+
return merged;
|
|
3007
|
+
}
|
|
3008
|
+
function countRenderedSpacingGraphemes(text, kind) {
|
|
3009
|
+
if (kind === 'zero-width-break' ||
|
|
3010
|
+
kind === 'soft-hyphen' ||
|
|
3011
|
+
kind === 'hard-break') {
|
|
3012
|
+
return 0;
|
|
3013
|
+
}
|
|
3014
|
+
if (kind === 'tab')
|
|
3015
|
+
return 1;
|
|
3016
|
+
let count = 0;
|
|
3017
|
+
const graphemeSegmenter = getSharedGraphemeSegmenter();
|
|
3018
|
+
for (const _ of graphemeSegmenter.segment(text))
|
|
3019
|
+
count++;
|
|
3020
|
+
return count;
|
|
3021
|
+
}
|
|
3022
|
+
function addInternalLetterSpacing(width, graphemeCount, letterSpacing) {
|
|
3023
|
+
return graphemeCount > 1 ? width + (graphemeCount - 1) * letterSpacing : width;
|
|
3024
|
+
}
|
|
3025
|
+
function measureAnalysis(analysis, font, includeSegments, wordBreak, letterSpacing) {
|
|
3026
|
+
const engineProfile = getEngineProfile();
|
|
3027
|
+
const { cache, emojiCorrection } = getFontMeasurementState(font, textMayContainEmoji(analysis.normalized));
|
|
3028
|
+
const discretionaryHyphenWidth = getCorrectedSegmentWidth('-', getSegmentMetrics('-', cache), emojiCorrection) +
|
|
3029
|
+
(letterSpacing === 0 ? 0 : letterSpacing);
|
|
3030
|
+
const spaceWidth = getCorrectedSegmentWidth(' ', getSegmentMetrics(' ', cache), emojiCorrection);
|
|
3031
|
+
const tabStopAdvance = spaceWidth * 8;
|
|
3032
|
+
const hasLetterSpacing = letterSpacing !== 0;
|
|
3033
|
+
if (analysis.len === 0)
|
|
3034
|
+
return createEmptyPrepared();
|
|
3035
|
+
const widths = [];
|
|
3036
|
+
const lineEndFitAdvances = [];
|
|
3037
|
+
const lineEndPaintAdvances = [];
|
|
3038
|
+
const kinds = [];
|
|
3039
|
+
let simpleLineWalkFastPath = analysis.chunks.length <= 1 && !hasLetterSpacing;
|
|
3040
|
+
const segStarts = null;
|
|
3041
|
+
const breakableFitAdvances = [];
|
|
3042
|
+
const spacingGraphemeCounts = [];
|
|
3043
|
+
const segments = includeSegments ? [] : null;
|
|
3044
|
+
const preparedStartByAnalysisIndex = Array.from({ length: analysis.len });
|
|
3045
|
+
function pushMeasuredSegment(text, width, lineEndFitAdvance, lineEndPaintAdvance, kind, start, breakableFitAdvance, spacingGraphemeCount) {
|
|
3046
|
+
if (kind !== 'text' && kind !== 'space' && kind !== 'zero-width-break') {
|
|
3047
|
+
simpleLineWalkFastPath = false;
|
|
3048
|
+
}
|
|
3049
|
+
widths.push(width);
|
|
3050
|
+
lineEndFitAdvances.push(lineEndFitAdvance);
|
|
3051
|
+
lineEndPaintAdvances.push(lineEndPaintAdvance);
|
|
3052
|
+
kinds.push(kind);
|
|
3053
|
+
breakableFitAdvances.push(breakableFitAdvance);
|
|
3054
|
+
if (hasLetterSpacing)
|
|
3055
|
+
spacingGraphemeCounts.push(spacingGraphemeCount);
|
|
3056
|
+
if (segments !== null)
|
|
3057
|
+
segments.push(text);
|
|
3058
|
+
}
|
|
3059
|
+
function pushMeasuredTextSegment(text, kind, start, wordLike, allowOverflowBreaks) {
|
|
3060
|
+
const textMetrics = getSegmentMetrics(text, cache);
|
|
3061
|
+
const spacingGraphemeCount = hasLetterSpacing
|
|
3062
|
+
? countRenderedSpacingGraphemes(text, kind)
|
|
3063
|
+
: 0;
|
|
3064
|
+
const width = addInternalLetterSpacing(getCorrectedSegmentWidth(text, textMetrics, emojiCorrection), spacingGraphemeCount, letterSpacing);
|
|
3065
|
+
const baseLineEndFitAdvance = kind === 'space' || kind === 'preserved-space' || kind === 'zero-width-break'
|
|
3066
|
+
? 0
|
|
3067
|
+
: width;
|
|
3068
|
+
const lineEndFitAdvance = baseLineEndFitAdvance === 0
|
|
3069
|
+
? 0
|
|
3070
|
+
: baseLineEndFitAdvance + (spacingGraphemeCount > 0 ? letterSpacing : 0);
|
|
3071
|
+
const lineEndPaintAdvance = kind === 'space' || kind === 'zero-width-break'
|
|
3072
|
+
? 0
|
|
3073
|
+
: width;
|
|
3074
|
+
if (allowOverflowBreaks && wordLike && text.length > 1) {
|
|
3075
|
+
let fitMode = 'sum-graphemes';
|
|
3076
|
+
if (letterSpacing !== 0) {
|
|
3077
|
+
fitMode = 'segment-prefixes';
|
|
3078
|
+
}
|
|
3079
|
+
else if (isNumericRunSegment(text)) {
|
|
3080
|
+
fitMode = 'pair-context';
|
|
3081
|
+
}
|
|
3082
|
+
else if (engineProfile.preferPrefixWidthsForBreakableRuns) {
|
|
3083
|
+
fitMode = 'segment-prefixes';
|
|
3084
|
+
}
|
|
3085
|
+
const fitAdvances = getSegmentBreakableFitAdvances(text, textMetrics, cache, emojiCorrection, fitMode);
|
|
3086
|
+
pushMeasuredSegment(text, width, lineEndFitAdvance, lineEndPaintAdvance, kind, start, fitAdvances, spacingGraphemeCount);
|
|
3087
|
+
return;
|
|
3088
|
+
}
|
|
3089
|
+
pushMeasuredSegment(text, width, lineEndFitAdvance, lineEndPaintAdvance, kind, start, null, spacingGraphemeCount);
|
|
3090
|
+
}
|
|
3091
|
+
for (let mi = 0; mi < analysis.len; mi++) {
|
|
3092
|
+
preparedStartByAnalysisIndex[mi] = widths.length;
|
|
3093
|
+
const segText = analysis.texts[mi];
|
|
3094
|
+
const segWordLike = analysis.isWordLike[mi];
|
|
3095
|
+
const segKind = analysis.kinds[mi];
|
|
3096
|
+
const segStart = analysis.starts[mi];
|
|
3097
|
+
if (segKind === 'soft-hyphen') {
|
|
3098
|
+
pushMeasuredSegment(segText, 0, discretionaryHyphenWidth, discretionaryHyphenWidth, segKind, segStart, null, 0);
|
|
3099
|
+
continue;
|
|
3100
|
+
}
|
|
3101
|
+
if (segKind === 'hard-break') {
|
|
3102
|
+
pushMeasuredSegment(segText, 0, 0, 0, segKind, segStart, null, 0);
|
|
3103
|
+
continue;
|
|
3104
|
+
}
|
|
3105
|
+
if (segKind === 'tab') {
|
|
3106
|
+
pushMeasuredSegment(segText, 0, 0, 0, segKind, segStart, null, hasLetterSpacing ? countRenderedSpacingGraphemes(segText, segKind) : 0);
|
|
3107
|
+
continue;
|
|
3108
|
+
}
|
|
3109
|
+
const segMetrics = getSegmentMetrics(segText, cache);
|
|
3110
|
+
if (segKind === 'text' && segMetrics.containsCJK) {
|
|
3111
|
+
const baseUnits = buildBaseCjkUnits(segText, engineProfile);
|
|
3112
|
+
const measuredUnits = wordBreak === 'keep-all'
|
|
3113
|
+
? mergeKeepAllTextUnits(baseUnits)
|
|
3114
|
+
: baseUnits;
|
|
3115
|
+
for (let i = 0; i < measuredUnits.length; i++) {
|
|
3116
|
+
const unit = measuredUnits[i];
|
|
3117
|
+
pushMeasuredTextSegment(unit.text, 'text', segStart + unit.start, segWordLike, wordBreak === 'keep-all' || !isCJK(unit.text));
|
|
3118
|
+
}
|
|
3119
|
+
continue;
|
|
3120
|
+
}
|
|
3121
|
+
pushMeasuredTextSegment(segText, segKind, segStart, segWordLike, true);
|
|
3122
|
+
}
|
|
3123
|
+
const chunks = mapAnalysisChunksToPreparedChunks(analysis.chunks, preparedStartByAnalysisIndex, widths.length);
|
|
3124
|
+
const segLevels = segStarts === null ? null : computeSegmentLevels(analysis.normalized, segStarts);
|
|
3125
|
+
if (segments !== null) {
|
|
3126
|
+
return {
|
|
3127
|
+
widths,
|
|
3128
|
+
lineEndFitAdvances,
|
|
3129
|
+
lineEndPaintAdvances,
|
|
3130
|
+
kinds,
|
|
3131
|
+
simpleLineWalkFastPath,
|
|
3132
|
+
segLevels,
|
|
3133
|
+
breakableFitAdvances,
|
|
3134
|
+
letterSpacing,
|
|
3135
|
+
spacingGraphemeCounts,
|
|
3136
|
+
discretionaryHyphenWidth,
|
|
3137
|
+
tabStopAdvance,
|
|
3138
|
+
chunks,
|
|
3139
|
+
segments,
|
|
3140
|
+
};
|
|
3141
|
+
}
|
|
3142
|
+
return {
|
|
3143
|
+
widths,
|
|
3144
|
+
lineEndFitAdvances,
|
|
3145
|
+
lineEndPaintAdvances,
|
|
3146
|
+
kinds,
|
|
3147
|
+
simpleLineWalkFastPath,
|
|
3148
|
+
segLevels,
|
|
3149
|
+
breakableFitAdvances,
|
|
3150
|
+
letterSpacing,
|
|
3151
|
+
spacingGraphemeCounts,
|
|
3152
|
+
discretionaryHyphenWidth,
|
|
3153
|
+
tabStopAdvance,
|
|
3154
|
+
chunks,
|
|
3155
|
+
};
|
|
3156
|
+
}
|
|
3157
|
+
function mapAnalysisChunksToPreparedChunks(chunks, preparedStartByAnalysisIndex, preparedEndSegmentIndex) {
|
|
3158
|
+
const preparedChunks = [];
|
|
3159
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
3160
|
+
const chunk = chunks[i];
|
|
3161
|
+
const startSegmentIndex = chunk.startSegmentIndex < preparedStartByAnalysisIndex.length
|
|
3162
|
+
? preparedStartByAnalysisIndex[chunk.startSegmentIndex]
|
|
3163
|
+
: preparedEndSegmentIndex;
|
|
3164
|
+
const endSegmentIndex = chunk.endSegmentIndex < preparedStartByAnalysisIndex.length
|
|
3165
|
+
? preparedStartByAnalysisIndex[chunk.endSegmentIndex]
|
|
3166
|
+
: preparedEndSegmentIndex;
|
|
3167
|
+
const consumedEndSegmentIndex = chunk.consumedEndSegmentIndex < preparedStartByAnalysisIndex.length
|
|
3168
|
+
? preparedStartByAnalysisIndex[chunk.consumedEndSegmentIndex]
|
|
3169
|
+
: preparedEndSegmentIndex;
|
|
3170
|
+
preparedChunks.push({
|
|
3171
|
+
startSegmentIndex,
|
|
3172
|
+
endSegmentIndex,
|
|
3173
|
+
consumedEndSegmentIndex,
|
|
3174
|
+
});
|
|
3175
|
+
}
|
|
3176
|
+
return preparedChunks;
|
|
3177
|
+
}
|
|
3178
|
+
function prepareInternal(text, font, includeSegments, options) {
|
|
3179
|
+
const wordBreak = options?.wordBreak ?? 'normal';
|
|
3180
|
+
const letterSpacing = options?.letterSpacing ?? 0;
|
|
3181
|
+
const analysis = analyzeText(text, getEngineProfile(), options?.whiteSpace, wordBreak);
|
|
3182
|
+
return measureAnalysis(analysis, font, includeSegments, wordBreak, letterSpacing);
|
|
3183
|
+
}
|
|
3184
|
+
// Prepare text for layout. Segments the text, measures each segment via canvas,
|
|
3185
|
+
// and stores the widths for fast relayout at any width. Call once per text block
|
|
3186
|
+
// (e.g. when a comment first appears). The result is width-independent — the
|
|
3187
|
+
// same PreparedText can be laid out at any maxWidth and lineHeight via layout().
|
|
3188
|
+
//
|
|
3189
|
+
// Steps:
|
|
3190
|
+
// 1. Normalize collapsible whitespace (CSS white-space: normal behavior)
|
|
3191
|
+
// 2. Segment via Intl.Segmenter (handles CJK, Thai, etc.)
|
|
3192
|
+
// 3. Merge punctuation into preceding word ("better." as one unit)
|
|
3193
|
+
// 4. Split CJK words into individual graphemes (per-character line breaks)
|
|
3194
|
+
// 5. Measure each segment via canvas measureText, cache by (segment, font)
|
|
3195
|
+
// 6. Pre-measure graphemes of long words (for overflow-wrap: break-word)
|
|
3196
|
+
// 7. Correct emoji canvas inflation (auto-detected per font size)
|
|
3197
|
+
// 8. Optionally compute rich-path bidi metadata for custom renderers
|
|
3198
|
+
function prepare(text, font, options) {
|
|
3199
|
+
return prepareInternal(text, font, false, options);
|
|
3200
|
+
}
|
|
3201
|
+
function getInternalPrepared(prepared) {
|
|
3202
|
+
return prepared;
|
|
3203
|
+
}
|
|
3204
|
+
// Layout prepared text at a given max width and caller-provided lineHeight.
|
|
3205
|
+
// Pure arithmetic on cached widths — no canvas calls, no DOM reads, no string
|
|
3206
|
+
// operations, no allocations.
|
|
3207
|
+
// ~0.0002ms per text block. Call on every resize.
|
|
3208
|
+
//
|
|
3209
|
+
// Line breaking rules (matching CSS white-space: normal + overflow-wrap: break-word):
|
|
3210
|
+
// - Break before any non-space segment that would overflow the line
|
|
3211
|
+
// - Trailing whitespace hangs past the line edge (doesn't trigger breaks)
|
|
3212
|
+
// - Segments wider than maxWidth are broken at grapheme boundaries
|
|
3213
|
+
function layout(prepared, maxWidth, lineHeight) {
|
|
3214
|
+
// Keep the resize hot path specialized. `layoutWithLines()` shares the same
|
|
3215
|
+
// break semantics but also tracks line ranges; the extra bookkeeping is too
|
|
3216
|
+
// expensive to pay on every hot-path `layout()` call.
|
|
3217
|
+
const lineCount = countPreparedLines(getInternalPrepared(prepared), maxWidth);
|
|
3218
|
+
return { lineCount, height: lineCount * lineHeight };
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
// SPDX-FileCopyrightText: © 2024 Schneider Electric
|
|
3222
|
+
//
|
|
3223
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3224
|
+
const inheritAttributes = (element, attributes = []) => {
|
|
3225
|
+
const attributeObject = {};
|
|
3226
|
+
for (const attribute of attributes) {
|
|
3227
|
+
const value = element.getAttribute(attribute);
|
|
3228
|
+
if (value !== null) {
|
|
3229
|
+
attributeObject[attribute] = value;
|
|
3230
|
+
element.removeAttribute(attribute);
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
return attributeObject;
|
|
3234
|
+
};
|
|
3235
|
+
const ariaAttributes = [
|
|
3236
|
+
'aria-activedescendant',
|
|
3237
|
+
'aria-atomic',
|
|
3238
|
+
'aria-autocomplete',
|
|
3239
|
+
'aria-braillelabel',
|
|
3240
|
+
'aria-brailleroledescription',
|
|
3241
|
+
'aria-busy',
|
|
3242
|
+
'aria-checked',
|
|
3243
|
+
'aria-colcount',
|
|
3244
|
+
'aria-colindex',
|
|
3245
|
+
'aria-colindextext',
|
|
3246
|
+
'aria-colspan',
|
|
3247
|
+
'aria-controls',
|
|
3248
|
+
'aria-current',
|
|
3249
|
+
'aria-describedby',
|
|
3250
|
+
'aria-description',
|
|
3251
|
+
'aria-details',
|
|
3252
|
+
'aria-disabled',
|
|
3253
|
+
'aria-errormessage',
|
|
3254
|
+
'aria-expanded',
|
|
3255
|
+
'aria-flowto',
|
|
3256
|
+
'aria-haspopup',
|
|
3257
|
+
'aria-hidden',
|
|
3258
|
+
'aria-invalid',
|
|
3259
|
+
'aria-keyshortcuts',
|
|
3260
|
+
'aria-label',
|
|
3261
|
+
'aria-labelledby',
|
|
3262
|
+
'aria-level',
|
|
3263
|
+
'aria-live',
|
|
3264
|
+
'aria-multiline',
|
|
3265
|
+
'aria-multiselectable',
|
|
3266
|
+
'aria-orientation',
|
|
3267
|
+
'aria-owns',
|
|
3268
|
+
'aria-placeholder',
|
|
3269
|
+
'aria-posinset',
|
|
3270
|
+
'aria-pressed',
|
|
3271
|
+
'aria-readonly',
|
|
3272
|
+
'aria-relevant',
|
|
3273
|
+
'aria-required',
|
|
3274
|
+
'aria-roledescription',
|
|
3275
|
+
'aria-rowcount',
|
|
3276
|
+
'aria-rowindex',
|
|
3277
|
+
'aria-rowindextext',
|
|
3278
|
+
'aria-rowspan',
|
|
3279
|
+
'aria-selected',
|
|
3280
|
+
'aria-setsize',
|
|
3281
|
+
'aria-sort',
|
|
3282
|
+
'aria-valuemax',
|
|
3283
|
+
'aria-valuemin',
|
|
3284
|
+
'aria-valuenow',
|
|
3285
|
+
'aria-valuetext',
|
|
3286
|
+
'role',
|
|
3287
|
+
];
|
|
3288
|
+
/**
|
|
3289
|
+
* Returns an array of aria attributes that should be copied from
|
|
3290
|
+
* the shadow host element to a target within the light DOM.
|
|
3291
|
+
*
|
|
3292
|
+
* @param element The element that the attributes should be copied from.
|
|
3293
|
+
*/
|
|
3294
|
+
const inheritAriaAttributes = (element) => inheritAttributes(element, ariaAttributes);
|
|
3295
|
+
const prefix = 'Invariant failed';
|
|
3296
|
+
/**
|
|
3297
|
+
* Throws an error if the value is falsy.
|
|
3298
|
+
*
|
|
3299
|
+
* @param value Value to test.
|
|
3300
|
+
* @param message Optional message to display in development builds.
|
|
3301
|
+
*/
|
|
3302
|
+
function invariant(value, message) {
|
|
3303
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3304
|
+
if (value)
|
|
3305
|
+
return;
|
|
3306
|
+
throw new Error(prefix);
|
|
3307
|
+
}
|
|
3308
|
+
/**
|
|
3309
|
+
* From an object pick a set of keys.
|
|
3310
|
+
*
|
|
3311
|
+
* @param object Object to pick from.
|
|
3312
|
+
* @param keys They keys to pick.
|
|
3313
|
+
* @returns New object with only the picked keys.
|
|
3314
|
+
*/
|
|
3315
|
+
const pick = (object, ...keys) => {
|
|
3316
|
+
const returnValue = {};
|
|
3317
|
+
for (const key of keys)
|
|
3318
|
+
returnValue[key] = object[key];
|
|
3319
|
+
return returnValue;
|
|
3320
|
+
};
|
|
3321
|
+
const pickFocusEventAttributes = (event) => pick(event, 'relatedTarget');
|
|
3322
|
+
const pickInputEventAttributes = (event) => pick(event, 'data', 'inputType', 'isComposing');
|
|
3323
|
+
const getConversionFactor = (element, unit) => {
|
|
3324
|
+
switch (unit) {
|
|
3325
|
+
case 'cm': {
|
|
3326
|
+
return 96 / 2.54;
|
|
3327
|
+
}
|
|
3328
|
+
case 'em': {
|
|
3329
|
+
return Number.parseFloat(globalThis.getComputedStyle(element.parentElement ?? document.documentElement).fontSize);
|
|
3330
|
+
}
|
|
3331
|
+
case 'in': {
|
|
3332
|
+
return 96;
|
|
3333
|
+
}
|
|
3334
|
+
case 'mm': {
|
|
3335
|
+
return 96 / 25.4;
|
|
3336
|
+
}
|
|
3337
|
+
case 'pc': {
|
|
3338
|
+
return 16;
|
|
3339
|
+
}
|
|
3340
|
+
case 'pt': {
|
|
3341
|
+
return 96 / 72;
|
|
3342
|
+
}
|
|
3343
|
+
case 'px': {
|
|
3344
|
+
return 1;
|
|
3345
|
+
}
|
|
3346
|
+
case 'rem': {
|
|
3347
|
+
return Number.parseFloat(globalThis.getComputedStyle(document.documentElement).fontSize);
|
|
3348
|
+
}
|
|
3349
|
+
default: {
|
|
3350
|
+
return undefined;
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
};
|
|
3354
|
+
const propertyToPx = (element, property) => {
|
|
3355
|
+
const value = globalThis.getComputedStyle(element).getPropertyValue(property);
|
|
3356
|
+
const number = Number.parseFloat(value);
|
|
3357
|
+
if (Number.isNaN(number))
|
|
3358
|
+
return undefined;
|
|
3359
|
+
const unit = /\s*[\d+.-]*\s*(.*)/.exec(value)?.[1] ?? '';
|
|
3360
|
+
const conversionFactor = getConversionFactor(element, unit) ?? 1;
|
|
3361
|
+
return number * conversionFactor;
|
|
3362
|
+
};
|
|
3363
|
+
const ignorePromise = (promise) => {
|
|
3364
|
+
promise.catch(() => {
|
|
3365
|
+
invariant(false);
|
|
3366
|
+
});
|
|
3367
|
+
};
|
|
3368
|
+
const isTouchDevice = () => 'ontouchstart' in globalThis ||
|
|
3369
|
+
('maxTouchPoints' in globalThis && globalThis.navigator.maxTouchPoints > 0);
|
|
3370
|
+
const toPretextWhiteSpace = (value) => value === 'pre-wrap' ? 'pre-wrap' : 'normal';
|
|
3371
|
+
const toPretextWordBreak = (value) => value === 'keep-all' ? 'keep-all' : 'normal';
|
|
3372
|
+
/**
|
|
3373
|
+
* Checks if an element's ellipsis is active.
|
|
3374
|
+
*
|
|
3375
|
+
* @param element The element to check.
|
|
3376
|
+
* @returns `true` if ellipsis is active, `false` otherwise.
|
|
3377
|
+
*/
|
|
3378
|
+
const isEllipsisActive = (element) => {
|
|
3379
|
+
const computedStyle = globalThis.getComputedStyle(element);
|
|
3380
|
+
const { webkitLineClamp, lineHeight, font, fontStyle, fontWeight, fontSize, fontFamily, paddingLeft, paddingRight, borderLeftWidth, borderRightWidth, whiteSpace, wordBreak, } = computedStyle;
|
|
3381
|
+
// `font` shorthand returns "" in Chromium/Firefox for shadow DOM elements
|
|
3382
|
+
// whose font was set via CSS custom properties. Build it from the individual
|
|
3383
|
+
// sub-properties which are always reliably populated.
|
|
3384
|
+
const resolvedFont = font === ''
|
|
3385
|
+
? `${fontStyle} ${fontWeight} ${fontSize} ${fontFamily}`.trim()
|
|
3386
|
+
: font;
|
|
3387
|
+
const parsedLineClamp = Number.parseInt(webkitLineClamp, 10);
|
|
3388
|
+
if (Number.isNaN(parsedLineClamp)) {
|
|
3389
|
+
return element.scrollWidth > element.clientWidth;
|
|
3390
|
+
}
|
|
3391
|
+
const parsedLineHeight = Number.parseFloat(lineHeight);
|
|
3392
|
+
if (Number.isNaN(parsedLineHeight)) {
|
|
3393
|
+
return element.scrollHeight > element.clientHeight;
|
|
3394
|
+
}
|
|
3395
|
+
const contentWidth = element.getBoundingClientRect().width -
|
|
3396
|
+
Number.parseFloat(paddingLeft) -
|
|
3397
|
+
Number.parseFloat(paddingRight) -
|
|
3398
|
+
Number.parseFloat(borderLeftWidth) -
|
|
3399
|
+
Number.parseFloat(borderRightWidth);
|
|
3400
|
+
if (contentWidth <= 0)
|
|
3401
|
+
return false;
|
|
3402
|
+
const text = element.textContent ?? '';
|
|
3403
|
+
if (text.trim() === '')
|
|
3404
|
+
return false;
|
|
3405
|
+
const parsedLetterSpacing = Number.parseFloat(computedStyle.letterSpacing);
|
|
3406
|
+
const letterSpacing = Number.isNaN(parsedLetterSpacing)
|
|
3407
|
+
? undefined
|
|
3408
|
+
: parsedLetterSpacing;
|
|
3409
|
+
try {
|
|
3410
|
+
const prepared = prepare(text, resolvedFont, {
|
|
3411
|
+
letterSpacing,
|
|
3412
|
+
whiteSpace: toPretextWhiteSpace(whiteSpace),
|
|
3413
|
+
wordBreak: toPretextWordBreak(wordBreak),
|
|
3414
|
+
});
|
|
3415
|
+
const { lineCount } = layout(prepared, contentWidth, parsedLineHeight);
|
|
3416
|
+
return lineCount > parsedLineClamp;
|
|
3417
|
+
}
|
|
3418
|
+
catch {
|
|
3419
|
+
return element.scrollHeight > parsedLineClamp * parsedLineHeight;
|
|
3420
|
+
}
|
|
3421
|
+
};
|
|
3422
|
+
const determineLinkIcon = (target,
|
|
3423
|
+
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
3424
|
+
rel) => {
|
|
3425
|
+
if (!(rel?.split(' ') ?? []).includes('external'))
|
|
3426
|
+
return undefined;
|
|
3427
|
+
return target === '_blank' ? 'external-new-tab-link' : 'external-link';
|
|
3428
|
+
};
|
|
3429
|
+
const resolveTarget = (target) => {
|
|
3430
|
+
const resolvedTarget = typeof target === 'function' ? target() : target;
|
|
3431
|
+
if (typeof resolvedTarget !== 'string')
|
|
3432
|
+
return resolvedTarget;
|
|
3433
|
+
const element = document.querySelector(resolvedTarget);
|
|
3434
|
+
if (element === null)
|
|
3435
|
+
throw new Error('String must resolve to an Element.');
|
|
3436
|
+
return element;
|
|
3437
|
+
};
|
|
3438
|
+
/**
|
|
3439
|
+
* Patched version of requestAnimationFrame that avoids ngzone
|
|
3440
|
+
* Use only when you know ngzone should not run
|
|
3441
|
+
*/
|
|
3442
|
+
const raf = (h) => {
|
|
3443
|
+
const win = window;
|
|
3444
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
3445
|
+
if (typeof win.__zone_symbol__requestAnimationFrame === 'function') {
|
|
3446
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
3447
|
+
return win.__zone_symbol__requestAnimationFrame(h);
|
|
3448
|
+
}
|
|
3449
|
+
if (typeof requestAnimationFrame === 'function') {
|
|
3450
|
+
return requestAnimationFrame(h);
|
|
3451
|
+
}
|
|
3452
|
+
return setTimeout(h);
|
|
3453
|
+
};
|
|
3454
|
+
/**
|
|
3455
|
+
* Waits for a component to be ready for
|
|
3456
|
+
* both custom element and non-custom element builds.
|
|
3457
|
+
* If non-custom element build, el.componentOnReady
|
|
3458
|
+
* will be used.
|
|
3459
|
+
* For custom element builds, we wait a frame
|
|
3460
|
+
* so that the inner contents of the component
|
|
3461
|
+
* have a chance to render.
|
|
3462
|
+
*
|
|
3463
|
+
* Use this utility rather than calling
|
|
3464
|
+
* el.componentOnReady yourself.
|
|
3465
|
+
*
|
|
3466
|
+
* Reference: https://stenciljs.com/docs/api#componentonready
|
|
3467
|
+
*/
|
|
3468
|
+
const componentOnReady = (element, callback) => {
|
|
3469
|
+
if (element.componentOnReady === undefined) {
|
|
3470
|
+
raf(() => {
|
|
3471
|
+
callback(element);
|
|
3472
|
+
});
|
|
3473
|
+
}
|
|
3474
|
+
else {
|
|
3475
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
3476
|
+
element.componentOnReady().then((resolvedElement) => {
|
|
3477
|
+
callback(resolvedElement);
|
|
3478
|
+
});
|
|
3479
|
+
}
|
|
3480
|
+
};
|
|
3481
|
+
const resolvePanelFromValue = (value) => {
|
|
3482
|
+
if (value instanceof HTMLElement) {
|
|
3483
|
+
return value;
|
|
3484
|
+
}
|
|
3485
|
+
if (typeof value === 'string') {
|
|
3486
|
+
const element = document.querySelector(value);
|
|
3487
|
+
return element instanceof HTMLElement ? element : undefined;
|
|
3488
|
+
}
|
|
3489
|
+
return undefined;
|
|
3490
|
+
};
|
|
3491
|
+
const resolvePanelElement = (tab) => {
|
|
3492
|
+
const panelValue = typeof tab.panel === 'function' ? tab.panel() : tab.panel;
|
|
3493
|
+
return resolvePanelFromValue(panelValue);
|
|
3494
|
+
};
|
|
3495
|
+
const HORIZONTAL_MOVE_KEYS = new Set([
|
|
3496
|
+
'ArrowLeft',
|
|
3497
|
+
'ArrowRight',
|
|
3498
|
+
'Home',
|
|
3499
|
+
'End',
|
|
3500
|
+
]);
|
|
3501
|
+
const VERTICAL_MOVE_KEYS = new Set([
|
|
3502
|
+
'ArrowUp',
|
|
3503
|
+
'ArrowDown',
|
|
3504
|
+
'Home',
|
|
3505
|
+
'End',
|
|
3506
|
+
]);
|
|
3507
|
+
const closestElement = (selector, base) => {
|
|
3508
|
+
function closestFrom(element) {
|
|
3509
|
+
if (element === document || element === globalThis)
|
|
3510
|
+
return undefined;
|
|
3511
|
+
const { assignedSlot } = element;
|
|
3512
|
+
// eslint-disable-next-line no-param-reassign
|
|
3513
|
+
if (assignedSlot)
|
|
3514
|
+
element = assignedSlot;
|
|
3515
|
+
const found = element.closest(selector);
|
|
3516
|
+
return (found ??
|
|
3517
|
+
closestFrom(element.getRootNode().host));
|
|
3518
|
+
}
|
|
3519
|
+
return closestFrom(base);
|
|
3520
|
+
};
|
|
3521
|
+
const isRTL = (element) => getComputedStyle(element).direction === 'rtl';
|
|
3522
|
+
const getSubmenuOpenKey = (element) => isRTL(element) ? 'ArrowLeft' : 'ArrowRight';
|
|
3523
|
+
const getSubmenuCloseKey = (element) => isRTL(element) ? 'ArrowRight' : 'ArrowLeft';
|
|
3524
|
+
const isCurrentPage = (url) => {
|
|
3525
|
+
try {
|
|
3526
|
+
const currentUrl = new URL(window.location.href);
|
|
3527
|
+
const targetUrl = new URL(url);
|
|
3528
|
+
return (currentUrl.origin === targetUrl.origin &&
|
|
3529
|
+
currentUrl.pathname === targetUrl.pathname);
|
|
3530
|
+
}
|
|
3531
|
+
catch {
|
|
3532
|
+
return false;
|
|
3533
|
+
}
|
|
3534
|
+
};
|
|
3535
|
+
|
|
3536
|
+
export { HORIZONTAL_MOVE_KEYS as H, VERTICAL_MOVE_KEYS as V, isEllipsisActive as a, isCurrentPage as b, inheritAriaAttributes as c, determineLinkIcon as d, pickInputEventAttributes as e, ignorePromise as f, isRTL as g, getSubmenuOpenKey as h, invariant as i, closestElement as j, getSubmenuCloseKey as k, propertyToPx as l, resolvePanelElement as m, componentOnReady as n, isTouchDevice as o, pickFocusEventAttributes as p, resolveTarget as r };
|
|
3537
|
+
//# sourceMappingURL=p-CaibVX_2.js.map
|
|
3538
|
+
|
|
3539
|
+
//# sourceMappingURL=p-CaibVX_2.js.map
|