@stll/folio-core 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/ai-edits/apply.d.ts +3 -9
  2. package/dist/ai-edits/apply.js +94 -14
  3. package/dist/ai-edits/blockRange.d.ts +33 -0
  4. package/dist/ai-edits/blockRange.js +58 -0
  5. package/dist/ai-edits/headless.d.ts +35 -5
  6. package/dist/ai-edits/headless.js +92 -22
  7. package/dist/ai-edits/index.d.ts +5 -3
  8. package/dist/ai-edits/index.js +3 -2
  9. package/dist/ai-edits/snapshot.d.ts +14 -2
  10. package/dist/ai-edits/snapshot.js +12 -1
  11. package/dist/ai-edits/types.d.ts +42 -3
  12. package/dist/compat/eigenpal.d.ts +3 -2
  13. package/dist/compat/eigenpal.js +6 -5
  14. package/dist/controller/layoutPipeline.d.ts +1 -0
  15. package/dist/controller/layoutPipeline.js +35 -115
  16. package/dist/controller/layoutScheduler.d.ts +2 -1
  17. package/dist/controller/layoutScheduler.js +6 -0
  18. package/dist/document-operations.d.ts +122 -0
  19. package/dist/document-operations.js +575 -0
  20. package/dist/docx/blockContentParser.js +17 -7
  21. package/dist/docx/encryption/agileDecryption.d.ts +6 -0
  22. package/dist/docx/encryption/agileDecryption.js +209 -0
  23. package/dist/docx/encryption/compoundFile.d.ts +20 -0
  24. package/dist/docx/encryption/compoundFile.js +251 -0
  25. package/dist/docx/encryption/containerFormat.d.ts +15 -0
  26. package/dist/docx/encryption/containerFormat.js +40 -0
  27. package/dist/docx/encryption/cryptoBytes.d.ts +11 -0
  28. package/dist/docx/encryption/cryptoBytes.js +55 -0
  29. package/dist/docx/encryption/encryptionInfo.d.ts +32 -0
  30. package/dist/docx/encryption/encryptionInfo.js +128 -0
  31. package/dist/docx/encryption/errors.d.ts +18 -0
  32. package/dist/docx/encryption/errors.js +13 -0
  33. package/dist/docx/encryption/index.d.ts +4 -0
  34. package/dist/docx/encryption/index.js +4 -0
  35. package/dist/docx/encryption/openEncryptedDocx.d.ts +28 -0
  36. package/dist/docx/encryption/openEncryptedDocx.js +65 -0
  37. package/dist/docx/footnoteParser.d.ts +1 -17
  38. package/dist/docx/footnoteParser.js +1 -27
  39. package/dist/docx/groupDrawingParser.d.ts +8 -0
  40. package/dist/docx/groupDrawingParser.js +131 -0
  41. package/dist/docx/index.d.ts +3 -1
  42. package/dist/docx/index.js +3 -1
  43. package/dist/docx/numberingParser.d.ts +3 -1
  44. package/dist/docx/numberingParser.js +8 -2
  45. package/dist/docx/paragraphParser.js +9 -3
  46. package/dist/docx/parser.d.ts +4 -5
  47. package/dist/docx/parser.js +8 -2
  48. package/dist/docx/runParser.js +8 -1
  49. package/dist/docx/selectiveXmlPatch.js +4 -10
  50. package/dist/docx/serializer/numberingSerializer.js +3 -1
  51. package/dist/docx/settingsParser.d.ts +6 -3
  52. package/dist/docx/settingsParser.js +2 -0
  53. package/dist/docx/unzip.d.ts +7 -5
  54. package/dist/docx/unzip.js +8 -2
  55. package/dist/docx/xmlParser.js +11 -4
  56. package/dist/index.d.ts +3 -2
  57. package/dist/index.js +6 -5
  58. package/dist/layout-bridge/convert/footnoteLayout.d.ts +37 -1
  59. package/dist/layout-bridge/convert/footnoteLayout.js +138 -14
  60. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +6 -8
  61. package/dist/layout-bridge/convert/headerFooterLayout.js +21 -13
  62. package/dist/layout-bridge/convert/toFlowBlocks.js +58 -19
  63. package/dist/layout-engine/index.d.ts +6 -5
  64. package/dist/layout-engine/index.js +116 -27
  65. package/dist/layout-engine/keep-together.d.ts +13 -8
  66. package/dist/layout-engine/keep-together.js +40 -25
  67. package/dist/layout-engine/layoutInstrumentation.d.ts +11 -1
  68. package/dist/layout-engine/layoutInstrumentation.js +10 -1
  69. package/dist/layout-engine/measure/measureBlocks.js +43 -19
  70. package/dist/layout-engine/measure/measureParagraph.js +91 -14
  71. package/dist/layout-engine/paginator.d.ts +2 -1
  72. package/dist/layout-engine/paginator.js +9 -3
  73. package/dist/layout-engine/textBoxGroup.d.ts +7 -0
  74. package/dist/layout-engine/textBoxGroup.js +8 -0
  75. package/dist/layout-engine/types.d.ts +33 -9
  76. package/dist/layout-engine/types.js +20 -2
  77. package/dist/layout-painter/renderPage.d.ts +15 -1
  78. package/dist/layout-painter/renderPage.js +29 -12
  79. package/dist/layout-painter/renderParagraph.js +44 -9
  80. package/dist/layout-painter/renderTable.js +27 -7
  81. package/dist/managers/DocumentLoaderManager.d.ts +3 -1
  82. package/dist/managers/DocumentLoaderManager.js +13 -5
  83. package/dist/managers/TableSelectionManager.js +1 -1
  84. package/dist/model.js +1 -1
  85. package/dist/paged-layout/pageText.d.ts +14 -0
  86. package/dist/paged-layout/pageText.js +21 -0
  87. package/dist/prosemirror/attrs/index.js +3 -0
  88. package/dist/prosemirror/commands/comments.js +75 -5
  89. package/dist/prosemirror/commands/hyperlink.js +4 -2
  90. package/dist/prosemirror/commands/image.js +2 -1
  91. package/dist/prosemirror/commands/index.js +1 -1
  92. package/dist/prosemirror/commands/propertyChangeScope.d.ts +68 -0
  93. package/dist/prosemirror/commands/propertyChangeScope.js +242 -0
  94. package/dist/prosemirror/conversion/fromProseDoc.js +21 -5
  95. package/dist/prosemirror/conversion/toProseDoc.js +43 -15
  96. package/dist/prosemirror/extensions/core/ParagraphExtension.js +3 -0
  97. package/dist/prosemirror/extensions/features/ListExtension.js +6 -0
  98. package/dist/prosemirror/extensions/nodes/TableExtension.js +12 -11
  99. package/dist/prosemirror/findReplaceSelection.js +2 -1
  100. package/dist/prosemirror/index.js +1 -1
  101. package/dist/prosemirror/insertOperations.js +1 -1
  102. package/dist/prosemirror/schema/nodes.d.ts +14 -7
  103. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  104. package/dist/prosemirror/utils/tabCalculator.js +4 -2
  105. package/dist/redline.d.ts +20 -0
  106. package/dist/redline.js +127 -0
  107. package/dist/server.d.ts +7 -3
  108. package/dist/server.js +6 -2
  109. package/dist/symbols.d.ts +35 -0
  110. package/dist/symbols.js +512 -0
  111. package/dist/utils/clipboard.js +3 -3
  112. package/dist/utils/fontLoader.js +3 -0
  113. package/dist/utils/fontResolver.js +65 -1
  114. package/dist/utils/zoom.d.ts +21 -0
  115. package/dist/utils/zoom.js +21 -0
  116. package/dist/version-comparison.d.ts +92 -0
  117. package/dist/version-comparison.js +436 -0
  118. package/package.json +7 -3
  119. package/dist/paged-layout/headerFooterMargins.d.ts +0 -73
  120. package/dist/paged-layout/headerFooterMargins.js +0 -120
