@keymanapp/common-types 17.0.299-beta → 17.0.301-beta

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.
Files changed (142) hide show
  1. package/build/src/consts/virtual-key-constants.js +222 -221
  2. package/build/src/consts/virtual-key-constants.js.map +1 -1
  3. package/build/src/keyman-touch-layout/keyman-touch-layout-file-reader.js +73 -72
  4. package/build/src/keyman-touch-layout/keyman-touch-layout-file-reader.js.map +1 -1
  5. package/build/src/keyman-touch-layout/keyman-touch-layout-file-writer.js +121 -120
  6. package/build/src/keyman-touch-layout/keyman-touch-layout-file-writer.js.map +1 -1
  7. package/build/src/keyman-touch-layout/keyman-touch-layout-file.js +55 -54
  8. package/build/src/keyman-touch-layout/keyman-touch-layout-file.js.map +1 -1
  9. package/build/src/kmx/element-string.js +126 -125
  10. package/build/src/kmx/element-string.js.map +1 -1
  11. package/build/src/kmx/keyman-targets.js +80 -79
  12. package/build/src/kmx/keyman-targets.js.map +1 -1
  13. package/build/src/kmx/kmx-builder.js +190 -189
  14. package/build/src/kmx/kmx-builder.js.map +1 -1
  15. package/build/src/kmx/kmx-file-reader.js +135 -134
  16. package/build/src/kmx/kmx-file-reader.js.map +1 -1
  17. package/build/src/kmx/kmx-plus-builder/build-disp.js +28 -27
  18. package/build/src/kmx/kmx-plus-builder/build-disp.js.map +1 -1
  19. package/build/src/kmx/kmx-plus-builder/build-elem.js +90 -89
  20. package/build/src/kmx/kmx-plus-builder/build-elem.js.map +1 -1
  21. package/build/src/kmx/kmx-plus-builder/build-keys.js +108 -107
  22. package/build/src/kmx/kmx-plus-builder/build-keys.js.map +1 -1
  23. package/build/src/kmx/kmx-plus-builder/build-layr.js +102 -101
  24. package/build/src/kmx/kmx-plus-builder/build-layr.js.map +1 -1
  25. package/build/src/kmx/kmx-plus-builder/build-list.js +67 -66
  26. package/build/src/kmx/kmx-plus-builder/build-list.js.map +1 -1
  27. package/build/src/kmx/kmx-plus-builder/build-loca.js +22 -21
  28. package/build/src/kmx/kmx-plus-builder/build-loca.js.map +1 -1
  29. package/build/src/kmx/kmx-plus-builder/build-meta.js +23 -22
  30. package/build/src/kmx/kmx-plus-builder/build-meta.js.map +1 -1
  31. package/build/src/kmx/kmx-plus-builder/build-sect.js +16 -15
  32. package/build/src/kmx/kmx-plus-builder/build-sect.js.map +1 -1
  33. package/build/src/kmx/kmx-plus-builder/build-strs.js +47 -46
  34. package/build/src/kmx/kmx-plus-builder/build-strs.js.map +1 -1
  35. package/build/src/kmx/kmx-plus-builder/build-tran.js +70 -69
  36. package/build/src/kmx/kmx-plus-builder/build-tran.js.map +1 -1
  37. package/build/src/kmx/kmx-plus-builder/build-uset.js +61 -60
  38. package/build/src/kmx/kmx-plus-builder/build-uset.js.map +1 -1
  39. package/build/src/kmx/kmx-plus-builder/build-vars.js +49 -48
  40. package/build/src/kmx/kmx-plus-builder/build-vars.js.map +1 -1
  41. package/build/src/kmx/kmx-plus-builder/builder-section.js +5 -4
  42. package/build/src/kmx/kmx-plus-builder/builder-section.js.map +1 -1
  43. package/build/src/kmx/kmx-plus-builder/kmx-plus-builder.js +138 -137
  44. package/build/src/kmx/kmx-plus-builder/kmx-plus-builder.js.map +1 -1
  45. package/build/src/kmx/kmx-plus.js +831 -830
  46. package/build/src/kmx/kmx-plus.js.map +1 -1
  47. package/build/src/kmx/kmx.d.ts.map +1 -1
  48. package/build/src/kmx/kmx.js +303 -299
  49. package/build/src/kmx/kmx.js.map +1 -1
  50. package/build/src/kmx/string-list.js +89 -88
  51. package/build/src/kmx/string-list.js.map +1 -1
  52. package/build/src/kpj/keyman-developer-project.js +196 -195
  53. package/build/src/kpj/keyman-developer-project.js.map +1 -1
  54. package/build/src/kpj/kpj-file-reader.js +120 -119
  55. package/build/src/kpj/kpj-file-reader.js.map +1 -1
  56. package/build/src/kpj/kpj-file.js +13 -12
  57. package/build/src/kpj/kpj-file.js.map +1 -1
  58. package/build/src/kvk/kvk-file-reader.js +38 -37
  59. package/build/src/kvk/kvk-file-reader.js.map +1 -1
  60. package/build/src/kvk/kvk-file-writer.js +78 -77
  61. package/build/src/kvk/kvk-file-writer.js.map +1 -1
  62. package/build/src/kvk/kvk-file.js +91 -90
  63. package/build/src/kvk/kvk-file.js.map +1 -1
  64. package/build/src/kvk/kvks-file-reader.js +176 -175
  65. package/build/src/kvk/kvks-file-reader.js.map +1 -1
  66. package/build/src/kvk/kvks-file-writer.js +107 -106
  67. package/build/src/kvk/kvks-file-writer.js.map +1 -1
  68. package/build/src/kvk/kvks-file.js +12 -11
  69. package/build/src/kvk/kvks-file.js.map +1 -1
  70. package/build/src/kvk/visual-keyboard.js +76 -75
  71. package/build/src/kvk/visual-keyboard.js.map +1 -1
  72. package/build/src/ldml-keyboard/ldml-keyboard-testdata-xml.js +22 -21
  73. package/build/src/ldml-keyboard/ldml-keyboard-testdata-xml.js.map +1 -1
  74. package/build/src/ldml-keyboard/ldml-keyboard-xml-reader.js +410 -409
  75. package/build/src/ldml-keyboard/ldml-keyboard-xml-reader.js.map +1 -1
  76. package/build/src/ldml-keyboard/ldml-keyboard-xml.js +58 -57
  77. package/build/src/ldml-keyboard/ldml-keyboard-xml.js.map +1 -1
  78. package/build/src/ldml-keyboard/pattern-parser.js +491 -490
  79. package/build/src/ldml-keyboard/pattern-parser.js.map +1 -1
  80. package/build/src/ldml-keyboard/unicodeset-parser-api.js +30 -29
  81. package/build/src/ldml-keyboard/unicodeset-parser-api.js.map +1 -1
  82. package/build/src/main.js +35 -34
  83. package/build/src/main.js.map +1 -1
  84. package/build/src/package/kmp-json-file.js +4 -3
  85. package/build/src/package/kmp-json-file.js.map +1 -1
  86. package/build/src/package/kps-file.js +18 -17
  87. package/build/src/package/kps-file.js.map +1 -1
  88. package/build/src/schema-validators.js +28 -27
  89. package/build/src/schema-validators.js.map +1 -1
  90. package/build/src/schemas/displaymap.schema.js +38 -37
  91. package/build/src/schemas/displaymap.schema.js.map +1 -1
  92. package/build/src/schemas/displaymap.schema.validator.mjs +267 -266
  93. package/build/src/schemas/displaymap.schema.validator.mjs.map +1 -1
  94. package/build/src/schemas/keyboard_info.schema.js +101 -100
  95. package/build/src/schemas/keyboard_info.schema.js.map +1 -1
  96. package/build/src/schemas/keyboard_info.schema.validator.mjs +1161 -1160
  97. package/build/src/schemas/keyboard_info.schema.validator.mjs.map +1 -1
  98. package/build/src/schemas/keyman-touch-layout.clean.spec.js +154 -153
  99. package/build/src/schemas/keyman-touch-layout.clean.spec.js.map +1 -1
  100. package/build/src/schemas/keyman-touch-layout.clean.spec.validator.mjs +1095 -1094
  101. package/build/src/schemas/keyman-touch-layout.clean.spec.validator.mjs.map +1 -1
  102. package/build/src/schemas/keyman-touch-layout.spec.js +143 -142
  103. package/build/src/schemas/keyman-touch-layout.spec.js.map +1 -1
  104. package/build/src/schemas/keyman-touch-layout.spec.validator.mjs +1437 -1436
  105. package/build/src/schemas/keyman-touch-layout.spec.validator.mjs.map +1 -1
  106. package/build/src/schemas/kmp.schema.js +356 -355
  107. package/build/src/schemas/kmp.schema.js.map +1 -1
  108. package/build/src/schemas/kmp.schema.validator.mjs +1628 -1627
  109. package/build/src/schemas/kmp.schema.validator.mjs.map +1 -1
  110. package/build/src/schemas/kpj-9.0.schema.js +134 -133
  111. package/build/src/schemas/kpj-9.0.schema.js.map +1 -1
  112. package/build/src/schemas/kpj-9.0.schema.validator.mjs +656 -655
  113. package/build/src/schemas/kpj-9.0.schema.validator.mjs.map +1 -1
  114. package/build/src/schemas/kpj.schema.js +132 -131
  115. package/build/src/schemas/kpj.schema.js.map +1 -1
  116. package/build/src/schemas/kpj.schema.validator.mjs +516 -515
  117. package/build/src/schemas/kpj.schema.validator.mjs.map +1 -1
  118. package/build/src/schemas/kvks.schema.js +185 -184
  119. package/build/src/schemas/kvks.schema.js.map +1 -1
  120. package/build/src/schemas/kvks.schema.validator.mjs +626 -625
  121. package/build/src/schemas/kvks.schema.validator.mjs.map +1 -1
  122. package/build/src/schemas/ldml-keyboard3.schema.js +699 -698
  123. package/build/src/schemas/ldml-keyboard3.schema.js.map +1 -1
  124. package/build/src/schemas/ldml-keyboard3.schema.validator.mjs +3118 -3117
  125. package/build/src/schemas/ldml-keyboard3.schema.validator.mjs.map +1 -1
  126. package/build/src/schemas/ldml-keyboardtest3.schema.js +228 -227
  127. package/build/src/schemas/ldml-keyboardtest3.schema.js.map +1 -1
  128. package/build/src/schemas/ldml-keyboardtest3.schema.validator.mjs +745 -744
  129. package/build/src/schemas/ldml-keyboardtest3.schema.validator.mjs.map +1 -1
  130. package/build/src/schemas.js +26 -25
  131. package/build/src/schemas.js.map +1 -1
  132. package/build/src/util/common-events.js +29 -28
  133. package/build/src/util/common-events.js.map +1 -1
  134. package/build/src/util/compiler-interfaces.js +381 -380
  135. package/build/src/util/compiler-interfaces.js.map +1 -1
  136. package/build/src/util/errors.js +8 -7
  137. package/build/src/util/errors.js.map +1 -1
  138. package/build/src/util/file-types.js +143 -142
  139. package/build/src/util/file-types.js.map +1 -1
  140. package/build/src/util/util.js +369 -368
  141. package/build/src/util/util.js.map +1 -1
  142. package/package.json +2 -2
