@stll/folio-core 0.43.0 → 0.45.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/__fixtures__/paragraphs.js +2 -2
- package/dist/ai-edits/headless.js +7 -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 +94 -54
- package/dist/compare/inline-atoms.js +34 -20
- package/dist/compare/style-resources.js +6 -0
- package/dist/content-controls/mutateContentControls.js +4 -2
- package/dist/display-list/dom/renderDisplayListToDom.js +8 -8
- package/dist/document-operations.js +14 -3
- 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 +80 -42
- package/dist/docx/commentReferenceNormalization.d.ts +4 -1
- package/dist/docx/commentReferenceNormalization.js +23 -14
- package/dist/docx/commentThreadKey.d.ts +18 -0
- package/dist/docx/commentThreadKey.js +22 -0
- 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/diagramPreview.js +87 -27
- 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 +4 -4
- 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 +13 -17
- package/dist/docx/imageParser.d.ts +10 -2
- package/dist/docx/imageParser.js +80 -30
- package/dist/docx/imageRawXml.d.ts +14 -1
- package/dist/docx/imageRawXml.js +35 -11
- package/dist/docx/markupRangeMarker.d.ts +15 -0
- package/dist/docx/markupRangeMarker.js +44 -0
- package/dist/docx/mathToMathml.js +12 -14
- package/dist/docx/nonVisualDrawingProps.d.ts +34 -0
- package/dist/docx/nonVisualDrawingProps.js +46 -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/paragraphTextBoxEnrichment.js +3 -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 +83 -29
- package/dist/docx/previewBudget.d.ts +64 -0
- package/dist/docx/previewBudget.js +88 -0
- package/dist/docx/relsParser.d.ts +28 -11
- package/dist/docx/relsParser.js +26 -13
- package/dist/docx/revisionIdNormalization.js +96 -10
- package/dist/docx/rezip.js +80 -40
- 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/sdtPropertiesPatch.js +24 -18
- package/dist/docx/sectionParser.d.ts +2 -1
- package/dist/docx/sectionParser.js +21 -65
- package/dist/docx/sectionReferenceHistory.js +2 -2
- package/dist/docx/selectiveSave.js +6 -6
- package/dist/docx/serializer/blockSdtSerializer.js +38 -26
- package/dist/docx/serializer/borderSerializer.d.ts +2 -3
- package/dist/docx/serializer/borderSerializer.js +13 -12
- package/dist/docx/serializer/commentSerializer.d.ts +41 -16
- package/dist/docx/serializer/commentSerializer.js +82 -72
- package/dist/docx/serializer/documentSerializer.d.ts +1 -5
- package/dist/docx/serializer/documentSerializer.js +6 -16
- package/dist/docx/serializer/fontTableSerializer.js +6 -6
- package/dist/docx/serializer/headerFooterSerializer.js +10 -5
- 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/numberingSerializer.js +7 -6
- package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
- package/dist/docx/serializer/paragraphSerializer.js +47 -52
- package/dist/docx/serializer/partNamespaces.js +2 -2
- package/dist/docx/serializer/runSerializer.js +57 -31
- package/dist/docx/serializer/sectionPropertiesSerializer.js +11 -10
- package/dist/docx/serializer/settingsSerializer.js +4 -3
- package/dist/docx/serializer/stylesSerializer.js +6 -6
- package/dist/docx/serializer/tableSerializer.js +37 -21
- package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
- package/dist/docx/serializer/textFormattingSerializer.js +29 -28
- package/dist/docx/serializer/themeSerializer.js +6 -6
- package/dist/docx/serializer/trackedChangeAttributes.js +2 -2
- package/dist/docx/serializer/xmlUtils.d.ts +1 -2
- package/dist/docx/serializer/xmlUtils.js +1 -13
- package/dist/docx/server/boundedArchive.d.ts +12 -0
- package/dist/docx/server/boundedArchive.js +20 -1
- 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/server/validateDocxConformance.js +22 -1
- package/dist/docx/shadingParser.d.ts +6 -0
- package/dist/docx/shadingParser.js +32 -0
- package/dist/docx/shapeParser.js +10 -8
- 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 +11 -6
- 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/unzip.d.ts +23 -0
- package/dist/docx/unzip.js +32 -22
- package/dist/docx/verbatimCapture.js +5 -12
- package/dist/docx/vmlImageParser.js +5 -4
- package/dist/docx/vmlPreview.d.ts +1 -3
- package/dist/docx/vmlPreview.js +2 -30
- package/dist/docx/watermarkParser.js +2 -2
- package/dist/docx/xmlParser.d.ts +38 -33
- package/dist/docx/xmlParser.js +92 -47
- package/dist/docx/xmlResourceLimits.d.ts +89 -9
- package/dist/docx/xmlResourceLimits.js +105 -24
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
- package/dist/internal/paragraphFormattingSerialization.js +29 -8
- 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/layout-painter/renderImage.js +4 -3
- package/dist/layout-painter/renderParagraph.js +4 -3
- package/dist/managers/autoSaveCodec.js +2 -8
- package/dist/markdown/images.js +1 -4
- 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 +71 -5
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
- package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
- package/dist/prosemirror/commands/image.js +1 -0
- 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 +197 -68
- package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
- package/dist/prosemirror/conversion/toProseDoc.js +458 -335
- 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/HyperlinkExtension.js +2 -3
- 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 +6 -1
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +8 -2
- package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +8 -4
- 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 +162 -0
- package/dist/prosemirror/paragraphFormattingProvenance.js +115 -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 +81 -1
- 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/base64.d.ts +36 -0
- package/dist/utils/base64.js +40 -0
- package/dist/utils/clipboard.js +2 -1
- 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/dist/utils/units.d.ts +10 -1
- package/dist/utils/units.js +12 -1
- package/dist/utils/urlSecurity.d.ts +8 -2
- package/dist/utils/urlSecurity.js +21 -3
- 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
|
@@ -17,6 +17,23 @@ declare const BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING: {
|
|
|
17
17
|
lineSpacing: number;
|
|
18
18
|
lineSpacingRule: "auto";
|
|
19
19
|
};
|
|
20
|
+
type MintDefaultParagraphStyleOptions = {
|
|
21
|
+
takenStyleIds: ReadonlySet<string>;
|
|
22
|
+
/** Whether the source declared `w:docDefaults`, which the set carries over. */
|
|
23
|
+
hasDocDefaults: boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The default paragraph style a set needs when its source declared none.
|
|
27
|
+
*
|
|
28
|
+
* The id only has to be free, because the set is what defines it. The
|
|
29
|
+
* formatting has to be the built-in template's whenever the source had no
|
|
30
|
+
* `w:docDefaults`, because that is what the source itself rendered as: a
|
|
31
|
+
* consumer applies its built-in Normal only where no default paragraph style
|
|
32
|
+
* exists, and this minted style is one. Where the source did declare
|
|
33
|
+
* `w:docDefaults`, the set carries them and they remain authoritative, so the
|
|
34
|
+
* minted style states nothing.
|
|
35
|
+
*/
|
|
36
|
+
declare const mintDefaultParagraphStyle: ({ takenStyleIds, hasDocDefaults }: MintDefaultParagraphStyleOptions) => document_d_exports.Style;
|
|
20
37
|
declare const resolveDefaultParagraphStyle: (styles: Iterable<document_d_exports.Style>) => document_d_exports.Style | undefined;
|
|
21
38
|
//#endregion
|
|
22
|
-
export { BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, resolveDefaultParagraphStyle };
|
|
39
|
+
export { BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, mintDefaultParagraphStyle, resolveDefaultParagraphStyle };
|
|
@@ -16,6 +16,28 @@ const BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING = {
|
|
|
16
16
|
lineSpacing: 259,
|
|
17
17
|
lineSpacingRule: "auto"
|
|
18
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* The default paragraph style a set needs when its source declared none.
|
|
21
|
+
*
|
|
22
|
+
* The id only has to be free, because the set is what defines it. The
|
|
23
|
+
* formatting has to be the built-in template's whenever the source had no
|
|
24
|
+
* `w:docDefaults`, because that is what the source itself rendered as: a
|
|
25
|
+
* consumer applies its built-in Normal only where no default paragraph style
|
|
26
|
+
* exists, and this minted style is one. Where the source did declare
|
|
27
|
+
* `w:docDefaults`, the set carries them and they remain authoritative, so the
|
|
28
|
+
* minted style states nothing.
|
|
29
|
+
*/
|
|
30
|
+
const mintDefaultParagraphStyle = ({ takenStyleIds, hasDocDefaults }) => {
|
|
31
|
+
let styleId = BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID;
|
|
32
|
+
for (let suffix = 1; takenStyleIds.has(styleId); suffix += 1) styleId = `${BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID}${suffix}`;
|
|
33
|
+
return {
|
|
34
|
+
styleId,
|
|
35
|
+
type: "paragraph",
|
|
36
|
+
name: BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME,
|
|
37
|
+
default: true,
|
|
38
|
+
...hasDocDefaults ? {} : { pPr: { ...BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING } }
|
|
39
|
+
};
|
|
40
|
+
};
|
|
19
41
|
const resolveDefaultParagraphStyle = (styles) => {
|
|
20
42
|
let flagged;
|
|
21
43
|
let namedBuiltIn;
|
|
@@ -29,4 +51,4 @@ const resolveDefaultParagraphStyle = (styles) => {
|
|
|
29
51
|
return flagged ?? namedBuiltIn ?? idBuiltIn;
|
|
30
52
|
};
|
|
31
53
|
//#endregion
|
|
32
|
-
export { BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, resolveDefaultParagraphStyle };
|
|
54
|
+
export { BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, mintDefaultParagraphStyle, resolveDefaultParagraphStyle };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { bytesToDataUrl } from "../utils/base64.js";
|
|
2
|
+
import { PREVIEW_KINDS } from "./previewBudget.js";
|
|
3
|
+
import { resolveRelationshipIdOfType, resolveRelativePath } from "./relsParser.js";
|
|
4
|
+
import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, findChildByNamespaceUri, getAttribute, getAttributeByNamespaceUri, getLocalName, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
|
|
3
5
|
//#region src/docx/diagramPreview.ts
|
|
4
6
|
const MAX_PREVIEW_SHAPES = 128;
|
|
5
7
|
const MAX_PREVIEW_PIXELS = 144e4;
|
|
@@ -7,21 +9,47 @@ const MAX_PREVIEW_PAINT_PIXELS = MAX_PREVIEW_PIXELS * 4;
|
|
|
7
9
|
const DRAWINGML_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/main", "http://purl.oclc.org/ooxml/drawingml/main"]);
|
|
8
10
|
const DIAGRAM_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/diagram", "http://purl.oclc.org/ooxml/drawingml/diagram"]);
|
|
9
11
|
const DIAGRAM_DRAWING_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.microsoft.com/office/drawing/2008/diagram"]);
|
|
12
|
+
const DIAGRAM_DATA_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData";
|
|
13
|
+
const DIAGRAM_DRAWING_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/office/2007/relationships/diagramDrawing";
|
|
14
|
+
const DOCUMENT_PART_PATH = "word/document.xml";
|
|
10
15
|
const WORD_DRAWING_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "http://purl.oclc.org/ooxml/drawingml/wordprocessingDrawing"]);
|
|
16
|
+
/**
|
|
17
|
+
* The preview is a megapixel raster, so both checksums run over megabytes.
|
|
18
|
+
* `for (const byte of bytes)` drives the array iterator protocol once per
|
|
19
|
+
* byte, which profiles as the dominant cost of parsing a SmartArt document;
|
|
20
|
+
* indexed loops and a table-driven CRC produce the same numbers without it.
|
|
21
|
+
*/
|
|
22
|
+
const CRC32_TABLE = (() => {
|
|
23
|
+
const table = /* @__PURE__ */ new Uint32Array(256);
|
|
24
|
+
for (let index = 0; index < 256; index += 1) {
|
|
25
|
+
let value = index;
|
|
26
|
+
for (let bit = 0; bit < 8; bit += 1) value = value >>> 1 ^ (value & 1 ? 3988292384 : 0);
|
|
27
|
+
table[index] = value >>> 0;
|
|
28
|
+
}
|
|
29
|
+
return table;
|
|
30
|
+
})();
|
|
11
31
|
const crc32 = (bytes) => {
|
|
12
32
|
let crc = 4294967295;
|
|
13
|
-
for (
|
|
14
|
-
crc ^= byte;
|
|
15
|
-
for (let bit = 0; bit < 8; bit += 1) crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
|
|
16
|
-
}
|
|
33
|
+
for (let index = 0; index < bytes.length; index += 1) crc = crc >>> 8 ^ CRC32_TABLE[(crc ^ bytes[index]) & 255];
|
|
17
34
|
return (crc ^ 4294967295) >>> 0;
|
|
18
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* `a` and `b` stay below 2^31 for 5552 iterations from any legal state, so the
|
|
38
|
+
* modulo runs per block rather than per byte.
|
|
39
|
+
*/
|
|
40
|
+
const ADLER32_BLOCK = 5552;
|
|
19
41
|
const adler32 = (bytes) => {
|
|
20
42
|
let a = 1;
|
|
21
43
|
let b = 0;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
44
|
+
let index = 0;
|
|
45
|
+
while (index < bytes.length) {
|
|
46
|
+
const end = Math.min(index + ADLER32_BLOCK, bytes.length);
|
|
47
|
+
for (; index < end; index += 1) {
|
|
48
|
+
a += bytes[index];
|
|
49
|
+
b += a;
|
|
50
|
+
}
|
|
51
|
+
a %= 65521;
|
|
52
|
+
b %= 65521;
|
|
25
53
|
}
|
|
26
54
|
return b << 16 | a;
|
|
27
55
|
};
|
|
@@ -88,9 +116,8 @@ const previewPng = (width, height, shapes) => {
|
|
|
88
116
|
cursor += length;
|
|
89
117
|
offset += length;
|
|
90
118
|
}
|
|
91
|
-
|
|
92
|
-
output
|
|
93
|
-
new DataView(output.buffer).setUint32(cursor, adler32(pixels));
|
|
119
|
+
new DataView(compressed.buffer).setUint32(cursor, adler32(pixels));
|
|
120
|
+
const output = compressed;
|
|
94
121
|
const signature = new Uint8Array([
|
|
95
122
|
137,
|
|
96
123
|
80,
|
|
@@ -127,13 +154,38 @@ const extent = (drawing) => {
|
|
|
127
154
|
height: parseNumericAttribute(value, null, "cy") ?? 0
|
|
128
155
|
};
|
|
129
156
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const file = media.get(
|
|
135
|
-
|
|
136
|
-
|
|
157
|
+
/** Parse the part a relationship of the given type names, by that relationship's id. */
|
|
158
|
+
const partByRelationshipId = ({ rels, media, rId, type }) => {
|
|
159
|
+
const resolved = resolveRelationshipIdOfType(rels, rId ?? void 0, type);
|
|
160
|
+
if (resolved.status !== "resolved" || !resolved.relationship.target) return null;
|
|
161
|
+
const file = media.get(resolveRelativePath(DOCUMENT_PART_PATH, resolved.relationship.target));
|
|
162
|
+
return file?.data ? parseXmlDocument(new TextDecoder().decode(file.data)) : null;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* The drawing cache this diagram points at, reached through its own ids.
|
|
166
|
+
*
|
|
167
|
+
* `dgm:relIds/@r:dm` names the data part, and that part's `dsp:dataModelExt`
|
|
168
|
+
* extension names the cached drawing. Scanning the relationship map for a type
|
|
169
|
+
* instead of following the ids reads the wrong diagram whenever a document has
|
|
170
|
+
* more than one, which is why the scan refused outright on a second match:
|
|
171
|
+
* both diagrams in a two-diagram document then got no preview at all.
|
|
172
|
+
*/
|
|
173
|
+
const cachedDiagramShapes = (graphicData, rels, media) => {
|
|
174
|
+
const relIds = findChildByNamespaceUri(graphicData, DIAGRAM_NAMESPACE_URIS, "relIds");
|
|
175
|
+
const data = partByRelationshipId({
|
|
176
|
+
rels,
|
|
177
|
+
media,
|
|
178
|
+
rId: getAttributeByNamespaceUri(relIds, OFFICE_RELATIONSHIP_NAMESPACE_URIS, "dm"),
|
|
179
|
+
type: DIAGRAM_DATA_RELATIONSHIP_TYPE
|
|
180
|
+
});
|
|
181
|
+
if (!data) return [];
|
|
182
|
+
const dataModelExt = descendantsByNamespace(data, DIAGRAM_DRAWING_NAMESPACE_URIS, "dataModelExt").at(0);
|
|
183
|
+
const root = partByRelationshipId({
|
|
184
|
+
rels,
|
|
185
|
+
media,
|
|
186
|
+
rId: getAttribute(dataModelExt, null, "relId"),
|
|
187
|
+
type: DIAGRAM_DRAWING_RELATIONSHIP_TYPE
|
|
188
|
+
});
|
|
137
189
|
if (!root) return [];
|
|
138
190
|
const shapes = [];
|
|
139
191
|
for (const shape of descendantsByNamespace(root, DIAGRAM_DRAWING_NAMESPACE_URIS, "sp").slice(0, MAX_PREVIEW_SHAPES)) {
|
|
@@ -155,31 +207,39 @@ const cachedDiagramShapes = (rels, media) => {
|
|
|
155
207
|
}
|
|
156
208
|
return shapes;
|
|
157
209
|
};
|
|
210
|
+
const matchesNamespace = (element, namespaceUris, localName) => element.namespaceUri !== void 0 && namespaceUris.has(element.namespaceUri) && getLocalName(element.name ?? "") === localName;
|
|
158
211
|
const descendantsByNamespace = (root, namespaceUris, localName) => {
|
|
159
212
|
const result = [];
|
|
160
213
|
const visit = (element) => {
|
|
161
|
-
if (element
|
|
214
|
+
if (matchesNamespace(element, namespaceUris, localName)) result.push(element);
|
|
162
215
|
for (const child of element.elements ?? []) if (child.type === "element") visit(child);
|
|
163
216
|
};
|
|
164
217
|
visit(root);
|
|
165
218
|
return result;
|
|
166
219
|
};
|
|
220
|
+
/** The first match in document order, without walking the rest of the subtree. */
|
|
221
|
+
const firstDescendantByNamespace = (root, namespaceUris, localName) => {
|
|
222
|
+
if (matchesNamespace(root, namespaceUris, localName)) return root;
|
|
223
|
+
for (const child of root.elements ?? []) {
|
|
224
|
+
if (child.type !== "element") continue;
|
|
225
|
+
const found = firstDescendantByNamespace(child, namespaceUris, localName);
|
|
226
|
+
if (found) return found;
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
};
|
|
167
230
|
/** Create a deliberately simple, bounded preview; it is never an editable diagram projection. */
|
|
168
231
|
const parseDiagramPreview = (drawing, rels, media) => {
|
|
169
232
|
if (!rels || !media) return null;
|
|
170
|
-
const graphicData =
|
|
233
|
+
const graphicData = firstDescendantByNamespace(drawing, DRAWINGML_NAMESPACE_URIS, "graphicData");
|
|
171
234
|
if (!graphicData || !DIAGRAM_NAMESPACE_URIS.has(getAttribute(graphicData, null, "uri") ?? "")) return null;
|
|
172
235
|
const { width, height } = extent(drawing);
|
|
173
236
|
if (width <= 0 || height <= 0) return null;
|
|
174
|
-
const png = previewPng(width, height, cachedDiagramShapes(rels, media));
|
|
175
|
-
let binary = "";
|
|
176
|
-
for (let offset = 0; offset < png.length; offset += 32768) binary += String.fromCodePoint(...png.subarray(offset, offset + 32768));
|
|
177
237
|
return {
|
|
178
238
|
type: "image",
|
|
179
239
|
rId: "",
|
|
180
|
-
src:
|
|
181
|
-
mimeType:
|
|
182
|
-
filename:
|
|
240
|
+
src: bytesToDataUrl(previewPng(width, height, cachedDiagramShapes(graphicData, rels, media)), PREVIEW_KINDS.smartArt.mimeType),
|
|
241
|
+
mimeType: PREVIEW_KINDS.smartArt.mimeType,
|
|
242
|
+
filename: PREVIEW_KINDS.smartArt.filename,
|
|
183
243
|
size: {
|
|
184
244
|
width,
|
|
185
245
|
height
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { NumberingMap } from "./numberingParser.js";
|
|
3
3
|
import { StyleMap } from "./styleParser.js";
|
|
4
|
+
import { ParseContext } from "./parseContext.js";
|
|
4
5
|
//#region src/docx/documentParser.d.ts
|
|
5
6
|
/**
|
|
6
7
|
* Extract template variables from text
|
|
@@ -27,7 +28,7 @@ declare function extractAllTemplateVariables(content: document_d_exports.BlockCo
|
|
|
27
28
|
* @param media - Media files
|
|
28
29
|
* @returns DocumentBody with content, sections, and template variables
|
|
29
30
|
*/
|
|
30
|
-
declare function parseDocumentBody(xml: string, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null): document_d_exports.DocumentBody;
|
|
31
|
+
declare function parseDocumentBody(xml: string, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext): document_d_exports.DocumentBody;
|
|
31
32
|
/**
|
|
32
33
|
* Get all paragraphs from document body (flattened)
|
|
33
34
|
*/
|
|
@@ -119,7 +119,7 @@ function canonicalizeLeadingBodySectionProperties(bodyElement, body) {
|
|
|
119
119
|
* @param media - Media files
|
|
120
120
|
* @returns DocumentBody with content, sections, and template variables
|
|
121
121
|
*/
|
|
122
|
-
function parseDocumentBody(xml, styles = null, theme = null, numbering = null, rels = null, media = null) {
|
|
122
|
+
function parseDocumentBody(xml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
|
|
123
123
|
const result = { content: [] };
|
|
124
124
|
if (!xml) return result;
|
|
125
125
|
const streamed = parseStreamingXml(xml);
|
|
@@ -129,7 +129,7 @@ function parseDocumentBody(xml, styles = null, theme = null, numbering = null, r
|
|
|
129
129
|
if (!bodyEl) return result;
|
|
130
130
|
result.content = parseBlockContent(bodyEl, styles, theme, numbering, rels, media, { rootXmlns: collectXmlnsDeclarations(documentEl) });
|
|
131
131
|
const finalSectPr = findChild(bodyEl, "w", "sectPr");
|
|
132
|
-
if (finalSectPr) result.finalSectionProperties = parseSectionProperties(finalSectPr);
|
|
132
|
+
if (finalSectPr) result.finalSectionProperties = parseSectionProperties(finalSectPr, context);
|
|
133
133
|
canonicalizeLeadingBodySectionProperties(bodyEl, result);
|
|
134
134
|
result.sections = buildSections(result.content, result.finalSectionProperties);
|
|
135
135
|
return result;
|
|
@@ -67,6 +67,13 @@ declare function parseWrapElement(wrapEl: XmlElement | null, behindDoc: boolean,
|
|
|
67
67
|
/**
|
|
68
68
|
* Parse wrap from an anchor element (finds wrap child internally).
|
|
69
69
|
*/
|
|
70
|
+
/**
|
|
71
|
+
* Read `wp:anchor/@behindDoc`, the flag that puts an anchored object behind the
|
|
72
|
+
* body text. The attribute is xsd:boolean, so `1`, `0`, `true` and `false` are
|
|
73
|
+
* all legal spellings and producers differ: Word writes `1`, others `true`.
|
|
74
|
+
* Absent means in front of the text.
|
|
75
|
+
*/
|
|
76
|
+
declare function parseAnchorBehindDoc(anchor: XmlElement): boolean;
|
|
70
77
|
declare function parseAnchorWrap(anchor: XmlElement): document_d_exports.ImageWrap | undefined;
|
|
71
78
|
/**
|
|
72
79
|
* Resolve a ColorValue to a CSS hex string using default theme colors.
|
|
@@ -74,4 +81,4 @@ declare function parseAnchorWrap(anchor: XmlElement): document_d_exports.ImageWr
|
|
|
74
81
|
*/
|
|
75
82
|
declare function resolveColorValueToHex(color: document_d_exports.ColorValue | undefined): string | undefined;
|
|
76
83
|
//#endregion
|
|
77
|
-
export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
|
|
84
|
+
export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorBehindDoc, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, ShapeOutlineStyleSchema, narrowEnum } from "./parserEnums.js";
|
|
2
2
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
3
|
-
import { findByFullName, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getTextContent, parseNumericAttribute } from "./xmlParser.js";
|
|
3
|
+
import { findByFullName, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getTextContent, parseNumericAttribute, parseOnOffValue } from "./xmlParser.js";
|
|
4
4
|
//#region src/docx/drawingUtils.ts
|
|
5
5
|
/**
|
|
6
6
|
* Map OOXML scheme names to standard theme color slots.
|
|
@@ -361,9 +361,18 @@ function parseWrapElement(wrapEl, behindDoc, anchorDistances) {
|
|
|
361
361
|
/**
|
|
362
362
|
* Parse wrap from an anchor element (finds wrap child internally).
|
|
363
363
|
*/
|
|
364
|
+
/**
|
|
365
|
+
* Read `wp:anchor/@behindDoc`, the flag that puts an anchored object behind the
|
|
366
|
+
* body text. The attribute is xsd:boolean, so `1`, `0`, `true` and `false` are
|
|
367
|
+
* all legal spellings and producers differ: Word writes `1`, others `true`.
|
|
368
|
+
* Absent means in front of the text.
|
|
369
|
+
*/
|
|
370
|
+
function parseAnchorBehindDoc(anchor) {
|
|
371
|
+
return parseOnOffValue(getAttribute(anchor, null, "behindDoc")) ?? false;
|
|
372
|
+
}
|
|
364
373
|
function parseAnchorWrap(anchor) {
|
|
365
374
|
const children = getChildElements(anchor);
|
|
366
|
-
const behindDoc =
|
|
375
|
+
const behindDoc = parseAnchorBehindDoc(anchor);
|
|
367
376
|
const wrapEl = children.find((el) => WRAP_ELEMENT_NAMES.includes(el.name ?? ""));
|
|
368
377
|
const distT = parseNumericAttribute(anchor, null, "distT");
|
|
369
378
|
const distB = parseNumericAttribute(anchor, null, "distB");
|
|
@@ -409,4 +418,4 @@ function resolveColorValueToHex(color) {
|
|
|
409
418
|
if (color.themeColor) return `#${DEFAULT_THEME_COLOR_HEX[color.themeColor] ?? "000000"}`;
|
|
410
419
|
}
|
|
411
420
|
//#endregion
|
|
412
|
-
export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
|
|
421
|
+
export { THEME_COLOR_TO_DRAWING_SCHEME, WRAP_ELEMENT_NAMES, parseAnchorBehindDoc, parseAnchorPosition, parseAnchorWrap, parseColorElement, parseFill, parseOutline, parsePositionH, parsePositionV, parseWrapElement, resolveColorValueToHex };
|
package/dist/docx/fieldParser.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
|
|
2
2
|
import { FieldTypeSchema, narrowEnum } from "./parserEnums.js";
|
|
3
3
|
import { parseRun } from "./runParser.js";
|
|
4
|
-
import { findChildren, getAttribute } from "./xmlParser.js";
|
|
4
|
+
import { findChildren, getAttribute, parseOnOffAttribute } from "./xmlParser.js";
|
|
5
5
|
//#region src/docx/fieldParser.ts
|
|
6
6
|
/**
|
|
7
7
|
* All known field types from OOXML specification
|
|
@@ -164,10 +164,8 @@ function parseSimpleField(node, styles, theme) {
|
|
|
164
164
|
fieldType: parseFieldType(instruction),
|
|
165
165
|
content: []
|
|
166
166
|
};
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
const dirty = getAttribute(node, "w", "dirty");
|
|
170
|
-
if (dirty === "1" || dirty === "true") field.dirty = true;
|
|
167
|
+
if (parseOnOffAttribute(node, "w", "fldLock") === true) field.fldLock = true;
|
|
168
|
+
if (parseOnOffAttribute(node, "w", "dirty") === true) field.dirty = true;
|
|
171
169
|
const children = findChildren(node, "w", "r");
|
|
172
170
|
for (const child of children) {
|
|
173
171
|
const run = parseRun(child, styles, theme);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { NumberingMap } from "./numberingParser.js";
|
|
3
3
|
import { StyleMap } from "./styleParser.js";
|
|
4
|
+
import { ParseContext } from "./parseContext.js";
|
|
4
5
|
import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
|
|
5
6
|
//#region src/docx/footnoteParser.d.ts
|
|
6
7
|
/**
|
|
@@ -52,7 +53,7 @@ type EndnoteMap = {
|
|
|
52
53
|
* @param media - Media files for images
|
|
53
54
|
* @returns FootnoteMap with all footnotes
|
|
54
55
|
*/
|
|
55
|
-
declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null): FootnoteMap;
|
|
56
|
+
declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext): FootnoteMap;
|
|
56
57
|
/**
|
|
57
58
|
* Parse endnotes.xml
|
|
58
59
|
*
|
|
@@ -64,7 +65,7 @@ declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap |
|
|
|
64
65
|
* @param media - Media files for images
|
|
65
66
|
* @returns EndnoteMap with all endnotes
|
|
66
67
|
*/
|
|
67
|
-
declare function parseEndnotes(endnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null): EndnoteMap;
|
|
68
|
+
declare function parseEndnotes(endnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext): EndnoteMap;
|
|
68
69
|
/**
|
|
69
70
|
* Get plain text content of a footnote.
|
|
70
71
|
*
|
|
@@ -4,6 +4,7 @@ import { parseParagraph } from "./paragraphParser.js";
|
|
|
4
4
|
import { parseSdtProperties } from "./sdtProperties.js";
|
|
5
5
|
import { parseTable } from "./tableParser.js";
|
|
6
6
|
import { findChild, findChildren, getAttributes, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
|
|
7
|
+
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
7
8
|
//#region src/docx/footnoteParser.ts
|
|
8
9
|
/**
|
|
9
10
|
* Parse note type attribute
|
|
@@ -69,7 +70,7 @@ function parseFootnote(element, styles, theme, numbering, rels, media) {
|
|
|
69
70
|
* @param media - Media files for images
|
|
70
71
|
* @returns FootnoteMap with all footnotes
|
|
71
72
|
*/
|
|
72
|
-
function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null) {
|
|
73
|
+
function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
|
|
73
74
|
const byId = /* @__PURE__ */ new Map();
|
|
74
75
|
const footnotes = [];
|
|
75
76
|
if (!footnotesXml) return createFootnoteMap(byId, footnotes);
|
|
@@ -78,7 +79,14 @@ function parseFootnotes(footnotesXml, styles = null, theme = null, numbering = n
|
|
|
78
79
|
const footnoteElements = findChildren(rootElement, "w", "footnote");
|
|
79
80
|
for (const fnEl of footnoteElements) {
|
|
80
81
|
const footnote = parseFootnote(fnEl, styles, theme, numbering, rels, media);
|
|
81
|
-
if (byId.has(footnote.id))
|
|
82
|
+
if (byId.has(footnote.id)) {
|
|
83
|
+
context?.warn({
|
|
84
|
+
code: PARSE_WARNING_CODES.duplicateNoteId,
|
|
85
|
+
element: "w:footnote",
|
|
86
|
+
at: `w:id ${String(footnote.id)}`
|
|
87
|
+
});
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
82
90
|
byId.set(footnote.id, footnote);
|
|
83
91
|
footnotes.push(footnote);
|
|
84
92
|
}
|
|
@@ -130,7 +138,7 @@ function parseEndnote(element, styles, theme, numbering, rels, media) {
|
|
|
130
138
|
* @param media - Media files for images
|
|
131
139
|
* @returns EndnoteMap with all endnotes
|
|
132
140
|
*/
|
|
133
|
-
function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null) {
|
|
141
|
+
function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = null, rels = null, media = null, context) {
|
|
134
142
|
const byId = /* @__PURE__ */ new Map();
|
|
135
143
|
const endnotes = [];
|
|
136
144
|
if (!endnotesXml) return createEndnoteMap(byId, endnotes);
|
|
@@ -139,7 +147,14 @@ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = nul
|
|
|
139
147
|
const endnoteElements = findChildren(rootElement, "w", "endnote");
|
|
140
148
|
for (const enEl of endnoteElements) {
|
|
141
149
|
const endnote = parseEndnote(enEl, styles, theme, numbering, rels, media);
|
|
142
|
-
if (byId.has(endnote.id))
|
|
150
|
+
if (byId.has(endnote.id)) {
|
|
151
|
+
context?.warn({
|
|
152
|
+
code: PARSE_WARNING_CODES.duplicateNoteId,
|
|
153
|
+
element: "w:endnote",
|
|
154
|
+
at: `w:id ${String(endnote.id)}`
|
|
155
|
+
});
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
143
158
|
byId.set(endnote.id, endnote);
|
|
144
159
|
endnotes.push(endnote);
|
|
145
160
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { emuToPixels } from "../utils/units.js";
|
|
2
2
|
import { parseImage, resolveImageData } from "./imageParser.js";
|
|
3
3
|
import { findAllDeep, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getLocalName, getTextContent, parseNumericAttribute } from "./xmlParser.js";
|
|
4
|
+
import { escapeXmlAttribute, escapeXmlText } from "@stll/docx-core";
|
|
4
5
|
//#region src/docx/groupDrawingParser.ts
|
|
5
6
|
const HEX_COLOR = /^[0-9A-Fa-f]{6}$/u;
|
|
6
7
|
const DEFAULT_TEXT_COLOR = "000000";
|
|
@@ -12,7 +13,6 @@ const CROP_SCALE = 1e5;
|
|
|
12
13
|
const MAX_PATH_COMMANDS = 1e4;
|
|
13
14
|
const MAX_TEXT_CHARACTERS = 2e4;
|
|
14
15
|
const MAX_SVG_CHARACTERS = 1e6;
|
|
15
|
-
const escapeXml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
16
16
|
const numericAttr = (element, name) => {
|
|
17
17
|
const direct = parseNumericAttribute(element, null, name);
|
|
18
18
|
if (direct !== void 0) return direct;
|
|
@@ -108,7 +108,7 @@ const renderTextBox = (wsp) => {
|
|
|
108
108
|
const color = colorFrom(findAllDeep(wsp, "w", "color").at(0) ?? null, DEFAULT_TEXT_COLOR);
|
|
109
109
|
const fontSize = halfPoints * HALF_POINT_TO_EMU;
|
|
110
110
|
const maxCharacters = Math.max(1, Math.floor(width / (fontSize * .38)));
|
|
111
|
-
const lines = paragraphs.flatMap((paragraph) => wrapLine(getTextContent(paragraph).slice(0, MAX_TEXT_CHARACTERS), maxCharacters)).map(
|
|
111
|
+
const lines = paragraphs.flatMap((paragraph) => wrapLine(getTextContent(paragraph).slice(0, MAX_TEXT_CHARACTERS), maxCharacters)).map(escapeXmlText);
|
|
112
112
|
if (lines.length === 0) return "";
|
|
113
113
|
const lineHeight = fontSize * 1.15;
|
|
114
114
|
const svgFontSize = 1e3;
|
|
@@ -121,7 +121,7 @@ const renderPicture = (picture, index, rels, media) => {
|
|
|
121
121
|
if (width <= 0 || height <= 0) return "";
|
|
122
122
|
const blipFill = findChildByLocalName(picture, "blipFill");
|
|
123
123
|
const blip = findChildByLocalName(blipFill, "blip");
|
|
124
|
-
const { src } = resolveImageData(getAttribute(blip, "r", "embed") ?? getAttribute(blip, "r", "link") ??
|
|
124
|
+
const { src } = resolveImageData(getAttribute(blip, "r", "embed") ?? getAttribute(blip, "r", "link") ?? void 0, rels, media);
|
|
125
125
|
if (!src) return "";
|
|
126
126
|
const sourceRect = findChildByLocalName(blipFill, "srcRect");
|
|
127
127
|
const left = Math.max(0, numericAttr(sourceRect, "l")) / CROP_SCALE;
|
|
@@ -131,7 +131,7 @@ const renderPicture = (picture, index, rels, media) => {
|
|
|
131
131
|
const visibleWidth = 1 - left - right;
|
|
132
132
|
const visibleHeight = 1 - top - bottom;
|
|
133
133
|
if (visibleWidth <= 0 || visibleHeight <= 0) return "";
|
|
134
|
-
const image = `<image x="${x - width * left / visibleWidth}" y="${y - height * top / visibleHeight}" width="${width / visibleWidth}" height="${height / visibleHeight}" href="${
|
|
134
|
+
const image = `<image x="${x - width * left / visibleWidth}" y="${y - height * top / visibleHeight}" width="${width / visibleWidth}" height="${height / visibleHeight}" href="${escapeXmlAttribute(src)}" preserveAspectRatio="none"/>`;
|
|
135
135
|
if (left === 0 && top === 0 && right === 0 && bottom === 0) return image;
|
|
136
136
|
const clipId = `group-picture-${index}`;
|
|
137
137
|
return `<defs><clipPath id="${clipId}"><rect x="${x}" y="${y}" width="${width}" height="${height}"/></clipPath></defs><g clip-path="url(#${clipId})">${image}</g>`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { ParseContext } from "./parseContext.js";
|
|
2
3
|
import { XmlElement } from "./xmlParser.js";
|
|
3
4
|
//#region src/docx/headerFooterRefParser.d.ts
|
|
4
5
|
/**
|
|
@@ -11,15 +12,15 @@ import { XmlElement } from "./xmlParser.js";
|
|
|
11
12
|
* header/footer reference types has to read them through here, or a
|
|
12
13
|
* normalisation at this boundary looks like a lost reference downstream.
|
|
13
14
|
*/
|
|
14
|
-
declare function parseHeaderFooterType(typeAttr: string | null): document_d_exports.HeaderFooterType;
|
|
15
|
+
declare function parseHeaderFooterType(typeAttr: string | null, context?: ParseContext): document_d_exports.HeaderFooterType;
|
|
15
16
|
/**
|
|
16
17
|
* Parse a header reference from sectPr (w:headerReference)
|
|
17
18
|
*/
|
|
18
|
-
declare function parseHeaderReference(element: XmlElement): document_d_exports.HeaderReference;
|
|
19
|
+
declare function parseHeaderReference(element: XmlElement, context?: ParseContext): document_d_exports.HeaderReference | null;
|
|
19
20
|
/**
|
|
20
21
|
* Parse a footer reference from sectPr (w:footerReference)
|
|
21
22
|
*/
|
|
22
|
-
declare function parseFooterReference(element: XmlElement): document_d_exports.FooterReference;
|
|
23
|
+
declare function parseFooterReference(element: XmlElement, context?: ParseContext): document_d_exports.FooterReference | null;
|
|
23
24
|
/**
|
|
24
25
|
* Parse all header references from a sectPr element
|
|
25
26
|
*/
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { findChildren, getAttribute } from "./xmlParser.js";
|
|
2
|
+
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
2
3
|
//#region src/docx/headerFooterRefParser.ts
|
|
3
4
|
/**
|
|
5
|
+
* Header/Footer Reference Parser
|
|
6
|
+
*
|
|
7
|
+
* Parses header/footer references (w:headerReference, w:footerReference) that
|
|
8
|
+
* appear in section properties. Extracted from headerFooterParser to break the
|
|
9
|
+
* circular dependency: headerFooterParser -> paragraphParser -> sectionParser -> headerFooterParser.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
4
12
|
* Read a `w:type` attribute as one of ECMA-376's three `ST_HdrFtr` values.
|
|
5
13
|
*
|
|
6
14
|
* The enumeration is `even`, `default` and `first` (17.18.36); `default` is
|
|
@@ -10,32 +18,48 @@ import { findChildren, getAttribute } from "./xmlParser.js";
|
|
|
10
18
|
* header/footer reference types has to read them through here, or a
|
|
11
19
|
* normalisation at this boundary looks like a lost reference downstream.
|
|
12
20
|
*/
|
|
13
|
-
function parseHeaderFooterType(typeAttr) {
|
|
21
|
+
function parseHeaderFooterType(typeAttr, context) {
|
|
14
22
|
switch (typeAttr) {
|
|
15
23
|
case "first": return "first";
|
|
16
24
|
case "even": return "even";
|
|
17
|
-
|
|
25
|
+
case "default":
|
|
26
|
+
case null: return "default";
|
|
27
|
+
default:
|
|
28
|
+
context?.warn({
|
|
29
|
+
code: PARSE_WARNING_CODES.headerFooterTypeOutsideEnum,
|
|
30
|
+
value: typeAttr,
|
|
31
|
+
element: "w:type"
|
|
32
|
+
});
|
|
33
|
+
return "default";
|
|
18
34
|
}
|
|
19
35
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
36
|
+
/**
|
|
37
|
+
* A reference with no `r:id` names no part, so it is not a reference.
|
|
38
|
+
*
|
|
39
|
+
* Coercing the missing attribute to `""` used to put the empty string in the
|
|
40
|
+
* model, where it became a part-map key on one side and an `r:id=""` the
|
|
41
|
+
* schema rejects on the other. Null here keeps the reference out of the model
|
|
42
|
+
* entirely, which is what the source said.
|
|
43
|
+
*/
|
|
44
|
+
function parseHeaderFooterReference(element, context) {
|
|
45
|
+
const rId = getAttribute(element, "r", "id");
|
|
46
|
+
if (rId === null || rId.length === 0) return null;
|
|
23
47
|
return {
|
|
24
|
-
type: parseHeaderFooterType(
|
|
48
|
+
type: parseHeaderFooterType(getAttribute(element, "w", "type"), context?.scoped({ at: `r:id "${rId}"` })),
|
|
25
49
|
rId
|
|
26
50
|
};
|
|
27
51
|
}
|
|
28
52
|
/**
|
|
29
53
|
* Parse a header reference from sectPr (w:headerReference)
|
|
30
54
|
*/
|
|
31
|
-
function parseHeaderReference(element) {
|
|
32
|
-
return parseHeaderFooterReference(element);
|
|
55
|
+
function parseHeaderReference(element, context) {
|
|
56
|
+
return parseHeaderFooterReference(element, context);
|
|
33
57
|
}
|
|
34
58
|
/**
|
|
35
59
|
* Parse a footer reference from sectPr (w:footerReference)
|
|
36
60
|
*/
|
|
37
|
-
function parseFooterReference(element) {
|
|
38
|
-
return parseHeaderFooterReference(element);
|
|
61
|
+
function parseFooterReference(element, context) {
|
|
62
|
+
return parseHeaderFooterReference(element, context);
|
|
39
63
|
}
|
|
40
64
|
/**
|
|
41
65
|
* Parse all header references from a sectPr element
|
|
@@ -43,7 +67,10 @@ function parseFooterReference(element) {
|
|
|
43
67
|
function parseHeaderReferences(sectPr) {
|
|
44
68
|
const refs = [];
|
|
45
69
|
const headerRefElements = findChildren(sectPr, "w", "headerReference");
|
|
46
|
-
for (const el of headerRefElements)
|
|
70
|
+
for (const el of headerRefElements) {
|
|
71
|
+
const ref = parseHeaderReference(el);
|
|
72
|
+
if (ref) refs.push(ref);
|
|
73
|
+
}
|
|
47
74
|
return refs;
|
|
48
75
|
}
|
|
49
76
|
/**
|
|
@@ -52,7 +79,10 @@ function parseHeaderReferences(sectPr) {
|
|
|
52
79
|
function parseFooterReferences(sectPr) {
|
|
53
80
|
const refs = [];
|
|
54
81
|
const footerRefElements = findChildren(sectPr, "w", "footerReference");
|
|
55
|
-
for (const el of footerRefElements)
|
|
82
|
+
for (const el of footerRefElements) {
|
|
83
|
+
const ref = parseFooterReference(el);
|
|
84
|
+
if (ref) refs.push(ref);
|
|
85
|
+
}
|
|
56
86
|
return refs;
|
|
57
87
|
}
|
|
58
88
|
//#endregion
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
//#region src/docx/headerFooterReferenceNormalization.d.ts
|
|
3
|
+
/** The codes this normalisation is reported under, owned here, not at the caller. */
|
|
4
|
+
declare const DANGLING_HEADER_REFERENCE_WARNING: "dangling-header-reference";
|
|
5
|
+
declare const DANGLING_FOOTER_REFERENCE_WARNING: "dangling-footer-reference";
|
|
3
6
|
type NormalizeHeaderFooterReferencesInput = {
|
|
4
7
|
documentBody: document_d_exports.DocumentBody;
|
|
5
8
|
headers?: Map<string, document_d_exports.HeaderFooter>;
|
|
@@ -11,4 +14,4 @@ type NormalizeHeaderFooterReferencesResult = {
|
|
|
11
14
|
};
|
|
12
15
|
declare const normalizeHeaderFooterReferences: ({ documentBody, headers, footers }: NormalizeHeaderFooterReferencesInput) => NormalizeHeaderFooterReferencesResult;
|
|
13
16
|
//#endregion
|
|
14
|
-
export { normalizeHeaderFooterReferences };
|
|
17
|
+
export { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, normalizeHeaderFooterReferences };
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
1
2
|
//#region src/docx/headerFooterReferenceNormalization.ts
|
|
3
|
+
/** The codes this normalisation is reported under, owned here, not at the caller. */
|
|
4
|
+
const DANGLING_HEADER_REFERENCE_WARNING = PARSE_WARNING_CODES.danglingHeaderReference;
|
|
5
|
+
const DANGLING_FOOTER_REFERENCE_WARNING = PARSE_WARNING_CODES.danglingFooterReference;
|
|
2
6
|
const normalizeHeaderFooterReferences = ({ documentBody, headers, footers }) => {
|
|
3
7
|
const seenSectionProperties = /* @__PURE__ */ new Set();
|
|
4
8
|
let removedDanglingHeaderReferences = 0;
|
|
@@ -61,4 +65,4 @@ const removeDanglingReferences = (references, validParts) => {
|
|
|
61
65
|
};
|
|
62
66
|
};
|
|
63
67
|
//#endregion
|
|
64
|
-
export { normalizeHeaderFooterReferences };
|
|
68
|
+
export { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, normalizeHeaderFooterReferences };
|