@stll/folio-core 0.59.0 → 0.60.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 (116) hide show
  1. package/README.md +10 -1
  2. package/dist/compat/eigenpal.d.ts +2 -2
  3. package/dist/compat/eigenpal.js +2 -2
  4. package/dist/controller/canonicalSession.js +3 -2
  5. package/dist/controller/canonicalStructure.js +10 -7
  6. package/dist/controller/fontReadiness.js +1 -1
  7. package/dist/controller/layoutPipeline.js +7 -1
  8. package/dist/controller/layoutSession.d.ts +2 -0
  9. package/dist/display-list/build/fontTable.js +7 -5
  10. package/dist/display-list/build/furniture.d.ts +1 -0
  11. package/dist/display-list/build/furniture.js +1 -0
  12. package/dist/display-list/build/watermarkPrimitives.d.ts +2 -1
  13. package/dist/display-list/build/watermarkPrimitives.js +9 -3
  14. package/dist/display-list/editor/pageRenderer.js +1 -0
  15. package/dist/docx/bookmarkIdNormalization.d.ts +10 -0
  16. package/dist/docx/bookmarkIdNormalization.js +100 -0
  17. package/dist/docx/bookmarkParser.js +4 -2
  18. package/dist/docx/importedIdCollisions.d.ts +136 -0
  19. package/dist/docx/importedIdCollisions.js +215 -0
  20. package/dist/docx/numberingParser.js +2 -2
  21. package/dist/docx/paragraphPropertySource.js +1 -2
  22. package/dist/docx/parseContext.d.ts +2 -1
  23. package/dist/docx/parseContext.js +1 -0
  24. package/dist/docx/parseWarningMessage.js +1 -0
  25. package/dist/docx/parser.js +5 -1
  26. package/dist/docx/relsParser.js +1 -1
  27. package/dist/docx/rezip.js +2 -1
  28. package/dist/docx/selectedXmlIdentityScan.d.ts +10 -0
  29. package/dist/docx/selectedXmlIdentityScan.js +36 -0
  30. package/dist/docx/selectiveSave.js +5 -4
  31. package/dist/docx/selectiveXmlPatch.js +44 -52
  32. package/dist/docx/serializer/commentSerializer.d.ts +3 -1
  33. package/dist/docx/serializer/commentSerializer.js +11 -2
  34. package/dist/docx/serializer/runSerializer.js +2 -2
  35. package/dist/docx/serializer/trackedChangeAttributes.d.ts +1 -3
  36. package/dist/docx/serializer/trackedChangeAttributes.js +1 -11
  37. package/dist/fonts/embeddedFontFingerprint.d.ts +5 -0
  38. package/dist/fonts/embeddedFontFingerprint.js +18 -0
  39. package/dist/fonts/embeddedFonts.d.ts +1 -1
  40. package/dist/fonts/embeddedFonts.js +1 -1
  41. package/dist/fonts/headlessMeasure.js +0 -0
  42. package/dist/headless-layout.js +1 -0
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.js +2 -2
  45. package/dist/layout-bridge/convert/flowConversionShared.d.ts +2 -0
  46. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -1
  47. package/dist/layout-bridge/convert/footnoteLayout.js +3 -0
  48. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  49. package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
  50. package/dist/layout-bridge/convert/paragraphConversion.js +8 -1
  51. package/dist/layout-bridge/convert/toFlowBlocks.js +25 -1
  52. package/dist/layout-engine/measure/cache.js +39 -7
  53. package/dist/layout-engine/measure/lineTypography.js +1 -0
  54. package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
  55. package/dist/layout-engine/measure/listMarkerWidth.js +1 -0
  56. package/dist/layout-engine/measure/measureContainer.js +3 -4
  57. package/dist/layout-engine/measure/measureHelpers.d.ts +6 -9
  58. package/dist/layout-engine/measure/measureHelpers.js +21 -18
  59. package/dist/layout-engine/measure/measureParagraph.js +2 -0
  60. package/dist/layout-engine/measure/measureTypes.d.ts +2 -0
  61. package/dist/layout-engine/types.d.ts +4 -1
  62. package/dist/layout-painter/renderPage.d.ts +1 -0
  63. package/dist/layout-painter/renderPage.js +11 -3
  64. package/dist/layout-painter/renderParagraph.js +13 -3
  65. package/dist/layout-painter/renderWatermark.d.ts +1 -0
  66. package/dist/layout-painter/renderWatermark.js +7 -3
  67. package/dist/managers/editorShortcuts.d.ts +2 -1
  68. package/dist/managers/editorShortcuts.js +2 -1
  69. package/dist/prosemirror/canonicalSelectionRange.d.ts +4 -1
  70. package/dist/prosemirror/canonicalSelectionRange.js +9 -3
  71. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +8 -2
  72. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +39 -3
  73. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.d.ts +8 -2
  74. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +4 -3
  75. package/dist/prosemirror/extensions/features/ImageDragExtension.js +4 -3
  76. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +4 -3
  77. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +9 -3
  78. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +6 -5
  79. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +8 -2
  80. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +11 -3
  81. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +4 -3
  82. package/dist/prosemirror/extensions/marks/markUtils.js +1 -1
  83. package/dist/prosemirror/pluginKeyOwner.d.ts +13 -0
  84. package/dist/prosemirror/pluginKeyOwner.js +35 -0
  85. package/dist/prosemirror/plugins/aiCitationDecorations.d.ts +11 -4
  86. package/dist/prosemirror/plugins/aiCitationDecorations.js +16 -3
  87. package/dist/prosemirror/plugins/aiSuggestionDecorations.d.ts +11 -4
  88. package/dist/prosemirror/plugins/aiSuggestionDecorations.js +18 -3
  89. package/dist/prosemirror/plugins/anonymizationDecorations.d.ts +11 -11
  90. package/dist/prosemirror/plugins/anonymizationDecorations.js +23 -13
  91. package/dist/prosemirror/plugins/autocompleteSuggestion.d.ts +8 -2
  92. package/dist/prosemirror/plugins/autocompleteSuggestion.js +27 -5
  93. package/dist/prosemirror/plugins/contentControlWidgets.d.ts +8 -2
  94. package/dist/prosemirror/plugins/contentControlWidgets.js +4 -3
  95. package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +6 -5
  96. package/dist/prosemirror/plugins/createDocScanPlugin.js +1 -1
  97. package/dist/prosemirror/plugins/documentNumbering.js +5 -3
  98. package/dist/prosemirror/plugins/documentStyleState.d.ts +8 -2
  99. package/dist/prosemirror/plugins/documentStyleState.js +2 -2
  100. package/dist/prosemirror/plugins/documentStyles.js +1 -1
  101. package/dist/prosemirror/plugins/selectionTracker.d.ts +8 -2
  102. package/dist/prosemirror/plugins/selectionTracker.js +4 -3
  103. package/dist/prosemirror/plugins/suggestionMode.d.ts +8 -2
  104. package/dist/prosemirror/plugins/suggestionMode.js +4 -3
  105. package/dist/prosemirror/plugins/templateDirectives.d.ts +8 -2
  106. package/dist/prosemirror/plugins/templateDirectives.js +19 -4
  107. package/dist/prosemirror/plugins/templatePreviewValues.d.ts +8 -2
  108. package/dist/prosemirror/plugins/templatePreviewValues.js +27 -5
  109. package/dist/prosemirror/plugins/templateSlashMenu.d.ts +8 -2
  110. package/dist/prosemirror/plugins/templateSlashMenu.js +23 -5
  111. package/dist/prosemirror/plugins/transactionInvariants.js +23 -3
  112. package/dist/utils/fontLoader.d.ts +2 -2
  113. package/dist/utils/fontLoader.js +2 -7
  114. package/dist/utils/fontResolver.d.ts +7 -3
  115. package/dist/utils/fontResolver.js +6 -8
  116. package/package.json +24 -8