@@ -1,491 +1,492 @@
1
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="23ab9a3b-f038-558e-8336-0b220887762e")}catch(e){}}();
2
- /**
3
- * Utilities for transform and marker processing
4
- */
5
- import { constants } from "@keymanapp/ldml-keyboard-constants";
6
- import { MATCH_QUAD_ESCAPE, isOneChar, unescapeOneQuadString, unescapeString, hexQuad } from "../util/util.js";
7
- /**
8
- * Helper function for extracting matched items
9
- * @param str input string
10
- * @param match global RegEx to use
11
- * @returns array of matched values
12
- */
13
- function matchArray(str, match) {
14
- const refs = (str || '').matchAll(match);
15
- return Array.from(refs).map(r => r[1]);
16
- }
17
- /**
18
- * Common regex for an ID
19
- */
20
- const COMMON_ID = /^[0-9A-Za-z_]{1,32}$/;
21
- /**
22
- * Class for helping with markers
23
- */
24
- export class MarkerParser {
25
- /**
26
- * A marker id has the same constraint as a key id. TODO-LDML: Needs to be reflected in the spec
27
- */
28
- static ID = COMMON_ID;
29
- /**
30
- * Special marker reference referring to any marker
31
- */
32
- static ANY_MARKER = '\\m{.}';
33
- /**
34
- * id of the 'any' marker
35
- */
36
- static ANY_MARKER_ID = '.';
37
- /**
38
- * Marker sentinel as a string - U+FFFF
39
- */
40
- static SENTINEL = String.fromCodePoint(constants.uc_sentinel);
41
- /** Marker sentinel as a regex match */
42
- static SENTINEL_MATCH = '\\u' + hexQuad(constants.uc_sentinel);
43
- /**
44
- * Marker code as a string - U+0008
45
- */
46
- static MARKER_CODE = String.fromCodePoint(constants.marker_code);
47
- /** Marker code as a regex match */
48
- static MARKER_CODE_MATCH = '\\u' + hexQuad(constants.marker_code);
49
- /** Minimum ID (trailing code unit) */
50
- static MIN_MARKER_INDEX = constants.marker_min_index;
51
- /** Index meaning 'any marker' == `\m{.}` */
52
- static ANY_MARKER_INDEX = constants.marker_any_index;
53
- /** Maximum usable marker index */
54
- static MAX_MARKER_INDEX = constants.marker_max_index;
55
- /** Max count of markers */
56
- static MAX_MARKER_COUNT = constants.marker_max_count;
57
- static anyMarkerMatch() {
58
- const start = hexQuad(MarkerParser.MIN_MARKER_INDEX);
59
- const end = hexQuad(MarkerParser.MAX_MARKER_INDEX);
60
- return `${MarkerParser.SENTINEL_MATCH}${MarkerParser.MARKER_CODE_MATCH}[\\u${start}-\\u${end}]`; // TODO-LDML: #9121 wrong escape format
61
- }
62
- /** Expression that matches any marker */
63
- static ANY_MARKER_MATCH = MarkerParser.anyMarkerMatch();
64
- /**
65
- * Pattern for matching a marker reference, OR the special marker \m{.}
66
- */
67
- static REFERENCE = /\\m{([0-9A-Za-z_]{1,32}|\.)}/g;
68
- /**
69
- * parse a string into marker references
70
- * @param str input string such as "\m{a} … \m{.}"
71
- * @returns `[]` or an array of all markers referenced
72
- */
73
- static allReferences(str) {
74
- if (!str) {
75
- return [];
76
- }
77
- return matchArray(str, MarkerParser.REFERENCE);
78
- }
79
- static markerCodeToString(n, forMatch) {
80
- if (!forMatch) {
81
- return String.fromCharCode(n);
82
- }
83
- else {
84
- return `\\u${hexQuad(n)}`; // TODO-LDML: #9121 wrong escape format
85
- }
86
- }
87
- /** @returns string for marker #n */
88
- static markerOutput(n, forMatch) {
89
- if (n < MarkerParser.MIN_MARKER_INDEX || n > MarkerParser.ANY_MARKER_INDEX) {
90
- throw RangeError(`Internal Error: marker index out of range ${n}`);
91
- }
92
- if (forMatch) {
93
- return MarkerParser.SENTINEL_MATCH + MarkerParser.MARKER_CODE_MATCH + MarkerParser.markerCodeToString(n, forMatch);
94
- }
95
- else {
96
- return MarkerParser.SENTINEL + MarkerParser.MARKER_CODE + MarkerParser.markerCodeToString(n, forMatch);
97
- }
98
- }
99
- /** @returns all marker strings as sentinel values */
100
- static toSentinelString(s, markers, forMatch) {
101
- if (!s)
102
- return s;
103
- return s.replaceAll(MarkerParser.REFERENCE, (sub, arg) => {
104
- if (arg === MarkerParser.ANY_MARKER_ID) {
105
- if (forMatch) {
106
- return MarkerParser.ANY_MARKER_MATCH;
107
- }
108
- return MarkerParser.markerOutput(MarkerParser.ANY_MARKER_INDEX);
109
- }
110
- if (!markers) {
111
- throw RangeError(`Internal Error: Could not find marker \\m{${arg}} (no markers defined)`);
112
- }
113
- const order = markers.getItemOrder(arg);
114
- if (order === -1) {
115
- throw RangeError(`Internal Error: Could not find marker \\m{${arg}}`);
116
- }
117
- else if (order > MarkerParser.MAX_MARKER_INDEX) {
118
- throw RangeError(`Internal Error: marker \\m{${arg}} has out of range index ${order}`);
119
- }
120
- else {
121
- return MarkerParser.markerOutput(order + 1, forMatch);
122
- }
123
- });
124
- }
125
- /**
126
- * NFD a string, respecting markers.
127
- * @param s input string
128
- * @param forMatch true if regex, false if individual
129
- * @returns the normalized string
130
- */
131
- static nfd_markers(s, forMatch) {
132
- const m = [];
133
- return this.nfd_markers_segment(s, m, forMatch);
134
- }
135
- /**
136
- * NFD a safe subset of a string, respecting markers
137
- * @param s input string
138
- * @param map output array of marker chars
139
- * @param forMatch true if used for regexes
140
- * @returns the updated string
141
- */
142
- static nfd_markers_segment(s, map, forMatch) {
143
- // remove (and parse) the markers first
144
- const str_unmarked = MarkerParser.remove_markers(s, map, forMatch);
145
- // then, NFD the normalized string
146
- const str_unmarked_nfd = str_unmarked.normalize("NFD");
147
- if (map.length == 0) {
148
- // no markers, so we can safely return the normalized unmarked string
149
- return str_unmarked_nfd;
150
- }
151
- else if (str_unmarked_nfd === str_unmarked) {
152
- // normalization didn't shuffle anything, so it's entirely a no-op.
153
- return s;
154
- }
155
- else {
156
- // we had markers AND the normalization made a difference.
157
- // add the markers back per the map, and return
158
- return MarkerParser.add_back_markers(str_unmarked_nfd, map, forMatch);
159
- }
160
- }
161
- /** return the string s but with a marker sequence before it */
162
- static prepend_marker(s, marker, forMatch) {
163
- if (forMatch && marker === constants.marker_any_index) {
164
- return MarkerParser.ANY_MARKER_MATCH + s;
165
- }
166
- else {
167
- return MarkerParser.markerOutput(marker, forMatch) + s;
168
- }
169
- }
170
- /**
171
- * Add back all markers in the map to the string
172
- * @param s input string
173
- * @param map output: the marker map
174
- * @param forMatch if true, use regex format
175
- */
176
- static add_back_markers(s, map, forMatch) {
177
- // quick check: if no string, or no map: nothing to do
178
- if (!s || !map?.length) {
179
- return s;
180
- }
181
- /** output string */
182
- let out = '';
183
- /** for checking: the total number of markers expected, skipping end markers */
184
- const max_markers = map.filter(({ end }) => !end).length;
185
- /** for checking: the number of markers we've written */
186
- let written_markers = 0;
187
- /** we are going to mutate the map, so copy it */
188
- const map2 = [...map]; // make a copy
189
- // First, add back all 'MARKER_BEFORE_EOT' markers
190
- while (map2.length && map2[map2.length - 1].ch === MARKER_BEFORE_EOT) {
191
- // remove from list
192
- const { marker, end } = map2.pop();
193
- if (!end) {
194
- out = MarkerParser.prepend_marker(out, marker, forMatch);
195
- written_markers++;
196
- }
197
- }
198
- // Then, take each codepoint (from back to front)
199
- for (let p of [...s].reverse()) {
200
- // reverse order code units, prepend to out
201
- out = p + out;
202
- for (let i = map2.length - 1; i >= 0; i--) {
203
- const { ch, marker, processed, end } = map2[i];
204
- if (ch === p && !processed) {
205
- map2[i].processed = true; // mark as processed
206
- if (end) {
207
- break; // exit loop
208
- }
209
- else {
210
- out = MarkerParser.prepend_marker(out, marker, forMatch);
211
- written_markers++;
212
- }
213
- }
214
- else if (map2[map2.length - 1]?.processed) {
215
- // keep the list as short as possible
216
- map2.pop();
217
- }
218
- }
219
- }
220
- // validate that we consumed all markers
221
- if (written_markers !== max_markers) {
222
- throw Error(`Internal Error: should have written ${max_markers} markers but only wrote ${written_markers}`);
223
- }
224
- return out;
225
- }
226
- /**
227
- * Remove (and parse) markers from a string
228
- * @param s input string
229
- * @param map output map containing marker locations
230
- * @param forMatch true if regex
231
- * @returns the original string, without any markers
232
- */
233
- static remove_markers(s, map, forMatch) {
234
- /** accumulated output */
235
- let out = '';
236
- /** array of marker ids in order waiting to be added */
237
- let last_markers = [];
238
- /** input string, split into codepoint runs */
239
- let a = [...s];
240
- /** were any markers found? */
241
- let had_markers = false;
242
- /**
243
- * subfunc: add all markers in the pending (last_markers) queue
244
- * @param l string the marker is 'glued' to, or '' for end
245
- */
246
- function add_pending_markers(l) {
247
- // first char, or, marker-before-eot
248
- const glueChars = (l === '') ? [MARKER_BEFORE_EOT] : [...(l.normalize("NFD"))];
249
- const glue = glueChars[0];
250
- // push the 'end' value
251
- map.push({ ch: glue, end: true });
252
- while (last_markers.length) {
253
- const marker = last_markers[0];
254
- last_markers = last_markers.slice(1); // pop from front
255
- map.push({ ch: glue, marker });
256
- }
257
- // now, push the rest of the glue chars as an NFD sequence.
258
- // For example, `\m{m}\u0344` will create the following stream:
259
- // { ch: 0308, end: true}
260
- // { ch: 0308, marker: 1}
261
- // { ch: 0301, end: true} // added because of decomp
262
- for (const ch of glueChars.slice(1)) {
263
- map.push({ ch, end: true });
264
- }
265
- }
266
- // iterate until the codepoint list is empty
267
- while (a.length > 0) {
268
- // does 'a' begin with a marker?
269
- const p = MarkerParser.parse_next_marker(a.join(''), forMatch);
270
- if (!p?.match) {
271
- // no match
272
- add_pending_markers(a[0]); // add any pending markers
273
- out = out + a[0]; // add the non-marker text to the buffer
274
- a = a.slice(1); // move forward 1 codepoint
275
- }
276
- else {
277
- // found a marker
278
- had_markers = true;
279
- const { marker, match } = p;
280
- if ((marker == constants.marker_any_index) ||
281
- (marker >= constants.marker_min_index && marker <= constants.marker_max_index)) {
282
- last_markers.push(marker);
283
- }
284
- else {
285
- throw RangeError(`String contained out-of-range marker ${marker}: '${s}'`);
286
- }
287
- a = a.slice([...match].length); // move forward over matched marker
288
- }
289
- }
290
- // add any remaining markers at the end of the string
291
- add_pending_markers('');
292
- if (!had_markers) {
293
- // no markers were found. clear out the map.
294
- map = [];
295
- }
296
- return out;
297
- }
298
- /**
299
- * analyze the string to see if it begins with a marker
300
- * @param s input string
301
- * @param forMatch true if regex
302
- * @returns parsed marker details
303
- */
304
- static parse_next_marker(s, forMatch) {
305
- if (!forMatch) {
306
- // plain
307
- const m = s.match(PARSE_SENTINEL_MARKER);
308
- if (m) {
309
- // full string matched
310
- const match = m[0];
311
- // extract the marker number
312
- const marker = match.codePointAt(2);
313
- return ({ match, marker });
314
- }
315
- }
316
- else {
317
- // regex
318
- const m = s.match(PARSE_REGEX_MARKER);
319
- if (m) {
320
- // full string
321
- const match = m[0];
322
- // hex digit (if a single)
323
- const single = m[1];
324
- if (single) {
325
- return ({ match, marker: Number.parseInt(single.substring(3), 16) });
326
- }
327
- else {
328
- // it's a range, so it's an any match
329
- return ({ match, marker: constants.marker_any_index });
330
- }
331
- }
332
- }
333
- return null;
334
- }
335
- }
336
- ;
337
- /** special noncharacter value denoting end of string */
338
- export const MARKER_BEFORE_EOT = '\ufffe';
339
- /** matcher for a sentinel */
340
- const PARSE_SENTINEL_MARKER = new RegExp(`^${MarkerParser.ANY_MARKER_MATCH}`);
341
- /** matcher for a regex marker, either single or any */
342
- const PARSE_REGEX_MARKER = /^\\uffff\\u0008(?:(\\u[0-9a-fA-F]{4})|(\[\\u[0-9a-fA-F]{4}-\\u[0-9a-fA-F]{4}\]))/;
343
- ;
344
- ;
345
- /**
346
- * Class for helping with markers
347
- */
348
- export class VariableParser {
349
- /**
350
- * A marker id has the same constraint as a key id. TODO-LDML: Needs to be reflected in the spec
351
- */
352
- static ID = COMMON_ID;
353
- /**
354
- * Pattern for matching a string reference `$(str)`
355
- */
356
- static STRING_REFERENCE = /\${([0-9A-Za-z_]{1,32})}/g;
357
- /**
358
- * Pattern for matching a set reference `$[set]`
359
- */
360
- static SET_REFERENCE = /\$\[([0-9A-Za-z_]{1,32})\]/g;
361
- /**
362
- * Pattern for matching a capture set reference `($[set])`
363
- */
364
- static CAPTURE_SET_REFERENCE = /\(\$\[([0-9A-Za-z_]{1,32})\]\)/;
365
- /**
366
- * `$[1:variable]`
367
- * This regex matches the whole string.
368
- */
369
- static MAPPED_SET_REFERENCE = /^\$\[1:([0-9A-Za-z_]{1,32})\]$/;
370
- /**
371
- * parse a string into references
372
- * @param str input string
373
- * @returns `[]` or an array of all string references referenced
374
- */
375
- static allStringReferences(str) {
376
- return matchArray(str, VariableParser.STRING_REFERENCE);
377
- }
378
- /**
379
- * parse a string into references
380
- * @param str input string
381
- * @returns `[]` or an array of all string references referenced
382
- */
383
- static allSetReferences(str) {
384
- return matchArray(str, VariableParser.SET_REFERENCE);
385
- }
386
- /**
387
- * Split an input string into a proper set
388
- * @param str input string
389
- * @returns
390
- */
391
- static setSplitter(str) {
392
- const s = str?.trim();
393
- if (!s)
394
- return [];
395
- return s.split(/\s+/);
396
- }
397
- }
398
- /** for ElementParser.segment() */
399
- export var ElementType;
400
- (function (ElementType) {
401
- ElementType["codepoint"] = ".";
402
- ElementType["escaped"] = "\\";
403
- ElementType["uset"] = "[";
404
- ElementType["string"] = "*";
405
- })(ElementType || (ElementType = {}));
406
- ;
407
- /** one portion of a segmented element string */
408
- export class ElementSegment {
409
- segment;
410
- type;
411
- /**
412
- * @param segment the string in the segment
413
- * @param type type of segment. Will be calculated if not provided.
414
- */
415
- constructor(segment, type) {
416
- this.segment = segment;
417
- if (type) {
418
- this.type = type;
419
- }
420
- else if (ElementParser.MATCH_USET.test(segment)) {
421
- this.type = ElementType.uset;
422
- }
423
- else if (ElementParser.MATCH_ESCAPED.test(segment)) {
424
- this.type = ElementType.escaped;
425
- }
426
- else {
427
- this.type = ElementType.codepoint;
428
- }
429
- }
430
- /** unescaped format */
431
- get unescaped() {
432
- if (this.type !== ElementType.escaped) {
433
- return this.segment;
434
- }
435
- else {
436
- if (MATCH_QUAD_ESCAPE.test(this.segment)) {
437
- return unescapeOneQuadString(this.segment);
438
- }
439
- else {
440
- return unescapeString(this.segment);
441
- }
442
- }
443
- }
444
- }
445
- ;
446
- /** Class for helping with Element strings (i.e. reorder) */
447
- export class ElementParser {
448
- /**
449
- * Matches any complex UnicodeSet that would otherwise be misinterpreted
450
- * by `MATCH_ELEMENT_SEGMENTS` due to nested `[]`'s.
451
- * For example, `[[a-z]-[aeiou]]` could be
452
- * mis-segmented into `[[a-z]`, `-`, `[aeiou]`, `]` */
453
- static MATCH_NESTED_SQUARE_BRACKETS = /\[[^\]]*\[/;
454
- /** Match (segment) UnicodeSets OR hex escapes OR single Unicode codepoints */
455
- static MATCH_ELEMENT_SEGMENTS = /(?:\[[^\]]*\]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]{1,6}\}|\\u\{(?:[0-9a-fA-F]{1,6})(?: [0-9a-fA-F]{1,6}){1,}\}|.)/gu;
456
- /** Does it start with a UnicodeSet? Used to test the segments. */
457
- static MATCH_USET = /^\[/;
458
- /** Does it start with an escaped char? Used to test the segments. */
459
- static MATCH_ESCAPED = /^\\u/;
460
- /** Split a string into ElementSegments */
461
- static segment(str) {
462
- if (ElementParser.MATCH_NESTED_SQUARE_BRACKETS.test(str)) {
463
- throw Error(`Unsupported: nested square brackets in element segment: ${str}`);
464
- }
465
- const list = [];
466
- for (let m of str.match(ElementParser.MATCH_ELEMENT_SEGMENTS)) {
467
- const e = new ElementSegment(m);
468
- if (e.type === ElementType.escaped) {
469
- // unescape
470
- const { unescaped } = e;
471
- if (isOneChar(unescaped)) {
472
- list.push(e);
473
- }
474
- else {
475
- // need to split the escaped segment, \u{41 42} -> \u{41}, \u{42}
476
- for (let s of unescaped) {
477
- list.push(new ElementSegment(`\\u{${s.codePointAt(0).toString(16)}}`));
478
- }
479
- }
480
- }
481
- else {
482
- // all others
483
- list.push(e);
484
- }
485
- }
486
- return list;
487
- }
488
- }
489
- ;
490
- //# debugId=23ab9a3b-f038-558e-8336-0b220887762e
1
+ /**
2
+ * Utilities for transform and marker processing
3
+ */
4
+
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9510fffa-cd53-504b-958e-23524b16749a")}catch(e){}}();
6
+ import { constants } from "@keymanapp/ldml-keyboard-constants";
7
+ import { MATCH_QUAD_ESCAPE, isOneChar, unescapeOneQuadString, unescapeString, hexQuad } from "../util/util.js";
8
+ /**
9
+ * Helper function for extracting matched items
10
+ * @param str input string
11
+ * @param match global RegEx to use
12
+ * @returns array of matched values
13
+ */
14
+ function matchArray(str, match) {
15
+ const refs = (str || '').matchAll(match);
16
+ return Array.from(refs).map(r => r[1]);
17
+ }
18
+ /**
19
+ * Common regex for an ID
20
+ */
21
+ const COMMON_ID = /^[0-9A-Za-z_]{1,32}$/;
22
+ /**
23
+ * Class for helping with markers
24
+ */
25
+ export class MarkerParser {
26
+ /**
27
+ * A marker id has the same constraint as a key id. TODO-LDML: Needs to be reflected in the spec
28
+ */
29
+ static ID = COMMON_ID;
30
+ /**
31
+ * Special marker reference referring to any marker
32
+ */
33
+ static ANY_MARKER = '\\m{.}';
34
+ /**
35
+ * id of the 'any' marker
36
+ */
37
+ static ANY_MARKER_ID = '.';
38
+ /**
39
+ * Marker sentinel as a string - U+FFFF
40
+ */
41
+ static SENTINEL = String.fromCodePoint(constants.uc_sentinel);
42
+ /** Marker sentinel as a regex match */
43
+ static SENTINEL_MATCH = '\\u' + hexQuad(constants.uc_sentinel);
44
+ /**
45
+ * Marker code as a string - U+0008
46
+ */
47
+ static MARKER_CODE = String.fromCodePoint(constants.marker_code);
48
+ /** Marker code as a regex match */
49
+ static MARKER_CODE_MATCH = '\\u' + hexQuad(constants.marker_code);
50
+ /** Minimum ID (trailing code unit) */
51
+ static MIN_MARKER_INDEX = constants.marker_min_index;
52
+ /** Index meaning 'any marker' == `\m{.}` */
53
+ static ANY_MARKER_INDEX = constants.marker_any_index;
54
+ /** Maximum usable marker index */
55
+ static MAX_MARKER_INDEX = constants.marker_max_index;
56
+ /** Max count of markers */
57
+ static MAX_MARKER_COUNT = constants.marker_max_count;
58
+ static anyMarkerMatch() {
59
+ const start = hexQuad(MarkerParser.MIN_MARKER_INDEX);
60
+ const end = hexQuad(MarkerParser.MAX_MARKER_INDEX);
61
+ return `${MarkerParser.SENTINEL_MATCH}${MarkerParser.MARKER_CODE_MATCH}[\\u${start}-\\u${end}]`; // TODO-LDML: #9121 wrong escape format
62
+ }
63
+ /** Expression that matches any marker */
64
+ static ANY_MARKER_MATCH = MarkerParser.anyMarkerMatch();
65
+ /**
66
+ * Pattern for matching a marker reference, OR the special marker \m{.}
67
+ */
68
+ static REFERENCE = /\\m{([0-9A-Za-z_]{1,32}|\.)}/g;
69
+ /**
70
+ * parse a string into marker references
71
+ * @param str input string such as "\m{a} … \m{.}"
72
+ * @returns `[]` or an array of all markers referenced
73
+ */
74
+ static allReferences(str) {
75
+ if (!str) {
76
+ return [];
77
+ }
78
+ return matchArray(str, MarkerParser.REFERENCE);
79
+ }
80
+ static markerCodeToString(n, forMatch) {
81
+ if (!forMatch) {
82
+ return String.fromCharCode(n);
83
+ }
84
+ else {
85
+ return `\\u${hexQuad(n)}`; // TODO-LDML: #9121 wrong escape format
86
+ }
87
+ }
88
+ /** @returns string for marker #n */
89
+ static markerOutput(n, forMatch) {
90
+ if (n < MarkerParser.MIN_MARKER_INDEX || n > MarkerParser.ANY_MARKER_INDEX) {
91
+ throw RangeError(`Internal Error: marker index out of range ${n}`);
92
+ }
93
+ if (forMatch) {
94
+ return MarkerParser.SENTINEL_MATCH + MarkerParser.MARKER_CODE_MATCH + MarkerParser.markerCodeToString(n, forMatch);
95
+ }
96
+ else {
97
+ return MarkerParser.SENTINEL + MarkerParser.MARKER_CODE + MarkerParser.markerCodeToString(n, forMatch);
98
+ }
99
+ }
100
+ /** @returns all marker strings as sentinel values */
101
+ static toSentinelString(s, markers, forMatch) {
102
+ if (!s)
103
+ return s;
104
+ return s.replaceAll(MarkerParser.REFERENCE, (sub, arg) => {
105
+ if (arg === MarkerParser.ANY_MARKER_ID) {
106
+ if (forMatch) {
107
+ return MarkerParser.ANY_MARKER_MATCH;
108
+ }
109
+ return MarkerParser.markerOutput(MarkerParser.ANY_MARKER_INDEX);
110
+ }
111
+ if (!markers) {
112
+ throw RangeError(`Internal Error: Could not find marker \\m{${arg}} (no markers defined)`);
113
+ }
114
+ const order = markers.getItemOrder(arg);
115
+ if (order === -1) {
116
+ throw RangeError(`Internal Error: Could not find marker \\m{${arg}}`);
117
+ }
118
+ else if (order > MarkerParser.MAX_MARKER_INDEX) {
119
+ throw RangeError(`Internal Error: marker \\m{${arg}} has out of range index ${order}`);
120
+ }
121
+ else {
122
+ return MarkerParser.markerOutput(order + 1, forMatch);
123
+ }
124
+ });
125
+ }
126
+ /**
127
+ * NFD a string, respecting markers.
128
+ * @param s input string
129
+ * @param forMatch true if regex, false if individual
130
+ * @returns the normalized string
131
+ */
132
+ static nfd_markers(s, forMatch) {
133
+ const m = [];
134
+ return this.nfd_markers_segment(s, m, forMatch);
135
+ }
136
+ /**
137
+ * NFD a safe subset of a string, respecting markers
138
+ * @param s input string
139
+ * @param map output array of marker chars
140
+ * @param forMatch true if used for regexes
141
+ * @returns the updated string
142
+ */
143
+ static nfd_markers_segment(s, map, forMatch) {
144
+ // remove (and parse) the markers first
145
+ const str_unmarked = MarkerParser.remove_markers(s, map, forMatch);
146
+ // then, NFD the normalized string
147
+ const str_unmarked_nfd = str_unmarked.normalize("NFD");
148
+ if (map.length == 0) {
149
+ // no markers, so we can safely return the normalized unmarked string
150
+ return str_unmarked_nfd;
151
+ }
152
+ else if (str_unmarked_nfd === str_unmarked) {
153
+ // normalization didn't shuffle anything, so it's entirely a no-op.
154
+ return s;
155
+ }
156
+ else {
157
+ // we had markers AND the normalization made a difference.
158
+ // add the markers back per the map, and return
159
+ return MarkerParser.add_back_markers(str_unmarked_nfd, map, forMatch);
160
+ }
161
+ }
162
+ /** return the string s but with a marker sequence before it */
163
+ static prepend_marker(s, marker, forMatch) {
164
+ if (forMatch && marker === constants.marker_any_index) {
165
+ return MarkerParser.ANY_MARKER_MATCH + s;
166
+ }
167
+ else {
168
+ return MarkerParser.markerOutput(marker, forMatch) + s;
169
+ }
170
+ }
171
+ /**
172
+ * Add back all markers in the map to the string
173
+ * @param s input string
174
+ * @param map output: the marker map
175
+ * @param forMatch if true, use regex format
176
+ */
177
+ static add_back_markers(s, map, forMatch) {
178
+ // quick check: if no string, or no map: nothing to do
179
+ if (!s || !map?.length) {
180
+ return s;
181
+ }
182
+ /** output string */
183
+ let out = '';
184
+ /** for checking: the total number of markers expected, skipping end markers */
185
+ const max_markers = map.filter(({ end }) => !end).length;
186
+ /** for checking: the number of markers we've written */
187
+ let written_markers = 0;
188
+ /** we are going to mutate the map, so copy it */
189
+ const map2 = [...map]; // make a copy
190
+ // First, add back all 'MARKER_BEFORE_EOT' markers
191
+ while (map2.length && map2[map2.length - 1].ch === MARKER_BEFORE_EOT) {
192
+ // remove from list
193
+ const { marker, end } = map2.pop();
194
+ if (!end) {
195
+ out = MarkerParser.prepend_marker(out, marker, forMatch);
196
+ written_markers++;
197
+ }
198
+ }
199
+ // Then, take each codepoint (from back to front)
200
+ for (let p of [...s].reverse()) {
201
+ // reverse order code units, prepend to out
202
+ out = p + out;
203
+ for (let i = map2.length - 1; i >= 0; i--) {
204
+ const { ch, marker, processed, end } = map2[i];
205
+ if (ch === p && !processed) {
206
+ map2[i].processed = true; // mark as processed
207
+ if (end) {
208
+ break; // exit loop
209
+ }
210
+ else {
211
+ out = MarkerParser.prepend_marker(out, marker, forMatch);
212
+ written_markers++;
213
+ }
214
+ }
215
+ else if (map2[map2.length - 1]?.processed) {
216
+ // keep the list as short as possible
217
+ map2.pop();
218
+ }
219
+ }
220
+ }
221
+ // validate that we consumed all markers
222
+ if (written_markers !== max_markers) {
223
+ throw Error(`Internal Error: should have written ${max_markers} markers but only wrote ${written_markers}`);
224
+ }
225
+ return out;
226
+ }
227
+ /**
228
+ * Remove (and parse) markers from a string
229
+ * @param s input string
230
+ * @param map output map containing marker locations
231
+ * @param forMatch true if regex
232
+ * @returns the original string, without any markers
233
+ */
234
+ static remove_markers(s, map, forMatch) {
235
+ /** accumulated output */
236
+ let out = '';
237
+ /** array of marker ids in order waiting to be added */
238
+ let last_markers = [];
239
+ /** input string, split into codepoint runs */
240
+ let a = [...s];
241
+ /** were any markers found? */
242
+ let had_markers = false;
243
+ /**
244
+ * subfunc: add all markers in the pending (last_markers) queue
245
+ * @param l string the marker is 'glued' to, or '' for end
246
+ */
247
+ function add_pending_markers(l) {
248
+ // first char, or, marker-before-eot
249
+ const glueChars = (l === '') ? [MARKER_BEFORE_EOT] : [...(l.normalize("NFD"))];
250
+ const glue = glueChars[0];
251
+ // push the 'end' value
252
+ map.push({ ch: glue, end: true });
253
+ while (last_markers.length) {
254
+ const marker = last_markers[0];
255
+ last_markers = last_markers.slice(1); // pop from front
256
+ map.push({ ch: glue, marker });
257
+ }
258
+ // now, push the rest of the glue chars as an NFD sequence.
259
+ // For example, `\m{m}\u0344` will create the following stream:
260
+ // { ch: 0308, end: true}
261
+ // { ch: 0308, marker: 1}
262
+ // { ch: 0301, end: true} // added because of decomp
263
+ for (const ch of glueChars.slice(1)) {
264
+ map.push({ ch, end: true });
265
+ }
266
+ }
267
+ // iterate until the codepoint list is empty
268
+ while (a.length > 0) {
269
+ // does 'a' begin with a marker?
270
+ const p = MarkerParser.parse_next_marker(a.join(''), forMatch);
271
+ if (!p?.match) {
272
+ // no match
273
+ add_pending_markers(a[0]); // add any pending markers
274
+ out = out + a[0]; // add the non-marker text to the buffer
275
+ a = a.slice(1); // move forward 1 codepoint
276
+ }
277
+ else {
278
+ // found a marker
279
+ had_markers = true;
280
+ const { marker, match } = p;
281
+ if ((marker == constants.marker_any_index) ||
282
+ (marker >= constants.marker_min_index && marker <= constants.marker_max_index)) {
283
+ last_markers.push(marker);
284
+ }
285
+ else {
286
+ throw RangeError(`String contained out-of-range marker ${marker}: '${s}'`);
287
+ }
288
+ a = a.slice([...match].length); // move forward over matched marker
289
+ }
290
+ }
291
+ // add any remaining markers at the end of the string
292
+ add_pending_markers('');
293
+ if (!had_markers) {
294
+ // no markers were found. clear out the map.
295
+ map = [];
296
+ }
297
+ return out;
298
+ }
299
+ /**
300
+ * analyze the string to see if it begins with a marker
301
+ * @param s input string
302
+ * @param forMatch true if regex
303
+ * @returns parsed marker details
304
+ */
305
+ static parse_next_marker(s, forMatch) {
306
+ if (!forMatch) {
307
+ // plain
308
+ const m = s.match(PARSE_SENTINEL_MARKER);
309
+ if (m) {
310
+ // full string matched
311
+ const match = m[0];
312
+ // extract the marker number
313
+ const marker = match.codePointAt(2);
314
+ return ({ match, marker });
315
+ }
316
+ }
317
+ else {
318
+ // regex
319
+ const m = s.match(PARSE_REGEX_MARKER);
320
+ if (m) {
321
+ // full string
322
+ const match = m[0];
323
+ // hex digit (if a single)
324
+ const single = m[1];
325
+ if (single) {
326
+ return ({ match, marker: Number.parseInt(single.substring(3), 16) });
327
+ }
328
+ else {
329
+ // it's a range, so it's an any match
330
+ return ({ match, marker: constants.marker_any_index });
331
+ }
332
+ }
333
+ }
334
+ return null;
335
+ }
336
+ }
337
+ ;
338
+ /** special noncharacter value denoting end of string */
339
+ export const MARKER_BEFORE_EOT = '\ufffe';
340
+ /** matcher for a sentinel */
341
+ const PARSE_SENTINEL_MARKER = new RegExp(`^${MarkerParser.ANY_MARKER_MATCH}`);
342
+ /** matcher for a regex marker, either single or any */
343
+ const PARSE_REGEX_MARKER = /^\\uffff\\u0008(?:(\\u[0-9a-fA-F]{4})|(\[\\u[0-9a-fA-F]{4}-\\u[0-9a-fA-F]{4}\]))/;
344
+ ;
345
+ ;
346
+ /**
347
+ * Class for helping with markers
348
+ */
349
+ export class VariableParser {
350
+ /**
351
+ * A marker id has the same constraint as a key id. TODO-LDML: Needs to be reflected in the spec
352
+ */
353
+ static ID = COMMON_ID;
354
+ /**
355
+ * Pattern for matching a string reference `$(str)`
356
+ */
357
+ static STRING_REFERENCE = /\${([0-9A-Za-z_]{1,32})}/g;
358
+ /**
359
+ * Pattern for matching a set reference `$[set]`
360
+ */
361
+ static SET_REFERENCE = /\$\[([0-9A-Za-z_]{1,32})\]/g;
362
+ /**
363
+ * Pattern for matching a capture set reference `($[set])`
364
+ */
365
+ static CAPTURE_SET_REFERENCE = /\(\$\[([0-9A-Za-z_]{1,32})\]\)/;
366
+ /**
367
+ * `$[1:variable]`
368
+ * This regex matches the whole string.
369
+ */
370
+ static MAPPED_SET_REFERENCE = /^\$\[1:([0-9A-Za-z_]{1,32})\]$/;
371
+ /**
372
+ * parse a string into references
373
+ * @param str input string
374
+ * @returns `[]` or an array of all string references referenced
375
+ */
376
+ static allStringReferences(str) {
377
+ return matchArray(str, VariableParser.STRING_REFERENCE);
378
+ }
379
+ /**
380
+ * parse a string into references
381
+ * @param str input string
382
+ * @returns `[]` or an array of all string references referenced
383
+ */
384
+ static allSetReferences(str) {
385
+ return matchArray(str, VariableParser.SET_REFERENCE);
386
+ }
387
+ /**
388
+ * Split an input string into a proper set
389
+ * @param str input string
390
+ * @returns
391
+ */
392
+ static setSplitter(str) {
393
+ const s = str?.trim();
394
+ if (!s)
395
+ return [];
396
+ return s.split(/\s+/);
397
+ }
398
+ }
399
+ /** for ElementParser.segment() */
400
+ export var ElementType;
401
+ (function (ElementType) {
402
+ ElementType["codepoint"] = ".";
403
+ ElementType["escaped"] = "\\";
404
+ ElementType["uset"] = "[";
405
+ ElementType["string"] = "*";
406
+ })(ElementType || (ElementType = {}));
407
+ ;
408
+ /** one portion of a segmented element string */
409
+ export class ElementSegment {
410
+ segment;
411
+ type;
412
+ /**
413
+ * @param segment the string in the segment
414
+ * @param type type of segment. Will be calculated if not provided.
415
+ */
416
+ constructor(segment, type) {
417
+ this.segment = segment;
418
+ if (type) {
419
+ this.type = type;
420
+ }
421
+ else if (ElementParser.MATCH_USET.test(segment)) {
422
+ this.type = ElementType.uset;
423
+ }
424
+ else if (ElementParser.MATCH_ESCAPED.test(segment)) {
425
+ this.type = ElementType.escaped;
426
+ }
427
+ else {
428
+ this.type = ElementType.codepoint;
429
+ }
430
+ }
431
+ /** unescaped format */
432
+ get unescaped() {
433
+ if (this.type !== ElementType.escaped) {
434
+ return this.segment;
435
+ }
436
+ else {
437
+ if (MATCH_QUAD_ESCAPE.test(this.segment)) {
438
+ return unescapeOneQuadString(this.segment);
439
+ }
440
+ else {
441
+ return unescapeString(this.segment);
442
+ }
443
+ }
444
+ }
445
+ }
446
+ ;
447
+ /** Class for helping with Element strings (i.e. reorder) */
448
+ export class ElementParser {
449
+ /**
450
+ * Matches any complex UnicodeSet that would otherwise be misinterpreted
451
+ * by `MATCH_ELEMENT_SEGMENTS` due to nested `[]`'s.
452
+ * For example, `[[a-z]-[aeiou]]` could be
453
+ * mis-segmented into `[[a-z]`, `-`, `[aeiou]`, `]` */
454
+ static MATCH_NESTED_SQUARE_BRACKETS = /\[[^\]]*\[/;
455
+ /** Match (segment) UnicodeSets OR hex escapes OR single Unicode codepoints */
456
+ static MATCH_ELEMENT_SEGMENTS = /(?:\[[^\]]*\]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]{1,6}\}|\\u\{(?:[0-9a-fA-F]{1,6})(?: [0-9a-fA-F]{1,6}){1,}\}|.)/gu;
457
+ /** Does it start with a UnicodeSet? Used to test the segments. */
458
+ static MATCH_USET = /^\[/;
459
+ /** Does it start with an escaped char? Used to test the segments. */
460
+ static MATCH_ESCAPED = /^\\u/;
461
+ /** Split a string into ElementSegments */
462
+ static segment(str) {
463
+ if (ElementParser.MATCH_NESTED_SQUARE_BRACKETS.test(str)) {
464
+ throw Error(`Unsupported: nested square brackets in element segment: ${str}`);
465
+ }
466
+ const list = [];
467
+ for (let m of str.match(ElementParser.MATCH_ELEMENT_SEGMENTS)) {
468
+ const e = new ElementSegment(m);
469
+ if (e.type === ElementType.escaped) {
470
+ // unescape
471
+ const { unescaped } = e;
472
+ if (isOneChar(unescaped)) {
473
+ list.push(e);
474
+ }
475
+ else {
476
+ // need to split the escaped segment, \u{41 42} -> \u{41}, \u{42}
477
+ for (let s of unescaped) {
478
+ list.push(new ElementSegment(`\\u{${s.codePointAt(0).toString(16)}}`));
479
+ }
480
+ }
481
+ }
482
+ else {
483
+ // all others
484
+ list.push(e);
485
+ }
486
+ }
487
+ return list;
488
+ }
489
+ }
490
+ ;
491
491
  //# sourceMappingURL=pattern-parser.js.map
492
+ //# debugId=9510fffa-cd53-504b-958e-23524b16749a