@@ -0,0 +1,512 @@
1
+ //#region src/symbols.ts
2
+ const SYMBOL_CATEGORIES = [
3
+ {
4
+ name: "Common",
5
+ nameKey: "dialogs.insertSymbol.categories.common",
6
+ symbols: [
7
+ {
8
+ char: "©",
9
+ name: "Copyright"
10
+ },
11
+ {
12
+ char: "®",
13
+ name: "Registered"
14
+ },
15
+ {
16
+ char: "™",
17
+ name: "Trademark"
18
+ },
19
+ {
20
+ char: "•",
21
+ name: "Bullet"
22
+ },
23
+ {
24
+ char: "…",
25
+ name: "Ellipsis"
26
+ },
27
+ {
28
+ char: "—",
29
+ name: "Em dash"
30
+ },
31
+ {
32
+ char: "–",
33
+ name: "En dash"
34
+ },
35
+ {
36
+ char: "±",
37
+ name: "Plus-minus"
38
+ },
39
+ {
40
+ char: "×",
41
+ name: "Multiply"
42
+ },
43
+ {
44
+ char: "÷",
45
+ name: "Divide"
46
+ },
47
+ {
48
+ char: "≠",
49
+ name: "Not equal"
50
+ },
51
+ {
52
+ char: "≈",
53
+ name: "Approximately"
54
+ },
55
+ {
56
+ char: "≤",
57
+ name: "Less or equal"
58
+ },
59
+ {
60
+ char: "≥",
61
+ name: "Greater or equal"
62
+ },
63
+ {
64
+ char: "°",
65
+ name: "Degree"
66
+ },
67
+ {
68
+ char: "µ",
69
+ name: "Micro"
70
+ },
71
+ {
72
+ char: "¶",
73
+ name: "Pilcrow"
74
+ },
75
+ {
76
+ char: "§",
77
+ name: "Section"
78
+ },
79
+ {
80
+ char: "†",
81
+ name: "Dagger"
82
+ },
83
+ {
84
+ char: "‡",
85
+ name: "Double dagger"
86
+ },
87
+ {
88
+ char: "¿",
89
+ name: "Inverted question"
90
+ },
91
+ {
92
+ char: "¡",
93
+ name: "Inverted exclamation"
94
+ },
95
+ {
96
+ char: "‰",
97
+ name: "Per mille"
98
+ },
99
+ {
100
+ char: "∞",
101
+ name: "Infinity"
102
+ }
103
+ ]
104
+ },
105
+ {
106
+ name: "Arrows",
107
+ nameKey: "dialogs.insertSymbol.categories.arrows",
108
+ symbols: [
109
+ {
110
+ char: "←",
111
+ name: "Left"
112
+ },
113
+ {
114
+ char: "→",
115
+ name: "Right"
116
+ },
117
+ {
118
+ char: "↑",
119
+ name: "Up"
120
+ },
121
+ {
122
+ char: "↓",
123
+ name: "Down"
124
+ },
125
+ {
126
+ char: "↔",
127
+ name: "Left-right"
128
+ },
129
+ {
130
+ char: "↕",
131
+ name: "Up-down"
132
+ },
133
+ {
134
+ char: "⇐",
135
+ name: "Double left"
136
+ },
137
+ {
138
+ char: "⇒",
139
+ name: "Double right"
140
+ },
141
+ {
142
+ char: "⇑",
143
+ name: "Double up"
144
+ },
145
+ {
146
+ char: "⇓",
147
+ name: "Double down"
148
+ },
149
+ {
150
+ char: "⇔",
151
+ name: "Double left-right"
152
+ },
153
+ {
154
+ char: "➡",
155
+ name: "Heavy right"
156
+ },
157
+ {
158
+ char: "↩",
159
+ name: "Return"
160
+ },
161
+ {
162
+ char: "↪",
163
+ name: "Curved right"
164
+ },
165
+ {
166
+ char: "↻",
167
+ name: "Clockwise"
168
+ },
169
+ {
170
+ char: "↺",
171
+ name: "Counter-clockwise"
172
+ }
173
+ ]
174
+ },
175
+ {
176
+ name: "Math",
177
+ nameKey: "dialogs.insertSymbol.categories.math",
178
+ symbols: [
179
+ {
180
+ char: "∑",
181
+ name: "Summation"
182
+ },
183
+ {
184
+ char: "∏",
185
+ name: "Product"
186
+ },
187
+ {
188
+ char: "∫",
189
+ name: "Integral"
190
+ },
191
+ {
192
+ char: "√",
193
+ name: "Square root"
194
+ },
195
+ {
196
+ char: "∂",
197
+ name: "Partial diff"
198
+ },
199
+ {
200
+ char: "∇",
201
+ name: "Nabla"
202
+ },
203
+ {
204
+ char: "∈",
205
+ name: "Element of"
206
+ },
207
+ {
208
+ char: "∉",
209
+ name: "Not element"
210
+ },
211
+ {
212
+ char: "⊂",
213
+ name: "Subset"
214
+ },
215
+ {
216
+ char: "⊃",
217
+ name: "Superset"
218
+ },
219
+ {
220
+ char: "∪",
221
+ name: "Union"
222
+ },
223
+ {
224
+ char: "∩",
225
+ name: "Intersection"
226
+ },
227
+ {
228
+ char: "∧",
229
+ name: "And"
230
+ },
231
+ {
232
+ char: "∨",
233
+ name: "Or"
234
+ },
235
+ {
236
+ char: "¬",
237
+ name: "Not"
238
+ },
239
+ {
240
+ char: "∀",
241
+ name: "For all"
242
+ },
243
+ {
244
+ char: "∃",
245
+ name: "Exists"
246
+ },
247
+ {
248
+ char: "∅",
249
+ name: "Empty set"
250
+ },
251
+ {
252
+ char: "∝",
253
+ name: "Proportional"
254
+ },
255
+ {
256
+ char: "∠",
257
+ name: "Angle"
258
+ }
259
+ ]
260
+ },
261
+ {
262
+ name: "Greek",
263
+ nameKey: "dialogs.insertSymbol.categories.greek",
264
+ symbols: [
265
+ {
266
+ char: "α",
267
+ name: "alpha"
268
+ },
269
+ {
270
+ char: "β",
271
+ name: "beta"
272
+ },
273
+ {
274
+ char: "γ",
275
+ name: "gamma"
276
+ },
277
+ {
278
+ char: "δ",
279
+ name: "delta"
280
+ },
281
+ {
282
+ char: "ε",
283
+ name: "epsilon"
284
+ },
285
+ {
286
+ char: "ζ",
287
+ name: "zeta"
288
+ },
289
+ {
290
+ char: "η",
291
+ name: "eta"
292
+ },
293
+ {
294
+ char: "θ",
295
+ name: "theta"
296
+ },
297
+ {
298
+ char: "λ",
299
+ name: "lambda"
300
+ },
301
+ {
302
+ char: "μ",
303
+ name: "mu"
304
+ },
305
+ {
306
+ char: "π",
307
+ name: "pi"
308
+ },
309
+ {
310
+ char: "ρ",
311
+ name: "rho"
312
+ },
313
+ {
314
+ char: "σ",
315
+ name: "sigma"
316
+ },
317
+ {
318
+ char: "τ",
319
+ name: "tau"
320
+ },
321
+ {
322
+ char: "φ",
323
+ name: "phi"
324
+ },
325
+ {
326
+ char: "ψ",
327
+ name: "psi"
328
+ },
329
+ {
330
+ char: "ω",
331
+ name: "omega"
332
+ },
333
+ {
334
+ char: "Δ",
335
+ name: "Delta"
336
+ },
337
+ {
338
+ char: "Σ",
339
+ name: "Sigma"
340
+ },
341
+ {
342
+ char: "Ω",
343
+ name: "Omega"
344
+ },
345
+ {
346
+ char: "Π",
347
+ name: "Pi"
348
+ },
349
+ {
350
+ char: "Φ",
351
+ name: "Phi"
352
+ },
353
+ {
354
+ char: "Ψ",
355
+ name: "Psi"
356
+ },
357
+ {
358
+ char: "Θ",
359
+ name: "Theta"
360
+ }
361
+ ]
362
+ },
363
+ {
364
+ name: "Currency",
365
+ nameKey: "dialogs.insertSymbol.categories.currency",
366
+ symbols: [
367
+ {
368
+ char: "$",
369
+ name: "Dollar"
370
+ },
371
+ {
372
+ char: "€",
373
+ name: "Euro"
374
+ },
375
+ {
376
+ char: "£",
377
+ name: "Pound"
378
+ },
379
+ {
380
+ char: "¥",
381
+ name: "Yen"
382
+ },
383
+ {
384
+ char: "₹",
385
+ name: "Rupee"
386
+ },
387
+ {
388
+ char: "₽",
389
+ name: "Ruble"
390
+ },
391
+ {
392
+ char: "₩",
393
+ name: "Won"
394
+ },
395
+ {
396
+ char: "₿",
397
+ name: "Bitcoin"
398
+ },
399
+ {
400
+ char: "¢",
401
+ name: "Cent"
402
+ },
403
+ {
404
+ char: "₫",
405
+ name: "Dong"
406
+ },
407
+ {
408
+ char: "₺",
409
+ name: "Lira"
410
+ },
411
+ {
412
+ char: "₴",
413
+ name: "Hryvnia"
414
+ }
415
+ ]
416
+ },
417
+ {
418
+ name: "Shapes",
419
+ nameKey: "dialogs.insertSymbol.categories.shapes",
420
+ symbols: [
421
+ {
422
+ char: "■",
423
+ name: "Black square"
424
+ },
425
+ {
426
+ char: "□",
427
+ name: "White square"
428
+ },
429
+ {
430
+ char: "▲",
431
+ name: "Up triangle"
432
+ },
433
+ {
434
+ char: "▼",
435
+ name: "Down triangle"
436
+ },
437
+ {
438
+ char: "●",
439
+ name: "Black circle"
440
+ },
441
+ {
442
+ char: "○",
443
+ name: "White circle"
444
+ },
445
+ {
446
+ char: "◆",
447
+ name: "Black diamond"
448
+ },
449
+ {
450
+ char: "◇",
451
+ name: "White diamond"
452
+ },
453
+ {
454
+ char: "★",
455
+ name: "Black star"
456
+ },
457
+ {
458
+ char: "☆",
459
+ name: "White star"
460
+ },
461
+ {
462
+ char: "♠",
463
+ name: "Spade"
464
+ },
465
+ {
466
+ char: "♥",
467
+ name: "Heart"
468
+ },
469
+ {
470
+ char: "♦",
471
+ name: "Diamond"
472
+ },
473
+ {
474
+ char: "♣",
475
+ name: "Club"
476
+ },
477
+ {
478
+ char: "✓",
479
+ name: "Check mark"
480
+ },
481
+ {
482
+ char: "✗",
483
+ name: "Ballot X"
484
+ },
485
+ {
486
+ char: "✦",
487
+ name: "Four pointed star"
488
+ },
489
+ {
490
+ char: "◌",
491
+ name: "Dotted circle"
492
+ }
493
+ ]
494
+ }
495
+ ];
496
+ /** Every catalog symbol, flattened and tagged with its category. */
497
+ const ALL_SYMBOLS = SYMBOL_CATEGORIES.flatMap((category) => category.symbols.map((symbol) => ({
498
+ ...symbol,
499
+ category: category.name
500
+ })));
501
+ /**
502
+ * Symbols whose descriptive name contains `query` (case-insensitive), or whose
503
+ * character is exactly `query`. An empty/whitespace query returns `[]` so
504
+ * callers fall back to the active category.
505
+ */
506
+ function filterSymbols(query) {
507
+ const q = query.trim().toLowerCase();
508
+ if (!q) return [];
509
+ return ALL_SYMBOLS.filter((symbol) => symbol.name.toLowerCase().includes(q) || symbol.char === q);
510
+ }
511
+ //#endregion
512
+ export { ALL_SYMBOLS, SYMBOL_CATEGORIES, filterSymbols };
@@ -86,7 +86,7 @@ async function copyRuns(runs, options = {}) {
86
86
  try {
87
87
  return await writeToClipboard(runsToClipboardContent(runs, includeFormatting));
88
88
  } catch (error) {
89
- onError?.(error);
89
+ onError?.(error instanceof Error ? error : new Error(String(error)));
90
90
  return false;
91
91
  }
92
92
  }