@@ -14,11 +14,11 @@ import { requiredWrapPolygon, serializeWrapPolygon } from "../wrapPolygon.js";
14
14
  import { serializeParagraph } from "./paragraphSerializer.js";
15
15
  import { serializeTable } from "./tableSerializer.js";
16
16
  import { serializeTextFormatting } from "./textFormattingSerializer.js";
17
- import { getSingularRunPropertyChange, serializeTrackedChangeAttributes } from "./trackedChangeAttributes.js";
17
+ import { serializeTrackedChangeAttributes } from "./trackedChangeAttributes.js";
18
18
  import { intAttr } from "./xmlUtils.js";
19
19
  import { panic } from "better-result";
20
20
  import { escapeXmlAttribute, escapeXmlText, isValidOoxmlNumericId, requiresXmlSpacePreserve } from "@stll/docx-core";
21
- import { SCHEME_COLOR_VALUE_BY_THEME_COLOR, knownThemeColor, presetLineDashToken } from "@stll/docx-core/model";
21
+ import { SCHEME_COLOR_VALUE_BY_THEME_COLOR, getSingularRunPropertyChange, knownThemeColor, presetLineDashToken } from "@stll/docx-core/model";
22
22
  //#region src/docx/serializer/runSerializer.ts
23
23
  /**
24
24
  * Run Serializer - Serialize runs to OOXML XML
@@ -1,11 +1,9 @@
1
1
  import { document_d_exports } from "../../types/document.js";
2
2
  //#region src/docx/serializer/trackedChangeAttributes.d.ts
3
3
  type SerializableTrackedChangeInfo = document_d_exports.TrackedChangeInfo | document_d_exports.PropertyChangeInfo;
4
- /** Enforces the singular `w:rPrChange` child in a run-property container. */
5
- declare const getSingularRunPropertyChange: (propertyChanges: readonly document_d_exports.RunPropertyChange[] | undefined) => document_d_exports.RunPropertyChange | undefined;
6
4
  /** Normalized, unescaped attributes in schema order for an XML element or string serializer. */
7
5
  declare const trackedChangeAttributeEntries: (info: SerializableTrackedChangeInfo) => readonly (readonly [string, string])[];
8
6
  declare const trackedChangeAttributeRecord: (info: SerializableTrackedChangeInfo) => Record<string, string>;
9
7
  declare const serializeTrackedChangeAttributes: (info: SerializableTrackedChangeInfo) => string;
10
8
  //#endregion
11
- export { getSingularRunPropertyChange, serializeTrackedChangeAttributes, trackedChangeAttributeEntries, trackedChangeAttributeRecord };
9
+ export { serializeTrackedChangeAttributes, trackedChangeAttributeEntries, trackedChangeAttributeRecord };
@@ -1,17 +1,7 @@
1
1
  import { DATE_UTC_ATTRIBUTE } from "../trackedChangeInfo.js";
2
- import { panic } from "better-result";
3
2
  import { assertValidOoxmlNumericId, escapeXmlAttribute } from "@stll/docx-core";
4
3
  import { normalizeRevisionId } from "@stll/docx-core/model";
5
4
  //#region src/docx/serializer/trackedChangeAttributes.ts
6
- /** Enforces the singular `w:rPrChange` child in a run-property container. */
7
- const getSingularRunPropertyChange = (propertyChanges) => {
8
- const propertyChangeCount = propertyChanges?.length ?? 0;
9
- if (propertyChangeCount > 1) panic("A run-property container cannot serialize more than one w:rPrChange", {
10
- elementName: "w:rPrChange",
11
- propertyChangeCount
12
- });
13
- return propertyChanges?.at(0);
14
- };
15
5
  /** Normalized, unescaped attributes in schema order for an XML element or string serializer. */
