@stll/folio-core 0.47.7 → 0.49.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.
- package/dist/ai-edits/apply.js +565 -121
- package/dist/ai-edits/minimal-replacement.d.ts +64 -0
- package/dist/ai-edits/minimal-replacement.js +282 -0
- package/dist/controller/fontReadiness.js +3 -3
- package/dist/controller/hyphenationReadiness.d.ts +19 -0
- package/dist/controller/hyphenationReadiness.js +47 -0
- package/dist/controller/layoutPipeline.d.ts +3 -0
- package/dist/controller/layoutPipeline.js +70 -18
- package/dist/display-list/build/buildDisplayList.js +39 -12
- package/dist/display-list/build/pageFurniture.d.ts +7 -1
- package/dist/display-list/build/pageFurniture.js +21 -8
- package/dist/display-list/build/paragraphPrimitives.js +68 -11
- package/dist/display-list/build/tablePrimitives.js +10 -6
- package/dist/display-list/build/textBoxPrimitives.js +1 -1
- package/dist/display-list/build/unsupported.d.ts +2 -2
- package/dist/display-list/build/unsupported.js +0 -0
- package/dist/display-list/dom/renderDisplayListToDom.js +0 -1
- package/dist/docx/attributeRemainder.js +10 -2
- package/dist/docx/blockContentParser.d.ts +2 -0
- package/dist/docx/blockContentParser.js +79 -64
- package/dist/docx/bulletMarkers.d.ts +18 -2
- package/dist/docx/bulletMarkers.js +27 -2
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +57 -45
- package/dist/docx/containerChildren.d.ts +21 -8
- package/dist/docx/containerChildren.js +39 -9
- package/dist/docx/documentParser.d.ts +5 -1
- package/dist/docx/documentParser.js +8 -5
- package/dist/docx/documentSectionFacts.d.ts +22 -0
- package/dist/docx/documentSectionFacts.js +43 -0
- package/dist/docx/drawingGroupChildren.d.ts +60 -0
- package/dist/docx/drawingGroupChildren.js +176 -0
- package/dist/docx/drawingUtils.js +3 -0
- package/dist/docx/fieldParser.d.ts +8 -1
- package/dist/docx/fieldParser.js +47 -3
- package/dist/docx/fontTableParser.js +34 -27
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +15 -12
- package/dist/docx/groupDrawingParser.d.ts +9 -2
- package/dist/docx/groupDrawingParser.js +125 -37
- package/dist/docx/headerFooterParser.d.ts +7 -2
- package/dist/docx/headerFooterParser.js +15 -5
- package/dist/docx/hyperlinkParser.d.ts +48 -36
- package/dist/docx/hyperlinkParser.js +97 -82
- package/dist/docx/numberingParser.js +108 -84
- package/dist/docx/packageParts.d.ts +45 -1
- package/dist/docx/packageParts.js +93 -2
- package/dist/docx/paraIdAttribute.d.ts +3 -2
- package/dist/docx/paragraphParser.d.ts +5 -1
- package/dist/docx/paragraphParser.js +468 -365
- package/dist/docx/paragraphProperties.js +123 -109
- package/dist/docx/paragraphPropertySource.d.ts +6 -1
- package/dist/docx/paragraphPropertySource.js +9 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +143 -10
- package/dist/docx/parser.d.ts +7 -1
- package/dist/docx/parser.js +33 -16
- package/dist/docx/previewBudget.d.ts +55 -33
- package/dist/docx/previewBudget.js +59 -65
- package/dist/docx/rezip.js +41 -58
- package/dist/docx/runParser.d.ts +4 -1
- package/dist/docx/runParser.js +182 -184
- package/dist/docx/sdtProperties.js +87 -84
- package/dist/docx/sectionParser.js +169 -160
- package/dist/docx/selectiveSaveFlags.d.ts +10 -3
- package/dist/docx/selectiveSaveFlags.js +1 -1
- package/dist/docx/selectiveXmlPatch.d.ts +56 -34
- package/dist/docx/selectiveXmlPatch.js +222 -115
- package/dist/docx/serializer/groupTextBoxWriteBack.d.ts +12 -0
- package/dist/docx/serializer/groupTextBoxWriteBack.js +101 -0
- package/dist/docx/serializer/paragraphSerializer.js +47 -42
- package/dist/docx/serializer/runSerializer.d.ts +5 -1
- package/dist/docx/serializer/runSerializer.js +4 -3
- package/dist/docx/serializer/settingsSerializer.js +19 -1
- package/dist/docx/settingsParser.js +8 -0
- package/dist/docx/shapeAlternateContent.d.ts +25 -0
- package/dist/docx/shapeAlternateContent.js +52 -0
- package/dist/docx/streamingXmlParser.d.ts +6 -2
- package/dist/docx/streamingXmlParser.js +12 -7
- package/dist/docx/styleParser.js +34 -8
- package/dist/docx/tableParser.d.ts +21 -12
- package/dist/docx/tableParser.js +518 -441
- package/dist/docx/textBoxParser.d.ts +18 -5
- package/dist/docx/textBoxParser.js +12 -6
- package/dist/docx/verbatimCapture.d.ts +10 -8
- package/dist/docx/verbatimCapture.js +45 -2
- package/dist/docx/vmlImageParser.d.ts +15 -13
- package/dist/docx/vmlImageParser.js +75 -60
- package/dist/docx/vmlPreview.d.ts +3 -3
- package/dist/docx/vmlPreview.js +3 -4
- package/dist/docx/xmlNamespaceContext.d.ts +9 -0
- package/dist/docx/xmlNamespaceContext.js +54 -0
- package/dist/docx/xmlParser.d.ts +6 -3
- package/dist/docx/xmlParser.js +11 -41
- package/dist/docx/xmlResourceLimits.d.ts +2 -1
- package/dist/docx/xmlResourceLimits.js +4 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/headless-layout.d.ts +11 -2
- package/dist/headless-layout.js +153 -107
- package/dist/internal/headlessRevisionResolution.js +50 -13
- package/dist/internal/paragraphFormattingSerialization.js +3 -3
- package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
- package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
- package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
- package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
- package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +284 -39
- package/dist/layout-bridge/engine/hitTest.js +5 -3
- package/dist/layout-bridge/engine/selectionRects.js +5 -3
- package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
- package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +102 -14
- package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
- package/dist/layout-engine/justificationCompatibility.js +9 -5
- package/dist/layout-engine/keep-together.d.ts +15 -6
- package/dist/layout-engine/keep-together.js +43 -16
- package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
- package/dist/layout-engine/layoutInstrumentation.js +8 -1
- package/dist/layout-engine/measure/advanceComposition.js +50 -7
- package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
- package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
- package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
- package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
- package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
- package/dist/layout-engine/measure/lineBreaks.js +10 -3
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
- package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
- package/dist/layout-engine/measure/measureBlocks.js +46 -10
- package/dist/layout-engine/measure/measureContainer.js +51 -8
- package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
- package/dist/layout-engine/measure/measureHelpers.js +34 -8
- package/dist/layout-engine/measure/measureParagraph.js +143 -101
- package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
- package/dist/layout-engine/measure/smallCapsCasing.d.ts +56 -0
- package/dist/layout-engine/measure/smallCapsCasing.js +88 -0
- package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
- package/dist/layout-engine/measure/tabCalculator.js +2 -1
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +51 -19
- package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
- package/dist/layout-engine/measure/tableCellGrid.js +45 -5
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
- package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
- package/dist/layout-engine/noteAreaFlow.js +83 -0
- package/dist/layout-engine/paginator.d.ts +12 -1
- package/dist/layout-engine/paginator.js +18 -2
- package/dist/layout-engine/paragraphSpacing.d.ts +4 -2
- package/dist/layout-engine/paragraphSpacing.js +2 -1
- package/dist/layout-engine/tableRowBreak.d.ts +8 -1
- package/dist/layout-engine/tableRowBreak.js +25 -2
- package/dist/layout-engine/types.d.ts +108 -3
- package/dist/layout-engine/types.js +96 -1
- package/dist/layout-painter/index.d.ts +3 -0
- package/dist/layout-painter/renderPage.js +32 -83
- package/dist/layout-painter/renderParagraph.d.ts +6 -1
- package/dist/layout-painter/renderParagraph.js +75 -26
- package/dist/layout-painter/renderTable.js +26 -13
- package/dist/layout-painter/renderTextBox.d.ts +12 -2
- package/dist/layout-painter/renderTextBox.js +26 -2
- package/dist/prosemirror/alternateContentAttrs.d.ts +9 -0
- package/dist/prosemirror/alternateContentAttrs.js +35 -0
- package/dist/prosemirror/attrs/index.d.ts +9 -9
- package/dist/prosemirror/attrs/index.js +133 -11
- package/dist/prosemirror/commands/comments.js +51 -41
- package/dist/prosemirror/contentControlRevisions.d.ts +43 -0
- package/dist/prosemirror/contentControlRevisions.js +84 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +54 -23
- package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
- package/dist/prosemirror/conversion/markInterner.js +90 -0
- package/dist/prosemirror/conversion/toProseDoc.js +117 -58
- package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +7 -7
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -7
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +6 -3
- package/dist/prosemirror/extensions/nodes/SdtExtension.js +9 -2
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +5 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +4 -2
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/paragraphDirection.d.ts +29 -2
- package/dist/prosemirror/paragraphDirection.js +21 -2
- package/dist/prosemirror/plugins/suggestionMode.js +37 -8
- package/dist/prosemirror/rejoinRunCarriers.d.ts +27 -0
- package/dist/prosemirror/rejoinRunCarriers.js +66 -0
- package/dist/prosemirror/runIdentityAcrossRevisions.d.ts +10 -0
- package/dist/prosemirror/runIdentityAcrossRevisions.js +90 -0
- package/dist/prosemirror/schema/nodes.d.ts +50 -6
- package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
- package/dist/prosemirror/textBoxHostParagraph.js +21 -0
- package/dist/prosemirror/validation.js +91 -80
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/createDocument.js +10 -1
- package/dist/utils/scriptSegments.d.ts +33 -4
- package/dist/utils/scriptSegments.js +39 -6
- package/dist/utils/textFormattingMerge.d.ts +17 -3
- package/dist/utils/textFormattingMerge.js +18 -12
- package/dist/utils/trailingText.d.ts +22 -0
- package/dist/utils/trailingText.js +32 -0
- package/package.json +2 -2
- package/dist/layout-engine/justifiedLineFit.d.ts +0 -7
- package/dist/layout-engine/justifiedLineFit.js +0 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { convertBulletToUnicode } from "../../docx/bulletMarkers.js";
|
|
1
|
+
import { bulletMarkerFontName, convertBulletToUnicode } from "../../docx/bulletMarkers.js";
|
|
2
2
|
import { resolveDocumentGridLinePitch } from "../../docx/documentGrid.js";
|
|
3
3
|
import { getFontAlternate } from "../../fonts/fontAlternates.js";
|
|
4
4
|
import { buildPageBreakRunDescendantIndex } from "../../internal/pageBreakRunDescendantIndex.js";
|
|
@@ -17,6 +17,7 @@ import { directionIsRtl, directionToBidi } from "../../prosemirror/paragraphDire
|
|
|
17
17
|
import { resolveEffectiveRunStyleFormatting } from "../../prosemirror/runStyleFormatting.js";
|
|
18
18
|
import { parseSectionBreakType } from "../../prosemirror/sectionCarrier.js";
|
|
19
19
|
import { expectTextBoxAnchorAttrs } from "../../prosemirror/textBoxAnchorAttrs.js";
|
|
20
|
+
import { textBoxHostParagraph } from "../../prosemirror/textBoxHostParagraph.js";
|
|
20
21
|
import { assertValidProseMirrorDocument } from "../../prosemirror/validation.js";
|
|
21
22
|
import { createStyleEngine } from "../../style-engine/styleEngine.js";
|
|
22
23
|
import { normalizeShapeTextAnchor } from "../../types/documentEnumValues.js";
|
|
@@ -26,12 +27,14 @@ import { resolveThemeFont } from "../../utils/fontResolver.js";
|
|
|
26
27
|
import { resolveShadingFill } from "../../utils/formatToStyle.js";
|
|
27
28
|
import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
|
|
28
29
|
import { decodeOoxmlSymbolCharacter } from "../../utils/ooxmlSymbol.js";
|
|
30
|
+
import { mergeParagraphTabStops } from "../../utils/paragraphFormattingMerge.js";
|
|
29
31
|
import { sanitizeImageSrc } from "../../utils/sanitizeImageSrc.js";
|
|
30
32
|
import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
|
|
31
|
-
import { STYLE_TOGGLE_KEYS } from "../../utils/textFormattingMerge.js";
|
|
33
|
+
import { STYLE_TOGGLE_KEYS, mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
32
34
|
import { AUTO_PARAGRAPH_SPACING_PX, halfPointsToPixels, halfPointsToPoints, pointsToPixels } from "../../utils/units.js";
|
|
33
35
|
import { getColumns } from "../sectionColumns.js";
|
|
34
36
|
import { groupParagraphFrames } from "./paragraphFrames.js";
|
|
37
|
+
import { resolveParagraphMarkFormatting, resolveParagraphMarkOwnFormatting } from "./paragraphMarkFormatting.js";
|
|
35
38
|
import { panic } from "better-result";
|
|
36
39
|
import { headingLevelOf, paragraphNumberingLevel, paragraphNumberingReferenceId, sameStatedParagraphNumbering, statesNoBorder } from "@stll/docx-core/model";
|
|
37
40
|
//#region src/layout-bridge/convert/toFlowBlocks.ts
|
|
@@ -42,6 +45,32 @@ const expectDetachedWatermarkHostAttr = (attrs) => {
|
|
|
42
45
|
if (typeof value !== "boolean") panic("Invalid ProseMirror detached watermark host attrs:\nparagraph.attrs._detachedWatermarkHost: Expected a boolean.");
|
|
43
46
|
return value;
|
|
44
47
|
};
|
|
48
|
+
const NOTE_REFERENCE_MARK_XML = /^<(?:[^\s:/>]+:)?(?:footnoteRef|endnoteRef)[\s/>]/u;
|
|
49
|
+
/**
|
|
50
|
+
* Runs with `idKey` set, in document order: the note references a block list
|
|
51
|
+
* makes, through table cells (and tables within cells) and text boxes.
|
|
52
|
+
*/
|
|
53
|
+
function collectNoteRefs(blocks, idKey) {
|
|
54
|
+
const refs = [];
|
|
55
|
+
const walk = (containerBlocks) => {
|
|
56
|
+
for (const block of containerBlocks) if (block.kind === "paragraph") for (const run of block.runs) {
|
|
57
|
+
if (run.kind !== "text") continue;
|
|
58
|
+
const noteId = run[idKey];
|
|
59
|
+
if (noteId !== void 0) refs.push({
|
|
60
|
+
noteId,
|
|
61
|
+
pmPos: run.pmStart ?? 0
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else if (block.kind === "table") for (const row of block.rows) for (const cell of row.cells) walk(cell.blocks);
|
|
65
|
+
else if (block.kind === "textBox") walk(block.content);
|
|
66
|
+
};
|
|
67
|
+
walk(blocks);
|
|
68
|
+
return refs;
|
|
69
|
+
}
|
|
70
|
+
/** Whether captured run-child markup is a note story's `w:footnoteRef`/`w:endnoteRef`. */
|
|
71
|
+
function isNoteReferenceMarkXml(xml) {
|
|
72
|
+
return NOTE_REFERENCE_MARK_XML.test(xml);
|
|
73
|
+
}
|
|
45
74
|
/**
|
|
46
75
|
* Word's layout fallback when an imported OOXML style hierarchy never supplies
|
|
47
76
|
* `w:sz`. ECMA-376 deliberately leaves that terminal fallback to the consumer;
|
|
@@ -256,6 +285,7 @@ function extractRunFormatting(marks, theme, fontAlternates) {
|
|
|
256
285
|
const alternate = getFontAlternate(eastAsiaFont, fontAlternates);
|
|
257
286
|
if (alternate) formatting.eastAsiaAlternateFontFamily = alternate;
|
|
258
287
|
}
|
|
288
|
+
if (attrs.hint) formatting.eastAsiaHint = attrs.hint === "eastAsia";
|
|
259
289
|
const complexScriptFont = resolveComplexScriptThemeFont(attrs, theme);
|
|
260
290
|
if (complexScriptFont) {
|
|
261
291
|
formatting.complexScriptFontFamily = complexScriptFont;
|
|
@@ -564,6 +594,7 @@ function textFormattingToRunFormatting(defaultTextFormatting, theme, fontAlterna
|
|
|
564
594
|
const alternate = getFontAlternate(eastAsiaFontFamily, fontAlternates);
|
|
565
595
|
if (alternate) result.eastAsiaAlternateFontFamily = alternate;
|
|
566
596
|
}
|
|
597
|
+
if (defaultTextFormatting.fontFamily?.hint) result.eastAsiaHint = defaultTextFormatting.fontFamily.hint === "eastAsia";
|
|
567
598
|
const complexScriptFontFamily = defaultTextFormatting.fontFamily ? resolveComplexScriptThemeFont(defaultTextFormatting.fontFamily, theme) : void 0;
|
|
568
599
|
if (complexScriptFontFamily) {
|
|
569
600
|
result.complexScriptFontFamily = complexScriptFontFamily;
|
|
@@ -608,6 +639,34 @@ function textFormattingToRunFormatting(defaultTextFormatting, theme, fontAlterna
|
|
|
608
639
|
if (defaultTextFormatting.emphasisMark && defaultTextFormatting.emphasisMark !== "none") result.emphasisMark = defaultTextFormatting.emphasisMark;
|
|
609
640
|
return result;
|
|
610
641
|
}
|
|
642
|
+
const LIST_MARKER_FORMATTING_KEYS = [
|
|
643
|
+
"fontFamily",
|
|
644
|
+
"alternateFontFamily",
|
|
645
|
+
"eastAsiaFontFamily",
|
|
646
|
+
"eastAsiaAlternateFontFamily",
|
|
647
|
+
"complexScriptFontFamily",
|
|
648
|
+
"complexScriptAlternateFontFamily",
|
|
649
|
+
"fontSize",
|
|
650
|
+
"complexScriptFontSize",
|
|
651
|
+
"bold",
|
|
652
|
+
"complexScriptBold",
|
|
653
|
+
"italic",
|
|
654
|
+
"complexScriptItalic",
|
|
655
|
+
"rtl",
|
|
656
|
+
"forceComplexScript",
|
|
657
|
+
"color"
|
|
658
|
+
];
|
|
659
|
+
/**
|
|
660
|
+
* The numbering symbol's typography: the numbering level's `w:rPr` applied
|
|
661
|
+
* over the paragraph mark's run properties (ECMA-376 §17.9.24, §17.3.1.29).
|
|
662
|
+
* Text runs of the paragraph play no part.
|
|
663
|
+
*/
|
|
664
|
+
function listMarkerFormattingFor(levelFormatting, paragraphMarkFormatting, theme, fontAlternates) {
|
|
665
|
+
const runFormatting = textFormattingToRunFormatting(mergeTextFormatting(paragraphMarkFormatting, levelFormatting), theme, fontAlternates);
|
|
666
|
+
const formatting = {};
|
|
667
|
+
for (const key of LIST_MARKER_FORMATTING_KEYS) if (runFormatting[key] !== void 0) Reflect.set(formatting, key, runFormatting[key]);
|
|
668
|
+
return Object.keys(formatting).length > 0 ? formatting : void 0;
|
|
669
|
+
}
|
|
611
670
|
function paragraphRunDefaults(pmAttrs, theme, fontAlternates) {
|
|
612
671
|
return textFormattingToRunFormatting(pmAttrs.defaultTextFormatting, theme, fontAlternates);
|
|
613
672
|
}
|
|
@@ -615,7 +674,7 @@ function paragraphRunDefaults(pmAttrs, theme, fontAlternates) {
|
|
|
615
674
|
* Build an ImageRun from ProseMirror node attrs, applying conditional property assignment
|
|
616
675
|
* to satisfy exactOptionalPropertyTypes.
|
|
617
676
|
*/
|
|
618
|
-
function buildImageRun(attrs, constrained, pmStart, pmEnd, trackedChange) {
|
|
677
|
+
function buildImageRun(attrs, constrained, pmStart, pmEnd, trackedChange, forceLayoutInCell) {
|
|
619
678
|
const run = {
|
|
620
679
|
kind: "image",
|
|
621
680
|
src: attrs.src,
|
|
@@ -647,7 +706,8 @@ function buildImageRun(attrs, constrained, pmStart, pmEnd, trackedChange) {
|
|
|
647
706
|
const runBorderStyle = cssBorderStyleOf(attrs.borderStyle);
|
|
648
707
|
if (runBorderStyle) run.borderStyle = runBorderStyle;
|
|
649
708
|
if (attrs.position !== void 0) run.position = attrs.position;
|
|
650
|
-
if (
|
|
709
|
+
if (forceLayoutInCell) run.layoutInCell = true;
|
|
710
|
+
else if (attrs.anchor?.layoutInCell !== void 0) run.layoutInCell = attrs.anchor.layoutInCell;
|
|
651
711
|
if (trackedChange?.isInsertion) run.isInsertion = true;
|
|
652
712
|
if (trackedChange?.isDeletion) run.isDeletion = true;
|
|
653
713
|
if (trackedChange?.changeAuthor !== void 0) run.changeAuthor = trackedChange.changeAuthor;
|
|
@@ -790,7 +850,8 @@ function paragraphToRuns(node, startPos, _options, pageBreaks) {
|
|
|
790
850
|
return;
|
|
791
851
|
}
|
|
792
852
|
if (child.type.name === "preservedXml") {
|
|
793
|
-
const { text } = expectPreservedXmlAttrs(child);
|
|
853
|
+
const { xml, text: capturedText } = expectPreservedXmlAttrs(child);
|
|
854
|
+
const text = capturedText === "" && _options.noteReferenceMarkText !== void 0 && isNoteReferenceMarkXml(xml) ? _options.noteReferenceMarkText : capturedText;
|
|
794
855
|
if (text === "") return;
|
|
795
856
|
const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
|
|
796
857
|
applyCharacterStyleToggleFormatting({
|
|
@@ -838,7 +899,7 @@ function paragraphToRuns(node, startPos, _options, pageBreaks) {
|
|
|
838
899
|
if (!hasPaintableImageSource(attrs) && !hasRelationshipBackedImageBox(attrs)) return;
|
|
839
900
|
const constrained = constrainImageToPage(attrs.width ?? 100, attrs.height ?? 100, _options.pageContentHeight);
|
|
840
901
|
const trackedFmt = extractRunFormatting(effectiveMarks, theme, fontAlternates);
|
|
841
|
-
const run = buildImageRun(attrs, constrained, childPos, childPos + child.nodeSize, trackedFmt);
|
|
902
|
+
const run = buildImageRun(attrs, constrained, childPos, childPos + child.nodeSize, trackedFmt, _options.forceAnchorLayoutInCell);
|
|
842
903
|
runs.push(run);
|
|
843
904
|
return;
|
|
844
905
|
}
|
|
@@ -992,11 +1053,11 @@ function resolveDeletedListMarker(previousListAttrs, listCounterState) {
|
|
|
992
1053
|
const marker = computeListMarker(previousListAttrs, listCounterState);
|
|
993
1054
|
if (marker) return marker;
|
|
994
1055
|
}
|
|
995
|
-
if (previousListAttrs.listMarker) return previousListAttrs.listIsBullet ? convertBulletToUnicode(previousListAttrs.listMarker) : previousListAttrs.listMarker;
|
|
1056
|
+
if (previousListAttrs.listMarker) return previousListAttrs.listIsBullet ? convertBulletToUnicode(previousListAttrs.listMarker, bulletMarkerFontName(previousListAttrs.listMarkerFormatting)) : previousListAttrs.listMarker;
|
|
996
1057
|
if (previousListAttrs.listIsBullet) return "•";
|
|
997
1058
|
return null;
|
|
998
1059
|
}
|
|
999
|
-
function applyDeletedListMarkerAttrs(attrs, change, listCounterState, theme, fontAlternates) {
|
|
1060
|
+
function applyDeletedListMarkerAttrs(attrs, change, listCounterState, theme, fontAlternates, paragraphMarkFormatting) {
|
|
1000
1061
|
const previousListAttrs = toPreviousListAttrs(change.previousFormatting);
|
|
1001
1062
|
const marker = resolveDeletedListMarker(previousListAttrs, listCounterState);
|
|
1002
1063
|
if (!marker) return;
|
|
@@ -1004,7 +1065,8 @@ function applyDeletedListMarkerAttrs(attrs, change, listCounterState, theme, fon
|
|
|
1004
1065
|
attrs.listMarkerRevision = toListMarkerRevision("del", change.info);
|
|
1005
1066
|
if (previousListAttrs.listIsBullet !== void 0) attrs.listIsBullet = previousListAttrs.listIsBullet;
|
|
1006
1067
|
if (previousListAttrs.listMarkerHidden !== void 0) attrs.listMarkerHidden = previousListAttrs.listMarkerHidden;
|
|
1007
|
-
|
|
1068
|
+
const listMarkerFormatting = listMarkerFormattingFor(previousListAttrs.listMarkerFormatting, paragraphMarkFormatting(), theme, fontAlternates);
|
|
1069
|
+
if (listMarkerFormatting) attrs.listMarkerFormatting = listMarkerFormatting;
|
|
1008
1070
|
if (previousListAttrs.listMarkerAlignment) attrs.listMarkerAlignment = previousListAttrs.listMarkerAlignment;
|
|
1009
1071
|
if (previousListAttrs.listMarkerSuffix) attrs.listMarkerSuffix = previousListAttrs.listMarkerSuffix;
|
|
1010
1072
|
}
|
|
@@ -1041,7 +1103,7 @@ const resolveFlowAlignment = (alignment, rightToLeft) => {
|
|
|
1041
1103
|
default: return flow;
|
|
1042
1104
|
}
|
|
1043
1105
|
};
|
|
1044
|
-
function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStreams, defaultTabStopTwips }) {
|
|
1106
|
+
function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStreams, defaultTabStopTwips, paragraphMarkFormatting }) {
|
|
1045
1107
|
const attrs = {};
|
|
1046
1108
|
if (pmAttrs.alignment) attrs.alignment = resolveFlowAlignment(pmAttrs.alignment, directionIsRtl(pmAttrs.direction));
|
|
1047
1109
|
if (pmAttrs.outlineLevel !== void 0) attrs.outlineLevel = pmAttrs.outlineLevel;
|
|
@@ -1116,9 +1178,10 @@ function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStre
|
|
|
1116
1178
|
}
|
|
1117
1179
|
const shadingRgb = pmAttrs.shading?.fill?.rgb?.toUpperCase();
|
|
1118
1180
|
if (shadingRgb && shadingRgb !== "FFFFFF" && shadingRgb !== "FFFFFE") attrs.shading = `#${pmAttrs.shading?.fill?.rgb}`;
|
|
1119
|
-
|
|
1181
|
+
const tabs = mergeParagraphTabStops(pmAttrs.listLevelTabs ?? void 0, pmAttrs.tabs ?? void 0);
|
|
1182
|
+
if (tabs && tabs.length > 0) {
|
|
1120
1183
|
const rightToLeft = directionIsRtl(pmAttrs.direction);
|
|
1121
|
-
attrs.tabs =
|
|
1184
|
+
attrs.tabs = tabs.map((tab) => {
|
|
1122
1185
|
const tabStop = {
|
|
1123
1186
|
val: resolveTabAlignment(tab.alignment, rightToLeft),
|
|
1124
1187
|
pos: tab.position
|
|
@@ -1156,17 +1219,20 @@ function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStre
|
|
|
1156
1219
|
}
|
|
1157
1220
|
const resolvedMarker = applyMarkerAllCaps(advanceVisibleListMarker(pmAttrs, listCounterStreams).marker, pmAttrs.listMarkerAllCaps);
|
|
1158
1221
|
if (resolvedMarker !== null) attrs.listMarker = resolvedMarker;
|
|
1159
|
-
else if (pmAttrs.listMarker) attrs.listMarker = pmAttrs.listIsBullet ? convertBulletToUnicode(pmAttrs.listMarker) : pmAttrs.listMarker;
|
|
1222
|
+
else if (pmAttrs.listMarker) attrs.listMarker = pmAttrs.listIsBullet ? convertBulletToUnicode(pmAttrs.listMarker, bulletMarkerFontName(pmAttrs.listMarkerFormatting)) : pmAttrs.listMarker;
|
|
1160
1223
|
if (pmAttrs.listIsBullet !== void 0) attrs.listIsBullet = pmAttrs.listIsBullet;
|
|
1161
1224
|
if (pmAttrs.listMarkerHidden) attrs.listMarkerHidden = true;
|
|
1162
|
-
if (
|
|
1225
|
+
if (attrs.listMarker !== void 0 || pmAttrs.listMarkerFormatting) {
|
|
1226
|
+
const listMarkerFormatting = listMarkerFormattingFor(pmAttrs.listMarkerFormatting, paragraphMarkFormatting(), theme, fontAlternates);
|
|
1227
|
+
if (listMarkerFormatting) attrs.listMarkerFormatting = listMarkerFormatting;
|
|
1228
|
+
}
|
|
1163
1229
|
if (pmAttrs.listMarkerAlignment) attrs.listMarkerAlignment = pmAttrs.listMarkerAlignment;
|
|
1164
1230
|
if (pmAttrs.listMarkerSuffix) attrs.listMarkerSuffix = pmAttrs.listMarkerSuffix;
|
|
1165
1231
|
if (pmAttrs.listMarkerSecondSlotOffsetTwips !== void 0) attrs.listMarkerSecondSlotOffsetTwips = pmAttrs.listMarkerSecondSlotOffsetTwips;
|
|
1166
1232
|
if (!pmAttrs.numPr) {
|
|
1167
1233
|
const numberingRemovedChange = propertyChanges.find(isRemovedNumberingChange);
|
|
1168
1234
|
if (numberingRemovedChange) {
|
|
1169
|
-
applyDeletedListMarkerAttrs(attrs, numberingRemovedChange, void 0, theme, fontAlternates);
|
|
1235
|
+
applyDeletedListMarkerAttrs(attrs, numberingRemovedChange, void 0, theme, fontAlternates, paragraphMarkFormatting);
|
|
1170
1236
|
if (resolvedMarker !== null) {
|
|
1171
1237
|
attrs.listMarker = resolvedMarker;
|
|
1172
1238
|
attrs.listMarkerRevision = toListMarkerRevision("del", numberingRemovedChange.info);
|
|
@@ -1177,7 +1243,7 @@ function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStre
|
|
|
1177
1243
|
const dtf = pmAttrs.defaultTextFormatting;
|
|
1178
1244
|
if (dtf) {
|
|
1179
1245
|
if (dtf.fontSize !== void 0) attrs.defaultFontSize = dtf.fontSize / 2;
|
|
1180
|
-
if (attrs.listMarker !== void 0 && !attrs.listMarkerHidden && dtf.fontSizeCs !== void 0 && (dtf.fontSize === void 0 || dtf.fontSizeCs > dtf.fontSize)) attrs.listParagraphMarkFontSize = dtf.fontSizeCs / 2;
|
|
1246
|
+
if (attrs.listMarker !== void 0 && !attrs.listMarkerHidden && (attrs.bidi === true || dtf.rtl === true || dtf.cs === true) && dtf.fontSizeCs !== void 0 && (dtf.fontSize === void 0 || dtf.fontSizeCs > dtf.fontSize)) attrs.listParagraphMarkFontSize = dtf.fontSizeCs / 2;
|
|
1181
1247
|
if (dtf.fontFamily) {
|
|
1182
1248
|
const resolvedFamily = resolveWesternThemeFont(dtf.fontFamily, theme);
|
|
1183
1249
|
if (resolvedFamily) {
|
|
@@ -1231,6 +1297,18 @@ function hasOnlyHiddenTextRuns(runs) {
|
|
|
1231
1297
|
function hasVisibleParagraphPayload(attrs) {
|
|
1232
1298
|
return attrs.listMarker !== void 0 && !attrs.listMarkerHidden || attrs.borders?.top !== void 0 || attrs.borders?.bottom !== void 0 || attrs.borders?.left !== void 0 || attrs.borders?.right !== void 0 || attrs.borders?.between !== void 0 || attrs.borders?.bar !== void 0 || attrs.shading !== void 0;
|
|
1233
1299
|
}
|
|
1300
|
+
/** Whether any `w:pBdr` side draws a rule (`none`/`nil` sides draw nothing). */
|
|
1301
|
+
function drawsParagraphBorder(borders) {
|
|
1302
|
+
if (!borders) return false;
|
|
1303
|
+
return [
|
|
1304
|
+
borders.top,
|
|
1305
|
+
borders.bottom,
|
|
1306
|
+
borders.left,
|
|
1307
|
+
borders.right,
|
|
1308
|
+
borders.between,
|
|
1309
|
+
borders.bar
|
|
1310
|
+
].some((border) => border?.style !== void 0 && !statesNoBorder(border.style));
|
|
1311
|
+
}
|
|
1234
1312
|
function convertParagraph(node, startPos, options, pageBreaks) {
|
|
1235
1313
|
const pmAttrs = expectParagraphAttrs(node);
|
|
1236
1314
|
const runs = paragraphToRuns(node, startPos, options, pageBreaks);
|
|
@@ -1238,8 +1316,10 @@ function convertParagraph(node, startPos, options, pageBreaks) {
|
|
|
1238
1316
|
theme: options.theme,
|
|
1239
1317
|
fontAlternates: options.fontAlternates,
|
|
1240
1318
|
listCounterStreams: options.listCounterStreams,
|
|
1241
|
-
defaultTabStopTwips: options.defaultTabStopTwips
|
|
1319
|
+
defaultTabStopTwips: options.defaultTabStopTwips,
|
|
1320
|
+
paragraphMarkFormatting: () => resolveParagraphMarkFormatting(pmAttrs, options.styleResolver)
|
|
1242
1321
|
});
|
|
1322
|
+
if (options.numberingTabIgnoresIndent && attrs.listMarker !== void 0) attrs.listNumberingTabIgnoresIndent = true;
|
|
1243
1323
|
if (options.defaultFont !== void 0) attrs.defaultFontFamily ??= options.defaultFont;
|
|
1244
1324
|
if (options.defaultSize !== void 0) attrs.defaultFontSize ??= options.defaultSize;
|
|
1245
1325
|
if (options.lineBreakRules) attrs.lineBreakRules = options.lineBreakRules;
|
|
@@ -1248,8 +1328,9 @@ function convertParagraph(node, startPos, options, pageBreaks) {
|
|
|
1248
1328
|
const defaultTextFormatting = pmAttrs.defaultTextFormatting;
|
|
1249
1329
|
if (runs.length === 0 || hasOnlyVisuallyEmptyTextRuns(runs)) {
|
|
1250
1330
|
if (pmAttrs._originalFormatting && Object.entries(pmAttrs._originalFormatting).some(([key, value]) => key !== "runProperties" && value !== void 0 && value !== null)) attrs.hasDirectParagraphFormatting = true;
|
|
1251
|
-
const
|
|
1252
|
-
if (
|
|
1331
|
+
const directParagraphMarkFormatting = pmAttrs._originalFormatting?.runProperties;
|
|
1332
|
+
if (directParagraphMarkFormatting && Object.values(directParagraphMarkFormatting).some((value) => value !== void 0 && value !== null)) attrs.hasDirectParagraphMarkFormatting = true;
|
|
1333
|
+
const paragraphMarkFormatting = resolveParagraphMarkOwnFormatting(directParagraphMarkFormatting, options.styleResolver);
|
|
1253
1334
|
if (paragraphMarkFormatting?.fontSize !== void 0) attrs.defaultFontSize = paragraphMarkFormatting.fontSize / 2;
|
|
1254
1335
|
const paragraphMarkFontFamily = paragraphMarkFormatting?.fontFamily ? resolveWesternThemeFont(paragraphMarkFormatting.fontFamily, options.theme) : void 0;
|
|
1255
1336
|
if (paragraphMarkFontFamily) {
|
|
@@ -1393,14 +1474,18 @@ function splitParagraphAtPageBreaks({ pageBreaks, paragraph, splitPageBreakAndPa
|
|
|
1393
1474
|
fragmentStart = pageBreak.pmEnd;
|
|
1394
1475
|
}
|
|
1395
1476
|
const remainingRuns = partitioned.remaining;
|
|
1477
|
+
let paragraphMarkCarrier;
|
|
1396
1478
|
if (remainingRuns.length > 0) appendParagraph(remainingRuns, fragmentStart, paragraph.pmEnd ?? fragmentStart);
|
|
1397
1479
|
else if (paragraph.runs.length === 0 || splitPageBreakAndParagraphMark && pageBreaks.at(-1)?.pmEnd === (paragraph.pmEnd ?? fragmentStart) - 1) {
|
|
1398
1480
|
appendParagraph([], fragmentStart, paragraph.pmEnd ?? fragmentStart);
|
|
1399
1481
|
const carrier = result.at(-1);
|
|
1400
|
-
if (carrier?.kind === "paragraph" && !splitPageBreakAndParagraphMark && !hasVisibleParagraphPayload(carrier.attrs ?? {}))
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1482
|
+
if (carrier?.kind === "paragraph" && !splitPageBreakAndParagraphMark && !hasVisibleParagraphPayload(carrier.attrs ?? {})) {
|
|
1483
|
+
carrier.attrs = {
|
|
1484
|
+
...carrier.attrs,
|
|
1485
|
+
suppressEmptyParagraphHeight: true
|
|
1486
|
+
};
|
|
1487
|
+
paragraphMarkCarrier = carrier;
|
|
1488
|
+
}
|
|
1404
1489
|
}
|
|
1405
1490
|
const fragments = result.filter((block) => block.kind === "paragraph");
|
|
1406
1491
|
for (let index = 0; index < fragments.length; index += 1) {
|
|
@@ -1410,8 +1495,20 @@ function splitParagraphAtPageBreaks({ pageBreaks, paragraph, splitPageBreakAndPa
|
|
|
1410
1495
|
if (attrs) fragment.attrs = attrs;
|
|
1411
1496
|
else delete fragment.attrs;
|
|
1412
1497
|
}
|
|
1498
|
+
if (paragraphMarkCarrier?.attrs) paragraphMarkCarrier.attrs = withoutParagraphSpacing(paragraphMarkCarrier.attrs);
|
|
1413
1499
|
return result;
|
|
1414
1500
|
}
|
|
1501
|
+
function withoutParagraphSpacing(source) {
|
|
1502
|
+
const attrs = { ...source };
|
|
1503
|
+
if (attrs.spacing) {
|
|
1504
|
+
const { before: _before, after: _after, ...lineSpacing } = attrs.spacing;
|
|
1505
|
+
if (Object.keys(lineSpacing).length > 0) attrs.spacing = lineSpacing;
|
|
1506
|
+
else delete attrs.spacing;
|
|
1507
|
+
}
|
|
1508
|
+
delete attrs.automaticSpacing;
|
|
1509
|
+
delete attrs.spacingExplicit;
|
|
1510
|
+
return attrs;
|
|
1511
|
+
}
|
|
1415
1512
|
/**
|
|
1416
1513
|
* Word keeps a final empty body paragraph after a table as an editable anchor,
|
|
1417
1514
|
* but that final anchor does not create a page of its own. Earlier authored
|
|
@@ -1513,12 +1610,22 @@ function convertTableCell(node, startPos, options, tableCellMargins) {
|
|
|
1513
1610
|
const authoredPageBreakPosition = options.firstPageBreakRunPosition(node);
|
|
1514
1611
|
const leadingParagraph = node.firstChild?.type.name === "paragraph" && countPageBreakRuns(node) === 1 && options.firstPageBreakRunPosition(node.firstChild) === authoredPageBreakPosition ? node.firstChild : void 0;
|
|
1515
1612
|
const pageBreaks = [];
|
|
1516
|
-
|
|
1613
|
+
const convertCellChild = (child, childStart) => {
|
|
1517
1614
|
if (child.type.name === "paragraph") {
|
|
1518
|
-
const block = convertParagraph(child,
|
|
1615
|
+
const block = convertParagraph(child, childStart, options, child === leadingParagraph ? pageBreaks : void 0);
|
|
1519
1616
|
blocks.push(block);
|
|
1520
|
-
} else if (child.type.name === "table") blocks.push(convertTable(child,
|
|
1521
|
-
else if (child.type.name === "textBox") blocks.push(convertTextBoxNode(child,
|
|
1617
|
+
} else if (child.type.name === "table") blocks.push(convertTable(child, childStart, options));
|
|
1618
|
+
else if (child.type.name === "textBox") blocks.push(convertTextBoxNode(child, childStart, options));
|
|
1619
|
+
else if (child.type.name === "blockSdt") {
|
|
1620
|
+
let sdtChildStart = childStart + 1;
|
|
1621
|
+
child.forEach((sdtChild) => {
|
|
1622
|
+
convertCellChild(sdtChild, sdtChildStart);
|
|
1623
|
+
sdtChildStart += sdtChild.nodeSize;
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
node.forEach((child) => {
|
|
1628
|
+
convertCellChild(child, offset);
|
|
1522
1629
|
offset += child.nodeSize;
|
|
1523
1630
|
});
|
|
1524
1631
|
const trailingBlock = blocks.at(-1);
|
|
@@ -1669,6 +1776,8 @@ function convertTable(node, startPos, options) {
|
|
|
1669
1776
|
if (originalFormatting?.layout !== void 0) tableBlock.layout = originalFormatting.layout;
|
|
1670
1777
|
if (justification) tableBlock.justification = justification;
|
|
1671
1778
|
if (indentPx !== void 0) tableBlock.indent = indentPx;
|
|
1779
|
+
const cellSpacing = originalFormatting?.cellSpacing;
|
|
1780
|
+
if (cellSpacing?.type === "dxa" && cellSpacing.value > 0) tableBlock.cellSpacing = twipsToPixels(cellSpacing.value);
|
|
1672
1781
|
if (options.tableIndentCompatibility && !dropsAuthoredIndent) tableBlock.indentCompatibility = options.tableIndentCompatibility;
|
|
1673
1782
|
if (floatingPx) tableBlock.floating = floatingPx;
|
|
1674
1783
|
if (rightToLeft) tableBlock.bidi = true;
|
|
@@ -1718,6 +1827,44 @@ function convertImage(node, startPos, pageContentHeight) {
|
|
|
1718
1827
|
if (imageBorderStyle) imgBlock.borderStyle = imageBorderStyle;
|
|
1719
1828
|
return imgBlock;
|
|
1720
1829
|
}
|
|
1830
|
+
const EMUS_PER_PIXEL = 9525;
|
|
1831
|
+
/**
|
|
1832
|
+
* The `wp:effectExtent` of an inline (`wp:inline`) box, in unrounded pixels.
|
|
1833
|
+
*
|
|
1834
|
+
* An inline object occupies its extent plus the effect extent on every side,
|
|
1835
|
+
* so the box itself sits `l`/`t` inside the space the line gives it. On a
|
|
1836
|
+
* `wp:anchor` the position offsets already locate the shape's own extent, so
|
|
1837
|
+
* the reservation only affects wrapping and is not applied here.
|
|
1838
|
+
*/
|
|
1839
|
+
function inlineEffectExtentPx(wrapType, extent) {
|
|
1840
|
+
if (wrapType !== void 0 && wrapType !== "inline" || extent === void 0) return;
|
|
1841
|
+
const px = (emu) => Math.max(0, (emu ?? 0) / EMUS_PER_PIXEL);
|
|
1842
|
+
const resolved = {
|
|
1843
|
+
top: px(extent.top),
|
|
1844
|
+
bottom: px(extent.bottom),
|
|
1845
|
+
left: px(extent.left),
|
|
1846
|
+
right: px(extent.right)
|
|
1847
|
+
};
|
|
1848
|
+
return resolved.top === 0 && resolved.bottom === 0 && resolved.left === 0 && resolved.right === 0 ? void 0 : resolved;
|
|
1849
|
+
}
|
|
1850
|
+
const GRADIENT_POSITION_SCALE = 1e5;
|
|
1851
|
+
/**
|
|
1852
|
+
* A linear `a:gradFill` with its stop colors resolved through the theme. A path
|
|
1853
|
+
* gradient (`a:path`) is not painted: nothing here places its focus.
|
|
1854
|
+
*/
|
|
1855
|
+
function resolveLinearGradientFill(fill, theme) {
|
|
1856
|
+
const gradient = fill?.gradient;
|
|
1857
|
+
if (gradient === void 0 || gradient.type !== "linear" || gradient.stops.length === 0) return;
|
|
1858
|
+
const stops = gradient.stops.map((stop) => ({
|
|
1859
|
+
offset: Math.min(1, Math.max(0, stop.position / GRADIENT_POSITION_SCALE)),
|
|
1860
|
+
color: resolveColor(stop.color, theme)
|
|
1861
|
+
})).toSorted((left, right) => left.offset - right.offset);
|
|
1862
|
+
return {
|
|
1863
|
+
angle: gradient.angle ?? 0,
|
|
1864
|
+
scaled: gradient.scaled ?? false,
|
|
1865
|
+
stops
|
|
1866
|
+
};
|
|
1867
|
+
}
|
|
1721
1868
|
/** Convert a textBox PM node to a TextBoxBlock. */
|
|
1722
1869
|
function convertTextBoxNode(node, startPos, opts) {
|
|
1723
1870
|
const attrs = expectTextBoxAttrs(node);
|
|
@@ -1750,6 +1897,10 @@ function convertTextBoxNode(node, startPos, opts) {
|
|
|
1750
1897
|
if (attrs.autoFit !== void 0) textBox.autoFit = attrs.autoFit;
|
|
1751
1898
|
if (attrs.textWrap !== void 0) textBox.textWrap = attrs.textWrap;
|
|
1752
1899
|
if (attrs.fillColor !== void 0) textBox.fillColor = attrs.fillColor;
|
|
1900
|
+
else {
|
|
1901
|
+
const fillGradient = resolveLinearGradientFill(attrs.gradientFill, opts.theme);
|
|
1902
|
+
if (fillGradient !== void 0) textBox.fillGradient = fillGradient;
|
|
1903
|
+
}
|
|
1753
1904
|
if (attrs.outlineWidth !== void 0) textBox.outlineWidth = attrs.outlineWidth;
|
|
1754
1905
|
if (attrs.outlineColor !== void 0) textBox.outlineColor = attrs.outlineColor;
|
|
1755
1906
|
if (attrs.outlineStyle !== void 0) textBox.outlineStyle = attrs.outlineStyle;
|
|
@@ -1763,6 +1914,19 @@ function convertTextBoxNode(node, startPos, opts) {
|
|
|
1763
1914
|
if (attrs.distLeft !== void 0) textBox.distLeft = attrs.distLeft;
|
|
1764
1915
|
if (attrs.distRight !== void 0) textBox.distRight = attrs.distRight;
|
|
1765
1916
|
if (attrs.position !== void 0) textBox.position = attrs.position;
|
|
1917
|
+
const effectExtent = inlineEffectExtentPx(attrs.wrapType, attrs.wrapEffectExtentSlots?.drawing);
|
|
1918
|
+
if (effectExtent !== void 0) textBox.effectExtent = effectExtent;
|
|
1919
|
+
const host = textBoxHostParagraph(node);
|
|
1920
|
+
if (host && attrs.position === void 0 && (attrs.wrapType ?? "inline") === "inline") {
|
|
1921
|
+
const hostAttrs = expectParagraphAttrs(host);
|
|
1922
|
+
textBox.hostParagraph = convertParagraphAttrs(hostAttrs, {
|
|
1923
|
+
theme: opts.theme,
|
|
1924
|
+
fontAlternates: opts.fontAlternates,
|
|
1925
|
+
listCounterStreams: opts.listCounterStreams,
|
|
1926
|
+
defaultTabStopTwips: opts.defaultTabStopTwips,
|
|
1927
|
+
paragraphMarkFormatting: () => resolveParagraphMarkFormatting(hostAttrs, opts.styleResolver)
|
|
1928
|
+
});
|
|
1929
|
+
}
|
|
1766
1930
|
if (attrs._docxGroupId !== void 0) setTextBoxGroupId(textBox, attrs._docxGroupId);
|
|
1767
1931
|
const anchorBlockId = attrs._docxAnchorId ? opts.textBoxAnchorBlockIds.get(attrs._docxAnchorId) : void 0;
|
|
1768
1932
|
if (anchorBlockId !== void 0) Reflect.set(textBox, TEXT_BOX_ANCHOR_BLOCK_ID, anchorBlockId);
|
|
@@ -1804,8 +1968,12 @@ function applySectionStartsToBoundaries(blocks, finalSectionStart) {
|
|
|
1804
1968
|
* continuous section resumes there too. Accept both the legacy generated
|
|
1805
1969
|
* carrier and the inline atom's one-token paragraph-mark fragment; neither is
|
|
1806
1970
|
* a physical layout boundary.
|
|
1971
|
+
*
|
|
1972
|
+
* A section break in `breaksWithoutMarker` ends at an empty w:sectPr paragraph
|
|
1973
|
+
* that projected no block, so a page break just before it ends an earlier
|
|
1974
|
+
* paragraph and still starts the next page.
|
|
1807
1975
|
*/
|
|
1808
|
-
function coalesceTrailingPageBreakBeforeContinuousSection(blocks, splitPageBreakAndParagraphMark) {
|
|
1976
|
+
function coalesceTrailingPageBreakBeforeContinuousSection(blocks, splitPageBreakAndParagraphMark, breaksWithoutMarker) {
|
|
1809
1977
|
if (splitPageBreakAndParagraphMark) return [...blocks];
|
|
1810
1978
|
const result = [];
|
|
1811
1979
|
for (let index = 0; index < blocks.length; index += 1) {
|
|
@@ -1815,8 +1983,8 @@ function coalesceTrailingPageBreakBeforeContinuousSection(blocks, splitPageBreak
|
|
|
1815
1983
|
const isLegacyGeneratedCarrier = block?.kind === "pageBreak" && carrier?.kind === "paragraph" && carrier.runs.length === 0 && block.pmStart !== void 0 && block.pmStart === carrier.pmStart && carrier.pmStart === carrier.pmEnd;
|
|
1816
1984
|
const isInlineParagraphMarkCarrier = block?.kind === "pageBreak" && carrier?.kind === "paragraph" && carrier.runs.length === 0 && block.pmEnd !== void 0 && carrier.pmStart === block.pmEnd && carrier.pmEnd === block.pmEnd + 1;
|
|
1817
1985
|
const isUnresolvedInsertion = block?.kind === "pageBreak" && block.isInsertion === true;
|
|
1818
|
-
if (block?.kind === "pageBreak" && !isUnresolvedInsertion && carrier?.kind === "sectionBreak" && carrier.type === "continuous") continue;
|
|
1819
|
-
if (block?.kind === "pageBreak" && !isUnresolvedInsertion && (isLegacyGeneratedCarrier || isInlineParagraphMarkCarrier) && section?.kind === "sectionBreak" && section.type === "continuous") {
|
|
1986
|
+
if (block?.kind === "pageBreak" && !isUnresolvedInsertion && carrier?.kind === "sectionBreak" && carrier.type === "continuous" && !breaksWithoutMarker.has(carrier.id)) continue;
|
|
1987
|
+
if (block?.kind === "pageBreak" && !isUnresolvedInsertion && (isLegacyGeneratedCarrier || isInlineParagraphMarkCarrier) && section?.kind === "sectionBreak" && section.type === "continuous" && !breaksWithoutMarker.has(section.id)) {
|
|
1820
1988
|
index += 1;
|
|
1821
1989
|
continue;
|
|
1822
1990
|
}
|
|
@@ -1884,6 +2052,7 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
1884
2052
|
},
|
|
1885
2053
|
firstPageBreakRunPosition,
|
|
1886
2054
|
textBoxAnchorBlockIds: /* @__PURE__ */ new Map(),
|
|
2055
|
+
numberingTabIgnoresIndent: doc.attrs["_doNotUseIndentAsNumberingTabStop"] === true,
|
|
1887
2056
|
styleResolver: createStyleEngine(options.styles),
|
|
1888
2057
|
numberedRefResults: resolveNumberedRefFields(doc, {
|
|
1889
2058
|
listCounterState: cloneListCounterState(listCounterState),
|
|
@@ -1917,11 +2086,72 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
1917
2086
|
const pageBreaks = [];
|
|
1918
2087
|
const paragraph = convertParagraph(node, pos, opts, pageBreaks);
|
|
1919
2088
|
if (stripLeadingLineBreak && paragraph.runs.at(0)?.kind === "lineBreak") paragraph.runs.shift();
|
|
1920
|
-
|
|
2089
|
+
const projected = splitParagraphAtPageBreaks({
|
|
1921
2090
|
pageBreaks,
|
|
1922
2091
|
paragraph,
|
|
1923
2092
|
splitPageBreakAndParagraphMark: options.splitPageBreakAndParagraphMark === true
|
|
1924
|
-
})
|
|
2093
|
+
});
|
|
2094
|
+
if (pageBreaks.length > 0) placeTextBoxAnchorsBeforePageBreaks(node, pos, projected);
|
|
2095
|
+
for (const block of projected) trackedPush(block);
|
|
2096
|
+
};
|
|
2097
|
+
/** Blocks emitted before the current section's first block. */
|
|
2098
|
+
let sectionStartBlockCount = 0;
|
|
2099
|
+
/** Section breaks whose empty w:sectPr paragraph projected no block. */
|
|
2100
|
+
const sectionBreaksWithoutMarker = /* @__PURE__ */ new Set();
|
|
2101
|
+
/**
|
|
2102
|
+
* The page break a text box anchored in an earlier part of its paragraph
|
|
2103
|
+
* must be laid out before, keyed by `_docxAnchorId`.
|
|
2104
|
+
*/
|
|
2105
|
+
const textBoxPageBreakByAnchorId = /* @__PURE__ */ new Map();
|
|
2106
|
+
/** Text boxes held back until every block is projected. */
|
|
2107
|
+
const textBoxesBeforePageBreak = /* @__PURE__ */ new Map();
|
|
2108
|
+
/**
|
|
2109
|
+
* An anchored object sits on the page holding its anchor run. When that run
|
|
2110
|
+
* precedes a `w:br w:type="page"` in the same paragraph, the object belongs
|
|
2111
|
+
* to the page the break ends. Either way its paragraph-relative position is
|
|
2112
|
+
* measured from the part of the paragraph holding the anchor.
|
|
2113
|
+
*/
|
|
2114
|
+
const placeTextBoxAnchorsBeforePageBreaks = (node, pos, projected) => {
|
|
2115
|
+
let breakIndex = 0;
|
|
2116
|
+
node.descendants((child, childOffset) => {
|
|
2117
|
+
if (child.type.name !== "textBoxAnchor") return true;
|
|
2118
|
+
const anchorPos = pos + 1 + childOffset;
|
|
2119
|
+
while (breakIndex < projected.length) {
|
|
2120
|
+
const block = projected[breakIndex];
|
|
2121
|
+
if (block?.kind === "pageBreak" && (block.pmStart ?? 0) > anchorPos) break;
|
|
2122
|
+
breakIndex += 1;
|
|
2123
|
+
}
|
|
2124
|
+
const { anchorId } = expectTextBoxAnchorAttrs(child);
|
|
2125
|
+
const pageBreak = projected[breakIndex];
|
|
2126
|
+
if (pageBreak?.kind === "pageBreak") textBoxPageBreakByAnchorId.set(anchorId, pageBreak);
|
|
2127
|
+
const anchorFragment = pageBreak ? projected[breakIndex - 1] : projected.at(-1);
|
|
2128
|
+
if (anchorFragment?.kind === "paragraph") opts.textBoxAnchorBlockIds.set(anchorId, anchorFragment.id);
|
|
2129
|
+
else opts.textBoxAnchorBlockIds.delete(anchorId);
|
|
2130
|
+
return false;
|
|
2131
|
+
});
|
|
2132
|
+
};
|
|
2133
|
+
const pushTextBox = (node, pos) => {
|
|
2134
|
+
const textBox = convertTextBoxNode(node, pos, opts);
|
|
2135
|
+
const anchorId = expectTextBoxAttrs(node)._docxAnchorId;
|
|
2136
|
+
const pageBreak = anchorId === void 0 ? void 0 : textBoxPageBreakByAnchorId.get(anchorId);
|
|
2137
|
+
if (!pageBreak) {
|
|
2138
|
+
trackedPush(textBox);
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
tagBlockWithSdtStack(textBox);
|
|
2142
|
+
const heldBack = textBoxesBeforePageBreak.get(pageBreak);
|
|
2143
|
+
if (heldBack) heldBack.push(textBox);
|
|
2144
|
+
else textBoxesBeforePageBreak.set(pageBreak, [textBox]);
|
|
2145
|
+
};
|
|
2146
|
+
/** Put every held-back text box just before its page break, in one pass. */
|
|
2147
|
+
const releaseTextBoxesBeforePageBreaks = () => {
|
|
2148
|
+
if (textBoxesBeforePageBreak.size === 0) return;
|
|
2149
|
+
const inFlowOrder = blocks.splice(0);
|
|
2150
|
+
for (const block of inFlowOrder) {
|
|
2151
|
+
const heldBack = block.kind === "pageBreak" ? textBoxesBeforePageBreak.get(block) : void 0;
|
|
2152
|
+
for (const textBox of heldBack ?? []) blocks.push(textBox);
|
|
2153
|
+
blocks.push(block);
|
|
2154
|
+
}
|
|
1925
2155
|
};
|
|
1926
2156
|
const trailingPageBreakSectionPositions = /* @__PURE__ */ new Set();
|
|
1927
2157
|
const consumedPageBreakPositions = /* @__PURE__ */ new Set();
|
|
@@ -2004,7 +2234,11 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
2004
2234
|
const hasListFormatting = pmAttrs.numPr !== null && pmAttrs.numPr !== void 0 || pmAttrs.listMarker !== null && pmAttrs.listMarker !== void 0;
|
|
2005
2235
|
const firstChild = node.firstChild;
|
|
2006
2236
|
const startsWithColumnBreak = firstChild?.type.name === "hardBreak" && expectHardBreakAttrs(firstChild).breakType === "column";
|
|
2007
|
-
|
|
2237
|
+
const isStandaloneColumnBreak = node.childCount === 1 && startsWithColumnBreak;
|
|
2238
|
+
const isEmptySectionMark = hasSectionBreak && node.content.size === 0;
|
|
2239
|
+
const opensSection = blocks.length === sectionStartBlockCount;
|
|
2240
|
+
let markerDropped = false;
|
|
2241
|
+
if (isStandaloneColumnBreak) {
|
|
2008
2242
|
const columnBreak = {
|
|
2009
2243
|
kind: "columnBreak",
|
|
2010
2244
|
id: nextBlockId(),
|
|
@@ -2021,7 +2255,12 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
2021
2255
|
};
|
|
2022
2256
|
trackedPush(columnBreak);
|
|
2023
2257
|
pushParagraphProjection(node, pos, true);
|
|
2024
|
-
} else if (
|
|
2258
|
+
} else if (!isEmptySectionMark) pushParagraphProjection(node, pos);
|
|
2259
|
+
else if (hasListFormatting || drawsParagraphBorder(pmAttrs.borders) || opensSection) {
|
|
2260
|
+
pushParagraphProjection(node, pos);
|
|
2261
|
+
const mark = blocks.at(-1);
|
|
2262
|
+
if (!opensSection && mark?.kind === "paragraph" && mark.attrs?.pageBreakBefore) delete mark.attrs.pageBreakBefore;
|
|
2263
|
+
} else markerDropped = true;
|
|
2025
2264
|
if (hasSectionBreak) {
|
|
2026
2265
|
if (trailingPageBreakSectionPositions.has(pos)) {
|
|
2027
2266
|
const sourceParagraph = blocks.at(-1);
|
|
@@ -2093,6 +2332,8 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
2093
2332
|
if (columns) sectionBreak.columns = columns;
|
|
2094
2333
|
}
|
|
2095
2334
|
trackedPush(sectionBreak);
|
|
2335
|
+
sectionStartBlockCount = blocks.length;
|
|
2336
|
+
if (markerDropped) sectionBreaksWithoutMarker.add(sectionBreak.id);
|
|
2096
2337
|
}
|
|
2097
2338
|
break;
|
|
2098
2339
|
}
|
|
@@ -2105,7 +2346,7 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
2105
2346
|
break;
|
|
2106
2347
|
}
|
|
2107
2348
|
case "textBox":
|
|
2108
|
-
|
|
2349
|
+
pushTextBox(node, pos);
|
|
2109
2350
|
break;
|
|
2110
2351
|
case "horizontalRule":
|
|
2111
2352
|
case "pageBreak": {
|
|
@@ -2125,15 +2366,19 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
2125
2366
|
doc.forEach((node, nodeOffset) => {
|
|
2126
2367
|
visit(node, offset + nodeOffset);
|
|
2127
2368
|
});
|
|
2369
|
+
releaseTextBoxesBeforePageBreaks();
|
|
2128
2370
|
reserveLeadingEmptyOutlineHeight(blocks);
|
|
2129
|
-
|
|
2130
|
-
|
|
2371
|
+
const trailingEndnoteIds = options.trailingEndnoteIds;
|
|
2372
|
+
if (!(trailingEndnoteIds !== void 0 && trailingEndnoteIds.size > 0 && collectNoteRefs(blocks, "endnoteRefId").some(({ noteId }) => trailingEndnoteIds.has(noteId)))) {
|
|
2373
|
+
suppressFinalEmptyParagraphAfterTable(blocks);
|
|
2374
|
+
suppressFinalParagraphInRepeatedEmptySuffix(blocks);
|
|
2375
|
+
}
|
|
2131
2376
|
const mergedBlocks = mergeRunInParagraphs(blocks);
|
|
2132
2377
|
const tableCellLinePitch = doc.attrs["_adjustLineHeightInTable"] === true ? "sectionGrid" : void 0;
|
|
2133
2378
|
return groupParagraphFrames(coalesceTrailingPageBreakBeforeContinuousSection(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
|
|
2134
2379
|
finalLinePitchTwips: opts.finalSectionDocumentGridLinePitchTwips,
|
|
2135
2380
|
tableCellLinePitch
|
|
2136
|
-
}), readFinalSectionStart(doc)), options.splitPageBreakAndParagraphMark === true), nextBlockId);
|
|
2381
|
+
}), readFinalSectionStart(doc)), options.splitPageBreakAndParagraphMark === true, sectionBreaksWithoutMarker), nextBlockId);
|
|
2137
2382
|
}
|
|
2138
2383
|
function applySectionDocumentGrid(blocks, { finalLinePitchTwips, tableCellLinePitch }) {
|
|
2139
2384
|
const result = [...blocks];
|
|
@@ -2234,4 +2479,4 @@ function mergeRunInParagraphs(blocks) {
|
|
|
2234
2479
|
return out;
|
|
2235
2480
|
}
|
|
2236
2481
|
//#endregion
|
|
2237
|
-
export { WORD_UNSPECIFIED_FONT_SIZE, convertBorderSpecToLayout, formatCounter, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
|
|
2482
|
+
export { WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, isNoteReferenceMarkXml, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getHeaderRowsHeight } from "../../layout-engine/index.js";
|
|
2
2
|
import { measuredLineRangeHeight } from "../../layout-engine/lineFlow.js";
|
|
3
3
|
import { getTableCellContentWidth } from "../../layout-engine/measure/tableCellFloating.js";
|
|
4
|
-
import { buildTableCellGrid, buildTableCellPlacements } from "../../layout-engine/measure/tableCellGrid.js";
|
|
4
|
+
import { buildTableCellGrid, buildTableCellPlacements, getTableCellSpacingInsetsY } from "../../layout-engine/measure/tableCellGrid.js";
|
|
5
5
|
import { resolveTableCellPadding } from "../../layout-engine/types.js";
|
|
6
6
|
//#region src/layout-bridge/engine/hitTest.ts
|
|
7
7
|
/**
|
|
@@ -222,7 +222,8 @@ function hitTestTableCell(pageHit, blocks, measures, pagePoint) {
|
|
|
222
222
|
const cellPlacements = buildTableCellPlacements({
|
|
223
223
|
grid: buildTableCellGrid(tableBlock.rows, tableMeasure.columnWidths.length),
|
|
224
224
|
columnWidths: tableMeasure.columnWidths,
|
|
225
|
-
bidi: tableBlock.bidi === true
|
|
225
|
+
bidi: tableBlock.bidi === true,
|
|
226
|
+
cellSpacing: tableBlock.cellSpacing
|
|
226
227
|
});
|
|
227
228
|
let nearestDistance = Infinity;
|
|
228
229
|
for (let c = 0; c < row.cells.length; c++) {
|
|
@@ -267,7 +268,8 @@ function hitTestTableCell(pageHit, blocks, measures, pagePoint) {
|
|
|
267
268
|
const cellLocalX = localX - cellLeft - padLeft;
|
|
268
269
|
const cellContentWidth = getTableCellContentWidth(cell, cellMeasure);
|
|
269
270
|
const clipOffset = isClickOnHeader ? 0 : tableFragment.topClip ?? 0;
|
|
270
|
-
const
|
|
271
|
+
const cellSpacingTop = getTableCellSpacingInsetsY(tableBlock.cellSpacing, rowIndex, cell.rowSpan ?? 1, tableBlock.rows.length).top;
|
|
272
|
+
const cellLocalY = localY - rowTop + clipOffset - cellSpacingTop;
|
|
271
273
|
return {
|
|
272
274
|
fragment: tableFragment,
|
|
273
275
|
block: tableBlock,
|