@@ -98,7 +98,7 @@ async function copyParagraphs(paragraphs, options = {}) {
98
98
  try {
99
99
  return await writeToClipboard(paragraphsToClipboardContent(paragraphs, includeFormatting));
100
100
  } catch (error) {
101
- onError?.(error);
101
+ onError?.(error instanceof Error ? error : new Error(String(error)));
102
102
  return false;
103
103
  }
104
104
  }
@@ -170,7 +170,7 @@ async function readFromClipboard(options = {}) {
170
170
  try {
171
171
  return await parseClipboardItems(await navigator.clipboard.read(), cleanWordFormatting);
172
172
  } catch (error) {
173
- onError?.(error);
173
+ onError?.(error instanceof Error ? error : new Error(String(error)));
174
174
  return null;
175
175
  }
176
176
  }
@@ -17,6 +17,8 @@ let isLoadingAny = false;
17
17
  * this map is used for font availability checks and preloading.
18
18
  */
19
19
  const FONT_MAPPING = {
20
+ Aptos: "Source Sans 3",
21
+ "Aptos Display": "Source Sans 3",
20
22
  Calibri: "Carlito",
21
23
  Cambria: "Caladea",
22
24
  Arial: "Arimo",
@@ -38,6 +40,7 @@ const BUNDLED_FONTS = /* @__PURE__ */ new Set([
38
40
  "Arimo",
39
41
  "Tinos",
40
42
  "Cousine",
43
+ "Source Sans 3",
41
44
  "Calibri",
42
45
  "Cambria",
43
46
  "Arial",
@@ -44,6 +44,11 @@ const JP_MEASURED_LINE_HEIGHT = {
44
44
  ratio: 1.303,
45
45
  note: "Measured against real Word: 10.5pt Japanese body, non-grid section, renders at 13.68pt line pitch."
46
46
  };
47
+ const APTOS_MEASURED_LINE_HEIGHT = {
48
+ source: "measured",
49
+ ratio: 1.2207,
50
+ note: "Measured against real Word: 11pt Aptos body, non-grid section, renders at 13.43pt line pitch."
51
+ };
47
52
  /**
48
53
  * Mapping of common DOCX fonts to Google Fonts equivalents
49
54
  *
@@ -59,6 +64,30 @@ const JP_MEASURED_LINE_HEIGHT = {
59
64
  * ratios carried over unchanged, pending measurement.
60
65
  */
61
66
  const FONT_MAPPINGS = {
67
+ aptos: {
68
+ googleFont: "Source Sans 3",
69
+ category: "sans-serif",
70
+ fallbackStack: [
71
+ "Aptos",
72
+ "Source Sans 3",
73
+ "Arial",
74
+ "Helvetica",
75
+ "sans-serif"
76
+ ],
77
+ singleLineRatio: singleLineRatioOf(APTOS_MEASURED_LINE_HEIGHT)
78
+ },
79
+ "aptos display": {
80
+ googleFont: "Source Sans 3",
81
+ category: "sans-serif",
82
+ fallbackStack: [
83
+ "Aptos Display",
84
+ "Source Sans 3",
85
+ "Arial",
86
+ "Helvetica",
87
+ "sans-serif"
88
+ ],
89
+ singleLineRatio: singleLineRatioOf(APTOS_MEASURED_LINE_HEIGHT)
90
+ },
62
91
  calibri: {
63
92
  googleFont: "Carlito",
64
93
  category: "sans-serif",
@@ -128,6 +157,23 @@ const FONT_MAPPINGS = {
128
157
  unitsPerEm: 2048
129
158
  })
130
159
  },
160
+ "cg times": {
161
+ googleFont: "Tinos",
162
+ category: "serif",
163
+ fallbackStack: [
164
+ "Times New Roman",
165
+ "Tinos",
166
+ "Times",
167
+ "serif"
168
+ ],
169
+ singleLineRatio: singleLineRatioOf({
170
+ source: "hhea",
171
+ hheaAscent: 1825,
172
+ hheaDescent: -443,
173
+ hheaLineGap: 87,
174
+ unitsPerEm: 2048
175
+ })
176
+ },
131
177
  "courier new": {
132
178
  googleFont: "Cousine",
133
179
  category: "monospace",
@@ -196,6 +242,23 @@ const FONT_MAPPINGS = {
196
242
  unitsPerEm: 2048
197
243
  })
198
244
  },
245
+ montserrat: {
246
+ googleFont: "Montserrat",
247
+ category: "sans-serif",
248
+ fallbackStack: [
249
+ "Montserrat",
250
+ "Arial",
251
+ "Helvetica",
252
+ "sans-serif"
253
+ ],
254
+ singleLineRatio: singleLineRatioOf({
255
+ source: "hhea",
256
+ hheaAscent: 968,
257
+ hheaDescent: -251,
258
+ hheaLineGap: 0,
259
+ unitsPerEm: 1e3
260
+ })
261
+ },
199
262
  "trebuchet ms": {
200
263
  googleFont: "Fira Sans",
201
264
  category: "sans-serif",
@@ -742,7 +805,8 @@ function resolveFontFamily(docxFontName) {
742
805
  singleLineRatio: mapping.singleLineRatio
743
806
  };
744
807
  }
745
- const defaultFallback = DEFAULT_FALLBACKS[detectFontCategory(docxFontName)];
808
+ const category = detectFontCategory(docxFontName);
809
+ const defaultFallback = DEFAULT_FALLBACKS[category];
746
810
  return {
747
811
  googleFont: null,
748
812
  cssFallback: withArabicFallback(`${quoteFontName(docxFontName)}, ${defaultFallback}`),
@@ -0,0 +1,21 @@
1
+ //#region src/utils/zoom.d.ts
2
+ /**
3
+ * Canonical zoom limits shared by every folio adapter (React, Vue, ...).
4
+ *
5
+ * Adapters must source their zoom range from here rather than hard-coding their
6
+ * own, so the reachable zoom span stays identical across framework hosts.
7
+ * Historically React clamped 0.25-4x while Vue clamped 0.5-2x; this module is
8
+ * the single source of truth that keeps them from drifting again.
9
+ *
10
+ * Note: the discrete zoom-level menu each adapter shows in its toolbar dropdown
11
+ * is a separate, deliberately curated subset (50-200%); it is not derived from
12
+ * these limits.
13
+ */
14
+ /** Minimum reachable zoom level (25%). */
15
+ declare const ZOOM_MIN = 0.25;
16
+ /** Maximum reachable zoom level (400%). */
17
+ declare const ZOOM_MAX = 4;
18
+ /** Step applied per zoom-in / zoom-out action and per keyboard shortcut. */
19
+ declare const ZOOM_STEP = 0.1;
20
+ //#endregion
21
+ export { ZOOM_MAX, ZOOM_MIN, ZOOM_STEP };
@@ -0,0 +1,21 @@
1
+ //#region src/utils/zoom.ts
2
+ /**
3
+ * Canonical zoom limits shared by every folio adapter (React, Vue, ...).
4
+ *
5
+ * Adapters must source their zoom range from here rather than hard-coding their
6
+ * own, so the reachable zoom span stays identical across framework hosts.
7
+ * Historically React clamped 0.25-4x while Vue clamped 0.5-2x; this module is
8
+ * the single source of truth that keeps them from drifting again.
9
+ *
10
+ * Note: the discrete zoom-level menu each adapter shows in its toolbar dropdown
11
+ * is a separate, deliberately curated subset (50-200%); it is not derived from
12
+ * these limits.
13
+ */
14
+ /** Minimum reachable zoom level (25%). */
15
+ const ZOOM_MIN = .25;
16
+ /** Maximum reachable zoom level (400%). */
17
+ const ZOOM_MAX = 4;
18
+ /** Step applied per zoom-in / zoom-out action and per keyboard shortcut. */
19
+ const ZOOM_STEP = .1;
20
+ //#endregion
21
+ export { ZOOM_MAX, ZOOM_MIN, ZOOM_STEP };