@stll/folio-core 0.66.0 → 0.66.2

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 (86) hide show
  1. package/dist/ai-edits/apply.d.ts +13 -1
  2. package/dist/ai-edits/apply.js +533 -136
  3. package/dist/ai-edits/batch-claims.d.ts +26 -0
  4. package/dist/ai-edits/batch-claims.js +30 -5
  5. package/dist/ai-edits/headless.d.ts +6 -0
  6. package/dist/ai-edits/headless.js +25 -3
  7. package/dist/ai-edits/newListNumbering.d.ts +4 -1
  8. package/dist/ai-edits/newListNumbering.js +4 -2
  9. package/dist/ai-edits/types.d.ts +1 -1
  10. package/dist/document-operations.d.ts +13 -1
  11. package/dist/document-operations.js +11 -4
  12. package/dist/docx/listNumberingInstances.d.ts +6 -4
  13. package/dist/docx/listNumberingInstances.js +12 -11
  14. package/dist/docx/numberingIds.d.ts +10 -0
  15. package/dist/docx/numberingIds.js +5 -1
  16. package/dist/docx/paragraphParser.js +16 -3
  17. package/dist/docx/paragraphProperties.js +2 -1
  18. package/dist/docx/serializer/paragraphSerializer.js +86 -66
  19. package/dist/fonts/bundledFonts.d.ts +54 -0
  20. package/dist/fonts/bundledFonts.js +45 -0
  21. package/dist/fonts/fontsourceFaces.d.ts +9 -14
  22. package/dist/fonts/fontsourceFaces.js +10 -22
  23. package/dist/i18n/messages/ar.gen.js +1 -0
  24. package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
  25. package/dist/i18n/messages/catalogs.gen.js +17 -0
  26. package/dist/i18n/messages/cs.gen.js +1 -0
  27. package/dist/i18n/messages/de.gen.js +1 -0
  28. package/dist/i18n/messages/en.gen.js +1 -0
  29. package/dist/i18n/messages/es.gen.js +1 -0
  30. package/dist/i18n/messages/et.gen.js +1 -0
  31. package/dist/i18n/messages/fr.gen.js +1 -0
  32. package/dist/i18n/messages/he.gen.js +1 -0
  33. package/dist/i18n/messages/hi.gen.js +1 -0
  34. package/dist/i18n/messages/hu.gen.js +1 -0
  35. package/dist/i18n/messages/lt.gen.js +1 -0
  36. package/dist/i18n/messages/lv.gen.js +1 -0
  37. package/dist/i18n/messages/messages.gen.d.ts +1 -0
  38. package/dist/i18n/messages/pl.gen.js +1 -0
  39. package/dist/i18n/messages/pt-BR.gen.js +1 -0
  40. package/dist/i18n/messages/sk.gen.js +1 -0
  41. package/dist/i18n/messages/tr.gen.js +1 -0
  42. package/dist/i18n/messages/zh-CN.gen.js +1 -0
  43. package/dist/internal/wholeStoryRevisionResolution.d.ts +1 -1
  44. package/dist/internal/wholeStoryRevisionResolution.js +24 -9
  45. package/dist/layout-bridge/convert/runMarkFormatting.js +1 -0
  46. package/dist/markdown/renderRuns.js +68 -12
  47. package/dist/prosemirror/commands/comments.js +2 -0
  48. package/dist/prosemirror/commands/resolveParagraphProperties.js +15 -2
  49. package/dist/prosemirror/conversion/fromProseDoc.js +55 -18
  50. package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +23 -1
  51. package/dist/prosemirror/conversion/hyphenTextCarriers.js +46 -1
  52. package/dist/prosemirror/conversion/toProseDoc.js +15 -9
  53. package/dist/prosemirror/extensions/StarterKit.js +1 -1
  54. package/dist/prosemirror/extensions/features/pasteCleanup.js +6 -0
  55. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +2 -1
  56. package/dist/prosemirror/extensions/markRegistry.d.ts +3 -1
  57. package/dist/prosemirror/extensions/markRegistry.js +3 -0
  58. package/dist/prosemirror/extensions/marks/HyphenElementExtension.d.ts +6 -0
  59. package/dist/prosemirror/extensions/marks/HyphenElementExtension.js +54 -0
  60. package/dist/prosemirror/fieldRepresentation.js +2 -1
  61. package/dist/prosemirror/hyphenElementAttrs.d.ts +10 -0
  62. package/dist/prosemirror/hyphenElementAttrs.js +32 -0
  63. package/dist/prosemirror/keptRangeBoundaries.d.ts +2 -0
  64. package/dist/prosemirror/keptRangeBoundaries.js +1 -1
  65. package/dist/prosemirror/listNumbering.js +3 -2
  66. package/dist/prosemirror/paragraphIndentation.js +2 -1
  67. package/dist/prosemirror/paragraphPropertyCarry.d.ts +1 -14
  68. package/dist/prosemirror/paragraphPropertyCarry.js +4 -28
  69. package/dist/prosemirror/plugins/suggestionMode.js +19 -6
  70. package/dist/prosemirror/replacedAnnotations.d.ts +1 -0
  71. package/dist/prosemirror/replacedAnnotations.js +1 -0
  72. package/dist/prosemirror/sectionCarrier.d.ts +8 -0
  73. package/dist/prosemirror/sectionCarrier.js +29 -1
  74. package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +10 -0
  75. package/dist/prosemirror/styles/paragraphStyleCascade.js +12 -2
  76. package/dist/prosemirror/tableRunIn.d.ts +24 -9
  77. package/dist/prosemirror/tableRunIn.js +107 -21
  78. package/dist/prosemirror/textInput.js +3 -1
  79. package/dist/prosemirror/validation.js +6 -0
  80. package/dist/utils/createDocument.js +11 -8
  81. package/dist/utils/fontLoader.d.ts +1 -1
  82. package/dist/utils/fontLoader.js +3 -11
  83. package/dist/utils/formatToStyle.js +2 -2
  84. package/dist/utils/units.d.ts +5 -0
  85. package/dist/utils/units.js +6 -1
  86. package/package.json +6 -4
