@stll/folio-core 0.11.0 → 0.13.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 (263) hide show
  1. package/dist/ai-edits/apply.d.ts +2 -1
  2. package/dist/ai-edits/apply.js +693 -63
  3. package/dist/ai-edits/block-identity.d.ts +4 -0
  4. package/dist/ai-edits/block-identity.js +9 -0
  5. package/dist/ai-edits/blockRange.d.ts +28 -1
  6. package/dist/ai-edits/blockRange.js +68 -2
  7. package/dist/ai-edits/clean-text.js +2 -1
  8. package/dist/ai-edits/headless.d.ts +4 -4
  9. package/dist/ai-edits/headless.js +9 -9
  10. package/dist/ai-edits/index.d.ts +2 -2
  11. package/dist/ai-edits/index.js +2 -2
  12. package/dist/ai-edits/read.d.ts +7 -7
  13. package/dist/ai-edits/read.js +110 -3
  14. package/dist/ai-edits/snapshot.js +21 -3
  15. package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
  16. package/dist/ai-edits/table-cell-mutations.js +238 -0
  17. package/dist/ai-edits/table-mutation-plan.d.ts +38 -0
  18. package/dist/ai-edits/table-mutation-plan.js +90 -0
  19. package/dist/ai-edits/table-row-column-mutations.d.ts +108 -0
  20. package/dist/ai-edits/table-row-column-mutations.js +300 -0
  21. package/dist/ai-edits/table-targets.d.ts +32 -0
  22. package/dist/ai-edits/table-targets.js +70 -0
  23. package/dist/ai-edits/types.d.ts +62 -1
  24. package/dist/ai-edits/word-diff.js +21 -0
  25. package/dist/compat/eigenpal.d.ts +3 -3
  26. package/dist/compat/eigenpal.js +3 -3
  27. package/dist/content-controls/mutateContentControls.js +1 -1
  28. package/dist/controller/activeEditorStory.d.ts +36 -0
  29. package/dist/controller/activeEditorStory.js +30 -0
  30. package/dist/controller/contentControlWidgetController.d.ts +55 -0
  31. package/dist/controller/contentControlWidgetController.js +141 -0
  32. package/dist/controller/fontReadiness.js +2 -0
  33. package/dist/controller/headerFooterEditorManager.js +2 -2
  34. package/dist/controller/hiddenEditorApi.js +2 -2
  35. package/dist/controller/hiddenEditorManager.d.ts +12 -1
  36. package/dist/controller/hiddenEditorManager.js +44 -12
  37. package/dist/controller/layoutPipeline.d.ts +2 -0
  38. package/dist/controller/layoutPipeline.js +17 -2
  39. package/dist/controller/noteEditorManager.d.ts +36 -0
  40. package/dist/controller/noteEditorManager.js +210 -0
  41. package/dist/document-operations.d.ts +43 -11
  42. package/dist/document-operations.js +186 -18
  43. package/dist/docx/blockContentParser.js +21 -7
  44. package/dist/docx/commentParser.js +6 -1
  45. package/dist/docx/commentRangeIntegrity.d.ts +6 -0
  46. package/dist/docx/commentRangeIntegrity.js +186 -0
  47. package/dist/docx/conformance.js +62 -1
  48. package/dist/docx/documentGrid.d.ts +8 -0
  49. package/dist/docx/documentGrid.js +8 -0
  50. package/dist/docx/drawingUtils.js +1 -1
  51. package/dist/docx/encryption/agileDecryption.js +12 -2
  52. package/dist/docx/encryption/compoundFile.js +6 -1
  53. package/dist/docx/encryption/encryptionInfo.d.ts +9 -1
  54. package/dist/docx/encryption/encryptionInfo.js +18 -2
  55. package/dist/docx/encryption/openEncryptedDocx.js +1 -1
  56. package/dist/docx/ensureParaIds.js +8 -7
  57. package/dist/docx/fieldParser.js +1 -1
  58. package/dist/docx/groupDrawingParser.js +10 -5
  59. package/dist/docx/hyperlinkParser.js +1 -1
  60. package/dist/docx/imageParser.js +10 -6
  61. package/dist/docx/metadataPrivacy.js +17 -3
  62. package/dist/docx/notePropertiesParser.js +1 -1
  63. package/dist/docx/numberingParser.js +1 -1
  64. package/dist/docx/paragraphParser.js +70 -61
  65. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  66. package/dist/docx/paragraphTextBoxEnrichment.js +67 -13
  67. package/dist/docx/paragraphTraversal.js +1 -1
  68. package/dist/docx/parser.js +3 -3
  69. package/dist/docx/rezip.js +20 -9
  70. package/dist/docx/runParser.js +17 -6
  71. package/dist/docx/sdtProperties.js +1 -1
  72. package/dist/docx/sectionParser.js +18 -5
  73. package/dist/docx/selectiveSave.js +5 -1
  74. package/dist/docx/selectiveXmlPatch.d.ts +22 -1
  75. package/dist/docx/selectiveXmlPatch.js +61 -1
  76. package/dist/docx/serializer/blockSdtSerializer.js +3 -2
  77. package/dist/docx/serializer/commentSerializer.js +5 -6
  78. package/dist/docx/serializer/documentSerializer.js +2 -2
  79. package/dist/docx/serializer/headerFooterSerializer.js +2 -2
  80. package/dist/docx/serializer/noteSerializer.js +2 -2
  81. package/dist/docx/serializer/paragraphSerializer.js +23 -15
  82. package/dist/docx/serializer/runSerializer.js +25 -21
  83. package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -1
  84. package/dist/docx/serializer/stylesSerializer.js +1 -1
  85. package/dist/docx/serializer/tableSerializer.d.ts +5 -4
  86. package/dist/docx/serializer/tableSerializer.js +26 -20
  87. package/dist/docx/serializer/xmlUtils.d.ts +13 -1
  88. package/dist/docx/serializer/xmlUtils.js +27 -1
  89. package/dist/docx/server/applyDocxXmlPatchProposal.d.ts +87 -0
  90. package/dist/docx/server/applyDocxXmlPatchProposal.js +204 -0
  91. package/dist/docx/server/boundedArchive.d.ts +14 -3
  92. package/dist/docx/server/boundedArchive.js +56 -11
  93. package/dist/docx/server/evaluateDocxXmlPatchProposal.d.ts +85 -0
  94. package/dist/docx/server/evaluateDocxXmlPatchProposal.js +361 -0
  95. package/dist/docx/server/extractDocxText.js +55 -8
  96. package/dist/docx/server/inspectDocxPackage.d.ts +70 -0
  97. package/dist/docx/server/inspectDocxPackage.js +217 -0
  98. package/dist/docx/server/validateDocxConformance.d.ts +41 -0
  99. package/dist/docx/server/validateDocxConformance.js +336 -0
  100. package/dist/docx/settingsParser.js +26 -3
  101. package/dist/docx/shapeParser.js +1 -1
  102. package/dist/docx/styleParser.js +4 -2
  103. package/dist/docx/tableParser.d.ts +8 -1
  104. package/dist/docx/tableParser.js +31 -10
  105. package/dist/docx/textBoxParser.d.ts +3 -3
  106. package/dist/docx/textBoxParser.js +16 -12
  107. package/dist/docx/unzip.js +1 -0
  108. package/dist/docx/vmlImageParser.js +11 -3
  109. package/dist/docx/xmlParser.js +11 -1
  110. package/dist/docx/xmlSafety.d.ts +5 -0
  111. package/dist/docx/xmlSafety.js +9 -0
  112. package/dist/fields/resolveFieldValues.js +1 -3
  113. package/dist/fonts/embeddedFonts.d.ts +33 -5
  114. package/dist/fonts/embeddedFonts.js +37 -8
  115. package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
  116. package/dist/i18n/messages/catalogs.gen.js +17 -0
  117. package/dist/i18n/messages/messages.gen.d.ts +1 -0
  118. package/dist/index.d.ts +3 -3
  119. package/dist/index.js +3 -3
  120. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  121. package/dist/layout-bridge/convert/footnoteLayout.js +47 -40
  122. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  123. package/dist/layout-bridge/convert/headerFooterLayout.js +3 -0
  124. package/dist/layout-bridge/convert/templatePreviewFlow.js +3 -3
  125. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
  126. package/dist/layout-bridge/convert/toFlowBlocks.js +151 -20
  127. package/dist/layout-bridge/dom/noteStoryDom.d.ts +6 -0
  128. package/dist/layout-bridge/dom/noteStoryDom.js +17 -0
  129. package/dist/layout-bridge/engine/clickToPosition.js +2 -2
  130. package/dist/layout-engine/index.d.ts +2 -2
  131. package/dist/layout-engine/index.js +58 -30
  132. package/dist/layout-engine/justificationCompatibility.d.ts +6 -0
  133. package/dist/layout-engine/justificationCompatibility.js +8 -0
  134. package/dist/layout-engine/keep-together.js +11 -1
  135. package/dist/layout-engine/measure/cache.js +23 -5
  136. package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +8 -2
  137. package/dist/layout-engine/measure/lineBreakProvider.d.ts +2 -2
  138. package/dist/layout-engine/measure/lineBreakProvider.js +56 -37
  139. package/dist/layout-engine/measure/measureBlocks.js +15 -4
  140. package/dist/layout-engine/measure/measureContainer.js +1 -1
  141. package/dist/layout-engine/measure/measureHelpers.d.ts +11 -2
  142. package/dist/layout-engine/measure/measureHelpers.js +15 -4
  143. package/dist/layout-engine/measure/measureParagraph.js +85 -25
  144. package/dist/layout-engine/measure/measureProvider.js +4 -3
  145. package/dist/layout-engine/measure/tableCellFlow.js +5 -2
  146. package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +9 -7
  147. package/dist/layout-engine/measure/textBoxParagraphLayout.js +22 -6
  148. package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +3 -1
  149. package/dist/layout-engine/measure/textMeasurementPolicy.js +7 -1
  150. package/dist/layout-engine/paginator.js +5 -1
  151. package/dist/layout-engine/paragraphSpacing.d.ts +28 -4
  152. package/dist/layout-engine/paragraphSpacing.js +107 -13
  153. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  154. package/dist/layout-engine/types.d.ts +48 -15
  155. package/dist/layout-painter/registry/modules/textBox.js +5 -1
  156. package/dist/layout-painter/renderImage.d.ts +12 -1
  157. package/dist/layout-painter/renderImage.js +21 -4
  158. package/dist/layout-painter/renderPage.d.ts +5 -2
  159. package/dist/layout-painter/renderPage.js +59 -14
  160. package/dist/layout-painter/renderParagraph.js +55 -15
  161. package/dist/layout-painter/renderTable.d.ts +5 -1
  162. package/dist/layout-painter/renderTable.js +7 -3
  163. package/dist/layout-painter/renderTextBox.d.ts +2 -1
  164. package/dist/layout-painter/renderTextBox.js +25 -14
  165. package/dist/layout-painter/renderWatermark.d.ts +1 -1
  166. package/dist/layout-painter/renderWatermark.js +2 -1
  167. package/dist/managers/DocumentLoaderManager.js +1 -1
  168. package/dist/markdown/fromMarkdown.js +1 -1
  169. package/dist/model.js +1 -1
  170. package/dist/prosemirror/attrs/index.d.ts +4 -2
  171. package/dist/prosemirror/attrs/index.js +175 -18
  172. package/dist/prosemirror/commands/comments.d.ts +79 -4
  173. package/dist/prosemirror/commands/comments.js +622 -13
  174. package/dist/prosemirror/commands/contentControls.js +1 -1
  175. package/dist/prosemirror/commands/hyperlink.js +15 -1
  176. package/dist/prosemirror/commands/image.js +7 -1
  177. package/dist/prosemirror/commands/index.d.ts +2 -2
  178. package/dist/prosemirror/commands/index.js +2 -2
  179. package/dist/prosemirror/commands/pageBreak.js +1 -1
  180. package/dist/prosemirror/commands/propertyChangeScope.d.ts +2 -2
  181. package/dist/prosemirror/commands/propertyChangeScope.js +3 -2
  182. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +9 -0
  183. package/dist/prosemirror/commands/tableCellMergeResolution.js +181 -0
  184. package/dist/prosemirror/commentIdAllocator.js +13 -3
  185. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
  186. package/dist/prosemirror/conversion/fromProseDoc.js +404 -62
  187. package/dist/prosemirror/conversion/index.js +1 -1
  188. package/dist/prosemirror/conversion/sdtAttrs.d.ts +9 -0
  189. package/dist/prosemirror/conversion/sdtAttrs.js +49 -0
  190. package/dist/prosemirror/conversion/toProseDoc.d.ts +2 -1
  191. package/dist/prosemirror/conversion/toProseDoc.js +364 -103
  192. package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
  193. package/dist/prosemirror/extensions/StarterKit.js +6 -1
  194. package/dist/prosemirror/extensions/core/ParagraphExtension.js +6 -2
  195. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
  196. package/dist/prosemirror/extensions/features/ImagePasteExtension.js +10 -2
  197. package/dist/prosemirror/extensions/features/ListExtension.js +1 -1
  198. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +10 -1
  199. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +93 -2
  200. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +2 -1
  201. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +6 -2
  202. package/dist/prosemirror/extensions/features/pasteCleanup.js +15 -2
  203. package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
  204. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +30 -4
  205. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
  206. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +70 -11
  207. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  208. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -0
  209. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +22 -0
  210. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  211. package/dist/prosemirror/extensions/nodes/TableExtension.js +14 -6
  212. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +13 -0
  213. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +41 -0
  214. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +5 -2
  215. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -1
  216. package/dist/prosemirror/index.d.ts +1 -1
  217. package/dist/prosemirror/index.js +1 -1
  218. package/dist/prosemirror/plugins/contentControlWidgets.d.ts +36 -10
  219. package/dist/prosemirror/plugins/contentControlWidgets.js +128 -94
  220. package/dist/prosemirror/plugins/revisionIds.d.ts +23 -0
  221. package/dist/prosemirror/plugins/revisionIds.js +57 -0
  222. package/dist/prosemirror/plugins/selectionTracker.js +1 -0
  223. package/dist/prosemirror/plugins/suggestionMode.js +5 -4
  224. package/dist/prosemirror/runFormattingMarkNames.d.ts +14 -0
  225. package/dist/prosemirror/runFormattingMarkNames.js +40 -0
  226. package/dist/prosemirror/schema/index.d.ts +2 -2
  227. package/dist/prosemirror/schema/marks.d.ts +30 -3
  228. package/dist/prosemirror/schema/marks.js +15 -0
  229. package/dist/prosemirror/schema/nodes.d.ts +111 -6
  230. package/dist/prosemirror/selectionState.js +1 -0
  231. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  232. package/dist/prosemirror/tableCellMergeRevision.d.ts +9 -0
  233. package/dist/prosemirror/tableCellMergeRevision.js +22 -0
  234. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +9 -0
  235. package/dist/prosemirror/textBoxAnchorAttrs.js +33 -0
  236. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +1 -1
  237. package/dist/prosemirror/utils/extractTrackedChanges.js +62 -14
  238. package/dist/prosemirror/validation.js +9 -1
  239. package/dist/render-dom/RemoteSelectionOverlay.js +2 -2
  240. package/dist/server.d.ts +7 -3
  241. package/dist/server.js +7 -3
  242. package/dist/utils/clipboard.d.ts +10 -1
  243. package/dist/utils/clipboard.js +33 -6
  244. package/dist/utils/colorResolver.d.ts +8 -1
  245. package/dist/utils/colorResolver.js +35 -5
  246. package/dist/utils/fontFamilyMerge.js +9 -11
  247. package/dist/utils/fontLoader.js +3 -2
  248. package/dist/utils/fontResolver.d.ts +2 -1
  249. package/dist/utils/fontResolver.js +31 -7
  250. package/dist/utils/fontWeights.d.ts +1 -1
  251. package/dist/utils/fontWeights.js +1 -1
  252. package/dist/utils/hexId.d.ts +11 -1
  253. package/dist/utils/hexId.js +11 -1
  254. package/dist/utils/paragraphFormattingMerge.js +1 -0
  255. package/dist/utils/sanitizeImageSrc.d.ts +21 -0
  256. package/dist/utils/sanitizeImageSrc.js +30 -0
  257. package/dist/utils/stripXmlDeclarations.d.ts +11 -0
  258. package/dist/utils/stripXmlDeclarations.js +35 -0
  259. package/dist/version-comparison.d.ts +22 -2
  260. package/dist/version-comparison.js +41 -12
  261. package/dist/watermark/index.d.ts +11 -1
  262. package/dist/watermark/index.js +22 -1
  263. package/package.json +3 -2
