@stll/folio-core 0.33.0 → 0.33.2
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/apply.d.ts +15 -0
- package/dist/ai-edits/apply.js +135 -24
- package/dist/ai-edits/headless.d.ts +47 -3
- package/dist/ai-edits/headless.js +53 -3
- package/dist/ai-edits/index.d.ts +1 -1
- package/dist/ai-edits/snapshot.d.ts +19 -1
- package/dist/ai-edits/snapshot.js +25 -3
- package/dist/ai-edits/table-geometry.d.ts +56 -0
- package/dist/ai-edits/table-geometry.js +217 -0
- package/dist/ai-edits/table-row-column-mutations.d.ts +34 -16
- package/dist/ai-edits/table-row-column-mutations.js +12 -4
- package/dist/ai-edits/table-template.d.ts +60 -0
- package/dist/ai-edits/table-template.js +176 -0
- package/dist/ai-edits/types.d.ts +7 -0
- package/dist/compare/__fixtures__/body-sequence.d.ts +86 -4
- package/dist/compare/__fixtures__/body-sequence.js +169 -12
- package/dist/compare/compare.d.ts +15 -8
- package/dist/compare/compare.js +138 -34
- package/dist/compare/plan.d.ts +31 -1
- package/dist/compare/plan.js +277 -28
- package/dist/compare/reproducible-package.d.ts +7 -3
- package/dist/compare/reproducible-package.js +20 -3
- package/dist/compare/types.d.ts +20 -3
- package/dist/compare/types.js +13 -1
- package/dist/compare/verification.d.ts +49 -2
- package/dist/compare/verification.js +115 -1
- package/dist/compat/eigenpal.d.ts +5 -5
- package/dist/compat/eigenpal.js +3 -3
- package/dist/document-operations.d.ts +10 -1
- package/dist/document-operations.js +3 -2
- package/dist/docx/appVersionNormalization.d.ts +49 -0
- package/dist/docx/appVersionNormalization.js +74 -0
- package/dist/docx/blockContentParser.js +3 -2
- package/dist/docx/drawingUtils.js +4 -3
- package/dist/docx/hyperlinkParser.d.ts +9 -1
- package/dist/docx/hyperlinkParser.js +19 -13
- package/dist/docx/paraIdRangeNormalization.d.ts +40 -0
- package/dist/docx/paraIdRangeNormalization.js +64 -0
- package/dist/docx/paragraphParser.js +82 -6
- package/dist/docx/revisionIdNormalization.d.ts +15 -1
- package/dist/docx/revisionIdNormalization.js +22 -4
- package/dist/docx/rezip.d.ts +13 -1
- package/dist/docx/rezip.js +80 -21
- package/dist/docx/runParser.js +9 -8
- package/dist/docx/sdtProperties.js +4 -3
- package/dist/docx/selectiveSave.js +7 -6
- package/dist/docx/serializer/commentSerializer.d.ts +1 -1
- package/dist/docx/serializer/commentSerializer.js +43 -19
- package/dist/docx/serializer/documentSerializer.d.ts +3 -1
- package/dist/docx/serializer/documentSerializer.js +42 -78
- package/dist/docx/serializer/fontTableSerializer.js +8 -5
- package/dist/docx/serializer/headerFooterSerializer.d.ts +4 -1
- package/dist/docx/serializer/headerFooterSerializer.js +34 -29
- package/dist/docx/serializer/noteSerializer.js +34 -30
- package/dist/docx/serializer/numberingSerializer.js +8 -4
- package/dist/docx/serializer/paragraphSerializer.js +45 -21
- package/dist/docx/serializer/partNamespaces.d.ts +78 -0
- package/dist/docx/serializer/partNamespaces.js +324 -0
- package/dist/docx/serializer/runSerializer.js +1 -1
- package/dist/docx/serializer/settingsSerializer.js +8 -2
- package/dist/docx/serializer/stylesSerializer.js +8 -5
- package/dist/docx/serializer/tableSerializer.js +107 -27
- package/dist/docx/serializer/themeSerializer.js +10 -2
- package/dist/docx/server/build.d.ts +1 -1
- package/dist/docx/strictValueEncodings.gen.d.ts +15 -0
- package/dist/docx/strictValueEncodings.gen.js +275 -0
- package/dist/docx/tableParser.d.ts +0 -6
- package/dist/docx/tableParser.js +52 -7
- package/dist/docx/transitionalSpelling.d.ts +23 -0
- package/dist/docx/transitionalSpelling.js +36 -0
- package/dist/docx/universalMeasure.d.ts +20 -0
- package/dist/docx/universalMeasure.js +32 -0
- package/dist/docx/verbatimCapture.d.ts +20 -0
- package/dist/docx/verbatimCapture.js +131 -0
- package/dist/docx/vmlImageParser.js +4 -3
- package/dist/docx/watermarkParser.js +4 -3
- package/dist/docx/xmlParser.d.ts +23 -2
- package/dist/docx/xmlParser.js +43 -11
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/prosemirror/commands/comments.js +8 -2
- package/dist/prosemirror/containerFinalParagraph.d.ts +47 -0
- package/dist/prosemirror/containerFinalParagraph.js +92 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +15 -4
- package/dist/prosemirror/conversion/toProseDoc.js +12 -3
- package/dist/prosemirror/extensions/nodes/TableExtension.js +5 -0
- package/dist/prosemirror/schema/marks.d.ts +1 -1
- package/dist/prosemirror/schema/nodes.d.ts +22 -0
- package/dist/server.d.ts +1 -1
- package/dist/types/block-id.d.ts +12 -1
- package/dist/types/block-id.js +17 -1
- package/dist/utils/canonicalJson.d.ts +14 -0
- package/dist/utils/canonicalJson.js +19 -0
- package/dist/utils/formatToStyle.d.ts +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { deterministicHexId } from "../../utils/hexId.js";
|
|
2
2
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
|
+
import { serializePartElement } from "./partNamespaces.js";
|
|
3
4
|
import { serializeTextFormatting } from "./runSerializer.js";
|
|
4
5
|
import { escapeXml } from "./xmlUtils.js";
|
|
5
6
|
//#region src/docx/serializer/commentSerializer.ts
|
|
@@ -36,12 +37,29 @@ function serializeComment(comment) {
|
|
|
36
37
|
xml += "</w:comment>";
|
|
37
38
|
return xml;
|
|
38
39
|
}
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const COMMENTS_BASELINE_PREFIXES = [
|
|
41
|
+
"wpc",
|
|
42
|
+
"mc",
|
|
43
|
+
"o",
|
|
44
|
+
"r",
|
|
45
|
+
"m",
|
|
46
|
+
"v",
|
|
47
|
+
"wp",
|
|
48
|
+
"w10",
|
|
49
|
+
"w",
|
|
50
|
+
"w14",
|
|
51
|
+
"wp14",
|
|
52
|
+
"wpg",
|
|
53
|
+
"wpi",
|
|
54
|
+
"wne",
|
|
55
|
+
"wps"
|
|
56
|
+
];
|
|
57
|
+
const COMMENTS_EXTENDED_BASELINE_PREFIXES = [
|
|
58
|
+
"mc",
|
|
59
|
+
"w",
|
|
60
|
+
"w15"
|
|
61
|
+
];
|
|
62
|
+
const XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
|
|
45
63
|
/**
|
|
46
64
|
* Serialize comments array to comments.xml content. Returns a valid empty
|
|
47
65
|
* `<w:comments/>` document for an empty array so callers can overwrite an
|
|
@@ -49,18 +67,21 @@ const COMMENTS_HEADER = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
|
49
67
|
* comment — leaving the previous file in place would otherwise re-emit
|
|
50
68
|
* the orphaned comment threads on every save.
|
|
51
69
|
*/
|
|
52
|
-
function serializeComments(comments) {
|
|
70
|
+
function serializeComments(comments, sourceBindings) {
|
|
53
71
|
const topLevel = [];
|
|
54
72
|
const replies = [];
|
|
55
73
|
for (const c of comments) {
|
|
56
74
|
const { parentId } = c;
|
|
57
75
|
(parentId === null || parentId === void 0 ? topLevel : replies).push(c);
|
|
58
76
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
+
});
|
|
64
85
|
}
|
|
65
86
|
/** The `w14:paraId` Word threads a comment by: its LAST paragraph's paraId. */
|
|
66
87
|
function commentThreadParaId(comment) {
|
|
@@ -145,7 +166,6 @@ function buildCommentExtendedEntries(comments) {
|
|
|
145
166
|
}
|
|
146
167
|
return entries.length > 0 ? entries : null;
|
|
147
168
|
}
|
|
148
|
-
const COMMENTS_EXTENDED_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w15:commentsEx xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" mc:Ignorable=\"w15\">";
|
|
149
169
|
/**
|
|
150
170
|
* Serialize `commentsExtended.xml` (`w15:commentsEx`) for reply threading and
|
|
151
171
|
* resolved state, or `null` when no comment needs an entry (see
|
|
@@ -155,13 +175,17 @@ const COMMENTS_EXTENDED_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" stand
|
|
|
155
175
|
function serializeCommentsExtended(comments) {
|
|
156
176
|
const entries = buildCommentExtendedEntries(comments);
|
|
157
177
|
if (!entries) return null;
|
|
158
|
-
|
|
159
|
-
for (const entry of entries) {
|
|
178
|
+
const body = entries.map((entry) => {
|
|
160
179
|
const parentAttr = entry.paraIdParent !== void 0 ? ` w15:paraIdParent="${escapeXml(entry.paraIdParent)}"` : "";
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
180
|
+
return `<w15:commentEx w15:paraId="${escapeXml(entry.paraId)}"${parentAttr} w15:done="${entry.done ? "1" : "0"}"/>`;
|
|
181
|
+
}).join("");
|
|
182
|
+
return XML_DECLARATION + serializePartElement({
|
|
183
|
+
partPath: "word/commentsExtended.xml",
|
|
184
|
+
rootName: "w15:commentsEx",
|
|
185
|
+
baselinePrefixes: COMMENTS_EXTENDED_BASELINE_PREFIXES,
|
|
186
|
+
sourceBindings: void 0,
|
|
187
|
+
body
|
|
188
|
+
});
|
|
165
189
|
}
|
|
166
190
|
//#endregion
|
|
167
191
|
export { ensureThreadedCommentParaIds, serializeComments, serializeCommentsExtended };
|
|
@@ -11,9 +11,11 @@ declare function serializeDocumentBody(body: document_d_exports.DocumentBody): s
|
|
|
11
11
|
* Serialize a complete Document to valid document.xml
|
|
12
12
|
*
|
|
13
13
|
* @param doc - The document to serialize
|
|
14
|
+
* @param sourceBindings - Root `xmlns:*` of the part being replaced, so a
|
|
15
|
+
* prefix only the source document bound keeps its URI
|
|
14
16
|
* @returns Complete XML string for document.xml
|
|
15
17
|
*/
|
|
16
|
-
declare function serializeDocument(doc: document_d_exports.Document): string;
|
|
18
|
+
declare function serializeDocument(doc: document_d_exports.Document, sourceBindings?: ReadonlyMap<string, string>): string;
|
|
17
19
|
/**
|
|
18
20
|
* Serialize just the document body (useful for partial updates)
|
|
19
21
|
*
|
|
@@ -1,78 +1,41 @@
|
|
|
1
1
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
2
2
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
|
+
import { serializePartElement } from "./partNamespaces.js";
|
|
3
4
|
import { resetAutoIdCounter } from "./runSerializer.js";
|
|
4
5
|
import { serializeSectionProperties } from "./sectionPropertiesSerializer.js";
|
|
5
6
|
import { serializeTable } from "./tableSerializer.js";
|
|
6
7
|
//#region src/docx/serializer/documentSerializer.ts
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
w16cid: "http://schemas.microsoft.com/office/word/2016/wordml/cid",
|
|
39
|
-
w16: "http://schemas.microsoft.com/office/word/2018/wordml",
|
|
40
|
-
w16sdtdh: "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash",
|
|
41
|
-
w16se: "http://schemas.microsoft.com/office/word/2015/wordml/symex",
|
|
42
|
-
wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup",
|
|
43
|
-
wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
|
|
44
|
-
wne: "http://schemas.microsoft.com/office/word/2006/wordml",
|
|
45
|
-
wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape"
|
|
46
|
-
};
|
|
47
|
-
/**
|
|
48
|
-
* Build namespace declaration string for document element
|
|
49
|
-
*/
|
|
50
|
-
function buildNamespaceDeclarations() {
|
|
51
|
-
const declared = {
|
|
52
|
-
a: NAMESPACES.a,
|
|
53
|
-
wpc: NAMESPACES.wpc,
|
|
54
|
-
mc: NAMESPACES.mc,
|
|
55
|
-
o: NAMESPACES.o,
|
|
56
|
-
pic: NAMESPACES.pic,
|
|
57
|
-
r: NAMESPACES.r,
|
|
58
|
-
m: NAMESPACES.m,
|
|
59
|
-
v: NAMESPACES.v,
|
|
60
|
-
wp14: NAMESPACES.wp14,
|
|
61
|
-
wp: NAMESPACES.wp,
|
|
62
|
-
w10: NAMESPACES.w10,
|
|
63
|
-
w: NAMESPACES.w,
|
|
64
|
-
w14: NAMESPACES.w14,
|
|
65
|
-
w15: NAMESPACES.w15,
|
|
66
|
-
w16: NAMESPACES.w16,
|
|
67
|
-
w16cex: NAMESPACES.w16cex,
|
|
68
|
-
w16cid: NAMESPACES.w16cid,
|
|
69
|
-
w16sdtdh: NAMESPACES.w16sdtdh,
|
|
70
|
-
w16se: NAMESPACES.w16se,
|
|
71
|
-
wpg: NAMESPACES.wpg,
|
|
72
|
-
wps: NAMESPACES.wps
|
|
73
|
-
};
|
|
74
|
-
return Object.entries(declared).map(([prefix, uri]) => `xmlns:${prefix}="${uri}"`).join(" ");
|
|
75
|
-
}
|
|
9
|
+
* Prefixes document.xml declares whether or not the body uses them.
|
|
10
|
+
*
|
|
11
|
+
* A canonical `<w:sdtPr>` legitimately carries `<w16sdtdh:dataHash>` /
|
|
12
|
+
* `<w16cex:*>` / `<w16cid:*>` children the parser stores opaquely, and the
|
|
13
|
+
* drawing prefixes host raw-replayed shapes, so the part keeps the shape Word
|
|
14
|
+
* writes even when this particular save emits none of them.
|
|
15
|
+
*/
|
|
16
|
+
const DOCUMENT_BASELINE_PREFIXES = [
|
|
17
|
+
"a",
|
|
18
|
+
"wpc",
|
|
19
|
+
"mc",
|
|
20
|
+
"o",
|
|
21
|
+
"pic",
|
|
22
|
+
"r",
|
|
23
|
+
"m",
|
|
24
|
+
"v",
|
|
25
|
+
"wp14",
|
|
26
|
+
"wp",
|
|
27
|
+
"w10",
|
|
28
|
+
"w",
|
|
29
|
+
"w14",
|
|
30
|
+
"w15",
|
|
31
|
+
"w16",
|
|
32
|
+
"w16cex",
|
|
33
|
+
"w16cid",
|
|
34
|
+
"w16sdtdh",
|
|
35
|
+
"w16se",
|
|
36
|
+
"wpg",
|
|
37
|
+
"wps"
|
|
38
|
+
];
|
|
76
39
|
/**
|
|
77
40
|
* Serialize a single block content item (paragraph, table, or block-level SDT).
|
|
78
41
|
*/
|
|
@@ -103,19 +66,20 @@ function serializeDocumentBody(body) {
|
|
|
103
66
|
* Serialize a complete Document to valid document.xml
|
|
104
67
|
*
|
|
105
68
|
* @param doc - The document to serialize
|
|
69
|
+
* @param sourceBindings - Root `xmlns:*` of the part being replaced, so a
|
|
70
|
+
* prefix only the source document bound keeps its URI
|
|
106
71
|
* @returns Complete XML string for document.xml
|
|
107
72
|
*/
|
|
108
|
-
function serializeDocument(doc) {
|
|
73
|
+
function serializeDocument(doc, sourceBindings) {
|
|
109
74
|
resetAutoIdCounter();
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return parts.join("");
|
|
75
|
+
const body = `<w:body>${serializeDocumentBody(doc.package.document)}</w:body>`;
|
|
76
|
+
return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + serializePartElement({
|
|
77
|
+
partPath: "word/document.xml",
|
|
78
|
+
rootName: "w:document",
|
|
79
|
+
baselinePrefixes: DOCUMENT_BASELINE_PREFIXES,
|
|
80
|
+
sourceBindings,
|
|
81
|
+
body
|
|
82
|
+
});
|
|
119
83
|
}
|
|
120
84
|
/**
|
|
121
85
|
* Serialize just the document body (useful for partial updates)
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { serializePartElement } from "./partNamespaces.js";
|
|
1
2
|
import { escapeXml } from "./xmlUtils.js";
|
|
2
3
|
//#region src/docx/serializer/fontTableSerializer.ts
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const serializeFontTableXml = (fontTable) => "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
5
|
+
partPath: "word/fontTable.xml",
|
|
6
|
+
rootName: "w:fonts",
|
|
7
|
+
baselinePrefixes: ["w"],
|
|
8
|
+
sourceBindings: void 0,
|
|
9
|
+
body: fontTable.fonts.map(serializeFont).join("")
|
|
10
|
+
});
|
|
8
11
|
const serializeFont = (font) => {
|
|
9
12
|
const parts = [];
|
|
10
13
|
if (font.altName) parts.push(`<w:altName w:val="${escapeXml(font.altName)}"/>`);
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
import { SourcePart } from "./partNamespaces.js";
|
|
2
3
|
//#region src/docx/serializer/headerFooterSerializer.d.ts
|
|
3
4
|
/**
|
|
4
5
|
* Serialize a HeaderFooter object to valid OOXML XML
|
|
5
6
|
*
|
|
6
7
|
* @param hf - HeaderFooter object to serialize
|
|
8
|
+
* @param source - The part being replaced, so a prefix only the source
|
|
9
|
+
* document bound keeps its URI
|
|
7
10
|
* @returns Complete XML string for header*.xml or footer*.xml
|
|
8
11
|
*/
|
|
9
|
-
declare function serializeHeaderFooter(hf: document_d_exports.HeaderFooter): string;
|
|
12
|
+
declare function serializeHeaderFooter(hf: document_d_exports.HeaderFooter, source?: SourcePart): string;
|
|
10
13
|
//#endregion
|
|
11
14
|
export { serializeHeaderFooter };
|
|
@@ -1,35 +1,33 @@
|
|
|
1
1
|
import { canReplayHeaderFooterVerbatim, getHeaderFooterVerbatimXml } from "../headerFooterVerbatim.js";
|
|
2
2
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
3
3
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
4
|
+
import { serializePartElement } from "./partNamespaces.js";
|
|
4
5
|
import { serializeTable } from "./tableSerializer.js";
|
|
5
6
|
import { escapeXml } from "./xmlUtils.js";
|
|
6
7
|
//#region src/docx/serializer/headerFooterSerializer.ts
|
|
7
|
-
const
|
|
8
|
-
wpc
|
|
9
|
-
mc
|
|
10
|
-
o
|
|
11
|
-
r
|
|
12
|
-
m
|
|
13
|
-
v
|
|
14
|
-
a
|
|
15
|
-
pic
|
|
16
|
-
wp14
|
|
17
|
-
wp
|
|
18
|
-
w10
|
|
19
|
-
w
|
|
20
|
-
w14
|
|
21
|
-
w15
|
|
22
|
-
w16
|
|
23
|
-
w16cex
|
|
24
|
-
w16cid
|
|
25
|
-
w16sdtdh
|
|
26
|
-
w16se
|
|
27
|
-
wpg
|
|
28
|
-
wps
|
|
29
|
-
|
|
30
|
-
function buildNamespaceDeclarations() {
|
|
31
|
-
return Object.entries(NAMESPACES).map(([prefix, uri]) => `xmlns:${prefix}="${uri}"`).join(" ");
|
|
32
|
-
}
|
|
8
|
+
const HEADER_FOOTER_BASELINE_PREFIXES = [
|
|
9
|
+
"wpc",
|
|
10
|
+
"mc",
|
|
11
|
+
"o",
|
|
12
|
+
"r",
|
|
13
|
+
"m",
|
|
14
|
+
"v",
|
|
15
|
+
"a",
|
|
16
|
+
"pic",
|
|
17
|
+
"wp14",
|
|
18
|
+
"wp",
|
|
19
|
+
"w10",
|
|
20
|
+
"w",
|
|
21
|
+
"w14",
|
|
22
|
+
"w15",
|
|
23
|
+
"w16",
|
|
24
|
+
"w16cex",
|
|
25
|
+
"w16cid",
|
|
26
|
+
"w16sdtdh",
|
|
27
|
+
"w16se",
|
|
28
|
+
"wpg",
|
|
29
|
+
"wps"
|
|
30
|
+
];
|
|
33
31
|
/**
|
|
34
32
|
* Serialize a block content item (paragraph, table, or block-level SDT) for
|
|
35
33
|
* header/footer.
|
|
@@ -43,13 +41,14 @@ function serializeBlock(block) {
|
|
|
43
41
|
* Serialize a HeaderFooter object to valid OOXML XML
|
|
44
42
|
*
|
|
45
43
|
* @param hf - HeaderFooter object to serialize
|
|
44
|
+
* @param source - The part being replaced, so a prefix only the source
|
|
45
|
+
* document bound keeps its URI
|
|
46
46
|
* @returns Complete XML string for header*.xml or footer*.xml
|
|
47
47
|
*/
|
|
48
|
-
function serializeHeaderFooter(hf) {
|
|
48
|
+
function serializeHeaderFooter(hf, source) {
|
|
49
49
|
const verbatim = getHeaderFooterVerbatimXml(hf);
|
|
50
50
|
if (verbatim && canReplayHeaderFooterVerbatim(hf)) return verbatim;
|
|
51
51
|
const rootTag = hf.type === "header" ? "w:hdr" : "w:ftr";
|
|
52
|
-
const nsDecl = buildNamespaceDeclarations();
|
|
53
52
|
const watermarkXml = serializeWatermarkParagraph(hf);
|
|
54
53
|
const watermarkInsertIndex = hf.watermarkBlockIndex !== void 0 ? Math.max(0, Math.min(hf.watermarkBlockIndex, hf.content.length)) : 0;
|
|
55
54
|
const blocksXml = hf.content.map((block) => serializeBlock(block));
|
|
@@ -57,7 +56,13 @@ function serializeHeaderFooter(hf) {
|
|
|
57
56
|
if (watermarkXml) contentXml = blocksXml.slice(0, watermarkInsertIndex).join("") + watermarkXml + blocksXml.slice(watermarkInsertIndex).join("");
|
|
58
57
|
else contentXml = blocksXml.join("");
|
|
59
58
|
if (!contentXml) contentXml = "<w:p><w:pPr/></w:p>";
|
|
60
|
-
return
|
|
59
|
+
return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
60
|
+
partPath: source?.path ?? `word/${hf.type}.xml`,
|
|
61
|
+
rootName: rootTag,
|
|
62
|
+
baselinePrefixes: HEADER_FOOTER_BASELINE_PREFIXES,
|
|
63
|
+
sourceBindings: source?.bindings,
|
|
64
|
+
body: contentXml
|
|
65
|
+
});
|
|
61
66
|
}
|
|
62
67
|
function serializeWatermarkParagraph(hf) {
|
|
63
68
|
if (hf.rawWatermarkXml) return hf.rawWatermarkXml;
|
|
@@ -1,33 +1,38 @@
|
|
|
1
1
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
2
2
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
|
+
import { serializePartElement } from "./partNamespaces.js";
|
|
3
4
|
import { serializeTable } from "./tableSerializer.js";
|
|
4
5
|
//#region src/docx/serializer/noteSerializer.ts
|
|
5
|
-
const
|
|
6
|
-
wpc
|
|
7
|
-
mc
|
|
8
|
-
o
|
|
9
|
-
r
|
|
10
|
-
m
|
|
11
|
-
v
|
|
12
|
-
a
|
|
13
|
-
pic
|
|
14
|
-
wp14
|
|
15
|
-
wp
|
|
16
|
-
w10
|
|
17
|
-
w
|
|
18
|
-
w14
|
|
19
|
-
w15
|
|
20
|
-
w16
|
|
21
|
-
w16cex
|
|
22
|
-
w16cid
|
|
23
|
-
w16sdtdh
|
|
24
|
-
w16se
|
|
25
|
-
wpg
|
|
26
|
-
wps
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
6
|
+
const NOTE_BASELINE_PREFIXES = [
|
|
7
|
+
"wpc",
|
|
8
|
+
"mc",
|
|
9
|
+
"o",
|
|
10
|
+
"r",
|
|
11
|
+
"m",
|
|
12
|
+
"v",
|
|
13
|
+
"a",
|
|
14
|
+
"pic",
|
|
15
|
+
"wp14",
|
|
16
|
+
"wp",
|
|
17
|
+
"w10",
|
|
18
|
+
"w",
|
|
19
|
+
"w14",
|
|
20
|
+
"w15",
|
|
21
|
+
"w16",
|
|
22
|
+
"w16cex",
|
|
23
|
+
"w16cid",
|
|
24
|
+
"w16sdtdh",
|
|
25
|
+
"w16se",
|
|
26
|
+
"wpg",
|
|
27
|
+
"wps"
|
|
28
|
+
];
|
|
29
|
+
const serializeNotePart = (elementName, body) => "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
30
|
+
partPath: `word/${elementName}s.xml`,
|
|
31
|
+
rootName: `w:${elementName}s`,
|
|
32
|
+
baselinePrefixes: NOTE_BASELINE_PREFIXES,
|
|
33
|
+
sourceBindings: void 0,
|
|
34
|
+
body
|
|
35
|
+
});
|
|
31
36
|
/**
|
|
32
37
|
* Serialize a block content item (paragraph, table, or block-level SDT) for a
|
|
33
38
|
* note body.
|
|
@@ -63,9 +68,8 @@ function insertNoteReferenceMark(xml, elementName) {
|
|
|
63
68
|
return `${xml.slice(0, insertAt)}${referenceRun}${xml.slice(insertAt)}`;
|
|
64
69
|
}
|
|
65
70
|
function serializeNewNotePart(elementName, notes) {
|
|
66
|
-
const nsDecl = buildNamespaceDeclarations();
|
|
67
71
|
const serializedNotes = notes.map((note) => insertNoteReferenceMark(serializeNote(elementName, note), elementName)).join("");
|
|
68
|
-
return
|
|
72
|
+
return serializeNotePart(elementName, serializeRequiredNoteSeparators(elementName) + serializedNotes);
|
|
69
73
|
}
|
|
70
74
|
/**
|
|
71
75
|
* Serialize footnotes to a complete word/footnotes.xml string.
|
|
@@ -74,7 +78,7 @@ function serializeNewNotePart(elementName, notes) {
|
|
|
74
78
|
* @returns Complete footnotes.xml string.
|
|
75
79
|
*/
|
|
76
80
|
function serializeFootnotes(footnotes) {
|
|
77
|
-
return
|
|
81
|
+
return serializeNotePart("footnote", footnotes.map((fn) => serializeNote("footnote", fn)).join(""));
|
|
78
82
|
}
|
|
79
83
|
/**
|
|
80
84
|
* Serialize endnotes to a complete word/endnotes.xml string.
|
|
@@ -83,7 +87,7 @@ function serializeFootnotes(footnotes) {
|
|
|
83
87
|
* @returns Complete endnotes.xml string.
|
|
84
88
|
*/
|
|
85
89
|
function serializeEndnotes(endnotes) {
|
|
86
|
-
return
|
|
90
|
+
return serializeNotePart("endnote", endnotes.map((en) => serializeNote("endnote", en)).join(""));
|
|
87
91
|
}
|
|
88
92
|
/** Serialize a brand-new footnote part, including Word's required separators
|
|
89
93
|
* and the automatic reference mark at the start of every normal note. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { serializePartElement } from "./partNamespaces.js";
|
|
1
2
|
import { serializeTextFormatting } from "./runSerializer.js";
|
|
2
3
|
import { escapeXml, intAttr } from "./xmlUtils.js";
|
|
3
4
|
//#region src/docx/serializer/numberingSerializer.ts
|
|
4
|
-
const W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
5
5
|
/**
|
|
6
6
|
* Serialize a level's paragraph properties — the modeled subset is indentation
|
|
7
7
|
* plus tab stops (see `parseLevelParagraphProps`). Returns "" when neither is
|
|
@@ -87,9 +87,13 @@ function serializeNum(instance) {
|
|
|
87
87
|
* change detection and per-definition splicing, never to overwrite the part.
|
|
88
88
|
*/
|
|
89
89
|
function serializeNumberingXml(numbering) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + serializePartElement({
|
|
91
|
+
partPath: "word/numbering.xml",
|
|
92
|
+
rootName: "w:numbering",
|
|
93
|
+
baselinePrefixes: ["w"],
|
|
94
|
+
sourceBindings: void 0,
|
|
95
|
+
body: `${numbering.abstractNums.map(serializeAbstractNum).join("")}${numbering.nums.map(serializeNum).join("")}`
|
|
96
|
+
});
|
|
93
97
|
}
|
|
94
98
|
//#endregion
|
|
95
99
|
export { serializeNumberingXml };
|
|
@@ -150,12 +150,10 @@ function serializeParagraphFormatting(formatting, propertyChanges, pPrMark) {
|
|
|
150
150
|
if (formatting.styleId) parts.push(`<w:pStyle w:val="${escapeXml(formatting.styleId)}"/>`);
|
|
151
151
|
pushToggle("keepNext", formatting.keepNext);
|
|
152
152
|
pushToggle("keepLines", formatting.keepLines);
|
|
153
|
-
pushToggle("contextualSpacing", formatting.contextualSpacing);
|
|
154
153
|
pushToggle("pageBreakBefore", formatting.pageBreakBefore);
|
|
155
154
|
const frameXml = serializeFrameProperties(formatting.frame);
|
|
156
155
|
if (frameXml) parts.push(frameXml);
|
|
157
156
|
pushToggle("widowControl", formatting.widowControl);
|
|
158
|
-
pushToggle("snapToGrid", formatting.snapToGrid);
|
|
159
157
|
const numPrXml = formatting.numPrFromStyle != null && numPrEqual(formatting.numPr, formatting.numPrFromStyle) ? "" : serializeNumbering(formatting.numPr);
|
|
160
158
|
if (numPrXml) parts.push(numPrXml);
|
|
161
159
|
const bordersXml = serializeParagraphBorders(formatting.borders);
|
|
@@ -168,11 +166,13 @@ function serializeParagraphFormatting(formatting, propertyChanges, pPrMark) {
|
|
|
168
166
|
pushToggle("suppressAutoHyphens", formatting.suppressAutoHyphens);
|
|
169
167
|
pushToggle("kinsoku", formatting.kinsoku);
|
|
170
168
|
pushToggle("overflowPunct", formatting.overflowPunctuation);
|
|
169
|
+
pushToggle("bidi", formatting.bidi);
|
|
170
|
+
pushToggle("snapToGrid", formatting.snapToGrid);
|
|
171
171
|
const spacingXml = serializeSpacing(formatting);
|
|
172
172
|
if (spacingXml) parts.push(spacingXml);
|
|
173
173
|
const indXml = serializeIndentation(formatting);
|
|
174
174
|
if (indXml) parts.push(indXml);
|
|
175
|
-
pushToggle("
|
|
175
|
+
pushToggle("contextualSpacing", formatting.contextualSpacing);
|
|
176
176
|
if (formatting.alignment) parts.push(`<w:jc w:val="${formatting.alignment}"/>`);
|
|
177
177
|
if (formatting.outlineLevel !== void 0) parts.push(`<w:outlineLvl w:val="${formatting.outlineLevel}"/>`);
|
|
178
178
|
if (pPrMark || formatting.runProperties || formatting.runInWithNext) {
|
|
@@ -210,10 +210,8 @@ function serializeParagraphPropertyChange(change) {
|
|
|
210
210
|
const normalizedPreviousPPr = previousPPrInner.length > 0 ? `<w:pPr>${previousPPrInner}</w:pPr>` : "<w:pPr/>";
|
|
211
211
|
return `<w:pPrChange ${attrs.join(" ")}>${normalizedPreviousPPr}</w:pPrChange>`;
|
|
212
212
|
}
|
|
213
|
-
/**
|
|
214
|
-
|
|
215
|
-
*/
|
|
216
|
-
function serializeHyperlink(hyperlink) {
|
|
213
|
+
/** The attribute list of a `w:hyperlink`, without its children. */
|
|
214
|
+
function hyperlinkAttributes(hyperlink) {
|
|
217
215
|
const attrs = [];
|
|
218
216
|
if (hyperlink.rId) attrs.push(`r:id="${escapeXml(hyperlink.rId)}"`);
|
|
219
217
|
if (hyperlink.anchor) attrs.push(`w:anchor="${escapeXml(hyperlink.anchor)}"`);
|
|
@@ -222,12 +220,19 @@ function serializeHyperlink(hyperlink) {
|
|
|
222
220
|
if (hyperlink.history === true) attrs.push("w:history=\"1\"");
|
|
223
221
|
else if (hyperlink.history === false) attrs.push("w:history=\"0\"");
|
|
224
222
|
if (hyperlink.docLocation) attrs.push(`w:docLocation="${escapeXml(hyperlink.docLocation)}"`);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return
|
|
223
|
+
return attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
224
|
+
}
|
|
225
|
+
/** One `w:hyperlink` child, with the caller deciding how a run is written. */
|
|
226
|
+
function serializeHyperlinkChild(child, serializeChildRun) {
|
|
227
|
+
if (child.type === "run") return serializeChildRun(child);
|
|
228
|
+
return child.type === "bookmarkStart" ? serializeBookmarkStart(child) : serializeBookmarkEnd(child);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Serialize a hyperlink (w:hyperlink)
|
|
232
|
+
*/
|
|
233
|
+
function serializeHyperlink(hyperlink) {
|
|
234
|
+
const childrenXml = hyperlink.children.map((child) => serializeHyperlinkChild(child, serializeRun)).join("");
|
|
235
|
+
return `<w:hyperlink${hyperlinkAttributes(hyperlink)}>${childrenXml}</w:hyperlink>`;
|
|
231
236
|
}
|
|
232
237
|
/**
|
|
233
238
|
* Serialize bookmark start (w:bookmarkStart)
|
|
@@ -397,20 +402,39 @@ function serializeTrackedChange(tag, change) {
|
|
|
397
402
|
return rewriteRunTextAsDeleted(contentXml);
|
|
398
403
|
}).join("");
|
|
399
404
|
};
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
return serializeRun(item);
|
|
404
|
-
}
|
|
405
|
-
if (item.type === "hyperlink") return serializeHyperlink(item);
|
|
405
|
+
const serializeContentRun = (run) => tag === "del" || tag === "moveFrom" ? serializeDeletedRun(run) : serializeRun(run);
|
|
406
|
+
const serializeWrappedItem = (item) => {
|
|
407
|
+
if (item.type === "run") return serializeContentRun(item);
|
|
406
408
|
if (item.type === "simpleField" || item.type === "complexField") {
|
|
407
409
|
const xml = item.type === "simpleField" ? serializeSimpleField(item) : serializeComplexField(item);
|
|
408
410
|
return tag === "del" || tag === "moveFrom" ? rewriteRunTextAsDeleted(xml) : xml;
|
|
409
411
|
}
|
|
410
412
|
if (item.type === "insertion" || item.type === "deletion" || item.type === "moveFrom" || item.type === "moveTo") return serializeTrackedChange(trackedChangeTag(item), item);
|
|
411
413
|
return item.type === "bookmarkStart" ? serializeBookmarkStart(item) : serializeBookmarkEnd(item);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
+
};
|
|
415
|
+
const open = `<w:${tag} ${attrs.join(" ")}>`;
|
|
416
|
+
const close = `</w:${tag}>`;
|
|
417
|
+
const wrap = (inner) => inner.length === 0 ? "" : `${open}${inner}${close}`;
|
|
418
|
+
if (change.content.length === 0) return `${open}${close}`;
|
|
419
|
+
const segments = [];
|
|
420
|
+
const pending = [];
|
|
421
|
+
const flushPending = () => {
|
|
422
|
+
if (pending.length > 0) {
|
|
423
|
+
segments.push(wrap(pending.join("")));
|
|
424
|
+
pending.length = 0;
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
for (const item of change.content) {
|
|
428
|
+
if (item.type === "hyperlink") {
|
|
429
|
+
flushPending();
|
|
430
|
+
const childrenXml = item.children.map((child) => serializeHyperlinkChild(child, serializeContentRun)).join("");
|
|
431
|
+
segments.push(`<w:hyperlink${hyperlinkAttributes(item)}>${open}${childrenXml}${close}</w:hyperlink>`);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
pending.push(serializeWrappedItem(item));
|
|
435
|
+
}
|
|
436
|
+
flushPending();
|
|
437
|
+
return segments.join("");
|
|
414
438
|
}
|
|
415
439
|
/** Emit the `<w:commentReference>` run Word places after a comment range end. */
|
|
416
440
|
function serializeCommentReferenceRun(id) {
|