16
6
  const trackedChangeAttributeEntries = (info) => {
17
7
  assertValidOoxmlNumericId({
@@ -34,4 +24,4 @@ const trackedChangeAttributeEntries = (info) => {
34
24
  const trackedChangeAttributeRecord = (info) => Object.fromEntries(trackedChangeAttributeEntries(info));
35
25
  const serializeTrackedChangeAttributes = (info) => trackedChangeAttributeEntries(info).map(([name, value]) => `${name}="${escapeXmlAttribute(value)}"`).join(" ");
36
26
  //#endregion
37
- export { getSingularRunPropertyChange, serializeTrackedChangeAttributes, trackedChangeAttributeEntries, trackedChangeAttributeRecord };
27
+ export { serializeTrackedChangeAttributes, trackedChangeAttributeEntries, trackedChangeAttributeRecord };
@@ -0,0 +1,5 @@
1
+ //#region src/fonts/embeddedFontFingerprint.d.ts
2
+ /** Callers replace owned maps on font changes; mutating a published map is unsupported. */
3
+ declare const embeddedFontFingerprint: (families: ReadonlyMap<string, string>) => string;
4
+ //#endregion
5
+ export { embeddedFontFingerprint };
@@ -0,0 +1,18 @@
1
+ //#region src/fonts/embeddedFontFingerprint.ts
2
+ /** Immutable editor-owned lookups share content fingerprints without retaining disposed editors. */
3
+ const fingerprints = /* @__PURE__ */ new WeakMap();
4
+ /** Callers replace owned maps on font changes; mutating a published map is unsupported. */
5
+ const embeddedFontFingerprint = (families) => {
6
+ const cached = fingerprints.get(families);
7
+ if (cached !== void 0) return cached;
8
+ const entries = [...families].sort(([left], [right]) => {
9
+ if (left < right) return -1;
10
+ if (left > right) return 1;
11
+ return 0;
12
+ });
13
+ const fingerprint = JSON.stringify(entries);
14
+ fingerprints.set(families, fingerprint);
15
+ return fingerprint;
16
+ };
17
+ //#endregion
18
+ export { embeddedFontFingerprint };
@@ -66,7 +66,7 @@ declare function getEmbeddedFontFaces(parts: EmbeddedFontParts, docNonce?: strin
66
66
  /**
67
67
  * Build the original DOCX font name → scoped registered family map for a set
68
68
  * of resolved embedded faces. Callers thread this into font resolution (see
69
- * `utils/fontResolver.ts`'s `setEmbeddedFontFamilyMap`) so the document's own
69
+ * the editor-owned layout session) so the document's own
70
70
  * runs — which still carry the original name — keep resolving to the scoped
71
71
  * face that was actually registered on `document.fonts`.
72
72
  */
@@ -111,7 +111,7 @@ function getEmbeddedFontFaces(parts, docNonce = generateHexId()) {
111
111
  /**
112
112
  * Build the original DOCX font name → scoped registered family map for a set
113
113
  * of resolved embedded faces. Callers thread this into font resolution (see
114
- * `utils/fontResolver.ts`'s `setEmbeddedFontFamilyMap`) so the document's own
114
+ * the editor-owned layout session) so the document's own
115
115
  * runs — which still carry the original name — keep resolving to the scoped
116
116
  * face that was actually registered on `document.fonts`.
117
117
  */
Binary file
@@ -108,6 +108,7 @@ const buildBlockLookup = (blocks, measures) => new Map(blocks.flatMap((block, in
108
108
  }]];
109
109
  }));
110
110
  const buildStoryOptions = (flowOptions) => ({
111
+ ...flowOptions.embeddedFontFamilyMap === void 0 ? {} : { embeddedFontFamilyMap: flowOptions.embeddedFontFamilyMap },
111
112
  ...flowOptions.defaultSize === void 0 ? {} : { defaultSize: flowOptions.defaultSize },
112
113
  ...flowOptions.styles === void 0 ? {} : { styles: flowOptions.styles },
113
114
  ...flowOptions.theme === void 0 ? {} : { theme: flowOptions.theme },
package/dist/index.d.ts CHANGED
@@ -38,9 +38,9 @@ import { ImageMeta, ImageRef, MarkdownOptions, MarkdownResult } from "./markdown
38
38
  import { fromMarkdown } from "./markdown/fromMarkdown.js";
39
39
  import { toMarkdown, toMarkdownResult } from "./markdown/index.js";
40
40
  import { EmbeddedFont, EmbeddedFontParts, buildEmbeddedFontFamilyMap, extractEmbeddedFonts, getEmbeddedFontFaces, scopeEmbeddedFontFamily } from "./fonts/embeddedFonts.js";
41
- import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "./utils/fontResolver.js";
41
+ import { getGoogleFontsEnabled, setGoogleFontsEnabled } from "./utils/fontResolver.js";
42
42
  import { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError } from "./prosemirror/yjsDocumentMetadata.js";
43
43
  import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
44
44
  type Document = document_d_exports.Document;
45
45
  type DocxConformanceClass = document_d_exports.DocxConformanceClass;
46
- export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DEFAULT_OUTLINE_DEPTH, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_YJS_ATTR_SCHEMA_VERSION, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIDiagnosticBlock, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphBlock, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStatedNumbering, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioUndefinedReferencePolicy, type FolioWordDiffOptions, type FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type OutlineDepth, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, filterHeadingsByDepth, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
46
+ export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DEFAULT_OUTLINE_DEPTH, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_YJS_ATTR_SCHEMA_VERSION, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIDiagnosticBlock, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphBlock, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStatedNumbering, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioUndefinedReferencePolicy, type FolioWordDiffOptions, type FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type OutlineDepth, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, filterHeadingsByDepth, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
package/dist/index.js CHANGED
@@ -31,8 +31,8 @@ import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaSty
31
31
  import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION } from "./style-sets/types.js";
32
32
  import { currentFolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
33
33
  import { createEmptyDocument } from "./utils/createDocument.js";
34
- import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "./utils/fontResolver.js";
34
+ import { getGoogleFontsEnabled, setGoogleFontsEnabled } from "./utils/fontResolver.js";
35
35
  import { mergeDocumentContent } from "./utils/mergeDocumentContent.js";
36
36
  import { DEFAULT_OUTLINE_DEPTH, filterHeadingsByDepth } from "./utils/outlineDepth.js";
37
37
  import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
38
- export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DEFAULT_OUTLINE_DEPTH, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioContentComparisonLimitError, FolioContentInlinePresentationProjectionError, FolioYjsAttrSchemaVersionError, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, filterHeadingsByDepth, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
38
+ export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DEFAULT_OUTLINE_DEPTH, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, FOLIO_CONTENT_COMPARISON_LIMITS, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioContentComparisonLimitError, FolioContentInlinePresentationProjectionError, FolioYjsAttrSchemaVersionError, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, filterHeadingsByDepth, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
@@ -9,6 +9,8 @@ import { Node } from "prosemirror-model";
9
9
  * Options for the conversion.
10
10
  */
11
11
  type ToFlowBlocksOptions = {
12
+ /** Embedded families owned by this editor, never ambient process state. */
13
+ embeddedFontFamilyMap?: ReadonlyMap<string, string>;
12
14
  /** Default font family. */
13
15
  defaultFont?: string;
14
16
  /** Default font size in points. */
@@ -4,7 +4,7 @@ import { ToFlowBlocksOptions } from "./flowConversionShared.js";
4
4
  import "./toFlowBlocks.js";
5
5
  //#region src/layout-bridge/convert/footnoteLayout.d.ts
6
6
  type MeasureBlocksFn = (blocks: FlowBlock[], contentWidth: number) => Measure[];
7
- type ConvertFootnoteOptions = {
7
+ type ConvertFootnoteOptions = Pick<ToFlowBlocksOptions, "embeddedFontFamilyMap"> & {
8
8
  styles?: document_d_exports.StyleDefinitions | null;
9
9
  numbering?: document_d_exports.NumberingDefinitions;
10
10
  theme?: document_d_exports.Theme | null;
@@ -208,6 +208,7 @@ function convertNoteStoryToFlowBlocks(content, options, referenceMarkText) {
208
208
  if (options.defaultSize !== void 0) flowOptions.defaultSize = options.defaultSize;
209
209
  if (options.styles) flowOptions.styles = options.styles;
210
210
  if (options.theme !== void 0) flowOptions.theme = options.theme;
211
+ if (options.embeddedFontFamilyMap !== void 0) flowOptions.embeddedFontFamilyMap = options.embeddedFontFamilyMap;
211
212
  if (options.fontAlternates !== void 0) flowOptions.fontAlternates = options.fontAlternates;
212
213
  if (options.defaultTabStopTwips !== void 0) flowOptions.defaultTabStopTwips = options.defaultTabStopTwips;
213
214
  if (options.lineBreakRules) flowOptions.lineBreakRules = options.lineBreakRules;
@@ -392,6 +393,8 @@ function createFootnoteNumberRun(displayNumber, paragraph) {
392
393
  fontSize: firstFormattedRun?.fontSize ?? paragraph.attrs?.defaultFontSize ?? FOOTNOTE_FONT_SIZE,
393
394
  superscript: true
394
395
  };
396
+ const embeddedFontFamilyMap = firstFormattedRun?.embeddedFontFamilyMap ?? paragraph.attrs?.embeddedFontFamilyMap;
397
+ if (embeddedFontFamilyMap) numberRun.embeddedFontFamilyMap = embeddedFontFamilyMap;
395
398
  const fontFamily = firstFormattedRun?.fontFamily ?? paragraph.attrs?.defaultFontFamily;
396
399
  if (fontFamily) numberRun.fontFamily = fontFamily;
397
400
  const alternateFontFamily = firstFormattedRun?.fontFamily !== void 0 ? firstFormattedRun.alternateFontFamily : paragraph.attrs?.defaultAlternateFontFamily;
@@ -45,6 +45,7 @@ type ConvertHeaderFooterOptions = {
45
45
  theme?: document_d_exports.Theme | null;
46
46
  defaultSize?: number;
47
47
  fontAlternates?: ToFlowBlocksOptions["fontAlternates"];
48
+ embeddedFontFamilyMap?: ReadonlyMap<string, string>;
48
49
  measureBlocks: MeasureBlocksFn;
49
50
  /** Document-wide `w:defaultTabStop` in twips — forwarded to toFlowBlocks. */
50
51
  defaultTabStopTwips?: number;
@@ -346,6 +346,7 @@ function convertHeaderFooterToContent(headerFooter, contentWidth, metrics, optio
346
346
  if (options.defaultSize !== void 0) flowOptions.defaultSize = options.defaultSize;
347
347
  if (options.styles) flowOptions.styles = options.styles;
348
348
  if (options.theme !== void 0) flowOptions.theme = options.theme;
349
+ if (options.embeddedFontFamilyMap !== void 0) flowOptions.embeddedFontFamilyMap = options.embeddedFontFamilyMap;
349
350
  if (options.fontAlternates !== void 0) flowOptions.fontAlternates = options.fontAlternates;
350
351
  if (options.defaultTabStopTwips !== void 0) flowOptions.defaultTabStopTwips = options.defaultTabStopTwips;
351
352
  if (options.lineBreakRules) flowOptions.lineBreakRules = options.lineBreakRules;
@@ -371,6 +372,7 @@ function convertHeaderFooterPmDocToContent(pmDoc, contentWidth, metrics, options
371
372
  if (options.defaultSize !== void 0) flowOptions.defaultSize = options.defaultSize;
372
373
  if (options.styles) flowOptions.styles = options.styles;
373
374
  if (options.theme !== void 0) flowOptions.theme = options.theme;
375
+ if (options.embeddedFontFamilyMap !== void 0) flowOptions.embeddedFontFamilyMap = options.embeddedFontFamilyMap;
374
376
  if (options.fontAlternates !== void 0) flowOptions.fontAlternates = options.fontAlternates;
375
377
  if (options.defaultTabStopTwips !== void 0) flowOptions.defaultTabStopTwips = options.defaultTabStopTwips;
376
378
  if (options.lineBreakRules) flowOptions.lineBreakRules = options.lineBreakRules;
@@ -1,6 +1,7 @@
1
1
  import { getFontAlternate } from "../../fonts/fontAlternates.js";
2
2
  import { setParagraphFrame } from "../../layout-engine/paragraphFrame.js";
3
3
  import { expectParagraphAttrs } from "../../prosemirror/attrs/index.js";
4
+ import { expectBookmarkBoundaryAttrs } from "../../prosemirror/bookmarkBoundaryAttrs.js";
4
5
  import { expectTextBoxAnchorAttrs } from "../../prosemirror/textBoxAnchorAttrs.js";
5
6
  import { nextBlockId, twipsToPixels } from "./flowConversionShared.js";
6
7
  import { convertParagraphAttrs } from "./paragraphAttrs.js";
@@ -76,7 +77,13 @@ function convertParagraph(node, startPos, options, pageBreaks) {
76
77
  if (isFullyHiddenParagraph) attrs.suppressEmptyParagraphHeight = true;
77
78
  if (runs.length === 0 && expectDetachedWatermarkHostAttr(node.attrs)) attrs.suppressEmptyParagraphHeight = false;
78
79
  if (runs.length === 0 && pmAttrs._pageBreakCarrier === true && !hasVisibleParagraphPayload(attrs)) attrs.suppressEmptyParagraphHeight = true;
79
- const bookmarkNames = pmAttrs.bookmarks?.map((b) => b.name);
80
+ const bookmarkNames = pmAttrs.bookmarks?.map((b) => b.name) ?? [];
81
+ node.descendants((child) => {
82
+ if (child.type.name !== "bookmarkBoundary") return true;
83
+ const marker = expectBookmarkBoundaryAttrs(child);
84
+ if (marker.type === "start") bookmarkNames.push(marker.name);
85
+ return false;
86
+ });
80
87
  const block = {
81
88
  kind: "paragraph",
82
89
  id: nextBlockId(),
@@ -412,10 +412,34 @@ function toFlowBlocks(doc, options = {}) {
412
412
  }
413
413
  const mergedBlocks = mergeRunInParagraphs(blocks);
414
414
  const tableCellLinePitch = doc.attrs["_adjustLineHeightInTable"] === true ? "sectionGrid" : void 0;
415
- return groupParagraphFrames(coalesceTrailingPageBreakBeforeContinuousSection(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
415
+ const result = groupParagraphFrames(coalesceTrailingPageBreakBeforeContinuousSection(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
416
416
  finalLinePitchTwips: opts.finalSectionDocumentGridLinePitchTwips,
417
417
  tableCellLinePitch
418
418
  }), readFinalSectionStart(doc)), options.splitPageBreakAndParagraphMark === true, sectionBreaksWithoutMarker), nextBlockId);
419
+ if (options.embeddedFontFamilyMap) attachEmbeddedFontFamilies(result, options.embeddedFontFamilyMap);
420
+ return result;
419
421
  }
422
+ /** Attach editor-owned resolution to freshly derived blocks without changing authored data. */
423
+ const attachEmbeddedFontFamilies = (blocks, familyMap) => {
424
+ for (const block of blocks) switch (block.kind) {
425
+ case "paragraph":
426
+ for (const run of block.runs) if (run.kind !== "image" && run.kind !== "lineBreak") run.embeddedFontFamilyMap = familyMap;
427
+ block.attrs ??= {};
428
+ block.attrs.embeddedFontFamilyMap = familyMap;
429
+ if (block.attrs.listMarkerFormatting) block.attrs.listMarkerFormatting.embeddedFontFamilyMap = familyMap;
430
+ break;
431
+ case "table":
432
+ for (const row of block.rows) for (const cell of row.cells) attachEmbeddedFontFamilies(cell.blocks, familyMap);
433
+ break;
434
+ case "textBox":
435
+ attachEmbeddedFontFamilies(block.content, familyMap);
436
+ break;
437
+ case "image":
438
+ case "sectionBreak":
439
+ case "pageBreak":
440
+ case "columnBreak": break;
441
+ default: return block;
442
+ }
443
+ };
420
444
  //#endregion
421
445
  export { WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
@@ -1,7 +1,14 @@
1
+ import { embeddedFontFingerprint } from "../../fonts/embeddedFontFingerprint.js";
1
2
  import { getLineBreakProviderGeneration } from "./lineBreakProvider.js";
2
3
  import { clearFontResolvedCache } from "./measureHelpers.js";
3
4
  //#region src/layout-engine/measure/cache.ts
4
5
  /**
6
+ * Measurement Cache
7
+ *
8
+ * LRU cache for text width measurements and paragraph layout results.
9
+ * Improves performance by avoiding repeated measurements of identical content.
10
+ */
11
+ /**
5
12
  * Default max entries for text width cache
6
13
  * Large documents (30+ pages) can generate 20,000+ unique text measurements.
7
14
  * A generous default avoids cache thrashing on big docs.
@@ -176,21 +183,31 @@ const imageMeasureCacheInput = (run) => ({
176
183
  exactLineHeight: run.exactLineHeight,
177
184
  positioned: run.position !== void 0
178
185
  });
179
- const runMeasureCacheInput = (run) => {
186
+ const runMeasureCacheInput = (run, fontContextRef) => {
180
187
  switch (run.kind) {
181
188
  case "text":
182
189
  case "tab":
183
- case "lineBreak":
184
190
  case "renderedPageBreak":
185
191
  case "field":
186
- case "math": return run;
192
+ case "math": {
193
+ const { embeddedFontFamilyMap, ...formatting } = run;
194
+ return {
195
+ ...formatting,
196
+ embeddedFontFamilies: fontContextRef(embeddedFontFamilyMap)
197
+ };
198
+ }
199
+ case "lineBreak": return run;
187
200
  case "image": return imageMeasureCacheInput(run);
188
201
  default: return run;
189
202
  }
190
203
  };
191
- const paragraphAttrsMeasureCacheInput = (attrs) => {
204
+ const paragraphAttrsMeasureCacheInput = (attrs, fontContextRef) => {
192
205
  if (attrs === void 0) return void 0;
193
- const { snapToGrid, ...measurementAttrs } = attrs;
206
+ const { snapToGrid, embeddedFontFamilyMap, ...rest } = attrs;
207
+ const measurementAttrs = {
208
+ ...rest,
209
+ embeddedFontFamilies: fontContextRef(embeddedFontFamilyMap)
210
+ };
194
211
  if (measurementAttrs.documentGridLinePitch === void 0) return measurementAttrs;
195
212
  return {
196
213
  ...measurementAttrs,
@@ -199,10 +216,25 @@ const paragraphAttrsMeasureCacheInput = (attrs) => {
199
216
  };
200
217
  /** Serialize the complete, semantically normalized paragraph measurement contract into a cache key. */
201
218
  function hashParagraphBlock(block) {
219
+ const fontContexts = [];
220
+ const contextRefs = /* @__PURE__ */ new Map();
221
+ const fontContextRef = (families) => {
222
+ if (!families) return void 0;
223
+ const fingerprint = embeddedFontFingerprint(families);
224
+ const existing = contextRefs.get(fingerprint);
225
+ if (existing !== void 0) return existing;
226
+ const index = fontContexts.length;
227
+ contextRefs.set(fingerprint, index);
228
+ fontContexts.push(fingerprint);
229
+ return index;
230
+ };
231
+ const attrs = paragraphAttrsMeasureCacheInput(block.attrs, fontContextRef);
232
+ const runs = block.runs.map((run) => runMeasureCacheInput(run, fontContextRef));
202
233
  return JSON.stringify({
203
234
  lineBreakProviderGeneration: getLineBreakProviderGeneration(),
204
- attrs: paragraphAttrsMeasureCacheInput(block.attrs),
205
- runs: block.runs.map(runMeasureCacheInput)
235
+ attrs,
236
+ runs,
237
+ fontContexts
206
238
  });
207
239
  }
208
240
  /**
@@ -96,6 +96,7 @@ const WORD_SINGLE_LINE_FLOOR = 1.15;
96
96
  */
97
97
  function calculateEmptyParagraphMetrics(fontSize, spacing, fontFamily, attrs) {
98
98
  const result = calculateTypographyMetrics(fontSize, spacing, getFontMetrics({
99
+ ...attrs?.embeddedFontFamilyMap ? { embeddedFontFamilyMap: attrs.embeddedFontFamilyMap } : {},
99
100
  fontSize,
100
101
  fontFamily: fontFamily ?? "Times New Roman",
101
102
  ...attrs?.defaultAlternateFontFamily !== void 0 ? { alternateFontFamily: attrs.defaultAlternateFontFamily } : {}
@@ -13,6 +13,7 @@ declare const DEFAULT_TAB_STOP_TWIPS = 720;
13
13
  * of the paragraph do not format its number.
14
14
  */
15
15
  declare function resolveListMarkerFont(block: ParagraphBlock): {
16
+ embeddedFontFamilyMap?: ReadonlyMap<string, string>;
16
17
  fontFamily: string;
17
18
  alternateFontFamily?: string;
18
19
  fontSize: number;
@@ -27,6 +27,7 @@ function resolveListMarkerFont(block) {
27
27
  alternateFontFamily = markerFormatting.alternateFontFamily;
28
28
  }
29
29
  const base = {
30
+ ...attrs?.embeddedFontFamilyMap ? { embeddedFontFamilyMap: attrs.embeddedFontFamilyMap } : {},
30
31
  fontFamily,
31
32
  ...alternateFontFamily !== void 0 ? { alternateFontFamily } : {},
32
33
  fontSize: markerFormatting?.fontSize ?? attrs?.defaultFontSize ?? DEFAULT_FONT_SIZE,
@@ -61,8 +61,7 @@ function canvasGetFontMetrics(style) {
61
61
  const bold = style.bold ?? false;
62
62
  const italic = style.italic ?? false;
63
63
  const fontVariant = style.fontVariant;
64
- const alternateFontFamily = style.alternateFontFamily;
65
- const fontCacheFamily = alternateFontFamily ? `${fontFamily}\u0000${alternateFontFamily}` : fontFamily;
64
+ const fontCacheFamily = getResolvedData(fontFamily, style).cssFallback;
66
65
  const cached = getCachedFontMetrics(fontCacheFamily, fontSize, bold, italic, fontVariant);
67
66
  if (cached !== void 0) return {
68
67
  fontSize,
@@ -98,7 +97,7 @@ function canvasGetFontMetrics(style) {
98
97
  }
99
98
  } catch {}
100
99
  lineHeight = Math.max(lineHeight, ascent + descent);
101
- const singleLineRatio = getResolvedData(fontFamily, alternateFontFamily).singleLineRatio;
100
+ const singleLineRatio = getResolvedData(fontFamily, style).singleLineRatio;
102
101
  const result = {
103
102
  fontSize,
104
103
  ascent,
@@ -165,7 +164,7 @@ function canvasMeasureTextWidth(text, sourceStyle) {
165
164
  * takes the single-font path (no double-counting, no recursion).
166
165
  */
167
166
  function glyphAdvanceStyle(style) {
168
- const result = {};
167
+ const result = { ...style.embeddedFontFamilyMap ? { embeddedFontFamilyMap: style.embeddedFontFamilyMap } : {} };
169
168
  if (style.fontFamily !== void 0) result.fontFamily = style.fontFamily;
170
169
  if (style.alternateFontFamily !== void 0) result.alternateFontFamily = style.alternateFontFamily;
171
170
  if (style.fontSize !== void 0) result.fontSize = style.fontSize;
@@ -33,20 +33,17 @@ type ResolvedFontCache = {
33
33
  /**
34
34
  * Get the resolved font data for a font family, with caching.
35
35
  */
36
- declare function getResolvedData(fontFamily: string, alternateFontFamily?: string): ResolvedFontCache;
36
+ type ResolvedDataOptions = {
37
+ alternateFontFamily?: string | undefined;
38
+ embeddedFontFamilyMap?: ReadonlyMap<string, string> | undefined;
39
+ };
40
+ declare function getResolvedData(fontFamily: string, options?: ResolvedDataOptions): ResolvedFontCache;
37
41
  /**
38
42
  * Whether a face of `family` (a `FontFace.family`, possibly quoted) can change
39
43
  * a width this page has measured.
40
44
  */
41
45
  declare function isLayoutFontFamily(family: string): boolean;
42
- /**
43
- * Clear the resolved-font-family cache. `resolveFontFamily`'s output for a
44
- * given key can change even when the raw font names don't — e.g. when the
45
- * active document's embedded-font family map changes (see
46
- * `utils/fontResolver.ts`'s `setEmbeddedFontFamilyMap`) — so this must be
47
- * cleared whenever that happens, not just on font-name changes. Folded into
48
- * `clearAllCaches` (`./cache.ts`) so callers get it for free.
49
- */
46
+ /** Clear cached resolution after a browser font-set or font-policy change. */
50
47
  declare function clearFontResolvedCache(): void;
51
48
  /**
52
49
  * Build a CSS font string from styling properties
@@ -59,6 +59,7 @@ function buildRunFontStyle(run, fallbackFontFamily, fallbackFontSize) {
59
59
  const horizontalScale = normalizeHorizontalScalePercent(run.horizontalScale);
60
60
  return {
61
61
  fontFamily: run.fontFamily ?? fallbackFontFamily,
62
+ ...run.embeddedFontFamilyMap ? { embeddedFontFamilyMap: run.embeddedFontFamilyMap } : {},
62
63
  ...run.alternateFontFamily !== void 0 ? { alternateFontFamily: run.alternateFontFamily } : {},
63
64
  ...run.eastAsiaFontFamily !== void 0 ? { eastAsiaFontFamily: run.eastAsiaFontFamily } : {},
64
65
  ...run.eastAsiaAlternateFontFamily !== void 0 ? { eastAsiaAlternateFontFamily: run.eastAsiaAlternateFontFamily } : {},
@@ -80,19 +81,27 @@ function buildRunFontStyle(run, fallbackFontFamily, fallbackFontSize) {
80
81
  }
81
82
  /** Cache for resolved font data */
82
83
  const fontResolvedCache = /* @__PURE__ */ new Map();
83
- /**
84
- * Get the resolved font data for a font family, with caching.
85
- */
86
- function getResolvedData(fontFamily, alternateFontFamily) {
84
+ let embeddedFontResolvedCaches = /* @__PURE__ */ new WeakMap();
85
+ function getResolvedData(fontFamily, options = {}) {
86
+ const { alternateFontFamily, embeddedFontFamilyMap } = options;
87
+ let cache = fontResolvedCache;
88
+ if (embeddedFontFamilyMap) {
89
+ const owned = embeddedFontResolvedCaches.get(embeddedFontFamilyMap);
90
+ cache = owned ?? /* @__PURE__ */ new Map();
91
+ if (!owned) embeddedFontResolvedCaches.set(embeddedFontFamilyMap, cache);
92
+ }
87
93
  const cacheKey = `${fontFamily}\u0000${alternateFontFamily ?? ""}`;
88
- let cached = fontResolvedCache.get(cacheKey);
94
+ let cached = cache.get(cacheKey);
89
95
  if (cached === void 0) {
90
- const resolved = resolveFontFamily(fontFamily, alternateFontFamily);
96
+ const resolved = resolveFontFamily(fontFamily, {
97
+ alternateFontName: alternateFontFamily,
98
+ embeddedFontFamilyMap
99
+ });
91
100
  cached = {
92
101
  cssFallback: resolved.cssFallback,
93
102
  singleLineRatio: resolved.singleLineRatio
94
103
  };
95
- fontResolvedCache.set(cacheKey, cached);
104
+ cache.set(cacheKey, cached);
96
105
  for (const family of parseFontFamilyList(resolved.cssFallback)) layoutFontFamilies.add(normalizeFontFamilyName(family));
97
106
  }
98
107
  return cached;
@@ -119,19 +128,13 @@ function isLayoutFontFamily(family) {
119
128
  /**
120
129
  * Get the CSS fallback string for a font family, with caching.
121
130
  */
122
- function getResolvedFallback(fontFamily, alternateFontFamily) {
123
- return getResolvedData(fontFamily, alternateFontFamily).cssFallback;
131
+ function getResolvedFallback(fontFamily, style) {
132
+ return getResolvedData(fontFamily, style).cssFallback;
124
133
  }
125
- /**
126
- * Clear the resolved-font-family cache. `resolveFontFamily`'s output for a
127
- * given key can change even when the raw font names don't — e.g. when the
128
- * active document's embedded-font family map changes (see
129
- * `utils/fontResolver.ts`'s `setEmbeddedFontFamilyMap`) — so this must be
130
- * cleared whenever that happens, not just on font-name changes. Folded into
131
- * `clearAllCaches` (`./cache.ts`) so callers get it for free.
132
- */
134
+ /** Clear cached resolution after a browser font-set or font-policy change. */
133
135
  function clearFontResolvedCache() {
134
136
  fontResolvedCache.clear();
137
+ embeddedFontResolvedCaches = /* @__PURE__ */ new WeakMap();
135
138
  }
136
139
  /**
137
140
  * Build a CSS font string from styling properties
@@ -154,7 +157,7 @@ function buildFontString(style) {
154
157
  const fontSizePx = ptToPx(style.fontSize ?? 11);
155
158
  parts.push(`${fontSizePx}px`);
156
159
  const fontFamily = style.fontFamily ?? "Times New Roman";
157
- parts.push(getResolvedFallback(fontFamily, style.alternateFontFamily));
160
+ parts.push(getResolvedFallback(fontFamily, style));
158
161
  return parts.join(" ");
159
162
  }
160
163
  /**
@@ -169,6 +169,7 @@ function measureParagraph(block, maxWidth, options) {
169
169
  const metrics = lineFontMetrics ?? getFontMetrics({
170
170
  fontSize: paragraphFontSize,
171
171
  fontFamily: paragraphFontFamily,
172
+ ...attrs?.embeddedFontFamilyMap ? { embeddedFontFamilyMap: attrs.embeddedFontFamilyMap } : {},
172
173
  ...attrs?.defaultAlternateFontFamily !== void 0 ? { alternateFontFamily: attrs.defaultAlternateFontFamily } : {}
173
174
  });
174
175
  const finalTypography = { ...calculateTypographyMetrics(fontSize, spacing, metrics) };
@@ -402,6 +403,7 @@ function measureParagraph(block, maxWidth, options) {
402
403
  if (isMathRun(run)) {
403
404
  const style = {
404
405
  fontFamily: run.fontFamily ?? "Cambria Math",
406
+ ...run.embeddedFontFamilyMap ? { embeddedFontFamilyMap: run.embeddedFontFamilyMap } : {},
405
407
  fontSize: run.fontSize ?? 11,
406
408
  ...run.bold !== void 0 ? { bold: run.bold } : {},
407
409
  ...run.italic !== void 0 ? { italic: run.italic } : {}
@@ -13,6 +13,8 @@ declare namespace measureTypes_d_exports {
13
13
  * Font styling properties for measurement
14
14
  */
15
15
  type FontStyle = {
16
+ /** Embedded families owned by this editor, never ambient process state. */
17
+ embeddedFontFamilyMap?: ReadonlyMap<string, string>;
16
18
  fontFamily?: string;
17
19
  alternateFontFamily?: string;
18
20
  /**
@@ -13,6 +13,8 @@ type BlockId = string | number;
13
13
  * Common run formatting properties applied to text runs.
14
14
  */
15
15
  type RunFormatting = {
16
+ /** Embedded families owned by this editor, never ambient process state. */
17
+ embeddedFontFamilyMap?: ReadonlyMap<string, string>;
16
18
  bold?: boolean;
17
19
  italic?: boolean;
18
20
  /**
@@ -160,7 +162,7 @@ type RunFormatting = {
160
162
  /** Groups a suggestion's runs for accept/reject and scroll-to. */
161
163
  suggestionId?: string;
162
164
  };
163
- type ListMarkerFormatting = Pick<RunFormatting, "fontFamily" | "alternateFontFamily" | "eastAsiaFontFamily" | "eastAsiaAlternateFontFamily" | "complexScriptFontFamily" | "complexScriptAlternateFontFamily" | "fontSize" | "complexScriptFontSize" | "bold" | "complexScriptBold" | "italic" | "complexScriptItalic" | "rtl" | "forceComplexScript" | "color">;
165
+ type ListMarkerFormatting = Pick<RunFormatting, "embeddedFontFamilyMap" | "fontFamily" | "alternateFontFamily" | "eastAsiaFontFamily" | "eastAsiaAlternateFontFamily" | "complexScriptFontFamily" | "complexScriptAlternateFontFamily" | "fontSize" | "complexScriptFontSize" | "bold" | "complexScriptBold" | "italic" | "complexScriptItalic" | "rtl" | "forceComplexScript" | "color">;
164
166
  /**
165
167
  * Hyperlink information for a run.
166
168
  */
@@ -416,6 +418,7 @@ declare const isListNumPr: (value: ParagraphNumberingOverride | null | undefined
416
418
  * Paragraph block attributes.
417
419
  */
418
420
  type ParagraphAttrs = {
421
+ embeddedFontFamilyMap?: ReadonlyMap<string, string>;
419
422
  alignment?: "left" | "center" | "right" | "justify";
420
423
  /** Document-generation policy for justified line fitting. */
421
424
  justificationCompatibility?: {
@@ -93,6 +93,7 @@ type PaintPageRequest = {
93
93
  readonly options: RenderPageOptions;
94
94
  };
95
95
  type RenderPageOptions = {
96
+ embeddedFontFamilyMap?: ReadonlyMap<string, string>;
96
97
  /** Document to create elements in (default: window.document) */
97
98
  document?: Document;
98
99
  /** Bookmark name -> 1-indexed page, for resolving PAGEREF fields at paint. */