@akairos/typeset-studio 0.2.1 → 0.2.3

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 (62) hide show
  1. package/README.md +91 -95
  2. package/dist/assets/index-3Ko1UCBU.css +1 -0
  3. package/dist/assets/index-C9J0f4Lf.js +317 -0
  4. package/dist/index.html +2 -2
  5. package/dist/lib/adapter.js +6 -7734
  6. package/dist/lib/canvas-renderer-cxnar75n.js +23 -0
  7. package/dist/lib/font-loader-j28mt43t.js +11 -0
  8. package/dist/lib/index-0370qz9e.js +303 -0
  9. package/dist/lib/index-37x76zdn.js +4 -0
  10. package/dist/lib/index-6c43c7h4.js +3880 -0
  11. package/dist/lib/index-t9w3p2p9.js +3366 -0
  12. package/dist/lib/index-zdhqg5f0.js +459 -0
  13. package/dist/lib/index.js +26 -7734
  14. package/dist/lib/render-xxd348m1.js +11 -0
  15. package/package.json +3 -7
  16. package/src/adapter.test.ts +117 -0
  17. package/src/adapter.ts +190 -281
  18. package/src/core/canvas-draw.ts +150 -47
  19. package/src/core/canvas-renderer.test.ts +58 -0
  20. package/src/core/canvas-renderer.ts +2 -1
  21. package/src/core/data-dir.ts +13 -0
  22. package/src/core/engine.ts +86 -56
  23. package/src/core/font-loader.test.ts +20 -0
  24. package/src/core/font-loader.ts +6 -2
  25. package/src/core/image-layout.ts +4 -0
  26. package/src/core/inline-text.ts +6 -4
  27. package/src/core/obstacle-flow.ts +29 -15
  28. package/src/core/page-images.test.ts +90 -0
  29. package/src/core/pretext.ts +4 -10
  30. package/src/core/template.test.ts +38 -1
  31. package/src/core/template.ts +53 -41
  32. package/src/core/types.ts +46 -0
  33. package/src/core/typography.ts +0 -14
  34. package/src/index.ts +6 -3
  35. package/src/server/auth.ts +18 -13
  36. package/src/server/index.ts +11 -16
  37. package/src/server/routes/fonts.ts +1 -1
  38. package/src/server/routes/render.ts +60 -17
  39. package/src/server/routes/slots.test.ts +96 -0
  40. package/src/server/routes/templates.ts +37 -48
  41. package/src/server/routes/upload.ts +2 -1
  42. package/src/web/App.tsx +15 -6
  43. package/src/web/components/CanvasViewport.tsx +56 -42
  44. package/src/web/components/EditorSidebar.tsx +59 -48
  45. package/src/web/components/Header.tsx +1 -1
  46. package/src/web/components/TemplateModal.tsx +25 -28
  47. package/src/web/hooks/image-layout.ts +31 -0
  48. package/src/web/hooks/useLocalFonts.ts +10 -1
  49. package/src/web/hooks/useTypeset.ts +139 -100
  50. package/data/templates/.gitkeep +0 -0
  51. package/data/templates/tpl_1791681833354_iofsk.json +0 -46
  52. package/data/templates/tpl_1791682603199_875ny.json +0 -66
  53. package/data/templates/tpl_1791682780929_qnuiy.json +0 -66
  54. package/data/templates/tpl_longform_paper_sage.json +0 -47
  55. package/data/templates/tpl_longform_vintage_news.json +0 -47
  56. package/data/templates/tpl_newspic_poster_cover.json +0 -64
  57. package/data/templates/tpl_square_quote_card.json +0 -46
  58. package/data/templates/tpl_wechat_cover_editorial.json +0 -64
  59. package/data/templates/tpl_wechat_cover_minimal.json +0 -64
  60. package/data/templates/tpl_wide_tech_banner.json +0 -46
  61. package/dist/assets/index-CZ352D7X.css +0 -1
  62. package/dist/assets/index-Dpnz-F2g.js +0 -317
