@stll/folio-core 0.28.1 → 0.30.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 (125) hide show
  1. package/dist/controller/folioEditor.d.ts +28 -1
  2. package/dist/controller/folioEditor.js +37 -26
  3. package/dist/controller/fontReadiness.js +28 -24
  4. package/dist/controller/hiddenEditorManager.d.ts +2 -7
  5. package/dist/controller/layoutPipeline.js +33 -3
  6. package/dist/controller/noteEditorManager.d.ts +3 -6
  7. package/dist/docx/metafileSvg.d.ts +12 -0
  8. package/dist/docx/metafileSvg.js +462 -0
  9. package/dist/docx/paragraphTextBoxEnrichment.js +55 -4
  10. package/dist/docx/parser.d.ts +2 -2
  11. package/dist/docx/parser.js +26 -0
  12. package/dist/docx/runParser.js +2 -1
  13. package/dist/docx/serializer/runSerializer.js +14 -2
  14. package/dist/docx/styleParser.js +2 -1
  15. package/dist/docx/textBoxParser.js +14 -0
  16. package/dist/docx/vmlImageParser.js +72 -152
  17. package/dist/docx/vmlPreview.d.ts +31 -0
  18. package/dist/docx/vmlPreview.js +535 -0
  19. package/dist/docx/wrapTypes.d.ts +2 -36
  20. package/dist/docx/wrapTypes.js +1 -39
  21. package/dist/fonts/fontAlternates.d.ts +8 -0
  22. package/dist/fonts/fontAlternates.js +16 -0
  23. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  24. package/dist/layout-bridge/convert/footnoteLayout.js +34 -3
  25. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  26. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -0
  27. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
  28. package/dist/layout-bridge/convert/toFlowBlocks.js +136 -120
  29. package/dist/layout-bridge/dom/noteStoryDom.d.ts +1 -1
  30. package/dist/layout-bridge/engine/selectionRects.js +3 -1
  31. package/dist/layout-engine/index.js +65 -32
  32. package/dist/layout-engine/justifiedLineFit.d.ts +7 -0
  33. package/dist/layout-engine/justifiedLineFit.js +6 -0
  34. package/dist/layout-engine/keep-together.js +15 -10
  35. package/dist/layout-engine/measure/complexScriptFormatting.d.ts +6 -1
  36. package/dist/layout-engine/measure/complexScriptFormatting.js +11 -2
  37. package/dist/layout-engine/measure/floatingTablePosition.d.ts +16 -1
  38. package/dist/layout-engine/measure/floatingTablePosition.js +29 -6
  39. package/dist/layout-engine/measure/lineBreakProvider.js +67 -8
  40. package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
  41. package/dist/layout-engine/measure/listMarkerWidth.js +23 -10
  42. package/dist/layout-engine/measure/measureBlocks.d.ts +15 -0
  43. package/dist/layout-engine/measure/measureBlocks.js +197 -30
  44. package/dist/layout-engine/measure/measureContainer.js +20 -24
  45. package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
  46. package/dist/layout-engine/measure/measureHelpers.js +14 -8
  47. package/dist/layout-engine/measure/measureParagraph.js +111 -37
  48. package/dist/layout-engine/measure/measureTypes.d.ts +3 -0
  49. package/dist/layout-engine/measure/tabCalculator.d.ts +123 -0
  50. package/dist/layout-engine/measure/tabCalculator.js +144 -0
  51. package/dist/layout-engine/measure/tableCellFlow.d.ts +21 -1
  52. package/dist/layout-engine/measure/tableCellFlow.js +45 -8
  53. package/dist/layout-engine/measure/tableInlinePlacement.d.ts +10 -2
  54. package/dist/layout-engine/measure/tableInlinePlacement.js +17 -15
  55. package/dist/layout-engine/paginator.d.ts +26 -2
  56. package/dist/layout-engine/paginator.js +76 -14
  57. package/dist/layout-engine/paragraphSpacing.d.ts +3 -1
  58. package/dist/layout-engine/paragraphSpacing.js +4 -3
  59. package/dist/layout-engine/renderedBreakReconciliation.d.ts +14 -3
  60. package/dist/layout-engine/renderedBreakReconciliation.js +45 -14
  61. package/dist/layout-engine/section-breaks.d.ts +3 -1
  62. package/dist/layout-engine/section-breaks.js +6 -2
  63. package/dist/layout-engine/types.d.ts +18 -1
  64. package/dist/layout-engine/types.js +1 -1
  65. package/dist/layout-painter/imageLayout.d.ts +1 -1
  66. package/dist/layout-painter/renderPage.js +6 -1
  67. package/dist/layout-painter/renderParagraph.js +169 -82
  68. package/dist/layout-painter/renderTable.d.ts +1 -1
  69. package/dist/layout-painter/renderTable.js +18 -7
  70. package/dist/layout-painter/renderTextBox.d.ts +1 -1
  71. package/dist/layout-painter/renderTextBox.js +6 -1
  72. package/dist/markdown/renderParagraph.js +7 -2
  73. package/dist/model.d.ts +3 -3
  74. package/dist/model.js +2 -2
  75. package/dist/paged-layout/sectionBlockWidths.d.ts +14 -0
  76. package/dist/paged-layout/sectionBlockWidths.js +103 -14
  77. package/dist/prosemirror/attrs/index.js +14 -2
  78. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +8 -0
  79. package/dist/prosemirror/bookmarkBoundaryAttrs.js +66 -0
  80. package/dist/prosemirror/conversion/fromProseDoc.js +176 -54
  81. package/dist/prosemirror/conversion/toProseDoc.js +179 -64
  82. package/dist/prosemirror/extensions/StarterKit.js +11 -3
  83. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +8 -4
  84. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
  85. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +9 -5
  86. package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +10 -23
  87. package/dist/prosemirror/extensions/features/pasteCleanup.js +77 -22
  88. package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +9 -5
  89. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +9 -0
  90. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +67 -0
  91. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +10 -4
  92. package/dist/prosemirror/extensions/nodes/FieldExtension.js +77 -59
  93. package/dist/prosemirror/extensions/nodes/TableExtension.js +2 -0
  94. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +4 -1
  95. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +4 -3
  96. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +6 -2
  97. package/dist/prosemirror/listMarker.d.ts +58 -0
  98. package/dist/prosemirror/listMarker.js +185 -0
  99. package/dist/prosemirror/numberedRefFields.d.ts +24 -0
  100. package/dist/prosemirror/numberedRefFields.js +276 -0
  101. package/dist/prosemirror/paraText.js +56 -17
  102. package/dist/prosemirror/plugins/anonymizationDecorations.js +1 -1
  103. package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -1
  104. package/dist/prosemirror/plugins/pmTextScan.js +28 -7
  105. package/dist/prosemirror/plugins/templateDirectives.js +2 -2
  106. package/dist/prosemirror/schema/index.d.ts +2 -2
  107. package/dist/prosemirror/schema/nodes.d.ts +17 -1
  108. package/dist/prosemirror/utils/tabCalculator.d.ts +2 -123
  109. package/dist/prosemirror/utils/tabCalculator.js +1 -140
  110. package/dist/prosemirror/validation.js +93 -0
  111. package/dist/render-dom/RemoteSelectionOverlay.d.ts +4 -4
  112. package/dist/types/documentEnumValues.d.ts +4 -1
  113. package/dist/types/documentEnumValues.js +12 -1
  114. package/dist/types/editor-story.d.ts +8 -0
  115. package/dist/types/editor-story.js +0 -0
  116. package/dist/types/remote-selection.d.ts +11 -0
  117. package/dist/types/remote-selection.js +0 -0
  118. package/dist/types/wrap.d.ts +36 -0
  119. package/dist/types/wrap.js +40 -0
  120. package/dist/utils/fontResolver.d.ts +1 -1
  121. package/dist/utils/fontResolver.js +42 -2
  122. package/dist/utils/formatToStyle.js +4 -2
  123. package/dist/utils/horizontalScale.d.ts +28 -0
  124. package/dist/utils/horizontalScale.js +42 -0
  125. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import { measureParagraph } from "../../layout-engine/measure/measureParagraph.js";
