@stll/folio-core 0.42.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/compat/eigenpal.d.ts +2 -2
- package/dist/controller/layoutPipeline.d.ts +2 -1
- package/dist/controller/layoutPipeline.js +5 -2
- package/dist/controller/layoutSession.d.ts +2 -1
- package/dist/controller/layoutSession.js +1 -0
- package/dist/docx/appVersionNormalization.d.ts +0 -18
- package/dist/docx/blockContentParser.js +10 -1
- 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 +10 -0
- package/dist/docx/commentIdNormalization.js +33 -0
- 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 +39 -0
- package/dist/docx/defaultParagraphStyle.js +54 -0
- 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 -2
- package/dist/docx/groupDrawingParser.js +1 -1
- package/dist/docx/headerFooterRefParser.d.ts +15 -3
- package/dist/docx/headerFooterRefParser.js +51 -14
- 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/numberingParser.js +2 -1
- package/dist/docx/numberingReference.d.ts +21 -0
- package/dist/docx/numberingReference.js +21 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +14 -2
- package/dist/docx/numberingReferenceNormalization.js +51 -9
- package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
- package/dist/docx/paragraphParser.js +69 -101
- 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 +86 -24
- 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 +85 -27
- 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 +15 -22
- 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 +15 -89
- 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/index.d.ts +2 -2
- package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +2 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +9 -6
- 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-bridge/convert/templatePreviewFlow.d.ts +19 -11
- package/dist/layout-bridge/convert/templatePreviewFlow.js +103 -38
- package/dist/layout-bridge/convert/toFlowBlocks.js +12 -3
- 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/pageBreak.js +12 -1
- 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 +131 -41
- package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
- package/dist/prosemirror/conversion/toProseDoc.js +402 -328
- 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/ListExtension.js +42 -4
- 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/listMarker.js +2 -1
- package/dist/prosemirror/numberedRefFields.js +2 -1
- package/dist/prosemirror/pageBreakRunProjection.d.ts +11 -3
- package/dist/prosemirror/pageBreakRunProjection.js +16 -8
- 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/plugins/templatePreviewValues.d.ts +42 -1
- package/dist/prosemirror/plugins/templatePreviewValues.js +217 -14
- 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 +4 -1
- package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
- package/dist/prosemirror/styles/styleResolver.js +15 -6
- package/dist/prosemirror/utils/visualLineNavigation.d.ts +22 -2
- package/dist/prosemirror/utils/visualLineNavigation.js +80 -63
- package/dist/style-engine/styleEngine.d.ts +4 -1
- package/dist/style-engine/styleEngine.js +3 -0
- package/dist/style-sets/extract.js +35 -11
- 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 +3 -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
|
@@ -1,24 +1,31 @@
|
|
|
1
|
+
import { InlineContentRemovals, visitInlineContentSlots } from "./paragraphTraversal.js";
|
|
2
|
+
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
1
3
|
//#region src/docx/commentReferenceNormalization.ts
|
|
4
|
+
/** The codes this normalisation is reported under, owned here, not at the caller. */
|
|
5
|
+
const DANGLING_COMMENT_REFERENCE_WARNING = PARSE_WARNING_CODES.danglingCommentReference;
|
|
6
|
+
const UNBALANCED_COMMENT_RANGE_WARNING = PARSE_WARNING_CODES.unbalancedCommentRange;
|
|
2
7
|
const normalizeCommentReferences = ({ documentBody, comments, headers, footers, footnotes, endnotes }) => {
|
|
3
8
|
const validCommentIds = new Set(comments.map((comment) => comment.id));
|
|
4
9
|
const rangeMarkers = [];
|
|
10
|
+
const dangling = new InlineContentRemovals();
|
|
5
11
|
let removedDanglingReferences = 0;
|
|
6
12
|
const normalizeParagraph = (paragraph) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
13
|
+
visitInlineContentSlots(paragraph, ({ content, index, item }) => {
|
|
14
|
+
if (isCommentMarker(item) && !validCommentIds.has(item.id)) {
|
|
15
|
+
dangling.mark({
|
|
16
|
+
content,
|
|
17
|
+
index
|
|
18
|
+
});
|
|
10
19
|
removedDanglingReferences += 1;
|
|
11
|
-
|
|
20
|
+
return;
|
|
12
21
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
type: content.type
|
|
22
|
+
if (isCommentRangeMarker(item)) rangeMarkers.push({
|
|
23
|
+
content,
|
|
24
|
+
index,
|
|
25
|
+
id: item.id,
|
|
26
|
+
type: item.type
|
|
19
27
|
});
|
|
20
|
-
}
|
|
21
|
-
paragraph.content = nextContent;
|
|
28
|
+
});
|
|
22
29
|
};
|
|
23
30
|
const normalizeTable = (table) => {
|
|
24
31
|
for (const row of table.rows) for (const cell of row.cells) normalizeBlocks(cell.content);
|
|
@@ -43,9 +50,11 @@ const normalizeCommentReferences = ({ documentBody, comments, headers, footers,
|
|
|
43
50
|
for (const footnote of footnotes ?? []) normalizeBlocks(footnote.content);
|
|
44
51
|
for (const endnote of endnotes ?? []) normalizeBlocks(endnote.content);
|
|
45
52
|
for (const comment of comments) for (const paragraph of comment.content) normalizeParagraph(paragraph);
|
|
53
|
+
const reanchoredUnbalancedRanges = reanchorUnbalancedCommentRanges(rangeMarkers);
|
|
54
|
+
dangling.apply();
|
|
46
55
|
return {
|
|
47
56
|
removedDanglingReferences,
|
|
48
|
-
reanchoredUnbalancedRanges
|
|
57
|
+
reanchoredUnbalancedRanges
|
|
49
58
|
};
|
|
50
59
|
};
|
|
51
60
|
const reanchorUnbalancedCommentRanges = (rangeMarkers) => {
|
|
@@ -94,4 +103,4 @@ const reanchorCommentRangeMarker = (marker) => {
|
|
|
94
103
|
const isCommentMarker = (content) => content.type === "commentRangeStart" || content.type === "commentRangeEnd" || content.type === "commentReference";
|
|
95
104
|
const isCommentRangeMarker = (content) => content.type === "commentRangeStart" || content.type === "commentRangeEnd";
|
|
96
105
|
//#endregion
|
|
97
|
-
export { normalizeCommentReferences };
|
|
106
|
+
export { DANGLING_COMMENT_REFERENCE_WARNING, UNBALANCED_COMMENT_RANGE_WARNING, normalizeCommentReferences };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/danglingRelationshipReferences.d.ts
|
|
3
|
+
type DanglingRelationshipReferences = {
|
|
4
|
+
/** Drawings whose `r:embed` names no relationship. */
|
|
5
|
+
drawings: number;
|
|
6
|
+
/** Hyperlinks whose `r:id` names no relationship. */
|
|
7
|
+
hyperlinks: number;
|
|
8
|
+
};
|
|
9
|
+
type CountDanglingRelationshipReferencesOptions = {
|
|
10
|
+
content: readonly document_d_exports.BlockContent[];
|
|
11
|
+
relationships: document_d_exports.RelationshipMap | undefined;
|
|
12
|
+
};
|
|
13
|
+
declare const countDanglingRelationshipReferences: ({ content, relationships }: CountDanglingRelationshipReferencesOptions) => DanglingRelationshipReferences;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { DanglingRelationshipReferences, countDanglingRelationshipReferences };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { resolveRelationshipId } from "./relsParser.js";
|
|
2
|
+
//#region src/docx/danglingRelationshipReferences.ts
|
|
3
|
+
const countDanglingRelationshipReferences = ({ content, relationships }) => {
|
|
4
|
+
const counts = {
|
|
5
|
+
drawings: 0,
|
|
6
|
+
hyperlinks: 0
|
|
7
|
+
};
|
|
8
|
+
const isDangling = (rId) => resolveRelationshipId(relationships, rId).status === "dangling";
|
|
9
|
+
const visitBlocks = (blocks) => {
|
|
10
|
+
for (const block of blocks) {
|
|
11
|
+
if (block.type === "table") {
|
|
12
|
+
for (const row of block.rows) for (const cell of row.cells) visitBlocks(cell.content);
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (block.type !== "paragraph") continue;
|
|
16
|
+
for (const item of block.content) {
|
|
17
|
+
if (item.type === "hyperlink") {
|
|
18
|
+
if (isDangling(item.rId)) counts.hyperlinks += 1;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (item.type !== "run") continue;
|
|
22
|
+
for (const child of item.content) if (child.type === "drawing" && isDangling(child.image.rId)) counts.drawings += 1;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
visitBlocks(content);
|
|
27
|
+
return counts;
|
|
28
|
+
};
|
|
29
|
+
//#endregion
|
|
30
|
+
export { countDanglingRelationshipReferences };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/defaultParagraphStyle.d.ts
|
|
3
|
+
/** The name Word's built-in default paragraph style always carries in the file. */
|
|
4
|
+
declare const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME = "Normal";
|
|
5
|
+
/** The id English Word gives it, kept as the last resort for the reverse case. */
|
|
6
|
+
declare const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID = "Normal";
|
|
7
|
+
/**
|
|
8
|
+
* The formatting Word's default template gives Normal: 8pt (160 twips) after
|
|
9
|
+
* spacing, 1.08x line spacing.
|
|
10
|
+
*
|
|
11
|
+
* A package that declares neither a default paragraph style nor `w:docDefaults`
|
|
12
|
+
* renders as though it declared this, so anything that mints the missing
|
|
13
|
+
* default has to mint the formatting with it.
|
|
14
|
+
*/
|
|
15
|
+
declare const BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING: {
|
|
16
|
+
spaceAfter: number;
|
|
17
|
+
lineSpacing: number;
|
|
18
|
+
lineSpacingRule: "auto";
|
|
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;
|
|
37
|
+
declare const resolveDefaultParagraphStyle: (styles: Iterable<document_d_exports.Style>) => document_d_exports.Style | undefined;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID, BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, mintDefaultParagraphStyle, resolveDefaultParagraphStyle };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//#region src/docx/defaultParagraphStyle.ts
|
|
2
|
+
/** The name Word's built-in default paragraph style always carries in the file. */
|
|
3
|
+
const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME = "Normal";
|
|
4
|
+
/** The id English Word gives it, kept as the last resort for the reverse case. */
|
|
5
|
+
const BUILT_IN_DEFAULT_PARAGRAPH_STYLE_ID = "Normal";
|
|
6
|
+
/**
|
|
7
|
+
* The formatting Word's default template gives Normal: 8pt (160 twips) after
|
|
8
|
+
* spacing, 1.08x line spacing.
|
|
9
|
+
*
|
|
10
|
+
* A package that declares neither a default paragraph style nor `w:docDefaults`
|
|
11
|
+
* renders as though it declared this, so anything that mints the missing
|
|
12
|
+
* default has to mint the formatting with it.
|
|
13
|
+
*/
|
|
14
|
+
const BUILT_IN_DEFAULT_PARAGRAPH_FORMATTING = {
|
|
15
|
+
spaceAfter: 160,
|
|
16
|
+
lineSpacing: 259,
|
|
17
|
+
lineSpacingRule: "auto"
|
|
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
|
+
};
|
|
41
|
+
const resolveDefaultParagraphStyle = (styles) => {
|
|
42
|
+
let flagged;
|
|
43
|
+
let namedBuiltIn;
|
|
44
|
+
let idBuiltIn;
|
|
45
|
+
for (const style of styles) {
|
|
46
|
+
if (style.type !== "paragraph") continue;
|
|
47
|
+
if (style.default) flagged = style;
|
|
48
|
+
if (namedBuiltIn === void 0 && style.name === "Normal") namedBuiltIn = style;
|
|
49
|
+
if (idBuiltIn === void 0 && style.styleId === "Normal") idBuiltIn = style;
|
|
50
|
+
}
|
|
51
|
+
return flagged ?? namedBuiltIn ?? idBuiltIn;
|
|
52
|
+
};
|
|
53
|
+
//#endregion
|
|
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,6 +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);
|
|
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
|
+
}
|
|
81
90
|
byId.set(footnote.id, footnote);
|
|
82
91
|
footnotes.push(footnote);
|
|
83
92
|
}
|
|
@@ -129,7 +138,7 @@ function parseEndnote(element, styles, theme, numbering, rels, media) {
|
|
|
129
138
|
* @param media - Media files for images
|
|
130
139
|
* @returns EndnoteMap with all endnotes
|
|
131
140
|
*/
|
|
132
|
-
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) {
|
|
133
142
|
const byId = /* @__PURE__ */ new Map();
|
|
134
143
|
const endnotes = [];
|
|
135
144
|
if (!endnotesXml) return createEndnoteMap(byId, endnotes);
|
|
@@ -138,6 +147,14 @@ function parseEndnotes(endnotesXml, styles = null, theme = null, numbering = nul
|
|
|
138
147
|
const endnoteElements = findChildren(rootElement, "w", "endnote");
|
|
139
148
|
for (const enEl of endnoteElements) {
|
|
140
149
|
const endnote = parseEndnote(enEl, styles, theme, numbering, rels, media);
|
|
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
|
+
}
|
|
141
158
|
byId.set(endnote.id, endnote);
|
|
142
159
|
endnotes.push(endnote);
|
|
143
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,14 +1,26 @@
|
|
|
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
|
|
5
|
+
/**
|
|
6
|
+
* Read a `w:type` attribute as one of ECMA-376's three `ST_HdrFtr` values.
|
|
7
|
+
*
|
|
8
|
+
* The enumeration is `even`, `default` and `first` (17.18.36); `default` is
|
|
9
|
+
* the odd-page header, which is why a producer writing `odd` means the same
|
|
10
|
+
* thing. Word opens such a package, so anything outside the enumeration reads
|
|
11
|
+
* as the default the schema itself defaults to. Everything that compares
|
|
12
|
+
* header/footer reference types has to read them through here, or a
|
|
13
|
+
* normalisation at this boundary looks like a lost reference downstream.
|
|
14
|
+
*/
|
|
15
|
+
declare function parseHeaderFooterType(typeAttr: string | null, context?: ParseContext): document_d_exports.HeaderFooterType;
|
|
4
16
|
/**
|
|
5
17
|
* Parse a header reference from sectPr (w:headerReference)
|
|
6
18
|
*/
|
|
7
|
-
declare function parseHeaderReference(element: XmlElement): document_d_exports.HeaderReference;
|
|
19
|
+
declare function parseHeaderReference(element: XmlElement, context?: ParseContext): document_d_exports.HeaderReference | null;
|
|
8
20
|
/**
|
|
9
21
|
* Parse a footer reference from sectPr (w:footerReference)
|
|
10
22
|
*/
|
|
11
|
-
declare function parseFooterReference(element: XmlElement): document_d_exports.FooterReference;
|
|
23
|
+
declare function parseFooterReference(element: XmlElement, context?: ParseContext): document_d_exports.FooterReference | null;
|
|
12
24
|
/**
|
|
13
25
|
* Parse all header references from a sectPr element
|
|
14
26
|
*/
|
|
@@ -18,4 +30,4 @@ declare function parseHeaderReferences(sectPr: XmlElement): document_d_exports.H
|
|
|
18
30
|
*/
|
|
19
31
|
declare function parseFooterReferences(sectPr: XmlElement): document_d_exports.FooterReference[];
|
|
20
32
|
//#endregion
|
|
21
|
-
export { parseFooterReference, parseFooterReferences, parseHeaderReference, parseHeaderReferences };
|
|
33
|
+
export { parseFooterReference, parseFooterReferences, parseHeaderFooterType, parseHeaderReference, parseHeaderReferences };
|
|
@@ -1,34 +1,65 @@
|
|
|
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
|
/**
|
|
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.
|
|
5
10
|
*/
|
|
6
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Read a `w:type` attribute as one of ECMA-376's three `ST_HdrFtr` values.
|
|
13
|
+
*
|
|
14
|
+
* The enumeration is `even`, `default` and `first` (17.18.36); `default` is
|
|
15
|
+
* the odd-page header, which is why a producer writing `odd` means the same
|
|
16
|
+
* thing. Word opens such a package, so anything outside the enumeration reads
|
|
17
|
+
* as the default the schema itself defaults to. Everything that compares
|
|
18
|
+
* header/footer reference types has to read them through here, or a
|
|
19
|
+
* normalisation at this boundary looks like a lost reference downstream.
|
|
20
|
+
*/
|
|
21
|
+
function parseHeaderFooterType(typeAttr, context) {
|
|
7
22
|
switch (typeAttr) {
|
|
8
23
|
case "first": return "first";
|
|
9
24
|
case "even": return "even";
|
|
10
|
-
|
|
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";
|
|
11
34
|
}
|
|
12
35
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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;
|
|
16
47
|
return {
|
|
17
|
-
type: parseHeaderFooterType(
|
|
48
|
+
type: parseHeaderFooterType(getAttribute(element, "w", "type"), context?.scoped({ at: `r:id "${rId}"` })),
|
|
18
49
|
rId
|
|
19
50
|
};
|
|
20
51
|
}
|
|
21
52
|
/**
|
|
22
53
|
* Parse a header reference from sectPr (w:headerReference)
|
|
23
54
|
*/
|
|
24
|
-
function parseHeaderReference(element) {
|
|
25
|
-
return parseHeaderFooterReference(element);
|
|
55
|
+
function parseHeaderReference(element, context) {
|
|
56
|
+
return parseHeaderFooterReference(element, context);
|
|
26
57
|
}
|
|
27
58
|
/**
|
|
28
59
|
* Parse a footer reference from sectPr (w:footerReference)
|
|
29
60
|
*/
|
|
30
|
-
function parseFooterReference(element) {
|
|
31
|
-
return parseHeaderFooterReference(element);
|
|
61
|
+
function parseFooterReference(element, context) {
|
|
62
|
+
return parseHeaderFooterReference(element, context);
|
|
32
63
|
}
|
|
33
64
|
/**
|
|
34
65
|
* Parse all header references from a sectPr element
|
|
@@ -36,7 +67,10 @@ function parseFooterReference(element) {
|
|
|
36
67
|
function parseHeaderReferences(sectPr) {
|
|
37
68
|
const refs = [];
|
|
38
69
|
const headerRefElements = findChildren(sectPr, "w", "headerReference");
|
|
39
|
-
for (const el of headerRefElements)
|
|
70
|
+
for (const el of headerRefElements) {
|
|
71
|
+
const ref = parseHeaderReference(el);
|
|
72
|
+
if (ref) refs.push(ref);
|
|
73
|
+
}
|
|
40
74
|
return refs;
|
|
41
75
|
}
|
|
42
76
|
/**
|
|
@@ -45,8 +79,11 @@ function parseHeaderReferences(sectPr) {
|
|
|
45
79
|
function parseFooterReferences(sectPr) {
|
|
46
80
|
const refs = [];
|
|
47
81
|
const footerRefElements = findChildren(sectPr, "w", "footerReference");
|
|
48
|
-
for (const el of footerRefElements)
|
|
82
|
+
for (const el of footerRefElements) {
|
|
83
|
+
const ref = parseFooterReference(el);
|
|
84
|
+
if (ref) refs.push(ref);
|
|
85
|
+
}
|
|
49
86
|
return refs;
|
|
50
87
|
}
|
|
51
88
|
//#endregion
|
|
52
|
-
export { parseFooterReference, parseFooterReferences, parseHeaderReference, parseHeaderReferences };
|
|
89
|
+
export { parseFooterReference, parseFooterReferences, parseHeaderFooterType, parseHeaderReference, parseHeaderReferences };
|
|
@@ -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;
|