@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
|
@@ -5,12 +5,14 @@ import { DATE_UTC_ATTRIBUTE } from "../trackedChangeInfo.js";
|
|
|
5
5
|
import { toTransitionalNamespaceUri } from "../transitionalSpelling.js";
|
|
6
6
|
import { captureVerbatimXml, sanitizeCapturedXmlElement } from "../verbatimCapture.js";
|
|
7
7
|
import { NAMESPACES, OOXML_NAMESPACE_SCOPE, cloneElement, getChildElements, getLocalName, parseXml } from "../xmlParser.js";
|
|
8
|
+
import { bookmarkRangeAttributes, markupRangeAttributes, moveBookmarkAttributes } from "./markupRangeAttributes.js";
|
|
8
9
|
import { serializeRun } from "./runSerializer.js";
|
|
9
10
|
import { serializeSectionProperties } from "./sectionPropertiesSerializer.js";
|
|
10
11
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
11
12
|
import { serializeTrackedChangeAttributes, trackedChangeAttributeRecord } from "./trackedChangeAttributes.js";
|
|
12
|
-
import {
|
|
13
|
+
import { isSingleWellFormedElement } from "./xmlUtils.js";
|
|
13
14
|
import { panic } from "better-result";
|
|
15
|
+
import { escapeXmlAttribute, escapeXmlText } from "@stll/docx-core";
|
|
14
16
|
import { PARAGRAPH_MARK_CHANGE_KINDS } from "@stll/docx-core/model";
|
|
15
17
|
//#region src/docx/serializer/paragraphSerializer.ts
|
|
16
18
|
/**
|
|
@@ -21,13 +23,20 @@ function serializeParagraphMarkChange(mark) {
|
|
|
21
23
|
return `<w:${mark.kind} ${attrs}/>`;
|
|
22
24
|
}
|
|
23
25
|
const RESERVED_PARAGRAPH_PROPERTY_CHILDREN = /* @__PURE__ */ new Set(["pPrChange", "sectPr"]);
|
|
26
|
+
/**
|
|
27
|
+
* Revision records a captured `w:pPr` may not carry into a replay.
|
|
28
|
+
*
|
|
29
|
+
* `w:numberingChange` is not among them: the model holds it
|
|
30
|
+
* (`ParagraphFormatting.numberingChangeXml`) and the serializer writes it
|
|
31
|
+
* back, so both paths keep it. Refusing the capture used to force a rebuild
|
|
32
|
+
* that could not write it, which turned a replay gate into a lost revision.
|
|
33
|
+
*/
|
|
24
34
|
const RESERVED_PARAGRAPH_CAPTURE_CHILDREN = /* @__PURE__ */ new Set([
|
|
25
35
|
...RESERVED_PARAGRAPH_PROPERTY_CHILDREN,
|
|
26
36
|
...PARAGRAPH_MARK_CHANGE_KINDS,
|
|
27
37
|
"cellDel",
|
|
28
38
|
"cellIns",
|
|
29
39
|
"cellMerge",
|
|
30
|
-
"numberingChange",
|
|
31
40
|
"rPrChange",
|
|
32
41
|
"tblGridChange",
|
|
33
42
|
"tblPrChange",
|
|
@@ -119,7 +128,11 @@ const PARAGRAPH_MARK_BASE_CHILDREN = /* @__PURE__ */ new Set([
|
|
|
119
128
|
"oMath"
|
|
120
129
|
]);
|
|
121
130
|
const PARAGRAPH_NESTED_PROPERTY_CHILDREN = /* @__PURE__ */ new Map([
|
|
122
|
-
["numPr", /* @__PURE__ */ new Set([
|
|
131
|
+
["numPr", /* @__PURE__ */ new Set([
|
|
132
|
+
"ilvl",
|
|
133
|
+
"numId",
|
|
134
|
+
"numberingChange"
|
|
135
|
+
])],
|
|
123
136
|
["pBdr", /* @__PURE__ */ new Set([
|
|
124
137
|
"top",
|
|
125
138
|
"left",
|
|
@@ -319,13 +332,13 @@ function serializeParagraphPropertyChange(change) {
|
|
|
319
332
|
/** The attribute list of a `w:hyperlink`, without its children. */
|
|
320
333
|
function hyperlinkAttributes(hyperlink) {
|
|
321
334
|
const attrs = [];
|
|
322
|
-
if (hyperlink.rId) attrs.push(`r:id="${
|
|
323
|
-
if (hyperlink.anchor) attrs.push(`w:anchor="${
|
|
324
|
-
if (hyperlink.tooltip) attrs.push(`w:tooltip="${
|
|
325
|
-
if (hyperlink.target) attrs.push(`w:tgtFrame="${
|
|
335
|
+
if (hyperlink.rId) attrs.push(`r:id="${escapeXmlAttribute(hyperlink.rId)}"`);
|
|
336
|
+
if (hyperlink.anchor) attrs.push(`w:anchor="${escapeXmlAttribute(hyperlink.anchor)}"`);
|
|
337
|
+
if (hyperlink.tooltip) attrs.push(`w:tooltip="${escapeXmlAttribute(hyperlink.tooltip)}"`);
|
|
338
|
+
if (hyperlink.target) attrs.push(`w:tgtFrame="${escapeXmlAttribute(hyperlink.target)}"`);
|
|
326
339
|
if (hyperlink.history === true) attrs.push("w:history=\"1\"");
|
|
327
340
|
else if (hyperlink.history === false) attrs.push("w:history=\"0\"");
|
|
328
|
-
if (hyperlink.docLocation) attrs.push(`w:docLocation="${
|
|
341
|
+
if (hyperlink.docLocation) attrs.push(`w:docLocation="${escapeXmlAttribute(hyperlink.docLocation)}"`);
|
|
329
342
|
return attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
330
343
|
}
|
|
331
344
|
/** One `w:hyperlink` child, with the caller deciding how a run is written. */
|
|
@@ -344,20 +357,17 @@ function serializeHyperlink(hyperlink) {
|
|
|
344
357
|
* Serialize bookmark start (w:bookmarkStart)
|
|
345
358
|
*/
|
|
346
359
|
function serializeBookmarkStart(bookmark) {
|
|
347
|
-
|
|
348
|
-
if (bookmark.colFirst !== void 0) attrs.push(`w:colFirst="${bookmark.colFirst}"`);
|
|
349
|
-
if (bookmark.colLast !== void 0) attrs.push(`w:colLast="${bookmark.colLast}"`);
|
|
350
|
-
return `<w:bookmarkStart ${attrs.join(" ")}/>`;
|
|
360
|
+
return `<w:bookmarkStart ${bookmarkRangeAttributes(bookmark).join(" ")}/>`;
|
|
351
361
|
}
|
|
352
362
|
/**
|
|
353
363
|
* Serialize bookmark end (w:bookmarkEnd)
|
|
354
364
|
*/
|
|
355
365
|
function serializeBookmarkEnd(bookmark) {
|
|
356
|
-
return `<w:bookmarkEnd
|
|
366
|
+
return `<w:bookmarkEnd ${markupRangeAttributes(bookmark).join(" ")}/>`;
|
|
357
367
|
}
|
|
358
368
|
/** Serialize a simple field without changing its authored OOXML field form. */
|
|
359
369
|
function serializeSimpleField(field) {
|
|
360
|
-
const attrs = [`w:instr="${
|
|
370
|
+
const attrs = [`w:instr="${escapeXmlAttribute(field.instruction)}"`];
|
|
361
371
|
if (field.fldLock) attrs.push("w:fldLock=\"true\"");
|
|
362
372
|
if (field.dirty) attrs.push("w:dirty=\"true\"");
|
|
363
373
|
const contentXml = field.content.map((item) => item.type === "run" ? serializeRun(item) : serializeHyperlink(item)).join("");
|
|
@@ -379,7 +389,7 @@ function serializeComplexField(field) {
|
|
|
379
389
|
if (field.fieldCode.length > 0) parts.push(...field.fieldCode.map((run) => serializeRun(run)));
|
|
380
390
|
else if (field.instruction.length > 0) {
|
|
381
391
|
const spaceAttr = field.instruction.startsWith(" ") || field.instruction.endsWith(" ") || field.instruction.includes(" ") ? " xml:space=\"preserve\"" : "";
|
|
382
|
-
parts.push(`<w:r>${rPrXml}<w:instrText${spaceAttr}>${
|
|
392
|
+
parts.push(`<w:r>${rPrXml}<w:instrText${spaceAttr}>${escapeXmlText(field.instruction)}</w:instrText></w:r>`);
|
|
383
393
|
}
|
|
384
394
|
parts.push(`<w:r>${rPrXml}<w:fldChar w:fldCharType="separate"/></w:r>`);
|
|
385
395
|
parts.push(...field.fieldResult.map((run) => serializeRun(run)));
|
|
@@ -397,29 +407,29 @@ function serializeComplexField(field) {
|
|
|
397
407
|
function synthesizeInlineSdtPr(props) {
|
|
398
408
|
const prParts = [];
|
|
399
409
|
if (typeof props.id === "number") prParts.push(`<w:id w:val="${props.id}"/>`);
|
|
400
|
-
if (props.alias) prParts.push(`<w:alias w:val="${
|
|
401
|
-
if (props.tag) prParts.push(`<w:tag w:val="${
|
|
410
|
+
if (props.alias) prParts.push(`<w:alias w:val="${escapeXmlAttribute(props.alias)}"/>`);
|
|
411
|
+
if (props.tag) prParts.push(`<w:tag w:val="${escapeXmlAttribute(props.tag)}"/>`);
|
|
402
412
|
if (props.lock && props.lock !== "unlocked") prParts.push(`<w:lock w:val="${props.lock}"/>`);
|
|
403
|
-
if (props.placeholder) prParts.push(`<w:placeholder><w:docPart w:val="${
|
|
413
|
+
if (props.placeholder) prParts.push(`<w:placeholder><w:docPart w:val="${escapeXmlAttribute(props.placeholder)}"/></w:placeholder>`);
|
|
404
414
|
if (props.showingPlaceholder) prParts.push("<w:showingPlcHdr/>");
|
|
405
415
|
switch (props.sdtType) {
|
|
406
416
|
case "plainText":
|
|
407
417
|
prParts.push("<w:text/>");
|
|
408
418
|
break;
|
|
409
419
|
case "date": {
|
|
410
|
-
const fullDateAttr = props.dateValueISO ? ` w:fullDate="${
|
|
411
|
-
const formatChild = props.dateFormat ? `<w:dateFormat w:val="${
|
|
420
|
+
const fullDateAttr = props.dateValueISO ? ` w:fullDate="${escapeXmlAttribute(props.dateValueISO)}"` : "";
|
|
421
|
+
const formatChild = props.dateFormat ? `<w:dateFormat w:val="${escapeXmlAttribute(props.dateFormat)}"/>` : "";
|
|
412
422
|
if (fullDateAttr || formatChild) prParts.push(`<w:date${fullDateAttr}>${formatChild}</w:date>`);
|
|
413
423
|
else prParts.push("<w:date/>");
|
|
414
424
|
break;
|
|
415
425
|
}
|
|
416
426
|
case "dropdown": {
|
|
417
|
-
const items = (props.listItems ?? []).map((i) => `<w:listItem w:displayText="${
|
|
427
|
+
const items = (props.listItems ?? []).map((i) => `<w:listItem w:displayText="${escapeXmlAttribute(i.displayText)}" w:value="${escapeXmlAttribute(i.value)}"/>`).join("");
|
|
418
428
|
prParts.push(`<w:dropDownList>${items}</w:dropDownList>`);
|
|
419
429
|
break;
|
|
420
430
|
}
|
|
421
431
|
case "comboBox": {
|
|
422
|
-
const items = (props.listItems ?? []).map((i) => `<w:listItem w:displayText="${
|
|
432
|
+
const items = (props.listItems ?? []).map((i) => `<w:listItem w:displayText="${escapeXmlAttribute(i.displayText)}" w:value="${escapeXmlAttribute(i.value)}"/>`).join("");
|
|
423
433
|
prParts.push(`<w:comboBox>${items}</w:comboBox>`);
|
|
424
434
|
break;
|
|
425
435
|
}
|
|
@@ -471,7 +481,7 @@ function serializeInlineSdt(sdt) {
|
|
|
471
481
|
})}${props.rawEndPropertiesXml && isSingleWellFormedElement(props.rawEndPropertiesXml, "sdtEndPr") ? props.rawEndPropertiesXml : ""}<w:sdtContent>${contentXml}</w:sdtContent></w:sdt>`;
|
|
472
482
|
}
|
|
473
483
|
function serializeMoveRangeStart(tag, marker) {
|
|
474
|
-
return `<w:${tag} ${
|
|
484
|
+
return `<w:${tag} ${moveBookmarkAttributes(marker).join(" ")}/>`;
|
|
475
485
|
}
|
|
476
486
|
/**
|
|
477
487
|
* Serialize a tracked change wrapper (ins/del/moveFrom/moveTo)
|
|
@@ -560,17 +570,24 @@ function serializeParagraphContent(content, explicitCommentReferenceIds) {
|
|
|
560
570
|
case "simpleField": return serializeSimpleField(content);
|
|
561
571
|
case "complexField": return serializeComplexField(content);
|
|
562
572
|
case "inlineSdt": return serializeInlineSdt(content);
|
|
563
|
-
case "commentRangeStart": return `<w:commentRangeStart
|
|
564
|
-
case "commentRangeEnd":
|
|
573
|
+
case "commentRangeStart": return `<w:commentRangeStart ${markupRangeAttributes(content).join(" ")}/>`;
|
|
574
|
+
case "commentRangeEnd": {
|
|
575
|
+
const end = `<w:commentRangeEnd ${markupRangeAttributes(content).join(" ")}/>`;
|
|
576
|
+
return explicitCommentReferenceIds.has(content.id) ? end : `${end}${serializeCommentReferenceRun(content.id)}`;
|
|
577
|
+
}
|
|
565
578
|
case "commentReference": return serializeCommentReferenceRun(content.id);
|
|
566
579
|
case "insertion": return serializeTrackedChange("ins", content);
|
|
567
580
|
case "deletion": return serializeTrackedChange("del", content);
|
|
568
581
|
case "moveFrom": return serializeTrackedChange("moveFrom", content);
|
|
569
582
|
case "moveTo": return serializeTrackedChange("moveTo", content);
|
|
570
583
|
case "moveFromRangeStart": return serializeMoveRangeStart("moveFromRangeStart", content);
|
|
571
|
-
case "moveFromRangeEnd": return `<w:moveFromRangeEnd
|
|
584
|
+
case "moveFromRangeEnd": return `<w:moveFromRangeEnd ${markupRangeAttributes(content).join(" ")}/>`;
|
|
572
585
|
case "moveToRangeStart": return serializeMoveRangeStart("moveToRangeStart", content);
|
|
573
|
-
case "moveToRangeEnd": return `<w:moveToRangeEnd
|
|
586
|
+
case "moveToRangeEnd": return `<w:moveToRangeEnd ${markupRangeAttributes(content).join(" ")}/>`;
|
|
587
|
+
case "bidiWrapper": {
|
|
588
|
+
const tag = content.control === "override" ? "bdo" : "dir";
|
|
589
|
+
return `<w:${tag}${content.direction === void 0 ? "" : ` w:val="${escapeXmlAttribute(content.direction)}"`}>${content.content.map((child) => serializeParagraphContent(child, explicitCommentReferenceIds)).join("")}</w:${tag}>`;
|
|
590
|
+
}
|
|
574
591
|
case "mathEquation": return content.ommlXml || "";
|
|
575
592
|
default: return "";
|
|
576
593
|
}
|
|
@@ -584,8 +601,8 @@ function serializeParagraphContent(content, explicitCommentReferenceIds) {
|
|
|
584
601
|
function serializeParagraph(paragraph) {
|
|
585
602
|
const parts = [];
|
|
586
603
|
const attrs = [];
|
|
587
|
-
if (paragraph.paraId) attrs.push(`w14:paraId="${
|
|
588
|
-
if (paragraph.textId) attrs.push(`w14:textId="${
|
|
604
|
+
if (paragraph.paraId) attrs.push(`w14:paraId="${escapeXmlAttribute(paragraph.paraId)}"`);
|
|
605
|
+
if (paragraph.textId) attrs.push(`w14:textId="${escapeXmlAttribute(paragraph.textId)}"`);
|
|
589
606
|
if (paragraph.reviewCarrier) attrs.push(`folio:reviewCarrier="${paragraph.reviewCarrier}"`);
|
|
590
607
|
const attrsStr = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
591
608
|
parts.push(serializeParagraphFormattingWithOptions(paragraph.formatting, {
|
|
@@ -657,28 +674,6 @@ function hasParagraphFormatting(paragraph) {
|
|
|
657
674
|
return paragraph.formatting !== void 0 && Object.keys(paragraph.formatting).length > 0;
|
|
658
675
|
}
|
|
659
676
|
/**
|
|
660
|
-
* Get plain text from a paragraph (for comparison/debugging)
|
|
661
|
-
*/
|
|
662
|
-
function getParagraphPlainText(paragraph) {
|
|
663
|
-
const texts = [];
|
|
664
|
-
for (const content of paragraph.content) if (content.type === "run") {
|
|
665
|
-
for (const item of content.content) if (item.type === "text") texts.push(item.text);
|
|
666
|
-
else if (item.type === "tab") texts.push(" ");
|
|
667
|
-
else if (item.type === "break") texts.push("\n");
|
|
668
|
-
} else if (content.type === "hyperlink") {
|
|
669
|
-
for (const child of content.children) if (child.type === "run") {
|
|
670
|
-
for (const item of child.content) if (item.type === "text") texts.push(item.text);
|
|
671
|
-
}
|
|
672
|
-
} else if (content.type === "simpleField" || content.type === "inlineSdt" || content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo") {
|
|
673
|
-
for (const item of content.content) if (item.type === "run") {
|
|
674
|
-
for (const subItem of item.content) if (subItem.type === "text") texts.push(subItem.text);
|
|
675
|
-
}
|
|
676
|
-
} else if (content.type === "complexField") {
|
|
677
|
-
for (const run of content.fieldResult) for (const item of run.content) if (item.type === "text") texts.push(item.text);
|
|
678
|
-
}
|
|
679
|
-
return texts.join("");
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
677
|
* Create an empty paragraph
|
|
683
678
|
*/
|
|
684
679
|
function createEmptyParagraph(formatting) {
|
|
@@ -718,4 +713,4 @@ function getListLevel(paragraph) {
|
|
|
718
713
|
return paragraph.formatting?.numPr?.ilvl ?? -1;
|
|
719
714
|
}
|
|
720
715
|
//#endregion
|
|
721
|
-
export { createEmptyParagraph, createTextParagraph, getListLevel,
|
|
716
|
+
export { createEmptyParagraph, createTextParagraph, getListLevel, hasParagraphContent, hasParagraphFormatting, isListParagraph, serializeParagraph, serializeParagraphFormatting, serializeParagraphs };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { toTransitionalNamespaceUri } from "../transitionalSpelling.js";
|
|
2
|
-
import { escapeXml } from "./xmlUtils.js";
|
|
3
2
|
import { TaggedError } from "better-result";
|
|
3
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
4
4
|
import { OOXML_NS } from "@stll/docx-utils";
|
|
5
5
|
//#region src/docx/serializer/partNamespaces.ts
|
|
6
6
|
/**
|
|
@@ -319,7 +319,7 @@ const serializePartElement = ({ partPath, rootName, rootAttributes, baselinePref
|
|
|
319
319
|
...[...NAMESPACE_TABLE.keys()].filter((prefix) => extra.has(prefix)),
|
|
320
320
|
...[...extra].filter((prefix) => !NAMESPACE_TABLE.has(prefix)).sort()
|
|
321
321
|
];
|
|
322
|
-
const attributes = orderedPrefixes.map((prefix) => `xmlns:${prefix}="${
|
|
322
|
+
const attributes = orderedPrefixes.map((prefix) => `xmlns:${prefix}="${escapeXmlAttribute(bindings.get(prefix))}"`);
|
|
323
323
|
const ignorable = orderedPrefixes.filter((prefix) => NAMESPACE_TABLE.get(prefix)?.ignorable === true);
|
|
324
324
|
if (ignorable.length > 0) attributes.push(`mc:Ignorable="${ignorable.join(" ")}"`);
|
|
325
325
|
return `${openingTag} ${attributes.join(" ")}>${body}</${rootName}>`;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { isValidHexColor } from "../../utils/colorResolver.js";
|
|
2
2
|
import { THEME_COLOR_TO_DRAWING_SCHEME } from "../drawingUtils.js";
|
|
3
3
|
import { serializeGraphicFrameLocks } from "../graphicFrameLocks.js";
|
|
4
|
+
import { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE } from "../imageParser.js";
|
|
4
5
|
import { canReplayEditableImageRawXml } from "../imageRawXml.js";
|
|
5
|
-
import {
|
|
6
|
+
import { serializeNonVisualDrawingNames } from "../nonVisualDrawingProps.js";
|
|
6
7
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
7
8
|
import { serializeTable } from "./tableSerializer.js";
|
|
8
9
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
9
10
|
import { getSingularRunPropertyChange, serializeTrackedChangeAttributes } from "./trackedChangeAttributes.js";
|
|
10
|
-
import {
|
|
11
|
+
import { intAttr } from "./xmlUtils.js";
|
|
11
12
|
import { panic } from "better-result";
|
|
13
|
+
import { escapeXmlAttribute, escapeXmlText, requiresXmlSpacePreserve } from "@stll/docx-core";
|
|
12
14
|
//#region src/docx/serializer/runSerializer.ts
|
|
13
15
|
/**
|
|
14
16
|
* Run Serializer - Serialize runs to OOXML XML
|
|
@@ -59,7 +61,7 @@ function serializeRunProperties(formatting, propertyChanges) {
|
|
|
59
61
|
* Serialize text content (w:t)
|
|
60
62
|
*/
|
|
61
63
|
function serializeTextContent(content) {
|
|
62
|
-
return `<w:t${
|
|
64
|
+
return `<w:t${requiresXmlSpacePreserve(content.text) ? " xml:space=\"preserve\"" : ""}>${escapeXmlText(content.text)}</w:t>`;
|
|
63
65
|
}
|
|
64
66
|
/**
|
|
65
67
|
* Serialize tab content (w:tab)
|
|
@@ -67,9 +69,9 @@ function serializeTextContent(content) {
|
|
|
67
69
|
function serializeTabContent(content) {
|
|
68
70
|
if (!content.positional) return "<w:tab/>";
|
|
69
71
|
return `<w:ptab${[
|
|
70
|
-
content.positional.relativeTo ? ` w:relativeTo="${
|
|
71
|
-
content.positional.alignment ? ` w:alignment="${
|
|
72
|
-
content.positional.leader ? ` w:leader="${
|
|
72
|
+
content.positional.relativeTo ? ` w:relativeTo="${escapeXmlAttribute(content.positional.relativeTo)}"` : "",
|
|
73
|
+
content.positional.alignment ? ` w:alignment="${escapeXmlAttribute(content.positional.alignment)}"` : "",
|
|
74
|
+
content.positional.leader ? ` w:leader="${escapeXmlAttribute(content.positional.leader)}"` : ""
|
|
73
75
|
].join("")}/>`;
|
|
74
76
|
}
|
|
75
77
|
/**
|
|
@@ -88,7 +90,7 @@ function serializeBreakContent(content) {
|
|
|
88
90
|
* Serialize symbol content (w:sym)
|
|
89
91
|
*/
|
|
90
92
|
function serializeSymbolContent(content) {
|
|
91
|
-
return `<w:sym w:font="${
|
|
93
|
+
return `<w:sym${content.font === "" ? "" : ` w:font="${escapeXmlAttribute(content.font)}"`}${content.char === "" ? "" : ` w:char="${escapeXmlAttribute(content.char)}"`}/>`;
|
|
92
94
|
}
|
|
93
95
|
/**
|
|
94
96
|
* Serialize footnote/endnote reference
|
|
@@ -110,7 +112,7 @@ function serializeFieldChar(content) {
|
|
|
110
112
|
* Serialize field instruction text (w:instrText)
|
|
111
113
|
*/
|
|
112
114
|
function serializeInstrText(content) {
|
|
113
|
-
return `<w:instrText${content.text.startsWith(" ") || content.text.endsWith(" ") || content.text.includes(" ") ? " xml:space=\"preserve\"" : ""}>${
|
|
115
|
+
return `<w:instrText${content.text.startsWith(" ") || content.text.endsWith(" ") || content.text.includes(" ") ? " xml:space=\"preserve\"" : ""}>${escapeXmlText(content.text)}</w:instrText>`;
|
|
114
116
|
}
|
|
115
117
|
/**
|
|
116
118
|
* Serialize soft hyphen (w:softHyphen)
|
|
@@ -127,11 +129,11 @@ function serializeNoBreakHyphen(_content) {
|
|
|
127
129
|
/** Serialize a color value to DrawingML a:srgbClr or a:schemeClr */
|
|
128
130
|
function serializeDrawingColor(color) {
|
|
129
131
|
if (!color) return "";
|
|
130
|
-
if (color.rgb && isValidHexColor(color.rgb)) return `<a:srgbClr val="${
|
|
132
|
+
if (color.rgb && isValidHexColor(color.rgb)) return `<a:srgbClr val="${escapeXmlAttribute(color.rgb.replace("#", ""))}"/>`;
|
|
131
133
|
if (color.themeColor) {
|
|
132
134
|
let clr = `<a:schemeClr val="${THEME_COLOR_TO_DRAWING_SCHEME[color.themeColor]}"`;
|
|
133
|
-
if (color.themeTint) clr += `><a:tint val="${
|
|
134
|
-
else if (color.themeShade) clr += `><a:shade val="${
|
|
135
|
+
if (color.themeTint) clr += `><a:tint val="${escapeXmlAttribute(color.themeTint)}"/></a:schemeClr>`;
|
|
136
|
+
else if (color.themeShade) clr += `><a:shade val="${escapeXmlAttribute(color.themeShade)}"/></a:schemeClr>`;
|
|
135
137
|
else clr += `/>`;
|
|
136
138
|
return clr;
|
|
137
139
|
}
|
|
@@ -206,11 +208,17 @@ function serializeWrap(wrap) {
|
|
|
206
208
|
case "inline": return "<wp:wrapNone/>";
|
|
207
209
|
}
|
|
208
210
|
}
|
|
209
|
-
/**
|
|
210
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Build the common a:graphic > pic:pic element for images.
|
|
213
|
+
*
|
|
214
|
+
* Takes the relationship id as a separate argument so the caller has to have
|
|
215
|
+
* one. There is no default: a picture written against an invented id binds to
|
|
216
|
+
* whichever relationship the part happens to hold under that name.
|
|
217
|
+
*/
|
|
218
|
+
function serializePicGraphic(image, imageRId, sharedId) {
|
|
211
219
|
const cx = image.size.width;
|
|
212
220
|
const cy = image.size.height;
|
|
213
|
-
const rId =
|
|
221
|
+
const rId = escapeXmlAttribute(imageRId);
|
|
214
222
|
const id = sharedId;
|
|
215
223
|
const name = image.filename || `image${id}`;
|
|
216
224
|
let xfrmAttrs = "";
|
|
@@ -230,7 +238,7 @@ function serializePicGraphic(image, sharedId) {
|
|
|
230
238
|
"<a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">",
|
|
231
239
|
"<pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">",
|
|
232
240
|
"<pic:nvPicPr>",
|
|
233
|
-
`<pic:cNvPr id="${id}" name="${
|
|
241
|
+
`<pic:cNvPr id="${id}" name="${escapeXmlAttribute(name)}"${image.alt ? ` descr="${escapeXmlAttribute(image.alt)}"` : ""}/>`,
|
|
234
242
|
"<pic:cNvPicPr/>",
|
|
235
243
|
"</pic:nvPicPr>",
|
|
236
244
|
"<pic:blipFill>",
|
|
@@ -264,6 +272,19 @@ function serializeWrapDistanceAttrs(wrap) {
|
|
|
264
272
|
return attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
265
273
|
}
|
|
266
274
|
/**
|
|
275
|
+
* Serialize the `wp:docPr` extension list.
|
|
276
|
+
*
|
|
277
|
+
* The decorative flag is the one extension folio models; every other `a:ext`
|
|
278
|
+
* the source carried is replayed as it was captured, in its original order,
|
|
279
|
+
* because an extension dropped on save is a fact the document had and lost.
|
|
280
|
+
* The decorative extension goes first: it is the one folio may have added.
|
|
281
|
+
*/
|
|
282
|
+
function serializeDocPrExtensions(image) {
|
|
283
|
+
const preserved = image.docPrExtensions ?? [];
|
|
284
|
+
const entries = `${image.decorative === void 0 ? "" : `<a:ext uri="${DECORATIVE_EXTENSION_URI}"><adec:decorative xmlns:adec="${DECORATIVE_NAMESPACE}" val="${image.decorative ? "1" : "0"}"/></a:ext>`}${preserved.join("")}`;
|
|
285
|
+
return entries ? `<a:extLst>${entries}</a:extLst>` : "";
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
267
288
|
* Serialize drawing/image content (w:drawing) to full DrawingML XML
|
|
268
289
|
*/
|
|
269
290
|
function serializeDrawingContent(content) {
|
|
@@ -278,22 +299,23 @@ function serializeDrawingContent(content) {
|
|
|
278
299
|
const effB = image.padding?.bottom ?? 0;
|
|
279
300
|
const effectExtentEl = `<wp:effectExtent l="${intAttr(effL)}" t="${intAttr(effT)}" r="${intAttr(effR)}" b="${intAttr(effB)}"/>`;
|
|
280
301
|
const docPrId = getUniqueId(image.id);
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
const
|
|
302
|
+
const docPrNames = serializeNonVisualDrawingNames({
|
|
303
|
+
...image.docPrName !== void 0 ? { name: image.docPrName } : {},
|
|
304
|
+
...image.alt !== void 0 ? { alt: image.alt } : {},
|
|
305
|
+
...image.title !== void 0 ? { title: image.title } : {}
|
|
306
|
+
});
|
|
307
|
+
const hlinkClick = image.hlinkRId ? `<a:hlinkClick r:id="${escapeXmlAttribute(image.hlinkRId)}"/>` : "";
|
|
308
|
+
const docPrAttrs = `id="${docPrId}"${docPrNames}${image.hidden === void 0 ? "" : ` hidden="${image.hidden ? "1" : "0"}"`}`;
|
|
309
|
+
const docPrChildren = `${hlinkClick}${serializeDocPrExtensions(image)}`;
|
|
310
|
+
const docPr = docPrChildren ? `<wp:docPr ${docPrAttrs}>${docPrChildren}</wp:docPr>` : `<wp:docPr ${docPrAttrs}/>`;
|
|
289
311
|
const graphicFramePr = serializeGraphicFrameLocks(image.frameLocks);
|
|
290
|
-
const graphic = serializePicGraphic(image, docPrId);
|
|
312
|
+
const graphic = image.rId === void 0 ? "" : serializePicGraphic(image, image.rId, docPrId);
|
|
291
313
|
if (!isFloating) return [
|
|
292
314
|
"<w:drawing>",
|
|
293
315
|
`<wp:inline${wrapDistanceAttrs}>`,
|
|
294
316
|
`<wp:extent cx="${intAttr(cx)}" cy="${intAttr(cy)}"/>`,
|
|
295
317
|
effectExtentEl,
|
|
296
|
-
|
|
318
|
+
docPr,
|
|
297
319
|
graphicFramePr,
|
|
298
320
|
graphic,
|
|
299
321
|
"</wp:inline>",
|
|
@@ -310,7 +332,7 @@ function serializeDrawingContent(content) {
|
|
|
310
332
|
`<wp:extent cx="${intAttr(cx)}" cy="${intAttr(cy)}"/>`,
|
|
311
333
|
effectExtentEl,
|
|
312
334
|
wrap,
|
|
313
|
-
|
|
335
|
+
docPr,
|
|
314
336
|
graphicFramePr,
|
|
315
337
|
graphic,
|
|
316
338
|
"</wp:anchor>",
|
|
@@ -333,7 +355,7 @@ const serializeTextBodyAnchor = (anchor) => {
|
|
|
333
355
|
};
|
|
334
356
|
function serializeGeometryAdjustments(shape) {
|
|
335
357
|
if (!shape.geometryAdjustments || shape.geometryAdjustments.length === 0) return "<a:avLst/>";
|
|
336
|
-
return `<a:avLst>${shape.geometryAdjustments.map(({ name, formula }) => `<a:gd name="${
|
|
358
|
+
return `<a:avLst>${shape.geometryAdjustments.map(({ name, formula }) => `<a:gd name="${escapeXmlAttribute(name)}" fmla="${escapeXmlAttribute(formula)}"/>`).join("")}</a:avLst>`;
|
|
337
359
|
}
|
|
338
360
|
/**
|
|
339
361
|
* Serialize shape content to full DrawingML XML (wps:wsp inside w:drawing)
|
|
@@ -346,7 +368,11 @@ function serializeShapeContent(content) {
|
|
|
346
368
|
const isFloating = shape.wrap && shape.wrap.type !== "inline";
|
|
347
369
|
const wrapDistances = serializeWrapDistanceAttrs(shape.wrap);
|
|
348
370
|
const docPrId = getUniqueId(shape.id);
|
|
349
|
-
const
|
|
371
|
+
const docPrNames = serializeNonVisualDrawingNames({
|
|
372
|
+
...shape.name !== void 0 ? { name: shape.name } : {},
|
|
373
|
+
...shape.alt !== void 0 ? { alt: shape.alt } : {},
|
|
374
|
+
...shape.title !== void 0 ? { title: shape.title } : {}
|
|
375
|
+
});
|
|
350
376
|
let xfrmAttrs = "";
|
|
351
377
|
if (shape.transform?.rotation) xfrmAttrs += ` rot="${Math.round(shape.transform.rotation * 6e4)}"`;
|
|
352
378
|
if (shape.transform?.flipH) xfrmAttrs += " flipH=\"1\"";
|
|
@@ -380,7 +406,7 @@ function serializeShapeContent(content) {
|
|
|
380
406
|
if (tb.autoFit === "shape") autoFitXml = "<a:spAutoFit/>";
|
|
381
407
|
else if (tb.autoFit === "normal") autoFitXml = "<a:normAutofit/>";
|
|
382
408
|
else if (tb.autoFit === "none") autoFitXml = "<a:noAutofit/>";
|
|
383
|
-
const bodyPrChildren = `${tb.wordArt?.preset ? `<a:prstTxWarp prst="${
|
|
409
|
+
const bodyPrChildren = `${tb.wordArt?.preset ? `<a:prstTxWarp prst="${escapeXmlAttribute(tb.wordArt.preset)}">${tb.wordArt.adjustments && tb.wordArt.adjustments.length > 0 ? `<a:avLst>${tb.wordArt.adjustments.map(({ name, formula }) => `<a:gd name="${escapeXmlAttribute(name)}" fmla="${escapeXmlAttribute(formula)}"/>`).join("")}</a:avLst>` : "<a:avLst/>"}</a:prstTxWarp>` : ""}${autoFitXml}`;
|
|
384
410
|
const bodyPrXml = bodyPrChildren ? `<wps:bodyPr ${bpAttrs.join(" ")}>${bodyPrChildren}</wps:bodyPr>` : `<wps:bodyPr ${bpAttrs.join(" ")}/>`;
|
|
385
411
|
if (isTextBox) textBody = [
|
|
386
412
|
"<wps:txbx><w:txbxContent>",
|
|
@@ -408,7 +434,7 @@ function serializeShapeContent(content) {
|
|
|
408
434
|
`<wp:inline${wrapDistances}>`,
|
|
409
435
|
`<wp:extent cx="${intAttr(cx)}" cy="${intAttr(cy)}"/>`,
|
|
410
436
|
"<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>",
|
|
411
|
-
`<wp:docPr id="${docPrId}"
|
|
437
|
+
`<wp:docPr id="${docPrId}"${docPrNames}/>`,
|
|
412
438
|
"<wp:cNvGraphicFramePr/>",
|
|
413
439
|
graphic,
|
|
414
440
|
"</wp:inline>",
|
|
@@ -426,7 +452,7 @@ function serializeShapeContent(content) {
|
|
|
426
452
|
`<wp:extent cx="${intAttr(cx)}" cy="${intAttr(cy)}"/>`,
|
|
427
453
|
"<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>",
|
|
428
454
|
wrap,
|
|
429
|
-
`<wp:docPr id="${docPrId}"
|
|
455
|
+
`<wp:docPr id="${docPrId}"${docPrNames}/>`,
|
|
430
456
|
"<wp:cNvGraphicFramePr/>",
|
|
431
457
|
graphic,
|
|
432
458
|
"</wp:anchor>",
|
|
@@ -2,10 +2,11 @@ import { getUnserializedSectionPropertyChildNames } from "../sectionParser.js";
|
|
|
2
2
|
import { serializeSectionReferenceHistory } from "../sectionReferenceHistory.js";
|
|
3
3
|
import { serializeBorder } from "./borderSerializer.js";
|
|
4
4
|
import { serializeTrackedChangeAttributes } from "./trackedChangeAttributes.js";
|
|
5
|
-
import {
|
|
5
|
+
import { intAttr } from "./xmlUtils.js";
|
|
6
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
6
7
|
//#region src/docx/serializer/sectionPropertiesSerializer.ts
|
|
7
|
-
const serializeHeaderReference = (ref) => `<w:headerReference w:type="${ref.type}" r:id="${
|
|
8
|
-
const serializeFooterReference = (ref) => `<w:footerReference w:type="${ref.type}" r:id="${
|
|
8
|
+
const serializeHeaderReference = (ref) => `<w:headerReference w:type="${ref.type}" r:id="${escapeXmlAttribute(ref.rId)}"/>`;
|
|
9
|
+
const serializeFooterReference = (ref) => `<w:footerReference w:type="${ref.type}" r:id="${escapeXmlAttribute(ref.rId)}"/>`;
|
|
9
10
|
function serializeFootnoteProperties(props) {
|
|
10
11
|
if (!props) return "";
|
|
11
12
|
const parts = [];
|
|
@@ -84,7 +85,7 @@ function serializePageNumbering(props) {
|
|
|
84
85
|
if (pageNumbering.format) attrs.push(`w:fmt="${pageNumbering.format}"`);
|
|
85
86
|
if (pageNumbering.start !== void 0) attrs.push(`w:start="${intAttr(pageNumbering.start)}"`);
|
|
86
87
|
if (pageNumbering.chapterStyle !== void 0) attrs.push(`w:chapStyle="${intAttr(pageNumbering.chapterStyle)}"`);
|
|
87
|
-
if (pageNumbering.chapterSeparator) attrs.push(`w:chapSep="${
|
|
88
|
+
if (pageNumbering.chapterSeparator) attrs.push(`w:chapSep="${escapeXmlAttribute(pageNumbering.chapterSeparator)}"`);
|
|
88
89
|
return attrs.length > 0 ? `<w:pgNumType ${attrs.join(" ")}/>` : "";
|
|
89
90
|
}
|
|
90
91
|
function serializePageBorders(props) {
|
|
@@ -114,10 +115,10 @@ function serializeBackground(props) {
|
|
|
114
115
|
const attrs = [];
|
|
115
116
|
const { background } = props;
|
|
116
117
|
if (background.color?.auto) attrs.push("w:color=\"auto\"");
|
|
117
|
-
else if (background.color?.rgb) attrs.push(`w:color="${
|
|
118
|
-
if (background.themeColor ?? background.color?.themeColor) attrs.push(`w:themeColor="${
|
|
119
|
-
if (background.themeTint ?? background.color?.themeTint) attrs.push(`w:themeTint="${
|
|
120
|
-
if (background.themeShade ?? background.color?.themeShade) attrs.push(`w:themeShade="${
|
|
118
|
+
else if (background.color?.rgb) attrs.push(`w:color="${escapeXmlAttribute(background.color.rgb)}"`);
|
|
119
|
+
if (background.themeColor ?? background.color?.themeColor) attrs.push(`w:themeColor="${escapeXmlAttribute(background.themeColor ?? background.color?.themeColor ?? "")}"`);
|
|
120
|
+
if (background.themeTint ?? background.color?.themeTint) attrs.push(`w:themeTint="${escapeXmlAttribute(background.themeTint ?? background.color?.themeTint ?? "")}"`);
|
|
121
|
+
if (background.themeShade ?? background.color?.themeShade) attrs.push(`w:themeShade="${escapeXmlAttribute(background.themeShade ?? background.color?.themeShade ?? "")}"`);
|
|
121
122
|
return attrs.length > 0 ? `<w:background ${attrs.join(" ")}/>` : "";
|
|
122
123
|
}
|
|
123
124
|
function serializeDocGrid(props) {
|
|
@@ -127,7 +128,7 @@ function serializeDocGrid(props) {
|
|
|
127
128
|
if (dg.type) attrs.push(`w:type="${dg.type}"`);
|
|
128
129
|
if (dg.linePitch !== void 0) attrs.push(`w:linePitch="${intAttr(dg.linePitch)}"`);
|
|
129
130
|
if (dg.charSpace !== void 0) attrs.push(`w:charSpace="${intAttr(dg.charSpace)}"`);
|
|
130
|
-
return attrs.length > 0 ? `<w:docGrid ${attrs.join(" ")}/>` : "";
|
|
131
|
+
return attrs.length > 0 ? `<w:docGrid ${attrs.join(" ")}/>` : "<w:docGrid/>";
|
|
131
132
|
}
|
|
132
133
|
function serializeOnOffElement(value, name) {
|
|
133
134
|
if (value === void 0) return "";
|
|
@@ -173,7 +174,7 @@ function serializeSectionProperties(props) {
|
|
|
173
174
|
serializeOnOffElement(props.noEndnote, "noEndnote"),
|
|
174
175
|
serializeOnOffElement(props.rtlGutter, "rtlGutter")
|
|
175
176
|
]) if (xml) parts.push(xml);
|
|
176
|
-
if (props.printerSettingsRelationshipId) parts.push(`<w:printerSettings r:id="${
|
|
177
|
+
if (props.printerSettingsRelationshipId) parts.push(`<w:printerSettings r:id="${escapeXmlAttribute(props.printerSettingsRelationshipId)}"/>`);
|
|
177
178
|
for (const change of props.propertyChanges ?? []) parts.push(serializeSectionPropertyChange(change));
|
|
178
179
|
const unserializedChildNames = getUnserializedSectionPropertyChildNames(props);
|
|
179
180
|
if (unserializedChildNames && unserializedChildNames.length > 0) return "";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { serializePartElement } from "./partNamespaces.js";
|
|
2
|
-
import {
|
|
2
|
+
import { intAttr } from "./xmlUtils.js";
|
|
3
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
3
4
|
//#region src/docx/serializer/settingsSerializer.ts
|
|
4
5
|
const serializeSettingsXml = (settings) => {
|
|
5
6
|
const parts = [`<w:defaultTabStop w:val="${intAttr(settings.defaultTabStop)}"/>`];
|
|
@@ -7,8 +8,8 @@ const serializeSettingsXml = (settings) => {
|
|
|
7
8
|
if (settings.updateFields) parts.push("<w:updateFields w:val=\"true\"/>");
|
|
8
9
|
if (settings.themeFontLang) {
|
|
9
10
|
const attrs = [];
|
|
10
|
-
if (settings.themeFontLang.eastAsia) attrs.push(`w:eastAsia="${
|
|
11
|
-
if (settings.themeFontLang.bidi) attrs.push(`w:bidi="${
|
|
11
|
+
if (settings.themeFontLang.eastAsia) attrs.push(`w:eastAsia="${escapeXmlAttribute(settings.themeFontLang.eastAsia)}"`);
|
|
12
|
+
if (settings.themeFontLang.bidi) attrs.push(`w:bidi="${escapeXmlAttribute(settings.themeFontLang.bidi)}"`);
|
|
12
13
|
if (attrs.length > 0) parts.push(`<w:themeFontLang ${attrs.join(" ")}/>`);
|
|
13
14
|
}
|
|
14
15
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
@@ -2,7 +2,7 @@ import { serializeParagraphFormatting } from "./paragraphSerializer.js";
|
|
|
2
2
|
import { serializePartElement } from "./partNamespaces.js";
|
|
3
3
|
import { serializeTableCellFormatting, serializeTableFormatting, serializeTableRowFormatting } from "./tableSerializer.js";
|
|
4
4
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
5
|
-
import {
|
|
5
|
+
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
6
6
|
//#region src/docx/serializer/stylesSerializer.ts
|
|
7
7
|
const serializeStylesXml = (definitions) => {
|
|
8
8
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
@@ -28,12 +28,12 @@ const serializeLatentStyles = (definitions) => {
|
|
|
28
28
|
return `<w:latentStyles${attrs.length > 0 ? ` ${attrs.join(" ")}` : ""}/>`;
|
|
29
29
|
};
|
|
30
30
|
const serializeStyle = (style) => {
|
|
31
|
-
const attrs = [`w:type="${style.type}"`, `w:styleId="${
|
|
31
|
+
const attrs = [`w:type="${style.type}"`, `w:styleId="${escapeXmlAttribute(style.styleId)}"`];
|
|
32
32
|
if (style.default) attrs.push("w:default=\"1\"");
|
|
33
|
-
const parts = [`<w:name w:val="${
|
|
34
|
-
if (style.basedOn) parts.push(`<w:basedOn w:val="${
|
|
35
|
-
if (style.next) parts.push(`<w:next w:val="${
|
|
36
|
-
if (style.link) parts.push(`<w:link w:val="${
|
|
33
|
+
const parts = [`<w:name w:val="${escapeXmlAttribute(style.name ?? style.styleId)}"/>`];
|
|
34
|
+
if (style.basedOn) parts.push(`<w:basedOn w:val="${escapeXmlAttribute(style.basedOn)}"/>`);
|
|
35
|
+
if (style.next) parts.push(`<w:next w:val="${escapeXmlAttribute(style.next)}"/>`);
|
|
36
|
+
if (style.link) parts.push(`<w:link w:val="${escapeXmlAttribute(style.link)}"/>`);
|
|
37
37
|
if (style.uiPriority !== void 0) parts.push(`<w:uiPriority w:val="${style.uiPriority}"/>`);
|
|
38
38
|
pushBooleanElement(parts, "hidden", style.hidden);
|
|
39
39
|
pushBooleanElement(parts, "semiHidden", style.semiHidden);
|