@stll/folio-core 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/__fixtures__/paragraphs.js +2 -2
- package/dist/ai-edits/headless.js +7 -5
- package/dist/ai-edits/index.d.ts +2 -2
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/snapshot.js +13 -9
- package/dist/compare/content-alignment.js +94 -54
- package/dist/compare/inline-atoms.js +34 -20
- package/dist/compare/style-resources.js +6 -0
- package/dist/content-controls/mutateContentControls.js +4 -2
- package/dist/display-list/dom/renderDisplayListToDom.js +8 -8
- package/dist/document-operations.js +14 -3
- package/dist/docx/appVersionNormalization.d.ts +0 -18
- package/dist/docx/blockContentParser.js +8 -0
- package/dist/docx/blockRangeMarkers.d.ts +36 -0
- package/dist/docx/blockRangeMarkers.js +59 -0
- package/dist/docx/bookmarkParser.d.ts +2 -20
- package/dist/docx/bookmarkParser.js +6 -30
- package/dist/docx/borderParser.d.ts +13 -0
- package/dist/docx/borderParser.js +71 -0
- package/dist/docx/builtInStyles.d.ts +165 -0
- package/dist/docx/builtInStyles.js +239 -0
- package/dist/docx/commentIdNormalization.d.ts +3 -1
- package/dist/docx/commentIdNormalization.js +18 -1
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +80 -42
- package/dist/docx/commentReferenceNormalization.d.ts +4 -1
- package/dist/docx/commentReferenceNormalization.js +23 -14
- package/dist/docx/commentThreadKey.d.ts +18 -0
- package/dist/docx/commentThreadKey.js +22 -0
- package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
- package/dist/docx/danglingRelationshipReferences.js +30 -0
- package/dist/docx/defaultParagraphStyle.d.ts +18 -1
- package/dist/docx/defaultParagraphStyle.js +23 -1
- package/dist/docx/diagramPreview.js +87 -27
- package/dist/docx/documentParser.d.ts +2 -1
- package/dist/docx/documentParser.js +2 -2
- package/dist/docx/drawingUtils.d.ts +8 -1
- package/dist/docx/drawingUtils.js +12 -3
- package/dist/docx/fieldParser.js +3 -5
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +19 -4
- package/dist/docx/groupDrawingParser.js +4 -4
- package/dist/docx/headerFooterRefParser.d.ts +4 -3
- package/dist/docx/headerFooterRefParser.js +42 -12
- package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
- package/dist/docx/headerFooterReferenceNormalization.js +5 -1
- package/dist/docx/hyperlinkParser.js +13 -17
- package/dist/docx/imageParser.d.ts +10 -2
- package/dist/docx/imageParser.js +80 -30
- package/dist/docx/imageRawXml.d.ts +14 -1
- package/dist/docx/imageRawXml.js +35 -11
- package/dist/docx/markupRangeMarker.d.ts +15 -0
- package/dist/docx/markupRangeMarker.js +44 -0
- package/dist/docx/mathToMathml.js +12 -14
- package/dist/docx/nonVisualDrawingProps.d.ts +34 -0
- package/dist/docx/nonVisualDrawingProps.js +46 -0
- package/dist/docx/noteReferenceStyles.d.ts +29 -0
- package/dist/docx/noteReferenceStyles.js +70 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +4 -1
- package/dist/docx/numberingReferenceNormalization.js +20 -1
- package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
- package/dist/docx/paragraphParser.js +66 -99
- package/dist/docx/paragraphPropertySource.js +1 -0
- package/dist/docx/paragraphTextBoxEnrichment.js +3 -0
- package/dist/docx/paragraphTraversal.d.ts +37 -1
- package/dist/docx/paragraphTraversal.js +84 -1
- package/dist/docx/parseContext.d.ts +37 -0
- package/dist/docx/parseContext.js +67 -0
- package/dist/docx/parseWarningMessage.d.ts +6 -0
- package/dist/docx/parseWarningMessage.js +44 -0
- package/dist/docx/parser.js +83 -29
- package/dist/docx/previewBudget.d.ts +64 -0
- package/dist/docx/previewBudget.js +88 -0
- package/dist/docx/relsParser.d.ts +28 -11
- package/dist/docx/relsParser.js +26 -13
- package/dist/docx/revisionIdNormalization.js +96 -10
- package/dist/docx/rezip.js +80 -40
- package/dist/docx/runConsolidator.js +1 -2
- package/dist/docx/runParser.d.ts +8 -1
- package/dist/docx/runParser.js +30 -48
- package/dist/docx/sdtPropertiesPatch.js +24 -18
- package/dist/docx/sectionParser.d.ts +2 -1
- package/dist/docx/sectionParser.js +21 -65
- package/dist/docx/sectionReferenceHistory.js +2 -2
- package/dist/docx/selectiveSave.js +6 -6
- package/dist/docx/serializer/blockSdtSerializer.js +38 -26
- package/dist/docx/serializer/borderSerializer.d.ts +2 -3
- package/dist/docx/serializer/borderSerializer.js +13 -12
- package/dist/docx/serializer/commentSerializer.d.ts +41 -16
- package/dist/docx/serializer/commentSerializer.js +82 -72
- package/dist/docx/serializer/documentSerializer.d.ts +1 -5
- package/dist/docx/serializer/documentSerializer.js +6 -16
- package/dist/docx/serializer/fontTableSerializer.js +6 -6
- package/dist/docx/serializer/headerFooterSerializer.js +10 -5
- package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
- package/dist/docx/serializer/markupRangeAttributes.js +24 -0
- package/dist/docx/serializer/noteSerializer.js +5 -0
- package/dist/docx/serializer/numberingSerializer.js +7 -6
- package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
- package/dist/docx/serializer/paragraphSerializer.js +47 -52
- package/dist/docx/serializer/partNamespaces.js +2 -2
- package/dist/docx/serializer/runSerializer.js +57 -31
- package/dist/docx/serializer/sectionPropertiesSerializer.js +11 -10
- package/dist/docx/serializer/settingsSerializer.js +4 -3
- package/dist/docx/serializer/stylesSerializer.js +6 -6
- package/dist/docx/serializer/tableSerializer.js +37 -21
- package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
- package/dist/docx/serializer/textFormattingSerializer.js +29 -28
- package/dist/docx/serializer/themeSerializer.js +6 -6
- package/dist/docx/serializer/trackedChangeAttributes.js +2 -2
- package/dist/docx/serializer/xmlUtils.d.ts +1 -2
- package/dist/docx/serializer/xmlUtils.js +1 -13
- package/dist/docx/server/boundedArchive.d.ts +12 -0
- package/dist/docx/server/boundedArchive.js +20 -1
- package/dist/docx/server/build.js +8 -1
- package/dist/docx/server/createBilingualDocument.js +10 -18
- package/dist/docx/server/extractDocxText.js +3 -4
- package/dist/docx/server/validateDocxConformance.js +22 -1
- package/dist/docx/shadingParser.d.ts +6 -0
- package/dist/docx/shadingParser.js +32 -0
- package/dist/docx/shapeParser.js +10 -8
- package/dist/docx/styleParser.js +13 -87
- package/dist/docx/styleReferenceResolution.d.ts +36 -0
- package/dist/docx/styleReferenceResolution.js +51 -0
- package/dist/docx/tableLook.d.ts +57 -0
- package/dist/docx/tableLook.js +63 -0
- package/dist/docx/tableParser.d.ts +7 -9
- package/dist/docx/tableParser.js +64 -110
- package/dist/docx/textBoxParser.js +11 -6
- package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
- package/dist/docx/trackedMoveRangeNormalization.js +11 -21
- package/dist/docx/transitionalSpelling.d.ts +13 -2
- package/dist/docx/transitionalSpelling.js +23 -1
- package/dist/docx/unzip.d.ts +23 -0
- package/dist/docx/unzip.js +32 -22
- package/dist/docx/verbatimCapture.js +5 -12
- package/dist/docx/vmlImageParser.js +5 -4
- package/dist/docx/vmlPreview.d.ts +1 -3
- package/dist/docx/vmlPreview.js +2 -30
- package/dist/docx/watermarkParser.js +2 -2
- package/dist/docx/xmlParser.d.ts +38 -33
- package/dist/docx/xmlParser.js +92 -47
- package/dist/docx/xmlResourceLimits.d.ts +89 -9
- package/dist/docx/xmlResourceLimits.js +105 -24
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
- package/dist/internal/paragraphFormattingSerialization.js +29 -8
- package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +2 -2
- package/dist/layout-engine/measure/measureBlocks.js +1 -6
- package/dist/layout-engine/types.d.ts +8 -2
- package/dist/layout-engine/types.js +35 -2
- package/dist/layout-painter/renderImage.js +4 -3
- package/dist/layout-painter/renderParagraph.js +4 -3
- package/dist/managers/autoSaveCodec.js +2 -8
- package/dist/markdown/images.js +1 -4
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/internals.d.ts +6 -1
- package/dist/markdown/internals.js +14 -1
- package/dist/markdown/renderBlock.js +35 -21
- package/dist/markdown/renderParagraph.js +14 -5
- package/dist/markdown/renderRuns.js +4 -3
- package/dist/markdown/renderTable.js +4 -3
- package/dist/markdown/trailers.js +41 -7
- package/dist/markdown/types.d.ts +3 -7
- package/dist/prosemirror/attrs/index.js +71 -5
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
- package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
- package/dist/prosemirror/commands/image.js +1 -0
- package/dist/prosemirror/commands/index.d.ts +3 -3
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/paragraph.d.ts +3 -3
- package/dist/prosemirror/commands/paragraph.js +2 -2
- package/dist/prosemirror/commentIdAllocator.js +2 -7
- package/dist/prosemirror/conversion/fromProseDoc.js +197 -68
- package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
- package/dist/prosemirror/conversion/toProseDoc.js +458 -335
- package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +2 -3
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
- package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +6 -1
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +8 -2
- package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +8 -4
- package/dist/prosemirror/extensions/types.d.ts +2 -2
- package/dist/prosemirror/index.d.ts +3 -3
- package/dist/prosemirror/index.js +3 -3
- package/dist/prosemirror/insertOperations.d.ts +9 -2
- package/dist/prosemirror/insertOperations.js +9 -4
- package/dist/prosemirror/paragraphFormattingProvenance.d.ts +162 -0
- package/dist/prosemirror/paragraphFormattingProvenance.js +115 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
- package/dist/prosemirror/plugins/documentStyles.js +11 -1
- package/dist/prosemirror/plugins/index.d.ts +2 -2
- package/dist/prosemirror/plugins/index.js +2 -2
- package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
- package/dist/prosemirror/plugins/revisionIds.js +21 -6
- package/dist/prosemirror/runFormattingReconciliation.js +3 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
- package/dist/prosemirror/schema/nodes.d.ts +81 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -0
- package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
- package/dist/prosemirror/styles/styleResolver.js +12 -0
- package/dist/style-engine/styleEngine.d.ts +3 -0
- package/dist/style-engine/styleEngine.js +3 -0
- package/dist/style-sets/extract.js +1 -23
- package/dist/style-sets/stellaStyle.js +46 -39
- package/dist/style-sets/styleSetNormalization.d.ts +19 -0
- package/dist/style-sets/styleSetNormalization.js +99 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/base64.d.ts +36 -0
- package/dist/utils/base64.js +40 -0
- package/dist/utils/clipboard.js +2 -1
- package/dist/utils/createDocument.js +145 -20
- package/dist/utils/headingCollector.d.ts +8 -5
- package/dist/utils/headingCollector.js +23 -25
- package/dist/utils/tableOfContentsStyle.js +9 -2
- package/dist/utils/units.d.ts +10 -1
- package/dist/utils/units.js +12 -1
- package/dist/utils/urlSecurity.d.ts +8 -2
- package/dist/utils/urlSecurity.js +21 -3
- package/package.json +2 -2
- package/dist/docx/textWhitespace.d.ts +0 -4
- package/dist/docx/textWhitespace.js +0 -4
- package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
- package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
- package/dist/markdown/headings.d.ts +0 -13
- package/dist/markdown/headings.js +0 -20
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { deterministicHexId } from "../../utils/hexId.js";
|
|
2
|
+
import { commentThreadParaId } from "../commentThreadKey.js";
|
|
2
3
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
4
|
import { serializePartElement } from "./partNamespaces.js";
|
|
4
5
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
5
|
-
import {
|
|
6
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
6
7
|
//#region src/docx/serializer/commentSerializer.ts
|
|
7
8
|
/**
|
|
8
9
|
* Comment Serializer
|
|
@@ -26,9 +27,9 @@ function serializeParagraphWithAnnotationRef(paragraph, formatting) {
|
|
|
26
27
|
return xml.replace(/^<w:p(?=[\s>])[^>]*>/u, (openingTag) => `${openingTag}${annotationReference}`);
|
|
27
28
|
}
|
|
28
29
|
function serializeComment(comment) {
|
|
29
|
-
const attrs = [`w:id="${comment.id}"`, `w:author="${
|
|
30
|
-
if (comment.initials !== void 0) attrs.push(`w:initials="${
|
|
31
|
-
if (comment.date) attrs.push(`w:date="${
|
|
30
|
+
const attrs = [`w:id="${comment.id}"`, `w:author="${escapeXmlAttribute(comment.author)}"`];
|
|
31
|
+
if (comment.initials !== void 0) attrs.push(`w:initials="${escapeXmlAttribute(comment.initials)}"`);
|
|
32
|
+
if (comment.date) attrs.push(`w:date="${escapeXmlAttribute(comment.date)}"`);
|
|
32
33
|
let xml = `<w:comment ${attrs.join(" ")}>`;
|
|
33
34
|
if (comment.content.length > 0) {
|
|
34
35
|
xml += serializeParagraphWithAnnotationRef(comment.content[0], comment.annotationReferenceFormatting);
|
|
@@ -61,33 +62,6 @@ const COMMENTS_EXTENDED_BASELINE_PREFIXES = [
|
|
|
61
62
|
];
|
|
62
63
|
const XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
|
|
63
64
|
/**
|
|
64
|
-
* Serialize comments array to comments.xml content. Returns a valid empty
|
|
65
|
-
* `<w:comments/>` document for an empty array so callers can overwrite an
|
|
66
|
-
* existing `word/comments.xml` part when the editor has removed the last
|
|
67
|
-
* comment — leaving the previous file in place would otherwise re-emit
|
|
68
|
-
* the orphaned comment threads on every save.
|
|
69
|
-
*/
|
|
70
|
-
function serializeComments(comments, sourceBindings) {
|
|
71
|
-
const topLevel = [];
|
|
72
|
-
const replies = [];
|
|
73
|
-
for (const c of comments) {
|
|
74
|
-
const { parentId } = c;
|
|
75
|
-
(parentId === null || parentId === void 0 ? topLevel : replies).push(c);
|
|
76
|
-
}
|
|
77
|
-
const body = topLevel.map((comment) => serializeComment(comment)).join("") + replies.map((reply) => serializeComment(reply)).join("");
|
|
78
|
-
return XML_DECLARATION + serializePartElement({
|
|
79
|
-
partPath: "word/comments.xml",
|
|
80
|
-
rootName: "w:comments",
|
|
81
|
-
baselinePrefixes: COMMENTS_BASELINE_PREFIXES,
|
|
82
|
-
sourceBindings,
|
|
83
|
-
body
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
/** The `w14:paraId` Word threads a comment by: its LAST paragraph's paraId. */
|
|
87
|
-
function commentThreadParaId(comment) {
|
|
88
|
-
return comment.content?.at(-1)?.paraId;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
65
|
* The ids of comments that need a `commentsExtended.xml` entry: a reply, a
|
|
92
66
|
* reply's parent (the thread root), or any comment carrying a resolved state.
|
|
93
67
|
* A plain top-level comment set yields an empty set, so no part is written.
|
|
@@ -108,29 +82,71 @@ const commentPlainText = (comment) => {
|
|
|
108
82
|
return text;
|
|
109
83
|
};
|
|
110
84
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
85
|
+
* Plan both comment parts from the model, in the model's own order.
|
|
86
|
+
*
|
|
87
|
+
* The order is the document's: the order `word/comments.xml` listed the
|
|
88
|
+
* comments in is the order it is written back in, so a save neither reshuffles
|
|
89
|
+
* a reviewer's threads nor hands the next parse a different `comments[]` than
|
|
90
|
+
* the one it read.
|
|
91
|
+
*
|
|
92
|
+
* Planning also mints the `w14:paraId` a thread needs when the model has none —
|
|
93
|
+
* a comment written in the editor has no Word-authored id, and without one the
|
|
94
|
+
* `commentsExtended.xml` link would be dropped. Minting is deterministic
|
|
95
|
+
* (comment id and text derived) so repeated saves mint the same id, and it
|
|
96
|
+
* happens here rather than at each call site because both parts must see it.
|
|
119
97
|
*/
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
const used = /* @__PURE__ */ new Set();
|
|
124
|
-
for (const comment of comments) for (const paragraph of comment.content ?? []) if (paragraph.paraId) used.add(paragraph.paraId.toUpperCase());
|
|
98
|
+
const planCommentParts = (comments) => {
|
|
99
|
+
const byId = /* @__PURE__ */ new Map();
|
|
100
|
+
const order = [];
|
|
125
101
|
for (const comment of comments) {
|
|
126
|
-
if (
|
|
102
|
+
if (byId.has(comment.id)) continue;
|
|
103
|
+
byId.set(comment.id, comment);
|
|
104
|
+
order.push(comment.id);
|
|
105
|
+
}
|
|
106
|
+
const planned = [...byId.values()];
|
|
107
|
+
const threadedIds = threadedCommentIds(planned);
|
|
108
|
+
const used = /* @__PURE__ */ new Set();
|
|
109
|
+
for (const comment of planned) for (const paragraph of comment.content ?? []) if (paragraph.paraId) used.add(paragraph.paraId.toUpperCase());
|
|
110
|
+
const threadParaIdById = /* @__PURE__ */ new Map();
|
|
111
|
+
for (const id of order) {
|
|
112
|
+
const comment = byId.get(id);
|
|
113
|
+
const existing = commentThreadParaId((comment.content ?? []).map(({ paraId }) => paraId));
|
|
114
|
+
if (existing) {
|
|
115
|
+
threadParaIdById.set(id, existing);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
127
118
|
const last = (comment.content ?? []).at(-1);
|
|
128
|
-
if (!
|
|
129
|
-
let
|
|
130
|
-
for (let salt = 1; used.has(
|
|
131
|
-
used.add(
|
|
132
|
-
last.paraId =
|
|
119
|
+
if (!threadedIds.has(id) || !last) continue;
|
|
120
|
+
let minted = deterministicHexId(`comment:${id}:${commentPlainText(comment)}`);
|
|
121
|
+
for (let salt = 1; used.has(minted.toUpperCase()); salt++) minted = deterministicHexId(`comment:${id}:${salt}`);
|
|
122
|
+
used.add(minted.toUpperCase());
|
|
123
|
+
last.paraId = minted;
|
|
124
|
+
threadParaIdById.set(id, minted);
|
|
133
125
|
}
|
|
126
|
+
return {
|
|
127
|
+
order,
|
|
128
|
+
byId,
|
|
129
|
+
threadParaIdById,
|
|
130
|
+
threadedIds
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Serialize a comment plan to comments.xml content. Returns a valid empty
|
|
135
|
+
* `<w:comments/>` document for an empty plan so callers can overwrite an
|
|
136
|
+
* existing `word/comments.xml` part when the editor has removed the last
|
|
137
|
+
* comment — leaving the previous file in place would otherwise re-emit
|
|
138
|
+
* the orphaned comment threads on every save.
|
|
139
|
+
*/
|
|
140
|
+
function serializeComments({ order, byId }, sourceBindings) {
|
|
141
|
+
let body = "";
|
|
142
|
+
for (const id of order) body += serializeComment(byId.get(id));
|
|
143
|
+
return XML_DECLARATION + serializePartElement({
|
|
144
|
+
partPath: "word/comments.xml",
|
|
145
|
+
rootName: "w:comments",
|
|
146
|
+
baselinePrefixes: COMMENTS_BASELINE_PREFIXES,
|
|
147
|
+
sourceBindings,
|
|
148
|
+
body
|
|
149
|
+
});
|
|
134
150
|
}
|
|
135
151
|
/**
|
|
136
152
|
* Build the `commentsExtended.xml` entries for the comments that participate in
|
|
@@ -139,29 +155,23 @@ function ensureThreadedCommentParaIds(comments) {
|
|
|
139
155
|
* leave any existing part untouched — a plain top-level comment set gets no
|
|
140
156
|
* `commentsExtended.xml`, matching how Word omits it.
|
|
141
157
|
*
|
|
142
|
-
* A `w15:commentEx` keys on the comment's
|
|
143
|
-
* `w15:paraIdParent`
|
|
144
|
-
*
|
|
145
|
-
* skip is a last-ditch safety for a malformed model.
|
|
158
|
+
* A `w15:commentEx` keys on the comment's thread paraId; a reply's
|
|
159
|
+
* `w15:paraIdParent` on its parent's. Both come from the plan, so a reply and
|
|
160
|
+
* its parent name each other by `w:id` right up to the attribute.
|
|
146
161
|
*/
|
|
147
|
-
function buildCommentExtendedEntries(
|
|
148
|
-
|
|
149
|
-
if (threaded.size === 0) return null;
|
|
150
|
-
const paraIdByCommentId = /* @__PURE__ */ new Map();
|
|
151
|
-
for (const comment of comments) {
|
|
152
|
-
const paraId = commentThreadParaId(comment);
|
|
153
|
-
if (paraId) paraIdByCommentId.set(comment.id, paraId);
|
|
154
|
-
}
|
|
162
|
+
function buildCommentExtendedEntries({ order, byId, threadParaIdById, threadedIds }) {
|
|
163
|
+
if (threadedIds.size === 0) return null;
|
|
155
164
|
const entries = [];
|
|
156
|
-
for (const
|
|
157
|
-
if (!
|
|
158
|
-
const paraId =
|
|
165
|
+
for (const id of order) {
|
|
166
|
+
if (!threadedIds.has(id)) continue;
|
|
167
|
+
const paraId = threadParaIdById.get(id);
|
|
159
168
|
if (!paraId) continue;
|
|
160
|
-
const
|
|
169
|
+
const { parentId, done } = byId.get(id);
|
|
170
|
+
const parentParaId = parentId !== void 0 ? threadParaIdById.get(parentId) : void 0;
|
|
161
171
|
entries.push({
|
|
162
172
|
paraId,
|
|
163
173
|
...parentParaId !== void 0 ? { paraIdParent: parentParaId } : {},
|
|
164
|
-
done:
|
|
174
|
+
done: done ?? false
|
|
165
175
|
});
|
|
166
176
|
}
|
|
167
177
|
return entries.length > 0 ? entries : null;
|
|
@@ -172,12 +182,12 @@ function buildCommentExtendedEntries(comments) {
|
|
|
172
182
|
* {@link buildCommentExtendedEntries}). This is the part that makes Word render
|
|
173
183
|
* a comment as a REPLY rather than a separate top-level thread.
|
|
174
184
|
*/
|
|
175
|
-
function serializeCommentsExtended(
|
|
176
|
-
const entries = buildCommentExtendedEntries(
|
|
185
|
+
function serializeCommentsExtended(plan) {
|
|
186
|
+
const entries = buildCommentExtendedEntries(plan);
|
|
177
187
|
if (!entries) return null;
|
|
178
188
|
const body = entries.map((entry) => {
|
|
179
|
-
const parentAttr = entry.paraIdParent !== void 0 ? ` w15:paraIdParent="${
|
|
180
|
-
return `<w15:commentEx w15:paraId="${
|
|
189
|
+
const parentAttr = entry.paraIdParent !== void 0 ? ` w15:paraIdParent="${escapeXmlAttribute(entry.paraIdParent)}"` : "";
|
|
190
|
+
return `<w15:commentEx w15:paraId="${escapeXmlAttribute(entry.paraId)}"${parentAttr} w15:done="${entry.done ? "1" : "0"}"/>`;
|
|
181
191
|
}).join("");
|
|
182
192
|
return XML_DECLARATION + serializePartElement({
|
|
183
193
|
partPath: "word/commentsExtended.xml",
|
|
@@ -188,4 +198,4 @@ function serializeCommentsExtended(comments) {
|
|
|
188
198
|
});
|
|
189
199
|
}
|
|
190
200
|
//#endregion
|
|
191
|
-
export {
|
|
201
|
+
export { planCommentParts, serializeComments, serializeCommentsExtended };
|
|
@@ -47,10 +47,6 @@ declare function getDocumentParagraphCount(doc: document_d_exports.Document): nu
|
|
|
47
47
|
* Get table count in document
|
|
48
48
|
*/
|
|
49
49
|
declare function getDocumentTableCount(doc: document_d_exports.Document): number;
|
|
50
|
-
/**
|
|
51
|
-
* Get plain text from document (for comparison/debugging)
|
|
52
|
-
*/
|
|
53
|
-
declare function getDocumentPlainText(doc: document_d_exports.Document): string;
|
|
54
50
|
/**
|
|
55
51
|
* Create an empty document
|
|
56
52
|
*/
|
|
@@ -63,4 +59,4 @@ declare function createSimpleDocument(paragraphs: {
|
|
|
63
59
|
styleId?: string;
|
|
64
60
|
}[]): document_d_exports.Document;
|
|
65
61
|
//#endregion
|
|
66
|
-
export { createEmptyDocument, createSimpleDocument, getDocumentContentCount, getDocumentParagraphCount,
|
|
62
|
+
export { createEmptyDocument, createSimpleDocument, getDocumentContentCount, getDocumentParagraphCount, getDocumentTableCount, hasDocumentContent, hasDocumentSections, hasSectionProperties, serializeDocument, serializeDocumentBody, serializeDocumentBodyElement };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withBlockRangeMarkers } from "../blockRangeMarkers.js";
|
|
1
2
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
2
3
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
4
|
import { serializePartElement } from "./partNamespaces.js";
|
|
@@ -40,6 +41,10 @@ const DOCUMENT_BASELINE_PREFIXES = [
|
|
|
40
41
|
* Serialize a single block content item (paragraph, table, or block-level SDT).
|
|
41
42
|
*/
|
|
42
43
|
function serializeBlockContent(block) {
|
|
44
|
+
return withBlockRangeMarkers(block, serializeBlockBody(block));
|
|
45
|
+
}
|
|
46
|
+
/** The block itself, without the range markers that stood around it. */
|
|
47
|
+
function serializeBlockBody(block) {
|
|
43
48
|
if (block.type === "paragraph") return serializeParagraph(block);
|
|
44
49
|
if (block.type === "table") return serializeTable(block, serializeParagraph);
|
|
45
50
|
return serializeBlockSdt(block, serializeBlockContent);
|
|
@@ -127,21 +132,6 @@ function getDocumentTableCount(doc) {
|
|
|
127
132
|
return doc.package.document.content.filter((b) => b.type === "table").length;
|
|
128
133
|
}
|
|
129
134
|
/**
|
|
130
|
-
* Get plain text from document (for comparison/debugging)
|
|
131
|
-
*/
|
|
132
|
-
function getDocumentPlainText(doc) {
|
|
133
|
-
const texts = [];
|
|
134
|
-
for (const block of doc.package.document.content) if (block.type === "paragraph") {
|
|
135
|
-
for (const content of block.content) if (content.type === "run") {
|
|
136
|
-
for (const item of content.content) if (item.type === "text") texts.push(item.text);
|
|
137
|
-
else if (item.type === "tab") texts.push(" ");
|
|
138
|
-
else if (item.type === "break") texts.push("\n");
|
|
139
|
-
}
|
|
140
|
-
texts.push("\n");
|
|
141
|
-
}
|
|
142
|
-
return texts.join("");
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
135
|
* Create an empty document
|
|
146
136
|
*/
|
|
147
137
|
function createEmptyDocument() {
|
|
@@ -164,4 +154,4 @@ function createSimpleDocument(paragraphs) {
|
|
|
164
154
|
})) } } };
|
|
165
155
|
}
|
|
166
156
|
//#endregion
|
|
167
|
-
export { createEmptyDocument, createSimpleDocument, getDocumentContentCount, getDocumentParagraphCount,
|
|
157
|
+
export { createEmptyDocument, createSimpleDocument, getDocumentContentCount, getDocumentParagraphCount, getDocumentTableCount, hasDocumentContent, hasDocumentSections, hasSectionProperties, serializeDocument, serializeDocumentBody, serializeDocumentBodyElement };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { serializePartElement } from "./partNamespaces.js";
|
|
2
|
-
import {
|
|
2
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
3
3
|
//#region src/docx/serializer/fontTableSerializer.ts
|
|
4
4
|
const serializeFontTableXml = (fontTable) => "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
5
5
|
partPath: "word/fontTable.xml",
|
|
@@ -10,20 +10,20 @@ const serializeFontTableXml = (fontTable) => "<?xml version=\"1.0\" encoding=\"U
|
|
|
10
10
|
});
|
|
11
11
|
const serializeFont = (font) => {
|
|
12
12
|
const parts = [];
|
|
13
|
-
if (font.altName) parts.push(`<w:altName w:val="${
|
|
14
|
-
if (font.panose1) parts.push(`<w:panose1 w:val="${
|
|
15
|
-
if (font.charset) parts.push(`<w:charset w:val="${
|
|
13
|
+
if (font.altName) parts.push(`<w:altName w:val="${escapeXmlAttribute(font.altName)}"/>`);
|
|
14
|
+
if (font.panose1) parts.push(`<w:panose1 w:val="${escapeXmlAttribute(font.panose1)}"/>`);
|
|
15
|
+
if (font.charset) parts.push(`<w:charset w:val="${escapeXmlAttribute(font.charset)}"/>`);
|
|
16
16
|
if (font.family) parts.push(`<w:family w:val="${font.family}"/>`);
|
|
17
17
|
if (font.pitch) parts.push(`<w:pitch w:val="${font.pitch}"/>`);
|
|
18
18
|
if (font.sig) {
|
|
19
19
|
const attrs = [];
|
|
20
20
|
for (const [key, value] of Object.entries(font.sig)) {
|
|
21
21
|
if (value === void 0) continue;
|
|
22
|
-
attrs.push(`w:${key}="${
|
|
22
|
+
attrs.push(`w:${key}="${escapeXmlAttribute(value)}"`);
|
|
23
23
|
}
|
|
24
24
|
if (attrs.length > 0) parts.push(`<w:sig ${attrs.join(" ")}/>`);
|
|
25
25
|
}
|
|
26
|
-
return `<w:font w:name="${
|
|
26
|
+
return `<w:font w:name="${escapeXmlAttribute(font.name)}">${parts.join("")}</w:font>`;
|
|
27
27
|
};
|
|
28
28
|
//#endregion
|
|
29
29
|
export { serializeFontTableXml };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withBlockRangeMarkers } from "../blockRangeMarkers.js";
|
|
1
2
|
import { canReplayHeaderFooterVerbatim, getHeaderFooterVerbatimXml } from "../headerFooterVerbatim.js";
|
|
2
3
|
import { isEmptyParagraph } from "../paragraphParser.js";
|
|
3
4
|
import { captureVerbatimXml } from "../verbatimCapture.js";
|
|
@@ -6,7 +7,7 @@ import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
|
6
7
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
7
8
|
import { serializePartElement } from "./partNamespaces.js";
|
|
8
9
|
import { serializeTable } from "./tableSerializer.js";
|
|
9
|
-
import {
|
|
10
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
10
11
|
//#region src/docx/serializer/headerFooterSerializer.ts
|
|
11
12
|
const HEADER_FOOTER_BASELINE_PREFIXES = [
|
|
12
13
|
"wpc",
|
|
@@ -36,6 +37,10 @@ const HEADER_FOOTER_BASELINE_PREFIXES = [
|
|
|
36
37
|
* header/footer.
|
|
37
38
|
*/
|
|
38
39
|
function serializeBlock(block) {
|
|
40
|
+
return withBlockRangeMarkers(block, serializeBlockBody(block));
|
|
41
|
+
}
|
|
42
|
+
/** The block itself, without the range markers that stood around it. */
|
|
43
|
+
function serializeBlockBody(block) {
|
|
39
44
|
if (block.type === "paragraph") return serializeParagraph(block);
|
|
40
45
|
if (block.type === "table") return serializeTable(block, serializeParagraph);
|
|
41
46
|
return serializeBlockSdt(block, serializeBlock);
|
|
@@ -80,7 +85,7 @@ function serializeRawWatermarkIntoHost({ hostXml, rawWatermarkXml }) {
|
|
|
80
85
|
if (!rawHost || getLocalName(rawHost.name ?? "") !== "p") return rawWatermarkXml;
|
|
81
86
|
const watermarkContent = (rawHost.elements ?? []).filter((child) => child.type === "element" && getLocalName(child.name ?? "") !== "pPr").map((child) => captureVerbatimXml(child)).join("");
|
|
82
87
|
if (!watermarkContent) return rawWatermarkXml;
|
|
83
|
-
const namespaceAttributes = Object.entries(rawHost.attributes ?? {}).filter(([name, value]) => value !== void 0 && (name === "xmlns" || name.startsWith("xmlns:"))).map(([name, value]) => ` ${name}="${
|
|
88
|
+
const namespaceAttributes = Object.entries(rawHost.attributes ?? {}).filter(([name, value]) => value !== void 0 && (name === "xmlns" || name.startsWith("xmlns:"))).map(([name, value]) => ` ${name}="${escapeXmlAttribute(String(value))}"`).join("");
|
|
84
89
|
return hostXml.replace(/^<w:p(?=[\s>])/u, `<w:p${namespaceAttributes}`).replace("</w:p>", `${watermarkContent}</w:p>`);
|
|
85
90
|
}
|
|
86
91
|
function serializeWatermarkParagraph(hf) {
|
|
@@ -96,15 +101,15 @@ function synthesizeTextWatermark(watermark) {
|
|
|
96
101
|
const rotation = watermark.diagonal === false ? 0 : 315;
|
|
97
102
|
const fillcolor = watermark.color && watermark.color !== "auto" ? `#${watermark.color}` : "#C0C0C0";
|
|
98
103
|
const fontFamily = watermark.font ?? "Calibri";
|
|
99
|
-
const text =
|
|
100
|
-
return `<w:p><w:r><w:pict><v:shape id="PowerPlusWaterMarkObject1" type="#_x0000_t136" style="position:absolute;margin-left:0;margin-top:0;width:415pt;height:207pt;rotation:${rotation};z-index:-251658240;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin" fillcolor="${fillcolor}" stroked="f">${watermark.opacity !== void 0 ? `<v:fill opacity="${watermark.opacity}"/>` : ""}<v:textpath style="font-family:"${
|
|
104
|
+
const text = escapeXmlAttribute(watermark.text);
|
|
105
|
+
return `<w:p><w:r><w:pict><v:shape id="PowerPlusWaterMarkObject1" type="#_x0000_t136" style="position:absolute;margin-left:0;margin-top:0;width:415pt;height:207pt;rotation:${rotation};z-index:-251658240;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin" fillcolor="${fillcolor}" stroked="f">${watermark.opacity !== void 0 ? `<v:fill opacity="${watermark.opacity}"/>` : ""}<v:textpath style="font-family:"${escapeXmlAttribute(fontFamily)}";font-size:1pt" string="${text}"/></v:shape></w:pict></w:r></w:p>`;
|
|
101
106
|
}
|
|
102
107
|
const PICTURE_WATERMARK_DEFAULT_WIDTH_PT = 415;
|
|
103
108
|
const PICTURE_WATERMARK_DEFAULT_HEIGHT_PT = 207;
|
|
104
109
|
const PICTURE_WATERMARK_WASHOUT_GAIN = "19661f";
|
|
105
110
|
const PICTURE_WATERMARK_WASHOUT_BLACKLEVEL = "22938f";
|
|
106
111
|
function synthesizePictureWatermark(watermark) {
|
|
107
|
-
const rId =
|
|
112
|
+
const rId = escapeXmlAttribute(watermark.imageRId);
|
|
108
113
|
return `<w:p><w:r><w:pict><v:shape id="WordPictureWatermark1" type="#_x0000_t75" style="position:absolute;margin-left:0;margin-top:0;width:${watermark.scale === void 0 ? watermark.widthPt ?? PICTURE_WATERMARK_DEFAULT_WIDTH_PT : PICTURE_WATERMARK_DEFAULT_WIDTH_PT * watermark.scale}pt;height:${watermark.scale === void 0 ? watermark.heightPt ?? PICTURE_WATERMARK_DEFAULT_HEIGHT_PT : PICTURE_WATERMARK_DEFAULT_HEIGHT_PT * watermark.scale}pt;z-index:-251658240;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin"><v:imagedata r:id="${rId}" o:title=""${watermark.washout === false ? "" : ` gain="${PICTURE_WATERMARK_WASHOUT_GAIN}" blacklevel="${PICTURE_WATERMARK_WASHOUT_BLACKLEVEL}"`}/></v:shape></w:pict></w:r></w:p>`;
|
|
109
114
|
}
|
|
110
115
|
//#endregion
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
//#region src/docx/serializer/markupRangeAttributes.d.ts
|
|
3
|
+
declare const markupRangeAttributes: (marker: document_d_exports.MarkupRangeMarker) => string[];
|
|
4
|
+
declare const bookmarkRangeAttributes: (marker: document_d_exports.BookmarkRangeMarker) => string[];
|
|
5
|
+
/** `w:author` is required, so it is always written; `w:date` only when known. */
|
|
6
|
+
declare const moveBookmarkAttributes: (marker: document_d_exports.MoveBookmarkMarker) => string[];
|
|
7
|
+
//#endregion
|
|
8
|
+
export { bookmarkRangeAttributes, markupRangeAttributes, moveBookmarkAttributes };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
2
|
+
//#region src/docx/serializer/markupRangeAttributes.ts
|
|
3
|
+
const attribute = (name, value) => `${name}="${escapeXmlAttribute(String(value))}"`;
|
|
4
|
+
const markupRangeAttributes = (marker) => {
|
|
5
|
+
const attributes = [attribute("w:id", marker.id)];
|
|
6
|
+
if (marker.displacedByCustomXml !== void 0) attributes.push(attribute("w:displacedByCustomXml", marker.displacedByCustomXml));
|
|
7
|
+
return attributes;
|
|
8
|
+
};
|
|
9
|
+
const bookmarkRangeAttributes = (marker) => {
|
|
10
|
+
const attributes = markupRangeAttributes(marker);
|
|
11
|
+
if (marker.colFirst !== void 0) attributes.push(attribute("w:colFirst", marker.colFirst));
|
|
12
|
+
if (marker.colLast !== void 0) attributes.push(attribute("w:colLast", marker.colLast));
|
|
13
|
+
attributes.push(attribute("w:name", marker.name));
|
|
14
|
+
return attributes;
|
|
15
|
+
};
|
|
16
|
+
/** `w:author` is required, so it is always written; `w:date` only when known. */
|
|
17
|
+
const moveBookmarkAttributes = (marker) => {
|
|
18
|
+
const attributes = bookmarkRangeAttributes(marker);
|
|
19
|
+
attributes.push(attribute("w:author", marker.author.trim() || "Unknown"));
|
|
20
|
+
if (marker.date !== void 0 && marker.date.trim().length > 0) attributes.push(attribute("w:date", marker.date.trim()));
|
|
21
|
+
return attributes;
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { bookmarkRangeAttributes, markupRangeAttributes, moveBookmarkAttributes };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withBlockRangeMarkers } from "../blockRangeMarkers.js";
|
|
1
2
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
2
3
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
4
|
import { serializePartElement } from "./partNamespaces.js";
|
|
@@ -38,6 +39,10 @@ const serializeNotePart = (elementName, body) => "<?xml version=\"1.0\" encoding
|
|
|
38
39
|
* note body.
|
|
39
40
|
*/
|
|
40
41
|
function serializeBlock(block) {
|
|
42
|
+
return withBlockRangeMarkers(block, serializeBlockBody(block));
|
|
43
|
+
}
|
|
44
|
+
/** The block itself, without the range markers that stood around it. */
|
|
45
|
+
function serializeBlockBody(block) {
|
|
41
46
|
if (block.type === "paragraph") return serializeParagraph(block);
|
|
42
47
|
if (block.type === "table") return serializeTable(block, serializeParagraph);
|
|
43
48
|
return serializeBlockSdt(block, serializeBlock);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { serializePartElement } from "./partNamespaces.js";
|
|
2
2
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
3
|
-
import {
|
|
3
|
+
import { intAttr } from "./xmlUtils.js";
|
|
4
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
4
5
|
//#region src/docx/serializer/numberingSerializer.ts
|
|
5
6
|
/**
|
|
6
7
|
* Serialize a level's paragraph properties — the modeled subset is indentation
|
|
@@ -36,11 +37,11 @@ function serializeLevelParagraphProps(pPr) {
|
|
|
36
37
|
function serializeLevel(level) {
|
|
37
38
|
const parts = [];
|
|
38
39
|
if (level.start !== void 0) parts.push(`<w:start w:val="${intAttr(level.start)}"/>`);
|
|
39
|
-
parts.push(`<w:numFmt w:val="${
|
|
40
|
+
parts.push(`<w:numFmt w:val="${escapeXmlAttribute(level.numFmt)}"/>`);
|
|
40
41
|
if (level.lvlRestart !== void 0) parts.push(`<w:lvlRestart w:val="${intAttr(level.lvlRestart)}"/>`);
|
|
41
42
|
if (level.isLgl) parts.push("<w:isLgl/>");
|
|
42
43
|
if (level.suffix) parts.push(`<w:suff w:val="${level.suffix}"/>`);
|
|
43
|
-
parts.push(`<w:lvlText w:val="${
|
|
44
|
+
parts.push(`<w:lvlText w:val="${escapeXmlAttribute(level.lvlText)}"/>`);
|
|
44
45
|
if (level.legacy) {
|
|
45
46
|
const legacyAttrs = [`w:legacy="${level.legacy.legacy ? 1 : 0}"`];
|
|
46
47
|
if (level.legacy.legacySpace !== void 0) legacyAttrs.push(`w:legacySpace="${intAttr(level.legacy.legacySpace)}"`);
|
|
@@ -60,9 +61,9 @@ function serializeLevel(level) {
|
|
|
60
61
|
function serializeAbstractNum(abstractNum) {
|
|
61
62
|
const parts = [];
|
|
62
63
|
if (abstractNum.multiLevelType) parts.push(`<w:multiLevelType w:val="${abstractNum.multiLevelType}"/>`);
|
|
63
|
-
if (abstractNum.name !== void 0) parts.push(`<w:name w:val="${
|
|
64
|
-
if (abstractNum.styleLink !== void 0) parts.push(`<w:styleLink w:val="${
|
|
65
|
-
if (abstractNum.numStyleLink !== void 0) parts.push(`<w:numStyleLink w:val="${
|
|
64
|
+
if (abstractNum.name !== void 0) parts.push(`<w:name w:val="${escapeXmlAttribute(abstractNum.name)}"/>`);
|
|
65
|
+
if (abstractNum.styleLink !== void 0) parts.push(`<w:styleLink w:val="${escapeXmlAttribute(abstractNum.styleLink)}"/>`);
|
|
66
|
+
if (abstractNum.numStyleLink !== void 0) parts.push(`<w:numStyleLink w:val="${escapeXmlAttribute(abstractNum.numStyleLink)}"/>`);
|
|
66
67
|
const levels = [...abstractNum.levels].sort((a, b) => a.ilvl - b.ilvl);
|
|
67
68
|
for (const level of levels) parts.push(serializeLevel(level));
|
|
68
69
|
return `<w:abstractNum w:abstractNumId="${intAttr(abstractNum.abstractNumId)}">${parts.join("")}</w:abstractNum>`;
|
|
@@ -23,10 +23,6 @@ declare function hasParagraphContent(paragraph: document_d_exports.Paragraph): b
|
|
|
23
23
|
* Check if a paragraph has formatting
|
|
24
24
|
*/
|
|
25
25
|
declare function hasParagraphFormatting(paragraph: document_d_exports.Paragraph): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Get plain text from a paragraph (for comparison/debugging)
|
|
28
|
-
*/
|
|
29
|
-
declare function getParagraphPlainText(paragraph: document_d_exports.Paragraph): string;
|
|
30
26
|
/**
|
|
31
27
|
* Create an empty paragraph
|
|
32
28
|
*/
|
|
@@ -44,4 +40,4 @@ declare function isListParagraph(paragraph: document_d_exports.Paragraph): boole
|
|
|
44
40
|
*/
|
|
45
41
|
declare function getListLevel(paragraph: document_d_exports.Paragraph): number;
|
|
46
42
|
//#endregion
|
|
47
|
-
export { createEmptyParagraph, createTextParagraph, getListLevel,
|
|
43
|
+
export { createEmptyParagraph, createTextParagraph, getListLevel, hasParagraphContent, hasParagraphFormatting, isListParagraph, serializeParagraph, serializeParagraphFormatting, serializeParagraphs };
|