@@ -0,0 +1,3880 @@
1
+ // node_modules/@chenglou/pretext/dist/generated/bidi-data.js
2
+ var latin1BidiTypes = [
3
+ "BN",
4
+ "BN",
5
+ "BN",
6
+ "BN",
7
+ "BN",
8
+ "BN",
9
+ "BN",
10
+ "BN",
11
+ "BN",
12
+ "S",
13
+ "B",
14
+ "S",
15
+ "WS",
16
+ "B",
17
+ "BN",
18
+ "BN",
19
+ "BN",
20
+ "BN",
21
+ "BN",
22
+ "BN",
23
+ "BN",
24
+ "BN",
25
+ "BN",
26
+ "BN",
27
+ "BN",
28
+ "BN",
29
+ "BN",
30
+ "BN",
31
+ "B",
32
+ "B",
33
+ "B",
34
+ "S",
35
+ "WS",
36
+ "ON",
37
+ "ON",
38
+ "ET",
39
+ "ET",
40
+ "ET",
41
+ "ON",
42
+ "ON",
43
+ "ON",
44
+ "ON",
45
+ "ON",
46
+ "ES",
47
+ "CS",
48
+ "ES",
49
+ "CS",
50
+ "CS",
51
+ "EN",
52
+ "EN",
53
+ "EN",
54
+ "EN",
55
+ "EN",
56
+ "EN",
57
+ "EN",
58
+ "EN",
59
+ "EN",
60
+ "EN",
61
+ "CS",
62
+ "ON",
63
+ "ON",
64
+ "ON",
65
+ "ON",
66
+ "ON",
67
+ "ON",
68
+ "L",
69
+ "L",
70
+ "L",
71
+ "L",
72
+ "L",
73
+ "L",
74
+ "L",
75
+ "L",
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
+ "ON",
95
+ "ON",
96
+ "ON",
97
+ "ON",
98
+ "ON",
99
+ "ON",
100
+ "L",
101
+ "L",
102
+ "L",
103
+ "L",
104
+ "L",
105
+ "L",
106
+ "L",
107
+ "L",
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
+ "ON",
127
+ "ON",
128
+ "ON",
129
+ "ON",
130
+ "BN",
131
+ "BN",
132
+ "BN",
133
+ "BN",
134
+ "BN",
135
+ "BN",
136
+ "B",
137
+ "BN",
138
+ "BN",
139
+ "BN",
140
+ "BN",
141
+ "BN",
142
+ "BN",
143
+ "BN",
144
+ "BN",
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
+ "CS",
164
+ "ON",
165
+ "ET",
166
+ "ET",
167
+ "ET",
168
+ "ET",
169
+ "ON",
170
+ "ON",
171
+ "ON",
172
+ "ON",
173
+ "L",
174
+ "ON",
175
+ "ON",
176
+ "BN",
177
+ "ON",
178
+ "ON",
179
+ "ET",
180
+ "ET",
181
+ "EN",
182
+ "EN",
183
+ "ON",
184
+ "L",
185
+ "ON",
186
+ "ON",
187
+ "ON",
188
+ "EN",
189
+ "L",
190
+ "ON",
191
+ "ON",
192
+ "ON",
193
+ "ON",
194
+ "ON",
195
+ "L",
196
+ "L",
197
+ "L",
198
+ "L",
199
+ "L",
200
+ "L",
201
+ "L",
202
+ "L",
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
+ "ON",
219
+ "L",
220
+ "L",
221
+ "L",
222
+ "L",
223
+ "L",
224
+ "L",
225
+ "L",
226
+ "L",
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
+ "ON",
251
+ "L",
252
+ "L",
253
+ "L",
254
+ "L",
255
+ "L",
256
+ "L",
257
+ "L",
258
+ "L"
259
+ ];
260
+ var nonLatin1BidiRanges = [
261
+ [697, 698, "ON"],
262
+ [706, 719, "ON"],
263
+ [722, 735, "ON"],
264
+ [741, 749, "ON"],
265
+ [751, 767, "ON"],
266
+ [768, 879, "NSM"],
267
+ [884, 885, "ON"],
268
+ [894, 894, "ON"],
269
+ [900, 901, "ON"],
270
+ [903, 903, "ON"],
271
+ [1014, 1014, "ON"],
272
+ [1155, 1161, "NSM"],
273
+ [1418, 1418, "ON"],
274
+ [1421, 1422, "ON"],
275
+ [1423, 1423, "ET"],
276
+ [1424, 1424, "R"],
277
+ [1425, 1469, "NSM"],
278
+ [1470, 1470, "R"],
279
+ [1471, 1471, "NSM"],
280
+ [1472, 1472, "R"],
281
+ [1473, 1474, "NSM"],
282
+ [1475, 1475, "R"],
283
+ [1476, 1477, "NSM"],
284
+ [1478, 1478, "R"],
285
+ [1479, 1479, "NSM"],
286
+ [1480, 1535, "R"],
287
+ [1536, 1541, "AN"],
288
+ [1542, 1543, "ON"],
289
+ [1544, 1544, "AL"],
290
+ [1545, 1546, "ET"],
291
+ [1547, 1547, "AL"],
292
+ [1548, 1548, "CS"],
293
+ [1549, 1549, "AL"],
294
+ [1550, 1551, "ON"],
295
+ [1552, 1562, "NSM"],
296
+ [1563, 1610, "AL"],
297
+ [1611, 1631, "NSM"],
298
+ [1632, 1641, "AN"],
299
+ [1642, 1642, "ET"],
300
+ [1643, 1644, "AN"],
301
+ [1645, 1647, "AL"],
302
+ [1648, 1648, "NSM"],
303
+ [1649, 1749, "AL"],
304
+ [1750, 1756, "NSM"],
305
+ [1757, 1757, "AN"],
306
+ [1758, 1758, "ON"],
307
+ [1759, 1764, "NSM"],
308
+ [1765, 1766, "AL"],
309
+ [1767, 1768, "NSM"],
310
+ [1769, 1769, "ON"],
311
+ [1770, 1773, "NSM"],
312
+ [1774, 1775, "AL"],
313
+ [1776, 1785, "EN"],
314
+ [1786, 1808, "AL"],
315
+ [1809, 1809, "NSM"],
316
+ [1810, 1839, "AL"],
317
+ [1840, 1866, "NSM"],
318
+ [1867, 1957, "AL"],
319
+ [1958, 1968, "NSM"],
320
+ [1969, 1983, "AL"],
321
+ [1984, 2026, "R"],
322
+ [2027, 2035, "NSM"],
323
+ [2036, 2037, "R"],
324
+ [2038, 2041, "ON"],
325
+ [2042, 2044, "R"],
326
+ [2045, 2045, "NSM"],
327
+ [2046, 2069, "R"],
328
+ [2070, 2073, "NSM"],
329
+ [2074, 2074, "R"],
330
+ [2075, 2083, "NSM"],
331
+ [2084, 2084, "R"],
332
+ [2085, 2087, "NSM"],
333
+ [2088, 2088, "R"],
334
+ [2089, 2093, "NSM"],
335
+ [2094, 2136, "R"],
336
+ [2137, 2139, "NSM"],
337
+ [2140, 2143, "R"],
338
+ [2144, 2191, "AL"],
339
+ [2192, 2193, "AN"],
340
+ [2194, 2198, "AL"],
341
+ [2199, 2207, "NSM"],
342
+ [2208, 2249, "AL"],
343
+ [2250, 2273, "NSM"],
344
+ [2274, 2274, "AN"],
345
+ [2275, 2306, "NSM"],
346
+ [2362, 2362, "NSM"],
347
+ [2364, 2364, "NSM"],
348
+ [2369, 2376, "NSM"],
349
+ [2381, 2381, "NSM"],
350
+ [2385, 2391, "NSM"],
351
+ [2402, 2403, "NSM"],
352
+ [2433, 2433, "NSM"],
353
+ [2492, 2492, "NSM"],
354
+ [2497, 2500, "NSM"],
355
+ [2509, 2509, "NSM"],
356
+ [2530, 2531, "NSM"],
357
+ [2546, 2547, "ET"],
358
+ [2555, 2555, "ET"],
359
+ [2558, 2558, "NSM"],
360
+ [2561, 2562, "NSM"],
361
+ [2620, 2620, "NSM"],
362
+ [2625, 2626, "NSM"],
363
+ [2631, 2632, "NSM"],
364
+ [2635, 2637, "NSM"],
365
+ [2641, 2641, "NSM"],
366
+ [2672, 2673, "NSM"],
367
+ [2677, 2677, "NSM"],
368
+ [2689, 2690, "NSM"],
369
+ [2748, 2748, "NSM"],
370
+ [2753, 2757, "NSM"],
371
+ [2759, 2760, "NSM"],
372
+ [2765, 2765, "NSM"],
373
+ [2786, 2787, "NSM"],
374
+ [2801, 2801, "ET"],
375
+ [2810, 2815, "NSM"],
376
+ [2817, 2817, "NSM"],
377
+ [2876, 2876, "NSM"],
378
+ [2879, 2879, "NSM"],
379
+ [2881, 2884, "NSM"],
380
+ [2893, 2893, "NSM"],
381
+ [2901, 2902, "NSM"],
382
+ [2914, 2915, "NSM"],
383
+ [2946, 2946, "NSM"],
384
+ [3008, 3008, "NSM"],
385
+ [3021, 3021, "NSM"],
386
+ [3059, 3064, "ON"],
387
+ [3065, 3065, "ET"],
388
+ [3066, 3066, "ON"],
389
+ [3072, 3072, "NSM"],
390
+ [3076, 3076, "NSM"],
391
+ [3132, 3132, "NSM"],
392
+ [3134, 3136, "NSM"],
393
+ [3142, 3144, "NSM"],
394
+ [3146, 3149, "NSM"],
395
+ [3157, 3158, "NSM"],
396
+ [3170, 3171, "NSM"],
397
+ [3192, 3198, "ON"],
398
+ [3201, 3201, "NSM"],
399
+ [3260, 3260, "NSM"],
400
+ [3276, 3277, "NSM"],
401
+ [3298, 3299, "NSM"],
402
+ [3328, 3329, "NSM"],
403
+ [3387, 3388, "NSM"],
404
+ [3393, 3396, "NSM"],
405
+ [3405, 3405, "NSM"],
406
+ [3426, 3427, "NSM"],
407
+ [3457, 3457, "NSM"],
408
+ [3530, 3530, "NSM"],
409
+ [3538, 3540, "NSM"],
410
+ [3542, 3542, "NSM"],
411
+ [3633, 3633, "NSM"],
412
+ [3636, 3642, "NSM"],
413
+ [3647, 3647, "ET"],
414
+ [3655, 3662, "NSM"],
415
+ [3761, 3761, "NSM"],
416
+ [3764, 3772, "NSM"],
417
+ [3784, 3790, "NSM"],
418
+ [3864, 3865, "NSM"],
419
+ [3893, 3893, "NSM"],
420
+ [3895, 3895, "NSM"],
421
+ [3897, 3897, "NSM"],
422
+ [3898, 3901, "ON"],
423
+ [3953, 3966, "NSM"],
424
+ [3968, 3972, "NSM"],
425
+ [3974, 3975, "NSM"],
426
+ [3981, 3991, "NSM"],
427
+ [3993, 4028, "NSM"],
428
+ [4038, 4038, "NSM"],
429
+ [4141, 4144, "NSM"],
430
+ [4146, 4151, "NSM"],
431
+ [4153, 4154, "NSM"],
432
+ [4157, 4158, "NSM"],
433
+ [4184, 4185, "NSM"],
434
+ [4190, 4192, "NSM"],
435
+ [4209, 4212, "NSM"],
436
+ [4226, 4226, "NSM"],
437
+ [4229, 4230, "NSM"],
438
+ [4237, 4237, "NSM"],
439
+ [4253, 4253, "NSM"],
440
+ [4957, 4959, "NSM"],
441
+ [5008, 5017, "ON"],
442
+ [5120, 5120, "ON"],
443
+ [5760, 5760, "WS"],
444
+ [5787, 5788, "ON"],
445
+ [5906, 5908, "NSM"],
446
+ [5938, 5939, "NSM"],
447
+ [5970, 5971, "NSM"],
448
+ [6002, 6003, "NSM"],
449
+ [6068, 6069, "NSM"],
450
+ [6071, 6077, "NSM"],
451
+ [6086, 6086, "NSM"],
452
+ [6089, 6099, "NSM"],
453
+ [6107, 6107, "ET"],
454
+ [6109, 6109, "NSM"],
455
+ [6128, 6137, "ON"],
456
+ [6144, 6154, "ON"],
457
+ [6155, 6157, "NSM"],
458
+ [6158, 6158, "BN"],
459
+ [6159, 6159, "NSM"],
460
+ [6277, 6278, "NSM"],
461
+ [6313, 6313, "NSM"],
462
+ [6432, 6434, "NSM"],
463
+ [6439, 6440, "NSM"],
464
+ [6450, 6450, "NSM"],
465
+ [6457, 6459, "NSM"],
466
+ [6464, 6464, "ON"],
467
+ [6468, 6469, "ON"],
468
+ [6622, 6655, "ON"],
469
+ [6679, 6680, "NSM"],
470
+ [6683, 6683, "NSM"],
471
+ [6742, 6742, "NSM"],
472
+ [6744, 6750, "NSM"],
473
+ [6752, 6752, "NSM"],
474
+ [6754, 6754, "NSM"],
475
+ [6757, 6764, "NSM"],
476
+ [6771, 6780, "NSM"],
477
+ [6783, 6783, "NSM"],
478
+ [6832, 6877, "NSM"],
479
+ [6880, 6891, "NSM"],
480
+ [6912, 6915, "NSM"],
481
+ [6964, 6964, "NSM"],
482
+ [6966, 6970, "NSM"],
483
+ [6972, 6972, "NSM"],
484
+ [6978, 6978, "NSM"],
485
+ [7019, 7027, "NSM"],
486
+ [7040, 7041, "NSM"],
487
+ [7074, 7077, "NSM"],
488
+ [7080, 7081, "NSM"],
489
+ [7083, 7085, "NSM"],
490
+ [7142, 7142, "NSM"],
491
+ [7144, 7145, "NSM"],
492
+ [7149, 7149, "NSM"],
493
+ [7151, 7153, "NSM"],
494
+ [7212, 7219, "NSM"],
495
+ [7222, 7223, "NSM"],
496
+ [7376, 7378, "NSM"],
497
+ [7380, 7392, "NSM"],
498
+ [7394, 7400, "NSM"],
499
+ [7405, 7405, "NSM"],
500
+ [7412, 7412, "NSM"],
501
+ [7416, 7417, "NSM"],
502
+ [7616, 7679, "NSM"],
503
+ [8125, 8125, "ON"],
504
+ [8127, 8129, "ON"],
505
+ [8141, 8143, "ON"],
506
+ [8157, 8159, "ON"],
507
+ [8173, 8175, "ON"],
508
+ [8189, 8190, "ON"],
509
+ [8192, 8202, "WS"],
510
+ [8203, 8205, "BN"],
511
+ [8207, 8207, "R"],
512
+ [8208, 8231, "ON"],
513
+ [8232, 8232, "WS"],
514
+ [8233, 8233, "B"],
515
+ [8234, 8238, "BN"],
516
+ [8239, 8239, "CS"],
517
+ [8240, 8244, "ET"],
518
+ [8245, 8259, "ON"],
519
+ [8260, 8260, "CS"],
520
+ [8261, 8286, "ON"],
521
+ [8287, 8287, "WS"],
522
+ [8288, 8303, "BN"],
523
+ [8304, 8304, "EN"],
524
+ [8308, 8313, "EN"],
525
+ [8314, 8315, "ES"],
526
+ [8316, 8318, "ON"],
527
+ [8320, 8329, "EN"],
528
+ [8330, 8331, "ES"],
529
+ [8332, 8334, "ON"],
530
+ [8352, 8399, "ET"],
531
+ [8400, 8432, "NSM"],
532
+ [8448, 8449, "ON"],
533
+ [8451, 8454, "ON"],
534
+ [8456, 8457, "ON"],
535
+ [8468, 8468, "ON"],
536
+ [8470, 8472, "ON"],
537
+ [8478, 8483, "ON"],
538
+ [8485, 8485, "ON"],
539
+ [8487, 8487, "ON"],
540
+ [8489, 8489, "ON"],
541
+ [8494, 8494, "ET"],
542
+ [8506, 8507, "ON"],
543
+ [8512, 8516, "ON"],
544
+ [8522, 8525, "ON"],
545
+ [8528, 8543, "ON"],
546
+ [8585, 8587, "ON"],
547
+ [8592, 8721, "ON"],
548
+ [8722, 8722, "ES"],
549
+ [8723, 8723, "ET"],
550
+ [8724, 9013, "ON"],
551
+ [9083, 9108, "ON"],
552
+ [9110, 9257, "ON"],
553
+ [9280, 9290, "ON"],
554
+ [9312, 9351, "ON"],
555
+ [9352, 9371, "EN"],
556
+ [9450, 9899, "ON"],
557
+ [9901, 10239, "ON"],
558
+ [10496, 11123, "ON"],
559
+ [11126, 11263, "ON"],
560
+ [11493, 11498, "ON"],
561
+ [11503, 11505, "NSM"],
562
+ [11513, 11519, "ON"],
563
+ [11647, 11647, "NSM"],
564
+ [11744, 11775, "NSM"],
565
+ [11776, 11869, "ON"],
566
+ [11904, 11929, "ON"],
567
+ [11931, 12019, "ON"],
568
+ [12032, 12245, "ON"],
569
+ [12272, 12287, "ON"],
570
+ [12288, 12288, "WS"],
571
+ [12289, 12292, "ON"],
572
+ [12296, 12320, "ON"],
573
+ [12330, 12333, "NSM"],
574
+ [12336, 12336, "ON"],
575
+ [12342, 12343, "ON"],
576
+ [12349, 12351, "ON"],
577
+ [12441, 12442, "NSM"],
578
+ [12443, 12444, "ON"],
579
+ [12448, 12448, "ON"],
580
+ [12539, 12539, "ON"],
581
+ [12736, 12773, "ON"],
582
+ [12783, 12783, "ON"],
583
+ [12829, 12830, "ON"],
584
+ [12880, 12895, "ON"],
585
+ [12924, 12926, "ON"],
586
+ [12977, 12991, "ON"],
587
+ [13004, 13007, "ON"],
588
+ [13175, 13178, "ON"],
589
+ [13278, 13279, "ON"],
590
+ [13311, 13311, "ON"],
591
+ [19904, 19967, "ON"],
592
+ [42128, 42182, "ON"],
593
+ [42509, 42511, "ON"],
594
+ [42607, 42610, "NSM"],
595
+ [42611, 42611, "ON"],
596
+ [42612, 42621, "NSM"],
597
+ [42622, 42623, "ON"],
598
+ [42654, 42655, "NSM"],
599
+ [42736, 42737, "NSM"],
600
+ [42752, 42785, "ON"],
601
+ [42888, 42888, "ON"],
602
+ [43010, 43010, "NSM"],
603
+ [43014, 43014, "NSM"],
604
+ [43019, 43019, "NSM"],
605
+ [43045, 43046, "NSM"],
606
+ [43048, 43051, "ON"],
607
+ [43052, 43052, "NSM"],
608
+ [43064, 43065, "ET"],
609
+ [43124, 43127, "ON"],
610
+ [43204, 43205, "NSM"],
611
+ [43232, 43249, "NSM"],
612
+ [43263, 43263, "NSM"],
613
+ [43302, 43309, "NSM"],
614
+ [43335, 43345, "NSM"],
615
+ [43392, 43394, "NSM"],
616
+ [43443, 43443, "NSM"],
617
+ [43446, 43449, "NSM"],
618
+ [43452, 43453, "NSM"],
619
+ [43493, 43493, "NSM"],
620
+ [43561, 43566, "NSM"],
621
+ [43569, 43570, "NSM"],
622
+ [43573, 43574, "NSM"],
623
+ [43587, 43587, "NSM"],
624
+ [43596, 43596, "NSM"],
625
+ [43644, 43644, "NSM"],
626
+ [43696, 43696, "NSM"],
627
+ [43698, 43700, "NSM"],
628
+ [43703, 43704, "NSM"],
629
+ [43710, 43711, "NSM"],
630
+ [43713, 43713, "NSM"],
631
+ [43756, 43757, "NSM"],
632
+ [43766, 43766, "NSM"],
633
+ [43882, 43883, "ON"],
634
+ [44005, 44005, "NSM"],
635
+ [44008, 44008, "NSM"],
636
+ [44013, 44013, "NSM"],
637
+ [64285, 64285, "R"],
638
+ [64286, 64286, "NSM"],
639
+ [64287, 64296, "R"],
640
+ [64297, 64297, "ES"],
641
+ [64298, 64335, "R"],
642
+ [64336, 64450, "AL"],
643
+ [64451, 64466, "ON"],
644
+ [64467, 64829, "AL"],
645
+ [64830, 64847, "ON"],
646
+ [64848, 64911, "AL"],
647
+ [64912, 64913, "ON"],
648
+ [64914, 64967, "AL"],
649
+ [64968, 64975, "ON"],
650
+ [64976, 65007, "BN"],
651
+ [65008, 65020, "AL"],
652
+ [65021, 65023, "ON"],
653
+ [65024, 65039, "NSM"],
654
+ [65040, 65049, "ON"],
655
+ [65056, 65071, "NSM"],
656
+ [65072, 65103, "ON"],
657
+ [65104, 65104, "CS"],
658
+ [65105, 65105, "ON"],
659
+ [65106, 65106, "CS"],
660
+ [65108, 65108, "ON"],
661
+ [65109, 65109, "CS"],
662
+ [65110, 65118, "ON"],
663
+ [65119, 65119, "ET"],
664
+ [65120, 65121, "ON"],
665
+ [65122, 65123, "ES"],
666
+ [65124, 65126, "ON"],
667
+ [65128, 65128, "ON"],
668
+ [65129, 65130, "ET"],
669
+ [65131, 65131, "ON"],
670
+ [65136, 65278, "AL"],
671
+ [65279, 65279, "BN"],
672
+ [65281, 65282, "ON"],
673
+ [65283, 65285, "ET"],
674
+ [65286, 65290, "ON"],
675
+ [65291, 65291, "ES"],
676
+ [65292, 65292, "CS"],
677
+ [65293, 65293, "ES"],
678
+ [65294, 65295, "CS"],
679
+ [65296, 65305, "EN"],
680
+ [65306, 65306, "CS"],
681
+ [65307, 65312, "ON"],
682
+ [65339, 65344, "ON"],
683
+ [65371, 65381, "ON"],
684
+ [65504, 65505, "ET"],
685
+ [65506, 65508, "ON"],
686
+ [65509, 65510, "ET"],
687
+ [65512, 65518, "ON"],
688
+ [65520, 65528, "BN"],
689
+ [65529, 65533, "ON"],
690
+ [65534, 65535, "BN"],
691
+ [65793, 65793, "ON"],
692
+ [65856, 65932, "ON"],
693
+ [65936, 65948, "ON"],
694
+ [65952, 65952, "ON"],
695
+ [66045, 66045, "NSM"],
696
+ [66272, 66272, "NSM"],
697
+ [66273, 66299, "EN"],
698
+ [66422, 66426, "NSM"],
699
+ [67584, 67870, "R"],
700
+ [67871, 67871, "ON"],
701
+ [67872, 68096, "R"],
702
+ [68097, 68099, "NSM"],
703
+ [68100, 68100, "R"],
704
+ [68101, 68102, "NSM"],
705
+ [68103, 68107, "R"],
706
+ [68108, 68111, "NSM"],
707
+ [68112, 68151, "R"],
708
+ [68152, 68154, "NSM"],
709
+ [68155, 68158, "R"],
710
+ [68159, 68159, "NSM"],
711
+ [68160, 68324, "R"],
712
+ [68325, 68326, "NSM"],
713
+ [68327, 68408, "R"],
714
+ [68409, 68415, "ON"],
715
+ [68416, 68863, "R"],
716
+ [68864, 68899, "AL"],
717
+ [68900, 68903, "NSM"],
718
+ [68904, 68911, "AL"],
719
+ [68912, 68921, "AN"],
720
+ [68922, 68927, "AL"],
721
+ [68928, 68937, "AN"],
722
+ [68938, 68968, "R"],
723
+ [68969, 68973, "NSM"],
724
+ [68974, 68974, "ON"],
725
+ [68975, 69215, "R"],
726
+ [69216, 69246, "AN"],
727
+ [69247, 69290, "R"],
728
+ [69291, 69292, "NSM"],
729
+ [69293, 69311, "R"],
730
+ [69312, 69327, "AL"],
731
+ [69328, 69336, "ON"],
732
+ [69337, 69369, "AL"],
733
+ [69370, 69375, "NSM"],
734
+ [69376, 69423, "R"],
735
+ [69424, 69445, "AL"],
736
+ [69446, 69456, "NSM"],
737
+ [69457, 69487, "AL"],
738
+ [69488, 69505, "R"],
739
+ [69506, 69509, "NSM"],
740
+ [69510, 69631, "R"],
741
+ [69633, 69633, "NSM"],
742
+ [69688, 69702, "NSM"],
743
+ [69714, 69733, "ON"],
744
+ [69744, 69744, "NSM"],
745
+ [69747, 69748, "NSM"],
746
+ [69759, 69761, "NSM"],
747
+ [69811, 69814, "NSM"],
748
+ [69817, 69818, "NSM"],
749
+ [69826, 69826, "NSM"],
750
+ [69888, 69890, "NSM"],
751
+ [69927, 69931, "NSM"],
752
+ [69933, 69940, "NSM"],
753
+ [70003, 70003, "NSM"],
754
+ [70016, 70017, "NSM"],
755
+ [70070, 70078, "NSM"],
756
+ [70089, 70092, "NSM"],
757
+ [70095, 70095, "NSM"],
758
+ [70191, 70193, "NSM"],
759
+ [70196, 70196, "NSM"],
760
+ [70198, 70199, "NSM"],
761
+ [70206, 70206, "NSM"],
762
+ [70209, 70209, "NSM"],
763
+ [70367, 70367, "NSM"],
764
+ [70371, 70378, "NSM"],
765
+ [70400, 70401, "NSM"],
766
+ [70459, 70460, "NSM"],
767
+ [70464, 70464, "NSM"],
768
+ [70502, 70508, "NSM"],
769
+ [70512, 70516, "NSM"],
770
+ [70587, 70592, "NSM"],
771
+ [70606, 70606, "NSM"],
772
+ [70608, 70608, "NSM"],
773
+ [70610, 70610, "NSM"],
774
+ [70625, 70626, "NSM"],
775
+ [70712, 70719, "NSM"],
776
+ [70722, 70724, "NSM"],
777
+ [70726, 70726, "NSM"],
778
+ [70750, 70750, "NSM"],
779
+ [70835, 70840, "NSM"],
780
+ [70842, 70842, "NSM"],
781
+ [70847, 70848, "NSM"],
782
+ [70850, 70851, "NSM"],
783
+ [71090, 71093, "NSM"],
784
+ [71100, 71101, "NSM"],
785
+ [71103, 71104, "NSM"],
786
+ [71132, 71133, "NSM"],
787
+ [71219, 71226, "NSM"],
788
+ [71229, 71229, "NSM"],
789
+ [71231, 71232, "NSM"],
790
+ [71264, 71276, "ON"],
791
+ [71339, 71339, "NSM"],
792
+ [71341, 71341, "NSM"],
793
+ [71344, 71349, "NSM"],
794
+ [71351, 71351, "NSM"],
795
+ [71453, 71453, "NSM"],
796
+ [71455, 71455, "NSM"],
797
+ [71458, 71461, "NSM"],
798
+ [71463, 71467, "NSM"],
799
+ [71727, 71735, "NSM"],
800
+ [71737, 71738, "NSM"],
801
+ [71995, 71996, "NSM"],
802
+ [71998, 71998, "NSM"],
803
+ [72003, 72003, "NSM"],
804
+ [72148, 72151, "NSM"],
805
+ [72154, 72155, "NSM"],
806
+ [72160, 72160, "NSM"],
807
+ [72193, 72198, "NSM"],
808
+ [72201, 72202, "NSM"],
809
+ [72243, 72248, "NSM"],
810
+ [72251, 72254, "NSM"],
811
+ [72263, 72263, "NSM"],
812
+ [72273, 72278, "NSM"],
813
+ [72281, 72283, "NSM"],
814
+ [72330, 72342, "NSM"],
815
+ [72344, 72345, "NSM"],
816
+ [72544, 72544, "NSM"],
817
+ [72546, 72548, "NSM"],
818
+ [72550, 72550, "NSM"],
819
+ [72752, 72758, "NSM"],
820
+ [72760, 72765, "NSM"],
821
+ [72850, 72871, "NSM"],
822
+ [72874, 72880, "NSM"],
823
+ [72882, 72883, "NSM"],
824
+ [72885, 72886, "NSM"],
825
+ [73009, 73014, "NSM"],
826
+ [73018, 73018, "NSM"],
827
+ [73020, 73021, "NSM"],
828
+ [73023, 73029, "NSM"],
829
+ [73031, 73031, "NSM"],
830
+ [73104, 73105, "NSM"],
831
+ [73109, 73109, "NSM"],
832
+ [73111, 73111, "NSM"],
833
+ [73459, 73460, "NSM"],
834
+ [73472, 73473, "NSM"],
835
+ [73526, 73530, "NSM"],
836
+ [73536, 73536, "NSM"],
837
+ [73538, 73538, "NSM"],
838
+ [73562, 73562, "NSM"],
839
+ [73685, 73692, "ON"],
840
+ [73693, 73696, "ET"],
841
+ [73697, 73713, "ON"],
842
+ [78912, 78912, "NSM"],
843
+ [78919, 78933, "NSM"],
844
+ [90398, 90409, "NSM"],
845
+ [90413, 90415, "NSM"],
846
+ [92912, 92916, "NSM"],
847
+ [92976, 92982, "NSM"],
848
+ [94031, 94031, "NSM"],
849
+ [94095, 94098, "NSM"],
850
+ [94178, 94178, "ON"],
851
+ [94180, 94180, "NSM"],
852
+ [113821, 113822, "NSM"],
853
+ [113824, 113827, "BN"],
854
+ [117760, 117973, "ON"],
855
+ [118000, 118009, "EN"],
856
+ [118010, 118012, "ON"],
857
+ [118016, 118451, "ON"],
858
+ [118458, 118480, "ON"],
859
+ [118496, 118512, "ON"],
860
+ [118528, 118573, "NSM"],
861
+ [118576, 118598, "NSM"],
862
+ [119143, 119145, "NSM"],
863
+ [119155, 119162, "BN"],
864
+ [119163, 119170, "NSM"],
865
+ [119173, 119179, "NSM"],
866
+ [119210, 119213, "NSM"],
867
+ [119273, 119274, "ON"],
868
+ [119296, 119361, "ON"],
869
+ [119362, 119364, "NSM"],
870
+ [119365, 119365, "ON"],
871
+ [119552, 119638, "ON"],
872
+ [120513, 120513, "ON"],
873
+ [120539, 120539, "ON"],
874
+ [120571, 120571, "ON"],
875
+ [120597, 120597, "ON"],
876
+ [120629, 120629, "ON"],
877
+ [120655, 120655, "ON"],
878
+ [120687, 120687, "ON"],
879
+ [120713, 120713, "ON"],
880
+ [120745, 120745, "ON"],
881
+ [120771, 120771, "ON"],
882
+ [120782, 120831, "EN"],
883
+ [121344, 121398, "NSM"],
884
+ [121403, 121452, "NSM"],
885
+ [121461, 121461, "NSM"],
886
+ [121476, 121476, "NSM"],
887
+ [121499, 121503, "NSM"],
888
+ [121505, 121519, "NSM"],
889
+ [122880, 122886, "NSM"],
890
+ [122888, 122904, "NSM"],
891
+ [122907, 122913, "NSM"],
892
+ [122915, 122916, "NSM"],
893
+ [122918, 122922, "NSM"],
894
+ [123023, 123023, "NSM"],
895
+ [123184, 123190, "NSM"],
896
+ [123566, 123566, "NSM"],
897
+ [123628, 123631, "NSM"],
898
+ [123647, 123647, "ET"],
899
+ [124140, 124143, "NSM"],
900
+ [124398, 124399, "NSM"],
901
+ [124643, 124643, "NSM"],
902
+ [124646, 124646, "NSM"],
903
+ [124654, 124655, "NSM"],
904
+ [124661, 124661, "NSM"],
905
+ [124928, 125135, "R"],
906
+ [125136, 125142, "NSM"],
907
+ [125143, 125251, "R"],
908
+ [125252, 125258, "NSM"],
909
+ [125259, 126063, "R"],
910
+ [126064, 126143, "AL"],
911
+ [126144, 126207, "R"],
912
+ [126208, 126287, "AL"],
913
+ [126288, 126463, "R"],
914
+ [126464, 126703, "AL"],
915
+ [126704, 126705, "ON"],
916
+ [126706, 126719, "AL"],
917
+ [126720, 126975, "R"],
918
+ [126976, 127019, "ON"],
919
+ [127024, 127123, "ON"],
920
+ [127136, 127150, "ON"],
921
+ [127153, 127167, "ON"],
922
+ [127169, 127183, "ON"],
923
+ [127185, 127221, "ON"],
924
+ [127232, 127242, "EN"],
925
+ [127243, 127247, "ON"],
926
+ [127279, 127279, "ON"],
927
+ [127338, 127343, "ON"],
928
+ [127405, 127405, "ON"],
929
+ [127584, 127589, "ON"],
930
+ [127744, 128728, "ON"],
931
+ [128732, 128748, "ON"],
932
+ [128752, 128764, "ON"],
933
+ [128768, 128985, "ON"],
934
+ [128992, 129003, "ON"],
935
+ [129008, 129008, "ON"],
936
+ [129024, 129035, "ON"],
937
+ [129040, 129095, "ON"],
938
+ [129104, 129113, "ON"],
939
+ [129120, 129159, "ON"],
940
+ [129168, 129197, "ON"],
941
+ [129200, 129211, "ON"],
942
+ [129216, 129217, "ON"],
943
+ [129232, 129240, "ON"],
944
+ [129280, 129623, "ON"],
945
+ [129632, 129645, "ON"],
946
+ [129648, 129660, "ON"],
947
+ [129664, 129674, "ON"],
948
+ [129678, 129734, "ON"],
949
+ [129736, 129736, "ON"],
950
+ [129741, 129756, "ON"],
951
+ [129759, 129770, "ON"],
952
+ [129775, 129784, "ON"],
953
+ [129792, 129938, "ON"],
954
+ [129940, 130031, "ON"],
955
+ [130032, 130041, "EN"],
956
+ [130042, 130042, "ON"],
957
+ [131070, 131071, "BN"],
958
+ [196606, 196607, "BN"],
959
+ [262142, 262143, "BN"],
960
+ [327678, 327679, "BN"],
961
+ [393214, 393215, "BN"],
962
+ [458750, 458751, "BN"],
963
+ [524286, 524287, "BN"],
964
+ [589822, 589823, "BN"],
965
+ [655358, 655359, "BN"],
966
+ [720894, 720895, "BN"],
967
+ [786430, 786431, "BN"],
968
+ [851966, 851967, "BN"],
969
+ [917502, 917759, "BN"],
970
+ [917760, 917999, "NSM"],
971
+ [918000, 921599, "BN"],
972
+ [983038, 983039, "BN"],
973
+ [1048574, 1048575, "BN"],
974
+ [1114110, 1114111, "BN"]
975
+ ];
976
+
977
+ // node_modules/@chenglou/pretext/dist/bidi.js
978
+ function classifyCodePoint(codePoint) {
979
+ if (codePoint <= 255)
980
+ return latin1BidiTypes[codePoint];
981
+ let lo = 0;
982
+ let hi = nonLatin1BidiRanges.length - 1;
983
+ while (lo <= hi) {
984
+ const mid = lo + hi >> 1;
985
+ const range = nonLatin1BidiRanges[mid];
986
+ if (codePoint < range[0]) {
987
+ hi = mid - 1;
988
+ continue;
989
+ }
990
+ if (codePoint > range[1]) {
991
+ lo = mid + 1;
992
+ continue;
993
+ }
994
+ return range[2];
995
+ }
996
+ return "L";
997
+ }
998
+ function computeBidiLevels(str) {
999
+ const len = str.length;
1000
+ if (len === 0)
1001
+ return null;
1002
+ const types = new Array(len);
1003
+ let sawBidi = false;
1004
+ for (let i = 0;i < len; ) {
1005
+ const first = str.charCodeAt(i);
1006
+ let codePoint = first;
1007
+ let codeUnitLength = 1;
1008
+ if (first >= 55296 && first <= 56319 && i + 1 < len) {
1009
+ const second = str.charCodeAt(i + 1);
1010
+ if (second >= 56320 && second <= 57343) {
1011
+ codePoint = (first - 55296 << 10) + (second - 56320) + 65536;
1012
+ codeUnitLength = 2;
1013
+ }
1014
+ }
1015
+ const t = classifyCodePoint(codePoint);
1016
+ if (t === "R" || t === "AL" || t === "AN")
1017
+ sawBidi = true;
1018
+ for (let j = 0;j < codeUnitLength; j++) {
1019
+ types[i + j] = t;
1020
+ }
1021
+ i += codeUnitLength;
1022
+ }
1023
+ if (!sawBidi)
1024
+ return null;
1025
+ let startLevel = 0;
1026
+ for (let i = 0;i < len; i++) {
1027
+ const t = types[i];
1028
+ if (t === "L") {
1029
+ startLevel = 0;
1030
+ break;
1031
+ }
1032
+ if (t === "R" || t === "AL") {
1033
+ startLevel = 1;
1034
+ break;
1035
+ }
1036
+ }
1037
+ const levels = new Int8Array(len);
1038
+ for (let i = 0;i < len; i++)
1039
+ levels[i] = startLevel;
1040
+ const e = startLevel & 1 ? "R" : "L";
1041
+ const sor = e;
1042
+ let lastType = sor;
1043
+ for (let i = 0;i < len; i++) {
1044
+ if (types[i] === "NSM")
1045
+ types[i] = lastType;
1046
+ else
1047
+ lastType = types[i];
1048
+ }
1049
+ lastType = sor;
1050
+ for (let i = 0;i < len; i++) {
1051
+ const t = types[i];
1052
+ if (t === "EN")
1053
+ types[i] = lastType === "AL" ? "AN" : "EN";
1054
+ else if (t === "R" || t === "L" || t === "AL")
1055
+ lastType = t;
1056
+ }
1057
+ for (let i = 0;i < len; i++) {
1058
+ if (types[i] === "AL")
1059
+ types[i] = "R";
1060
+ }
1061
+ for (let i = 1;i < len - 1; i++) {
1062
+ if (types[i] === "ES" && types[i - 1] === "EN" && types[i + 1] === "EN") {
1063
+ types[i] = "EN";
1064
+ }
1065
+ if (types[i] === "CS" && (types[i - 1] === "EN" || types[i - 1] === "AN") && types[i + 1] === types[i - 1]) {
1066
+ types[i] = types[i - 1];
1067
+ }
1068
+ }
1069
+ for (let i = 0;i < len; i++) {
1070
+ if (types[i] !== "EN")
1071
+ continue;
1072
+ let j;
1073
+ for (j = i - 1;j >= 0 && types[j] === "ET"; j--)
1074
+ types[j] = "EN";
1075
+ for (j = i + 1;j < len && types[j] === "ET"; j++)
1076
+ types[j] = "EN";
1077
+ }
1078
+ for (let i = 0;i < len; i++) {
1079
+ const t = types[i];
1080
+ if (t === "WS" || t === "ES" || t === "ET" || t === "CS")
1081
+ types[i] = "ON";
1082
+ }
1083
+ lastType = sor;
1084
+ for (let i = 0;i < len; i++) {
1085
+ const t = types[i];
1086
+ if (t === "EN")
1087
+ types[i] = lastType === "L" ? "L" : "EN";
1088
+ else if (t === "R" || t === "L")
1089
+ lastType = t;
1090
+ }
1091
+ for (let i = 0;i < len; i++) {
1092
+ if (types[i] !== "ON")
1093
+ continue;
1094
+ let end = i + 1;
1095
+ while (end < len && types[end] === "ON")
1096
+ end++;
1097
+ const before = i > 0 ? types[i - 1] : sor;
1098
+ const after = end < len ? types[end] : sor;
1099
+ const bDir = before !== "L" ? "R" : "L";
1100
+ const aDir = after !== "L" ? "R" : "L";
1101
+ if (bDir === aDir) {
1102
+ for (let j = i;j < end; j++)
1103
+ types[j] = bDir;
1104
+ }
1105
+ i = end - 1;
1106
+ }
1107
+ for (let i = 0;i < len; i++) {
1108
+ if (types[i] === "ON")
1109
+ types[i] = e;
1110
+ }
1111
+ for (let i = 0;i < len; i++) {
1112
+ const t = types[i];
1113
+ if ((levels[i] & 1) === 0) {
1114
+ if (t === "R")
1115
+ levels[i]++;
1116
+ else if (t === "AN" || t === "EN")
1117
+ levels[i] += 2;
1118
+ } else if (t === "L" || t === "AN" || t === "EN") {
1119
+ levels[i]++;
1120
+ }
1121
+ }
1122
+ return levels;
1123
+ }
1124
+ function computeSegmentLevels(normalized, segStarts) {
1125
+ const bidiLevels = computeBidiLevels(normalized);
1126
+ if (bidiLevels === null)
1127
+ return null;
1128
+ const segLevels = new Int8Array(segStarts.length);
1129
+ for (let i = 0;i < segStarts.length; i++) {
1130
+ segLevels[i] = bidiLevels[segStarts[i]];
1131
+ }
1132
+ return segLevels;
1133
+ }
1134
+
1135
+ // node_modules/@chenglou/pretext/dist/analysis.js
1136
+ var collapsibleWhitespaceRunRe = /[ \t\n\r\f]+/g;
1137
+ var needsWhitespaceNormalizationRe = /[\t\n\r\f]| {2,}|^ | $/;
1138
+ function getWhiteSpaceProfile(whiteSpace) {
1139
+ const mode = whiteSpace ?? "normal";
1140
+ return mode === "pre-wrap" ? { mode, preserveOrdinarySpaces: true, preserveHardBreaks: true } : { mode, preserveOrdinarySpaces: false, preserveHardBreaks: false };
1141
+ }
1142
+ function normalizeWhitespaceNormal(text) {
1143
+ if (!needsWhitespaceNormalizationRe.test(text))
1144
+ return text;
1145
+ let normalized = text.replace(collapsibleWhitespaceRunRe, " ");
1146
+ if (normalized.charCodeAt(0) === 32) {
1147
+ normalized = normalized.slice(1);
1148
+ }
1149
+ if (normalized.length > 0 && normalized.charCodeAt(normalized.length - 1) === 32) {
1150
+ normalized = normalized.slice(0, -1);
1151
+ }
1152
+ return normalized;
1153
+ }
1154
+ function normalizeWhitespacePreWrap(text) {
1155
+ if (!/[\r\f]/.test(text))
1156
+ return text;
1157
+ return text.replace(/\r\n/g, `
1158
+ `).replace(/[\r\f]/g, `
1159
+ `);
1160
+ }
1161
+ var sharedWordSegmenter = null;
1162
+ var segmenterLocale;
1163
+ function getSharedWordSegmenter() {
1164
+ if (sharedWordSegmenter === null) {
1165
+ sharedWordSegmenter = new Intl.Segmenter(segmenterLocale, { granularity: "word" });
1166
+ }
1167
+ return sharedWordSegmenter;
1168
+ }
1169
+ function clearAnalysisCaches() {
1170
+ sharedWordSegmenter = null;
1171
+ }
1172
+ var arabicScriptRe = /\p{Script=Arabic}/u;
1173
+ var combiningMarkRe = /\p{M}/u;
1174
+ var decimalDigitRe = /\p{Nd}/u;
1175
+ function containsArabicScript(text) {
1176
+ return arabicScriptRe.test(text);
1177
+ }
1178
+ function isCJKCodePoint(codePoint) {
1179
+ return codePoint >= 19968 && codePoint <= 40959 || codePoint >= 13312 && codePoint <= 19903 || codePoint >= 131072 && codePoint <= 173791 || codePoint >= 173824 && codePoint <= 177983 || codePoint >= 177984 && codePoint <= 178207 || codePoint >= 178208 && codePoint <= 183983 || codePoint >= 183984 && codePoint <= 191471 || codePoint >= 191472 && codePoint <= 192093 || codePoint >= 194560 && codePoint <= 195103 || codePoint >= 196608 && codePoint <= 201551 || codePoint >= 201552 && codePoint <= 205743 || codePoint >= 205744 && codePoint <= 210041 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 12288 && codePoint <= 12351 || codePoint >= 12352 && codePoint <= 12447 || codePoint >= 12448 && codePoint <= 12543 || codePoint >= 12592 && codePoint <= 12687 || codePoint >= 44032 && codePoint <= 55215 || codePoint >= 65280 && codePoint <= 65519;
1180
+ }
1181
+ function isCJK(s) {
1182
+ for (let i = 0;i < s.length; i++) {
1183
+ const first = s.charCodeAt(i);
1184
+ if (first < 12288)
1185
+ continue;
1186
+ if (first >= 55296 && first <= 56319 && i + 1 < s.length) {
1187
+ const second = s.charCodeAt(i + 1);
1188
+ if (second >= 56320 && second <= 57343) {
1189
+ const codePoint = (first - 55296 << 10) + (second - 56320) + 65536;
1190
+ if (isCJKCodePoint(codePoint))
1191
+ return true;
1192
+ i++;
1193
+ continue;
1194
+ }
1195
+ }
1196
+ if (isCJKCodePoint(first))
1197
+ return true;
1198
+ }
1199
+ return false;
1200
+ }
1201
+ function endsWithLineStartProhibitedText(text) {
1202
+ const last = getLastCodePoint(text);
1203
+ return last !== null && (kinsokuStart.has(last) || leftStickyPunctuation.has(last));
1204
+ }
1205
+ var keepAllGlueChars = new Set([
1206
+ " ",
1207
+ " ",
1208
+ "⁠",
1209
+ "\uFEFF"
1210
+ ]);
1211
+ var keepAllDashBreakChars = new Set([
1212
+ "-",
1213
+ "‐",
1214
+ "–",
1215
+ "—"
1216
+ ]);
1217
+ function endsWithKeepAllGlueText(text) {
1218
+ const last = getLastCodePoint(text);
1219
+ return last !== null && keepAllGlueChars.has(last);
1220
+ }
1221
+ function endsWithKeepAllDashBreakText(text) {
1222
+ const last = getLastCodePoint(text);
1223
+ return last !== null && keepAllDashBreakChars.has(last);
1224
+ }
1225
+ function canContinueKeepAllTextRun(previousText, breakAfterPunctuation) {
1226
+ if (endsWithKeepAllGlueText(previousText))
1227
+ return false;
1228
+ if (!breakAfterPunctuation)
1229
+ return true;
1230
+ if (endsWithLineStartProhibitedText(previousText))
1231
+ return false;
1232
+ if (endsWithKeepAllDashBreakText(previousText))
1233
+ return false;
1234
+ return true;
1235
+ }
1236
+ var kinsokuStart = new Set([
1237
+ ",",
1238
+ ".",
1239
+ "!",
1240
+ ":",
1241
+ ";",
1242
+ "?",
1243
+ "、",
1244
+ "。",
1245
+ "・",
1246
+ ")",
1247
+ "〕",
1248
+ "〉",
1249
+ "》",
1250
+ "」",
1251
+ "』",
1252
+ "】",
1253
+ "〗",
1254
+ "〙",
1255
+ "〛",
1256
+ "ー",
1257
+ "々",
1258
+ "〻",
1259
+ "ゝ",
1260
+ "ゞ",
1261
+ "ヽ",
1262
+ "ヾ"
1263
+ ]);
1264
+ var kinsokuEnd = new Set([
1265
+ '"',
1266
+ "(",
1267
+ "[",
1268
+ "{",
1269
+ "¡",
1270
+ "¿",
1271
+ "“",
1272
+ "‘",
1273
+ "‚",
1274
+ "„",
1275
+ "«",
1276
+ "‹",
1277
+ "⸘",
1278
+ "(",
1279
+ "〔",
1280
+ "〈",
1281
+ "《",
1282
+ "「",
1283
+ "『",
1284
+ "【",
1285
+ "〖",
1286
+ "〘",
1287
+ "〚"
1288
+ ]);
1289
+ var forwardStickyGlue = new Set([
1290
+ "'",
1291
+ "’"
1292
+ ]);
1293
+ var leftStickyPunctuation = new Set([
1294
+ ".",
1295
+ ",",
1296
+ "!",
1297
+ "?",
1298
+ ":",
1299
+ ";",
1300
+ "،",
1301
+ "؛",
1302
+ "؟",
1303
+ "।",
1304
+ "॥",
1305
+ "၊",
1306
+ "။",
1307
+ "၌",
1308
+ "၍",
1309
+ "၏",
1310
+ ")",
1311
+ "]",
1312
+ "}",
1313
+ "%",
1314
+ '"',
1315
+ "”",
1316
+ "’",
1317
+ "»",
1318
+ "›",
1319
+ "…"
1320
+ ]);
1321
+ var arabicNoSpaceTrailingPunctuation = new Set([
1322
+ ":",
1323
+ ".",
1324
+ "،",
1325
+ "؛"
1326
+ ]);
1327
+ var myanmarMedialGlue = new Set([
1328
+ "၏"
1329
+ ]);
1330
+ var closingQuoteChars = new Set([
1331
+ "”",
1332
+ "’",
1333
+ "»",
1334
+ "›",
1335
+ "」",
1336
+ "』",
1337
+ "】",
1338
+ "》",
1339
+ "〉",
1340
+ "〕",
1341
+ ")"
1342
+ ]);
1343
+ function isLeftStickyPunctuationSegment(segment) {
1344
+ if (isEscapedQuoteClusterSegment(segment))
1345
+ return true;
1346
+ let sawPunctuation = false;
1347
+ for (const ch of segment) {
1348
+ if (leftStickyPunctuation.has(ch) || isLineBreakNumericAffix(ch)) {
1349
+ sawPunctuation = true;
1350
+ continue;
1351
+ }
1352
+ if (sawPunctuation && combiningMarkRe.test(ch))
1353
+ continue;
1354
+ return false;
1355
+ }
1356
+ return sawPunctuation;
1357
+ }
1358
+ function isCJKLineStartProhibitedSegment(segment) {
1359
+ for (const ch of segment) {
1360
+ if (!kinsokuStart.has(ch) && !leftStickyPunctuation.has(ch))
1361
+ return false;
1362
+ }
1363
+ return segment.length > 0;
1364
+ }
1365
+ function isForwardStickyClusterSegment(segment) {
1366
+ if (isEscapedQuoteClusterSegment(segment))
1367
+ return true;
1368
+ for (const ch of segment) {
1369
+ if (!kinsokuEnd.has(ch) && !forwardStickyGlue.has(ch) && !combiningMarkRe.test(ch) && !isLineBreakNumericAffix(ch)) {
1370
+ return false;
1371
+ }
1372
+ }
1373
+ return segment.length > 0;
1374
+ }
1375
+ function isEscapedQuoteClusterSegment(segment) {
1376
+ let sawQuote = false;
1377
+ for (const ch of segment) {
1378
+ if (ch === "\\" || combiningMarkRe.test(ch))
1379
+ continue;
1380
+ if (kinsokuEnd.has(ch) || leftStickyPunctuation.has(ch) || forwardStickyGlue.has(ch)) {
1381
+ sawQuote = true;
1382
+ continue;
1383
+ }
1384
+ return false;
1385
+ }
1386
+ return sawQuote;
1387
+ }
1388
+ function previousCodePointStart(text, end) {
1389
+ const last = end - 1;
1390
+ if (last <= 0)
1391
+ return Math.max(last, 0);
1392
+ const lastCodeUnit = text.charCodeAt(last);
1393
+ if (lastCodeUnit < 56320 || lastCodeUnit > 57343)
1394
+ return last;
1395
+ const maybeHigh = last - 1;
1396
+ if (maybeHigh < 0)
1397
+ return last;
1398
+ const highCodeUnit = text.charCodeAt(maybeHigh);
1399
+ return highCodeUnit >= 55296 && highCodeUnit <= 56319 ? maybeHigh : last;
1400
+ }
1401
+ function getLastCodePoint(text) {
1402
+ if (text.length === 0)
1403
+ return null;
1404
+ const start = previousCodePointStart(text, text.length);
1405
+ return text.slice(start);
1406
+ }
1407
+ function getFirstSignificantCodePoint(text) {
1408
+ for (const ch of text) {
1409
+ if (!combiningMarkRe.test(ch))
1410
+ return ch;
1411
+ }
1412
+ return null;
1413
+ }
1414
+ function getLastSignificantCodePoint(text) {
1415
+ for (let end = text.length;end > 0; ) {
1416
+ const start = previousCodePointStart(text, end);
1417
+ const ch = text.slice(start, end);
1418
+ if (!combiningMarkRe.test(ch))
1419
+ return ch;
1420
+ end = start;
1421
+ }
1422
+ return null;
1423
+ }
1424
+ var lineBreakNumericAffixRanges = [
1425
+ 36,
1426
+ 37,
1427
+ 43,
1428
+ 43,
1429
+ 92,
1430
+ 92,
1431
+ 162,
1432
+ 165,
1433
+ 176,
1434
+ 177,
1435
+ 1423,
1436
+ 1423,
1437
+ 1545,
1438
+ 1547,
1439
+ 1642,
1440
+ 1642,
1441
+ 2046,
1442
+ 2047,
1443
+ 2546,
1444
+ 2547,
1445
+ 2553,
1446
+ 2555,
1447
+ 2801,
1448
+ 2801,
1449
+ 3065,
1450
+ 3065,
1451
+ 3449,
1452
+ 3449,
1453
+ 3647,
1454
+ 3647,
1455
+ 6107,
1456
+ 6107,
1457
+ 8240,
1458
+ 8247,
1459
+ 8279,
1460
+ 8279,
1461
+ 8352,
1462
+ 8399,
1463
+ 8451,
1464
+ 8451,
1465
+ 8457,
1466
+ 8457,
1467
+ 8470,
1468
+ 8470,
1469
+ 8722,
1470
+ 8723,
1471
+ 43064,
1472
+ 43064,
1473
+ 65020,
1474
+ 65020,
1475
+ 65129,
1476
+ 65130,
1477
+ 65284,
1478
+ 65285,
1479
+ 65504,
1480
+ 65505,
1481
+ 65509,
1482
+ 65510,
1483
+ 73693,
1484
+ 73696,
1485
+ 123647,
1486
+ 123647,
1487
+ 126124,
1488
+ 126124,
1489
+ 126128,
1490
+ 126128
1491
+ ];
1492
+ function isCodePointInRanges(codePoint, ranges) {
1493
+ for (let i = 0;i < ranges.length; i += 2) {
1494
+ if (codePoint >= ranges[i] && codePoint <= ranges[i + 1])
1495
+ return true;
1496
+ }
1497
+ return false;
1498
+ }
1499
+ function isLineBreakNumericAffix(ch) {
1500
+ const codePoint = ch.codePointAt(0);
1501
+ return codePoint !== undefined && isCodePointInRanges(codePoint, lineBreakNumericAffixRanges);
1502
+ }
1503
+ function endsWithLineBreakNumericAffix(text) {
1504
+ const last = getLastSignificantCodePoint(text);
1505
+ return last !== null && isLineBreakNumericAffix(last);
1506
+ }
1507
+ function startsWithDecimalDigit(text) {
1508
+ const first = getFirstSignificantCodePoint(text);
1509
+ return first !== null && decimalDigitRe.test(first);
1510
+ }
1511
+ function splitTrailingForwardStickyCluster(text) {
1512
+ const chars = Array.from(text);
1513
+ let splitIndex = chars.length;
1514
+ while (splitIndex > 0) {
1515
+ const ch = chars[splitIndex - 1];
1516
+ if (combiningMarkRe.test(ch)) {
1517
+ splitIndex--;
1518
+ continue;
1519
+ }
1520
+ if (kinsokuEnd.has(ch) || forwardStickyGlue.has(ch)) {
1521
+ splitIndex--;
1522
+ continue;
1523
+ }
1524
+ break;
1525
+ }
1526
+ if (splitIndex <= 0 || splitIndex === chars.length)
1527
+ return null;
1528
+ return {
1529
+ head: chars.slice(0, splitIndex).join(""),
1530
+ tail: chars.slice(splitIndex).join("")
1531
+ };
1532
+ }
1533
+ function getRepeatableSingleCharRunChar(text, isWordLike, kind) {
1534
+ return kind === "text" && !isWordLike && text.length === 1 && text !== "-" && text !== "—" ? text : null;
1535
+ }
1536
+ function materializeDeferredSingleCharRun(texts, chars, lengths, index) {
1537
+ const ch = chars[index];
1538
+ const text = texts[index];
1539
+ if (ch == null)
1540
+ return text;
1541
+ const length = lengths[index];
1542
+ if (text.length === length)
1543
+ return text;
1544
+ const materialized = ch.repeat(length);
1545
+ texts[index] = materialized;
1546
+ return materialized;
1547
+ }
1548
+ function hasArabicNoSpacePunctuation(containsArabic, lastCodePoint) {
1549
+ return containsArabic && lastCodePoint !== null && arabicNoSpaceTrailingPunctuation.has(lastCodePoint);
1550
+ }
1551
+ function endsWithMyanmarMedialGlue(segment) {
1552
+ const lastCodePoint = getLastCodePoint(segment);
1553
+ return lastCodePoint !== null && myanmarMedialGlue.has(lastCodePoint);
1554
+ }
1555
+ function splitLeadingSpaceAndMarks(segment) {
1556
+ if (segment.length < 2 || segment[0] !== " ")
1557
+ return null;
1558
+ const marks = segment.slice(1);
1559
+ if (/^\p{M}+$/u.test(marks)) {
1560
+ return { space: " ", marks };
1561
+ }
1562
+ return null;
1563
+ }
1564
+ function endsWithClosingQuote(text) {
1565
+ let end = text.length;
1566
+ while (end > 0) {
1567
+ const start = previousCodePointStart(text, end);
1568
+ const ch = text.slice(start, end);
1569
+ if (closingQuoteChars.has(ch))
1570
+ return true;
1571
+ if (!leftStickyPunctuation.has(ch))
1572
+ return false;
1573
+ end = start;
1574
+ }
1575
+ return false;
1576
+ }
1577
+ function classifySegmentBreakChar(ch, whiteSpaceProfile) {
1578
+ if (whiteSpaceProfile.preserveOrdinarySpaces || whiteSpaceProfile.preserveHardBreaks) {
1579
+ if (ch === " ")
1580
+ return "preserved-space";
1581
+ if (ch === "\t")
1582
+ return "tab";
1583
+ if (whiteSpaceProfile.preserveHardBreaks && ch === `
1584
+ `)
1585
+ return "hard-break";
1586
+ }
1587
+ if (ch === " ")
1588
+ return "space";
1589
+ if (ch === " " || ch === " " || ch === "⁠" || ch === "\uFEFF") {
1590
+ return "glue";
1591
+ }
1592
+ if (ch === "​")
1593
+ return "zero-width-break";
1594
+ if (ch === "­")
1595
+ return "soft-hyphen";
1596
+ return "text";
1597
+ }
1598
+ var breakCharRe = /[\x20\t\n\xA0\xAD\u200B\u202F\u2060\uFEFF]/;
1599
+ function joinTextParts(parts) {
1600
+ return parts.length === 1 ? parts[0] : parts.join("");
1601
+ }
1602
+ function joinReversedPrefixParts(prefixParts, tail) {
1603
+ const parts = [];
1604
+ for (let i = prefixParts.length - 1;i >= 0; i--) {
1605
+ parts.push(prefixParts[i]);
1606
+ }
1607
+ parts.push(tail);
1608
+ return joinTextParts(parts);
1609
+ }
1610
+ function splitSegmentByBreakKind(segment, isWordLike, start, whiteSpaceProfile) {
1611
+ if (!breakCharRe.test(segment)) {
1612
+ return [{ text: segment, isWordLike, kind: "text", start }];
1613
+ }
1614
+ const pieces = [];
1615
+ let currentKind = null;
1616
+ let currentTextParts = [];
1617
+ let currentStart = start;
1618
+ let currentWordLike = false;
1619
+ let offset = 0;
1620
+ for (const ch of segment) {
1621
+ const kind = classifySegmentBreakChar(ch, whiteSpaceProfile);
1622
+ const wordLike = kind === "text" && isWordLike;
1623
+ if (currentKind !== null && kind === currentKind && wordLike === currentWordLike) {
1624
+ currentTextParts.push(ch);
1625
+ offset += ch.length;
1626
+ continue;
1627
+ }
1628
+ if (currentKind !== null) {
1629
+ pieces.push({
1630
+ text: joinTextParts(currentTextParts),
1631
+ isWordLike: currentWordLike,
1632
+ kind: currentKind,
1633
+ start: currentStart
1634
+ });
1635
+ }
1636
+ currentKind = kind;
1637
+ currentTextParts = [ch];
1638
+ currentStart = start + offset;
1639
+ currentWordLike = wordLike;
1640
+ offset += ch.length;
1641
+ }
1642
+ if (currentKind !== null) {
1643
+ pieces.push({
1644
+ text: joinTextParts(currentTextParts),
1645
+ isWordLike: currentWordLike,
1646
+ kind: currentKind,
1647
+ start: currentStart
1648
+ });
1649
+ }
1650
+ return pieces;
1651
+ }
1652
+ function isTextRunBoundary(kind) {
1653
+ return kind === "space" || kind === "preserved-space" || kind === "zero-width-break" || kind === "hard-break";
1654
+ }
1655
+ var urlSchemeSegmentRe = /^[A-Za-z][A-Za-z0-9+.-]*:$/;
1656
+ function isUrlLikeRunStart(segmentation, index) {
1657
+ const text = segmentation.texts[index];
1658
+ if (text.startsWith("www."))
1659
+ return true;
1660
+ return urlSchemeSegmentRe.test(text) && index + 1 < segmentation.len && segmentation.kinds[index + 1] === "text" && segmentation.texts[index + 1] === "//";
1661
+ }
1662
+ function isUrlQueryBoundarySegment(text) {
1663
+ return text.includes("?") && (text.includes("://") || text.startsWith("www."));
1664
+ }
1665
+ function mergeUrlLikeRuns(segmentation) {
1666
+ const texts = segmentation.texts.slice();
1667
+ const isWordLike = segmentation.isWordLike.slice();
1668
+ const kinds = segmentation.kinds.slice();
1669
+ const starts = segmentation.starts.slice();
1670
+ for (let i = 0;i < segmentation.len; i++) {
1671
+ if (kinds[i] !== "text" || !isUrlLikeRunStart(segmentation, i))
1672
+ continue;
1673
+ const mergedParts = [texts[i]];
1674
+ let j = i + 1;
1675
+ while (j < segmentation.len && !isTextRunBoundary(kinds[j])) {
1676
+ mergedParts.push(texts[j]);
1677
+ isWordLike[i] = true;
1678
+ const endsQueryPrefix = texts[j].includes("?");
1679
+ kinds[j] = "text";
1680
+ texts[j] = "";
1681
+ j++;
1682
+ if (endsQueryPrefix)
1683
+ break;
1684
+ }
1685
+ texts[i] = joinTextParts(mergedParts);
1686
+ }
1687
+ let compactLen = 0;
1688
+ for (let read = 0;read < texts.length; read++) {
1689
+ const text = texts[read];
1690
+ if (text.length === 0)
1691
+ continue;
1692
+ if (compactLen !== read) {
1693
+ texts[compactLen] = text;
1694
+ isWordLike[compactLen] = isWordLike[read];
1695
+ kinds[compactLen] = kinds[read];
1696
+ starts[compactLen] = starts[read];
1697
+ }
1698
+ compactLen++;
1699
+ }
1700
+ texts.length = compactLen;
1701
+ isWordLike.length = compactLen;
1702
+ kinds.length = compactLen;
1703
+ starts.length = compactLen;
1704
+ return {
1705
+ len: compactLen,
1706
+ texts,
1707
+ isWordLike,
1708
+ kinds,
1709
+ starts
1710
+ };
1711
+ }
1712
+ function mergeUrlQueryRuns(segmentation) {
1713
+ const texts = [];
1714
+ const isWordLike = [];
1715
+ const kinds = [];
1716
+ const starts = [];
1717
+ for (let i = 0;i < segmentation.len; i++) {
1718
+ const text = segmentation.texts[i];
1719
+ texts.push(text);
1720
+ isWordLike.push(segmentation.isWordLike[i]);
1721
+ kinds.push(segmentation.kinds[i]);
1722
+ starts.push(segmentation.starts[i]);
1723
+ if (!isUrlQueryBoundarySegment(text))
1724
+ continue;
1725
+ const nextIndex = i + 1;
1726
+ if (nextIndex >= segmentation.len || isTextRunBoundary(segmentation.kinds[nextIndex])) {
1727
+ continue;
1728
+ }
1729
+ const queryParts = [];
1730
+ const queryStart = segmentation.starts[nextIndex];
1731
+ let j = nextIndex;
1732
+ while (j < segmentation.len && !isTextRunBoundary(segmentation.kinds[j])) {
1733
+ queryParts.push(segmentation.texts[j]);
1734
+ j++;
1735
+ }
1736
+ if (queryParts.length > 0) {
1737
+ texts.push(joinTextParts(queryParts));
1738
+ isWordLike.push(true);
1739
+ kinds.push("text");
1740
+ starts.push(queryStart);
1741
+ i = j - 1;
1742
+ }
1743
+ }
1744
+ return {
1745
+ len: texts.length,
1746
+ texts,
1747
+ isWordLike,
1748
+ kinds,
1749
+ starts
1750
+ };
1751
+ }
1752
+ var numericJoinerChars = new Set([
1753
+ ":",
1754
+ "-",
1755
+ "/",
1756
+ "×",
1757
+ ",",
1758
+ ".",
1759
+ "+",
1760
+ "–",
1761
+ "—"
1762
+ ]);
1763
+ var wordInternalSymbolRe = /[\p{P}\p{S}\p{Co}]/u;
1764
+ var emojiPresentationRe = /\p{Emoji_Presentation}/u;
1765
+ var noSpaceWordBreakAfterChars = new Set([
1766
+ "?",
1767
+ "֊",
1768
+ "-",
1769
+ "‐",
1770
+ "‒",
1771
+ "–",
1772
+ "—",
1773
+ "…",
1774
+ "‼",
1775
+ "‽",
1776
+ "⁉"
1777
+ ]);
1778
+ function isAsciiWordInternalSymbolCode(code) {
1779
+ return code >= 33 && code <= 47 && code !== 45 || code >= 58 && code <= 64 && code !== 63 || code >= 91 && code <= 96 || code >= 123 && code <= 126;
1780
+ }
1781
+ function isNoSpaceWordInternalSymbol(ch) {
1782
+ const code = ch.charCodeAt(0);
1783
+ if (code < 128)
1784
+ return isAsciiWordInternalSymbolCode(code);
1785
+ return !noSpaceWordBreakAfterChars.has(ch) && !emojiPresentationRe.test(ch) && wordInternalSymbolRe.test(ch);
1786
+ }
1787
+ function isNoSpaceWordInternalSymbolSegment(text) {
1788
+ let sawSymbol = false;
1789
+ for (const ch of text) {
1790
+ if (combiningMarkRe.test(ch))
1791
+ continue;
1792
+ if (!isNoSpaceWordInternalSymbol(ch))
1793
+ return false;
1794
+ sawSymbol = true;
1795
+ }
1796
+ return sawSymbol;
1797
+ }
1798
+ function endsWithNoSpaceWordJoiner(text) {
1799
+ for (let end = text.length;end > 0; ) {
1800
+ const start = previousCodePointStart(text, end);
1801
+ const ch = text.slice(start, end);
1802
+ if (combiningMarkRe.test(ch)) {
1803
+ end = start;
1804
+ continue;
1805
+ }
1806
+ return isNoSpaceWordInternalSymbol(ch) || isLineBreakNumericAffix(ch);
1807
+ }
1808
+ return false;
1809
+ }
1810
+ function canJoinNoSpaceWordBoundary(leftText, leftWordLike, rightText, rightWordLike) {
1811
+ const leftSymbol = !leftWordLike && isNoSpaceWordInternalSymbolSegment(leftText);
1812
+ const rightSymbol = !rightWordLike && isNoSpaceWordInternalSymbolSegment(rightText);
1813
+ const leftAffix = endsWithLineBreakNumericAffix(leftText);
1814
+ const leftEndsJoiner = (leftWordLike || leftAffix) && endsWithNoSpaceWordJoiner(leftText);
1815
+ if (!leftSymbol && !rightSymbol && !leftEndsJoiner)
1816
+ return false;
1817
+ if (isCJK(leftText) || isCJK(rightText))
1818
+ return false;
1819
+ return (leftWordLike || leftSymbol || leftAffix) && (rightWordLike || rightSymbol);
1820
+ }
1821
+ function segmentContainsDecimalDigit(text) {
1822
+ for (const ch of text) {
1823
+ if (decimalDigitRe.test(ch))
1824
+ return true;
1825
+ }
1826
+ return false;
1827
+ }
1828
+ function isNumericRunSegment(text) {
1829
+ if (text.length === 0)
1830
+ return false;
1831
+ for (const ch of text) {
1832
+ if (decimalDigitRe.test(ch) || numericJoinerChars.has(ch))
1833
+ continue;
1834
+ return false;
1835
+ }
1836
+ return true;
1837
+ }
1838
+ function mergeNumericRuns(segmentation) {
1839
+ const texts = [];
1840
+ const isWordLike = [];
1841
+ const kinds = [];
1842
+ const starts = [];
1843
+ for (let i = 0;i < segmentation.len; i++) {
1844
+ const text = segmentation.texts[i];
1845
+ const kind = segmentation.kinds[i];
1846
+ if (kind === "text" && isNumericRunSegment(text) && segmentContainsDecimalDigit(text)) {
1847
+ const mergedParts = [text];
1848
+ let j = i + 1;
1849
+ while (j < segmentation.len && segmentation.kinds[j] === "text" && isNumericRunSegment(segmentation.texts[j])) {
1850
+ mergedParts.push(segmentation.texts[j]);
1851
+ j++;
1852
+ }
1853
+ texts.push(joinTextParts(mergedParts));
1854
+ isWordLike.push(true);
1855
+ kinds.push("text");
1856
+ starts.push(segmentation.starts[i]);
1857
+ i = j - 1;
1858
+ continue;
1859
+ }
1860
+ texts.push(text);
1861
+ isWordLike.push(segmentation.isWordLike[i]);
1862
+ kinds.push(kind);
1863
+ starts.push(segmentation.starts[i]);
1864
+ }
1865
+ return {
1866
+ len: texts.length,
1867
+ texts,
1868
+ isWordLike,
1869
+ kinds,
1870
+ starts
1871
+ };
1872
+ }
1873
+ function mergeNoSpaceWordChains(segmentation) {
1874
+ const texts = [];
1875
+ const isWordLike = [];
1876
+ const kinds = [];
1877
+ const starts = [];
1878
+ let i = 0;
1879
+ while (i < segmentation.len) {
1880
+ const text = segmentation.texts[i];
1881
+ const kind = segmentation.kinds[i];
1882
+ const wordLike = segmentation.isWordLike[i];
1883
+ if (kind === "text") {
1884
+ const mergedParts = [text];
1885
+ let j = i + 1;
1886
+ let mergedWordLike = wordLike;
1887
+ while (j < segmentation.len && segmentation.kinds[j] === "text" && canJoinNoSpaceWordBoundary(segmentation.texts[j - 1], segmentation.isWordLike[j - 1], segmentation.texts[j], segmentation.isWordLike[j])) {
1888
+ const nextText = segmentation.texts[j];
1889
+ mergedParts.push(nextText);
1890
+ mergedWordLike = mergedWordLike || segmentation.isWordLike[j];
1891
+ j++;
1892
+ }
1893
+ if (j > i + 1) {
1894
+ texts.push(joinTextParts(mergedParts));
1895
+ isWordLike.push(mergedWordLike);
1896
+ kinds.push("text");
1897
+ starts.push(segmentation.starts[i]);
1898
+ i = j;
1899
+ continue;
1900
+ }
1901
+ }
1902
+ texts.push(text);
1903
+ isWordLike.push(wordLike);
1904
+ kinds.push(kind);
1905
+ starts.push(segmentation.starts[i]);
1906
+ i++;
1907
+ }
1908
+ return {
1909
+ len: texts.length,
1910
+ texts,
1911
+ isWordLike,
1912
+ kinds,
1913
+ starts
1914
+ };
1915
+ }
1916
+ function splitHyphenatedNumericRuns(segmentation) {
1917
+ const texts = [];
1918
+ const isWordLike = [];
1919
+ const kinds = [];
1920
+ const starts = [];
1921
+ for (let i = 0;i < segmentation.len; i++) {
1922
+ const text = segmentation.texts[i];
1923
+ if (segmentation.kinds[i] === "text" && text.includes("-")) {
1924
+ const parts = text.split("-");
1925
+ let shouldSplit = parts.length > 1;
1926
+ for (let j = 0;j < parts.length; j++) {
1927
+ const part = parts[j];
1928
+ if (!shouldSplit)
1929
+ break;
1930
+ if (part.length === 0 || !segmentContainsDecimalDigit(part) || !isNumericRunSegment(part)) {
1931
+ shouldSplit = false;
1932
+ }
1933
+ }
1934
+ if (shouldSplit) {
1935
+ let offset = 0;
1936
+ for (let j = 0;j < parts.length; j++) {
1937
+ const part = parts[j];
1938
+ const splitText = j < parts.length - 1 ? `${part}-` : part;
1939
+ texts.push(splitText);
1940
+ isWordLike.push(true);
1941
+ kinds.push("text");
1942
+ starts.push(segmentation.starts[i] + offset);
1943
+ offset += splitText.length;
1944
+ }
1945
+ continue;
1946
+ }
1947
+ }
1948
+ texts.push(text);
1949
+ isWordLike.push(segmentation.isWordLike[i]);
1950
+ kinds.push(segmentation.kinds[i]);
1951
+ starts.push(segmentation.starts[i]);
1952
+ }
1953
+ return {
1954
+ len: texts.length,
1955
+ texts,
1956
+ isWordLike,
1957
+ kinds,
1958
+ starts
1959
+ };
1960
+ }
1961
+ function mergeGlueConnectedTextRuns(segmentation) {
1962
+ const texts = [];
1963
+ const isWordLike = [];
1964
+ const kinds = [];
1965
+ const starts = [];
1966
+ let read = 0;
1967
+ while (read < segmentation.len) {
1968
+ const textParts = [segmentation.texts[read]];
1969
+ let wordLike = segmentation.isWordLike[read];
1970
+ let kind = segmentation.kinds[read];
1971
+ let start = segmentation.starts[read];
1972
+ if (kind === "glue") {
1973
+ const glueParts = [textParts[0]];
1974
+ const glueStart = start;
1975
+ read++;
1976
+ while (read < segmentation.len && segmentation.kinds[read] === "glue") {
1977
+ glueParts.push(segmentation.texts[read]);
1978
+ read++;
1979
+ }
1980
+ const glueText = joinTextParts(glueParts);
1981
+ if (read < segmentation.len && segmentation.kinds[read] === "text") {
1982
+ textParts[0] = glueText;
1983
+ textParts.push(segmentation.texts[read]);
1984
+ wordLike = segmentation.isWordLike[read];
1985
+ kind = "text";
1986
+ start = glueStart;
1987
+ read++;
1988
+ } else {
1989
+ texts.push(glueText);
1990
+ isWordLike.push(false);
1991
+ kinds.push("glue");
1992
+ starts.push(glueStart);
1993
+ continue;
1994
+ }
1995
+ } else {
1996
+ read++;
1997
+ }
1998
+ if (kind === "text") {
1999
+ while (read < segmentation.len && segmentation.kinds[read] === "glue") {
2000
+ const glueParts = [];
2001
+ while (read < segmentation.len && segmentation.kinds[read] === "glue") {
2002
+ glueParts.push(segmentation.texts[read]);
2003
+ read++;
2004
+ }
2005
+ const glueText = joinTextParts(glueParts);
2006
+ if (read < segmentation.len && segmentation.kinds[read] === "text") {
2007
+ textParts.push(glueText, segmentation.texts[read]);
2008
+ wordLike = wordLike || segmentation.isWordLike[read];
2009
+ read++;
2010
+ continue;
2011
+ }
2012
+ textParts.push(glueText);
2013
+ }
2014
+ }
2015
+ texts.push(joinTextParts(textParts));
2016
+ isWordLike.push(wordLike);
2017
+ kinds.push(kind);
2018
+ starts.push(start);
2019
+ }
2020
+ return {
2021
+ len: texts.length,
2022
+ texts,
2023
+ isWordLike,
2024
+ kinds,
2025
+ starts
2026
+ };
2027
+ }
2028
+ function carryTrailingForwardStickyAcrossCJKBoundary(segmentation) {
2029
+ const texts = segmentation.texts.slice();
2030
+ const isWordLike = segmentation.isWordLike.slice();
2031
+ const kinds = segmentation.kinds.slice();
2032
+ const starts = segmentation.starts.slice();
2033
+ for (let i = 0;i < texts.length - 1; i++) {
2034
+ if (kinds[i] !== "text" || kinds[i + 1] !== "text")
2035
+ continue;
2036
+ if (!isCJK(texts[i]) || !isCJK(texts[i + 1]))
2037
+ continue;
2038
+ const split = splitTrailingForwardStickyCluster(texts[i]);
2039
+ if (split === null)
2040
+ continue;
2041
+ texts[i] = split.head;
2042
+ texts[i + 1] = split.tail + texts[i + 1];
2043
+ starts[i + 1] = starts[i] + split.head.length;
2044
+ }
2045
+ return {
2046
+ len: texts.length,
2047
+ texts,
2048
+ isWordLike,
2049
+ kinds,
2050
+ starts
2051
+ };
2052
+ }
2053
+ function buildMergedSegmentation(normalized, profile, whiteSpaceProfile) {
2054
+ const wordSegmenter = getSharedWordSegmenter();
2055
+ let mergedLen = 0;
2056
+ const mergedTexts = [];
2057
+ const mergedTextParts = [];
2058
+ const mergedWordLike = [];
2059
+ const mergedKinds = [];
2060
+ const mergedStarts = [];
2061
+ const mergedSingleCharRunChars = [];
2062
+ const mergedSingleCharRunLengths = [];
2063
+ const mergedContainsCJK = [];
2064
+ const mergedContainsArabicScript = [];
2065
+ const mergedEndsWithClosingQuote = [];
2066
+ const mergedEndsWithMyanmarMedialGlue = [];
2067
+ const mergedHasArabicNoSpacePunctuation = [];
2068
+ for (const s of wordSegmenter.segment(normalized)) {
2069
+ for (const piece of splitSegmentByBreakKind(s.segment, s.isWordLike ?? false, s.index, whiteSpaceProfile)) {
2070
+ let appendPieceToPrevious = function() {
2071
+ if (mergedSingleCharRunChars[prevIndex] !== null) {
2072
+ mergedTextParts[prevIndex] = [
2073
+ materializeDeferredSingleCharRun(mergedTexts, mergedSingleCharRunChars, mergedSingleCharRunLengths, prevIndex)
2074
+ ];
2075
+ mergedSingleCharRunChars[prevIndex] = null;
2076
+ }
2077
+ mergedTextParts[prevIndex].push(piece.text);
2078
+ mergedWordLike[prevIndex] = mergedWordLike[prevIndex] || piece.isWordLike;
2079
+ mergedContainsCJK[prevIndex] = mergedContainsCJK[prevIndex] || pieceContainsCJK;
2080
+ mergedContainsArabicScript[prevIndex] = mergedContainsArabicScript[prevIndex] || pieceContainsArabicScript;
2081
+ mergedEndsWithClosingQuote[prevIndex] = pieceEndsWithClosingQuote;
2082
+ mergedEndsWithMyanmarMedialGlue[prevIndex] = pieceEndsWithMyanmarMedialGlue;
2083
+ mergedHasArabicNoSpacePunctuation[prevIndex] = hasArabicNoSpacePunctuation(mergedContainsArabicScript[prevIndex], pieceLastCodePoint);
2084
+ };
2085
+ const isText = piece.kind === "text";
2086
+ const repeatableSingleCharRunChar = getRepeatableSingleCharRunChar(piece.text, piece.isWordLike, piece.kind);
2087
+ const pieceContainsCJK = isCJK(piece.text);
2088
+ const pieceContainsArabicScript = containsArabicScript(piece.text);
2089
+ const pieceLastCodePoint = getLastCodePoint(piece.text);
2090
+ const pieceEndsWithClosingQuote = endsWithClosingQuote(piece.text);
2091
+ const pieceEndsWithMyanmarMedialGlue = endsWithMyanmarMedialGlue(piece.text);
2092
+ const prevIndex = mergedLen - 1;
2093
+ if (profile.carryCJKAfterClosingQuote && isText && mergedLen > 0 && mergedKinds[prevIndex] === "text" && pieceContainsCJK && mergedContainsCJK[prevIndex] && mergedEndsWithClosingQuote[prevIndex]) {
2094
+ appendPieceToPrevious();
2095
+ } else if (isText && mergedLen > 0 && mergedKinds[prevIndex] === "text" && isCJKLineStartProhibitedSegment(piece.text) && mergedContainsCJK[prevIndex]) {
2096
+ appendPieceToPrevious();
2097
+ } else if (isText && mergedLen > 0 && mergedKinds[prevIndex] === "text" && mergedEndsWithMyanmarMedialGlue[prevIndex]) {
2098
+ appendPieceToPrevious();
2099
+ } else if (isText && mergedLen > 0 && mergedKinds[prevIndex] === "text" && piece.isWordLike && pieceContainsArabicScript && mergedHasArabicNoSpacePunctuation[prevIndex]) {
2100
+ appendPieceToPrevious();
2101
+ mergedWordLike[prevIndex] = true;
2102
+ } else if (repeatableSingleCharRunChar !== null && mergedLen > 0 && mergedKinds[prevIndex] === "text" && mergedSingleCharRunChars[prevIndex] === repeatableSingleCharRunChar) {
2103
+ mergedSingleCharRunLengths[prevIndex] = (mergedSingleCharRunLengths[prevIndex] ?? 1) + 1;
2104
+ } else if (isText && !piece.isWordLike && mergedLen > 0 && mergedKinds[prevIndex] === "text" && !mergedContainsCJK[prevIndex] && (isLeftStickyPunctuationSegment(piece.text) || piece.text === "-" && mergedWordLike[prevIndex])) {
2105
+ appendPieceToPrevious();
2106
+ } else {
2107
+ mergedTexts[mergedLen] = piece.text;
2108
+ mergedTextParts[mergedLen] = [piece.text];
2109
+ mergedWordLike[mergedLen] = piece.isWordLike;
2110
+ mergedKinds[mergedLen] = piece.kind;
2111
+ mergedStarts[mergedLen] = piece.start;
2112
+ mergedSingleCharRunChars[mergedLen] = repeatableSingleCharRunChar;
2113
+ mergedSingleCharRunLengths[mergedLen] = repeatableSingleCharRunChar === null ? 0 : 1;
2114
+ mergedContainsCJK[mergedLen] = pieceContainsCJK;
2115
+ mergedContainsArabicScript[mergedLen] = pieceContainsArabicScript;
2116
+ mergedEndsWithClosingQuote[mergedLen] = pieceEndsWithClosingQuote;
2117
+ mergedEndsWithMyanmarMedialGlue[mergedLen] = pieceEndsWithMyanmarMedialGlue;
2118
+ mergedHasArabicNoSpacePunctuation[mergedLen] = hasArabicNoSpacePunctuation(pieceContainsArabicScript, pieceLastCodePoint);
2119
+ mergedLen++;
2120
+ }
2121
+ }
2122
+ }
2123
+ for (let i = 0;i < mergedLen; i++) {
2124
+ if (mergedSingleCharRunChars[i] !== null) {
2125
+ mergedTexts[i] = materializeDeferredSingleCharRun(mergedTexts, mergedSingleCharRunChars, mergedSingleCharRunLengths, i);
2126
+ continue;
2127
+ }
2128
+ mergedTexts[i] = joinTextParts(mergedTextParts[i]);
2129
+ }
2130
+ for (let i = 1;i < mergedLen; i++) {
2131
+ if (mergedKinds[i] === "text" && !mergedWordLike[i] && isEscapedQuoteClusterSegment(mergedTexts[i]) && mergedKinds[i - 1] === "text" && !mergedContainsCJK[i - 1]) {
2132
+ mergedTexts[i - 1] += mergedTexts[i];
2133
+ mergedWordLike[i - 1] = mergedWordLike[i - 1] || mergedWordLike[i];
2134
+ mergedTexts[i] = "";
2135
+ }
2136
+ }
2137
+ const forwardStickyPrefixParts = Array.from({ length: mergedLen }, () => null);
2138
+ let nextLiveIndex = -1;
2139
+ for (let i = mergedLen - 1;i >= 0; i--) {
2140
+ const text = mergedTexts[i];
2141
+ if (text.length === 0)
2142
+ continue;
2143
+ if (mergedKinds[i] === "text" && !mergedWordLike[i] && nextLiveIndex >= 0 && mergedKinds[nextLiveIndex] === "text" && (isForwardStickyClusterSegment(text) || text === "-" && startsWithDecimalDigit(mergedTexts[nextLiveIndex]))) {
2144
+ const prefixParts = forwardStickyPrefixParts[nextLiveIndex] ?? [];
2145
+ prefixParts.push(text);
2146
+ forwardStickyPrefixParts[nextLiveIndex] = prefixParts;
2147
+ mergedStarts[nextLiveIndex] = mergedStarts[i];
2148
+ mergedTexts[i] = "";
2149
+ continue;
2150
+ }
2151
+ nextLiveIndex = i;
2152
+ }
2153
+ for (let i = 0;i < mergedLen; i++) {
2154
+ const prefixParts = forwardStickyPrefixParts[i];
2155
+ if (prefixParts == null)
2156
+ continue;
2157
+ mergedTexts[i] = joinReversedPrefixParts(prefixParts, mergedTexts[i]);
2158
+ }
2159
+ let compactLen = 0;
2160
+ for (let read = 0;read < mergedLen; read++) {
2161
+ const text = mergedTexts[read];
2162
+ if (text.length === 0)
2163
+ continue;
2164
+ if (compactLen !== read) {
2165
+ mergedTexts[compactLen] = text;
2166
+ mergedWordLike[compactLen] = mergedWordLike[read];
2167
+ mergedKinds[compactLen] = mergedKinds[read];
2168
+ mergedStarts[compactLen] = mergedStarts[read];
2169
+ }
2170
+ compactLen++;
2171
+ }
2172
+ mergedTexts.length = compactLen;
2173
+ mergedWordLike.length = compactLen;
2174
+ mergedKinds.length = compactLen;
2175
+ mergedStarts.length = compactLen;
2176
+ const compacted = mergeGlueConnectedTextRuns({
2177
+ len: compactLen,
2178
+ texts: mergedTexts,
2179
+ isWordLike: mergedWordLike,
2180
+ kinds: mergedKinds,
2181
+ starts: mergedStarts
2182
+ });
2183
+ const withMergedUrls = carryTrailingForwardStickyAcrossCJKBoundary(mergeNoSpaceWordChains(splitHyphenatedNumericRuns(mergeNumericRuns(mergeUrlQueryRuns(mergeUrlLikeRuns(compacted))))));
2184
+ for (let i = 0;i < withMergedUrls.len - 1; i++) {
2185
+ const split = splitLeadingSpaceAndMarks(withMergedUrls.texts[i]);
2186
+ if (split === null)
2187
+ continue;
2188
+ if (withMergedUrls.kinds[i] !== "space" && withMergedUrls.kinds[i] !== "preserved-space" || withMergedUrls.kinds[i + 1] !== "text" || !containsArabicScript(withMergedUrls.texts[i + 1])) {
2189
+ continue;
2190
+ }
2191
+ withMergedUrls.texts[i] = split.space;
2192
+ withMergedUrls.isWordLike[i] = false;
2193
+ withMergedUrls.kinds[i] = withMergedUrls.kinds[i] === "preserved-space" ? "preserved-space" : "space";
2194
+ withMergedUrls.texts[i + 1] = split.marks + withMergedUrls.texts[i + 1];
2195
+ withMergedUrls.starts[i + 1] = withMergedUrls.starts[i] + split.space.length;
2196
+ }
2197
+ return withMergedUrls;
2198
+ }
2199
+ function compileAnalysisChunks(segmentation, whiteSpaceProfile) {
2200
+ if (segmentation.len === 0)
2201
+ return [];
2202
+ if (!whiteSpaceProfile.preserveHardBreaks) {
2203
+ return [{
2204
+ startSegmentIndex: 0,
2205
+ endSegmentIndex: segmentation.len,
2206
+ consumedEndSegmentIndex: segmentation.len
2207
+ }];
2208
+ }
2209
+ const chunks = [];
2210
+ let startSegmentIndex = 0;
2211
+ for (let i = 0;i < segmentation.len; i++) {
2212
+ if (segmentation.kinds[i] !== "hard-break")
2213
+ continue;
2214
+ chunks.push({
2215
+ startSegmentIndex,
2216
+ endSegmentIndex: i,
2217
+ consumedEndSegmentIndex: i + 1
2218
+ });
2219
+ startSegmentIndex = i + 1;
2220
+ }
2221
+ if (startSegmentIndex < segmentation.len) {
2222
+ chunks.push({
2223
+ startSegmentIndex,
2224
+ endSegmentIndex: segmentation.len,
2225
+ consumedEndSegmentIndex: segmentation.len
2226
+ });
2227
+ }
2228
+ return chunks;
2229
+ }
2230
+ function mergeKeepAllTextSegments(normalized, segmentation, breakAfterPunctuation) {
2231
+ if (segmentation.len <= 1)
2232
+ return segmentation;
2233
+ const texts = [];
2234
+ const isWordLike = [];
2235
+ const kinds = [];
2236
+ const starts = [];
2237
+ let groupStart = -1;
2238
+ let groupContainsCJK = false;
2239
+ function pushOriginalText(index) {
2240
+ texts.push(segmentation.texts[index]);
2241
+ isWordLike.push(segmentation.isWordLike[index]);
2242
+ kinds.push("text");
2243
+ starts.push(segmentation.starts[index]);
2244
+ }
2245
+ function pushMergedText(start, end) {
2246
+ let wordLike = false;
2247
+ for (let i = start;i < end; i++) {
2248
+ wordLike = wordLike || segmentation.isWordLike[i];
2249
+ }
2250
+ const sourceStart = segmentation.starts[start];
2251
+ const sourceEnd = end < segmentation.len ? segmentation.starts[end] : normalized.length;
2252
+ texts.push(normalized.slice(sourceStart, sourceEnd));
2253
+ isWordLike.push(wordLike);
2254
+ kinds.push("text");
2255
+ starts.push(sourceStart);
2256
+ }
2257
+ function flushGroup(end) {
2258
+ if (groupStart < 0)
2259
+ return;
2260
+ if (groupContainsCJK) {
2261
+ if (groupStart + 1 === end) {
2262
+ pushOriginalText(groupStart);
2263
+ } else {
2264
+ pushMergedText(groupStart, end);
2265
+ }
2266
+ } else {
2267
+ for (let i = groupStart;i < end; i++)
2268
+ pushOriginalText(i);
2269
+ }
2270
+ groupStart = -1;
2271
+ groupContainsCJK = false;
2272
+ }
2273
+ for (let i = 0;i < segmentation.len; i++) {
2274
+ const text = segmentation.texts[i];
2275
+ const kind = segmentation.kinds[i];
2276
+ if (kind === "text") {
2277
+ if (groupStart >= 0 && !canContinueKeepAllTextRun(segmentation.texts[i - 1], breakAfterPunctuation)) {
2278
+ flushGroup(i);
2279
+ }
2280
+ if (groupStart < 0)
2281
+ groupStart = i;
2282
+ groupContainsCJK = groupContainsCJK || isCJK(text);
2283
+ continue;
2284
+ }
2285
+ flushGroup(i);
2286
+ texts.push(text);
2287
+ isWordLike.push(segmentation.isWordLike[i]);
2288
+ kinds.push(kind);
2289
+ starts.push(segmentation.starts[i]);
2290
+ }
2291
+ flushGroup(segmentation.len);
2292
+ return {
2293
+ len: texts.length,
2294
+ texts,
2295
+ isWordLike,
2296
+ kinds,
2297
+ starts
2298
+ };
2299
+ }
2300
+ function analyzeText(text, profile, whiteSpace = "normal", wordBreak = "normal") {
2301
+ const whiteSpaceProfile = getWhiteSpaceProfile(whiteSpace);
2302
+ const normalized = whiteSpaceProfile.mode === "pre-wrap" ? normalizeWhitespacePreWrap(text) : normalizeWhitespaceNormal(text);
2303
+ if (normalized.length === 0) {
2304
+ return {
2305
+ normalized,
2306
+ chunks: [],
2307
+ len: 0,
2308
+ texts: [],
2309
+ isWordLike: [],
2310
+ kinds: [],
2311
+ starts: []
2312
+ };
2313
+ }
2314
+ const mergedSegmentation = buildMergedSegmentation(normalized, profile, whiteSpaceProfile);
2315
+ const segmentation = wordBreak === "keep-all" ? mergeKeepAllTextSegments(normalized, mergedSegmentation, profile.breakKeepAllAfterPunctuation) : mergedSegmentation;
2316
+ return {
2317
+ normalized,
2318
+ chunks: compileAnalysisChunks(segmentation, whiteSpaceProfile),
2319
+ ...segmentation
2320
+ };
2321
+ }
2322
+
2323
+ // node_modules/@chenglou/pretext/dist/measurement.js
2324
+ var measureContext = null;
2325
+ var segmentMetricCaches = new Map;
2326
+ var cachedEngineProfile = null;
2327
+ var MAX_PREFIX_FIT_GRAPHEMES = 96;
2328
+ var emojiPresentationRe2 = /\p{Emoji_Presentation}/u;
2329
+ var maybeEmojiRe = /[\p{Emoji_Presentation}\p{Extended_Pictographic}\p{Regional_Indicator}\uFE0F\u20E3]/u;
2330
+ var sharedGraphemeSegmenter = null;
2331
+ var emojiCorrectionCache = new Map;
2332
+ function getMeasureContext() {
2333
+ if (measureContext !== null)
2334
+ return measureContext;
2335
+ if (typeof OffscreenCanvas !== "undefined") {
2336
+ measureContext = new OffscreenCanvas(1, 1).getContext("2d");
2337
+ return measureContext;
2338
+ }
2339
+ if (typeof document !== "undefined") {
2340
+ measureContext = document.createElement("canvas").getContext("2d");
2341
+ return measureContext;
2342
+ }
2343
+ throw new Error("Text measurement requires OffscreenCanvas or a DOM canvas context.");
2344
+ }
2345
+ function getSegmentMetricCache(font) {
2346
+ let cache = segmentMetricCaches.get(font);
2347
+ if (!cache) {
2348
+ cache = new Map;
2349
+ segmentMetricCaches.set(font, cache);
2350
+ }
2351
+ return cache;
2352
+ }
2353
+ function getSegmentMetrics(seg, cache) {
2354
+ let metrics = cache.get(seg);
2355
+ if (metrics === undefined) {
2356
+ const ctx = getMeasureContext();
2357
+ metrics = {
2358
+ width: ctx.measureText(seg).width,
2359
+ containsCJK: isCJK(seg)
2360
+ };
2361
+ cache.set(seg, metrics);
2362
+ }
2363
+ return metrics;
2364
+ }
2365
+ function getEngineProfile() {
2366
+ if (cachedEngineProfile !== null)
2367
+ return cachedEngineProfile;
2368
+ if (typeof navigator === "undefined") {
2369
+ cachedEngineProfile = {
2370
+ lineFitEpsilon: 0.005,
2371
+ carryCJKAfterClosingQuote: false,
2372
+ breakKeepAllAfterPunctuation: true,
2373
+ preferPrefixWidthsForBreakableRuns: false,
2374
+ preferEarlySoftHyphenBreak: false
2375
+ };
2376
+ return cachedEngineProfile;
2377
+ }
2378
+ const ua = navigator.userAgent;
2379
+ const vendor = navigator.vendor;
2380
+ const isSafari = vendor === "Apple Computer, Inc." && ua.includes("Safari/") && !ua.includes("Chrome/") && !ua.includes("Chromium/") && !ua.includes("CriOS/") && !ua.includes("FxiOS/") && !ua.includes("EdgiOS/");
2381
+ const isChromium = ua.includes("Chrome/") || ua.includes("Chromium/") || ua.includes("CriOS/") || ua.includes("Edg/");
2382
+ cachedEngineProfile = {
2383
+ lineFitEpsilon: isSafari ? 1 / 64 : 0.005,
2384
+ carryCJKAfterClosingQuote: isChromium,
2385
+ breakKeepAllAfterPunctuation: !isSafari,
2386
+ preferPrefixWidthsForBreakableRuns: isSafari,
2387
+ preferEarlySoftHyphenBreak: isSafari
2388
+ };
2389
+ return cachedEngineProfile;
2390
+ }
2391
+ function parseFontSize(font) {
2392
+ const m = font.match(/(\d+(?:\.\d+)?)\s*px/);
2393
+ return m ? parseFloat(m[1]) : 16;
2394
+ }
2395
+ function getSharedGraphemeSegmenter() {
2396
+ if (sharedGraphemeSegmenter === null) {
2397
+ sharedGraphemeSegmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
2398
+ }
2399
+ return sharedGraphemeSegmenter;
2400
+ }
2401
+ function isEmojiGrapheme(g) {
2402
+ return emojiPresentationRe2.test(g) || g.includes("️");
2403
+ }
2404
+ function textMayContainEmoji(text) {
2405
+ return maybeEmojiRe.test(text);
2406
+ }
2407
+ function getEmojiCorrection(font, fontSize) {
2408
+ let correction = emojiCorrectionCache.get(font);
2409
+ if (correction !== undefined)
2410
+ return correction;
2411
+ const ctx = getMeasureContext();
2412
+ ctx.font = font;
2413
+ const canvasW = ctx.measureText("\uD83D\uDE00").width;
2414
+ correction = 0;
2415
+ if (canvasW > fontSize + 0.5 && typeof document !== "undefined" && document.body !== null) {
2416
+ const span = document.createElement("span");
2417
+ span.style.font = font;
2418
+ span.style.display = "inline-block";
2419
+ span.style.visibility = "hidden";
2420
+ span.style.position = "absolute";
2421
+ span.textContent = "\uD83D\uDE00";
2422
+ document.body.appendChild(span);
2423
+ const domW = span.getBoundingClientRect().width;
2424
+ document.body.removeChild(span);
2425
+ if (canvasW - domW > 0.5) {
2426
+ correction = canvasW - domW;
2427
+ }
2428
+ }
2429
+ emojiCorrectionCache.set(font, correction);
2430
+ return correction;
2431
+ }
2432
+ function countEmojiGraphemes(text) {
2433
+ let count = 0;
2434
+ const graphemeSegmenter = getSharedGraphemeSegmenter();
2435
+ for (const g of graphemeSegmenter.segment(text)) {
2436
+ if (isEmojiGrapheme(g.segment))
2437
+ count++;
2438
+ }
2439
+ return count;
2440
+ }
2441
+ function getEmojiCount(seg, metrics) {
2442
+ if (metrics.emojiCount === undefined) {
2443
+ metrics.emojiCount = countEmojiGraphemes(seg);
2444
+ }
2445
+ return metrics.emojiCount;
2446
+ }
2447
+ function getCorrectedSegmentWidth(seg, metrics, emojiCorrection) {
2448
+ if (emojiCorrection === 0)
2449
+ return metrics.width;
2450
+ return metrics.width - getEmojiCount(seg, metrics) * emojiCorrection;
2451
+ }
2452
+ function getSegmentBreakableFitAdvances(seg, metrics, cache, emojiCorrection, mode) {
2453
+ if (metrics.breakableFitAdvances !== undefined && metrics.breakableFitMode === mode) {
2454
+ return metrics.breakableFitAdvances;
2455
+ }
2456
+ metrics.breakableFitMode = mode;
2457
+ const graphemeSegmenter = getSharedGraphemeSegmenter();
2458
+ const graphemes = [];
2459
+ for (const gs of graphemeSegmenter.segment(seg)) {
2460
+ graphemes.push(gs.segment);
2461
+ }
2462
+ if (graphemes.length <= 1) {
2463
+ metrics.breakableFitAdvances = null;
2464
+ return metrics.breakableFitAdvances;
2465
+ }
2466
+ if (mode === "sum-graphemes") {
2467
+ const advances2 = [];
2468
+ for (const grapheme of graphemes) {
2469
+ const graphemeMetrics = getSegmentMetrics(grapheme, cache);
2470
+ advances2.push(getCorrectedSegmentWidth(grapheme, graphemeMetrics, emojiCorrection));
2471
+ }
2472
+ metrics.breakableFitAdvances = advances2;
2473
+ return metrics.breakableFitAdvances;
2474
+ }
2475
+ if (mode === "pair-context" || graphemes.length > MAX_PREFIX_FIT_GRAPHEMES) {
2476
+ const advances2 = [];
2477
+ let previousGrapheme = null;
2478
+ let previousWidth = 0;
2479
+ for (const grapheme of graphemes) {
2480
+ const graphemeMetrics = getSegmentMetrics(grapheme, cache);
2481
+ const currentWidth = getCorrectedSegmentWidth(grapheme, graphemeMetrics, emojiCorrection);
2482
+ if (previousGrapheme === null) {
2483
+ advances2.push(currentWidth);
2484
+ } else {
2485
+ const pair = previousGrapheme + grapheme;
2486
+ const pairMetrics = getSegmentMetrics(pair, cache);
2487
+ advances2.push(getCorrectedSegmentWidth(pair, pairMetrics, emojiCorrection) - previousWidth);
2488
+ }
2489
+ previousGrapheme = grapheme;
2490
+ previousWidth = currentWidth;
2491
+ }
2492
+ metrics.breakableFitAdvances = advances2;
2493
+ return metrics.breakableFitAdvances;
2494
+ }
2495
+ const advances = [];
2496
+ let prefix = "";
2497
+ let prefixWidth = 0;
2498
+ for (const grapheme of graphemes) {
2499
+ prefix += grapheme;
2500
+ const prefixMetrics = getSegmentMetrics(prefix, cache);
2501
+ const nextPrefixWidth = getCorrectedSegmentWidth(prefix, prefixMetrics, emojiCorrection);
2502
+ advances.push(nextPrefixWidth - prefixWidth);
2503
+ prefixWidth = nextPrefixWidth;
2504
+ }
2505
+ metrics.breakableFitAdvances = advances;
2506
+ return metrics.breakableFitAdvances;
2507
+ }
2508
+ function getFontMeasurementState(font, needsEmojiCorrection) {
2509
+ const ctx = getMeasureContext();
2510
+ ctx.font = font;
2511
+ const cache = getSegmentMetricCache(font);
2512
+ const fontSize = parseFontSize(font);
2513
+ const emojiCorrection = needsEmojiCorrection ? getEmojiCorrection(font, fontSize) : 0;
2514
+ return { cache, fontSize, emojiCorrection };
2515
+ }
2516
+ function clearMeasurementCaches() {
2517
+ segmentMetricCaches.clear();
2518
+ emojiCorrectionCache.clear();
2519
+ sharedGraphemeSegmenter = null;
2520
+ }
2521
+
2522
+ // node_modules/@chenglou/pretext/dist/line-break.js
2523
+ function consumesAtLineStart(kind) {
2524
+ return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
2525
+ }
2526
+ function breaksAfter(kind) {
2527
+ return kind === "space" || kind === "preserved-space" || kind === "tab" || kind === "zero-width-break" || kind === "soft-hyphen";
2528
+ }
2529
+ function normalizeLineStartSegmentIndex(prepared, segmentIndex, endSegmentIndex = prepared.widths.length) {
2530
+ while (segmentIndex < endSegmentIndex) {
2531
+ const kind = prepared.kinds[segmentIndex];
2532
+ if (!consumesAtLineStart(kind))
2533
+ break;
2534
+ segmentIndex++;
2535
+ }
2536
+ return segmentIndex;
2537
+ }
2538
+ function getTabAdvance(lineWidth, tabStopAdvance) {
2539
+ if (tabStopAdvance <= 0)
2540
+ return 0;
2541
+ const remainder = lineWidth % tabStopAdvance;
2542
+ if (Math.abs(remainder) <= 0.000001)
2543
+ return tabStopAdvance;
2544
+ return tabStopAdvance - remainder;
2545
+ }
2546
+ function getLeadingLetterSpacing(prepared, hasContent, segmentIndex) {
2547
+ return prepared.letterSpacing !== 0 && hasContent && prepared.spacingGraphemeCounts[segmentIndex] > 0 ? prepared.letterSpacing : 0;
2548
+ }
2549
+ function getLineEndContribution(leadingSpacing, segmentContribution) {
2550
+ return segmentContribution === 0 ? 0 : leadingSpacing + segmentContribution;
2551
+ }
2552
+ function getTabTrailingLetterSpacing(prepared, segmentIndex) {
2553
+ return prepared.letterSpacing !== 0 && prepared.spacingGraphemeCounts[segmentIndex] > 0 ? prepared.letterSpacing : 0;
2554
+ }
2555
+ function getWholeSegmentFitContribution(prepared, kind, segmentIndex, leadingSpacing, segmentWidth) {
2556
+ const segmentContribution = kind === "tab" ? segmentWidth + getTabTrailingLetterSpacing(prepared, segmentIndex) : prepared.lineEndFitAdvances[segmentIndex];
2557
+ return getLineEndContribution(leadingSpacing, segmentContribution);
2558
+ }
2559
+ function getBreakOpportunityFitContribution(prepared, kind, segmentIndex, leadingSpacing) {
2560
+ const segmentContribution = kind === "tab" ? 0 : prepared.lineEndFitAdvances[segmentIndex];
2561
+ return getLineEndContribution(leadingSpacing, segmentContribution);
2562
+ }
2563
+ function getLineEndPaintContribution(prepared, kind, segmentIndex, leadingSpacing, segmentWidth) {
2564
+ const segmentContribution = kind === "tab" ? segmentWidth : prepared.lineEndPaintAdvances[segmentIndex];
2565
+ return getLineEndContribution(leadingSpacing, segmentContribution);
2566
+ }
2567
+ function getBreakableGraphemeAdvance(prepared, hasContent, baseAdvance) {
2568
+ return prepared.letterSpacing !== 0 && hasContent ? baseAdvance + prepared.letterSpacing : baseAdvance;
2569
+ }
2570
+ function getBreakableCandidateFitWidth(prepared, candidatePaintWidth) {
2571
+ return prepared.letterSpacing === 0 ? candidatePaintWidth : candidatePaintWidth + prepared.letterSpacing;
2572
+ }
2573
+ function getNextPreferredBreakIndex(preferredBreaks, preferredBreakIndex, graphemeEnd) {
2574
+ let index = preferredBreakIndex;
2575
+ while (index < preferredBreaks.length && preferredBreaks[index] < graphemeEnd) {
2576
+ index++;
2577
+ }
2578
+ return index;
2579
+ }
2580
+ function getTerminalLetterSpacing(prepared, startSegmentIndex, startGraphemeIndex, endSegmentIndex, endGraphemeIndex) {
2581
+ if (prepared.letterSpacing === 0)
2582
+ return 0;
2583
+ if (endGraphemeIndex > 0) {
2584
+ return prepared.spacingGraphemeCounts[endSegmentIndex] > 0 ? prepared.letterSpacing : 0;
2585
+ }
2586
+ for (let i = endSegmentIndex - 1;i >= startSegmentIndex; i--) {
2587
+ const kind = prepared.kinds[i];
2588
+ if (kind === "space" || kind === "zero-width-break" || kind === "hard-break")
2589
+ continue;
2590
+ if (kind === "soft-hyphen") {
2591
+ if (i === endSegmentIndex - 1)
2592
+ return 0;
2593
+ continue;
2594
+ }
2595
+ if (i === startSegmentIndex && startGraphemeIndex > 0) {
2596
+ return prepared.letterSpacing;
2597
+ }
2598
+ return prepared.spacingGraphemeCounts[i] > 0 ? prepared.letterSpacing : 0;
2599
+ }
2600
+ return 0;
2601
+ }
2602
+ function finalizeLinePaintWidth(prepared, width, startSegmentIndex, startGraphemeIndex, endSegmentIndex, endGraphemeIndex) {
2603
+ return width + getTerminalLetterSpacing(prepared, startSegmentIndex, startGraphemeIndex, endSegmentIndex, endGraphemeIndex);
2604
+ }
2605
+ function findChunkIndexForStart(prepared, segmentIndex) {
2606
+ let lo = 0;
2607
+ let hi = prepared.chunks.length;
2608
+ while (lo < hi) {
2609
+ const mid = Math.floor((lo + hi) / 2);
2610
+ if (segmentIndex < prepared.chunks[mid].consumedEndSegmentIndex) {
2611
+ hi = mid;
2612
+ } else {
2613
+ lo = mid + 1;
2614
+ }
2615
+ }
2616
+ return lo < prepared.chunks.length ? lo : -1;
2617
+ }
2618
+ function normalizeLineStartInChunk(prepared, chunkIndex, cursor) {
2619
+ let segmentIndex = cursor.segmentIndex;
2620
+ if (cursor.graphemeIndex > 0)
2621
+ return chunkIndex;
2622
+ const chunk = prepared.chunks[chunkIndex];
2623
+ if (chunk.startSegmentIndex === chunk.endSegmentIndex && segmentIndex === chunk.startSegmentIndex) {
2624
+ cursor.segmentIndex = segmentIndex;
2625
+ cursor.graphemeIndex = 0;
2626
+ return chunkIndex;
2627
+ }
2628
+ if (segmentIndex < chunk.startSegmentIndex)
2629
+ segmentIndex = chunk.startSegmentIndex;
2630
+ segmentIndex = normalizeLineStartSegmentIndex(prepared, segmentIndex, chunk.endSegmentIndex);
2631
+ if (segmentIndex < chunk.endSegmentIndex) {
2632
+ cursor.segmentIndex = segmentIndex;
2633
+ cursor.graphemeIndex = 0;
2634
+ return chunkIndex;
2635
+ }
2636
+ if (chunk.consumedEndSegmentIndex >= prepared.widths.length)
2637
+ return -1;
2638
+ cursor.segmentIndex = chunk.consumedEndSegmentIndex;
2639
+ cursor.graphemeIndex = 0;
2640
+ return chunkIndex + 1;
2641
+ }
2642
+ function normalizePreparedLineStart(prepared, cursor) {
2643
+ if (cursor.segmentIndex >= prepared.widths.length)
2644
+ return -1;
2645
+ const chunkIndex = findChunkIndexForStart(prepared, cursor.segmentIndex);
2646
+ if (chunkIndex < 0)
2647
+ return -1;
2648
+ return normalizeLineStartInChunk(prepared, chunkIndex, cursor);
2649
+ }
2650
+ function walkPreparedLinesSimple(prepared, maxWidth, onLine) {
2651
+ const { widths, kinds, breakableFitAdvances, breakablePreferredBreaks } = prepared;
2652
+ if (widths.length === 0)
2653
+ return 0;
2654
+ const engineProfile = getEngineProfile();
2655
+ const lineFitEpsilon = engineProfile.lineFitEpsilon;
2656
+ const fitLimit = maxWidth + lineFitEpsilon;
2657
+ let lineCount = 0;
2658
+ let lineW = 0;
2659
+ let hasContent = false;
2660
+ let lineStartSegmentIndex = 0;
2661
+ let lineStartGraphemeIndex = 0;
2662
+ let lineEndSegmentIndex = 0;
2663
+ let lineEndGraphemeIndex = 0;
2664
+ let pendingBreakSegmentIndex = -1;
2665
+ let pendingBreakPaintWidth = 0;
2666
+ function clearPendingBreak() {
2667
+ pendingBreakSegmentIndex = -1;
2668
+ pendingBreakPaintWidth = 0;
2669
+ }
2670
+ function emitCurrentLine(endSegmentIndex = lineEndSegmentIndex, endGraphemeIndex = lineEndGraphemeIndex, width = lineW) {
2671
+ lineCount++;
2672
+ onLine?.(width, lineStartSegmentIndex, lineStartGraphemeIndex, endSegmentIndex, endGraphemeIndex);
2673
+ lineW = 0;
2674
+ hasContent = false;
2675
+ clearPendingBreak();
2676
+ }
2677
+ function startLineAtSegment(segmentIndex, width) {
2678
+ hasContent = true;
2679
+ lineStartSegmentIndex = segmentIndex;
2680
+ lineStartGraphemeIndex = 0;
2681
+ lineEndSegmentIndex = segmentIndex + 1;
2682
+ lineEndGraphemeIndex = 0;
2683
+ lineW = width;
2684
+ }
2685
+ function startLineAtGrapheme(segmentIndex, graphemeIndex, width) {
2686
+ hasContent = true;
2687
+ lineStartSegmentIndex = segmentIndex;
2688
+ lineStartGraphemeIndex = graphemeIndex;
2689
+ lineEndSegmentIndex = segmentIndex;
2690
+ lineEndGraphemeIndex = graphemeIndex + 1;
2691
+ lineW = width;
2692
+ }
2693
+ function appendWholeSegment(segmentIndex, width) {
2694
+ if (!hasContent) {
2695
+ startLineAtSegment(segmentIndex, width);
2696
+ return;
2697
+ }
2698
+ lineW += width;
2699
+ lineEndSegmentIndex = segmentIndex + 1;
2700
+ lineEndGraphemeIndex = 0;
2701
+ }
2702
+ function appendBreakableSegmentFrom(segmentIndex, startGraphemeIndex) {
2703
+ const fitAdvances = breakableFitAdvances[segmentIndex];
2704
+ const preferredBreaks = breakablePreferredBreaks[segmentIndex] ?? null;
2705
+ let preferredBreakIndex = preferredBreaks === null ? -1 : getNextPreferredBreakIndex(preferredBreaks, 0, startGraphemeIndex + 1);
2706
+ let lastPreferredBreakEnd = -1;
2707
+ let lastPreferredBreakWidth = 0;
2708
+ let g = startGraphemeIndex;
2709
+ while (g < fitAdvances.length) {
2710
+ const gw = fitAdvances[g];
2711
+ if (!hasContent) {
2712
+ startLineAtGrapheme(segmentIndex, g, gw);
2713
+ } else if (lineW + gw > fitLimit) {
2714
+ if (preferredBreaks !== null && lastPreferredBreakEnd > startGraphemeIndex) {
2715
+ emitCurrentLine(segmentIndex, lastPreferredBreakEnd, lastPreferredBreakWidth);
2716
+ g = lastPreferredBreakEnd;
2717
+ preferredBreakIndex = getNextPreferredBreakIndex(preferredBreaks, preferredBreakIndex, g + 1);
2718
+ lastPreferredBreakEnd = -1;
2719
+ lastPreferredBreakWidth = 0;
2720
+ continue;
2721
+ }
2722
+ emitCurrentLine();
2723
+ startLineAtGrapheme(segmentIndex, g, gw);
2724
+ } else {
2725
+ lineW += gw;
2726
+ lineEndSegmentIndex = segmentIndex;
2727
+ lineEndGraphemeIndex = g + 1;
2728
+ }
2729
+ const graphemeEnd = g + 1;
2730
+ if (preferredBreaks !== null && preferredBreaks[preferredBreakIndex] === graphemeEnd) {
2731
+ lastPreferredBreakEnd = graphemeEnd;
2732
+ lastPreferredBreakWidth = lineW;
2733
+ preferredBreakIndex++;
2734
+ }
2735
+ g++;
2736
+ }
2737
+ if (hasContent && lineEndSegmentIndex === segmentIndex && lineEndGraphemeIndex === fitAdvances.length) {
2738
+ lineEndSegmentIndex = segmentIndex + 1;
2739
+ lineEndGraphemeIndex = 0;
2740
+ }
2741
+ }
2742
+ let i = 0;
2743
+ while (i < widths.length) {
2744
+ if (!hasContent) {
2745
+ i = normalizeLineStartSegmentIndex(prepared, i);
2746
+ if (i >= widths.length)
2747
+ break;
2748
+ }
2749
+ const w = widths[i];
2750
+ const kind = kinds[i];
2751
+ const breakAfter = breaksAfter(kind);
2752
+ if (!hasContent) {
2753
+ if (w > fitLimit && breakableFitAdvances[i] !== null) {
2754
+ appendBreakableSegmentFrom(i, 0);
2755
+ } else {
2756
+ startLineAtSegment(i, w);
2757
+ }
2758
+ if (breakAfter) {
2759
+ pendingBreakSegmentIndex = i + 1;
2760
+ pendingBreakPaintWidth = lineW - w;
2761
+ }
2762
+ i++;
2763
+ continue;
2764
+ }
2765
+ const newW = lineW + w;
2766
+ if (newW > fitLimit) {
2767
+ if (breakAfter) {
2768
+ appendWholeSegment(i, w);
2769
+ emitCurrentLine(i + 1, 0, lineW - w);
2770
+ i++;
2771
+ continue;
2772
+ }
2773
+ if (pendingBreakSegmentIndex >= 0) {
2774
+ if (lineEndSegmentIndex > pendingBreakSegmentIndex || lineEndSegmentIndex === pendingBreakSegmentIndex && lineEndGraphemeIndex > 0) {
2775
+ emitCurrentLine();
2776
+ continue;
2777
+ }
2778
+ emitCurrentLine(pendingBreakSegmentIndex, 0, pendingBreakPaintWidth);
2779
+ continue;
2780
+ }
2781
+ if (w > fitLimit && breakableFitAdvances[i] !== null) {
2782
+ emitCurrentLine();
2783
+ appendBreakableSegmentFrom(i, 0);
2784
+ i++;
2785
+ continue;
2786
+ }
2787
+ emitCurrentLine();
2788
+ continue;
2789
+ }
2790
+ appendWholeSegment(i, w);
2791
+ if (breakAfter) {
2792
+ pendingBreakSegmentIndex = i + 1;
2793
+ pendingBreakPaintWidth = lineW - w;
2794
+ }
2795
+ i++;
2796
+ }
2797
+ if (hasContent)
2798
+ emitCurrentLine();
2799
+ return lineCount;
2800
+ }
2801
+ function walkPreparedLinesRaw(prepared, maxWidth, onLine) {
2802
+ if (prepared.simpleLineWalkFastPath) {
2803
+ return walkPreparedLinesSimple(prepared, maxWidth, onLine);
2804
+ }
2805
+ const { widths, kinds, breakableFitAdvances, breakablePreferredBreaks, discretionaryHyphenWidth, chunks } = prepared;
2806
+ if (widths.length === 0 || chunks.length === 0)
2807
+ return 0;
2808
+ const engineProfile = getEngineProfile();
2809
+ const lineFitEpsilon = engineProfile.lineFitEpsilon;
2810
+ const fitLimit = maxWidth + lineFitEpsilon;
2811
+ let lineCount = 0;
2812
+ let lineW = 0;
2813
+ let hasContent = false;
2814
+ let lineStartSegmentIndex = 0;
2815
+ let lineStartGraphemeIndex = 0;
2816
+ let lineEndSegmentIndex = 0;
2817
+ let lineEndGraphemeIndex = 0;
2818
+ let pendingBreakSegmentIndex = -1;
2819
+ let pendingBreakFitWidth = 0;
2820
+ let pendingBreakPaintWidth = 0;
2821
+ let pendingBreakKind = null;
2822
+ function clearPendingBreak() {
2823
+ pendingBreakSegmentIndex = -1;
2824
+ pendingBreakFitWidth = 0;
2825
+ pendingBreakPaintWidth = 0;
2826
+ pendingBreakKind = null;
2827
+ }
2828
+ function getCurrentLinePaintWidth() {
2829
+ return pendingBreakKind === "soft-hyphen" && pendingBreakSegmentIndex === lineEndSegmentIndex && lineEndGraphemeIndex === 0 ? pendingBreakPaintWidth : lineW;
2830
+ }
2831
+ function emitCurrentLine(endSegmentIndex = lineEndSegmentIndex, endGraphemeIndex = lineEndGraphemeIndex, width) {
2832
+ lineCount++;
2833
+ if (onLine !== undefined) {
2834
+ onLine(finalizeLinePaintWidth(prepared, width ?? getCurrentLinePaintWidth(), lineStartSegmentIndex, lineStartGraphemeIndex, endSegmentIndex, endGraphemeIndex), lineStartSegmentIndex, lineStartGraphemeIndex, endSegmentIndex, endGraphemeIndex);
2835
+ }
2836
+ lineW = 0;
2837
+ hasContent = false;
2838
+ clearPendingBreak();
2839
+ }
2840
+ function startLineAtSegment(segmentIndex, width) {
2841
+ hasContent = true;
2842
+ lineStartSegmentIndex = segmentIndex;
2843
+ lineStartGraphemeIndex = 0;
2844
+ lineEndSegmentIndex = segmentIndex + 1;
2845
+ lineEndGraphemeIndex = 0;
2846
+ lineW = width;
2847
+ }
2848
+ function startLineAtGrapheme(segmentIndex, graphemeIndex, width) {
2849
+ hasContent = true;
2850
+ lineStartSegmentIndex = segmentIndex;
2851
+ lineStartGraphemeIndex = graphemeIndex;
2852
+ lineEndSegmentIndex = segmentIndex;
2853
+ lineEndGraphemeIndex = graphemeIndex + 1;
2854
+ lineW = width;
2855
+ }
2856
+ function appendWholeSegment(segmentIndex, advance) {
2857
+ if (!hasContent) {
2858
+ startLineAtSegment(segmentIndex, advance);
2859
+ return;
2860
+ }
2861
+ lineW += advance;
2862
+ lineEndSegmentIndex = segmentIndex + 1;
2863
+ lineEndGraphemeIndex = 0;
2864
+ }
2865
+ function updatePendingBreakForWholeSegment(kind, breakAfter, segmentIndex, segmentWidth, leadingSpacing, advance) {
2866
+ if (!breakAfter)
2867
+ return;
2868
+ const fitAdvance = getBreakOpportunityFitContribution(prepared, kind, segmentIndex, leadingSpacing);
2869
+ const paintAdvance = getLineEndPaintContribution(prepared, kind, segmentIndex, leadingSpacing, segmentWidth);
2870
+ pendingBreakSegmentIndex = segmentIndex + 1;
2871
+ pendingBreakFitWidth = lineW - advance + fitAdvance;
2872
+ pendingBreakPaintWidth = lineW - advance + paintAdvance;
2873
+ pendingBreakKind = kind;
2874
+ }
2875
+ function appendBreakableSegmentFrom(segmentIndex, startGraphemeIndex) {
2876
+ const fitAdvances = breakableFitAdvances[segmentIndex];
2877
+ const preferredBreaks = breakablePreferredBreaks[segmentIndex] ?? null;
2878
+ let preferredBreakIndex = preferredBreaks === null ? -1 : getNextPreferredBreakIndex(preferredBreaks, 0, startGraphemeIndex + 1);
2879
+ let lastPreferredBreakEnd = -1;
2880
+ let lastPreferredBreakWidth = 0;
2881
+ let g = startGraphemeIndex;
2882
+ while (g < fitAdvances.length) {
2883
+ const baseGw = fitAdvances[g];
2884
+ if (!hasContent) {
2885
+ startLineAtGrapheme(segmentIndex, g, baseGw);
2886
+ } else {
2887
+ const gw = getBreakableGraphemeAdvance(prepared, true, baseGw);
2888
+ const candidatePaintWidth = lineW + gw;
2889
+ if (getBreakableCandidateFitWidth(prepared, candidatePaintWidth) > fitLimit) {
2890
+ if (preferredBreaks !== null && lastPreferredBreakEnd > startGraphemeIndex) {
2891
+ emitCurrentLine(segmentIndex, lastPreferredBreakEnd, lastPreferredBreakWidth);
2892
+ g = lastPreferredBreakEnd;
2893
+ preferredBreakIndex = getNextPreferredBreakIndex(preferredBreaks, preferredBreakIndex, g + 1);
2894
+ lastPreferredBreakEnd = -1;
2895
+ lastPreferredBreakWidth = 0;
2896
+ continue;
2897
+ }
2898
+ emitCurrentLine();
2899
+ startLineAtGrapheme(segmentIndex, g, baseGw);
2900
+ } else {
2901
+ lineW = candidatePaintWidth;
2902
+ lineEndSegmentIndex = segmentIndex;
2903
+ lineEndGraphemeIndex = g + 1;
2904
+ }
2905
+ }
2906
+ const graphemeEnd = g + 1;
2907
+ if (preferredBreaks !== null && preferredBreaks[preferredBreakIndex] === graphemeEnd) {
2908
+ lastPreferredBreakEnd = graphemeEnd;
2909
+ lastPreferredBreakWidth = lineW;
2910
+ preferredBreakIndex++;
2911
+ }
2912
+ g++;
2913
+ }
2914
+ if (hasContent && lineEndSegmentIndex === segmentIndex && lineEndGraphemeIndex === fitAdvances.length) {
2915
+ lineEndSegmentIndex = segmentIndex + 1;
2916
+ lineEndGraphemeIndex = 0;
2917
+ }
2918
+ }
2919
+ function emitEmptyChunk(chunk) {
2920
+ lineCount++;
2921
+ onLine?.(0, chunk.startSegmentIndex, 0, chunk.consumedEndSegmentIndex, 0);
2922
+ clearPendingBreak();
2923
+ }
2924
+ for (let chunkIndex = 0;chunkIndex < chunks.length; chunkIndex++) {
2925
+ const chunk = chunks[chunkIndex];
2926
+ if (chunk.startSegmentIndex === chunk.endSegmentIndex) {
2927
+ emitEmptyChunk(chunk);
2928
+ continue;
2929
+ }
2930
+ hasContent = false;
2931
+ lineW = 0;
2932
+ lineStartSegmentIndex = chunk.startSegmentIndex;
2933
+ lineStartGraphemeIndex = 0;
2934
+ lineEndSegmentIndex = chunk.startSegmentIndex;
2935
+ lineEndGraphemeIndex = 0;
2936
+ clearPendingBreak();
2937
+ let i = chunk.startSegmentIndex;
2938
+ while (i < chunk.endSegmentIndex) {
2939
+ if (!hasContent) {
2940
+ i = normalizeLineStartSegmentIndex(prepared, i, chunk.endSegmentIndex);
2941
+ if (i >= chunk.endSegmentIndex)
2942
+ break;
2943
+ }
2944
+ const kind = kinds[i];
2945
+ const breakAfter = breaksAfter(kind);
2946
+ const leadingSpacing = getLeadingLetterSpacing(prepared, hasContent, i);
2947
+ const w = kind === "tab" ? getTabAdvance(lineW + leadingSpacing, prepared.tabStopAdvance) : widths[i];
2948
+ const advance = leadingSpacing + w;
2949
+ const fitAdvance = getWholeSegmentFitContribution(prepared, kind, i, leadingSpacing, w);
2950
+ if (kind === "soft-hyphen") {
2951
+ if (hasContent) {
2952
+ lineEndSegmentIndex = i + 1;
2953
+ lineEndGraphemeIndex = 0;
2954
+ pendingBreakSegmentIndex = i + 1;
2955
+ pendingBreakFitWidth = lineW + discretionaryHyphenWidth;
2956
+ pendingBreakPaintWidth = lineW + discretionaryHyphenWidth;
2957
+ pendingBreakKind = kind;
2958
+ }
2959
+ i++;
2960
+ continue;
2961
+ }
2962
+ if (!hasContent) {
2963
+ if (fitAdvance > fitLimit && breakableFitAdvances[i] !== null) {
2964
+ appendBreakableSegmentFrom(i, 0);
2965
+ } else {
2966
+ startLineAtSegment(i, w);
2967
+ }
2968
+ updatePendingBreakForWholeSegment(kind, breakAfter, i, w, leadingSpacing, advance);
2969
+ i++;
2970
+ continue;
2971
+ }
2972
+ const newFitW = lineW + fitAdvance;
2973
+ if (newFitW > fitLimit) {
2974
+ const currentBreakFitWidth = lineW + getBreakOpportunityFitContribution(prepared, kind, i, leadingSpacing);
2975
+ const currentBreakPaintWidth = lineW + getLineEndPaintContribution(prepared, kind, i, leadingSpacing, w);
2976
+ if (pendingBreakKind === "soft-hyphen" && engineProfile.preferEarlySoftHyphenBreak && pendingBreakFitWidth <= fitLimit) {
2977
+ emitCurrentLine(pendingBreakSegmentIndex, 0, pendingBreakPaintWidth);
2978
+ continue;
2979
+ }
2980
+ if (breakAfter && currentBreakFitWidth <= fitLimit) {
2981
+ appendWholeSegment(i, advance);
2982
+ emitCurrentLine(i + 1, 0, currentBreakPaintWidth);
2983
+ i++;
2984
+ continue;
2985
+ }
2986
+ if (pendingBreakSegmentIndex >= 0 && pendingBreakFitWidth <= fitLimit) {
2987
+ if (lineEndSegmentIndex > pendingBreakSegmentIndex || lineEndSegmentIndex === pendingBreakSegmentIndex && lineEndGraphemeIndex > 0) {
2988
+ emitCurrentLine();
2989
+ continue;
2990
+ }
2991
+ const nextSegmentIndex = pendingBreakSegmentIndex;
2992
+ emitCurrentLine(nextSegmentIndex, 0, pendingBreakPaintWidth);
2993
+ i = nextSegmentIndex;
2994
+ continue;
2995
+ }
2996
+ if (fitAdvance > fitLimit && breakableFitAdvances[i] !== null) {
2997
+ emitCurrentLine();
2998
+ appendBreakableSegmentFrom(i, 0);
2999
+ i++;
3000
+ continue;
3001
+ }
3002
+ emitCurrentLine();
3003
+ continue;
3004
+ }
3005
+ appendWholeSegment(i, advance);
3006
+ updatePendingBreakForWholeSegment(kind, breakAfter, i, w, leadingSpacing, advance);
3007
+ i++;
3008
+ }
3009
+ if (hasContent) {
3010
+ const finalPaintWidth = pendingBreakSegmentIndex === chunk.consumedEndSegmentIndex ? pendingBreakPaintWidth : lineW;
3011
+ emitCurrentLine(chunk.consumedEndSegmentIndex, 0, finalPaintWidth);
3012
+ }
3013
+ }
3014
+ return lineCount;
3015
+ }
3016
+ function stepPreparedChunkLineGeometry(prepared, cursor, chunkIndex, maxWidth) {
3017
+ const chunk = prepared.chunks[chunkIndex];
3018
+ if (chunk.startSegmentIndex === chunk.endSegmentIndex) {
3019
+ cursor.segmentIndex = chunk.consumedEndSegmentIndex;
3020
+ cursor.graphemeIndex = 0;
3021
+ return 0;
3022
+ }
3023
+ const { widths, kinds, breakableFitAdvances, breakablePreferredBreaks, discretionaryHyphenWidth } = prepared;
3024
+ const engineProfile = getEngineProfile();
3025
+ const lineFitEpsilon = engineProfile.lineFitEpsilon;
3026
+ const fitLimit = maxWidth + lineFitEpsilon;
3027
+ const lineStartSegmentIndex = cursor.segmentIndex;
3028
+ const lineStartGraphemeIndex = cursor.graphemeIndex;
3029
+ let lineW = 0;
3030
+ let hasContent = false;
3031
+ let lineEndSegmentIndex = cursor.segmentIndex;
3032
+ let lineEndGraphemeIndex = cursor.graphemeIndex;
3033
+ let pendingBreakSegmentIndex = -1;
3034
+ let pendingBreakFitWidth = 0;
3035
+ let pendingBreakPaintWidth = 0;
3036
+ let pendingBreakKind = null;
3037
+ function getCurrentLinePaintWidth() {
3038
+ return pendingBreakKind === "soft-hyphen" && pendingBreakSegmentIndex === lineEndSegmentIndex && lineEndGraphemeIndex === 0 ? pendingBreakPaintWidth : lineW;
3039
+ }
3040
+ function finishLine(endSegmentIndex = lineEndSegmentIndex, endGraphemeIndex = lineEndGraphemeIndex, width = getCurrentLinePaintWidth()) {
3041
+ if (!hasContent)
3042
+ return null;
3043
+ cursor.segmentIndex = endSegmentIndex;
3044
+ cursor.graphemeIndex = endGraphemeIndex;
3045
+ return finalizeLinePaintWidth(prepared, width, lineStartSegmentIndex, lineStartGraphemeIndex, endSegmentIndex, endGraphemeIndex);
3046
+ }
3047
+ function startLineAtSegment(segmentIndex, width) {
3048
+ hasContent = true;
3049
+ lineEndSegmentIndex = segmentIndex + 1;
3050
+ lineEndGraphemeIndex = 0;
3051
+ lineW = width;
3052
+ }
3053
+ function startLineAtGrapheme(segmentIndex, graphemeIndex, width) {
3054
+ hasContent = true;
3055
+ lineEndSegmentIndex = segmentIndex;
3056
+ lineEndGraphemeIndex = graphemeIndex + 1;
3057
+ lineW = width;
3058
+ }
3059
+ function appendWholeSegment(segmentIndex, advance) {
3060
+ if (!hasContent) {
3061
+ startLineAtSegment(segmentIndex, advance);
3062
+ return;
3063
+ }
3064
+ lineW += advance;
3065
+ lineEndSegmentIndex = segmentIndex + 1;
3066
+ lineEndGraphemeIndex = 0;
3067
+ }
3068
+ function updatePendingBreakForWholeSegment(kind, breakAfter, segmentIndex, segmentWidth, leadingSpacing, advance) {
3069
+ if (!breakAfter)
3070
+ return;
3071
+ const fitAdvance = getBreakOpportunityFitContribution(prepared, kind, segmentIndex, leadingSpacing);
3072
+ const paintAdvance = getLineEndPaintContribution(prepared, kind, segmentIndex, leadingSpacing, segmentWidth);
3073
+ pendingBreakSegmentIndex = segmentIndex + 1;
3074
+ pendingBreakFitWidth = lineW - advance + fitAdvance;
3075
+ pendingBreakPaintWidth = lineW - advance + paintAdvance;
3076
+ pendingBreakKind = kind;
3077
+ }
3078
+ function appendBreakableSegmentFrom(segmentIndex, startGraphemeIndex) {
3079
+ const fitAdvances = breakableFitAdvances[segmentIndex];
3080
+ const preferredBreaks = breakablePreferredBreaks[segmentIndex] ?? null;
3081
+ let preferredBreakIndex = preferredBreaks === null ? -1 : getNextPreferredBreakIndex(preferredBreaks, 0, startGraphemeIndex + 1);
3082
+ let lastPreferredBreakEnd = -1;
3083
+ let lastPreferredBreakWidth = 0;
3084
+ for (let g = startGraphemeIndex;g < fitAdvances.length; g++) {
3085
+ const baseGw = fitAdvances[g];
3086
+ if (!hasContent) {
3087
+ startLineAtGrapheme(segmentIndex, g, baseGw);
3088
+ } else {
3089
+ const gw = getBreakableGraphemeAdvance(prepared, true, baseGw);
3090
+ const candidatePaintWidth = lineW + gw;
3091
+ if (getBreakableCandidateFitWidth(prepared, candidatePaintWidth) > fitLimit) {
3092
+ if (preferredBreaks !== null && lastPreferredBreakEnd > startGraphemeIndex) {
3093
+ return finishLine(segmentIndex, lastPreferredBreakEnd, lastPreferredBreakWidth);
3094
+ }
3095
+ return finishLine();
3096
+ }
3097
+ lineW = candidatePaintWidth;
3098
+ lineEndSegmentIndex = segmentIndex;
3099
+ lineEndGraphemeIndex = g + 1;
3100
+ }
3101
+ const graphemeEnd = g + 1;
3102
+ if (preferredBreaks !== null && preferredBreaks[preferredBreakIndex] === graphemeEnd) {
3103
+ lastPreferredBreakEnd = graphemeEnd;
3104
+ lastPreferredBreakWidth = lineW;
3105
+ preferredBreakIndex++;
3106
+ }
3107
+ }
3108
+ if (hasContent && lineEndSegmentIndex === segmentIndex && lineEndGraphemeIndex === fitAdvances.length) {
3109
+ lineEndSegmentIndex = segmentIndex + 1;
3110
+ lineEndGraphemeIndex = 0;
3111
+ }
3112
+ return null;
3113
+ }
3114
+ function maybeFinishAtSoftHyphen() {
3115
+ if (pendingBreakKind !== "soft-hyphen" || pendingBreakSegmentIndex < 0)
3116
+ return null;
3117
+ if (pendingBreakFitWidth <= fitLimit) {
3118
+ return finishLine(pendingBreakSegmentIndex, 0, pendingBreakPaintWidth);
3119
+ }
3120
+ return null;
3121
+ }
3122
+ for (let i = cursor.segmentIndex;i < chunk.endSegmentIndex; i++) {
3123
+ const kind = kinds[i];
3124
+ const breakAfter = breaksAfter(kind);
3125
+ const startGraphemeIndex = i === cursor.segmentIndex ? cursor.graphemeIndex : 0;
3126
+ const leadingSpacing = getLeadingLetterSpacing(prepared, hasContent, i);
3127
+ const w = kind === "tab" ? getTabAdvance(lineW + leadingSpacing, prepared.tabStopAdvance) : widths[i];
3128
+ const advance = leadingSpacing + w;
3129
+ const fitAdvance = getWholeSegmentFitContribution(prepared, kind, i, leadingSpacing, w);
3130
+ if (kind === "soft-hyphen" && startGraphemeIndex === 0) {
3131
+ if (hasContent) {
3132
+ lineEndSegmentIndex = i + 1;
3133
+ lineEndGraphemeIndex = 0;
3134
+ pendingBreakSegmentIndex = i + 1;
3135
+ pendingBreakFitWidth = lineW + discretionaryHyphenWidth;
3136
+ pendingBreakPaintWidth = lineW + discretionaryHyphenWidth;
3137
+ pendingBreakKind = kind;
3138
+ }
3139
+ continue;
3140
+ }
3141
+ if (!hasContent) {
3142
+ if (startGraphemeIndex > 0) {
3143
+ const line = appendBreakableSegmentFrom(i, startGraphemeIndex);
3144
+ if (line !== null)
3145
+ return line;
3146
+ } else if (fitAdvance > fitLimit && breakableFitAdvances[i] !== null) {
3147
+ const line = appendBreakableSegmentFrom(i, 0);
3148
+ if (line !== null)
3149
+ return line;
3150
+ } else {
3151
+ startLineAtSegment(i, w);
3152
+ }
3153
+ updatePendingBreakForWholeSegment(kind, breakAfter, i, w, leadingSpacing, advance);
3154
+ continue;
3155
+ }
3156
+ const newFitW = lineW + fitAdvance;
3157
+ if (newFitW > fitLimit) {
3158
+ const currentBreakFitWidth = lineW + getBreakOpportunityFitContribution(prepared, kind, i, leadingSpacing);
3159
+ const currentBreakPaintWidth = lineW + getLineEndPaintContribution(prepared, kind, i, leadingSpacing, w);
3160
+ if (pendingBreakKind === "soft-hyphen" && engineProfile.preferEarlySoftHyphenBreak && pendingBreakFitWidth <= fitLimit) {
3161
+ return finishLine(pendingBreakSegmentIndex, 0, pendingBreakPaintWidth);
3162
+ }
3163
+ const softBreakLine = maybeFinishAtSoftHyphen();
3164
+ if (softBreakLine !== null)
3165
+ return softBreakLine;
3166
+ if (breakAfter && currentBreakFitWidth <= fitLimit) {
3167
+ appendWholeSegment(i, advance);
3168
+ return finishLine(i + 1, 0, currentBreakPaintWidth);
3169
+ }
3170
+ if (pendingBreakSegmentIndex >= 0 && pendingBreakFitWidth <= fitLimit) {
3171
+ if (lineEndSegmentIndex > pendingBreakSegmentIndex || lineEndSegmentIndex === pendingBreakSegmentIndex && lineEndGraphemeIndex > 0) {
3172
+ return finishLine();
3173
+ }
3174
+ return finishLine(pendingBreakSegmentIndex, 0, pendingBreakPaintWidth);
3175
+ }
3176
+ if (fitAdvance > fitLimit && breakableFitAdvances[i] !== null) {
3177
+ const currentLine = finishLine();
3178
+ if (currentLine !== null)
3179
+ return currentLine;
3180
+ const line = appendBreakableSegmentFrom(i, 0);
3181
+ if (line !== null)
3182
+ return line;
3183
+ }
3184
+ return finishLine();
3185
+ }
3186
+ appendWholeSegment(i, advance);
3187
+ updatePendingBreakForWholeSegment(kind, breakAfter, i, w, leadingSpacing, advance);
3188
+ }
3189
+ if (pendingBreakSegmentIndex === chunk.consumedEndSegmentIndex && lineEndGraphemeIndex === 0) {
3190
+ return finishLine(chunk.consumedEndSegmentIndex, 0, pendingBreakPaintWidth);
3191
+ }
3192
+ return finishLine(chunk.consumedEndSegmentIndex, 0, lineW);
3193
+ }
3194
+ function stepPreparedSimpleLineGeometry(prepared, cursor, maxWidth) {
3195
+ const { widths, kinds, breakableFitAdvances, breakablePreferredBreaks } = prepared;
3196
+ const engineProfile = getEngineProfile();
3197
+ const lineFitEpsilon = engineProfile.lineFitEpsilon;
3198
+ const fitLimit = maxWidth + lineFitEpsilon;
3199
+ let lineW = 0;
3200
+ let hasContent = false;
3201
+ let lineEndSegmentIndex = cursor.segmentIndex;
3202
+ let lineEndGraphemeIndex = cursor.graphemeIndex;
3203
+ let pendingBreakSegmentIndex = -1;
3204
+ let pendingBreakPaintWidth = 0;
3205
+ for (let i = cursor.segmentIndex;i < widths.length; i++) {
3206
+ const kind = kinds[i];
3207
+ const breakAfter = breaksAfter(kind);
3208
+ const startGraphemeIndex = i === cursor.segmentIndex ? cursor.graphemeIndex : 0;
3209
+ const breakableFitAdvance = breakableFitAdvances[i];
3210
+ const w = widths[i];
3211
+ if (!hasContent) {
3212
+ if (startGraphemeIndex > 0 || w > fitLimit && breakableFitAdvance !== null) {
3213
+ const fitAdvances = breakableFitAdvance;
3214
+ const preferredBreaks = breakablePreferredBreaks[i] ?? null;
3215
+ let preferredBreakIndex = preferredBreaks === null ? -1 : getNextPreferredBreakIndex(preferredBreaks, 0, startGraphemeIndex + 1);
3216
+ let lastPreferredBreakEnd = -1;
3217
+ let lastPreferredBreakWidth = 0;
3218
+ const firstGraphemeWidth = fitAdvances[startGraphemeIndex];
3219
+ hasContent = true;
3220
+ lineW = firstGraphemeWidth;
3221
+ lineEndSegmentIndex = i;
3222
+ lineEndGraphemeIndex = startGraphemeIndex + 1;
3223
+ if (preferredBreaks !== null && preferredBreaks[preferredBreakIndex] === lineEndGraphemeIndex) {
3224
+ lastPreferredBreakEnd = lineEndGraphemeIndex;
3225
+ lastPreferredBreakWidth = lineW;
3226
+ preferredBreakIndex++;
3227
+ }
3228
+ for (let g = startGraphemeIndex + 1;g < fitAdvances.length; g++) {
3229
+ const gw = fitAdvances[g];
3230
+ if (lineW + gw > fitLimit) {
3231
+ if (preferredBreaks !== null && lastPreferredBreakEnd > startGraphemeIndex) {
3232
+ cursor.segmentIndex = i;
3233
+ cursor.graphemeIndex = lastPreferredBreakEnd;
3234
+ return lastPreferredBreakWidth;
3235
+ }
3236
+ cursor.segmentIndex = lineEndSegmentIndex;
3237
+ cursor.graphemeIndex = lineEndGraphemeIndex;
3238
+ return lineW;
3239
+ }
3240
+ lineW += gw;
3241
+ lineEndSegmentIndex = i;
3242
+ lineEndGraphemeIndex = g + 1;
3243
+ if (preferredBreaks !== null && preferredBreaks[preferredBreakIndex] === lineEndGraphemeIndex) {
3244
+ lastPreferredBreakEnd = lineEndGraphemeIndex;
3245
+ lastPreferredBreakWidth = lineW;
3246
+ preferredBreakIndex++;
3247
+ }
3248
+ }
3249
+ if (lineEndSegmentIndex === i && lineEndGraphemeIndex === fitAdvances.length) {
3250
+ lineEndSegmentIndex = i + 1;
3251
+ lineEndGraphemeIndex = 0;
3252
+ }
3253
+ } else {
3254
+ hasContent = true;
3255
+ lineW = w;
3256
+ lineEndSegmentIndex = i + 1;
3257
+ lineEndGraphemeIndex = 0;
3258
+ }
3259
+ if (breakAfter) {
3260
+ pendingBreakSegmentIndex = i + 1;
3261
+ pendingBreakPaintWidth = lineW - w;
3262
+ }
3263
+ continue;
3264
+ }
3265
+ if (lineW + w > fitLimit) {
3266
+ if (breakAfter) {
3267
+ cursor.segmentIndex = i + 1;
3268
+ cursor.graphemeIndex = 0;
3269
+ return lineW;
3270
+ }
3271
+ if (pendingBreakSegmentIndex >= 0) {
3272
+ if (lineEndSegmentIndex > pendingBreakSegmentIndex || lineEndSegmentIndex === pendingBreakSegmentIndex && lineEndGraphemeIndex > 0) {
3273
+ cursor.segmentIndex = lineEndSegmentIndex;
3274
+ cursor.graphemeIndex = lineEndGraphemeIndex;
3275
+ return lineW;
3276
+ }
3277
+ cursor.segmentIndex = pendingBreakSegmentIndex;
3278
+ cursor.graphemeIndex = 0;
3279
+ return pendingBreakPaintWidth;
3280
+ }
3281
+ cursor.segmentIndex = lineEndSegmentIndex;
3282
+ cursor.graphemeIndex = lineEndGraphemeIndex;
3283
+ return lineW;
3284
+ }
3285
+ lineW += w;
3286
+ lineEndSegmentIndex = i + 1;
3287
+ lineEndGraphemeIndex = 0;
3288
+ if (breakAfter) {
3289
+ pendingBreakSegmentIndex = i + 1;
3290
+ pendingBreakPaintWidth = lineW - w;
3291
+ }
3292
+ }
3293
+ if (!hasContent)
3294
+ return null;
3295
+ cursor.segmentIndex = lineEndSegmentIndex;
3296
+ cursor.graphemeIndex = lineEndGraphemeIndex;
3297
+ return lineW;
3298
+ }
3299
+ function stepPreparedLineGeometryFromChunk(prepared, cursor, chunkIndex, maxWidth) {
3300
+ if (prepared.simpleLineWalkFastPath) {
3301
+ return stepPreparedSimpleLineGeometry(prepared, cursor, maxWidth);
3302
+ }
3303
+ return stepPreparedChunkLineGeometry(prepared, cursor, chunkIndex, maxWidth);
3304
+ }
3305
+ function stepPreparedLineGeometry(prepared, cursor, maxWidth) {
3306
+ const chunkIndex = normalizePreparedLineStart(prepared, cursor);
3307
+ if (chunkIndex < 0)
3308
+ return null;
3309
+ return stepPreparedLineGeometryFromChunk(prepared, cursor, chunkIndex, maxWidth);
3310
+ }
3311
+
3312
+ // node_modules/@chenglou/pretext/dist/line-text.js
3313
+ var sharedGraphemeSegmenter2 = null;
3314
+ var sharedLineTextCaches = new WeakMap;
3315
+ function getSharedGraphemeSegmenter2() {
3316
+ if (sharedGraphemeSegmenter2 === null) {
3317
+ sharedGraphemeSegmenter2 = new Intl.Segmenter(undefined, { granularity: "grapheme" });
3318
+ }
3319
+ return sharedGraphemeSegmenter2;
3320
+ }
3321
+ function getSegmentGraphemes(segmentIndex, segments, cache) {
3322
+ let graphemes = cache.get(segmentIndex);
3323
+ if (graphemes !== undefined)
3324
+ return graphemes;
3325
+ graphemes = [];
3326
+ const graphemeSegmenter = getSharedGraphemeSegmenter2();
3327
+ for (const gs of graphemeSegmenter.segment(segments[segmentIndex])) {
3328
+ graphemes.push(gs.segment);
3329
+ }
3330
+ cache.set(segmentIndex, graphemes);
3331
+ return graphemes;
3332
+ }
3333
+ function lineHasDiscretionaryHyphen(kinds, startSegmentIndex, endSegmentIndex) {
3334
+ return endSegmentIndex > startSegmentIndex && kinds[endSegmentIndex - 1] === "soft-hyphen";
3335
+ }
3336
+ function appendSegmentGraphemeRange(text, graphemes, startGraphemeIndex, endGraphemeIndex) {
3337
+ for (let i = startGraphemeIndex;i < endGraphemeIndex; i++) {
3338
+ text += graphemes[i];
3339
+ }
3340
+ return text;
3341
+ }
3342
+ function getLineTextCache(prepared) {
3343
+ let cache = sharedLineTextCaches.get(prepared);
3344
+ if (cache !== undefined)
3345
+ return cache;
3346
+ cache = new Map;
3347
+ sharedLineTextCaches.set(prepared, cache);
3348
+ return cache;
3349
+ }
3350
+ function buildLineTextFromRange(prepared, cache, startSegmentIndex, startGraphemeIndex, endSegmentIndex, endGraphemeIndex) {
3351
+ let text = "";
3352
+ const endsWithDiscretionaryHyphen = lineHasDiscretionaryHyphen(prepared.kinds, startSegmentIndex, endSegmentIndex);
3353
+ for (let i = startSegmentIndex;i < endSegmentIndex; i++) {
3354
+ if (prepared.kinds[i] === "soft-hyphen" || prepared.kinds[i] === "hard-break")
3355
+ continue;
3356
+ if (i === startSegmentIndex && startGraphemeIndex > 0) {
3357
+ const graphemes = getSegmentGraphemes(i, prepared.segments, cache);
3358
+ text = appendSegmentGraphemeRange(text, graphemes, startGraphemeIndex, graphemes.length);
3359
+ } else {
3360
+ text += prepared.segments[i];
3361
+ }
3362
+ }
3363
+ if (endGraphemeIndex > 0) {
3364
+ if (endsWithDiscretionaryHyphen)
3365
+ text += "-";
3366
+ const graphemes = getSegmentGraphemes(endSegmentIndex, prepared.segments, cache);
3367
+ text = appendSegmentGraphemeRange(text, graphemes, startSegmentIndex === endSegmentIndex ? startGraphemeIndex : 0, endGraphemeIndex);
3368
+ } else if (endsWithDiscretionaryHyphen) {
3369
+ text += "-";
3370
+ }
3371
+ return text;
3372
+ }
3373
+ function clearLineTextCaches() {
3374
+ sharedGraphemeSegmenter2 = null;
3375
+ sharedLineTextCaches = new WeakMap;
3376
+ }
3377
+
3378
+ // node_modules/@chenglou/pretext/dist/layout.js
3379
+ var sharedGraphemeSegmenter3 = null;
3380
+ function getSharedGraphemeSegmenter3() {
3381
+ if (sharedGraphemeSegmenter3 === null) {
3382
+ sharedGraphemeSegmenter3 = new Intl.Segmenter(undefined, { granularity: "grapheme" });
3383
+ }
3384
+ return sharedGraphemeSegmenter3;
3385
+ }
3386
+ function createEmptyPrepared(includeSegments) {
3387
+ if (includeSegments) {
3388
+ return {
3389
+ widths: [],
3390
+ lineEndFitAdvances: [],
3391
+ lineEndPaintAdvances: [],
3392
+ kinds: [],
3393
+ simpleLineWalkFastPath: true,
3394
+ segLevels: null,
3395
+ breakableFitAdvances: [],
3396
+ breakablePreferredBreaks: [],
3397
+ letterSpacing: 0,
3398
+ spacingGraphemeCounts: [],
3399
+ discretionaryHyphenWidth: 0,
3400
+ tabStopAdvance: 0,
3401
+ chunks: [],
3402
+ segments: []
3403
+ };
3404
+ }
3405
+ return {
3406
+ widths: [],
3407
+ lineEndFitAdvances: [],
3408
+ lineEndPaintAdvances: [],
3409
+ kinds: [],
3410
+ simpleLineWalkFastPath: true,
3411
+ segLevels: null,
3412
+ breakableFitAdvances: [],
3413
+ breakablePreferredBreaks: [],
3414
+ letterSpacing: 0,
3415
+ spacingGraphemeCounts: [],
3416
+ discretionaryHyphenWidth: 0,
3417
+ tabStopAdvance: 0,
3418
+ chunks: []
3419
+ };
3420
+ }
3421
+ function buildBaseCjkUnits(segText, engineProfile) {
3422
+ const units = [];
3423
+ let unitParts = [];
3424
+ let unitStart = 0;
3425
+ let unitContainsCJK = false;
3426
+ let unitEndsWithClosingQuote = false;
3427
+ let unitIsSingleKinsokuEnd = false;
3428
+ function pushUnit() {
3429
+ if (unitParts.length === 0)
3430
+ return;
3431
+ units.push({
3432
+ text: unitParts.length === 1 ? unitParts[0] : unitParts.join(""),
3433
+ start: unitStart
3434
+ });
3435
+ unitParts = [];
3436
+ unitContainsCJK = false;
3437
+ unitEndsWithClosingQuote = false;
3438
+ unitIsSingleKinsokuEnd = false;
3439
+ }
3440
+ function startUnit(grapheme, start, graphemeContainsCJK) {
3441
+ unitParts = [grapheme];
3442
+ unitStart = start;
3443
+ unitContainsCJK = graphemeContainsCJK;
3444
+ unitEndsWithClosingQuote = endsWithClosingQuote(grapheme);
3445
+ unitIsSingleKinsokuEnd = kinsokuEnd.has(grapheme);
3446
+ }
3447
+ function appendToUnit(grapheme, graphemeContainsCJK) {
3448
+ unitParts.push(grapheme);
3449
+ unitContainsCJK = unitContainsCJK || graphemeContainsCJK;
3450
+ const graphemeEndsWithClosingQuote = endsWithClosingQuote(grapheme);
3451
+ if (grapheme.length === 1 && leftStickyPunctuation.has(grapheme)) {
3452
+ unitEndsWithClosingQuote = unitEndsWithClosingQuote || graphemeEndsWithClosingQuote;
3453
+ } else {
3454
+ unitEndsWithClosingQuote = graphemeEndsWithClosingQuote;
3455
+ }
3456
+ unitIsSingleKinsokuEnd = false;
3457
+ }
3458
+ for (const gs of getSharedGraphemeSegmenter3().segment(segText)) {
3459
+ const grapheme = gs.segment;
3460
+ const graphemeContainsCJK = isCJK(grapheme);
3461
+ if (unitParts.length === 0) {
3462
+ startUnit(grapheme, gs.index, graphemeContainsCJK);
3463
+ continue;
3464
+ }
3465
+ if (unitIsSingleKinsokuEnd || kinsokuStart.has(grapheme) || leftStickyPunctuation.has(grapheme) || engineProfile.carryCJKAfterClosingQuote && graphemeContainsCJK && unitEndsWithClosingQuote) {
3466
+ appendToUnit(grapheme, graphemeContainsCJK);
3467
+ continue;
3468
+ }
3469
+ if (!unitContainsCJK && !graphemeContainsCJK) {
3470
+ appendToUnit(grapheme, graphemeContainsCJK);
3471
+ continue;
3472
+ }
3473
+ pushUnit();
3474
+ startUnit(grapheme, gs.index, graphemeContainsCJK);
3475
+ }
3476
+ pushUnit();
3477
+ return units;
3478
+ }
3479
+ function mergeKeepAllTextUnits(segText, units, breakAfterPunctuation) {
3480
+ if (units.length <= 1)
3481
+ return units;
3482
+ const merged = [];
3483
+ let groupStart = -1;
3484
+ let groupContainsCJK = false;
3485
+ function pushMergedUnit(start, end) {
3486
+ const sourceStart = units[start].start;
3487
+ const sourceEnd = end < units.length ? units[end].start : segText.length;
3488
+ merged.push({
3489
+ text: segText.slice(sourceStart, sourceEnd),
3490
+ start: sourceStart
3491
+ });
3492
+ }
3493
+ function flushGroup(end) {
3494
+ if (groupStart < 0)
3495
+ return;
3496
+ if (groupContainsCJK) {
3497
+ if (groupStart + 1 === end) {
3498
+ merged.push(units[groupStart]);
3499
+ } else {
3500
+ pushMergedUnit(groupStart, end);
3501
+ }
3502
+ } else {
3503
+ for (let i = groupStart;i < end; i++)
3504
+ merged.push(units[i]);
3505
+ }
3506
+ groupStart = -1;
3507
+ groupContainsCJK = false;
3508
+ }
3509
+ for (let i = 0;i < units.length; i++) {
3510
+ const unit = units[i];
3511
+ if (groupStart >= 0 && !canContinueKeepAllTextRun(units[i - 1].text, breakAfterPunctuation)) {
3512
+ flushGroup(i);
3513
+ }
3514
+ if (groupStart < 0)
3515
+ groupStart = i;
3516
+ groupContainsCJK = groupContainsCJK || isCJK(unit.text);
3517
+ }
3518
+ flushGroup(units.length);
3519
+ return merged;
3520
+ }
3521
+ function countRenderedSpacingGraphemes(text, kind) {
3522
+ if (kind === "zero-width-break" || kind === "soft-hyphen" || kind === "hard-break") {
3523
+ return 0;
3524
+ }
3525
+ if (kind === "tab")
3526
+ return 1;
3527
+ let count = 0;
3528
+ const graphemeSegmenter = getSharedGraphemeSegmenter3();
3529
+ for (const _ of graphemeSegmenter.segment(text))
3530
+ count++;
3531
+ return count;
3532
+ }
3533
+ function isPreferredBreakGrapheme(grapheme) {
3534
+ return grapheme === "-" || grapheme === "֊" || grapheme === "‐" || grapheme === "‒" || grapheme === "–" || grapheme === "—";
3535
+ }
3536
+ function getBreakablePreferredBreaks(text) {
3537
+ if (!/[-\u058A\u2010\u2012\u2013\u2014]/u.test(text))
3538
+ return null;
3539
+ const breaks = [];
3540
+ let graphemeIndex = 0;
3541
+ for (const gs of getSharedGraphemeSegmenter3().segment(text)) {
3542
+ graphemeIndex++;
3543
+ if (isPreferredBreakGrapheme(gs.segment))
3544
+ breaks.push(graphemeIndex);
3545
+ }
3546
+ return breaks.length === 0 ? null : breaks;
3547
+ }
3548
+ function addInternalLetterSpacing(width, graphemeCount, letterSpacing) {
3549
+ return graphemeCount > 1 ? width + (graphemeCount - 1) * letterSpacing : width;
3550
+ }
3551
+ function measureAnalysis(analysis, font, includeSegments, wordBreak, letterSpacing) {
3552
+ const engineProfile = getEngineProfile();
3553
+ const { cache, emojiCorrection } = getFontMeasurementState(font, textMayContainEmoji(analysis.normalized));
3554
+ const discretionaryHyphenWidth = getCorrectedSegmentWidth("-", getSegmentMetrics("-", cache), emojiCorrection) + (letterSpacing === 0 ? 0 : letterSpacing * 2);
3555
+ const spaceWidth = getCorrectedSegmentWidth(" ", getSegmentMetrics(" ", cache), emojiCorrection);
3556
+ const tabStopAdvance = spaceWidth * 8;
3557
+ const hasLetterSpacing = letterSpacing !== 0;
3558
+ if (analysis.len === 0)
3559
+ return createEmptyPrepared(includeSegments);
3560
+ const widths = [];
3561
+ const lineEndFitAdvances = [];
3562
+ const lineEndPaintAdvances = [];
3563
+ const kinds = [];
3564
+ let simpleLineWalkFastPath = analysis.chunks.length <= 1 && !hasLetterSpacing;
3565
+ const segStarts = includeSegments ? [] : null;
3566
+ const breakableFitAdvances = [];
3567
+ const breakablePreferredBreaks = [];
3568
+ const spacingGraphemeCounts = [];
3569
+ const segments = includeSegments ? [] : null;
3570
+ const preparedStartByAnalysisIndex = Array.from({ length: analysis.len });
3571
+ function pushMeasuredSegment(text, width, lineEndFitAdvance, lineEndPaintAdvance, kind, start, breakableFitAdvance, breakablePreferredBreak, spacingGraphemeCount) {
3572
+ if (kind !== "text" && kind !== "space" && kind !== "zero-width-break") {
3573
+ simpleLineWalkFastPath = false;
3574
+ }
3575
+ widths.push(width);
3576
+ lineEndFitAdvances.push(lineEndFitAdvance);
3577
+ lineEndPaintAdvances.push(lineEndPaintAdvance);
3578
+ kinds.push(kind);
3579
+ segStarts?.push(start);
3580
+ breakableFitAdvances.push(breakableFitAdvance);
3581
+ breakablePreferredBreaks.push(breakablePreferredBreak);
3582
+ if (hasLetterSpacing)
3583
+ spacingGraphemeCounts.push(spacingGraphemeCount);
3584
+ if (segments !== null)
3585
+ segments.push(text);
3586
+ }
3587
+ function pushMeasuredTextSegment(text, kind, start, wordLike, allowOverflowBreaks) {
3588
+ const textMetrics = getSegmentMetrics(text, cache);
3589
+ const spacingGraphemeCount = hasLetterSpacing ? countRenderedSpacingGraphemes(text, kind) : 0;
3590
+ const width = addInternalLetterSpacing(getCorrectedSegmentWidth(text, textMetrics, emojiCorrection), spacingGraphemeCount, letterSpacing);
3591
+ const baseLineEndFitAdvance = kind === "space" || kind === "preserved-space" || kind === "zero-width-break" ? 0 : width;
3592
+ const lineEndFitAdvance = baseLineEndFitAdvance === 0 ? 0 : baseLineEndFitAdvance + (spacingGraphemeCount > 0 ? letterSpacing : 0);
3593
+ const lineEndPaintAdvance = kind === "space" || kind === "zero-width-break" ? 0 : width;
3594
+ if (allowOverflowBreaks && wordLike && text.length > 1) {
3595
+ let fitMode = "sum-graphemes";
3596
+ if (letterSpacing !== 0) {
3597
+ fitMode = "segment-prefixes";
3598
+ } else if (isNumericRunSegment(text)) {
3599
+ fitMode = "pair-context";
3600
+ } else if (engineProfile.preferPrefixWidthsForBreakableRuns) {
3601
+ fitMode = "segment-prefixes";
3602
+ }
3603
+ const fitAdvances = getSegmentBreakableFitAdvances(text, textMetrics, cache, emojiCorrection, fitMode);
3604
+ const preferredBreaks = fitAdvances === null || wordBreak === "keep-all" ? null : getBreakablePreferredBreaks(text);
3605
+ pushMeasuredSegment(text, width, lineEndFitAdvance, lineEndPaintAdvance, kind, start, fitAdvances, preferredBreaks, spacingGraphemeCount);
3606
+ return;
3607
+ }
3608
+ pushMeasuredSegment(text, width, lineEndFitAdvance, lineEndPaintAdvance, kind, start, null, null, spacingGraphemeCount);
3609
+ }
3610
+ for (let mi = 0;mi < analysis.len; mi++) {
3611
+ preparedStartByAnalysisIndex[mi] = widths.length;
3612
+ const segText = analysis.texts[mi];
3613
+ const segWordLike = analysis.isWordLike[mi];
3614
+ const segKind = analysis.kinds[mi];
3615
+ const segStart = analysis.starts[mi];
3616
+ if (segKind === "soft-hyphen") {
3617
+ pushMeasuredSegment(segText, 0, discretionaryHyphenWidth, discretionaryHyphenWidth, segKind, segStart, null, null, 0);
3618
+ continue;
3619
+ }
3620
+ if (segKind === "hard-break") {
3621
+ pushMeasuredSegment(segText, 0, 0, 0, segKind, segStart, null, null, 0);
3622
+ continue;
3623
+ }
3624
+ if (segKind === "tab") {
3625
+ pushMeasuredSegment(segText, 0, 0, 0, segKind, segStart, null, null, hasLetterSpacing ? countRenderedSpacingGraphemes(segText, segKind) : 0);
3626
+ continue;
3627
+ }
3628
+ const segMetrics = getSegmentMetrics(segText, cache);
3629
+ if (segKind === "text" && segMetrics.containsCJK) {
3630
+ const baseUnits = buildBaseCjkUnits(segText, engineProfile);
3631
+ const measuredUnits = wordBreak === "keep-all" ? mergeKeepAllTextUnits(segText, baseUnits, engineProfile.breakKeepAllAfterPunctuation) : baseUnits;
3632
+ for (let i = 0;i < measuredUnits.length; i++) {
3633
+ const unit = measuredUnits[i];
3634
+ pushMeasuredTextSegment(unit.text, "text", segStart + unit.start, segWordLike, wordBreak === "keep-all" || !isCJK(unit.text));
3635
+ }
3636
+ continue;
3637
+ }
3638
+ pushMeasuredTextSegment(segText, segKind, segStart, segWordLike, true);
3639
+ }
3640
+ const chunks = mapAnalysisChunksToPreparedChunks(analysis.chunks, preparedStartByAnalysisIndex, widths.length);
3641
+ const segLevels = segStarts === null ? null : computeSegmentLevels(analysis.normalized, segStarts);
3642
+ if (segments !== null) {
3643
+ return {
3644
+ widths,
3645
+ lineEndFitAdvances,
3646
+ lineEndPaintAdvances,
3647
+ kinds,
3648
+ simpleLineWalkFastPath,
3649
+ segLevels,
3650
+ breakableFitAdvances,
3651
+ breakablePreferredBreaks,
3652
+ letterSpacing,
3653
+ spacingGraphemeCounts,
3654
+ discretionaryHyphenWidth,
3655
+ tabStopAdvance,
3656
+ chunks,
3657
+ segments
3658
+ };
3659
+ }
3660
+ return {
3661
+ widths,
3662
+ lineEndFitAdvances,
3663
+ lineEndPaintAdvances,
3664
+ kinds,
3665
+ simpleLineWalkFastPath,
3666
+ segLevels,
3667
+ breakableFitAdvances,
3668
+ breakablePreferredBreaks,
3669
+ letterSpacing,
3670
+ spacingGraphemeCounts,
3671
+ discretionaryHyphenWidth,
3672
+ tabStopAdvance,
3673
+ chunks
3674
+ };
3675
+ }
3676
+ function mapAnalysisChunksToPreparedChunks(chunks, preparedStartByAnalysisIndex, preparedEndSegmentIndex) {
3677
+ const preparedChunks = [];
3678
+ for (let i = 0;i < chunks.length; i++) {
3679
+ const chunk = chunks[i];
3680
+ const startSegmentIndex = chunk.startSegmentIndex < preparedStartByAnalysisIndex.length ? preparedStartByAnalysisIndex[chunk.startSegmentIndex] : preparedEndSegmentIndex;
3681
+ const endSegmentIndex = chunk.endSegmentIndex < preparedStartByAnalysisIndex.length ? preparedStartByAnalysisIndex[chunk.endSegmentIndex] : preparedEndSegmentIndex;
3682
+ const consumedEndSegmentIndex = chunk.consumedEndSegmentIndex < preparedStartByAnalysisIndex.length ? preparedStartByAnalysisIndex[chunk.consumedEndSegmentIndex] : preparedEndSegmentIndex;
3683
+ preparedChunks.push({
3684
+ startSegmentIndex,
3685
+ endSegmentIndex,
3686
+ consumedEndSegmentIndex
3687
+ });
3688
+ }
3689
+ return preparedChunks;
3690
+ }
3691
+ function prepareInternal(text, font, includeSegments, options) {
3692
+ const wordBreak = options?.wordBreak ?? "normal";
3693
+ const letterSpacing = options?.letterSpacing ?? 0;
3694
+ const analysis = analyzeText(text, getEngineProfile(), options?.whiteSpace, wordBreak);
3695
+ return measureAnalysis(analysis, font, includeSegments, wordBreak, letterSpacing);
3696
+ }
3697
+ function prepareWithSegments(text, font, options) {
3698
+ return prepareInternal(text, font, true, options);
3699
+ }
3700
+ function getInternalPrepared(prepared) {
3701
+ return prepared;
3702
+ }
3703
+ function measureNaturalWidth(prepared) {
3704
+ let maxWidth = 0;
3705
+ walkPreparedLinesRaw(getInternalPrepared(prepared), Number.POSITIVE_INFINITY, (width) => {
3706
+ if (width > maxWidth)
3707
+ maxWidth = width;
3708
+ });
3709
+ return maxWidth;
3710
+ }
3711
+ function clearCache() {
3712
+ clearAnalysisCaches();
3713
+ sharedGraphemeSegmenter3 = null;
3714
+ clearLineTextCaches();
3715
+ clearMeasurementCaches();
3716
+ }
3717
+
3718
+ // src/core/font-loader.ts
3719
+ import { createRequire } from "node:module";
3720
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
3721
+ import { basename, extname, join, resolve } from "node:path";
3722
+ function readFontFamilyName(filePath) {
3723
+ try {
3724
+ const buf = readFileSync(filePath);
3725
+ if (buf.length < 12)
3726
+ return null;
3727
+ const numTables = buf.readUInt16BE(4);
3728
+ let nameTableOffset = 0;
3729
+ for (let i = 0;i < numTables; i++) {
3730
+ const offset = 12 + i * 16;
3731
+ if (offset + 16 > buf.length)
3732
+ break;
3733
+ const tag = buf.toString("utf8", offset, offset + 4);
3734
+ if (tag === "name") {
3735
+ nameTableOffset = buf.readUInt32BE(offset + 8);
3736
+ break;
3737
+ }
3738
+ }
3739
+ if (!nameTableOffset || nameTableOffset + 6 > buf.length)
3740
+ return null;
3741
+ const count = buf.readUInt16BE(nameTableOffset + 2);
3742
+ const stringOffset = nameTableOffset + buf.readUInt16BE(nameTableOffset + 4);
3743
+ let familyName = null;
3744
+ let preferredFamily = null;
3745
+ for (let i = 0;i < count; i++) {
3746
+ const recOffset = nameTableOffset + 6 + i * 12;
3747
+ if (recOffset + 12 > buf.length)
3748
+ break;
3749
+ const platformId = buf.readUInt16BE(recOffset);
3750
+ const nameId = buf.readUInt16BE(recOffset + 6);
3751
+ const length = buf.readUInt16BE(recOffset + 8);
3752
+ const strOffset = stringOffset + buf.readUInt16BE(recOffset + 10);
3753
+ if (strOffset + length > buf.length)
3754
+ continue;
3755
+ if (nameId === 1 || nameId === 16) {
3756
+ let str = "";
3757
+ if (platformId === 0 || platformId === 3) {
3758
+ if (length % 2 !== 0)
3759
+ continue;
3760
+ str = Buffer.from(buf.subarray(strOffset, strOffset + length)).swap16().toString("utf16le").trim();
3761
+ } else {
3762
+ str = buf.toString("utf8", strOffset, strOffset + length).trim();
3763
+ }
3764
+ str = str.replace(/\0/g, "").trim();
3765
+ if (str) {
3766
+ if (nameId === 16)
3767
+ preferredFamily = str;
3768
+ if (nameId === 1 && !familyName)
3769
+ familyName = str;
3770
+ }
3771
+ }
3772
+ }
3773
+ return preferredFamily || familyName || null;
3774
+ } catch {
3775
+ return null;
3776
+ }
3777
+ }
3778
+ var SUPPORTED_EXTS = new Set([".ttf", ".otf", ".woff2", ".woff"]);
3779
+ var FORMAT_MAP = {
3780
+ ".ttf": "truetype",
3781
+ ".otf": "opentype",
3782
+ ".woff2": "woff2",
3783
+ ".woff": "woff"
3784
+ };
3785
+ var cachedFonts = null;
3786
+ var registeredServerFonts = false;
3787
+ function scanLocalFonts(options) {
3788
+ if (cachedFonts && !options?.refresh) {
3789
+ return cachedFonts;
3790
+ }
3791
+ const cwd = options?.cwd || process.cwd();
3792
+ const searchDirs = [
3793
+ join(cwd, "public", "fonts"),
3794
+ join(cwd, "dist", "fonts"),
3795
+ join(cwd, "fonts")
3796
+ ];
3797
+ const foundMap = new Map;
3798
+ const seenFilenames = new Set;
3799
+ for (const dir of searchDirs) {
3800
+ if (!existsSync(dir))
3801
+ continue;
3802
+ let manifest = {};
3803
+ const manifestPath = join(dir, "fonts.json");
3804
+ if (existsSync(manifestPath)) {
3805
+ try {
3806
+ manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
3807
+ } catch (err) {
3808
+ console.warn(`[font-loader] Failed to parse manifest ${manifestPath}:`, err);
3809
+ }
3810
+ }
3811
+ let files = [];
3812
+ try {
3813
+ files = readdirSync(dir);
3814
+ } catch {
3815
+ continue;
3816
+ }
3817
+ for (const filename of files) {
3818
+ if (seenFilenames.has(filename))
3819
+ continue;
3820
+ const ext = extname(filename).toLowerCase();
3821
+ if (!SUPPORTED_EXTS.has(ext))
3822
+ continue;
3823
+ const fullPath = resolve(dir, filename);
3824
+ let fileStat;
3825
+ try {
3826
+ fileStat = statSync(fullPath);
3827
+ if (!fileStat.isFile())
3828
+ continue;
3829
+ } catch {
3830
+ continue;
3831
+ }
3832
+ seenFilenames.add(filename);
3833
+ const rawBase = basename(filename, ext);
3834
+ const customMeta = manifest[filename] || manifest[rawBase] || {};
3835
+ const parsedFamily = ext === ".ttf" || ext === ".otf" ? readFontFamilyName(fullPath) : null;
3836
+ const family = customMeta.family || parsedFamily || rawBase;
3837
+ const label = customMeta.label || `${family} (本地字体)`;
3838
+ if (!foundMap.has(family)) {
3839
+ foundMap.set(family, {
3840
+ family,
3841
+ label,
3842
+ filename,
3843
+ path: fullPath,
3844
+ url: `/fonts/${encodeURIComponent(filename)}`,
3845
+ format: FORMAT_MAP[ext] || "truetype",
3846
+ fileSizeBytes: fileStat.size
3847
+ });
3848
+ }
3849
+ }
3850
+ }
3851
+ cachedFonts = Array.from(foundMap.values());
3852
+ return cachedFonts;
3853
+ }
3854
+ function registerServerFonts(options) {
3855
+ const fonts = scanLocalFonts({ refresh: options?.refresh });
3856
+ if (registeredServerFonts && !options?.refresh) {
3857
+ return fonts;
3858
+ }
3859
+ try {
3860
+ const { GlobalFonts } = createRequire(import.meta.url)("@napi-rs/canvas");
3861
+ if (GlobalFonts && typeof GlobalFonts.registerFromPath === "function") {
3862
+ for (const font of fonts) {
3863
+ try {
3864
+ GlobalFonts.registerFromPath(font.path, font.family);
3865
+ const rawBase = basename(font.filename, extname(font.filename));
3866
+ if (rawBase !== font.family) {
3867
+ GlobalFonts.registerFromPath(font.path, rawBase);
3868
+ }
3869
+ } catch (err) {
3870
+ console.warn(`[font-loader] Failed to register font ${font.filename} in Skia:`, err);
3871
+ }
3872
+ }
3873
+ registeredServerFonts = true;
3874
+ clearCache();
3875
+ }
3876
+ } catch {}
3877
+ return fonts;
3878
+ }
3879
+
3880
+ export { stepPreparedLineGeometry, getLineTextCache, buildLineTextFromRange, prepareWithSegments, measureNaturalWidth, readFontFamilyName, scanLocalFonts, registerServerFonts };