@@ -299,20 +299,20 @@ function hyperlinkAttributes(hyperlink) {
299
299
  if (hyperlink.docLocation) attrs.push(`w:docLocation="${escapeXmlAttribute(hyperlink.docLocation)}"`);
300
300
  return attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
301
301
  }
302
- /** One `w:hyperlink` child, written with the link's own disposition. */
303
- function serializeHyperlinkChild(child, disposition) {
302
+ /** One `w:hyperlink` child, written with the link's own spelling. */
303
+ function serializeHyperlinkChild(child, spelling) {
304
304
  switch (child.type) {
305
- case "run": return serializeInlineRun(child, disposition);
305
+ case "run": return serializeInlineRun(child, spelling);
306
306
  case "bookmarkStart": return serializeBookmarkMarker(child);
307
307
  case "bookmarkEnd": return serializeBookmarkMarker(child);
308
308
  case "commentRangeStart":
309
- case "commentRangeEnd": return serializeParagraphContent(child, disposition);
309
+ case "commentRangeEnd": return serializeParagraphContent(child, spelling);
310
310
  case "commentReference": return serializeCommentReferenceRun(child.id);
311
311
  case "moveFromRangeStart":
312
312
  case "moveFromRangeEnd":
313
313
  case "moveToRangeStart":
314
314
  case "moveToRangeEnd": return serializeMoveRangeMarker(child);
315
- case "inlineWrapper": return serializeParagraphContent(child, disposition);
315
+ case "inlineWrapper": return serializeParagraphContent(child, spelling);
316
316
  case "preservedInline": return child.xml;
317
317
  default: return child;
318
318
  }
@@ -320,8 +320,8 @@ function serializeHyperlinkChild(child, disposition) {
320
320
  /**
321
321
  * Serialize a hyperlink (w:hyperlink)
322
322
  */
323
- function serializeHyperlink(hyperlink, disposition = "kept") {
324
- const childrenXml = hyperlink.children.map((child) => serializeHyperlinkChild(child, disposition)).join("");
323
+ function serializeHyperlink(hyperlink, spelling = "text") {
324
+ const childrenXml = hyperlink.children.map((child) => serializeHyperlinkChild(child, spelling)).join("");
325
325
  return `<w:hyperlink${hyperlinkAttributes(hyperlink)}>${childrenXml}</w:hyperlink>`;
326
326
  }
327
327
  /** Serialize a simple field without changing its authored OOXML field form. */
@@ -356,16 +356,25 @@ function serializeComplexField(field) {
356
356
  }
357
357
  const UnrepresentableTrackedCaptureErrorBase = TaggedError("UnrepresentableTrackedCaptureError");
358
358
  var UnrepresentableTrackedCaptureError = class extends UnrepresentableTrackedCaptureErrorBase {};
359
+ /** Whether a capture is plain runs whose text a respelling can reach. */
360
+ const isPlainRunCapture = (xml) => /^<w:r[\s>]/u.test(xml) && !/<w:(?:drawing|pict|object)\b|<mc:AlternateContent\b/u.test(xml);
359
361
  /**
360
- * Preserved markup inside a removal. Markup captured from a removal already
361
- * spells its text as deleted text. Markup captured outside one and put under
362
- * a removal afterwards does not: plain runs are respelled here, as a deleted
363
- * run is. A folded list-number capture that cannot be respelled is refused,
364
- * rather than written as live text inside the removal.
362
+ * Preserved markup inside a revision, spelled the way the revision spells its
363
+ * typed runs. Markup captured inside a `w:del` already spells its text as
364
+ * deleted text; markup captured elsewhere and put under one afterwards does
365
+ * not, and markup captured from a move source that spelled its text as
366
+ * deleted text holds the reverse. Plain runs are respelled here, as a typed
367
+ * run is. A folded list-number capture that cannot be respelled into a
368
+ * deletion is refused, rather than written as live text inside it.
365
369
  */
366
- function serializeRemovedPreservedInline(item) {
370
+ function serializeTrackedPreservedInline(item, spelling) {
371
+ switch (spelling) {
372
+ case "text": return isPlainRunCapture(item.xml) ? rewriteRunTextAsText(item.xml) : item.xml;
373
+ case "deletedText": break;
374
+ default: return spelling;
375
+ }
367
376
  if (!/<w:(?:t|instrText)[\s>]/u.test(item.xml)) return item.xml;
368
- if (/^<w:r[\s>]/u.test(item.xml) && !/<w:(?:drawing|pict|object)\b|<mc:AlternateContent\b/u.test(item.xml)) return rewriteRunTextAsDeleted(item.xml);
377
+ if (isPlainRunCapture(item.xml)) return rewriteRunTextAsDeleted(item.xml);
369
378
  if (item.foldedListNumber) throw new UnrepresentableTrackedCaptureError({ message: "A folded list-number field holds markup that cannot be written as deleted content." });
370
379
  return item.xml;
371
380
  }
@@ -440,29 +449,29 @@ const trackedSimpleFieldContent = (field) => {
440
449
  * the properties block was re-synthesized from the modeled projection alone,
441
450
  * silently dropping every unmodeled feature (and `w:sdtEndPr`) on save.
442
451
  */
443
- function serializeInlineSdt(sdt, disposition = "kept") {
452
+ function serializeInlineSdt(sdt, spelling = "text") {
444
453
  const props = sdt.properties;
445
454
  const contentXml = sdt.content.map((item) => {
446
455
  switch (item.type) {
447
- case "run": return serializeInlineRun(item, disposition);
448
- case "hyperlink": return serializeHyperlink(item, disposition);
456
+ case "run": return serializeInlineRun(item, spelling);
457
+ case "hyperlink": return serializeHyperlink(item, spelling);
449
458
  case "simpleField": return serializeSimpleField(item);
450
459
  case "complexField": return serializeComplexField(item);
451
- case "inlineSdt": return serializeInlineSdt(item, disposition);
452
- case "inlineWrapper": return serializeParagraphContent(item, disposition);
460
+ case "inlineSdt": return serializeInlineSdt(item, spelling);
461
+ case "inlineWrapper": return serializeParagraphContent(item, spelling);
453
462
  case "bookmarkStart": return serializeBookmarkMarker(item);
454
463
  case "bookmarkEnd": return serializeBookmarkMarker(item);
455
464
  case "commentRangeStart":
456
- case "commentRangeEnd": return serializeParagraphContent(item, disposition);
465
+ case "commentRangeEnd": return serializeParagraphContent(item, spelling);
457
466
  case "commentReference": return serializeCommentReferenceRun(item.id);
458
467
  case "moveFromRangeStart":
459
468
  case "moveFromRangeEnd":
460
469
  case "moveToRangeStart":
461
470
  case "moveToRangeEnd": return serializeMoveRangeMarker(item);
462
- case "insertion": return serializeTrackedChange("ins", item);
463
- case "deletion": return serializeTrackedChange("del", item);
464
- case "moveFrom": return serializeTrackedChange("moveFrom", item);
465
- case "moveTo": return serializeTrackedChange("moveTo", item);
471
+ case "insertion":
472
+ case "deletion":
473
+ case "moveFrom":
474
+ case "moveTo": return serializeTrackedChange(item);
466
475
  case "mathEquation": return item.ommlXml || "";
467
476
  case "preservedInline": return item.xml;
468
477
  default: return item;
@@ -470,12 +479,35 @@ function serializeInlineSdt(sdt, disposition = "kept") {
470
479
  }).join("");
471
480
  return serializeSdtWrapper(props, contentXml);
472
481
  }
473
- /**
474
- * Serialize a tracked change wrapper (ins/del/moveFrom/moveTo)
475
- */
482
+ /** Respell a run's text and field code as deleted text and field code. */
476
483
  function rewriteRunTextAsDeleted(xml) {
477
484
  return xml.replace(/<w:t\b/gu, "<w:delText").replace(/<\/w:t>/gu, "</w:delText>").replace(/<w:instrText\b/gu, "<w:delInstrText").replace(/<\/w:instrText>/gu, "</w:delInstrText>");
478
485
  }
486
+ /** Respell a run's deleted text and field code as plain text and field code. */
487
+ function rewriteRunTextAsText(xml) {
488
+ return xml.replace(/<w:delText\b/gu, "<w:t").replace(/<\/w:delText>/gu, "</w:t>").replace(/<w:delInstrText\b/gu, "<w:instrText").replace(/<\/w:delInstrText>/gu, "</w:instrText>");
489
+ }
490
+ /** The element each tracked run change is written as. */
491
+ const TRACKED_CHANGE_ELEMENT = {
492
+ insertion: "ins",
493
+ deletion: "del",
494
+ moveFrom: "moveFrom",
495
+ moveTo: "moveTo"
496
+ };
497
+ /**
498
+ * The text spelling of the runs each revision holds.
499
+ *
500
+ * ISO/IEC 29500-1 §17.3.3.7 reserves `w:delText` for runs in a deleted region
501
+ * (`w:del`, §17.13.5.14), and `w:delInstrText` likewise. A move source
502
+ * (`w:moveFrom`, §17.13.5.22) is not a deletion: its content moved elsewhere,
503
+ * and the spec's own example spells its run text `w:t`.
504
+ */
505
+ const TRACKED_CHANGE_TEXT_SPELLING = {
506
+ ins: "text",
507
+ del: "deletedText",
508
+ moveFrom: "text",
509
+ moveTo: "text"
510
+ };
479
511
  function serializeDeletedRun(run) {
480
512
  const xml = serializeRun(run);
481
513
  if (!run.content.some((c) => c.type === "drawing" || c.type === "shape")) return rewriteRunTextAsDeleted(xml);
@@ -489,22 +521,12 @@ function serializeDeletedRun(run) {
489
521
  return rewriteRunTextAsDeleted(contentXml);
490
522
  }).join("");
491
523
  }
492
- function serializeInlineRun(run, disposition) {
493
- return disposition === "removed" ? serializeDeletedRun(run) : serializeRun(run);
494
- }
495
- function trackedChangeTag(change) {
496
- switch (change.type) {
497
- case "insertion": return "ins";
498
- case "deletion": return "del";
499
- case "moveFrom": return "moveFrom";
500
- case "moveTo": return "moveTo";
501
- }
524
+ function serializeInlineRun(run, spelling) {
525
+ return spelling === "deletedText" ? serializeDeletedRun(run) : serializeRun(run);
502
526
  }
503
- function serializeTrackedChange(tag, change) {
504
- return emitTrackedInlineSegments(trackedChangeSegments({
505
- tag,
506
- change
507
- }));
527
+ /** Serialize a tracked change wrapper (ins/del/moveFrom/moveTo). */
528
+ function serializeTrackedChange(change) {
529
+ return emitTrackedInlineSegments(trackedChangeSegments(change));
508
530
  }
509
531
  const emitTrackedInlineSegments = (segments) => segments.map((segment) => {
510
532
  switch (segment.type) {
@@ -546,9 +568,10 @@ const wrapTrackedInlineSegments = (segments, wrap) => {
546
568
  flush();
547
569
  return result;
548
570
  };
549
- const trackedChangeSegments = ({ tag, change }) => {
550
- const disposition = tag === "del" || tag === "moveFrom" ? "removed" : "kept";
551
- const segments = walkTrackedInlineContent(change.content, disposition);
571
+ const trackedChangeSegments = (change) => {
572
+ const tag = TRACKED_CHANGE_ELEMENT[change.type];
573
+ const spelling = TRACKED_CHANGE_TEXT_SPELLING[tag];
574
+ const segments = walkTrackedInlineContent(change.content, spelling);
552
575
  if (change.resolutionJoins !== void 0 && segments.some((segment) => segment.type === "hyperlink")) throw new ReviewResolutionProvenanceError({
553
576
  attribute: "resolutionJoins",
554
577
  reason: "unrepresentable",
@@ -560,11 +583,11 @@ const trackedChangeSegments = ({ tag, change }) => {
560
583
  const UnrepresentableNestedHyperlinkErrorBase = TaggedError("UnrepresentableNestedHyperlinkError");
561
584
  var UnrepresentableNestedHyperlinkError = class extends UnrepresentableNestedHyperlinkErrorBase {};
562
585
  /** One exhaustive recursive owner for all containers inside a tracked revision. */
563
- const walkTrackedInlineContent = (content, disposition) => {
586
+ const walkTrackedInlineContent = (content, spelling) => {
564
587
  const segments = [];
565
588
  for (const item of content) switch (item.type) {
566
589
  case "hyperlink": {
567
- const children = walkTrackedInlineContent(item.children, disposition);
590
+ const children = walkTrackedInlineContent(item.children, spelling);
568
591
  if (children.some((child) => child.type === "hyperlink")) throw new UnrepresentableNestedHyperlinkError({ message: "A tracked hyperlink cannot contain another hyperlink." });
569
592
  segments.push({
570
593
  type: "hyperlink",
@@ -574,31 +597,28 @@ const walkTrackedInlineContent = (content, disposition) => {
574
597
  break;
575
598
  }
576
599
  case "simpleField":
577
- segments.push(...walkTrackedInlineContent(trackedSimpleFieldContent(item), disposition));
600
+ segments.push(...walkTrackedInlineContent(trackedSimpleFieldContent(item), spelling));
578
601
  break;
579
602
  case "insertion":
580
603
  case "deletion":
581
604
  case "moveFrom":
582
605
  case "moveTo":
583
- segments.push(...trackedChangeSegments({
584
- tag: trackedChangeTag(item),
585
- change: item
586
- }));
606
+ segments.push(...trackedChangeSegments(item));
587
607
  break;
588
608
  case "inlineWrapper":
589
- segments.push(...wrapTrackedInlineSegments(walkTrackedInlineContent(item.content, disposition), (xml) => serializeInlineWrapperMarkup(item, xml)));
609
+ segments.push(...wrapTrackedInlineSegments(walkTrackedInlineContent(item.content, spelling), (xml) => serializeInlineWrapperMarkup(item, xml)));
590
610
  break;
591
611
  case "inlineSdt":
592
612
  segments.push({
593
613
  type: "plain",
594
- xml: serializeSdtWrapper(item.properties, emitTrackedInlineSegments(walkTrackedInlineContent(item.content, disposition)))
614
+ xml: serializeSdtWrapper(item.properties, emitTrackedInlineSegments(walkTrackedInlineContent(item.content, spelling)))
595
615
  });
596
616
  break;
597
617
  case "complexField": {
598
618
  const xml = serializeComplexField(item);
599
619
  segments.push({
600
620
  type: "plain",
601
- xml: disposition === "removed" ? rewriteRunTextAsDeleted(xml) : xml
621
+ xml: spelling === "deletedText" ? rewriteRunTextAsDeleted(xml) : xml
602
622
  });
603
623
  break;
604
624
  }
@@ -615,7 +635,7 @@ const walkTrackedInlineContent = (content, disposition) => {
615
635
  }
616
636
  segments.push({
617
637
  type: "plain",
618
- xml: disposition === "removed" ? serializeRemovedPreservedInline(item) : item.xml
638
+ xml: serializeTrackedPreservedInline(item, spelling)
619
639
  });
620
640
  break;
621
641
  }
@@ -632,7 +652,7 @@ const walkTrackedInlineContent = (content, disposition) => {
632
652
  case "commentReference":
633
653
  segments.push({
634
654
  type: "plain",
635
- xml: serializeParagraphContent(item, disposition)
655
+ xml: serializeParagraphContent(item, spelling)
636
656
  });
637
657
  break;
638
658
  default: return item;
@@ -694,27 +714,27 @@ function serializeInlineWrapperMarkup(content, inner) {
694
714
  * `completeCommentReferences` fills it in for a model that arrived without
695
715
  * one; a guess made here from one paragraph cannot see the rest of the story.
696
716
  */
697
- function serializeParagraphContent(content, disposition = "kept") {
717
+ function serializeParagraphContent(content, spelling = "text") {
698
718
  switch (content.type) {
699
- case "run": return serializeInlineRun(content, disposition);
700
- case "hyperlink": return serializeHyperlink(content, disposition);
719
+ case "run": return serializeInlineRun(content, spelling);
720
+ case "hyperlink": return serializeHyperlink(content, spelling);
701
721
  case "bookmarkStart":
702
722
  case "bookmarkEnd": return serializeBookmarkMarker(content);
703
723
  case "simpleField": return serializeSimpleField(content);
704
724
  case "complexField": return serializeComplexField(content);
705
- case "inlineSdt": return serializeInlineSdt(content, disposition);
725
+ case "inlineSdt": return serializeInlineSdt(content, spelling);
706
726
  case "commentRangeStart": return `<w:commentRangeStart ${markupRangeAttributes(content).join(" ")}/>`;
707
727
  case "commentRangeEnd": return `<w:commentRangeEnd ${markupRangeAttributes(content).join(" ")}/>`;
708
728
  case "commentReference": return serializeCommentReferenceRun(content.id);
709
- case "insertion": return serializeTrackedChange("ins", content);
710
- case "deletion": return serializeTrackedChange("del", content);
711
- case "moveFrom": return serializeTrackedChange("moveFrom", content);
712
- case "moveTo": return serializeTrackedChange("moveTo", content);
729
+ case "insertion":
730
+ case "deletion":
731
+ case "moveFrom":
732
+ case "moveTo": return serializeTrackedChange(content);
713
733
  case "moveFromRangeStart":
714
734
  case "moveFromRangeEnd":
715
735
  case "moveToRangeStart":
716
736
  case "moveToRangeEnd": return serializeMoveRangeMarker(content);
717
- case "inlineWrapper": return serializeInlineWrapperMarkup(content, content.content.map((child) => serializeParagraphContent(child, disposition)).join(""));
737
+ case "inlineWrapper": return serializeInlineWrapperMarkup(content, content.content.map((child) => serializeParagraphContent(child, spelling)).join(""));
718
738
  case "mathEquation": return content.ommlXml || "";
719
739
  case "preservedInline": return content.xml;
720
740
  default: return "";
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The document fonts folio bundles: one table for every place that names them.
3
+ *
4
+ * `@stll/folio-fonts` ships the files, and its generator
5
+ * (`scripts/generate-folio-fonts.ts`) reads this table to decide which files
6
+ * to copy and which `@font-face` rules to write, so the published package and
7
+ * the resolver here cannot disagree about a family. The module imports nothing:
8
+ * the generator, the resolver and the editor's availability check all read it
9
+ * without pulling in the rest of the engine.
10
+ */
11
+ declare const PACKAGE_TABLE: {
12
+ readonly Arimo: "arimo";
13
+ readonly Caladea: "caladea";
14
+ readonly Carlito: "carlito";
15
+ readonly Cousine: "cousine";
16
+ readonly Lato: "lato";
17
+ readonly "Noto Sans Arabic": "noto-sans-arabic";
18
+ readonly "Source Sans 3": "source-sans-3";
19
+ readonly Tinos: "tinos";
20
+ };
21
+ export type FontsourcePackageTable = typeof PACKAGE_TABLE;
22
+ /** Each bundled family and the directory (an `@fontsource` package name) that ships it. */
23
+ export declare const FONTSOURCE_PACKAGES: FontsourcePackageTable;
24
+ export type BundledFamily = keyof FontsourcePackageTable;
25
+ /**
26
+ * What each bundled family stands in for, as prose for the package's notices.
27
+ * The resolver's own mapping lives in `utils/fontLoader.ts` and
28
+ * `utils/fontResolver.ts`.
29
+ */
30
+ export declare const BUNDLED_FAMILY_SUBSTITUTES: Readonly<Record<BundledFamily, string>>;
31
+ /**
32
+ * The subsets a headless measurer or the PDF writer reads, in resolution
33
+ * priority: a code point two subsets cover resolves to the earlier one.
34
+ * A browser is served every subset the family is cut into.
35
+ */
36
+ export declare const MEASURED_SUBSETS: readonly ["latin", "latin-ext", "arabic"];
37
+ export type MeasuredSubset = (typeof MEASURED_SUBSETS)[number];
38
+ /** Folio paints 400 and 700 only, as `DisplayFontFace` states. */
39
+ export declare const BUNDLED_WEIGHTS: readonly [400, 700];
40
+ export type BundledWeight = (typeof BUNDLED_WEIGHTS)[number];
41
+ /** The styles a family may be cut in; a family without italics ships `normal` only. */
42
+ export declare const BUNDLED_STYLES: readonly ["normal", "italic"];
43
+ export type BundledStyle = (typeof BUNDLED_STYLES)[number];
44
+ /** `files/<package>-<subset>-<weight>-<style>.<format>`: the path of one served binary. */
45
+ export declare const bundledFontFilePath: ({ packageName, subset, weight, style, format }: {
46
+ readonly packageName: string;
47
+ readonly subset: string;
48
+ readonly weight: number;
49
+ readonly style: BundledStyle;
50
+ readonly format: "woff" | "woff2";
51
+ }) => string;
52
+ /** Each family's directory carries the ranges its subsets were cut with. */
53
+ export declare const UNICODE_RANGE_FILE = "unicode.json";
54
+ export {};
@@ -0,0 +1,45 @@
1
+ /** Each bundled family and the directory (an `@fontsource` package name) that ships it. */
2
+ const FONTSOURCE_PACKAGES = {
3
+ Arimo: "arimo",
4
+ Caladea: "caladea",
5
+ Carlito: "carlito",
6
+ Cousine: "cousine",
7
+ Lato: "lato",
8
+ "Noto Sans Arabic": "noto-sans-arabic",
9
+ "Source Sans 3": "source-sans-3",
10
+ Tinos: "tinos"
11
+ };
12
+ /**
13
+ * What each bundled family stands in for, as prose for the package's notices.
14
+ * The resolver's own mapping lives in `utils/fontLoader.ts` and
15
+ * `utils/fontResolver.ts`.
16
+ */
17
+ const BUNDLED_FAMILY_SUBSTITUTES = {
18
+ Arimo: "Arial, and the generic sans-serif",
19
+ Caladea: "Cambria",
20
+ Carlito: "Calibri",
21
+ Cousine: "Courier New, and the generic monospace",
22
+ Lato: "Aptos and Aptos Display",
23
+ "Noto Sans Arabic": "Dubai, and Arabic script in every other family",
24
+ "Source Sans 3": "Segoe UI",
25
+ Tinos: "Times New Roman, and the generic serif"
26
+ };
27
+ /**
28
+ * The subsets a headless measurer or the PDF writer reads, in resolution
29
+ * priority: a code point two subsets cover resolves to the earlier one.
30
+ * A browser is served every subset the family is cut into.
31
+ */
32
+ const MEASURED_SUBSETS = [
33
+ "latin",
34
+ "latin-ext",
35
+ "arabic"
36
+ ];
37
+ /** Folio paints 400 and 700 only, as `DisplayFontFace` states. */
38
+ const BUNDLED_WEIGHTS = [400, 700];
39
+ /** The styles a family may be cut in; a family without italics ships `normal` only. */
40
+ const BUNDLED_STYLES = ["normal", "italic"];
41
+ /** `files/<package>-<subset>-<weight>-<style>.<format>`: the path of one served binary. */
42
+ const bundledFontFilePath = ({ packageName, subset, weight, style, format }) => `files/${packageName}-${subset}-${String(weight)}-${style}.${format}`;
43
+ /** Each family's directory carries the ranges its subsets were cut with. */
44
+ const UNICODE_RANGE_FILE = "unicode.json";
45
+ export { BUNDLED_FAMILY_SUBSTITUTES, BUNDLED_STYLES, BUNDLED_WEIGHTS, FONTSOURCE_PACKAGES, MEASURED_SUBSETS, UNICODE_RANGE_FILE, bundledFontFilePath };
@@ -1,20 +1,14 @@
1
1
  import { HeadlessFontSource } from "./headlessMeasure.js";
2
- /** Where `@fontsource` files come from: `null` when the package or file is absent. */
2
+ import { FONTSOURCE_PACKAGES } from "./bundledFonts.js";
3
+ /**
4
+ * Where the face files come from: `null` when the family or file is absent.
5
+ * Each family is a directory laid out like its `@fontsource` package;
6
+ * `@stll/folio-fonts/node` reads the copies that package ships.
7
+ */
3
8
  export type FontsourceFiles = {
4
- /** Bytes of `@fontsource/<packageName>/<relativePath>`. */
9
+ /** Bytes of `<relativePath>` in the family directory `<packageName>`. */
5
10
  readonly read: (packageName: string, relativePath: string) => Uint8Array | null;
6
11
  };
7
- /** Each bundled family and the `@fontsource` package that ships it. */
8
- export declare const FONTSOURCE_PACKAGES: {
9
- readonly Arimo: "arimo";
10
- readonly Caladea: "caladea";
11
- readonly Carlito: "carlito";
12
- readonly Cousine: "cousine";
13
- readonly Lato: "lato";
14
- readonly "Noto Sans Arabic": "noto-sans-arabic";
15
- readonly "Source Sans 3": "source-sans-3";
16
- readonly Tinos: "tinos";
17
- };
18
12
  /**
19
13
  * A CSS `<string>` token, quoted and escaped. A family name comes from an
20
14
  * authored document and is emitted into a `<style>` element, so the
@@ -41,4 +35,5 @@ export type FontsourceFaces = {
41
35
  readonly fontFaceCss: (options?: FontsourceFontFaceCssOptions) => string;
42
36
  };
43
37
  /** The `@fontsource` faces, read through `files` and cached per face. */
44
- export declare const createFontsourceFaces: (files: FontsourceFiles) => FontsourceFaces;
38
+ export declare const createFontsourceFaces: (files: FontsourceFiles) => FontsourceFaces;
39
+ export { FONTSOURCE_PACKAGES };
@@ -2,6 +2,7 @@ import { bytesToDataUrl } from "../utils/base64.js";
2
2
  import { FONT_MAPPING } from "../utils/fontLoader.js";
3
3
  import { parseFontFamilyList, resolveFontFamily } from "../utils/fontResolver.js";
4
4
  import { decodeText } from "../utils/textEncoding.js";
5
+ import { BUNDLED_WEIGHTS, FONTSOURCE_PACKAGES, MEASURED_SUBSETS, UNICODE_RANGE_FILE, bundledFontFilePath } from "./bundledFonts.js";
5
6
  // src/fonts/fontsourceFaces.ts
6
7
  /**
7
8
  * Faces from the `@fontsource` packages, for a caller that measures and paints
@@ -23,25 +24,8 @@ import { decodeText } from "../utils/textEncoding.js";
23
24
  * The subsets served, in resolution priority: a code point two subsets cover
24
25
  * resolves to the earlier one on both sides.
25
26
  */
26
- const SUBSET_PRIORITY = [
27
- "latin",
28
- "latin-ext",
29
- "arabic"
30
- ];
31
- /** Folio paints 400 and 700 only, as `DisplayFontFace` states. */
32
- const REGULAR_WEIGHT = 400;
33
- const BOLD_WEIGHT = 700;
34
- /** Each bundled family and the `@fontsource` package that ships it. */
35
- const FONTSOURCE_PACKAGES = {
36
- Arimo: "arimo",
37
- Caladea: "caladea",
38
- Carlito: "carlito",
39
- Cousine: "cousine",
40
- Lato: "lato",
41
- "Noto Sans Arabic": "noto-sans-arabic",
42
- "Source Sans 3": "source-sans-3",
43
- Tinos: "tinos"
44
- };
27
+ const SUBSET_PRIORITY = MEASURED_SUBSETS;
28
+ const [REGULAR_WEIGHT, BOLD_WEIGHT] = BUNDLED_WEIGHTS;
45
29
  /** A CSS stack ends in a generic, so a generic must resolve to a bundled family too. */
46
30
  const GENERIC_FAMILIES = {
47
31
  serif: "Tinos",
@@ -81,8 +65,6 @@ const resolveBundledFamily = (family) => {
81
65
  return null;
82
66
  };
83
67
  const weightOf = (bold) => bold ? BOLD_WEIGHT : REGULAR_WEIGHT;
84
- /** `@fontsource` ships the ranges it cut each subset with, beside the files. */
85
- const UNICODE_RANGE_FILE = "unicode.json";
86
68
  const RANGE_TOKEN_RE = /^U\+([0-9A-Fa-f]+)(?:-([0-9A-Fa-f]+))?$/u;
87
69
  const parseRangeToken = (token) => {
88
70
  const match = RANGE_TOKEN_RE.exec(token.trim());
@@ -172,7 +154,13 @@ const createFontsourceFaces = (files) => {
172
154
  const cached = faceCache.get(key);
173
155
  if (cached !== void 0) return cached;
174
156
  const binaries = SUBSET_PRIORITY.flatMap((subset) => {
175
- const bytes = files.read(packageName, `files/${packageName}-${subset}-${String(weight)}-${style}.woff`);
157
+ const bytes = files.read(packageName, bundledFontFilePath({
158
+ packageName,
159
+ subset,
160
+ weight,
161
+ style,
162
+ format: "woff"
163
+ }));
176
164
  return bytes === null ? [] : [{
177
165
  subset,
178
166
  bytes
@@ -335,6 +335,7 @@ const messages = { "folio": {
335
335
  "editSaveFailedTitle": "تعذّر حفظ ملف DOCX",
336
336
  "editSessionTakenOver": "فتح علامة تبويب أو نافذة أو جهاز آخر هذا المستند للتعديل، لذا تم تحرير هذه الجلسة. تم الحفاظ على التغييرات المحلية غير المحفوظة؛ أعد فتح المستند للمتابعة.",
337
337
  "editor": {
338
+ "accessibleName": "محرر المستندات",
338
339
  "editing": "تحرير",
339
340
  "editingDescription": "تحرير المستند مباشرةً",
340
341
  "outlineDepthAll": "كل المستويات",
@@ -336,6 +336,7 @@ export declare const CATALOGS: {
336
336
  readonly editSaveFailedTitle: "Could not save DOCX";
337
337
  readonly editSessionTakenOver: "Another tab, window, or device opened this document for editing, so this session was released. Unsaved local changes are preserved — reopen the doc to continue.";
338
338
  readonly editor: {
339
+ readonly accessibleName: "Document editor";
339
340
  readonly editing: "Editing";
340
341
  readonly editingDescription: "Edit the document directly";
341
342
  readonly outlineDepthAll: "All levels";
@@ -996,6 +997,7 @@ export declare const CATALOGS: {
996
997
  readonly editSaveFailedTitle: "DOCX-Datei konnte nicht gespeichert werden";
997
998
  readonly editSessionTakenOver: "Diese Bearbeitungssitzung wurde an anderer Stelle übernommen.";
998
999
  readonly editor: {
1000
+ readonly accessibleName: "Dokumenteditor";
999
1001
  readonly editing: "Bearbeiten";
1000
1002
  readonly editingDescription: "Dokument direkt bearbeiten";
1001
1003
  readonly outlineDepthAll: "Alle Ebenen";
@@ -1656,6 +1658,7 @@ export declare const CATALOGS: {
1656
1658
  readonly editSaveFailedTitle: "Impossible d’enregistrer le DOCX";
1657
1659
  readonly editSessionTakenOver: "Cette session de modification a été reprise ailleurs.";
1658
1660
  readonly editor: {
1661
+ readonly accessibleName: "Éditeur de documents";
1659
1662
  readonly editing: "Modification";
1660
1663
  readonly editingDescription: "Modifier directement le document";
1661
1664
  readonly outlineDepthAll: "Tous les niveaux";
@@ -2316,6 +2319,7 @@ export declare const CATALOGS: {
2316
2319
  readonly editSaveFailedTitle: "No se pudo guardar el DOCX";
2317
2320
  readonly editSessionTakenOver: "Esta sesión de edición se tomó en otro lugar.";
2318
2321
  readonly editor: {
2322
+ readonly accessibleName: "Editor de documentos";
2319
2323
  readonly editing: "Edición";
2320
2324
  readonly editingDescription: "Editar el documento directamente";
2321
2325
  readonly outlineDepthAll: "Todos los niveles";
@@ -2976,6 +2980,7 @@ export declare const CATALOGS: {
2976
2980
  readonly editSaveFailedTitle: "DOCX se nepodařilo uložit";
2977
2981
  readonly editSessionTakenOver: "Tento dokument byl otevřen k úpravám v jiné kartě, okně nebo zařízení, takže byla tato relace ukončena. Neuložené místní změny zůstávají zachovány — otevřete dokument znovu a pokračujte.";
2978
2982
  readonly editor: {
2983
+ readonly accessibleName: "Editor dokumentů";
2979
2984
  readonly editing: "Úpravy";
2980
2985
  readonly editingDescription: "Upravovat dokument přímo";
2981
2986
  readonly outlineDepthAll: "Vše";
@@ -3636,6 +3641,7 @@ export declare const CATALOGS: {
3636
3641
  readonly editSaveFailedTitle: "تعذّر حفظ ملف DOCX";
3637
3642
  readonly editSessionTakenOver: "فتح علامة تبويب أو نافذة أو جهاز آخر هذا المستند للتعديل، لذا تم تحرير هذه الجلسة. تم الحفاظ على التغييرات المحلية غير المحفوظة؛ أعد فتح المستند للمتابعة.";
3638
3643
  readonly editor: {
3644
+ readonly accessibleName: "محرر المستندات";
3639
3645
  readonly editing: "تحرير";
3640
3646
  readonly editingDescription: "تحرير المستند مباشرةً";
3641
3647
  readonly outlineDepthAll: "كل المستويات";
@@ -4296,6 +4302,7 @@ export declare const CATALOGS: {
4296
4302
  readonly editSaveFailedTitle: "DOCX-i ei saanud salvestada";
4297
4303
  readonly editSessionTakenOver: "See muutmisseanss võeti mujal üle.";
4298
4304
  readonly editor: {
4305
+ readonly accessibleName: "Dokumendiredaktor";
4299
4306
  readonly editing: "Redigeerimine";
4300
4307
  readonly editingDescription: "Redigeerige dokumenti otse";
4301
4308
  readonly outlineDepthAll: "Kõik tasemed";
@@ -4956,6 +4963,7 @@ export declare const CATALOGS: {
4956
4963
  readonly editSaveFailedTitle: "לא ניתן לשמור את ה-DOCX";
4957
4964
  readonly editSessionTakenOver: "כרטיסייה, חלון או מכשיר אחר פתחו מסמך זה לעריכה, ולכן הפעלה זו שוחררה. שינויים מקומיים שלא נשמרו נשמרו — פתח מחדש את המסמך כדי להמשיך.";
4958
4965
  readonly editor: {
4966
+ readonly accessibleName: "עורך מסמכים";
4959
4967
  readonly editing: "עריכה";
4960
4968
  readonly editingDescription: "ערוך את המסמך ישירות";
4961
4969
  readonly outlineDepthAll: "כל הרמות";
@@ -5616,6 +5624,7 @@ export declare const CATALOGS: {
5616
5624
  readonly editSaveFailedTitle: "DOCX सहेजा नहीं जा सका";
5617
5625
  readonly editSessionTakenOver: "किसी अन्य टैब, विंडो या डिवाइस ने इस दस्तावेज़ को संपादन के लिए खोला, इसलिए यह सत्र बंद कर दिया गया। सहेजे नहीं गए स्थानीय परिवर्तन सुरक्षित हैं — जारी रखने के लिए दस्तावेज़ फिर से खोलें।";
5618
5626
  readonly editor: {
5627
+ readonly accessibleName: "दस्तावेज़ संपादक";
5619
5628
  readonly editing: "संपादन";
5620
5629
  readonly editingDescription: "दस्तावेज़ को सीधे संपादित करें";
5621
5630
  readonly outlineDepthAll: "सभी स्तर";
@@ -6276,6 +6285,7 @@ export declare const CATALOGS: {
6276
6285
  readonly editSaveFailedTitle: "A DOCX nem menthető";
6277
6286
  readonly editSessionTakenOver: "Ezt a szerkesztési munkamenetet máshol vették át.";
6278
6287
  readonly editor: {
6288
+ readonly accessibleName: "Dokumentumszerkesztő";
6279
6289
  readonly editing: "Szerkesztés";
6280
6290
  readonly editingDescription: "A dokumentum közvetlen szerkesztése";
6281
6291
  readonly outlineDepthAll: "Minden szint";
@@ -6936,6 +6946,7 @@ export declare const CATALOGS: {
6936
6946
  readonly editSaveFailedTitle: "Nepavyko išsaugoti DOCX";
6937
6947
  readonly editSessionTakenOver: "Ši redagavimo sesija buvo perimta kitur.";
6938
6948
  readonly editor: {
6949
+ readonly accessibleName: "Dokumentų redaktorius";
6939
6950
  readonly editing: "Redagavimas";
6940
6951
  readonly editingDescription: "Redaguokite dokumentą tiesiogiai";
6941
6952
  readonly outlineDepthAll: "Visi lygiai";
@@ -7596,6 +7607,7 @@ export declare const CATALOGS: {
7596
7607
  readonly editSaveFailedTitle: "Neizdevās saglabāt DOCX";
7597
7608
  readonly editSessionTakenOver: "Šo rediģēšanas sesiju pārņēma citur.";
7598
7609
  readonly editor: {
7610
+ readonly accessibleName: "Dokumentu redaktors";
7599
7611
  readonly editing: "Rediģēšana";
7600
7612
  readonly editingDescription: "Rediģējiet dokumentu tieši";
7601
7613
  readonly outlineDepthAll: "Visi līmeņi";
@@ -8256,6 +8268,7 @@ export declare const CATALOGS: {
8256
8268
  readonly editSaveFailedTitle: "Nie udało się zapisać pliku DOCX";
8257
8269
  readonly editSessionTakenOver: "Ta sesja edycji została przejęta gdzie indziej.";
8258
8270
  readonly editor: {
8271
+ readonly accessibleName: "Edytor dokumentów";
8259
8272
  readonly editing: "Edytowanie";
8260
8273
  readonly editingDescription: "Edytuj dokument bezpośrednio";
8261
8274
  readonly outlineDepthAll: "Wszystkie poziomy";
@@ -8916,6 +8929,7 @@ export declare const CATALOGS: {
8916
8929
  readonly editSaveFailedTitle: "Não foi possível salvar DOCX";
8917
8930
  readonly editSessionTakenOver: "Esta sessão de edição foi assumida em outro lugar.";
8918
8931
  readonly editor: {
8932
+ readonly accessibleName: "Editor de documentos";
8919
8933
  readonly editing: "Editando";
8920
8934
  readonly editingDescription: "Edite o documento diretamente";
8921
8935
  readonly outlineDepthAll: "Todos os níveis";
@@ -9576,6 +9590,7 @@ export declare const CATALOGS: {
9576
9590
  readonly editSaveFailedTitle: "DOCX sa nepodarilo uložiť";
9577
9591
  readonly editSessionTakenOver: "Túto reláciu úprav prevzalo iné okno.";
9578
9592
  readonly editor: {
9593
+ readonly accessibleName: "Editor dokumentov";
9579
9594
  readonly editing: "Úpravy";
9580
9595
  readonly editingDescription: "Upravujte dokument priamo";
9581
9596
  readonly outlineDepthAll: "Všetky úrovne";
@@ -10236,6 +10251,7 @@ export declare const CATALOGS: {
10236
10251
  readonly editSaveFailedTitle: "DOCX kaydedilemedi";
10237
10252
  readonly editSessionTakenOver: "Başka bir sekme, pencere veya cihaz bu belgeyi düzenlemek için açtığından bu oturum sonlandırıldı. Kaydedilmemiş yerel değişiklikler korunur; devam etmek için belgeyi yeniden açın.";
10238
10253
  readonly editor: {
10254
+ readonly accessibleName: "Belge düzenleyici";
10239
10255
  readonly editing: "Düzenleme";
10240
10256
  readonly editingDescription: "Belgeyi doğrudan düzenleyin";
10241
10257
  readonly outlineDepthAll: "Tüm düzeyler";
@@ -10896,6 +10912,7 @@ export declare const CATALOGS: {
10896
10912
  readonly editSaveFailedTitle: "无法保存 DOCX";
10897
10913
  readonly editSessionTakenOver: "另一个标签页、窗口或设备已打开此文档进行编辑,因此本会话已释放。未保存的本地更改会保留,请重新打开文档以继续。";
10898
10914
  readonly editor: {
10915
+ readonly accessibleName: "文档编辑器";
10899
10916
  readonly editing: "编辑";
10900
10917
  readonly editingDescription: "直接编辑文档";
10901
10918
  readonly outlineDepthAll: "所有级别";