@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
|
@@ -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,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
|
}
|
|
@@ -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;
|
|
@@ -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 };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { sanitizeExternalUrl, sanitizeLinkTarget } from "../utils/urlSecurity.js";
|
|
2
|
+
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
|
|
2
3
|
import { parseRun } from "./runParser.js";
|
|
3
|
-
import { getAttribute, getChildElements, getLocalName, mergeXmlnsDeclarations, parseNumericAttribute } from "./xmlParser.js";
|
|
4
|
+
import { getAttribute, getChildElements, getLocalName, mergeXmlnsDeclarations, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
|
|
4
5
|
//#region src/docx/hyperlinkParser.ts
|
|
5
6
|
/**
|
|
6
7
|
* Parse bookmark start (w:bookmarkStart)
|
|
@@ -49,11 +50,9 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
|
|
|
49
50
|
const rId = getAttribute(node, "r", "id");
|
|
50
51
|
if (rId) {
|
|
51
52
|
hyperlink.rId = rId;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
if (sanitizeExternalUrl(rel.target)) hyperlink.href = rel.target;
|
|
56
|
-
}
|
|
53
|
+
const resolved = resolveRelationshipIdOfType(rels, rId, RELATIONSHIP_TYPES.hyperlink);
|
|
54
|
+
if (resolved.status === "resolved") {
|
|
55
|
+
if (sanitizeExternalUrl(resolved.relationship.target)) hyperlink.href = resolved.relationship.target;
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
const anchor = getAttribute(node, "w", "anchor");
|
|
@@ -65,8 +64,7 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
|
|
|
65
64
|
if (tooltip) hyperlink.tooltip = tooltip;
|
|
66
65
|
const tgtFrame = getAttribute(node, "w", "tgtFrame");
|
|
67
66
|
if (tgtFrame) hyperlink.target = sanitizeLinkTarget(tgtFrame);
|
|
68
|
-
|
|
69
|
-
if (history === "1" || history === "true") hyperlink.history = true;
|
|
67
|
+
if (parseOnOffAttribute(node, "w", "history") === true) hyperlink.history = true;
|
|
70
68
|
const docLocation = getAttribute(node, "w", "docLocation");
|
|
71
69
|
if (docLocation) hyperlink.docLocation = docLocation;
|
|
72
70
|
const inScopeXmlns = mergeXmlnsDeclarations(rootXmlns, node);
|
|
@@ -168,13 +166,11 @@ function getHyperlinkRuns(hyperlink) {
|
|
|
168
166
|
* @returns The resolved URL or undefined
|
|
169
167
|
*/
|
|
170
168
|
function resolveHyperlinkUrl(hyperlink, rels) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return hyperlink.href;
|
|
177
|
-
}
|
|
169
|
+
const resolved = resolveRelationshipIdOfType(rels, hyperlink.rId, RELATIONSHIP_TYPES.hyperlink);
|
|
170
|
+
if (resolved.status === "resolved") {
|
|
171
|
+
if (sanitizeExternalUrl(resolved.relationship.target)) {
|
|
172
|
+
hyperlink.href = resolved.relationship.target;
|
|
173
|
+
return hyperlink.href;
|
|
178
174
|
}
|
|
179
175
|
}
|
|
180
176
|
if (hyperlink.anchor && !hyperlink.href) {
|
|
@@ -9,7 +9,7 @@ import { XmlElement } from "./xmlParser.js";
|
|
|
9
9
|
* @param media - Media files map
|
|
10
10
|
* @returns Object with src (data URL or blob), mimeType, and filename
|
|
11
11
|
*/
|
|
12
|
-
declare function resolveImageData(rId: string, rels: document_d_exports.RelationshipMap | undefined, media: Map<string, document_d_exports.MediaFile> | undefined): {
|
|
12
|
+
declare function resolveImageData(rId: string | undefined, rels: document_d_exports.RelationshipMap | undefined, media: Map<string, document_d_exports.MediaFile> | undefined): {
|
|
13
13
|
src?: string;
|
|
14
14
|
mimeType?: string;
|
|
15
15
|
filename?: string;
|
package/dist/docx/imageParser.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
2
2
|
import { emuToPixels } from "../utils/units.js";
|
|
3
3
|
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
4
|
-
import { WRAP_ELEMENT_NAMES, parsePositionH, parsePositionV, parseWrapElement } from "./drawingUtils.js";
|
|
4
|
+
import { WRAP_ELEMENT_NAMES, parseAnchorBehindDoc, parsePositionH, parsePositionV, parseWrapElement } from "./drawingUtils.js";
|
|
5
5
|
import { parseGraphicFrameLocks } from "./graphicFrameLocks.js";
|
|
6
|
-
import {
|
|
6
|
+
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
|
|
7
7
|
import { isTextBoxDrawing } from "./textBoxParser.js";
|
|
8
8
|
import { findByFullName, findChild, getAttribute, getChildElements, parseNumericAttribute, parseOnOffValue } from "./xmlParser.js";
|
|
9
9
|
//#region src/docx/imageParser.ts
|
|
@@ -178,17 +178,20 @@ function parseImageOpacity(blip) {
|
|
|
178
178
|
return Math.max(0, amt / 1e5);
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
|
-
* Extract rId from a:blip element
|
|
181
|
+
* Extract rId from a:blip element.
|
|
182
|
+
*
|
|
183
|
+
* Undefined when the drawing has no blip to read one from: a chart, a diagram
|
|
184
|
+
* or an OLE frame carries an `a:graphic` that is not a picture, and a
|
|
185
|
+
* `wp:inline` may carry no graphic at all.
|
|
182
186
|
*/
|
|
183
187
|
function extractBlipRId(blip) {
|
|
184
|
-
if (!blip) return
|
|
188
|
+
if (!blip) return;
|
|
185
189
|
const rEmbed = getAttribute(blip, "r", "embed");
|
|
186
190
|
if (rEmbed) return rEmbed;
|
|
187
191
|
const embed = getAttribute(blip, null, "embed");
|
|
188
192
|
if (embed) return embed;
|
|
189
193
|
const rLink = getAttribute(blip, "r", "link");
|
|
190
194
|
if (rLink) return rLink;
|
|
191
|
-
return "";
|
|
192
195
|
}
|
|
193
196
|
/**
|
|
194
197
|
* Find transform (a:xfrm) from picture shape properties
|
|
@@ -242,10 +245,9 @@ function getMimeType(path) {
|
|
|
242
245
|
* @returns Object with src (data URL or blob), mimeType, and filename
|
|
243
246
|
*/
|
|
244
247
|
function resolveImageData(rId, rels, media) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const targetPath = rel.target;
|
|
248
|
+
const resolved = resolveRelationshipIdOfType(rels, rId, RELATIONSHIP_TYPES.image);
|
|
249
|
+
if (resolved.status !== "resolved") return {};
|
|
250
|
+
const targetPath = resolved.relationship.target;
|
|
249
251
|
if (!targetPath) return {};
|
|
250
252
|
const normalizedPath = normalizeMediaPath(targetPath);
|
|
251
253
|
const filename = targetPath.split("/").pop();
|
|
@@ -319,7 +321,7 @@ function parseInline(inlineEl, rels, media) {
|
|
|
319
321
|
if (distR !== void 0) wrap.distR = distR;
|
|
320
322
|
const image = {
|
|
321
323
|
type: "image",
|
|
322
|
-
rId,
|
|
324
|
+
...rId === void 0 ? {} : { rId },
|
|
323
325
|
size,
|
|
324
326
|
wrap
|
|
325
327
|
};
|
|
@@ -337,11 +339,12 @@ function parseInline(inlineEl, rels, media) {
|
|
|
337
339
|
if (crop) image.crop = crop;
|
|
338
340
|
if (opacity !== void 0) image.opacity = opacity;
|
|
339
341
|
if (frameLocks) image.frameLocks = frameLocks;
|
|
340
|
-
|
|
341
|
-
|
|
342
|
+
const hlink = resolveRelationshipIdOfType(rels, props.hlinkRId, RELATIONSHIP_TYPES.hyperlink);
|
|
343
|
+
if (hlink.status === "resolved") {
|
|
344
|
+
const safeHref = sanitizeExternalUrl(hlink.relationship.target);
|
|
342
345
|
if (safeHref) {
|
|
343
346
|
image.hlinkHref = safeHref;
|
|
344
|
-
image.hlinkRId =
|
|
347
|
+
image.hlinkRId = hlink.relationship.id;
|
|
345
348
|
}
|
|
346
349
|
}
|
|
347
350
|
return image;
|
|
@@ -359,7 +362,7 @@ function parseAnchor(anchorEl, rels, media) {
|
|
|
359
362
|
const padding = parseEffectExtent(findByFullName(anchorEl, "wp:effectExtent"));
|
|
360
363
|
const props = parseDocProps(findByFullName(anchorEl, "wp:docPr"));
|
|
361
364
|
const frameLocks = parseGraphicFrameLocks(anchorEl);
|
|
362
|
-
const behindDoc =
|
|
365
|
+
const behindDoc = parseAnchorBehindDoc(anchorEl);
|
|
363
366
|
const layoutInCell = parseOnOffAttr(anchorEl, "layoutInCell");
|
|
364
367
|
const allowOverlap = parseOnOffAttr(anchorEl, "allowOverlap");
|
|
365
368
|
const anchorDistT = parseNumericAttribute(anchorEl, null, "distT");
|
|
@@ -391,7 +394,7 @@ function parseAnchor(anchorEl, rels, media) {
|
|
|
391
394
|
const transform = parseTransform(findPictureTransform(anchorEl));
|
|
392
395
|
const image = {
|
|
393
396
|
type: "image",
|
|
394
|
-
rId,
|
|
397
|
+
...rId === void 0 ? {} : { rId },
|
|
395
398
|
size,
|
|
396
399
|
wrap
|
|
397
400
|
};
|
|
@@ -412,11 +415,12 @@ function parseAnchor(anchorEl, rels, media) {
|
|
|
412
415
|
if (frameLocks) image.frameLocks = frameLocks;
|
|
413
416
|
if (layoutInCell !== void 0) image.layoutInCell = layoutInCell;
|
|
414
417
|
if (allowOverlap !== void 0) image.allowOverlap = allowOverlap;
|
|
415
|
-
|
|
416
|
-
|
|
418
|
+
const hlink = resolveRelationshipIdOfType(rels, props.hlinkRId, RELATIONSHIP_TYPES.hyperlink);
|
|
419
|
+
if (hlink.status === "resolved") {
|
|
420
|
+
const safeHref = sanitizeExternalUrl(hlink.relationship.target);
|
|
417
421
|
if (safeHref) {
|
|
418
422
|
image.hlinkHref = safeHref;
|
|
419
|
-
image.hlinkRId =
|
|
423
|
+
image.hlinkRId = hlink.relationship.id;
|
|
420
424
|
}
|
|
421
425
|
}
|
|
422
426
|
return image;
|
package/dist/docx/imageRawXml.js
CHANGED
|
@@ -46,12 +46,12 @@ const DRAWING_SAFETY_CLASSES = {
|
|
|
46
46
|
OPAQUE: "opaque"
|
|
47
47
|
};
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
49
|
+
* A drawing with no picture relationship has no picture to regenerate. The
|
|
50
|
+
* serializer writes the anchor back without a graphic, which is faithful for an
|
|
51
|
+
* anchor that never had one and lossy for a chart or an OLE frame, so the
|
|
52
|
+
* drawing counts as opaque and an edit must block the save.
|
|
53
53
|
*/
|
|
54
|
-
const canRegenerateDrawing = (drawing) => drawing.image.rId !==
|
|
54
|
+
const canRegenerateDrawing = (drawing) => drawing.image.rId !== void 0;
|
|
55
55
|
/**
|
|
56
56
|
* Classify a drawing by what the run serializer will do with it.
|
|
57
57
|
*
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { XmlElement } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/markupRangeMarker.d.ts
|
|
4
|
+
declare const parseMarkupRangeMarker: (node: XmlElement) => document_d_exports.MarkupRangeMarker;
|
|
5
|
+
declare const parseBookmarkRangeMarker: (node: XmlElement) => document_d_exports.BookmarkRangeMarker;
|
|
6
|
+
/**
|
|
7
|
+
* `w:author` is required on `CT_MoveBookmark`, so an absent one takes the same
|
|
8
|
+
* `Unknown` fallback a tracked change takes rather than leaving the saved
|
|
9
|
+
* package short of an attribute the schema demands. `w:date` is required too,
|
|
10
|
+
* but inventing a timestamp would state a fact about the document that is not
|
|
11
|
+
* true, so an absent date stays absent.
|
|
12
|
+
*/
|
|
13
|
+
declare const parseMoveBookmarkMarker: (node: XmlElement) => document_d_exports.MoveBookmarkMarker;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { parseBookmarkRangeMarker, parseMarkupRangeMarker, parseMoveBookmarkMarker };
|