2
2
  import { layoutTextBoxContent } from "../../layout-engine/measure/textBoxParagraphLayout.js";
3
- import { DEFAULT_TEXTBOX_MARGINS, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT } from "../../layout-engine/types.js";
3
+ import { DEFAULT_TEXTBOX_MARGINS, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, isFloatingImageRun } from "../../layout-engine/types.js";
4
4
  import { footnoteToProseDoc } from "../../prosemirror/conversion/toProseDoc.js";
5
5
  import { toFlowBlocks } from "./toFlowBlocks.js";
6
6
  //#region src/layout-bridge/convert/footnoteLayout.ts
@@ -196,6 +196,7 @@ function convertFootnoteToContent(footnote, displayNumber, contentWidth, options
196
196
  const pmDoc = footnoteToProseDoc(footnote.content, proseOptions);
197
197
  const flowOptions = {};
198
198
  if (options.theme !== void 0) flowOptions.theme = options.theme;
199
+ if (options.fontAlternates !== void 0) flowOptions.fontAlternates = options.fontAlternates;
199
200
  if (options.defaultTabStopTwips !== void 0) flowOptions.defaultTabStopTwips = options.defaultTabStopTwips;
200
201
  if (options.lineBreakRules) flowOptions.lineBreakRules = options.lineBreakRules;
201
202
  if (options.justificationCompatibility) flowOptions.justificationCompatibility = options.justificationCompatibility;
@@ -363,18 +364,48 @@ function applyFootnotePresentation(blocks, displayNumber) {
363
364
  return output;
364
365
  }
365
366
  function createFootnoteNumberRun(displayNumber, paragraph) {
366
- const firstTextRun = paragraph.runs.find((run) => run.kind === "text");
367
367
  const firstFormattedRun = paragraph.runs.find((run) => run.kind === "text" || run.kind === "tab" || run.kind === "field");
368
368
  const numberRun = {
369
369
  kind: "text",
370
- text: firstTextRun?.text.match(/^\s/u) ? `${displayNumber}` : `${displayNumber} `,
370
+ text: `${displayNumber}${resolveFootnoteNumberSuffix(paragraph.runs) === FOOTNOTE_NUMBER_SUFFIX.SEPARATED ? " " : ""}`,
371
371
  fontSize: firstFormattedRun?.fontSize ?? paragraph.attrs?.defaultFontSize ?? FOOTNOTE_FONT_SIZE,
372
372
  superscript: true
373
373
  };
374
374
  const fontFamily = firstFormattedRun?.fontFamily ?? paragraph.attrs?.defaultFontFamily;
375
375
  if (fontFamily) numberRun.fontFamily = fontFamily;
376
+ const alternateFontFamily = firstFormattedRun?.fontFamily !== void 0 ? firstFormattedRun.alternateFontFamily : paragraph.attrs?.defaultAlternateFontFamily;
377
+ if (alternateFontFamily) numberRun.alternateFontFamily = alternateFontFamily;
376
378
  return numberRun;
377
379
  }
380
+ const FOOTNOTE_NUMBER_SUFFIX = {
381
+ ATTACHED: "none",
382
+ SEPARATED: "space"
383
+ };
384
+ const ATTACHED_FOOTNOTE_SUFFIX_PATTERN = /^(?:[\p{Pe}\p{Pf}\p{Sentence_Terminal}]|[,;:\u060c\u061b\u3001\uff0c\uff1a\uff1b])/u;
385
+ const LEADING_WHITESPACE_PATTERN = /^\s/u;
386
+ function resolveTextFootnoteNumberSuffix(text) {
387
+ if (LEADING_WHITESPACE_PATTERN.test(text) || ATTACHED_FOOTNOTE_SUFFIX_PATTERN.test(text)) return FOOTNOTE_NUMBER_SUFFIX.ATTACHED;
388
+ return FOOTNOTE_NUMBER_SUFFIX.SEPARATED;
389
+ }
390
+ function resolveRunFootnoteNumberSuffix(run) {
391
+ switch (run.kind) {
392
+ case "text": return run.text.length === 0 ? void 0 : resolveTextFootnoteNumberSuffix(run.text);
393
+ case "tab":
394
+ case "lineBreak": return FOOTNOTE_NUMBER_SUFFIX.ATTACHED;
395
+ case "field": return resolveTextFootnoteNumberSuffix(run.fallback || "1");
396
+ case "image": return isFloatingImageRun(run) ? void 0 : FOOTNOTE_NUMBER_SUFFIX.SEPARATED;
397
+ case "math": return FOOTNOTE_NUMBER_SUFFIX.SEPARATED;
398
+ case "renderedPageBreak": return;
399
+ default: return run;
400
+ }
401
+ }
402
+ function resolveFootnoteNumberSuffix(runs) {
403
+ for (const run of runs) {
404
+ const suffix = resolveRunFootnoteNumberSuffix(run);
405
+ if (suffix !== void 0) return suffix;
406
+ }
407
+ return FOOTNOTE_NUMBER_SUFFIX.SEPARATED;
408
+ }
378
409
  function applyFootnoteBlockPresentation(block) {
379
410
  if (block.kind === "paragraph") return applyFootnoteParagraphPresentation(block);
380
411
  if (block.kind === "table") return applyFootnoteTablePresentation(block);
@@ -41,6 +41,7 @@ declare function calculateHeaderFooterBodyTopClearance(blocks: FlowBlock[], flow
41
41
  type ConvertHeaderFooterOptions = {
42
42
  styles?: document_d_exports.StyleDefinitions | null;
43
43
  theme?: document_d_exports.Theme | null;
44
+ fontAlternates?: ToFlowBlocksOptions["fontAlternates"];
44
45
  measureBlocks: MeasureBlocksFn;
45
46
  /** Document-wide `w:defaultTabStop` in twips — forwarded to toFlowBlocks. */
46
47
  defaultTabStopTwips?: number;
@@ -333,6 +333,7 @@ function convertHeaderFooterToContent(headerFooter, contentWidth, metrics, optio
333
333
  const pmDoc = headerFooterToProseDoc(headerFooter.content, proseDocOptions);
334
334
  const flowOptions = {};
335
335
  if (options.theme !== void 0) flowOptions.theme = options.theme;
336
+ if (options.fontAlternates !== void 0) flowOptions.fontAlternates = options.fontAlternates;
336
337
  if (options.defaultTabStopTwips !== void 0) flowOptions.defaultTabStopTwips = options.defaultTabStopTwips;
337
338
  if (options.lineBreakRules) flowOptions.lineBreakRules = options.lineBreakRules;
338
339
  if (options.justificationCompatibility) flowOptions.justificationCompatibility = options.justificationCompatibility;
@@ -354,6 +355,7 @@ function convertHeaderFooterPmDocToContent(pmDoc, contentWidth, metrics, options
354
355
  if (!pmDoc || pmDoc.content.size === 0) return;
355
356
  const flowOptions = {};
356
357
  if (options.theme !== void 0) flowOptions.theme = options.theme;
358
+ if (options.fontAlternates !== void 0) flowOptions.fontAlternates = options.fontAlternates;
357
359
  if (options.defaultTabStopTwips !== void 0) flowOptions.defaultTabStopTwips = options.defaultTabStopTwips;
358
360
  if (options.lineBreakRules) flowOptions.lineBreakRules = options.lineBreakRules;
359
361
  if (options.justificationCompatibility) flowOptions.justificationCompatibility = options.justificationCompatibility;
@@ -495,8 +497,11 @@ function serializeRunFmt(run) {
495
497
  "highlightColor",
496
498
  "fontSize",
497
499
  "fontFamily",
500
+ "alternateFontFamily",
498
501
  "eastAsiaFontFamily",
502
+ "eastAsiaAlternateFontFamily",
499
503
  "complexScriptFontFamily",
504
+ "complexScriptAlternateFontFamily",
500
505
  "complexScriptFontSize",
501
506
  "complexScriptBold",
502
507
  "complexScriptItalic",
@@ -1,5 +1,7 @@
1
1
  import { document_d_exports } from "../../types/document.js";
2
2
  import { BorderStyle, FlowBlock, ParagraphAttrs } from "../../layout-engine/types.js";
3
+ import { FontAlternates } from "../../fonts/fontAlternates.js";
4
+ import { formatCounter, resolveListTemplate } from "../../prosemirror/listMarker.js";
3
5
  import { Node } from "prosemirror-model";
4
6
  //#region src/layout-bridge/convert/toFlowBlocks.d.ts
5
7
  /**
@@ -12,6 +14,8 @@ type ToFlowBlocksOptions = {
12
14
  defaultSize?: number;
13
15
  /** Theme for resolving theme colors. */
14
16
  theme?: document_d_exports.Theme | null;
17
+ /** Document-scoped OOXML primary-font to `w:altName` lookup. */
18
+ fontAlternates?: FontAlternates;
15
19
  /** Page content height in pixels (pageHeight - marginTop - marginBottom). Images taller than this are scaled down to fit. */
16
20
  pageContentHeight?: number;
17
21
  /** Shared list counters for nested containers. */
@@ -59,8 +63,6 @@ type ToFlowBlocksOptions = {
59
63
  /** Line pitch for the final body section, whose properties live outside the PM body. */
60
64
  finalSectionDocumentGridLinePitchTwips?: number;
61
65
  };
62
- declare function formatCounter(value: number, format: document_d_exports.NumberFormat | undefined): string;
63
- declare function resolveListTemplate(template: string, counters: number[], levelFormats: document_d_exports.NumberFormat[] | undefined, forceDecimal?: boolean): string;
64
66
  /**
65
67
  * Reset the block ID counter (useful for testing).
66
68
  */
@@ -1,6 +1,6 @@
1
1
  import { convertBulletToUnicode } from "../../docx/bulletMarkers.js";
2
2
  import { resolveDocumentGridLinePitch } from "../../docx/documentGrid.js";
3
- import { formatOoxmlCounter } from "../../docx/ooxmlCounterFormatter.js";
3
+ import { getFontAlternate } from "../../fonts/fontAlternates.js";
4
4
  import { setHyperlinkInstanceIndex } from "../../layout-engine/measure/hyperlinkInstance.js";
5
5
  import { setParagraphFrame } from "../../layout-engine/paragraphFrame.js";
6
6
  import { setTextBoxGroupId } from "../../layout-engine/textBoxGroup.js";
@@ -9,12 +9,16 @@ import { getPageNumbering } from "../../paged-layout/sectionGeometry.js";
9
9
  import { expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs, expectRunShadingMarkAttrs, expectSymbolAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs } from "../../prosemirror/attrs/index.js";
10
10
  import { autospacingMatchesBase } from "../../prosemirror/autospacingBase.js";
11
11
  import { runShadingAttrsToShading } from "../../prosemirror/conversion/runShadingMark.js";
12
+ import { advanceListMarker, advanceVisibleListMarker, cloneListCounterState, formatCounter, resolveListTemplate } from "../../prosemirror/listMarker.js";
13
+ import { resolveNumberedRefFields } from "../../prosemirror/numberedRefFields.js";
12
14
  import { directionToBidi } from "../../prosemirror/paragraphDirection.js";
13
15
  import { cascadeStyleTextFormatting } from "../../prosemirror/styles/styleToggleCascade.js";
14
16
  import { assertValidProseMirrorDocument } from "../../prosemirror/validation.js";
17
+ import { normalizeShapeTextAnchor } from "../../types/documentEnumValues.js";
15
18
  import { resolveColor, resolveHighlightToCss } from "../../utils/colorResolver.js";
16
19
  import { resolveThemeFont } from "../../utils/fontResolver.js";
17
20
  import { resolveShadingFill } from "../../utils/formatToStyle.js";
21
+ import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
18
22
  import { decodeOoxmlSymbolCharacter } from "../../utils/ooxmlSymbol.js";
19
23
  import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
20
24
  import { AUTO_PARAGRAPH_SPACING_PX, halfPointsToPixels, halfPointsToPoints, pointsToPixels } from "../../utils/units.js";
@@ -68,79 +72,12 @@ let blockIdCounter = 0;
68
72
  function nextBlockId() {
69
73
  return `block-${++blockIdCounter}`;
70
74
  }
71
- function formatNumberedMarker(counters, level) {
72
- const parts = [];
73
- for (let i = 0; i <= level; i += 1) {
74
- const value = counters[i] ?? 0;
75
- if (!Number.isFinite(value) || value <= 0) break;
76
- parts.push(value);
77
- }
78
- if (parts.length === 0) return "1.";
79
- return `${parts.join(".")}.`;
80
- }
81
- function formatCounter(value, format) {
82
- return formatOoxmlCounter(value, format);
83
- }
84
- function resolveListTemplate(template, counters, levelFormats, forceDecimal = false) {
85
- return template.replace(/%(?<digit>\d)(?<punct>[.):\]])?/gu, (...args) => {
86
- const { digit, punct = "" } = args.at(-1);
87
- const index = Number.parseInt(digit, 10) - 1;
88
- if (index < 0) return "";
89
- const counter = counters[index];
90
- if (counter === void 0 || Number.isNaN(counter)) return "";
91
- const formatted = formatCounter(counter, forceDecimal ? "decimal" : levelFormats?.[index]);
92
- return formatted ? `${formatted}${punct}` : "";
93
- });
94
- }
95
- function getLastListCounters(listCounters) {
96
- let lastCounters;
97
- for (const counters of listCounters.values()) lastCounters = counters;
98
- return lastCounters;
99
- }
100
75
  function applyMarkerAllCaps(marker, allCaps) {
101
76
  if (marker === null || !allCaps) return marker;
102
77
  return marker.toLocaleUpperCase();
103
78
  }
104
- function computeListMarker(pmAttrs, listCounters, abstractCounters, seenNumIds) {
105
- const numId = pmAttrs.numPr?.numId;
106
- if (numId === void 0 || numId === 0) {
107
- if (pmAttrs.listMarker?.includes("%") && !pmAttrs.listIsBullet) {
108
- const counters = getLastListCounters(listCounters);
109
- if (counters) return resolveListTemplate(pmAttrs.listMarker, counters, pmAttrs.listLevelNumFmts, pmAttrs.listIsLegal);
110
- }
111
- return null;
112
- }
113
- if (pmAttrs.listIsBullet) return convertBulletToUnicode(pmAttrs.listMarker || "");
114
- const level = pmAttrs.numPr?.ilvl ?? 0;
115
- const counters = listCounters.get(numId) ?? Array.from({ length: 9 }, () => NaN);
116
- const abstractNumId = pmAttrs.listAbstractNumId;
117
- if (level > 0) {
118
- const latestAbstractCounters = abstractNumId === void 0 ? void 0 : abstractCounters.get(abstractNumId);
119
- if (counters.slice(0, level).every((counter) => !Number.isFinite(counter))) for (let i = 0; i < level; i += 1) {
120
- const latestCounter = latestAbstractCounters?.[i];
121
- counters[i] = latestCounter !== void 0 && Number.isFinite(latestCounter) ? latestCounter : pmAttrs.listLevelStarts?.[i] ?? 1;
122
- }
123
- }
124
- const seenKey = `${numId}:${level}`;
125
- if (!seenNumIds.has(seenKey)) {
126
- seenNumIds.add(seenKey);
127
- if (pmAttrs.listStartOverride != null) counters[level] = pmAttrs.listStartOverride - 1;
128
- }
129
- if (!Number.isFinite(counters[level])) counters[level] = (pmAttrs.listLevelStarts?.[level] ?? 1) - 1;
130
- counters[level] = (counters[level] ?? 0) + 1;
131
- for (let i = level + 1; i < counters.length; i += 1) counters[i] = NaN;
132
- const childAdvances = pmAttrs.listImplicitChildLevelAdvances ?? 0;
133
- if (childAdvances > 0 && level + 1 < counters.length) {
134
- const childCounter = counters[level + 1];
135
- counters[level + 1] = (childCounter === void 0 || !Number.isFinite(childCounter) ? 0 : childCounter) + childAdvances;
136
- }
137
- listCounters.set(numId, counters);
138
- if (abstractNumId !== void 0) abstractCounters.set(abstractNumId, [...counters]);
139
- const levelFormats = pmAttrs.listLevelNumFmts ?? (pmAttrs.listNumFmt ? [pmAttrs.listNumFmt] : void 0);
140
- if (pmAttrs.listMarker && pmAttrs.listMarker.includes("%")) return resolveListTemplate(pmAttrs.listMarker, counters, levelFormats, pmAttrs.listIsLegal);
141
- if (pmAttrs.listMarker) return pmAttrs.listMarker;
142
- if ((levelFormats?.[level] ?? pmAttrs.listNumFmt) === "none" || pmAttrs.listMarker === "") return null;
143
- return formatNumberedMarker(counters, level);
79
+ function computeListMarker(pmAttrs, state) {
80
+ return advanceListMarker(pmAttrs, state);
144
81
  }
145
82
  /**
146
83
  * Reset the block ID counter (useful for testing).
@@ -151,7 +88,7 @@ function resetBlockIdCounter() {
151
88
  /**
152
89
  * Extract run formatting from ProseMirror marks.
153
90
  */
154
- function extractRunFormatting(marks, theme) {
91
+ function extractRunFormatting(marks, theme, fontAlternates) {
155
92
  const formatting = {};
156
93
  let hasNoteRef = false;
157
94
  for (const mark of marks) switch (mark.type.name) {
@@ -203,11 +140,23 @@ function extractRunFormatting(marks, theme) {
203
140
  case "fontFamily": {
204
141
  const attrs = expectFontFamilyMarkAttrs(mark);
205
142
  const font = resolveWesternThemeFont(attrs, theme);
206
- if (font) formatting.fontFamily = font;
143
+ if (font) {
144
+ formatting.fontFamily = font;
145
+ const alternate = getFontAlternate(font, fontAlternates);
146
+ if (alternate) formatting.alternateFontFamily = alternate;
147
+ }
207
148
  const eastAsiaFont = resolveEastAsiaThemeFont(attrs, theme);
208
- if (eastAsiaFont) formatting.eastAsiaFontFamily = eastAsiaFont;
149
+ if (eastAsiaFont) {
150
+ formatting.eastAsiaFontFamily = eastAsiaFont;
151
+ const alternate = getFontAlternate(eastAsiaFont, fontAlternates);
152
+ if (alternate) formatting.eastAsiaAlternateFontFamily = alternate;
153
+ }
209
154
  const complexScriptFont = resolveComplexScriptThemeFont(attrs, theme);
210
- if (complexScriptFont) formatting.complexScriptFontFamily = complexScriptFont;
155
+ if (complexScriptFont) {
156
+ formatting.complexScriptFontFamily = complexScriptFont;
157
+ const alternate = getFontAlternate(complexScriptFont, fontAlternates);
158
+ if (alternate) formatting.complexScriptAlternateFontFamily = alternate;
159
+ }
211
160
  break;
212
161
  }
213
162
  case "language": {
@@ -223,7 +172,8 @@ function extractRunFormatting(marks, theme) {
223
172
  const attrs = expectCharacterSpacingMarkAttrs(mark);
224
173
  if (attrs.spacing !== void 0) formatting.letterSpacing = twipsToPixels(attrs.spacing);
225
174
  if (attrs.position !== void 0 && attrs.position !== 0) formatting.positionPx = halfPointsToPixels(attrs.position);
226
- if (attrs.scale !== void 0 && attrs.scale !== 100) formatting.horizontalScale = attrs.scale;
175
+ const horizontalScale = normalizeHorizontalScalePercent(attrs.scale);
176
+ if (horizontalScale !== void 0) formatting.horizontalScale = horizontalScale;
227
177
  if (attrs.kerning !== void 0 && attrs.kerning > 0) formatting.kerningMinPt = halfPointsToPoints(attrs.kerning);
228
178
  break;
229
179
  }
@@ -346,7 +296,11 @@ function mergeRunFormatting(paraDefaults, formatting) {
346
296
  ...paraDefaults,
347
297
  ...markDefaultBlackTextColorSource(formatting, paraDefaults)
348
298
  };
299
+ if (formatting.fontFamily !== void 0 && formatting.alternateFontFamily === void 0) delete merged.alternateFontFamily;
300
+ if (formatting.eastAsiaFontFamily !== void 0 && formatting.eastAsiaAlternateFontFamily === void 0) delete merged.eastAsiaAlternateFontFamily;
301
+ if (formatting.complexScriptFontFamily !== void 0 && formatting.complexScriptAlternateFontFamily === void 0) delete merged.complexScriptAlternateFontFamily;
349
302
  if (merged.letterSpacing === 0) delete merged.letterSpacing;
303
+ if (formatting.horizontalScale === 100 && paraDefaults.horizontalScale === void 0) delete merged.horizontalScale;
350
304
  return merged;
351
305
  }
352
306
  /** Restore character-style toggle values that plain visual marks cannot represent. */
@@ -398,15 +352,27 @@ function applyRunFormattingOverrides(formatting, attrs) {
398
352
  if (attrs.fontSizeCs !== void 0) formatting.complexScriptFontSize = attrs.fontSizeCs / 2;
399
353
  if (attrs.cs !== void 0) formatting.forceComplexScript = attrs.cs;
400
354
  }
401
- function textFormattingToRunFormatting(defaultTextFormatting, theme) {
355
+ function textFormattingToRunFormatting(defaultTextFormatting, theme, fontAlternates) {
402
356
  if (!defaultTextFormatting) return {};
403
357
  const result = {};
404
358
  const fontFamily = defaultTextFormatting.fontFamily ? resolveWesternThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
405
- if (fontFamily) result.fontFamily = fontFamily;
359
+ if (fontFamily) {
360
+ result.fontFamily = fontFamily;
361
+ const alternate = getFontAlternate(fontFamily, fontAlternates);
362
+ if (alternate) result.alternateFontFamily = alternate;
363
+ }
406
364
  const eastAsiaFontFamily = defaultTextFormatting.fontFamily ? resolveEastAsiaThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
407
- if (eastAsiaFontFamily) result.eastAsiaFontFamily = eastAsiaFontFamily;
365
+ if (eastAsiaFontFamily) {
366
+ result.eastAsiaFontFamily = eastAsiaFontFamily;
367
+ const alternate = getFontAlternate(eastAsiaFontFamily, fontAlternates);
368
+ if (alternate) result.eastAsiaAlternateFontFamily = alternate;
369
+ }
408
370
  const complexScriptFontFamily = defaultTextFormatting.fontFamily ? resolveComplexScriptThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
409
- if (complexScriptFontFamily) result.complexScriptFontFamily = complexScriptFontFamily;
371
+ if (complexScriptFontFamily) {
372
+ result.complexScriptFontFamily = complexScriptFontFamily;
373
+ const alternate = getFontAlternate(complexScriptFontFamily, fontAlternates);
374
+ if (alternate) result.complexScriptAlternateFontFamily = alternate;
375
+ }
410
376
  if (defaultTextFormatting.language) result.language = { ...defaultTextFormatting.language };
411
377
  if (defaultTextFormatting.fontSize !== void 0) result.fontSize = defaultTextFormatting.fontSize / 2;
412
378
  if (defaultTextFormatting.fontSizeCs !== void 0) result.complexScriptFontSize = defaultTextFormatting.fontSizeCs / 2;
@@ -435,7 +401,8 @@ function textFormattingToRunFormatting(defaultTextFormatting, theme) {
435
401
  if (defaultTextFormatting.smallCaps !== void 0) result.smallCaps = defaultTextFormatting.smallCaps;
436
402
  if (defaultTextFormatting.spacing !== void 0 && defaultTextFormatting.spacing !== 0) result.letterSpacing = twipsToPixels(defaultTextFormatting.spacing);
437
403
  if (defaultTextFormatting.position !== void 0 && defaultTextFormatting.position !== 0) result.positionPx = halfPointsToPixels(defaultTextFormatting.position);
438
- if (defaultTextFormatting.scale !== void 0 && defaultTextFormatting.scale !== 100) result.horizontalScale = defaultTextFormatting.scale;
404
+ const horizontalScale = normalizeHorizontalScalePercent(defaultTextFormatting.scale);
405
+ if (horizontalScale !== void 0 && horizontalScale !== 100) result.horizontalScale = horizontalScale;
439
406
  if (defaultTextFormatting.kerning !== void 0 && defaultTextFormatting.kerning > 0) result.kerningMinPt = halfPointsToPoints(defaultTextFormatting.kerning);
440
407
  if (defaultTextFormatting.emboss !== void 0) result.emboss = defaultTextFormatting.emboss;
441
408
  if (defaultTextFormatting.imprint !== void 0) result.imprint = defaultTextFormatting.imprint;
@@ -444,8 +411,8 @@ function textFormattingToRunFormatting(defaultTextFormatting, theme) {
444
411
  if (defaultTextFormatting.emphasisMark && defaultTextFormatting.emphasisMark !== "none") result.emphasisMark = defaultTextFormatting.emphasisMark;
445
412
  return result;
446
413
  }
447
- function paragraphRunDefaults(pmAttrs, theme) {
448
- return textFormattingToRunFormatting(pmAttrs.defaultTextFormatting, theme);
414
+ function paragraphRunDefaults(pmAttrs, theme, fontAlternates) {
415
+ return textFormattingToRunFormatting(pmAttrs.defaultTextFormatting, theme, fontAlternates);
449
416
  }
450
417
  /**
451
418
  * Build an ImageRun from ProseMirror node attrs, applying conditional property assignment
@@ -509,12 +476,14 @@ function paragraphToRuns(node, startPos, _options) {
509
476
  const runs = [];
510
477
  const offset = startPos + 1;
511
478
  const theme = _options.theme;
479
+ const fontAlternates = _options.fontAlternates;
512
480
  const pmAttrs = expectParagraphAttrs(node);
513
- const paraDefaults = paragraphRunDefaults(pmAttrs, theme);
481
+ const paraDefaults = paragraphRunDefaults(pmAttrs, theme, fontAlternates);
514
482
  const paragraphStyleId = pmAttrs.styleId;
515
483
  const inTocParagraph = pmAttrs._tableOfContentsLevel !== void 0 || tableOfContentsStyleLevel({ styleId: paragraphStyleId }) !== void 0;
516
484
  let leadingRenderedPageBreakPending = pmAttrs.renderedPageBreakBefore === true;
517
485
  function pushRunsForChild(child, childPos) {
486
+ if (child.type.name === "bookmarkBoundary") return;
518
487
  if (child.type.name === "renderedPageBreak") {
519
488
  if (leadingRenderedPageBreakPending) {
520
489
  leadingRenderedPageBreakPending = false;
@@ -529,7 +498,7 @@ function paragraphToRuns(node, startPos, _options) {
529
498
  }
530
499
  if (child.type.name !== "sdt") leadingRenderedPageBreakPending = false;
531
500
  if (child.isText && child.text) {
532
- const formatting = extractRunFormatting(child.marks, theme);
501
+ const formatting = extractRunFormatting(child.marks, theme, fontAlternates);
533
502
  applyCharacterStyleToggleFormatting({
534
503
  formatting,
535
504
  marks: child.marks,
@@ -550,18 +519,20 @@ function paragraphToRuns(node, startPos, _options) {
550
519
  const attrs = expectSymbolAttrs(child);
551
520
  const text = decodeOoxmlSymbolCharacter(attrs.char);
552
521
  if (text === null) return;
553
- const formatting = extractRunFormatting(child.marks, theme);
522
+ const formatting = extractRunFormatting(child.marks, theme, fontAlternates);
554
523
  applyCharacterStyleToggleFormatting({
555
524
  formatting,
556
525
  marks: child.marks,
557
526
  paraDefaults
558
527
  });
559
528
  if (inTocParagraph) stripTocHyperlinkStyle(formatting);
529
+ const alternateFontFamily = getFontAlternate(attrs.font, fontAlternates);
530
+ formatting.fontFamily = attrs.font;
531
+ if (alternateFontFamily) formatting.alternateFontFamily = alternateFontFamily;
560
532
  runs.push({
561
533
  kind: "text",
562
534
  text,
563
535
  ...mergeRunFormatting(paraDefaults, formatting),
564
- fontFamily: attrs.font,
565
536
  pmStart: childPos,
566
537
  pmEnd: childPos + child.nodeSize
567
538
  });
@@ -576,7 +547,7 @@ function paragraphToRuns(node, startPos, _options) {
576
547
  return;
577
548
  }
578
549
  if (child.type.name === "tab") {
579
- const formatting = extractRunFormatting(child.marks, theme);
550
+ const formatting = extractRunFormatting(child.marks, theme, fontAlternates);
580
551
  applyCharacterStyleToggleFormatting({
581
552
  formatting,
582
553
  marks: child.marks,
@@ -595,12 +566,12 @@ function paragraphToRuns(node, startPos, _options) {
595
566
  const attrs = expectImageAttrs(child);
596
567
  if (!attrs.src) return;
597
568
  const constrained = constrainImageToPage(attrs.width ?? 100, attrs.height ?? 100, _options.pageContentHeight);
598
- const trackedFmt = extractRunFormatting(child.marks, theme);
569
+ const trackedFmt = extractRunFormatting(child.marks, theme, fontAlternates);
599
570
  const run = buildImageRun(attrs, constrained, childPos, childPos + child.nodeSize, trackedFmt);
600
571
  runs.push(run);
601
572
  return;
602
573
  }
603
- if (child.type.name === "field") {
574
+ if (child.type.name === "field" || child.type.name === "structuredField") {
604
575
  const attrs = expectFieldAttrs(child);
605
576
  const ft = attrs.fieldType;
606
577
  let mappedType = "OTHER";
@@ -608,7 +579,7 @@ function paragraphToRuns(node, startPos, _options) {
608
579
  else if (ft === "NUMPAGES") mappedType = "NUMPAGES";
609
580
  else if (ft === "DATE") mappedType = "DATE";
610
581
  else if (ft === "TIME") mappedType = "TIME";
611
- const extractedFieldFormatting = extractRunFormatting(child.marks, theme);
582
+ const extractedFieldFormatting = extractRunFormatting(child.marks, theme, fontAlternates);
612
583
  applyCharacterStyleToggleFormatting({
613
584
  formatting: extractedFieldFormatting,
614
585
  marks: child.marks,
@@ -620,7 +591,7 @@ function paragraphToRuns(node, startPos, _options) {
620
591
  kind: "field",
621
592
  fieldType: mappedType,
622
593
  instruction: attrs.instruction,
623
- fallback: attrs.displayText || "",
594
+ fallback: _options.numberedRefResults?.get(child) ?? attrs.displayText ?? "",
624
595
  ...attrs.fldLock ? { fldLock: true } : {},
625
596
  pmStart: childPos,
626
597
  pmEnd: childPos + child.nodeSize,
@@ -711,28 +682,28 @@ function toPreviousListAttrs(previousFormatting) {
711
682
  if (listMarkerSuffix !== void 0) attrs.listMarkerSuffix = listMarkerSuffix;
712
683
  return attrs;
713
684
  }
714
- function resolveDeletedListMarker(previousListAttrs, listCounters, listAbstractCounters, listSeenNumIds) {
715
- if (listCounters && previousListAttrs.numPr) {
716
- const marker = computeListMarker(previousListAttrs, listCounters, listAbstractCounters ?? /* @__PURE__ */ new Map(), listSeenNumIds ?? /* @__PURE__ */ new Set());
685
+ function resolveDeletedListMarker(previousListAttrs, listCounterState) {
686
+ if (listCounterState && previousListAttrs.numPr) {
687
+ const marker = computeListMarker(previousListAttrs, listCounterState);
717
688
  if (marker) return marker;
718
689
  }
719
690
  if (previousListAttrs.listMarker) return previousListAttrs.listIsBullet ? convertBulletToUnicode(previousListAttrs.listMarker) : previousListAttrs.listMarker;
720
691
  if (previousListAttrs.listIsBullet) return "•";
721
692
  return null;
722
693
  }
723
- function applyDeletedListMarkerAttrs(attrs, change, listCounters, listAbstractCounters, listSeenNumIds, theme) {
694
+ function applyDeletedListMarkerAttrs(attrs, change, listCounterState, theme, fontAlternates) {
724
695
  const previousListAttrs = toPreviousListAttrs(change.previousFormatting);
725
- const marker = resolveDeletedListMarker(previousListAttrs, listCounters, listAbstractCounters, listSeenNumIds);
696
+ const marker = resolveDeletedListMarker(previousListAttrs, listCounterState);
726
697
  if (!marker) return;
727
698
  attrs.listMarker = marker;
728
699
  attrs.listMarkerRevision = toListMarkerRevision("del", change.info);
729
700
  if (previousListAttrs.listIsBullet !== void 0) attrs.listIsBullet = previousListAttrs.listIsBullet;
730
701
  if (previousListAttrs.listMarkerHidden !== void 0) attrs.listMarkerHidden = previousListAttrs.listMarkerHidden;
731
- if (previousListAttrs.listMarkerFormatting) attrs.listMarkerFormatting = textFormattingToRunFormatting(previousListAttrs.listMarkerFormatting, theme);
702
+ if (previousListAttrs.listMarkerFormatting) attrs.listMarkerFormatting = textFormattingToRunFormatting(previousListAttrs.listMarkerFormatting, theme, fontAlternates);
732
703
  if (previousListAttrs.listMarkerAlignment) attrs.listMarkerAlignment = previousListAttrs.listMarkerAlignment;
733
704
  if (previousListAttrs.listMarkerSuffix) attrs.listMarkerSuffix = previousListAttrs.listMarkerSuffix;
734
705
  }
735
- function convertParagraphAttrs(pmAttrs, theme, listCounters, listAbstractCounters, listSeenNumIds, defaultTabStopTwips, originalListCounters, originalListAbstractCounters, originalListSeenNumIds) {
706
+ function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStreams, defaultTabStopTwips }) {
736
707
  const attrs = {};
737
708
  if (pmAttrs.alignment) {
738
709
  const align = pmAttrs.alignment;
@@ -851,26 +822,24 @@ function convertParagraphAttrs(pmAttrs, theme, listCounters, listAbstractCounter
851
822
  if (numberingInsertionChange) attrs.listMarkerRevision = toListMarkerRevision("ins", numberingInsertionChange.info);
852
823
  }
853
824
  }
854
- const useOriginalStream = attrs.listMarkerRevision?.kind === "del" && originalListCounters !== void 0;
855
- const streamCounters = useOriginalStream ? originalListCounters : listCounters;
856
- const resolvedMarker = applyMarkerAllCaps(streamCounters ? computeListMarker(pmAttrs, streamCounters, (useOriginalStream ? originalListAbstractCounters : listAbstractCounters) ?? /* @__PURE__ */ new Map(), (useOriginalStream ? originalListSeenNumIds : listSeenNumIds) ?? /* @__PURE__ */ new Set()) : null, pmAttrs.listMarkerAllCaps);
857
- const numberedNumId = pmAttrs.numPr?.numId;
858
- if (attrs.listMarkerRevision === void 0 && !pmAttrs.listIsBullet && originalListCounters !== void 0 && numberedNumId !== void 0 && numberedNumId !== 0) computeListMarker(pmAttrs, originalListCounters, originalListAbstractCounters ?? /* @__PURE__ */ new Map(), originalListSeenNumIds ?? /* @__PURE__ */ new Set());
859
- else if (changedNumberingChange !== void 0 && originalListCounters !== void 0) {
860
- const previousListAttrs = toPreviousListAttrs(changedNumberingChange.previousFormatting);
861
- if (previousListAttrs.numPr && !previousListAttrs.listIsBullet) computeListMarker(previousListAttrs, originalListCounters, originalListAbstractCounters ?? /* @__PURE__ */ new Map(), originalListSeenNumIds ?? /* @__PURE__ */ new Set());
862
- }
825
+ const resolvedMarker = applyMarkerAllCaps(advanceVisibleListMarker(pmAttrs, listCounterStreams).marker, pmAttrs.listMarkerAllCaps);
863
826
  if (resolvedMarker !== null) attrs.listMarker = resolvedMarker;
864
827
  else if (pmAttrs.listMarker) attrs.listMarker = pmAttrs.listIsBullet ? convertBulletToUnicode(pmAttrs.listMarker) : pmAttrs.listMarker;
865
828
  if (pmAttrs.listIsBullet !== void 0) attrs.listIsBullet = pmAttrs.listIsBullet;
866
829
  if (pmAttrs.listMarkerHidden) attrs.listMarkerHidden = true;
867
- if (pmAttrs.listMarkerFormatting) attrs.listMarkerFormatting = textFormattingToRunFormatting(pmAttrs.listMarkerFormatting, theme);
830
+ if (pmAttrs.listMarkerFormatting) attrs.listMarkerFormatting = textFormattingToRunFormatting(pmAttrs.listMarkerFormatting, theme, fontAlternates);
868
831
  if (pmAttrs.listMarkerAlignment) attrs.listMarkerAlignment = pmAttrs.listMarkerAlignment;
869
832
  if (pmAttrs.listMarkerSuffix) attrs.listMarkerSuffix = pmAttrs.listMarkerSuffix;
870
833
  if (pmAttrs.listMarkerSecondSlotOffsetTwips !== void 0) attrs.listMarkerSecondSlotOffsetTwips = pmAttrs.listMarkerSecondSlotOffsetTwips;
871
834
  if (!pmAttrs.numPr) {
872
835
  const numberingRemovedChange = propertyChanges.find(isRemovedNumberingChange);
873
- if (numberingRemovedChange) applyDeletedListMarkerAttrs(attrs, numberingRemovedChange, originalListCounters, originalListAbstractCounters, originalListSeenNumIds, theme);
836
+ if (numberingRemovedChange) {
837
+ applyDeletedListMarkerAttrs(attrs, numberingRemovedChange, void 0, theme, fontAlternates);
838
+ if (resolvedMarker !== null) {
839
+ attrs.listMarker = resolvedMarker;
840
+ attrs.listMarkerRevision = toListMarkerRevision("del", numberingRemovedChange.info);
841
+ }
842
+ }
874
843
  }
875
844
  if (defaultTabStopTwips !== void 0) attrs.defaultTabStopTwips = defaultTabStopTwips;
876
845
  const dtf = pmAttrs.defaultTextFormatting;
@@ -879,7 +848,11 @@ function convertParagraphAttrs(pmAttrs, theme, listCounters, listAbstractCounter
879
848
  if (attrs.listMarker !== void 0 && !attrs.listMarkerHidden && dtf.fontSizeCs !== void 0 && (dtf.fontSize === void 0 || dtf.fontSizeCs > dtf.fontSize)) attrs.listParagraphMarkFontSize = dtf.fontSizeCs / 2;
880
849
  if (dtf.fontFamily) {
881
850
  const resolvedFamily = resolveWesternThemeFont(dtf.fontFamily, theme);
882
- if (resolvedFamily) attrs.defaultFontFamily = resolvedFamily;
851
+ if (resolvedFamily) {
852
+ attrs.defaultFontFamily = resolvedFamily;
853
+ const alternate = getFontAlternate(resolvedFamily, fontAlternates);
854
+ if (alternate) attrs.defaultAlternateFontFamily = alternate;
855
+ }
883
856
  }
884
857
  }
885
858
  return attrs;
@@ -908,7 +881,12 @@ function hasOnlyVisuallyEmptyTextRuns(runs) {
908
881
  function convertParagraph(node, startPos, options) {
909
882
  const pmAttrs = expectParagraphAttrs(node);
910
883
  const runs = paragraphToRuns(node, startPos, options);
911
- const attrs = convertParagraphAttrs(pmAttrs, options.theme, options.listCounters, options.listAbstractCounters, options.listSeenNumIds, options.defaultTabStopTwips, options.originalListCounters, options.originalListAbstractCounters, options.originalListSeenNumIds);
884
+ const attrs = convertParagraphAttrs(pmAttrs, {
885
+ theme: options.theme,
886
+ fontAlternates: options.fontAlternates,
887
+ listCounterStreams: options.listCounterStreams,
888
+ defaultTabStopTwips: options.defaultTabStopTwips
889
+ });
912
890
  if (options.lineBreakRules) attrs.lineBreakRules = options.lineBreakRules;
913
891
  if (options.justificationCompatibility) attrs.justificationCompatibility = options.justificationCompatibility;
914
892
  if (options.automaticHyphenation) attrs.automaticHyphenation = options.automaticHyphenation;
@@ -919,7 +897,11 @@ function convertParagraph(node, startPos, options) {
919
897
  if (paragraphMarkFormatting && Object.values(paragraphMarkFormatting).some((value) => value !== void 0 && value !== null)) attrs.hasDirectParagraphMarkFormatting = true;
920
898
  if (paragraphMarkFormatting?.fontSize !== void 0) attrs.defaultFontSize = paragraphMarkFormatting.fontSize / 2;
921
899
  const paragraphMarkFontFamily = paragraphMarkFormatting?.fontFamily ? resolveWesternThemeFont(paragraphMarkFormatting.fontFamily, options.theme) : void 0;
922
- if (paragraphMarkFontFamily) attrs.defaultFontFamily = paragraphMarkFontFamily;
900
+ if (paragraphMarkFontFamily) {
901
+ attrs.defaultFontFamily = paragraphMarkFontFamily;
902
+ const alternate = getFontAlternate(paragraphMarkFontFamily, options.fontAlternates);
903
+ if (alternate) attrs.defaultAlternateFontFamily = alternate;
904
+ }
923
905
  }
924
906
  if (runs.length === 0 && defaultTextFormatting?.hidden === true) {
925
907
  attrs.suppressEmptyParagraphHeight = true;
@@ -1139,6 +1121,8 @@ function convertTableRow(node, startPos, options, tableCellMargins) {
1139
1121
  if (attrs.isHeader) row.isHeader = attrs.isHeader;
1140
1122
  if (attrs._originalFormatting?.cantSplit) row.cantSplit = true;
1141
1123
  if (attrs.hidden) row.hidden = attrs.hidden;
1124
+ const effectiveJustification = attrs._originalFormatting?.justification ?? attrs._resolvedJustification;
1125
+ if (effectiveJustification) row.justification = effectiveJustification;
1142
1126
  return row;
1143
1127
  }
1144
1128
  /**
@@ -1160,7 +1144,7 @@ function convertTable(node, startPos, options) {
1160
1144
  const cellWidths = rows[0].cells.map((cell) => cell.width);
1161
1145
  if (cellWidths.every((w) => w !== void 0 && w > 0)) columnWidths = cellWidths;
1162
1146
  }
1163
- const justification = attrs.justification;
1147
+ const justification = attrs.justification ?? attrs._resolvedJustification;
1164
1148
  const originalFormatting = attrs._originalFormatting;
1165
1149
  const effectiveIndent = attrs._resolvedIndent ?? originalFormatting?.indent;
1166
1150
  const indentPx = effectiveIndent?.value !== void 0 && effectiveIndent?.type === "dxa" ? twipsToPixels(effectiveIndent.value) : void 0;
@@ -1264,6 +1248,8 @@ function convertTextBoxNode(node, startPos, opts) {
1264
1248
  pmStart: startPos,
1265
1249
  pmEnd: startPos + node.nodeSize
1266
1250
  };
1251
+ const verticalAlign = normalizeShapeTextAnchor(attrs.verticalAlign);
1252
+ if (verticalAlign !== void 0) textBox.verticalAlign = verticalAlign;
1267
1253
  if (attrs.height !== void 0) textBox.height = attrs.height;
1268
1254
  if (attrs.autoFit !== void 0) textBox.autoFit = attrs.autoFit;
1269
1255
  if (attrs.textWrap !== void 0) textBox.textWrap = attrs.textWrap;
@@ -1283,6 +1269,11 @@ function convertTextBoxNode(node, startPos, opts) {
1283
1269
  if (attrs._docxGroupId !== void 0) setTextBoxGroupId(textBox, attrs._docxGroupId);
1284
1270
  return textBox;
1285
1271
  }
1272
+ function getLastMapKey(map) {
1273
+ let lastKey;
1274
+ for (const key of map.keys()) lastKey = key;
1275
+ return lastKey;
1276
+ }
1286
1277
  /**
1287
1278
  * Convert a ProseMirror document to FlowBlock array.
1288
1279
  *
@@ -1292,16 +1283,40 @@ function convertTextBoxNode(node, startPos, opts) {
1292
1283
  function toFlowBlocks(doc, options = {}) {
1293
1284
  assertValidProseMirrorDocument(doc, "Cannot layout invalid ProseMirror document");
1294
1285
  resetBlockIdCounter();
1286
+ const listCounters = options.listCounters ?? /* @__PURE__ */ new Map();
1287
+ const originalListCounters = options.originalListCounters ?? /* @__PURE__ */ new Map();
1288
+ const lastAdvancedNumId = getLastMapKey(listCounters);
1289
+ const lastAdvancedOriginalNumId = getLastMapKey(originalListCounters);
1290
+ const listCounterState = {
1291
+ counters: listCounters,
1292
+ abstractCounters: options.listAbstractCounters ?? /* @__PURE__ */ new Map(),
1293
+ seenLevels: options.listSeenNumIds ?? /* @__PURE__ */ new Set(),
1294
+ ...lastAdvancedNumId !== void 0 ? { lastAdvancedNumId } : {}
1295
+ };
1296
+ const originalListCounterState = {
1297
+ counters: originalListCounters,
1298
+ abstractCounters: options.originalListAbstractCounters ?? /* @__PURE__ */ new Map(),
1299
+ seenLevels: options.originalListSeenNumIds ?? /* @__PURE__ */ new Set(),
1300
+ ...lastAdvancedOriginalNumId !== void 0 ? { lastAdvancedNumId: lastAdvancedOriginalNumId } : {}
1301
+ };
1295
1302
  const opts = {
1296
1303
  ...options,
1297
1304
  defaultFont: options.defaultFont ?? DEFAULT_FONT,
1298
1305
  defaultSize: options.defaultSize ?? DEFAULT_SIZE,
1299
- listCounters: options.listCounters ?? /* @__PURE__ */ new Map(),
1300
- listAbstractCounters: options.listAbstractCounters ?? /* @__PURE__ */ new Map(),
1301
- listSeenNumIds: options.listSeenNumIds ?? /* @__PURE__ */ new Set(),
1302
- originalListCounters: options.originalListCounters ?? /* @__PURE__ */ new Map(),
1303
- originalListAbstractCounters: options.originalListAbstractCounters ?? /* @__PURE__ */ new Map(),
1304
- originalListSeenNumIds: options.originalListSeenNumIds ?? /* @__PURE__ */ new Set()
1306
+ listCounters: listCounterState.counters,
1307
+ listAbstractCounters: listCounterState.abstractCounters,
1308
+ listSeenNumIds: listCounterState.seenLevels,
1309
+ originalListCounters: originalListCounterState.counters,
1310
+ originalListAbstractCounters: originalListCounterState.abstractCounters,
1311
+ originalListSeenNumIds: originalListCounterState.seenLevels,
1312
+ listCounterStreams: {
1313
+ final: listCounterState,
1314
+ original: originalListCounterState
1315
+ },
1316
+ numberedRefResults: resolveNumberedRefFields(doc, {
1317
+ listCounterState: cloneListCounterState(listCounterState),
1318
+ originalListCounterState: cloneListCounterState(originalListCounterState)
1319
+ })
1305
1320
  };
1306
1321
  const blocks = [];
1307
1322
  const offset = 0;
@@ -1450,7 +1465,8 @@ function toFlowBlocks(doc, options = {}) {
1450
1465
  ...sourceAttrs?.snapToGrid !== void 0 ? { snapToGrid: sourceAttrs.snapToGrid } : {},
1451
1466
  ...sourceAttrs?.documentGridLinePitch !== void 0 ? { documentGridLinePitch: sourceAttrs.documentGridLinePitch } : {},
1452
1467
  ...sourceAttrs?.defaultFontSize !== void 0 ? { defaultFontSize: sourceAttrs.defaultFontSize } : {},
1453
- ...sourceAttrs?.defaultFontFamily !== void 0 ? { defaultFontFamily: sourceAttrs.defaultFontFamily } : {}
1468
+ ...sourceAttrs?.defaultFontFamily !== void 0 ? { defaultFontFamily: sourceAttrs.defaultFontFamily } : {},
1469
+ ...sourceAttrs?.defaultAlternateFontFamily !== void 0 ? { defaultAlternateFontFamily: sourceAttrs.defaultAlternateFontFamily } : {}
1454
1470
  };
1455
1471
  const carrier = {
1456
1472
  kind: "paragraph",
@@ -1,4 +1,4 @@
1
- import { NoteStoryKey } from "../../controller/noteEditorManager.js";
1
+ import { NoteStoryKey } from "../../types/editor-story.js";
2
2
  //#region src/layout-bridge/dom/noteStoryDom.d.ts
3
3
  declare const findNoteStoryForTarget: (target: unknown) => NoteStoryKey | null;
4
4
  //#endregion