@@ -1,8 +1,8 @@
1
- import { findChild, findChildren, getAttribute, getLocalName, parseBooleanElement, parseNumericAttribute, parseTableMeasurementValue, parseXmlDocument } from "./xmlParser.js";
2
1
  import { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FontThemeSchema, HighlightColorSchema, LineSpacingRuleSchema, ParagraphAlignmentSchema, ShadingPatternSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
3
- import { resolveThemeFontRef } from "./themeParser.js";
2
+ import { findChild, findChildren, getAttribute, getLocalName, parseBooleanElement, parseNumericAttribute, parseTableMeasurementValue, parseXmlDocument } from "./xmlParser.js";
4
3
  import { mergeTextFormatting } from "../utils/textFormattingMerge.js";
5
4
  import { mergeParagraphFormatting } from "../utils/paragraphFormattingMerge.js";
5
+ import { resolveThemeFontRef } from "./themeParser.js";
6
6
  //#region src/docx/styleParser.ts
7
7
  /**
8
8
  * Parse text formatting properties (w:rPr)
@@ -263,6 +263,8 @@ function parseParagraphProperties(pPr, theme) {
263
263
  }
264
264
  const bidi = findChild(pPr, "w", "bidi");
265
265
  if (bidi) formatting.bidi = parseBooleanElement(bidi);
266
+ const snapToGrid = findChild(pPr, "w", "snapToGrid");
267
+ if (snapToGrid) formatting.snapToGrid = parseBooleanElement(snapToGrid);
266
268
  const spacing = findChild(pPr, "w", "spacing");
267
269
  if (spacing) {
268
270
  const before = parseNumericAttribute(spacing, "w", "before");
@@ -4,6 +4,13 @@ import { StyleMap } from "./styleParser.js";
4
4
  import { XmlElement } from "./xmlParser.js";
5
5
 
6
6
  //#region src/docx/tableParser.d.ts
7
+ /**
8
+ * Sanity cap on `w:gridSpan` (and the derived table column count). Word's
9
+ * practical column limit is 63; a hostile/corrupt value here would blow up
10
+ * every downstream structure sized by column count (TableMap, border grids,
11
+ * cell-grid arrays).
12
+ */
13
+ declare const MAX_TABLE_COLUMNS = 63;
7
14
  /**
8
15
  * Parse a table measurement (width, height, etc.)
9
16
  *
@@ -199,4 +206,4 @@ declare function getHeaderRows(table: document_d_exports.Table): document_d_expo
199
206
  */
200
207
  declare function isFloatingTable(table: document_d_exports.Table): boolean;
201
208
  //#endregion
202
- export { getHeaderRows, getTableColumnCount, getTableRowCount, getTableText, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, parseBorderSpec, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseShading, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTableRow, parseTableRowProperties };
209
+ export { MAX_TABLE_COLUMNS, getHeaderRows, getTableColumnCount, getTableRowCount, getTableText, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, parseBorderSpec, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseShading, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTableRow, parseTableRowProperties };
@@ -1,11 +1,19 @@
1
+ import { BorderStyleSchema, FloatingTableXSpecSchema, FloatingTableYSpecSchema, ShadingPatternSchema, TableCellTextDirectionSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
1
2
  import { findChild, findChildByLocalName, findChildren, getAttribute, getChildElements, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute, parseTableMeasurementValue } from "./xmlParser.js";
2
3
  import { parseBookmarkEnd, parseBookmarkStart } from "./bookmarkParser.js";
3
- import { BorderStyleSchema, FloatingTableXSpecSchema, FloatingTableYSpecSchema, ShadingPatternSchema, TableCellTextDirectionSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
4
4
  import { parseParagraph } from "./paragraphParser.js";
5
5
  import { appendBookmarkMarkerToLastParagraphInBlocks, appendBookmarkMarkerToLastParagraphInCells, prependBookmarkMarkersToFirstParagraphInBlocks, prependBookmarkMarkersToFirstParagraphInCell } from "./bookmarkPlacement.js";
6
6
  import { enrichParagraphTextBoxes } from "./paragraphTextBoxEnrichment.js";
7
+ import { normalizeRevisionId } from "@stll/docx-core/model";
7
8
  //#region src/docx/tableParser.ts
8
9
  /**
10
+ * Sanity cap on `w:gridSpan` (and the derived table column count). Word's
11
+ * practical column limit is 63; a hostile/corrupt value here would blow up
12
+ * every downstream structure sized by column count (TableMap, border grids,
13
+ * cell-grid arrays).
14
+ */
15
+ const MAX_TABLE_COLUMNS = 63;
16
+ /**
9
17
  * Parse a table measurement (width, height, etc.)
10
18
  *
11
19
  * @param element - Element with w:w and w:type attributes
@@ -32,11 +40,13 @@ function parseTrackedChangeInfo(node) {
32
40
  const parsedId = rawId ? Number.parseInt(rawId, 10) : 0;
33
41
  const author = (getAttribute(node, "w", "author") ?? "").trim();
34
42
  const date = (getAttribute(node, "w", "date") ?? "").trim();
43
+ const initials = (getAttribute(node, "w", "initials") ?? "").trim();
35
44
  const info = {
36
- id: Number.isInteger(parsedId) && parsedId >= 0 ? parsedId : 0,
45
+ id: normalizeRevisionId(parsedId),
37
46
  author: author.length > 0 ? author : "Unknown"
38
47
  };
39
48
  if (date.length > 0) info.date = date;
49
+ if (initials.length > 0) info.initials = initials;
40
50
  return info;
41
51
  }
42
52
  function parsePropertyChangeInfo(node) {
@@ -349,10 +359,20 @@ function parseTableCellStructuralChange(tcPrElement) {
349
359
  info: parseTrackedChangeInfo(deletion)
350
360
  };
351
361
  const merge = findChild(tcPrElement, "w", "cellMerge");
352
- if (merge) return {
353
- type: "tableCellMerge",
354
- info: parseTrackedChangeInfo(merge)
355
- };
362
+ if (merge) {
363
+ const verticalMerge = parseTableCellVerticalMergeRevisionValue(getAttribute(merge, "w", "vMerge"));
364
+ const verticalMergeOriginal = parseTableCellVerticalMergeRevisionValue(getAttribute(merge, "w", "vMergeOrig"));
365
+ return {
366
+ type: "tableCellMerge",
367
+ info: parseTrackedChangeInfo(merge),
368
+ ...verticalMerge !== void 0 ? { verticalMerge } : {},
369
+ ...verticalMergeOriginal !== void 0 ? { verticalMergeOriginal } : {}
370
+ };
371
+ }
372
+ }
373
+ function parseTableCellVerticalMergeRevisionValue(value) {
374
+ if (value === "cont") return "continue";
375
+ if (value === "rest") return "rest";
356
376
  }
357
377
  /**
358
378
  * Parse table row properties (w:trPr)
@@ -475,14 +495,15 @@ function parseTableCellProperties(tcPrElement) {
475
495
  const gridSpanElement = findChild(tcPrElement, "w", "gridSpan");
476
496
  if (gridSpanElement) {
477
497
  const gridSpan = parseNumericAttribute(gridSpanElement, "w", "val");
478
- if (gridSpan !== void 0 && gridSpan > 1) formatting.gridSpan = gridSpan;
498
+ if (gridSpan !== void 0 && gridSpan > 1) formatting.gridSpan = Math.min(gridSpan, 63);
479
499
  }
480
500
  const vMergeElement = findChild(tcPrElement, "w", "vMerge");
481
501
  if (vMergeElement) if (getAttribute(vMergeElement, "w", "val") === "restart") formatting.vMerge = "restart";
482
502
  else formatting.vMerge = "continue";
483
503
  if (parseBooleanElement(findChild(tcPrElement, "w", "tcFitText"))) formatting.fitText = true;
484
504
  if (parseBooleanElement(findChild(tcPrElement, "w", "noWrap"))) formatting.noWrap = true;
485
- if (parseBooleanElement(findChild(tcPrElement, "w", "hideMark"))) formatting.hideMark = true;
505
+ const hideMark = parseBooleanElement(findChild(tcPrElement, "w", "hideMark"));
506
+ if (hideMark !== void 0) formatting.hideMark = hideMark;
486
507
  const conditionalFormat = parseConditionalFormatStyle(findChild(tcPrElement, "w", "cnfStyle"));
487
508
  if (conditionalFormat) formatting.conditionalFormat = conditionalFormat;
488
509
  if (Object.keys(formatting).length === 0) return;
@@ -508,7 +529,7 @@ function parseCellContent(tcElement, styles, theme, numbering, rels, media, opti
508
529
  const localName = getLocalName(child.name);
509
530
  if (localName === "p") {
510
531
  const para = parseParagraph(child, styles, theme, numbering, rels, media, options);
511
- enrichParagraphTextBoxes(para, child, styles, theme, numbering, rels, media);
532
+ enrichParagraphTextBoxes(para, child, styles, theme, numbering, rels, media, parseTable);
512
533
  prependPendingBookmarkMarkers(para, pendingBookmarkMarkers);
513
534
  content.push(para);
514
535
  } else if (localName === "tbl") {
@@ -827,4 +848,4 @@ function isFloatingTable(table) {
827
848
  return table.formatting?.floating !== void 0;
828
849
  }
829
850
  //#endregion
830
- export { getHeaderRows, getTableColumnCount, getTableRowCount, getTableText, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, parseBorderSpec, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseShading, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTableRow, parseTableRowProperties };
851
+ export { MAX_TABLE_COLUMNS, getHeaderRows, getTableColumnCount, getTableRowCount, getTableText, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, parseBorderSpec, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseShading, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTableRow, parseTableRowProperties };
@@ -15,16 +15,16 @@ declare function extractTextBoxContentElements(txbxContent: XmlElement | null):
15
15
  /**
16
16
  * Type for the paragraph parser function to avoid circular imports
17
17
  */
18
- type ParagraphParserFn = (node: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null) => document_d_exports.Paragraph;
18
+ type ParagraphParserFn = (node: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null) => document_d_exports.Paragraph;
19
19
  /**
20
20
  * Type for the table parser function to avoid circular imports
21
21
  */
22
- type TableParserFn = (node: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile>) => document_d_exports.Table;
22
+ type TableParserFn = (node: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null) => document_d_exports.Table;
23
23
  /**
24
24
  * Parse text box content with provided parser functions
25
25
  * This avoids circular dependencies by accepting parser functions as parameters
26
26
  */
27
- declare function parseTextBoxContent(txbxContent: XmlElement | null, parseParagraph: ParagraphParserFn, parseTable: TableParserFn | null, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, _media?: Map<string, document_d_exports.MediaFile>): document_d_exports.Paragraph[];
27
+ declare function parseTextBoxContent(txbxContent: XmlElement | null, parseParagraph: ParagraphParserFn, parseTable: TableParserFn | null, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null): (document_d_exports.Paragraph | document_d_exports.Table)[];
28
28
  /**
29
29
  * Check if a drawing element contains a text box
30
30
  * Text boxes are shapes with wps:txbx content
@@ -44,20 +44,20 @@ function extractTextBoxContentElements(txbxContent) {
44
44
  * Parse text box content with provided parser functions
45
45
  * This avoids circular dependencies by accepting parser functions as parameters
46
46
  */
47
- function parseTextBoxContent(txbxContent, parseParagraph, parseTable, styles, theme, numbering, rels, _media) {
47
+ function parseTextBoxContent(txbxContent, parseParagraph, parseTable, styles, theme, numbering, rels, media) {
48
48
  if (!txbxContent) return [];
49
- const paragraphs = [];
49
+ const blocks = [];
50
50
  const children = getChildElements(txbxContent);
51
51
  for (const child of children) {
52
52
  const name = child.name || "";
53
53
  const colonIdx = name.indexOf(":");
54
54
  const localName = colonIdx !== -1 ? name.slice(colonIdx + 1) : name;
55
55
  if (localName === "p") {
56
- const paragraph = parseParagraph(child, styles, theme, numbering, rels);
57
- paragraphs.push(paragraph);
58
- } else if (localName === "tbl" && parseTable) {}
56
+ const paragraph = parseParagraph(child, styles, theme, numbering, rels, media);
57
+ blocks.push(paragraph);
58
+ } else if (localName === "tbl" && parseTable) blocks.push(parseTable(child, styles, theme, numbering, rels, media));
59
59
  }
60
- return paragraphs;
60
+ return blocks;
61
61
  }
62
62
  /**
63
63
  * Check if a drawing element contains a text box
@@ -232,16 +232,20 @@ function hasTextBoxContent(textBox) {
232
232
  * Get plain text from text box (helper for search/indexing)
233
233
  */
234
234
  function getTextBoxText(textBox) {
235
- const parts = [];
236
- for (const paragraph of textBox.content) {
235
+ return textBox.content.map(getTextBoxBlockText).join("\n");
236
+ }
237
+ const getTextBoxBlockText = (block) => {
238
+ if (block.type === "paragraph") {
237
239
  const runTexts = [];
238
- for (const item of paragraph.content) if (item.type === "run") {
240
+ for (const item of block.content) {
241
+ if (item.type !== "run") continue;
239
242
  for (const content of item.content) if (content.type === "text") runTexts.push(content.text);
240
243
  }
241
- parts.push(runTexts.join(""));
244
+ return runTexts.join("");
242
245
  }
243
- return parts.join("\n");
244
- }
246
+ if (block.type === "table") return block.rows.map((row) => row.cells.map((cell) => cell.content.map(getTextBoxBlockText).join("\n")).join(" ")).join("\n");
247
+ return block.content.map(getTextBoxBlockText).join("\n");
248
+ };
245
249
  /**
246
250
  * Resolve fill color to CSS color string
247
251
  */
@@ -261,6 +261,7 @@ function isPreservableDocxEntry(path) {
261
261
  if (!isSafeDocxPath(path)) return false;
262
262
  const lowerPath = path.toLowerCase();
263
263
  if (lowerPath.startsWith("word/media/")) return PRESERVABLE_MEDIA_MIME_TYPES.has(getMediaMimeType(path));
264
+ if (lowerPath.startsWith("docprops/thumbnail.")) return PRESERVABLE_MEDIA_MIME_TYPES.has(getMediaMimeType(path));
264
265
  if (lowerPath.startsWith("word/fonts/")) return true;
265
266
  if (!(lowerPath.endsWith(".xml") || lowerPath.endsWith(".rels"))) return false;
266
267
  return lowerPath === "[content_types].xml" || lowerPath.startsWith("_rels/") || lowerPath.startsWith("docprops/") || lowerPath.startsWith("word/") || lowerPath.startsWith("customxml/");
@@ -1,5 +1,6 @@
1
1
  import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
2
2
  import { pixelsToEmu } from "../utils/units.js";
3
+ import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
3
4
  import { resolveImageData } from "./imageParser.js";
4
5
  import { isWatermarkShape } from "./watermarkParser.js";
5
6
  //#region src/docx/vmlImageParser.ts
@@ -49,16 +50,22 @@ function cssLengthToPx(raw) {
49
50
  default: return;
50
51
  }
51
52
  }
53
+ const PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
54
+ "__proto__",
55
+ "constructor",
56
+ "prototype"
57
+ ]);
52
58
  /** Read a `style="k1:v1;k2:v2"` attribute into a lowercased key/value record. */
53
59
  function parseStyleAttr(style) {
54
- const out = {};
60
+ const out = Object.create(null);
55
61
  if (!style) return out;
56
62
  for (const decl of style.split(";")) {
57
63
  const colon = decl.indexOf(":");
58
64
  if (colon < 0) continue;
59
65
  const key = decl.slice(0, colon).trim().toLowerCase();
60
66
  const value = decl.slice(colon + 1).trim();
61
- if (key) out[key] = value;
67
+ if (!key || PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
68
+ out[key] = value;
62
69
  }
63
70
  return out;
64
71
  }
@@ -216,7 +223,8 @@ function parseVmlImageContent(pictElement, rels, media, rootXmlns = {}) {
216
223
  },
217
224
  wrap: { type: "inline" }
218
225
  };
219
- if (src) image.src = src;
226
+ const safeSrc = sanitizeImageSrc(src);
227
+ if (safeSrc) image.src = safeSrc;
220
228
  if (mimeType) image.mimeType = mimeType;
221
229
  if (filename) image.filename = filename;
222
230
  const title = getAttribute(imagedata, "o", "title");
@@ -500,6 +500,13 @@ function findAllDeep(root, namespace, localName) {
500
500
  return results;
501
501
  }
502
502
  /**
503
+ * Sanity cap on distinct `xmlns:*` declarations collected per element. Real
504
+ * documents declare a handful; a hostile element with thousands of unique
505
+ * prefixes would otherwise get replayed onto every captured `w:pict` rawXml
506
+ * subtree that inherits from it.
507
+ */
508
+ const MAX_XMLNS_DECLARATIONS_PER_ELEMENT = 64;
509
+ /**
503
510
  * Collect every `xmlns` / `xmlns:*` declaration from an element's attributes.
504
511
  *
505
512
  * The serializer's hard-coded root namespaces only cover canonical prefixes
@@ -512,7 +519,10 @@ function collectXmlnsDeclarations(element) {
512
519
  const out = {};
513
520
  const attrs = element.attributes;
514
521
  if (!attrs) return out;
515
- for (const [key, value] of Object.entries(attrs)) if ((key === "xmlns" || key.startsWith("xmlns:")) && value !== void 0) out[key] = String(value);
522
+ for (const [key, value] of Object.entries(attrs)) {
523
+ if (Object.keys(out).length >= MAX_XMLNS_DECLARATIONS_PER_ELEMENT) break;
524
+ if ((key === "xmlns" || key.startsWith("xmlns:")) && value !== void 0) out[key] = String(value);
525
+ }
516
526
  return out;
517
527
  }
518
528
  /**
@@ -0,0 +1,5 @@
1
+ //#region src/docx/xmlSafety.d.ts
2
+ type DocxXmlSafetyIssue = "doctype-forbidden" | "not-well-formed";
3
+ declare const getDocxXmlSafetyIssue: (xml: string) => DocxXmlSafetyIssue | null;
4
+ //#endregion
5
+ export { DocxXmlSafetyIssue, getDocxXmlSafetyIssue };
@@ -0,0 +1,9 @@
1
+ import { XMLValidator } from "fast-xml-parser";
2
+ //#region src/docx/xmlSafety.ts
3
+ const DOCTYPE_PATTERN = /<!DOCTYPE(?:\s|>)/iu;
4
+ const getDocxXmlSafetyIssue = (xml) => {
5
+ if (DOCTYPE_PATTERN.test(xml)) return "doctype-forbidden";
6
+ return XMLValidator.validate(xml) === true ? null : "not-well-formed";
7
+ };
8
+ //#endregion
9
+ export { getDocxXmlSafetyIssue };
@@ -196,9 +196,7 @@ function collectFieldRuns(block, out) {
196
196
  if (block.kind === "paragraph") {
197
197
  for (const run of block.runs) if (run.kind === "field") out.push(run);
198
198
  } else if (block.kind === "table") for (const row of block.rows) for (const cell of row.cells) for (const cellBlock of cell.blocks) collectFieldRuns(cellBlock, out);
199
- else if (block.kind === "textBox") {
200
- for (const paragraph of block.content) for (const run of paragraph.runs) if (run.kind === "field") out.push(run);
201
- }
199
+ else if (block.kind === "textBox") for (const child of block.content) collectFieldRuns(child, out);
202
200
  }
203
201
  //#endregion
204
202
  export { buildHeaderFooterFieldValues, fieldValuesEqual, resolveFieldValues };
@@ -15,9 +15,24 @@
15
15
  *
16
16
  * Ported from eigenpal/docx-editor (see NOTICE.md).
17
17
  */
18
+ /**
19
+ * Build the per-document scoped family name an embedded face registers
20
+ * under. `docNonce` is fresh per document load (see {@link getEmbeddedFontFaces}),
21
+ * so the same original name in two different documents (or two loads of the
22
+ * same document) never collides.
23
+ */
24
+ declare function scopeEmbeddedFontFamily(docNonce: string, originalFamily: string): string;
18
25
  /** A single de-obfuscated embedded font face, ready to register as `@font-face`. */
19
26
  type EmbeddedFont = {
20
- /** Word font name to register the face under (`w:font w:name`). */family: string; /** CSS `font-style` the face maps to (`embed*Italic` → `italic`). */
27
+ /**
28
+ * Family name to register the face under (`@font-face`/`FontFace`).
29
+ * Always a per-document SCOPED name (see {@link scopeEmbeddedFontFamily}) —
30
+ * never the raw `w:font w:name` from the DOCX. Use `originalFamily` (and
31
+ * {@link buildEmbeddedFontFamilyMap}) to resolve document runs, which
32
+ * still reference the font by its original DOCX name, to this family.
33
+ */
34
+ family: string; /** Original Word font name (`w:font w:name`), before scoping. */
35
+ originalFamily: string; /** CSS `font-style` the face maps to (`embed*Italic` → `italic`). */
21
36
  style: "normal" | "italic"; /** CSS `font-weight` the face maps to (`embedBold*` → `700`). */
22
37
  weight: 400 | 700; /** De-obfuscated OpenType/TrueType bytes (backed by a fresh, non-shared buffer). */
23
38
  bytes: Uint8Array<ArrayBuffer>; /** Whether the source face was subsetted (`w:subsetted`). */
@@ -33,14 +48,27 @@ type EmbeddedFontParts = {
33
48
  * Resolve and de-obfuscate every embedded font face declared in a font table.
34
49
  * Pure and DOM-free. Faces whose relationship or binary is missing are skipped,
35
50
  * so the result only contains faces that produced usable bytes.
51
+ *
52
+ * `docNonce` scopes every face's registered family to one document load (see
53
+ * {@link scopeEmbeddedFontFamily}); defaults to a fresh random id so callers
54
+ * that don't care about a specific value still get per-call isolation. Pass
55
+ * an explicit value for deterministic tests.
56
+ */
57
+ declare function getEmbeddedFontFaces(parts: EmbeddedFontParts, docNonce?: string): EmbeddedFont[];
58
+ /**
59
+ * Build the original DOCX font name → scoped registered family map for a set
60
+ * of resolved embedded faces. Callers thread this into font resolution (see
61
+ * `utils/fontResolver.ts`'s `setEmbeddedFontFamilyMap`) so the document's own
62
+ * runs — which still carry the original name — keep resolving to the scoped
63
+ * face that was actually registered on `document.fonts`.
36
64
  */
37
- declare function getEmbeddedFontFaces(parts: EmbeddedFontParts): EmbeddedFont[];
65
+ declare function buildEmbeddedFontFamilyMap(faces: readonly EmbeddedFont[]): Map<string, string>;
38
66
  /**
39
67
  * Extract every embedded font face from a raw `.docx` buffer. Unzips the
40
68
  * package, then resolves + de-obfuscates the faces via
41
69
  * {@link getEmbeddedFontFaces}. Returns an empty list for documents with no
42
- * embedded fonts.
70
+ * embedded fonts. See {@link getEmbeddedFontFaces} for `docNonce`.
43
71
  */
44
- declare function extractEmbeddedFonts(buffer: ArrayBuffer): Promise<EmbeddedFont[]>;
72
+ declare function extractEmbeddedFonts(buffer: ArrayBuffer, docNonce?: string): Promise<EmbeddedFont[]>;
45
73
  //#endregion
46
- export { EmbeddedFont, EmbeddedFontParts, extractEmbeddedFonts, getEmbeddedFontFaces };
74
+ export { EmbeddedFont, EmbeddedFontParts, buildEmbeddedFontFamilyMap, extractEmbeddedFonts, getEmbeddedFontFaces, scopeEmbeddedFontFamily };
@@ -1,4 +1,5 @@
1
1
  import { parseRelationships, resolveRelativePath } from "../docx/relsParser.js";
2
+ import { generateHexId } from "../utils/hexId.js";
2
3
  import { unzipDocx } from "../docx/unzip.js";
3
4
  import { deobfuscateFont, isValidFontKey } from "./fontDeobfuscation.js";
4
5
  import { parseEmbeddedFontTable } from "./embeddedFontTable.js";
@@ -19,6 +20,16 @@ import { parseEmbeddedFontTable } from "./embeddedFontTable.js";
19
20
  *
20
21
  * Ported from eigenpal/docx-editor (see NOTICE.md).
21
22
  */
23
+ const SCOPED_FAMILY_PREFIX = "folio-embedded";
24
+ /**
25
+ * Build the per-document scoped family name an embedded face registers
26
+ * under. `docNonce` is fresh per document load (see {@link getEmbeddedFontFaces}),
27
+ * so the same original name in two different documents (or two loads of the
28
+ * same document) never collides.
29
+ */
30
+ function scopeEmbeddedFontFamily(docNonce, originalFamily) {
31
+ return `${SCOPED_FAMILY_PREFIX}-${docNonce}-${originalFamily}`;
32
+ }
22
33
  /** Pairs each embed field with the CSS weight/style it renders as. */
23
34
  const EMBED_KINDS = [
24
35
  {
@@ -57,7 +68,7 @@ function lookupFontData(resolvedPath, fonts) {
57
68
  const wanted = normalizePackagePath(resolvedPath);
58
69
  for (const [path, data] of fonts) if (normalizePackagePath(path) === wanted) return data;
59
70
  }
60
- function resolveFace(family, ref, kind, fonts, rels) {
71
+ function resolveFace(originalFamily, ref, kind, fonts, rels, docNonce) {
61
72
  const target = rels.get(ref.relId)?.target;
62
73
  if (!target) return null;
63
74
  const raw = lookupFontData(resolveRelativePath(FONTTABLE_RELS_BASE_PATH, target), fonts);
@@ -65,7 +76,8 @@ function resolveFace(family, ref, kind, fonts, rels) {
65
76
  const bytes = new Uint8Array(raw);
66
77
  const data = ref.fontKey && isValidFontKey(ref.fontKey) ? deobfuscateFont(bytes, ref.fontKey) : bytes;
67
78
  return {
68
- family,
79
+ family: scopeEmbeddedFontFamily(docNonce, originalFamily),
80
+ originalFamily,
69
81
  style: kind.style,
70
82
  weight: kind.weight,
71
83
  bytes: data,
@@ -76,8 +88,13 @@ function resolveFace(family, ref, kind, fonts, rels) {
76
88
  * Resolve and de-obfuscate every embedded font face declared in a font table.
77
89
  * Pure and DOM-free. Faces whose relationship or binary is missing are skipped,
78
90
  * so the result only contains faces that produced usable bytes.
91
+ *
92
+ * `docNonce` scopes every face's registered family to one document load (see
93
+ * {@link scopeEmbeddedFontFamily}); defaults to a fresh random id so callers
94
+ * that don't care about a specific value still get per-call isolation. Pass
95
+ * an explicit value for deterministic tests.
79
96
  */
80
- function getEmbeddedFontFaces(parts) {
97
+ function getEmbeddedFontFaces(parts, docNonce = generateHexId()) {
81
98
  const entries = parseEmbeddedFontTable(parts.fontTableXml);
82
99
  if (entries.length === 0) return [];
83
100
  if (!parts.fontTableRelsXml || parts.fonts.size === 0) return [];
@@ -86,11 +103,23 @@ function getEmbeddedFontFaces(parts) {
86
103
  for (const entry of entries) for (const kind of EMBED_KINDS) {
87
104
  const ref = entry[kind.ref];
88
105
  if (!ref) continue;
89
- const face = resolveFace(entry.name, ref, kind, parts.fonts, rels);
106
+ const face = resolveFace(entry.name, ref, kind, parts.fonts, rels, docNonce);
90
107
  if (face) faces.push(face);
91
108
  }
92
109
  return faces;
93
110
  }
111
+ /**
112
+ * Build the original DOCX font name → scoped registered family map for a set
113
+ * of resolved embedded faces. Callers thread this into font resolution (see
114
+ * `utils/fontResolver.ts`'s `setEmbeddedFontFamilyMap`) so the document's own
115
+ * runs — which still carry the original name — keep resolving to the scoped
116
+ * face that was actually registered on `document.fonts`.
117
+ */
118
+ function buildEmbeddedFontFamilyMap(faces) {
119
+ const map = /* @__PURE__ */ new Map();
120
+ for (const face of faces) map.set(face.originalFamily, face.family);
121
+ return map;
122
+ }
94
123
  function findFontTableRels(allXml) {
95
124
  for (const [path, xml] of allXml) if (normalizePackagePath(path) === FONTTABLE_RELS_PATH) return xml;
96
125
  }
@@ -98,15 +127,15 @@ function findFontTableRels(allXml) {
98
127
  * Extract every embedded font face from a raw `.docx` buffer. Unzips the
99
128
  * package, then resolves + de-obfuscates the faces via
100
129
  * {@link getEmbeddedFontFaces}. Returns an empty list for documents with no
101
- * embedded fonts.
130
+ * embedded fonts. See {@link getEmbeddedFontFaces} for `docNonce`.
102
131
  */
103
- async function extractEmbeddedFonts(buffer) {
132
+ async function extractEmbeddedFonts(buffer, docNonce = generateHexId()) {
104
133
  const raw = await unzipDocx(buffer);
105
134
  return getEmbeddedFontFaces({
106
135
  fontTableXml: raw.fontTableXml,
107
136
  fontTableRelsXml: findFontTableRels(raw.allXml),
108
137
  fonts: raw.fonts
109
- });
138
+ }, docNonce);
110
139
  }
111
140
  //#endregion
112
- export { extractEmbeddedFonts, getEmbeddedFontFaces };
141
+ export { buildEmbeddedFontFamilyMap, extractEmbeddedFonts, getEmbeddedFontFaces, scopeEmbeddedFontFamily };
@@ -493,6 +493,7 @@ declare const CATALOGS: {
493
493
  readonly rowDeleted: "Row deleted";
494
494
  readonly rowInserted: "Row inserted";
495
495
  readonly rowPropertiesChanged: "Row formatting changed";
496
+ readonly runPropertiesChanged: "Text formatting changed";
496
497
  readonly tableDeleted: "Table deleted";
497
498
  readonly tableInserted: "Table inserted";
498
499
  readonly tablePropertiesChanged: "Table formatting changed";
@@ -1135,6 +1136,7 @@ declare const CATALOGS: {
1135
1136
  readonly rowDeleted: "Zeile gelöscht";
1136
1137
  readonly rowInserted: "Zeile eingefügt";
1137
1138
  readonly rowPropertiesChanged: "Zeilenformatierung geändert";
1139
+ readonly runPropertiesChanged: "Textformatierung geändert";
1138
1140
  readonly tableDeleted: "Tabelle gelöscht";
1139
1141
  readonly tableInserted: "Tabelle eingefügt";
1140
1142
  readonly tablePropertiesChanged: "Tabellenformatierung geändert";
@@ -1777,6 +1779,7 @@ declare const CATALOGS: {
1777
1779
  readonly rowDeleted: "Ligne supprimée";
1778
1780
  readonly rowInserted: "Ligne insérée";
1779
1781
  readonly rowPropertiesChanged: "Mise en forme de ligne modifiée";
1782
+ readonly runPropertiesChanged: "Mise en forme du texte modifiée";
1780
1783
  readonly tableDeleted: "Tableau supprimé";
1781
1784
  readonly tableInserted: "Tableau inséré";
1782
1785
  readonly tablePropertiesChanged: "Mise en forme de tableau modifiée";
@@ -2419,6 +2422,7 @@ declare const CATALOGS: {
2419
2422
  readonly rowDeleted: "Fila eliminada";
2420
2423
  readonly rowInserted: "Fila insertada";
2421
2424
  readonly rowPropertiesChanged: "Formato de fila cambiado";
2425
+ readonly runPropertiesChanged: "Formato de texto cambiado";
2422
2426
  readonly tableDeleted: "Tabla eliminada";
2423
2427
  readonly tableInserted: "Tabla insertada";
2424
2428
  readonly tablePropertiesChanged: "Formato de tabla cambiado";
@@ -3061,6 +3065,7 @@ declare const CATALOGS: {
3061
3065
  readonly rowDeleted: "Řádek odstraněn";
3062
3066
  readonly rowInserted: "Řádek vložen";
3063
3067
  readonly rowPropertiesChanged: "Formátování řádku změněno";
3068
+ readonly runPropertiesChanged: "Formátování textu změněno";
3064
3069
  readonly tableDeleted: "Tabulka odstraněna";
3065
3070
  readonly tableInserted: "Tabulka vložena";
3066
3071
  readonly tablePropertiesChanged: "Formátování tabulky změněno";
@@ -3703,6 +3708,7 @@ declare const CATALOGS: {
3703
3708
  readonly rowDeleted: "تم حذف الصف";
3704
3709
  readonly rowInserted: "تم إدراج الصف";
3705
3710
  readonly rowPropertiesChanged: "تم تغيير تنسيق الصف";
3711
+ readonly runPropertiesChanged: "تم تغيير تنسيق النص";
3706
3712
  readonly tableDeleted: "تم حذف الجدول";
3707
3713
  readonly tableInserted: "تم إدراج الجدول";
3708
3714
  readonly tablePropertiesChanged: "تم تغيير تنسيق الجدول";
@@ -4345,6 +4351,7 @@ declare const CATALOGS: {
4345
4351
  readonly rowDeleted: "Rida kustutatud";
4346
4352
  readonly rowInserted: "Rida lisatud";
4347
4353
  readonly rowPropertiesChanged: "Rea vormingut muudeti";
4354
+ readonly runPropertiesChanged: "Teksti vormingut muudeti";
4348
4355
  readonly tableDeleted: "Tabel kustutatud";
4349
4356
  readonly tableInserted: "Tabel lisatud";
4350
4357
  readonly tablePropertiesChanged: "Tabeli vormingut muudeti";
@@ -4987,6 +4994,7 @@ declare const CATALOGS: {
4987
4994
  readonly rowDeleted: "השורה נמחקה";
4988
4995
  readonly rowInserted: "השורה נוספה";
4989
4996
  readonly rowPropertiesChanged: "עיצוב השורה השתנה";
4997
+ readonly runPropertiesChanged: "עיצוב הטקסט השתנה";
4990
4998
  readonly tableDeleted: "הטבלה נמחקה";
4991
4999
  readonly tableInserted: "הטבלה נוספה";
4992
5000
  readonly tablePropertiesChanged: "עיצוב הטבלה השתנה";
@@ -5629,6 +5637,7 @@ declare const CATALOGS: {
5629
5637
  readonly rowDeleted: "पंक्ति हटाई गई";
5630
5638
  readonly rowInserted: "पंक्ति सम्मिलित की गई";
5631
5639
  readonly rowPropertiesChanged: "पंक्ति प्रारूपण बदला गया";
5640
+ readonly runPropertiesChanged: "पाठ स्वरूपण बदला गया";
5632
5641
  readonly tableDeleted: "तालिका हटाई गई";
5633
5642
  readonly tableInserted: "तालिका सम्मिलित की गई";
5634
5643
  readonly tablePropertiesChanged: "तालिका प्रारूपण बदला गया";
@@ -6271,6 +6280,7 @@ declare const CATALOGS: {
6271
6280
  readonly rowDeleted: "Sor törölve";
6272
6281
  readonly rowInserted: "Sor beszúrva";
6273
6282
  readonly rowPropertiesChanged: "Sorformázás megváltozott";
6283
+ readonly runPropertiesChanged: "Szövegformázás megváltozott";
6274
6284
  readonly tableDeleted: "Táblázat törölve";
6275
6285
  readonly tableInserted: "Táblázat beszúrva";
6276
6286
  readonly tablePropertiesChanged: "Táblázatformázás megváltozott";
@@ -6913,6 +6923,7 @@ declare const CATALOGS: {
6913
6923
  readonly rowDeleted: "Eilutė panaikinta";
6914
6924
  readonly rowInserted: "Eilutė įterpta";
6915
6925
  readonly rowPropertiesChanged: "Eilutės formatavimas pakeistas";
6926
+ readonly runPropertiesChanged: "Teksto formatavimas pakeistas";
6916
6927
  readonly tableDeleted: "Lentelė panaikinta";
6917
6928
  readonly tableInserted: "Lentelė įterpta";
6918
6929
  readonly tablePropertiesChanged: "Lentelės formatavimas pakeistas";
@@ -7555,6 +7566,7 @@ declare const CATALOGS: {
7555
7566
  readonly rowDeleted: "Rinda izdzēsta";
7556
7567
  readonly rowInserted: "Rinda ievietota";
7557
7568
  readonly rowPropertiesChanged: "Rindas formatējums mainīts";
7569
+ readonly runPropertiesChanged: "Teksta formatējums mainīts";
7558
7570
  readonly tableDeleted: "Tabula izdzēsta";
7559
7571
  readonly tableInserted: "Tabula ievietota";
7560
7572
  readonly tablePropertiesChanged: "Tabulas formatējums mainīts";
@@ -8197,6 +8209,7 @@ declare const CATALOGS: {
8197
8209
  readonly rowDeleted: "Usunięto wiersz";
8198
8210
  readonly rowInserted: "Wstawiono wiersz";
8199
8211
  readonly rowPropertiesChanged: "Zmieniono formatowanie wiersza";
8212
+ readonly runPropertiesChanged: "Zmieniono formatowanie tekstu";
8200
8213
  readonly tableDeleted: "Usunięto tabelę";
8201
8214
  readonly tableInserted: "Wstawiono tabelę";
8202
8215
  readonly tablePropertiesChanged: "Zmieniono formatowanie tabeli";
@@ -8839,6 +8852,7 @@ declare const CATALOGS: {
8839
8852
  readonly rowDeleted: "Linha excluída";
8840
8853
  readonly rowInserted: "Linha inserida";
8841
8854
  readonly rowPropertiesChanged: "Formatação da linha alterada";
8855
+ readonly runPropertiesChanged: "Formatação do texto alterada";
8842
8856
  readonly tableDeleted: "Tabela excluída";
8843
8857
  readonly tableInserted: "Tabela inserida";
8844
8858
  readonly tablePropertiesChanged: "Formatação da tabela alterada";
@@ -9481,6 +9495,7 @@ declare const CATALOGS: {
9481
9495
  readonly rowDeleted: "Riadok odstránený";
9482
9496
  readonly rowInserted: "Riadok vložený";
9483
9497
  readonly rowPropertiesChanged: "Formátovanie riadka zmenené";
9498
+ readonly runPropertiesChanged: "Formátovanie textu zmenené";
9484
9499
  readonly tableDeleted: "Tabuľka odstránená";
9485
9500
  readonly tableInserted: "Tabuľka vložená";
9486
9501
  readonly tablePropertiesChanged: "Formátovanie tabuľky zmenené";
@@ -10123,6 +10138,7 @@ declare const CATALOGS: {
10123
10138
  readonly rowDeleted: "Satır silindi";
10124
10139
  readonly rowInserted: "Satır eklendi";
10125
10140
  readonly rowPropertiesChanged: "Satır biçimlendirmesi değiştirildi";
10141
+ readonly runPropertiesChanged: "Metin biçimlendirmesi değiştirildi";
10126
10142
  readonly tableDeleted: "Tablo silindi";
10127
10143
  readonly tableInserted: "Tablo eklendi";
10128
10144
  readonly tablePropertiesChanged: "Tablo biçimlendirmesi değiştirildi";
@@ -10765,6 +10781,7 @@ declare const CATALOGS: {
10765
10781
  readonly rowDeleted: "已删除行";
10766
10782
  readonly rowInserted: "已插入行";
10767
10783
  readonly rowPropertiesChanged: "行格式已更改";
10784
+ readonly runPropertiesChanged: "文本格式已更改";
10768
10785
  readonly tableDeleted: "已删除表格";
10769
10786
  readonly tableInserted: "已插入表格";
10770
10787
  readonly tablePropertiesChanged: "表格格式已更改";