@stll/folio-core 0.47.7 → 0.48.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/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 +59 -17
- 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 +5 -4
- package/dist/display-list/build/tablePrimitives.js +10 -6
- package/dist/docx/attributeRemainder.js +10 -2
- package/dist/docx/blockContentParser.d.ts +2 -0
- package/dist/docx/blockContentParser.js +77 -62
- 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/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 +2 -1
- package/dist/docx/groupDrawingParser.js +3 -6
- 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/paragraphParser.d.ts +5 -1
- package/dist/docx/paragraphParser.js +381 -362
- 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 +17 -6
- 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 +172 -184
- package/dist/docx/sdtProperties.js +87 -84
- package/dist/docx/sectionParser.js +169 -160
- package/dist/docx/serializer/paragraphSerializer.js +42 -38
- package/dist/docx/serializer/settingsSerializer.js +19 -1
- package/dist/docx/settingsParser.js +8 -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 +8 -3
- package/dist/docx/textBoxParser.js +3 -3
- 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/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 +258 -35
- 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 +70 -11
- 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 +11 -5
- package/dist/layout-engine/keep-together.js +39 -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 +4 -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 +42 -8
- package/dist/layout-engine/measure/measureContainer.js +5 -5
- package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
- package/dist/layout-engine/measure/measureHelpers.js +21 -5
- package/dist/layout-engine/measure/measureParagraph.js +109 -30
- package/dist/layout-engine/measure/measureTypes.d.ts +5 -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 +10 -1
- package/dist/layout-engine/paginator.js +13 -1
- package/dist/layout-engine/tableRowBreak.js +3 -1
- package/dist/layout-engine/types.d.ts +89 -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 +34 -22
- package/dist/layout-painter/renderTable.js +26 -13
- package/dist/prosemirror/attrs/index.d.ts +9 -9
- package/dist/prosemirror/attrs/index.js +43 -11
- package/dist/prosemirror/conversion/fromProseDoc.js +8 -1
- package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
- package/dist/prosemirror/conversion/markInterner.js +90 -0
- package/dist/prosemirror/conversion/toProseDoc.js +77 -41
- package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +2 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +2 -0
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/schema/nodes.d.ts +13 -1
- package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
- package/dist/prosemirror/textBoxHostParagraph.js +21 -0
- package/dist/prosemirror/validation.js +91 -80
- 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
|
@@ -14,6 +14,7 @@ import { panic } from "better-result";
|
|
|
14
14
|
import { DRAWING_RAW_XML_MODES, THEME_COLORS, isOoxmlSymbolCharacter } from "@stll/docx-core/model";
|
|
15
15
|
import { isSafePreservedChildXml, isWithinPreservedMarkupBudget } from "@stll/docx-core/schema";
|
|
16
16
|
//#region src/prosemirror/attrs/index.ts
|
|
17
|
+
const RUN_FORMATTING_VALUE_PROPERTY_SET = new Set(RUN_FORMATTING_VALUE_PROPERTIES);
|
|
17
18
|
const PRESERVED_XML_LEVEL_VALUES = new Set(Object.values(PRESERVED_XML_LEVELS));
|
|
18
19
|
const IMAGE_DISPLAY_MODES = [
|
|
19
20
|
"inline",
|
|
@@ -149,15 +150,12 @@ const SECTION_VERTICAL_ALIGNMENTS = [
|
|
|
149
150
|
"bottom"
|
|
150
151
|
];
|
|
151
152
|
const OMITTED_GRID_SLOT_VALUES = ["before", "after"];
|
|
152
|
-
const paragraphAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
153
153
|
const hardBreakAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
154
154
|
const pageBreakRunAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
155
155
|
const tabAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
156
156
|
const symbolAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
157
157
|
const preservedXmlAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
158
158
|
const preservedBlockAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
159
|
-
const tableAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
160
|
-
const tableRowAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
161
159
|
const tableCellAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
162
160
|
const imageAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
163
161
|
const fieldAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -185,7 +183,36 @@ const runIdentityAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
|
185
183
|
const inlineWrapperAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
186
184
|
const runFormattingOverrideAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
187
185
|
const hyperlinkAttrsCache = /* @__PURE__ */ new WeakMap();
|
|
188
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Read a node's attrs once per node. Nodes are immutable, and one conversion
|
|
188
|
+
* reads each paragraph, table and row several times (node validation, the
|
|
189
|
+
* bookmark walk, numbering). The cached result is frozen, value and issues
|
|
190
|
+
* included, so no caller can change what the next one reads.
|
|
191
|
+
*/
|
|
192
|
+
const memoizeNodeAttrsReader = (read) => {
|
|
193
|
+
const results = /* @__PURE__ */ new WeakMap();
|
|
194
|
+
return (node) => {
|
|
195
|
+
const cached = results.get(node);
|
|
196
|
+
if (cached !== void 0) return cached;
|
|
197
|
+
const result = freezeAttrsResult(read(node));
|
|
198
|
+
results.set(node, result);
|
|
199
|
+
return result;
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
const freezeAttrsResult = (result) => {
|
|
203
|
+
if (!result.ok) {
|
|
204
|
+
const issues = result.issues.map((issue) => Object.freeze({ ...issue }));
|
|
205
|
+
return Object.freeze({
|
|
206
|
+
ok: false,
|
|
207
|
+
issues: Object.freeze(issues)
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return Object.freeze({
|
|
211
|
+
ok: true,
|
|
212
|
+
value: Object.freeze(result.value)
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
const readParagraphAttrsUncached = (node) => {
|
|
189
216
|
const attrs = attrsRecord(node.attrs);
|
|
190
217
|
const issues = [];
|
|
191
218
|
expectNodeType(node, "paragraph", issues);
|
|
@@ -244,6 +271,7 @@ const readParagraphAttrs = (node) => {
|
|
|
244
271
|
});
|
|
245
272
|
optionalStringArray(attrs, "listLevelNumFmts", "paragraph.attrs.listLevelNumFmts", issues);
|
|
246
273
|
optionalNumberArray(attrs, "listLevelStarts", "paragraph.attrs.listLevelStarts", issues);
|
|
274
|
+
optionalTabStops(attrs, "listLevelTabs", "paragraph.attrs.listLevelTabs", issues);
|
|
247
275
|
optionalNumber(attrs, "listAbstractNumId", "paragraph.attrs.listAbstractNumId", issues);
|
|
248
276
|
optionalBorderMap(attrs, "borders", "paragraph.attrs.borders", issues, [
|
|
249
277
|
"top",
|
|
@@ -271,7 +299,8 @@ const readParagraphAttrs = (node) => {
|
|
|
271
299
|
optionalPreservedAttributes(attrs, "_preservedAttributes", "paragraph.attrs._preservedAttributes", issues);
|
|
272
300
|
return attrsResult(attrs, issues);
|
|
273
301
|
};
|
|
274
|
-
const
|
|
302
|
+
const readParagraphAttrs = memoizeNodeAttrsReader(readParagraphAttrsUncached);
|
|
303
|
+
const expectParagraphAttrs = (node) => expectAttrs(readParagraphAttrs(node), "paragraph attrs");
|
|
275
304
|
const readHardBreakAttrs = (node) => {
|
|
276
305
|
const attrs = attrsRecord(node.attrs);
|
|
277
306
|
const issues = [];
|
|
@@ -348,7 +377,7 @@ const readPreservedBlockAttrs = (node) => {
|
|
|
348
377
|
return attrsResult(attrs, issues);
|
|
349
378
|
};
|
|
350
379
|
const expectPreservedBlockAttrs = (node) => expectCachedNodeAttrs(node, preservedBlockAttrsCache, readPreservedBlockAttrs, "preservedBlock attrs");
|
|
351
|
-
const
|
|
380
|
+
const readTableAttrsUncached = (node) => {
|
|
352
381
|
const attrs = attrsRecord(node.attrs);
|
|
353
382
|
const issues = [];
|
|
354
383
|
expectNodeType(node, "table", issues);
|
|
@@ -375,8 +404,9 @@ const readTableAttrs = (node) => {
|
|
|
375
404
|
optionalTablePreservedMarkup(attrs, "_preserved", "table.attrs._preserved", issues);
|
|
376
405
|
return attrsResult(attrs, issues);
|
|
377
406
|
};
|
|
378
|
-
const
|
|
379
|
-
const
|
|
407
|
+
const readTableAttrs = memoizeNodeAttrsReader(readTableAttrsUncached);
|
|
408
|
+
const expectTableAttrs = (node) => expectAttrs(readTableAttrs(node), "table attrs");
|
|
409
|
+
const readTableRowAttrsUncached = (node) => {
|
|
380
410
|
const attrs = attrsRecord(node.attrs);
|
|
381
411
|
const issues = [];
|
|
382
412
|
expectNodeType(node, "tableRow", issues);
|
|
@@ -399,7 +429,8 @@ const readTableRowAttrs = (node) => {
|
|
|
399
429
|
optionalTablePreservedMarkup(attrs, "_preserved", "tableRow.attrs._preserved", issues);
|
|
400
430
|
return attrsResult(attrs, issues);
|
|
401
431
|
};
|
|
402
|
-
const
|
|
432
|
+
const readTableRowAttrs = memoizeNodeAttrsReader(readTableRowAttrsUncached);
|
|
433
|
+
const expectTableRowAttrs = (node) => expectAttrs(readTableRowAttrs(node), "table row attrs");
|
|
403
434
|
const readTableCellAttrs = (node) => {
|
|
404
435
|
const attrs = attrsRecord(node.attrs);
|
|
405
436
|
const issues = [];
|
|
@@ -656,6 +687,7 @@ const readTextBoxAttrs = (node) => {
|
|
|
656
687
|
optionalTextBoxTrackedChange(attrs, issues);
|
|
657
688
|
optionalTextBoxInlineSdts(attrs, issues);
|
|
658
689
|
optionalPreservedAttributes(attrs, "_preservedAttributes", "textBox.attrs._preservedAttributes", issues);
|
|
690
|
+
optionalRecord(attrs, "_docxHostParagraph", "textBox.attrs._docxHostParagraph", issues);
|
|
659
691
|
return attrsResult(attrs, issues);
|
|
660
692
|
};
|
|
661
693
|
const expectTextBoxAttrs = (node) => expectCachedNodeAttrs(node, textBoxAttrsCache, readTextBoxAttrs, "text box attrs");
|
|
@@ -1042,8 +1074,7 @@ const readRunFormattingOverrideMarkAttrs = (mark) => {
|
|
|
1042
1074
|
optionalTextFormatting(attrs, "_authoredValues", "runFormattingOverride.attrs._authoredValues", issues);
|
|
1043
1075
|
const authoredValues = attrs["_authoredValues"];
|
|
1044
1076
|
if (isRecord(authoredValues)) {
|
|
1045
|
-
const
|
|
1046
|
-
for (const property of Object.keys(authoredValues)) if (!allowed.has(property)) issues.push({
|
|
1077
|
+
for (const property of Object.keys(authoredValues)) if (!RUN_FORMATTING_VALUE_PROPERTY_SET.has(property)) issues.push({
|
|
1047
1078
|
path: `runFormattingOverride.attrs._authoredValues.${property}`,
|
|
1048
1079
|
message: "Expected a non-boolean authored formatting property."
|
|
1049
1080
|
});
|
|
@@ -2199,6 +2230,7 @@ const validateParagraphFormatting = (value, path, issues) => {
|
|
|
2199
2230
|
]);
|
|
2200
2231
|
optionalOneOfArray(value, "listLevelNumFmts", `${path}.listLevelNumFmts`, issues, COUNTER_FORMAT_VALUES);
|
|
2201
2232
|
optionalNumberArray(value, "listLevelStarts", `${path}.listLevelStarts`, issues);
|
|
2233
|
+
optionalTabStops(value, "listLevelTabs", `${path}.listLevelTabs`, issues);
|
|
2202
2234
|
optionalAutospacingBase(value, `${path}._autospacingBase`, issues);
|
|
2203
2235
|
for (const key of ["numPr", "numPrFromStyle"]) optionalParagraphNumbering(value, key, `${path}.${key}`, issues);
|
|
2204
2236
|
const direction = value["direction"];
|
|
@@ -42,6 +42,7 @@ import { schema } from "../schema/index.js";
|
|
|
42
42
|
import { PRESERVED_XML_LEVELS } from "../schema/nodes.js";
|
|
43
43
|
import { parseShapeGeometryAdjustments } from "../shapeGeometryAdjustments.js";
|
|
44
44
|
import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
|
|
45
|
+
import { textBoxHostParagraph } from "../textBoxHostParagraph.js";
|
|
45
46
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
46
47
|
import { hasSinkChildren } from "./preservedSinkCarriers.js";
|
|
47
48
|
import { runShadingAttrsToShading, shadingToRunShadingAttrs } from "./runShadingMark.js";
|
|
@@ -678,7 +679,7 @@ function isStillSyntheticFiller(blocks) {
|
|
|
678
679
|
}
|
|
679
680
|
function appendTextBoxBlock(blocks, node, options) {
|
|
680
681
|
const attrs = expectTextBoxAttrs(node);
|
|
681
|
-
|
|
682
|
+
let paragraph = convertPMTextBox(node, options.styleResolver);
|
|
682
683
|
const previousBlock = blocks.at(-1);
|
|
683
684
|
if (attrs._docxPlacement === "inlineWithPrevious" && previousBlock?.type === "paragraph") {
|
|
684
685
|
appendPageBreaks(previousBlock, options.pendingPageBreaks);
|
|
@@ -696,6 +697,12 @@ function appendTextBoxBlock(blocks, node, options) {
|
|
|
696
697
|
if (!mergeTextBoxIntoTrailingInlineSdts(options.previousStandaloneTextBox.paragraph, paragraph, attrs._docxInlineSdts ?? [])) options.previousStandaloneTextBox.paragraph.content.push(...paragraph.content);
|
|
697
698
|
return options.previousStandaloneTextBox;
|
|
698
699
|
}
|
|
700
|
+
const host = attrs._docxPlacement === "standalone" ? textBoxHostParagraph(node) : void 0;
|
|
701
|
+
if (host) {
|
|
702
|
+
const hostParagraph = convertPMParagraph(host, void 0, void 0, options.styleResolver);
|
|
703
|
+
hostParagraph.content = paragraph.content;
|
|
704
|
+
paragraph = hostParagraph;
|
|
705
|
+
}
|
|
699
706
|
if (attrs._docxPlacement === "standalone" && attrs._preservedAttributes?.length) paragraph.preservedAttributes = attrs._preservedAttributes;
|
|
700
707
|
prependPageBreaks(paragraph, options.pendingPageBreaks);
|
|
701
708
|
blocks.push(paragraph);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MarkFactory } from "../extensions/marks/markUtils.js";
|
|
2
|
+
import { Schema } from "prosemirror-model";
|
|
3
|
+
//#region src/prosemirror/conversion/markInterner.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build marks that share one instance per distinct (type, attrs) value.
|
|
6
|
+
*
|
|
7
|
+
* A document repeats a small set of run formattings across thousands of runs,
|
|
8
|
+
* so one conversion builds each distinct mark once. Marks are immutable, and
|
|
9
|
+
* ProseMirror compares them by value, so sharing an instance changes nothing a
|
|
10
|
+
* caller can observe except the saved allocation. Create one interner per
|
|
11
|
+
* conversion; it holds every mark it built until it is dropped.
|
|
12
|
+
*
|
|
13
|
+
* The native JSON serialization is only a lookup key: it collapses values the
|
|
14
|
+
* mark would keep apart (`-0`, `NaN`, nested `undefined`), so a hit is shared
|
|
15
|
+
* only after an exact comparison, and a mismatch builds an unshared mark. A
|
|
16
|
+
* mark holding `NaN` is never shared: ProseMirror does not find two of them
|
|
17
|
+
* equal, and a shared instance would.
|
|
18
|
+
*/
|
|
19
|
+
declare const createMarkInterner: (schema: Schema) => MarkFactory;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { createMarkInterner };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { panic } from "better-result";
|
|
2
|
+
//#region src/prosemirror/conversion/markInterner.ts
|
|
3
|
+
/**
|
|
4
|
+
* Leaves ProseMirror compares with `===`, minus `-0`/`0`: sharing a mark makes
|
|
5
|
+
* `Mark.eq` take its identity shortcut, so two leaves may share only when
|
|
6
|
+
* ProseMirror would call them equal anyway. `NaN` never equals itself there.
|
|
7
|
+
*/
|
|
8
|
+
const sameLeaf = (left, right) => left === right && Object.is(left, right);
|
|
9
|
+
/**
|
|
10
|
+
* Whether two attr values are interchangeable: `sameLeaf` on leaves, and the
|
|
11
|
+
* same own keys in the same order, so `-0`/`0`, `NaN` and `undefined`/absent
|
|
12
|
+
* stay apart. Output follows the shared value's key order, which is why order
|
|
13
|
+
* counts.
|
|
14
|
+
*/
|
|
15
|
+
const sameAttrValue = (left, right) => {
|
|
16
|
+
if (sameLeaf(left, right)) return true;
|
|
17
|
+
if (typeof left !== "object" || typeof right !== "object" || left === null || right === null) return false;
|
|
18
|
+
if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) return false;
|
|
19
|
+
if (Array.isArray(left)) {
|
|
20
|
+
if (!Array.isArray(right) || left.length !== right.length) return false;
|
|
21
|
+
for (let index = 0; index < left.length; index += 1) if (index in left !== index in right || !sameAttrValue(left[index], right[index])) return false;
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
const leftKeys = Object.keys(left);
|
|
25
|
+
const rightKeys = Object.keys(right);
|
|
26
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && sameAttrValue(Reflect.get(left, key), Reflect.get(right, key)));
|
|
27
|
+
};
|
|
28
|
+
const internedMark = (type, attrs) => {
|
|
29
|
+
const mark = type.create(attrs);
|
|
30
|
+
const nonDefault = /* @__PURE__ */ new Set();
|
|
31
|
+
for (const [name, spec] of Object.entries(type.spec.attrs ?? {})) if (!sameLeaf(mark.attrs[name], spec.default)) nonDefault.add(name);
|
|
32
|
+
return {
|
|
33
|
+
mark,
|
|
34
|
+
nonDefault
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Whether `create(attrs)` would compute attrs interchangeable with the
|
|
39
|
+
* interned mark's. `create` fills every declared attr `attrs` leaves
|
|
40
|
+
* `undefined` from its default, so the given attrs must match each value they
|
|
41
|
+
* set and set every attr where the mark holds something else.
|
|
42
|
+
*/
|
|
43
|
+
const matchesInterned = (type, attrs, { mark, nonDefault }) => {
|
|
44
|
+
const specs = type.spec.attrs ?? {};
|
|
45
|
+
let covered = 0;
|
|
46
|
+
for (const name in attrs) {
|
|
47
|
+
const given = attrs[name];
|
|
48
|
+
if (given === void 0 || !Object.hasOwn(specs, name)) continue;
|
|
49
|
+
if (!sameAttrValue(given, mark.attrs[name])) return false;
|
|
50
|
+
if (nonDefault.has(name)) covered += 1;
|
|
51
|
+
}
|
|
52
|
+
return covered === nonDefault.size;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Build marks that share one instance per distinct (type, attrs) value.
|
|
56
|
+
*
|
|
57
|
+
* A document repeats a small set of run formattings across thousands of runs,
|
|
58
|
+
* so one conversion builds each distinct mark once. Marks are immutable, and
|
|
59
|
+
* ProseMirror compares them by value, so sharing an instance changes nothing a
|
|
60
|
+
* caller can observe except the saved allocation. Create one interner per
|
|
61
|
+
* conversion; it holds every mark it built until it is dropped.
|
|
62
|
+
*
|
|
63
|
+
* The native JSON serialization is only a lookup key: it collapses values the
|
|
64
|
+
* mark would keep apart (`-0`, `NaN`, nested `undefined`), so a hit is shared
|
|
65
|
+
* only after an exact comparison, and a mismatch builds an unshared mark. A
|
|
66
|
+
* mark holding `NaN` is never shared: ProseMirror does not find two of them
|
|
67
|
+
* equal, and a shared instance would.
|
|
68
|
+
*/
|
|
69
|
+
const createMarkInterner = (schema) => {
|
|
70
|
+
const marksByType = /* @__PURE__ */ new Map();
|
|
71
|
+
return (typeName, attrs) => {
|
|
72
|
+
const type = schema.marks[typeName];
|
|
73
|
+
if (type === void 0) panic(`Unknown mark type ${typeName}.`);
|
|
74
|
+
let marks = marksByType.get(type);
|
|
75
|
+
if (marks === void 0) {
|
|
76
|
+
marks = /* @__PURE__ */ new Map();
|
|
77
|
+
marksByType.set(type, marks);
|
|
78
|
+
}
|
|
79
|
+
const key = JSON.stringify(attrs ?? null);
|
|
80
|
+
const cached = marks.get(key);
|
|
81
|
+
if (cached === void 0) {
|
|
82
|
+
const interned = internedMark(type, attrs);
|
|
83
|
+
marks.set(key, interned);
|
|
84
|
+
return interned.mark;
|
|
85
|
+
}
|
|
86
|
+
return matchesInterned(type, attrs, cached) ? cached.mark : type.create(attrs);
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
//#endregion
|
|
90
|
+
export { createMarkInterner };
|
|
@@ -2,7 +2,7 @@ import { rangedCommentIds } from "../../docx/commentAnchorIndex.js";
|
|
|
2
2
|
import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
|
|
3
3
|
import { isInlineSdtContent, isTrackedChangeWrapperChild } from "../../docx/inlineWrapperContent.js";
|
|
4
4
|
import { mergeParagraphNumbering as mergeParagraphNumbering$1, paragraphNumberingReferenceId as paragraphNumberingReferenceId$1 } from "../../docx/numberingReference.js";
|
|
5
|
-
import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, createProseParagraphWithPropertySource, getDocumentParagraphPropertySourceContract, recreateProseNodeWithParagraphPropertySource, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
|
|
5
|
+
import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, createProseParagraphWithPropertySource, getDocumentParagraphPropertySourceContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithParagraphPropertySource, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
|
|
6
6
|
import { isBaselineVertAlign } from "../../docx/runParser.js";
|
|
7
7
|
import { resolveTableLook } from "../../docx/tableLook.js";
|
|
8
8
|
import { isCellMergeContinuation } from "../../docx/tableParser.js";
|
|
@@ -41,6 +41,7 @@ import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
|
|
|
41
41
|
import { canCarryTrackedRunMark, trackedRunInlineAtomDisposition } from "../trackedRunInlineAtoms.js";
|
|
42
42
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
43
43
|
import { resolveEffectiveTableCellFormatting } from "./effectiveTableCellFormatting.js";
|
|
44
|
+
import { createMarkInterner } from "./markInterner.js";
|
|
44
45
|
import { hasSinkChildren } from "./preservedSinkCarriers.js";
|
|
45
46
|
import { sdtAttrsFromProperties } from "./sdtAttrs.js";
|
|
46
47
|
import { panic } from "better-result";
|
|
@@ -227,7 +228,8 @@ function toProseDoc(document, options) {
|
|
|
227
228
|
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(paragraphs),
|
|
228
229
|
storyRangedCommentIds: rangedCommentIds(paragraphs),
|
|
229
230
|
openCommentIds: /* @__PURE__ */ new Set(),
|
|
230
|
-
warnPageBreakProjection: pageBreakProjectionWarn(options?.warn)
|
|
231
|
+
warnPageBreakProjection: pageBreakProjectionWarn(options?.warn),
|
|
232
|
+
createMark: createMarkInterner(schema)
|
|
231
233
|
};
|
|
232
234
|
const convertBodyBlocks = (blocks) => {
|
|
233
235
|
const out = [];
|
|
@@ -259,10 +261,12 @@ function toProseDoc(document, options) {
|
|
|
259
261
|
if (nodes.length === 0) nodes.push(schema.node("paragraph", {}, []));
|
|
260
262
|
const finalSectionStart = document.package.document.sections?.at(-1)?.properties.sectionStart ?? null;
|
|
261
263
|
const adjustLineHeightInTable = document.package.settings?.adjustLineHeightInTable === true;
|
|
264
|
+
const doNotUseIndentAsNumberingTabStop = document.package.settings?.doNotUseIndentAsNumberingTabStop === true;
|
|
262
265
|
const pmDoc = stampNumberedRefFieldBaselines(schema.node("doc", {
|
|
263
266
|
[PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR]: getDocumentParagraphPropertySourceContract(document) ?? null,
|
|
264
267
|
_finalSectionStart: finalSectionStart,
|
|
265
|
-
_adjustLineHeightInTable: adjustLineHeightInTable
|
|
268
|
+
_adjustLineHeightInTable: adjustLineHeightInTable,
|
|
269
|
+
_doNotUseIndentAsNumberingTabStop: doNotUseIndentAsNumberingTabStop
|
|
266
270
|
}, nodes));
|
|
267
271
|
assertValidProseMirrorDocument(pmDoc, "Document conversion produced an invalid ProseMirror document");
|
|
268
272
|
return pmDoc;
|
|
@@ -355,7 +359,10 @@ function convertBlockSdt(blockSdt, convertBlocks) {
|
|
|
355
359
|
function convertParagraph(paragraph, styleResolver, context, extraRunFormatting, tableParagraphOverlay, textBoxAnchors) {
|
|
356
360
|
const { nextHyperlinkInstanceIndex, pairedBookmarkIds, pageBreakRunSourceDescendants, storyRangedCommentIds, openCommentIds } = context;
|
|
357
361
|
let runIdentityId = 0;
|
|
358
|
-
const
|
|
362
|
+
const runScope = {
|
|
363
|
+
nextRunIdentityId: () => runIdentityId++,
|
|
364
|
+
createMark: context.createMark
|
|
365
|
+
};
|
|
359
366
|
const { attrs, effectiveFrame } = paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay);
|
|
360
367
|
reportParagraphPageBreakProjection({
|
|
361
368
|
paragraph,
|
|
@@ -452,7 +459,7 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
|
|
|
452
459
|
historical: getHistoricalRunFormatting
|
|
453
460
|
};
|
|
454
461
|
const emitTrackedChange = (change, markType, moveKind) => {
|
|
455
|
-
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex,
|
|
462
|
+
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, runScope, trackedRunFormattingResolvers, styleResolver, moveKind, textBoxAnchors, wrapperStack));
|
|
456
463
|
};
|
|
457
464
|
const stacked = withInlineWrapperStacks(paragraph.content);
|
|
458
465
|
const emptyRanges = planEmptyRanges(stacked.map((item) => item.content));
|
|
@@ -476,7 +483,7 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
|
|
|
476
483
|
emitInlineNode(schema.node("commentReference", { commentId: content.id }));
|
|
477
484
|
break;
|
|
478
485
|
case "run":
|
|
479
|
-
emitInlineNodes(convertRun(content, getInheritedRunFormatting(content.formatting),
|
|
486
|
+
emitInlineNodes(convertRun(content, getInheritedRunFormatting(content.formatting), runScope, styleResolver, textBoxAnchors));
|
|
480
487
|
break;
|
|
481
488
|
case "hyperlink": {
|
|
482
489
|
const linkNodes = convertHyperlink(content, {
|
|
@@ -484,7 +491,7 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
|
|
|
484
491
|
styleResolver,
|
|
485
492
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
486
493
|
textBoxAnchors,
|
|
487
|
-
|
|
494
|
+
runScope
|
|
488
495
|
});
|
|
489
496
|
if (linkNodes.length === 0) {
|
|
490
497
|
const emptyWrapperStacks = emptyInlineWrapperStacks(content.children);
|
|
@@ -511,12 +518,12 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
|
|
|
511
518
|
getInheritedRunFormatting,
|
|
512
519
|
styleResolver,
|
|
513
520
|
nextHyperlinkInstanceIndex,
|
|
514
|
-
|
|
521
|
+
runScope,
|
|
515
522
|
textBoxAnchors
|
|
516
523
|
}));
|
|
517
524
|
break;
|
|
518
525
|
case "inlineSdt":
|
|
519
|
-
emitInlineNode(convertInlineSdt(content, nextHyperlinkInstanceIndex,
|
|
526
|
+
emitInlineNode(convertInlineSdt(content, nextHyperlinkInstanceIndex, runScope, getInheritedRunFormatting, trackedRunFormattingResolvers, styleResolver, textBoxAnchors, stack));
|
|
520
527
|
break;
|
|
521
528
|
case "insertion":
|
|
522
529
|
case "moveTo":
|
|
@@ -630,13 +637,13 @@ const withTrackedRunMark = (node, mark, ancestor) => {
|
|
|
630
637
|
* Convert tracked change (insertion or deletion) content to PM nodes with
|
|
631
638
|
* an insertion/deletion mark applied.
|
|
632
639
|
*/
|
|
633
|
-
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex,
|
|
640
|
+
function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, runScope, runFormattingResolvers, styleResolver, moveKind = null, textBoxAnchors, wrappedBy = []) {
|
|
634
641
|
const nodes = [];
|
|
635
642
|
const getTrackedRunFormatting = markType === "deletion" ? runFormattingResolvers.historical : runFormattingResolvers.current;
|
|
636
643
|
for (const { content: item, stack } of withInlineWrapperStacks(change.content)) {
|
|
637
644
|
if (!isTrackedChangeWrapperChild(item)) continue;
|
|
638
645
|
const itemNodes = [];
|
|
639
|
-
if (item.type === "run") itemNodes.push(...convertRun(item, getTrackedRunFormatting(item.formatting),
|
|
646
|
+
if (item.type === "run") itemNodes.push(...convertRun(item, getTrackedRunFormatting(item.formatting), runScope, styleResolver, textBoxAnchors));
|
|
640
647
|
else if (item.type === "hyperlink") {
|
|
641
648
|
const currentHyperlinkIndex = nextHyperlinkInstanceIndex();
|
|
642
649
|
itemNodes.push(...convertHyperlink(item, {
|
|
@@ -644,14 +651,14 @@ function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, next
|
|
|
644
651
|
styleResolver,
|
|
645
652
|
hyperlinkIndex: currentHyperlinkIndex,
|
|
646
653
|
textBoxAnchors,
|
|
647
|
-
|
|
654
|
+
runScope
|
|
648
655
|
}));
|
|
649
656
|
} else if (item.type === "simpleField" || item.type === "complexField") {
|
|
650
657
|
const fieldNode = convertField(item, {
|
|
651
658
|
getInheritedRunFormatting: getTrackedRunFormatting,
|
|
652
659
|
styleResolver,
|
|
653
660
|
nextHyperlinkInstanceIndex,
|
|
654
|
-
|
|
661
|
+
runScope,
|
|
655
662
|
textBoxAnchors
|
|
656
663
|
});
|
|
657
664
|
if (fieldNode) itemNodes.push(fieldNode);
|
|
@@ -661,9 +668,9 @@ function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, next
|
|
|
661
668
|
} else if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") {
|
|
662
669
|
const nestedMarkType = item.type === "insertion" || item.type === "moveTo" ? "insertion" : "deletion";
|
|
663
670
|
const nestedMoveKind = item.type === "moveFrom" || item.type === "moveTo" ? item.type : null;
|
|
664
|
-
itemNodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex,
|
|
671
|
+
itemNodes.push(...convertTrackedChange(item, nestedMarkType, nextHyperlinkInstanceIndex, runScope, runFormattingResolvers, styleResolver, nestedMoveKind, textBoxAnchors, [...wrappedBy, ...stack]));
|
|
665
672
|
} else if (item.type === "inlineSdt") {
|
|
666
|
-
const sdtNode = convertInlineSdt(item, nextHyperlinkInstanceIndex,
|
|
673
|
+
const sdtNode = convertInlineSdt(item, nextHyperlinkInstanceIndex, runScope, getTrackedRunFormatting, runFormattingResolvers, styleResolver, textBoxAnchors, [...wrappedBy, ...stack]);
|
|
667
674
|
if (sdtNode) itemNodes.push(sdtNode);
|
|
668
675
|
} else if (item.type === "bookmarkStart") itemNodes.push(schema.node("bookmarkBoundary", {
|
|
669
676
|
type: "start",
|
|
@@ -1080,8 +1087,7 @@ function convertTable(table, styleResolver, context) {
|
|
|
1080
1087
|
const tableStyleId = table.formatting?.styleId;
|
|
1081
1088
|
const look = resolveTableLook(table.formatting?.look);
|
|
1082
1089
|
const tableStyle = tableStyleId ? styleResolver?.getStyle(tableStyleId) : void 0;
|
|
1083
|
-
const
|
|
1084
|
-
const fallbackTableStyle = tableStyleId ? void 0 : defaultTableStyle;
|
|
1090
|
+
const fallbackTableStyle = tableStyle ? void 0 : styleResolver?.getDefaultTableStyle();
|
|
1085
1091
|
const conditionalTableStyleId = tableStyle?.styleId ?? fallbackTableStyle?.styleId;
|
|
1086
1092
|
const resolvedTableBorders = table.formatting?.borders ?? tableStyle?.tblPr?.borders ?? fallbackTableStyle?.tblPr?.borders;
|
|
1087
1093
|
const fallbackTableIndent = fallbackTableStyle?.tblPr?.indent;
|
|
@@ -1466,7 +1472,8 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
|
1466
1472
|
pageBreakRunSourceDescendants,
|
|
1467
1473
|
storyRangedCommentIds: rangedCommentIds(cell.content),
|
|
1468
1474
|
openCommentIds: /* @__PURE__ */ new Set(),
|
|
1469
|
-
warnPageBreakProjection: noPageBreakProjectionWarning
|
|
1475
|
+
warnPageBreakProjection: noPageBreakProjectionWarning,
|
|
1476
|
+
createMark: createMarkInterner(schema)
|
|
1470
1477
|
},
|
|
1471
1478
|
isHeader: nodeType === "tableHeader",
|
|
1472
1479
|
gridWidthPercent: void 0,
|
|
@@ -1479,7 +1486,7 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
|
1479
1486
|
defaultCellMargins: void 0
|
|
1480
1487
|
});
|
|
1481
1488
|
}
|
|
1482
|
-
function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyperlinkInstanceIndex,
|
|
1489
|
+
function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyperlinkInstanceIndex, runScope, textBoxAnchors }) {
|
|
1483
1490
|
let displayText = "";
|
|
1484
1491
|
let fieldFormatting;
|
|
1485
1492
|
let fieldPropertyChanges;
|
|
@@ -1490,7 +1497,7 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1490
1497
|
fieldFormatting ??= run.formatting;
|
|
1491
1498
|
fieldPropertyChanges ??= run.propertyChanges;
|
|
1492
1499
|
if (!hasStructuredSourceContent) return;
|
|
1493
|
-
into.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType),
|
|
1500
|
+
into.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType), runScope, styleResolver, textBoxAnchors));
|
|
1494
1501
|
};
|
|
1495
1502
|
if (field.type === "simpleField") for (const { content, stack } of withInlineWrapperStacks(field.content)) {
|
|
1496
1503
|
const itemNodes = [];
|
|
@@ -1512,7 +1519,7 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1512
1519
|
styleResolver,
|
|
1513
1520
|
hyperlinkIndex: nextHyperlinkInstanceIndex(),
|
|
1514
1521
|
textBoxAnchors,
|
|
1515
|
-
|
|
1522
|
+
runScope
|
|
1516
1523
|
}));
|
|
1517
1524
|
break;
|
|
1518
1525
|
default: break;
|
|
@@ -1522,7 +1529,12 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1522
1529
|
else for (const run of field.fieldResult) appendRun(run, inlineNodes);
|
|
1523
1530
|
if (!fieldFormatting && field.type === "complexField" && field.fieldResult.length === 0) fieldFormatting = field.formatting;
|
|
1524
1531
|
const inheritedFormatting = getInheritedRunFormatting(fieldFormatting, field.fieldType);
|
|
1525
|
-
const { marks } = buildRunMarks(
|
|
1532
|
+
const { marks } = buildRunMarks({
|
|
1533
|
+
runFormatting: fieldFormatting,
|
|
1534
|
+
inherited: inheritedFormatting,
|
|
1535
|
+
styleResolver,
|
|
1536
|
+
createMark: runScope.createMark
|
|
1537
|
+
});
|
|
1526
1538
|
const hasConvertedHyperlinkContent = inlineNodes.some((node) => node.marks.some((mark) => mark.type.name === "hyperlink"));
|
|
1527
1539
|
const hasConvertedPageBreakContent = inlineNodes.some((node) => node.type.name === "pageBreakRun");
|
|
1528
1540
|
const hasConvertedPreservedContent = inlineNodes.some((node) => node.type.name === "preservedXml");
|
|
@@ -1602,7 +1614,7 @@ function convertMathEquation(math) {
|
|
|
1602
1614
|
* its own leaves, so nothing outside can mark them afterwards: the caller's
|
|
1603
1615
|
* stack has to reach them here, under the wrappers written inside the control.
|
|
1604
1616
|
*/
|
|
1605
|
-
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex,
|
|
1617
|
+
function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, runScope, getInheritedRunFormatting, trackedRunFormattingResolvers, styleResolver, textBoxAnchors, wrappedBy = []) {
|
|
1606
1618
|
const props = sdt.properties;
|
|
1607
1619
|
const inlineNodes = [];
|
|
1608
1620
|
const stacked = withInlineWrapperStacks(sdt.content, wrappedBy);
|
|
@@ -1618,7 +1630,7 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextRunIdentityId, ge
|
|
|
1618
1630
|
if (emptyRanges.closedAt.has(index)) continue;
|
|
1619
1631
|
switch (content.type) {
|
|
1620
1632
|
case "run":
|
|
1621
|
-
itemNodes.push(...convertRun(content, getInheritedRunFormatting(content.formatting),
|
|
1633
|
+
itemNodes.push(...convertRun(content, getInheritedRunFormatting(content.formatting), runScope, styleResolver, textBoxAnchors));
|
|
1622
1634
|
break;
|
|
1623
1635
|
case "hyperlink": {
|
|
1624
1636
|
const currentHyperlinkIndex = nextHyperlinkInstanceIndex();
|
|
@@ -1627,7 +1639,7 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextRunIdentityId, ge
|
|
|
1627
1639
|
styleResolver,
|
|
1628
1640
|
hyperlinkIndex: currentHyperlinkIndex,
|
|
1629
1641
|
textBoxAnchors,
|
|
1630
|
-
|
|
1642
|
+
runScope
|
|
1631
1643
|
}));
|
|
1632
1644
|
break;
|
|
1633
1645
|
}
|
|
@@ -1637,14 +1649,14 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextRunIdentityId, ge
|
|
|
1637
1649
|
getInheritedRunFormatting,
|
|
1638
1650
|
styleResolver,
|
|
1639
1651
|
nextHyperlinkInstanceIndex,
|
|
1640
|
-
|
|
1652
|
+
runScope,
|
|
1641
1653
|
textBoxAnchors
|
|
1642
1654
|
});
|
|
1643
1655
|
if (fieldNode) itemNodes.push(fieldNode);
|
|
1644
1656
|
break;
|
|
1645
1657
|
}
|
|
1646
1658
|
case "inlineSdt": {
|
|
1647
|
-
const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex,
|
|
1659
|
+
const nestedSdt = convertInlineSdt(content, nextHyperlinkInstanceIndex, runScope, getInheritedRunFormatting, trackedRunFormattingResolvers, styleResolver, textBoxAnchors, stack);
|
|
1648
1660
|
if (nestedSdt) itemNodes.push(nestedSdt);
|
|
1649
1661
|
break;
|
|
1650
1662
|
}
|
|
@@ -1652,7 +1664,7 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextRunIdentityId, ge
|
|
|
1652
1664
|
case "deletion":
|
|
1653
1665
|
case "moveTo":
|
|
1654
1666
|
case "moveFrom":
|
|
1655
|
-
itemNodes.push(...convertTrackedChange(content, content.type === "insertion" || content.type === "moveTo" ? "insertion" : "deletion", nextHyperlinkInstanceIndex,
|
|
1667
|
+
itemNodes.push(...convertTrackedChange(content, content.type === "insertion" || content.type === "moveTo" ? "insertion" : "deletion", nextHyperlinkInstanceIndex, runScope, trackedRunFormattingResolvers, styleResolver, content.type === "moveTo" || content.type === "moveFrom" ? content.type : null, textBoxAnchors));
|
|
1656
1668
|
break;
|
|
1657
1669
|
case "mathEquation": {
|
|
1658
1670
|
const mathNode = convertMathEquation(content);
|
|
@@ -1697,11 +1709,16 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, nextRunIdentityId, ge
|
|
|
1697
1709
|
* @param run - The run to convert
|
|
1698
1710
|
* @param resolvedStyleFormatting - Paragraph formatting and its explicit style-toggle state
|
|
1699
1711
|
*/
|
|
1700
|
-
function convertRun(run, resolvedStyleFormatting,
|
|
1712
|
+
function convertRun(run, resolvedStyleFormatting, runScope, styleResolver, textBoxAnchors) {
|
|
1701
1713
|
const nodes = [];
|
|
1702
|
-
const { marks, mergedFormatting } = buildRunMarks(
|
|
1714
|
+
const { marks, mergedFormatting } = buildRunMarks({
|
|
1715
|
+
runFormatting: run.formatting,
|
|
1716
|
+
inherited: resolvedStyleFormatting,
|
|
1717
|
+
styleResolver,
|
|
1718
|
+
createMark: runScope.createMark
|
|
1719
|
+
});
|
|
1703
1720
|
if (run.propertyChanges && run.propertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...run.propertyChanges] }));
|
|
1704
|
-
const identity = runIdentityMark(run, nextRunIdentityId);
|
|
1721
|
+
const identity = runIdentityMark(run, runScope.nextRunIdentityId);
|
|
1705
1722
|
if (identity) marks.push(identity);
|
|
1706
1723
|
for (const content of run.content) {
|
|
1707
1724
|
const contentNodes = convertRunContent(content, marks, mergedFormatting, textBoxAnchors, run.formatting);
|
|
@@ -2015,12 +2032,13 @@ const canReconstructAuthoredRunFormatting = ({ directFormatting, effectiveFormat
|
|
|
2015
2032
|
}
|
|
2016
2033
|
return true;
|
|
2017
2034
|
};
|
|
2018
|
-
function buildRunMarks(runFormatting, inherited, styleResolver) {
|
|
2035
|
+
function buildRunMarks({ runFormatting, inherited, styleResolver, createMark }) {
|
|
2019
2036
|
if (runFormatting === void 0 && inherited.implicitCharacterStyleApplied === true && inherited.paragraphMarkOverrides === void 0) return {
|
|
2020
2037
|
marks: textFormattingToMarks(inherited.formatting, schema, {
|
|
2021
2038
|
overrideFormatting: void 0,
|
|
2022
2039
|
directFormatting: void 0,
|
|
2023
|
-
authoredCarrier: "reconstruct"
|
|
2040
|
+
authoredCarrier: "reconstruct",
|
|
2041
|
+
createMark
|
|
2024
2042
|
}),
|
|
2025
2043
|
mergedFormatting: inherited.formatting
|
|
2026
2044
|
};
|
|
@@ -2064,9 +2082,10 @@ function buildRunMarks(runFormatting, inherited, styleResolver) {
|
|
|
2064
2082
|
const marks = textFormattingToMarks(mergedFormatting, schema, {
|
|
2065
2083
|
overrideFormatting,
|
|
2066
2084
|
directFormatting: runFormatting,
|
|
2067
|
-
authoredCarrier
|
|
2085
|
+
authoredCarrier,
|
|
2086
|
+
createMark
|
|
2068
2087
|
});
|
|
2069
|
-
if (styleId) marks.push(
|
|
2088
|
+
if (styleId) marks.push(createMark("characterStyle", { styleId }));
|
|
2070
2089
|
return {
|
|
2071
2090
|
marks,
|
|
2072
2091
|
mergedFormatting
|
|
@@ -2334,7 +2353,7 @@ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runForma
|
|
|
2334
2353
|
_docxRunFormatting: runFormatting
|
|
2335
2354
|
});
|
|
2336
2355
|
}
|
|
2337
|
-
function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver, hyperlinkIndex, textBoxAnchors,
|
|
2356
|
+
function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver, hyperlinkIndex, textBoxAnchors, runScope }) {
|
|
2338
2357
|
const nodes = [];
|
|
2339
2358
|
const href = hyperlink.href || (hyperlink.anchor ? `#${hyperlink.anchor}` : "");
|
|
2340
2359
|
const linkMark = schema.mark("hyperlink", {
|
|
@@ -2371,9 +2390,14 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
2371
2390
|
break;
|
|
2372
2391
|
case "run": {
|
|
2373
2392
|
const inheritedFormatting = getInheritedRunFormatting(child.formatting);
|
|
2374
|
-
const { marks: runMarks, mergedFormatting } = buildRunMarks(
|
|
2393
|
+
const { marks: runMarks, mergedFormatting } = buildRunMarks({
|
|
2394
|
+
runFormatting: child.formatting,
|
|
2395
|
+
inherited: inheritedFormatting,
|
|
2396
|
+
styleResolver,
|
|
2397
|
+
createMark: runScope.createMark
|
|
2398
|
+
});
|
|
2375
2399
|
if (child.propertyChanges && child.propertyChanges.length > 0) runMarks.push(schema.mark("runPropertyChange", { changes: [...child.propertyChanges] }));
|
|
2376
|
-
const identity = runIdentityMark(child, nextRunIdentityId);
|
|
2400
|
+
const identity = runIdentityMark(child, runScope.nextRunIdentityId);
|
|
2377
2401
|
if (identity) runMarks.push(identity);
|
|
2378
2402
|
const allMarks = [...runMarks, linkMark];
|
|
2379
2403
|
for (const content of child.content) childNodes.push(...convertRunContent(content, allMarks, mergedFormatting, textBoxAnchors, child.formatting));
|
|
@@ -2518,10 +2542,20 @@ function convertParagraphWithTextBoxes(block, styleResolver, { textBoxGroupId, c
|
|
|
2518
2542
|
context,
|
|
2519
2543
|
trackedChange,
|
|
2520
2544
|
inlineSdts,
|
|
2521
|
-
...standalone && index === 0 && block.preservedAttributes ? { hostPreservedAttributes: block.preservedAttributes } : {}
|
|
2545
|
+
...standalone && index === 0 && block.preservedAttributes ? { hostPreservedAttributes: block.preservedAttributes } : {},
|
|
2546
|
+
...standalone && index === 0 ? { hostParagraph: hostParagraphAttrs(pmParagraph.attrs) } : {}
|
|
2522
2547
|
}));
|
|
2523
2548
|
return nodes;
|
|
2524
2549
|
}
|
|
2550
|
+
/**
|
|
2551
|
+
* The host paragraph's attributes without its identity. The node may be
|
|
2552
|
+
* copied, and a copy must not make a second claim on the same `w:p`; the
|
|
2553
|
+
* attribute remainder travels in the node's own `_preservedAttributes`.
|
|
2554
|
+
*/
|
|
2555
|
+
function hostParagraphAttrs(attrs) {
|
|
2556
|
+
const { paraId: _paraId, textId: _textId, idStability: _idStability, _preservedAttributes, ...host } = proseParagraphAttrsWithoutPropertySource(attrs);
|
|
2557
|
+
return host;
|
|
2558
|
+
}
|
|
2525
2559
|
function hasContentBesidesTextBoxAnchors(paragraph) {
|
|
2526
2560
|
let hasContent = false;
|
|
2527
2561
|
paragraph.descendants((node) => {
|
|
@@ -2785,7 +2819,8 @@ function convertTextBox(textBox, styleResolver, options) {
|
|
|
2785
2819
|
_docxTextBodyContentState: textBox.content.length === 0 ? { type: "source-empty" } : { type: "authored" },
|
|
2786
2820
|
_docxTrackedChange: options.trackedChange,
|
|
2787
2821
|
_docxInlineSdts: options.inlineSdts.length > 0 ? options.inlineSdts : void 0,
|
|
2788
|
-
_preservedAttributes: options.hostPreservedAttributes
|
|
2822
|
+
_preservedAttributes: options.hostPreservedAttributes,
|
|
2823
|
+
_docxHostParagraph: options.hostParagraph
|
|
2789
2824
|
}, contentNodes);
|
|
2790
2825
|
}
|
|
2791
2826
|
/**
|
|
@@ -2809,7 +2844,8 @@ function headerFooterToProseDoc(content, options) {
|
|
|
2809
2844
|
pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(content),
|
|
2810
2845
|
storyRangedCommentIds: rangedCommentIds(content),
|
|
2811
2846
|
openCommentIds: /* @__PURE__ */ new Set(),
|
|
2812
|
-
warnPageBreakProjection: pageBreakProjectionWarn(options?.warn)
|
|
2847
|
+
warnPageBreakProjection: pageBreakProjectionWarn(options?.warn),
|
|
2848
|
+
createMark: createMarkInterner(schema)
|
|
2813
2849
|
};
|
|
2814
2850
|
const convertBlocks = (blocks) => {
|
|
2815
2851
|
const out = [];
|
|
@@ -11,7 +11,8 @@ const DocExtension = createNodeExtension({
|
|
|
11
11
|
attrs: {
|
|
12
12
|
[PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR]: { default: null },
|
|
13
13
|
_finalSectionStart: { default: null },
|
|
14
|
-
_adjustLineHeightInTable: { default: false }
|
|
14
|
+
_adjustLineHeightInTable: { default: false },
|
|
15
|
+
_doNotUseIndentAsNumberingTabStop: { default: false }
|
|
15
16
|
},
|
|
16
17
|
content: "(paragraph | horizontalRule | pageBreak | table | textBox | blockSdt | preservedBlock | blockBookmarkBoundary)+"
|
|
17
18
|
}
|