@stll/folio-core 0.43.0 → 0.44.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/headless.js +6 -5
- package/dist/ai-edits/index.d.ts +2 -2
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/snapshot.js +13 -9
- package/dist/compare/content-alignment.js +16 -1
- package/dist/compare/inline-atoms.js +1 -1
- package/dist/compare/style-resources.js +6 -0
- package/dist/docx/appVersionNormalization.d.ts +0 -18
- package/dist/docx/blockContentParser.js +8 -0
- package/dist/docx/blockRangeMarkers.d.ts +36 -0
- package/dist/docx/blockRangeMarkers.js +59 -0
- package/dist/docx/bookmarkParser.d.ts +2 -20
- package/dist/docx/bookmarkParser.js +6 -30
- package/dist/docx/borderParser.d.ts +13 -0
- package/dist/docx/borderParser.js +71 -0
- package/dist/docx/builtInStyles.d.ts +165 -0
- package/dist/docx/builtInStyles.js +239 -0
- package/dist/docx/commentIdNormalization.d.ts +3 -1
- package/dist/docx/commentIdNormalization.js +18 -1
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +34 -7
- package/dist/docx/commentReferenceNormalization.d.ts +4 -1
- package/dist/docx/commentReferenceNormalization.js +23 -14
- package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
- package/dist/docx/danglingRelationshipReferences.js +30 -0
- package/dist/docx/defaultParagraphStyle.d.ts +18 -1
- package/dist/docx/defaultParagraphStyle.js +23 -1
- package/dist/docx/documentParser.d.ts +2 -1
- package/dist/docx/documentParser.js +2 -2
- package/dist/docx/drawingUtils.d.ts +8 -1
- package/dist/docx/drawingUtils.js +12 -3
- package/dist/docx/fieldParser.js +3 -5
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +19 -4
- package/dist/docx/groupDrawingParser.js +1 -1
- package/dist/docx/headerFooterRefParser.d.ts +4 -3
- package/dist/docx/headerFooterRefParser.js +42 -12
- package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
- package/dist/docx/headerFooterReferenceNormalization.js +5 -1
- package/dist/docx/hyperlinkParser.js +11 -15
- package/dist/docx/imageParser.d.ts +1 -1
- package/dist/docx/imageParser.js +22 -18
- package/dist/docx/imageRawXml.js +5 -5
- package/dist/docx/markupRangeMarker.d.ts +15 -0
- package/dist/docx/markupRangeMarker.js +44 -0
- package/dist/docx/noteReferenceStyles.d.ts +29 -0
- package/dist/docx/noteReferenceStyles.js +70 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +4 -1
- package/dist/docx/numberingReferenceNormalization.js +20 -1
- package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
- package/dist/docx/paragraphParser.js +66 -99
- package/dist/docx/paragraphPropertySource.js +1 -0
- package/dist/docx/paragraphTraversal.d.ts +37 -1
- package/dist/docx/paragraphTraversal.js +84 -1
- package/dist/docx/parseContext.d.ts +37 -0
- package/dist/docx/parseContext.js +67 -0
- package/dist/docx/parseWarningMessage.d.ts +6 -0
- package/dist/docx/parseWarningMessage.js +44 -0
- package/dist/docx/parser.js +81 -27
- package/dist/docx/relsParser.d.ts +28 -11
- package/dist/docx/relsParser.js +26 -13
- package/dist/docx/revisionIdNormalization.js +81 -7
- package/dist/docx/rezip.js +63 -22
- package/dist/docx/runConsolidator.js +1 -2
- package/dist/docx/runParser.d.ts +8 -1
- package/dist/docx/runParser.js +30 -48
- package/dist/docx/sectionParser.d.ts +2 -1
- package/dist/docx/sectionParser.js +21 -65
- package/dist/docx/serializer/borderSerializer.d.ts +1 -2
- package/dist/docx/serializer/commentSerializer.js +22 -9
- package/dist/docx/serializer/documentSerializer.d.ts +1 -5
- package/dist/docx/serializer/documentSerializer.js +6 -16
- package/dist/docx/serializer/headerFooterSerializer.js +5 -0
- package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
- package/dist/docx/serializer/markupRangeAttributes.js +24 -0
- package/dist/docx/serializer/noteSerializer.js +5 -0
- package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
- package/dist/docx/serializer/paragraphSerializer.js +29 -35
- package/dist/docx/serializer/runSerializer.js +13 -7
- package/dist/docx/serializer/tableSerializer.js +28 -13
- package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
- package/dist/docx/server/build.js +8 -1
- package/dist/docx/server/createBilingualDocument.js +10 -18
- package/dist/docx/server/extractDocxText.js +3 -4
- package/dist/docx/shadingParser.d.ts +6 -0
- package/dist/docx/shadingParser.js +32 -0
- package/dist/docx/shapeParser.js +3 -3
- package/dist/docx/styleParser.js +13 -87
- package/dist/docx/styleReferenceResolution.d.ts +36 -0
- package/dist/docx/styleReferenceResolution.js +51 -0
- package/dist/docx/tableLook.d.ts +57 -0
- package/dist/docx/tableLook.js +63 -0
- package/dist/docx/tableParser.d.ts +7 -9
- package/dist/docx/tableParser.js +64 -110
- package/dist/docx/textBoxParser.js +4 -4
- package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
- package/dist/docx/trackedMoveRangeNormalization.js +11 -21
- package/dist/docx/transitionalSpelling.d.ts +13 -2
- package/dist/docx/transitionalSpelling.js +23 -1
- package/dist/docx/verbatimCapture.js +4 -11
- package/dist/docx/vmlImageParser.js +2 -2
- package/dist/docx/watermarkParser.js +2 -2
- package/dist/docx/xmlParser.d.ts +22 -32
- package/dist/docx/xmlParser.js +36 -21
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
- package/dist/internal/paragraphFormattingSerialization.js +26 -6
- package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +2 -2
- package/dist/layout-engine/measure/measureBlocks.js +1 -6
- package/dist/layout-engine/types.d.ts +8 -2
- package/dist/layout-engine/types.js +35 -2
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/internals.d.ts +6 -1
- package/dist/markdown/internals.js +14 -1
- package/dist/markdown/renderBlock.js +35 -21
- package/dist/markdown/renderParagraph.js +14 -5
- package/dist/markdown/renderRuns.js +4 -3
- package/dist/markdown/renderTable.js +4 -3
- package/dist/markdown/trailers.js +41 -7
- package/dist/markdown/types.d.ts +3 -7
- package/dist/prosemirror/attrs/index.js +2 -5
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
- package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
- package/dist/prosemirror/commands/index.d.ts +3 -3
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/paragraph.d.ts +3 -3
- package/dist/prosemirror/commands/paragraph.js +2 -2
- package/dist/prosemirror/commentIdAllocator.js +2 -7
- package/dist/prosemirror/conversion/fromProseDoc.js +129 -40
- package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
- package/dist/prosemirror/conversion/toProseDoc.js +375 -316
- package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
- package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
- package/dist/prosemirror/extensions/types.d.ts +2 -2
- package/dist/prosemirror/index.d.ts +3 -3
- package/dist/prosemirror/index.js +3 -3
- package/dist/prosemirror/insertOperations.d.ts +9 -2
- package/dist/prosemirror/insertOperations.js +9 -4
- package/dist/prosemirror/paragraphFormattingProvenance.d.ts +159 -0
- package/dist/prosemirror/paragraphFormattingProvenance.js +106 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
- package/dist/prosemirror/plugins/documentStyles.js +11 -1
- package/dist/prosemirror/plugins/index.d.ts +2 -2
- package/dist/prosemirror/plugins/index.js +2 -2
- package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
- package/dist/prosemirror/plugins/revisionIds.js +21 -6
- package/dist/prosemirror/runFormattingReconciliation.js +3 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
- package/dist/prosemirror/schema/nodes.d.ts +31 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -0
- package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
- package/dist/prosemirror/styles/styleResolver.js +12 -0
- package/dist/style-engine/styleEngine.d.ts +3 -0
- package/dist/style-engine/styleEngine.js +3 -0
- package/dist/style-sets/extract.js +1 -23
- package/dist/style-sets/stellaStyle.js +46 -39
- package/dist/style-sets/styleSetNormalization.d.ts +19 -0
- package/dist/style-sets/styleSetNormalization.js +99 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/createDocument.js +145 -20
- package/dist/utils/headingCollector.d.ts +8 -5
- package/dist/utils/headingCollector.js +23 -25
- package/dist/utils/tableOfContentsStyle.js +9 -2
- package/package.json +2 -2
- package/dist/docx/textWhitespace.d.ts +0 -4
- package/dist/docx/textWhitespace.js +0 -4
- package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
- package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
- package/dist/markdown/headings.d.ts +0 -13
- package/dist/markdown/headings.js +0 -20
package/dist/docx/xmlParser.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { transitionalSlotEncoding } from "./transitionalSpelling.js";
|
|
1
|
+
import { NUMBERS_PER_PERCENT, percentageSpelling, transitionalSlotEncoding } from "./transitionalSpelling.js";
|
|
2
2
|
import { universalMeasureAs } from "./universalMeasure.js";
|
|
3
3
|
import { XMLBuilder, XMLParser } from "fast-xml-parser";
|
|
4
4
|
import { OOXML_NS } from "@stll/docx-utils";
|
|
5
|
+
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
5
6
|
//#region src/docx/xmlParser.ts
|
|
6
7
|
/**
|
|
7
8
|
* XML Parser Utilities for OOXML
|
|
@@ -481,17 +482,19 @@ function getTextContent(element) {
|
|
|
481
482
|
return text;
|
|
482
483
|
}
|
|
483
484
|
/**
|
|
484
|
-
*
|
|
485
|
+
* Read an `ST_OnOff` attribute.
|
|
485
486
|
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
487
|
+
* The type has three spellings per polarity — `1`/`true`/`on` and
|
|
488
|
+
* `0`/`false`/`off` — and producers use all of them. `undefined` means the
|
|
489
|
+
* author said nothing (absent, or a value outside the type), so the caller
|
|
490
|
+
* still owns what absence means for its own slot.
|
|
491
|
+
*
|
|
492
|
+
* Every on/off attribute goes through here: a hand-rolled `=== "1"` reads
|
|
493
|
+
* `w:beforeAutospacing="on"` as false, and the save path then writes `"0"`,
|
|
494
|
+
* inverting what the document said.
|
|
490
495
|
*/
|
|
491
|
-
function
|
|
492
|
-
|
|
493
|
-
if (value === null) return false;
|
|
494
|
-
return parseOnOffValue(value) ?? true;
|
|
496
|
+
function parseOnOffAttribute(element, namespace, name, context) {
|
|
497
|
+
return parseOnOffValue(getAttribute(element, namespace, name), context, element?.name ?? name);
|
|
495
498
|
}
|
|
496
499
|
/**
|
|
497
500
|
* Check if a child element exists (used for boolean flags in OOXML)
|
|
@@ -554,17 +557,19 @@ function parseNumberingLevelAttribute(element) {
|
|
|
554
557
|
return level !== void 0 && level >= 0 ? level : void 0;
|
|
555
558
|
}
|
|
556
559
|
/**
|
|
557
|
-
* Parse `w:w` on a table width/height element.
|
|
558
|
-
*
|
|
559
|
-
* (`5000`);
|
|
560
|
+
* Parse `w:w` on a table width/height element. A percentage may be spelled the
|
|
561
|
+
* way it reads (`100%`) or as the number its slot counts in
|
|
562
|
+
* (50ths-of-percent, `5000`); the generated slot table says which unit that
|
|
563
|
+
* is, so the two spellings are not decided here.
|
|
560
564
|
*/
|
|
561
565
|
function parseTableMeasurementValue(element, widthType) {
|
|
562
566
|
const raw = getAttribute(element, "w", "w");
|
|
563
567
|
if (raw === null) return;
|
|
564
568
|
const trimmed = raw.trim();
|
|
565
|
-
if (widthType === "pct"
|
|
566
|
-
const
|
|
567
|
-
|
|
569
|
+
if (widthType === "pct") {
|
|
570
|
+
const percent = percentageSpelling(trimmed);
|
|
571
|
+
const unit = element === null || element === void 0 ? void 0 : transitionalSlotEncoding(element.namespaceUri, getLocalName(element.name), "w")?.percent;
|
|
572
|
+
if (percent !== void 0 && unit !== void 0) return Math.round(percent * NUMBERS_PER_PERCENT[unit]);
|
|
568
573
|
}
|
|
569
574
|
const measure = universalMeasureAs(trimmed, "twips");
|
|
570
575
|
if (measure !== void 0) return measure;
|
|
@@ -573,8 +578,12 @@ function parseTableMeasurementValue(element, widthType) {
|
|
|
573
578
|
}
|
|
574
579
|
/**
|
|
575
580
|
* Parse an OOXML `ST_OnOff` lexical value.
|
|
581
|
+
*
|
|
582
|
+
* `context` is optional and trailing on purpose: every call site that has one
|
|
583
|
+
* reports the value folio declined to read, and the hundred that do not yet
|
|
584
|
+
* thread one keep compiling and keep their behaviour.
|
|
576
585
|
*/
|
|
577
|
-
function parseOnOffValue(value) {
|
|
586
|
+
function parseOnOffValue(value, context, element) {
|
|
578
587
|
if (value === null || value === void 0) return;
|
|
579
588
|
switch (value) {
|
|
580
589
|
case "1":
|
|
@@ -583,7 +592,13 @@ function parseOnOffValue(value) {
|
|
|
583
592
|
case "0":
|
|
584
593
|
case "false":
|
|
585
594
|
case "off": return false;
|
|
586
|
-
default:
|
|
595
|
+
default:
|
|
596
|
+
context?.warn({
|
|
597
|
+
code: PARSE_WARNING_CODES.unrecognisedOnOffValue,
|
|
598
|
+
value,
|
|
599
|
+
...element === void 0 ? {} : { element }
|
|
600
|
+
});
|
|
601
|
+
return;
|
|
587
602
|
}
|
|
588
603
|
}
|
|
589
604
|
/**
|
|
@@ -598,7 +613,7 @@ function parseOnOffValue(value) {
|
|
|
598
613
|
* @param namespace - Namespace for val attribute
|
|
599
614
|
* @returns boolean value
|
|
600
615
|
*/
|
|
601
|
-
function parseBooleanElement(element, namespace = "w") {
|
|
616
|
+
function parseBooleanElement(element, namespace = "w", context) {
|
|
602
617
|
if (!element) return false;
|
|
603
618
|
let val = null;
|
|
604
619
|
const elementName = element.name ?? "";
|
|
@@ -613,7 +628,7 @@ function parseBooleanElement(element, namespace = "w") {
|
|
|
613
628
|
}
|
|
614
629
|
}
|
|
615
630
|
if (val === null) return true;
|
|
616
|
-
return parseOnOffValue(val) ??
|
|
631
|
+
return parseOnOffValue(val, context, elementName) ?? false;
|
|
617
632
|
}
|
|
618
633
|
/**
|
|
619
634
|
* Deep find - search recursively for an element
|
|
@@ -810,4 +825,4 @@ function cloneElement(element, overrides) {
|
|
|
810
825
|
return clone;
|
|
811
826
|
}
|
|
812
827
|
//#endregion
|
|
813
|
-
export { NAMESPACES, OFFICE_RELATIONSHIP_NAMESPACE_URIS, OOXML_NAMESPACE_SCOPE, WORDPROCESSINGML_NAMESPACE_URIS, attachXmlNamespaceContext, cloneElement, cloneWithXmlnsDeclarations, collectXmlnsDeclarations, elementToXml, findAllDeep, findAttributeByNamespaceUri, findByFullName, findChild, findChildByLocalName, findChildByNamespaceUri, findChildren, findChildrenByLocalName, findChildrenByNamespaceUri, findDeep, getAttribute, getAttributeAny, getAttributeAnyPrefix, getAttributeByNamespaceUri, getAttributes, getChildElements, getLocalName, getNamespacePrefix, getNamespaceUri, getTextContent, hasChild,
|
|
828
|
+
export { NAMESPACES, OFFICE_RELATIONSHIP_NAMESPACE_URIS, OOXML_NAMESPACE_SCOPE, WORDPROCESSINGML_NAMESPACE_URIS, attachXmlNamespaceContext, cloneElement, cloneWithXmlnsDeclarations, collectXmlnsDeclarations, elementToXml, findAllDeep, findAttributeByNamespaceUri, findByFullName, findChild, findChildByLocalName, findChildByNamespaceUri, findChildren, findChildrenByLocalName, findChildrenByNamespaceUri, findDeep, getAttribute, getAttributeAny, getAttributeAnyPrefix, getAttributeByNamespaceUri, getAttributes, getChildElements, getLocalName, getNamespacePrefix, getNamespaceUri, getTextContent, hasChild, matchesName, mergeXmlnsDeclarations, parseBooleanElement, parseColorElement, parseNumberingLevelAttribute, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue, parseTableMeasurementValue, parseXml, parseXmlDocument, selectAlternateContentBranch };
|
|
@@ -59,7 +59,8 @@ const buildPageBreakRunSourceDescendantIndex = (rootContent) => {
|
|
|
59
59
|
case "deletion":
|
|
60
60
|
case "moveFrom":
|
|
61
61
|
case "moveTo":
|
|
62
|
-
case "inlineSdt":
|
|
62
|
+
case "inlineSdt":
|
|
63
|
+
case "bidiWrapper": return inspectMany(content.content, inspectParagraphContent);
|
|
63
64
|
case "simpleField": {
|
|
64
65
|
const fieldResultFlags = inspectMany(content.content, inspectParagraphContent);
|
|
65
66
|
if (hasFlag(fieldResultFlags, SOURCE_FLAGS.paragraphPageBreak) && hasFlag(fieldResultFlags, SOURCE_FLAGS.paragraphTextBoxShape)) return fieldResultFlags | SOURCE_FLAGS.pageBreakSharesTextBoxShape;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
//#region src/internal/paragraphFormattingSerialization.d.ts
|
|
3
|
-
type ExhaustiveFields<Source, Classified extends keyof Source> = Exclude<keyof Source, Classified> extends never ? Source : never;
|
|
4
3
|
type ParagraphNumberingReference = document_d_exports.ParagraphFormatting["numPr"] | null;
|
|
5
|
-
type ClassifiedParagraphFormattingField = "alignment" | "bidi" | "kinsoku" | "overflowPunctuation" | "spaceBefore" | "spaceAfter" | "lineSpacing" | "lineSpacingRule" | "snapToGrid" | "beforeAutospacing" | "afterAutospacing" | "spacingExplicit" | "indentLeft" | "indentRight" | "indentFirstLine" | "hangingIndent" | "borders" | "shading" | "tabs" | "keepNext" | "keepLines" | "widowControl" | "pageBreakBefore" | "contextualSpacing" | "numPr" | "numPrFromStyle" | "outlineLevel" | "styleId" | "frame" | "suppressLineNumbers" | "suppressAutoHyphens" | "runProperties" | "runInWithNext";
|
|
6
|
-
type ExhaustiveParagraphFormatting = ExhaustiveFields<document_d_exports.ParagraphFormatting, ClassifiedParagraphFormattingField>;
|
|
4
|
+
type ClassifiedParagraphFormattingField = "alignment" | "bidi" | "kinsoku" | "overflowPunctuation" | "spaceBefore" | "spaceAfter" | "lineSpacing" | "lineSpacingRule" | "snapToGrid" | "beforeAutospacing" | "afterAutospacing" | "spacingExplicit" | "indentLeft" | "indentRight" | "indentFirstLine" | "hangingIndent" | "borders" | "shading" | "tabs" | "keepNext" | "keepLines" | "widowControl" | "pageBreakBefore" | "contextualSpacing" | "numPr" | "numPrFromStyle" | "numberingChangeXml" | "outlineLevel" | "styleId" | "frame" | "suppressLineNumbers" | "suppressAutoHyphens" | "runProperties" | "runInWithNext";
|
|
5
|
+
type ExhaustiveParagraphFormatting = document_d_exports.ExhaustiveFields<document_d_exports.ParagraphFormatting, ClassifiedParagraphFormattingField>;
|
|
7
6
|
/** Compare numbering references by their emitted id and effective level. */
|
|
8
7
|
declare const paragraphNumberingReferencesEqual: (left: ParagraphNumberingReference, right: ParagraphNumberingReference) => boolean;
|
|
9
8
|
/** Compare the authored `w:numPr` attributes, including an absent `w:ilvl`. */
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { serializeBorder } from "../docx/serializer/borderSerializer.js";
|
|
2
2
|
import { serializeShading, serializeTextFormatting } from "../docx/serializer/textFormattingSerializer.js";
|
|
3
3
|
import { escapeXml, intAttr } from "../docx/serializer/xmlUtils.js";
|
|
4
|
+
import { sanitizeCapturedXmlElement } from "../docx/verbatimCapture.js";
|
|
5
|
+
import { NAMESPACES, OOXML_NAMESPACE_SCOPE } from "../docx/xmlParser.js";
|
|
4
6
|
//#region src/internal/paragraphFormattingSerialization.ts
|
|
5
7
|
const modelParagraphNumberingReference = (reference) => {
|
|
6
8
|
if (!reference) return null;
|
|
@@ -74,14 +76,32 @@ const serializeIndentation = (formatting) => {
|
|
|
74
76
|
}
|
|
75
77
|
return attrs.length === 0 ? "" : `<w:ind ${attrs.join(" ")}/>`;
|
|
76
78
|
};
|
|
77
|
-
|
|
79
|
+
/**
|
|
80
|
+
* `w:numPr`, with the tracked record of the numbering it replaced.
|
|
81
|
+
*
|
|
82
|
+
* `w:numberingChange` is the revision a reviewer's numbering change left
|
|
83
|
+
* behind. It is history: nothing in the model derives it, and a rebuilt
|
|
84
|
+
* `w:numPr` that drops it discards the revision silently. It is written even
|
|
85
|
+
* when the paragraph's own numbering reference is gone, because a change
|
|
86
|
+
* record with nothing left to describe is still a record — the schema declares
|
|
87
|
+
* it last in `CT_NumPr`, after `w:ilvl` and `w:numId`.
|
|
88
|
+
*/
|
|
89
|
+
const serializeNumbering = (numPr, numberingChangeXml) => {
|
|
78
90
|
const modeled = modelParagraphNumberingReference(numPr ?? null);
|
|
79
|
-
if (!modeled) return "";
|
|
80
91
|
const parts = [];
|
|
81
|
-
if (modeled
|
|
82
|
-
if (modeled
|
|
92
|
+
if (modeled?.ilvl !== void 0) parts.push(`<w:ilvl w:val="${intAttr(modeled.ilvl)}"/>`);
|
|
93
|
+
if (modeled?.numId !== void 0) parts.push(`<w:numId w:val="${intAttr(modeled.numId)}"/>`);
|
|
94
|
+
const change = replayableNumberingChangeXml(numberingChangeXml);
|
|
95
|
+
if (change !== null) parts.push(change);
|
|
83
96
|
return parts.length === 0 ? "" : `<w:numPr>${parts.join("")}</w:numPr>`;
|
|
84
97
|
};
|
|
98
|
+
const NUMBERING_CHANGE_ROOT_NAME = /* @__PURE__ */ new Set(["numberingChange"]);
|
|
99
|
+
const WORDPROCESSINGML_NAMESPACE = /* @__PURE__ */ new Set([NAMESPACES.w]);
|
|
100
|
+
const replayableNumberingChangeXml = (numberingChangeXml) => sanitizeCapturedXmlElement(numberingChangeXml, {
|
|
101
|
+
allowedLocalNames: NUMBERING_CHANGE_ROOT_NAME,
|
|
102
|
+
allowedNamespaceUris: WORDPROCESSINGML_NAMESPACE,
|
|
103
|
+
inheritedNamespaceScope: OOXML_NAMESPACE_SCOPE
|
|
104
|
+
});
|
|
85
105
|
const serializeFrameProperties = (frame) => {
|
|
86
106
|
if (!frame) return "";
|
|
87
107
|
const { dropCap, lines, width, height, hSpace, vSpace, hAnchor, vAnchor, x, y, xAlign, yAlign, wrap } = frame;
|
|
@@ -117,7 +137,7 @@ const extractRunPropertiesInnerXml = (runPropertiesXml) => {
|
|
|
117
137
|
*/
|
|
118
138
|
const modelParagraphFormattingEmission = (input) => {
|
|
119
139
|
if (!input) return {};
|
|
120
|
-
const { alignment, bidi, kinsoku, overflowPunctuation, spaceBefore, spaceAfter, lineSpacing, lineSpacingRule, snapToGrid, beforeAutospacing, afterAutospacing, spacingExplicit, indentLeft, indentRight, indentFirstLine, hangingIndent, borders, shading, tabs, keepNext, keepLines, widowControl, pageBreakBefore, contextualSpacing, numPr, numPrFromStyle, outlineLevel, styleId, frame, suppressLineNumbers, suppressAutoHyphens, runProperties, runInWithNext } = input;
|
|
140
|
+
const { alignment, bidi, kinsoku, overflowPunctuation, spaceBefore, spaceAfter, lineSpacing, lineSpacingRule, snapToGrid, beforeAutospacing, afterAutospacing, spacingExplicit, indentLeft, indentRight, indentFirstLine, hangingIndent, borders, shading, tabs, keepNext, keepLines, widowControl, pageBreakBefore, contextualSpacing, numPr, numPrFromStyle, numberingChangeXml, outlineLevel, styleId, frame, suppressLineNumbers, suppressAutoHyphens, runProperties, runInWithNext } = input;
|
|
121
141
|
modelSpacingProvenance(spacingExplicit);
|
|
122
142
|
const propertiesXml = [
|
|
123
143
|
styleId ? `<w:pStyle w:val="${escapeXml(styleId)}"/>` : "",
|
|
@@ -126,7 +146,7 @@ const modelParagraphFormattingEmission = (input) => {
|
|
|
126
146
|
serializeToggle("pageBreakBefore", pageBreakBefore),
|
|
127
147
|
serializeFrameProperties(frame),
|
|
128
148
|
serializeToggle("widowControl", widowControl),
|
|
129
|
-
isStyleSourcedParagraphNumbering(numPr, numPrFromStyle) ?
|
|
149
|
+
isStyleSourcedParagraphNumbering(numPr, numPrFromStyle) ? serializeNumbering(void 0, numberingChangeXml) : serializeNumbering(numPr, numberingChangeXml),
|
|
130
150
|
serializeToggle("suppressLineNumbers", suppressLineNumbers),
|
|
131
151
|
serializeParagraphBorders(borders),
|
|
132
152
|
serializeShading(shading),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { measureParagraph } from "../../layout-engine/measure/measureParagraph.js";
|
|
2
2
|
import { layoutTextBoxContent } from "../../layout-engine/measure/textBoxParagraphLayout.js";
|
|
3
|
-
import { DEFAULT_TEXTBOX_MARGINS, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, isFloatingImageRun } from "../../layout-engine/types.js";
|
|
3
|
+
import { DEFAULT_TEXTBOX_MARGINS, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, isFloatingImageRun, resolveTableWidthPx } from "../../layout-engine/types.js";
|
|
4
4
|
import { footnoteToProseDoc } from "../../prosemirror/conversion/toProseDoc.js";
|
|
5
5
|
import { toFlowBlocks } from "./toFlowBlocks.js";
|
|
6
6
|
//#region src/layout-bridge/convert/footnoteLayout.ts
|
|
@@ -264,14 +264,9 @@ function measureFootnoteBlock(block, contentWidth) {
|
|
|
264
264
|
default: return block;
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
|
-
function resolveFootnoteTableWidth(width, widthType, contentWidth) {
|
|
268
|
-
if (!width) return;
|
|
269
|
-
if (widthType === "pct") return contentWidth * width / 5e3;
|
|
270
|
-
if (widthType === "dxa" || !widthType || widthType === "auto") return width / 1440 * 96;
|
|
271
|
-
}
|
|
272
267
|
function measureFootnoteTable(tableBlock, contentWidth) {
|
|
273
268
|
let columnWidths = tableBlock.columnWidths ?? [];
|
|
274
|
-
const explicitWidth =
|
|
269
|
+
const explicitWidth = resolveTableWidthPx(tableBlock.width, tableBlock.widthType, contentWidth);
|
|
275
270
|
if (columnWidths.length === 0) {
|
|
276
271
|
const firstRow = tableBlock.rows.at(0);
|
|
277
272
|
let colCount = 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, tableColumnsArePinned } from "./types.js";
|
|
1
|
+
import { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, resolveTableWidthPx, tableColumnsArePinned } from "./types.js";
|
|
2
2
|
import { PageState, Paginator, PaginatorOptions, createPaginator } from "./paginator.js";
|
|
3
3
|
import { KeepNextChain, calculateChainHeight, computeKeepNextChains, getMidChainIndices, hasKeepLines, hasPageBreakBefore } from "./keep-together.js";
|
|
4
4
|
import { resolveSectionHeaderFooterRefs } from "./headerFooterRefs.js";
|
|
@@ -42,4 +42,4 @@ declare function layoutDocument(blocks: FlowBlock[], measures: Measure[], option
|
|
|
42
42
|
*/
|
|
43
43
|
declare function getHeaderRowsHeight(measure: TableMeasure, headerRowCount: number): number;
|
|
44
44
|
//#endregion
|
|
45
|
-
export { BlockId, BorderStyle, type BreakDecision, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, type KeepNextChain, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, type PageState, type Paginator, type PaginatorOptions, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionLayoutConfig, SectionPageNumbering, type SectionState, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, resolveTableCellPadding, scheduleSectionBreak, tableColumnsArePinned };
|
|
45
|
+
export { BlockId, BorderStyle, type BreakDecision, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, type KeepNextChain, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, type PageState, type Paginator, type PaginatorOptions, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionLayoutConfig, SectionPageNumbering, type SectionState, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, resolveTableCellPadding, resolveTableWidthPx, scheduleSectionBreak, tableColumnsArePinned };
|
|
@@ -14,7 +14,7 @@ import { applyPendingToActive, createInitialSectionState, getEffectiveColumns, g
|
|
|
14
14
|
import { applySectionVerticalAlignment } from "./sectionVerticalAlignment.js";
|
|
15
15
|
import { buildTableRowBreakInfo, getRowContinuationSkip, snapRowBreak } from "./tableRowBreak.js";
|
|
16
16
|
import { bandFragmentX, bandTopContentY, isPageFrameRelativeAnchor } from "./textBoxFlow.js";
|
|
17
|
-
import { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, tableColumnsArePinned } from "./types.js";
|
|
17
|
+
import { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, resolveTableWidthPx, tableColumnsArePinned } from "./types.js";
|
|
18
18
|
import { panic } from "better-result";
|
|
19
19
|
//#region src/layout-engine/index.ts
|
|
20
20
|
/**
|
|
@@ -1036,4 +1036,4 @@ function handleSectionBreak(_block, paginator, nextSectionConfig, nextSectionTyp
|
|
|
1036
1036
|
paginator.updateColumns(nextSectionConfig.columns ?? DEFAULT_COLUMNS);
|
|
1037
1037
|
}
|
|
1038
1038
|
//#endregion
|
|
1039
|
-
export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, resolveTableCellPadding, scheduleSectionBreak, tableColumnsArePinned };
|
|
1039
|
+
export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, applyContextualSpacing, applyPendingToActive, assertExhaustiveFlowBlock, calculateChainHeight, collectSectionConfigs, computeKeepNextChains, createInitialSectionState, createPaginator, findPageIndexContainingPmPos, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getEffectiveColumns, getEffectiveMargins, getEffectivePageSize, getHeaderRowsHeight, getMidChainIndices, getTableRowLeadingWidth, hasKeepLines, hasPageBreakBefore, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, layoutDocument, resolveSectionHeaderFooterRefs, resolveTableCellPadding, resolveTableWidthPx, scheduleSectionBreak, tableColumnsArePinned };
|
|
@@ -4,7 +4,7 @@ import { isParagraphFrameTextBox } from "../paragraphFrame.js";
|
|
|
4
4
|
import { normalizeSectionBreakType } from "../section-breaks.js";
|
|
5
5
|
import { bandFragmentX, bandTopContentY, isPageFrameRelativeAnchor } from "../textBoxFlow.js";
|
|
6
6
|
import { getTextBoxGroupId } from "../textBoxGroup.js";
|
|
7
|
-
import { DEFAULT_TEXTBOX_MARGINS, floatingTextBoxReservesBand, floatingTextBoxWrapsText, resolveTableCellPadding, tableColumnsArePinned } from "../types.js";
|
|
7
|
+
import { DEFAULT_TEXTBOX_MARGINS, floatingTextBoxReservesBand, floatingTextBoxWrapsText, resolveTableCellPadding, resolveTableWidthPx, tableColumnsArePinned } from "../types.js";
|
|
8
8
|
import { getCachedParagraphMeasure, setCachedParagraphMeasure } from "./cache.js";
|
|
9
9
|
import { resolveFloatingTablePageX } from "./floatingTablePosition.js";
|
|
10
10
|
import { findClearLineY, measureParagraph } from "./measureParagraph.js";
|
|
@@ -59,11 +59,6 @@ function emuToPixels(emu) {
|
|
|
59
59
|
if (emu === void 0) return 0;
|
|
60
60
|
return Math.round(emu * 96 / 914400);
|
|
61
61
|
}
|
|
62
|
-
function resolveTableWidthPx(width, widthType, contentWidth) {
|
|
63
|
-
if (!width) return;
|
|
64
|
-
if (widthType === "pct") return contentWidth * width / 5e3;
|
|
65
|
-
if (widthType === "dxa" || !widthType || widthType === "auto") return Math.round(width / 20 * 1.333);
|
|
66
|
-
}
|
|
67
62
|
function measureTableBlock(tableBlock, contentWidth, fieldValues) {
|
|
68
63
|
let columnWidths = tableBlock.columnWidths ?? [];
|
|
69
64
|
const explicitWidthPx = resolveTableWidthPx(tableBlock.width, tableBlock.widthType, contentWidth);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OutlineStyleAttr } from "../types/documentEnumValues.js";
|
|
2
2
|
import { ImagePosition, ImageWrap, NumberFormat, SdtProperties, SdtType, ShapeTextBody, TableCellFormatting, TableWidthType, VerticalAlign } from "@stll/docx-core/model";
|
|
3
3
|
declare namespace types_d_exports {
|
|
4
|
-
export { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, tableColumnsArePinned };
|
|
4
|
+
export { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, resolveTableWidthPx, tableColumnsArePinned };
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* Unique identifier for a block in the document.
|
|
@@ -1429,7 +1429,13 @@ declare function floatingTextBoxReservesBand(block: TextBoxFlowAttrs): boolean;
|
|
|
1429
1429
|
* and the painter both consult this so their line count and `white-space` agree.
|
|
1430
1430
|
*/
|
|
1431
1431
|
declare function tableColumnsArePinned(table: TableBlock): boolean;
|
|
1432
|
+
/**
|
|
1433
|
+
* Resolve a `w:tblW`/`w:tcW` pair to pixels. The single reader: measurement and
|
|
1434
|
+
* the footnote layout bridge both go through it so a table cannot be pinned in
|
|
1435
|
+
* one and autofitted in the other.
|
|
1436
|
+
*/
|
|
1437
|
+
declare function resolveTableWidthPx(width: number | undefined, widthType: TableWidthType | undefined, containerWidth: number): number | undefined;
|
|
1432
1438
|
/** Return the leading visual offset for a row with omitted grid columns. */
|
|
1433
1439
|
declare const getTableRowLeadingWidth: (row: TableRow, columnWidths: readonly number[]) => number;
|
|
1434
1440
|
//#endregion
|
|
1435
|
-
export { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, tableColumnsArePinned, types_d_exports };
|
|
1441
|
+
export { BlockId, BorderStyle, CellBorderSpec, CellBorders, ColumnBreakBlock, ColumnBreakMeasure, ColumnLayout, DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, DocumentPosition, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, FieldRun, FloatingTablePosition, FlowBlock, FootnoteContent, Fragment, FragmentBase, HeaderFooterContent, HeaderFooterContentHeights, HeaderFooterLayout, HitTestResult, HyperlinkInfo, ImageBlock, ImageFragment, ImageMeasure, ImageRun, ImageRunPosition, Layout, LayoutOptions, LineBreakRun, ListMarkerFormatting, ListNumPr, MathRun, Measure, MeasuredLine, Page, PageBreakBlock, PageBreakMeasure, PageHeaderFooterRefs, PageMargins, ParagraphAttrs, ParagraphBlock, ParagraphBorders, ParagraphFragment, ParagraphIndent, ParagraphMeasure, ParagraphSpacing, RenderedPageBreakRun, Run, RunFormatting, SdtGroup, SectionBreakBlock, SectionBreakMeasure, SectionPageNumbering, TabAlignment, TabRun, TabStop, TableBlock, TableCell, TableCellMeasure, TableFragment, TableMeasure, TableRow, TableRowMeasure, TextBoxBlock, TextBoxFlowAttrs, TextBoxFragment, TextBoxMeasure, TextRun, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, resolveTableWidthPx, tableColumnsArePinned, types_d_exports };
|
|
@@ -14,6 +14,7 @@ var types_exports = /* @__PURE__ */ __exportAll({
|
|
|
14
14
|
isFloatingTextBoxBlock: () => isFloatingTextBoxBlock,
|
|
15
15
|
isTextWrappingFloatingImageRun: () => isTextWrappingFloatingImageRun,
|
|
16
16
|
resolveTableCellPadding: () => resolveTableCellPadding,
|
|
17
|
+
resolveTableWidthPx: () => resolveTableWidthPx,
|
|
17
18
|
tableColumnsArePinned: () => tableColumnsArePinned
|
|
18
19
|
});
|
|
19
20
|
const DEFAULT_TABLE_CELL_PADDING = {
|
|
@@ -129,7 +130,39 @@ function floatingTextBoxReservesBand(block) {
|
|
|
129
130
|
*/
|
|
130
131
|
function tableColumnsArePinned(table) {
|
|
131
132
|
if (table.layout === "fixed") return true;
|
|
132
|
-
return table.widthType
|
|
133
|
+
return hasMeasuredTableWidth(table.widthType);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Whether `w:tblW`/`w:tcW`'s `w:w` is a measurement at all.
|
|
137
|
+
*
|
|
138
|
+
* Under `w:type="auto"` or `"nil"` (§17.18.87) the number is meaningless:
|
|
139
|
+
* `auto` asks the consumer to size the table to its content and `nil` declares
|
|
140
|
+
* no width, so both ignore `w:w` entirely. Word still writes a leftover value
|
|
141
|
+
* there, and reading it as twips pins a table that should autofit.
|
|
142
|
+
*/
|
|
143
|
+
function hasMeasuredTableWidth(widthType) {
|
|
144
|
+
switch (widthType) {
|
|
145
|
+
case "dxa":
|
|
146
|
+
case "pct": return true;
|
|
147
|
+
case "auto":
|
|
148
|
+
case "nil":
|
|
149
|
+
case void 0: return false;
|
|
150
|
+
default: return widthType;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const TWIPS_PER_INCH = 1440;
|
|
154
|
+
const PIXELS_PER_INCH = 96;
|
|
155
|
+
/** `w:type="pct"` measures in fiftieths of a percent, so 5000 is 100 %. */
|
|
156
|
+
const PERCENT_DENOMINATOR = 5e3;
|
|
157
|
+
/**
|
|
158
|
+
* Resolve a `w:tblW`/`w:tcW` pair to pixels. The single reader: measurement and
|
|
159
|
+
* the footnote layout bridge both go through it so a table cannot be pinned in
|
|
160
|
+
* one and autofitted in the other.
|
|
161
|
+
*/
|
|
162
|
+
function resolveTableWidthPx(width, widthType, containerWidth) {
|
|
163
|
+
if (width === void 0 || width <= 0 || !hasMeasuredTableWidth(widthType)) return;
|
|
164
|
+
if (widthType === "pct") return width / PERCENT_DENOMINATOR * containerWidth;
|
|
165
|
+
return width / TWIPS_PER_INCH * PIXELS_PER_INCH;
|
|
133
166
|
}
|
|
134
167
|
const tableRowOwnsNestedGrid = (row) => {
|
|
135
168
|
const cell = row.cells.length === 1 ? row.cells.at(0) : void 0;
|
|
@@ -142,4 +175,4 @@ const getTableRowLeadingWidth = (row, columnWidths) => {
|
|
|
142
175
|
return columnWidths.slice(0, row.gridBefore ?? 0).reduce((sum, columnWidth) => sum + columnWidth, 0);
|
|
143
176
|
};
|
|
144
177
|
//#endregion
|
|
145
|
-
export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, tableColumnsArePinned, types_exports };
|
|
178
|
+
export { DEFAULT_TEXTBOX_MARGINS, DEFAULT_TEXTBOX_WIDTH, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, floatingTextBoxReservesBand, floatingTextBoxWrapsText, getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun, resolveTableCellPadding, resolveTableWidthPx, tableColumnsArePinned, types_exports };
|
package/dist/markdown/index.js
CHANGED
|
@@ -19,7 +19,7 @@ function toMarkdownResult(doc, opts) {
|
|
|
19
19
|
return renderDocument(doc, opts);
|
|
20
20
|
}
|
|
21
21
|
function renderDocument(doc, opts = {}) {
|
|
22
|
-
const ctx = newContext(opts);
|
|
22
|
+
const ctx = newContext(opts, doc.package.styles);
|
|
23
23
|
const markdown = appendTrailers(ctx, doc, renderBlocks(ctx, doc.package, doc.package.document.content));
|
|
24
24
|
if (doc.warnings) ctx.warnings.unshift(...doc.warnings);
|
|
25
25
|
if (!markdown.trim()) ctx.warnings.push("document has no content");
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
1
2
|
import { MarkdownOptions, RenderContext } from "./types.js";
|
|
2
3
|
//#region src/markdown/internals.d.ts
|
|
3
4
|
/**
|
|
4
5
|
* Build a fresh `RenderContext` from caller options, applying defaults. The
|
|
5
6
|
* `footnotes` default is `"keep"` (folio addition over upstream #595).
|
|
7
|
+
*
|
|
8
|
+
* The document's styles are indexed once here: every paragraph asks the index
|
|
9
|
+
* whether it is a heading or a quote, so rebuilding it per paragraph would
|
|
10
|
+
* make the render quadratic.
|
|
6
11
|
*/
|
|
7
|
-
declare function newContext(opts?: MarkdownOptions): RenderContext;
|
|
12
|
+
declare function newContext(opts?: MarkdownOptions, styles?: document_d_exports.StyleDefinitions | undefined): RenderContext;
|
|
8
13
|
/**
|
|
9
14
|
* Push a warning into the context, deduplicating against existing entries so
|
|
10
15
|
* recurring messages appear at most once.
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
import { createBuiltInStyleIndex } from "../docx/builtInStyles.js";
|
|
1
2
|
//#region src/markdown/internals.ts
|
|
2
3
|
/**
|
|
4
|
+
* Internal helpers shared by the markdown converter: context construction and
|
|
5
|
+
* warning dedupe. Kept free of renderer imports so the renderers can import
|
|
6
|
+
* `pushWarning` without forming an import cycle (trailer emission, which needs
|
|
7
|
+
* `renderBlock`, lives in `trailers.ts`). Ported from eigenpal/docx-editor
|
|
8
|
+
* PR #595, trimmed to the sync continuous path.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
3
11
|
* Build a fresh `RenderContext` from caller options, applying defaults. The
|
|
4
12
|
* `footnotes` default is `"keep"` (folio addition over upstream #595).
|
|
13
|
+
*
|
|
14
|
+
* The document's styles are indexed once here: every paragraph asks the index
|
|
15
|
+
* whether it is a heading or a quote, so rebuilding it per paragraph would
|
|
16
|
+
* make the render quadratic.
|
|
5
17
|
*/
|
|
6
|
-
function newContext(opts = {}) {
|
|
18
|
+
function newContext(opts = {}, styles) {
|
|
7
19
|
return {
|
|
20
|
+
builtInStyles: createBuiltInStyleIndex(styles?.styles ?? [], styles?.docDefaults),
|
|
8
21
|
opts: {
|
|
9
22
|
annotations: opts.annotations ?? "html",
|
|
10
23
|
trackedChanges: opts.trackedChanges ?? "annotate",
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { cloneParagraphWithoutPropertySource } from "../docx/paragraphPropertySource.js";
|
|
2
2
|
import { renderParagraph } from "./renderParagraph.js";
|
|
3
3
|
import { renderTable } from "./renderTable.js";
|
|
4
|
+
import { panic } from "better-result";
|
|
4
5
|
//#region src/markdown/renderBlock.ts
|
|
5
6
|
/**
|
|
7
|
+
* Block-level dispatcher. Walks `BlockContent[]` and joins the rendered
|
|
8
|
+
* markdown for each block, suppressing redundant blank lines between list items
|
|
9
|
+
* of the same list. Ported from eigenpal/docx-editor PR #595.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
6
12
|
* In `trackedChanges: "clean"` mode every change is accepted. A paragraph whose
|
|
7
13
|
* end-of-paragraph mark is a pending deletion (`pPrMark.kind === "del"`) loses
|
|
8
14
|
* its break on accept and merges with the following paragraph. Word's join
|
|
@@ -34,30 +40,38 @@ function renderBlocks(ctx, pkg, blocks) {
|
|
|
34
40
|
const out = [];
|
|
35
41
|
let prevWasListItem = false;
|
|
36
42
|
const ordered = ctx.opts.trackedChanges === "clean" ? mergeAcceptedParagraphBreaks(blocks) : blocks;
|
|
37
|
-
for (const block of ordered)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
for (const block of ordered) switch (block.type) {
|
|
44
|
+
case "paragraph": {
|
|
45
|
+
const isListItem = !!block.listRendering && !block.listRendering.markerHidden;
|
|
46
|
+
const md = renderParagraph(ctx, pkg, block);
|
|
47
|
+
if (!md) {
|
|
48
|
+
prevWasListItem = false;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (isListItem && prevWasListItem) out.push(md);
|
|
52
|
+
else if (out.length) out.push("", md);
|
|
53
|
+
else out.push(md);
|
|
54
|
+
prevWasListItem = isListItem;
|
|
55
|
+
break;
|
|
43
56
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
out.push(md);
|
|
57
|
+
case "table": {
|
|
58
|
+
const md = renderTable(ctx, pkg, block);
|
|
59
|
+
if (md) {
|
|
60
|
+
if (out.length) out.push("");
|
|
61
|
+
out.push(md);
|
|
62
|
+
}
|
|
63
|
+
prevWasListItem = false;
|
|
64
|
+
break;
|
|
53
65
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
case "blockSdt": {
|
|
67
|
+
const nested = renderBlocks(ctx, pkg, block.content);
|
|
68
|
+
if (nested) {
|
|
69
|
+
if (out.length) out.push("");
|
|
70
|
+
out.push(nested);
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
60
73
|
}
|
|
74
|
+
default: panic(`Unsupported block content in markdown: ${JSON.stringify(block)}`);
|
|
61
75
|
}
|
|
62
76
|
return out.join("\n");
|
|
63
77
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { isQuoteStyle, resolveHeadingLevel } from "../docx/builtInStyles.js";
|
|
1
2
|
import { resolveListTemplate } from "../prosemirror/listMarker.js";
|
|
2
|
-
import { isHeadingStyle, parseHeadingLevel } from "./headings.js";
|
|
3
3
|
import { renderParagraphInline } from "./renderRuns.js";
|
|
4
4
|
//#region src/markdown/renderParagraph.ts
|
|
5
5
|
/**
|
|
@@ -8,7 +8,13 @@ import { renderParagraphInline } from "./renderRuns.js";
|
|
|
8
8
|
* marker preserved); plain prose → escaped inline content. Word's `Quote` /
|
|
9
9
|
* `IntenseQuote` styles become blockquotes. Ported from eigenpal/docx-editor
|
|
10
10
|
* PR #595.
|
|
11
|
+
*
|
|
12
|
+
* Which paragraphs those are is `builtInStyles`' decision, not this file's: the
|
|
13
|
+
* id `Nadpis1` and the id `Heading1` are the same heading, and `ClauseHeading1`
|
|
14
|
+
* is not one at all.
|
|
11
15
|
*/
|
|
16
|
+
/** Markdown has six heading levels; Word has nine. */
|
|
17
|
+
const MAX_MARKDOWN_HEADING_LEVEL = 6;
|
|
12
18
|
/**
|
|
13
19
|
* Render a paragraph and return the block text. No surrounding blank line: the
|
|
14
20
|
* caller joins blocks.
|
|
@@ -16,13 +22,16 @@ import { renderParagraphInline } from "./renderRuns.js";
|
|
|
16
22
|
function renderParagraph(ctx, pkg, para) {
|
|
17
23
|
const inline = renderParagraphInline(ctx, pkg, para.content, para.paraId);
|
|
18
24
|
const styleId = para.formatting?.styleId;
|
|
19
|
-
|
|
25
|
+
const headingLevel = resolveHeadingLevel({
|
|
26
|
+
outlineLevel: para.formatting?.outlineLevel,
|
|
27
|
+
styleId
|
|
28
|
+
}, ctx.builtInStyles);
|
|
29
|
+
if (headingLevel !== void 0) {
|
|
20
30
|
if (!inline) return "";
|
|
21
|
-
|
|
22
|
-
return `${"#".repeat(Math.max(1, Math.min(6, level)))} ${inline}`;
|
|
31
|
+
return `${"#".repeat(Math.min(MAX_MARKDOWN_HEADING_LEVEL, headingLevel + 1))} ${inline}`;
|
|
23
32
|
}
|
|
24
33
|
if (para.listRendering && !para.listRendering.markerHidden) return renderListItem(ctx, para.listRendering, inline);
|
|
25
|
-
if (styleId
|
|
34
|
+
if (isQuoteStyle(styleId, ctx.builtInStyles)) return inline.split("\n").map((line) => `> ${line}`).join("\n");
|
|
26
35
|
return escapeLeadingBlockMarker(inline);
|
|
27
36
|
}
|
|
28
37
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "../docx/relsParser.js";
|
|
1
2
|
import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
|
|
2
3
|
import { wrapComment, wrapDeletion, wrapInsertion, wrapMoveFrom, wrapMoveTo } from "./annotations.js";
|
|
3
4
|
import { escapeAltText, escapeInline, escapeLinkUrl } from "./escape.js";
|
|
@@ -88,8 +89,8 @@ function renderRunContent(ctx, pkg, content, paraId) {
|
|
|
88
89
|
break;
|
|
89
90
|
}
|
|
90
91
|
case "drawing": {
|
|
91
|
-
const ref = pkg?.relationships
|
|
92
|
-
const media = ref ? pkg?.media?.get(ref.target) : void 0;
|
|
92
|
+
const ref = resolveRelationshipIdOfType(pkg?.relationships, item.image.rId, RELATIONSHIP_TYPES.image);
|
|
93
|
+
const media = ref.status === "resolved" ? pkg?.media?.get(ref.relationship.target) : void 0;
|
|
93
94
|
if (media) {
|
|
94
95
|
const reg = registerImage(ctx, media, item.image, paraId);
|
|
95
96
|
const alt = reg.alt ? escapeAltText(reg.alt) : "";
|
|
@@ -101,7 +102,7 @@ function renderRunContent(ctx, pkg, content, paraId) {
|
|
|
101
102
|
out += ``;
|
|
102
103
|
break;
|
|
103
104
|
}
|
|
104
|
-
pushWarning(ctx, `image rId=${item.image.rId} not resolvable`);
|
|
105
|
+
pushWarning(ctx, `image rId=${item.image.rId ?? "(absent)"} not resolvable`);
|
|
105
106
|
break;
|
|
106
107
|
}
|
|
107
108
|
case "shape":
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "../docx/relsParser.js";
|
|
1
2
|
import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
|
|
2
3
|
import { escapeTableCell } from "./escape.js";
|
|
3
4
|
import { registerImage } from "./images.js";
|
|
@@ -185,8 +186,8 @@ function renderHtmlRun(ctx, pkg, run, paraId) {
|
|
|
185
186
|
break;
|
|
186
187
|
case "softHyphen": break;
|
|
187
188
|
case "drawing": {
|
|
188
|
-
const ref = pkg?.relationships
|
|
189
|
-
const media = ref ? pkg?.media?.get(ref.target) : void 0;
|
|
189
|
+
const ref = resolveRelationshipIdOfType(pkg?.relationships, item.image.rId, RELATIONSHIP_TYPES.image);
|
|
190
|
+
const media = ref.status === "resolved" ? pkg?.media?.get(ref.relationship.target) : void 0;
|
|
190
191
|
if (media) {
|
|
191
192
|
const reg = registerImage(ctx, media, item.image, paraId);
|
|
192
193
|
const alt = reg.alt ? escapeHtml(reg.alt) : "";
|
|
@@ -198,7 +199,7 @@ function renderHtmlRun(ctx, pkg, run, paraId) {
|
|
|
198
199
|
text += `<img src="${escapeHtml(item.image.src)}" alt="${alt}">`;
|
|
199
200
|
break;
|
|
200
201
|
}
|
|
201
|
-
pushWarning(ctx, `image rId=${item.image.rId} not resolvable`);
|
|
202
|
+
pushWarning(ctx, `image rId=${item.image.rId ?? "(absent)"} not resolvable`);
|
|
202
203
|
break;
|
|
203
204
|
}
|
|
204
205
|
case "footnoteRef":
|