@portone/docx-editor 0.2.1 → 0.4.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/CHANGELOG.md +155 -0
- package/CONTRIBUTING.md +5 -1
- package/dist/DocxEditor.d.ts +6 -0
- package/dist/DocxEditor.js +13 -29
- package/dist/core.d.ts +23 -8
- package/dist/core.js +9 -4
- package/dist/docx/cloning.d.ts +38 -0
- package/dist/docx/cloning.js +74 -0
- package/dist/docx/commentOnlyChange.d.ts +12 -7
- package/dist/docx/commentOnlyChange.js +9 -156
- package/dist/docx/comments/constants.d.ts +0 -1
- package/dist/docx/comments/constants.js +0 -2
- package/dist/docx/comments/grammar.d.ts +10 -4
- package/dist/docx/comments/grammar.js +12 -2
- package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
- package/dist/docx/comments/parts.js +279 -0
- package/dist/docx/comments/people.d.ts +11 -2
- package/dist/docx/comments/people.js +16 -92
- package/dist/docx/comments/policy.d.ts +7 -0
- package/dist/docx/comments/policy.js +43 -0
- package/dist/docx/comments/reading.js +8 -10
- package/dist/docx/comments/writing.d.ts +19 -7
- package/dist/docx/comments/writing.js +59 -112
- package/dist/docx/documentSettings.d.ts +7 -0
- package/dist/docx/documentSettings.js +10 -2
- package/dist/docx/exportDocx.d.ts +40 -5
- package/dist/docx/exportDocx.js +88 -74
- package/dist/docx/exportRefs.d.ts +5 -2
- package/dist/docx/exportRefs.js +3 -1
- package/dist/docx/fidelity.d.ts +43 -0
- package/dist/docx/fidelity.js +64 -0
- package/dist/docx/formatting/attrs.d.ts +45 -0
- package/dist/docx/formatting/attrs.js +86 -0
- package/dist/docx/formatting/context.d.ts +39 -0
- package/dist/docx/formatting/context.js +60 -0
- package/dist/docx/formatting/direct.d.ts +6 -5
- package/dist/docx/formatting/direct.js +52 -78
- package/dist/docx/formatting/resolve.d.ts +51 -0
- package/dist/docx/formatting/resolve.js +160 -0
- package/dist/docx/formatting/runProperties.d.ts +93 -0
- package/dist/docx/formatting/runProperties.js +316 -0
- package/dist/docx/formatting/styles.d.ts +25 -2
- package/dist/docx/formatting/styles.js +87 -6
- package/dist/docx/formatting/tabStops.js +7 -22
- package/dist/docx/formatting.d.ts +4 -1
- package/dist/docx/formatting.js +4 -1
- package/dist/docx/headersFooters.js +6 -13
- package/dist/docx/hyperlink.d.ts +14 -4
- package/dist/docx/hyperlink.js +4 -1
- package/dist/docx/identities.d.ts +67 -0
- package/dist/docx/identities.js +174 -0
- package/dist/docx/importDocx.d.ts +12 -1
- package/dist/docx/importDocx.js +90 -88
- package/dist/docx/importParagraph.d.ts +1 -1
- package/dist/docx/importParagraph.js +4 -3
- package/dist/docx/importTable.d.ts +2 -2
- package/dist/docx/importTable.js +69 -56
- package/dist/docx/invariants.d.ts +33 -0
- package/dist/docx/invariants.js +269 -0
- package/dist/docx/media.d.ts +6 -4
- package/dist/docx/media.js +6 -37
- package/dist/docx/newLists.d.ts +50 -0
- package/dist/docx/newLists.js +59 -0
- package/dist/docx/notes.js +3 -7
- package/dist/docx/numberingPlanner.d.ts +11 -0
- package/dist/docx/numberingPlanner.js +50 -0
- package/dist/docx/packageParts.d.ts +42 -0
- package/dist/docx/packageParts.js +135 -0
- package/dist/docx/pageGeometry.d.ts +2 -0
- package/dist/docx/pageGeometry.js +18 -9
- package/dist/docx/paraProps.d.ts +10 -22
- package/dist/docx/paraProps.js +47 -76
- package/dist/docx/partPlan.d.ts +36 -0
- package/dist/docx/partPlan.js +59 -0
- package/dist/docx/protectionPolicy.d.ts +127 -0
- package/dist/docx/protectionPolicy.js +169 -0
- package/dist/docx/relationships.d.ts +1 -1
- package/dist/docx/relationships.js +8 -13
- package/dist/docx/runProps.d.ts +9 -22
- package/dist/docx/runProps.js +15 -168
- package/dist/docx/scan.js +20 -52
- package/dist/docx/sdt.js +9 -34
- package/dist/docx/sdtProps.d.ts +8 -1
- package/dist/docx/sdtProps.js +10 -0
- package/dist/docx/serializeBlock.d.ts +2 -0
- package/dist/docx/serializeBlock.js +8 -5
- package/dist/docx/serializeTable.js +32 -15
- package/dist/docx/session.d.ts +42 -14
- package/dist/docx/session.js +53 -17
- package/dist/docx/tableFormatting/conditions.d.ts +76 -0
- package/dist/docx/tableFormatting/conditions.js +196 -0
- package/dist/docx/tableFormatting/editing.d.ts +7 -3
- package/dist/docx/tableFormatting/editing.js +111 -143
- package/dist/docx/tableFormatting/reading.d.ts +63 -23
- package/dist/docx/tableFormatting/reading.js +132 -38
- package/dist/docx/tableFormatting.d.ts +1 -0
- package/dist/docx/tableFormatting.js +1 -0
- package/dist/docx/tableTemplate.js +30 -19
- package/dist/download.d.ts +8 -5
- package/dist/download.js +2 -0
- package/dist/editor/clipboard/inlineFormatting.js +19 -30
- package/dist/editor/commands/comments/editing.d.ts +6 -2
- package/dist/editor/commands/comments/editing.js +19 -31
- package/dist/editor/commands/exportQueries.d.ts +15 -0
- package/dist/editor/commands/exportQueries.js +14 -0
- package/dist/editor/commands/fidelityQueries.d.ts +12 -0
- package/dist/editor/commands/fidelityQueries.js +8 -0
- package/dist/editor/commands/formatting/editing.d.ts +2 -2
- package/dist/editor/commands/formatting/editing.js +26 -108
- package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
- package/dist/editor/commands/formatting/propertyCommands.js +108 -0
- package/dist/editor/commands/formatting/shared.d.ts +3 -3
- package/dist/editor/commands/formatting/shared.js +5 -2
- package/dist/editor/commands/indentCommands.js +5 -4
- package/dist/editor/commands/index.d.ts +11 -0
- package/dist/editor/commands/index.js +5 -0
- package/dist/editor/commands/linkCommands.js +5 -6
- package/dist/editor/commands/listCommands.d.ts +6 -3
- package/dist/editor/commands/listCommands.js +73 -30
- package/dist/editor/commands/lockCommands.d.ts +7 -1
- package/dist/editor/commands/lockCommands.js +35 -46
- package/dist/editor/commands/paragraphCommands.js +33 -31
- package/dist/editor/commands/spacingCommands.js +1 -1
- package/dist/editor/createEditor.d.ts +17 -29
- package/dist/editor/createEditor.js +58 -58
- package/dist/editor/documentStyles.d.ts +11 -35
- package/dist/editor/documentStyles.js +9 -52
- package/dist/editor/editorDocument.d.ts +57 -0
- package/dist/editor/editorDocument.js +86 -0
- package/dist/editor/externalClipboard.d.ts +13 -2
- package/dist/editor/externalClipboard.js +76 -75
- package/dist/editor/insertTable.js +4 -3
- package/dist/editor/paragraphEdits.d.ts +27 -19
- package/dist/editor/paragraphEdits.js +18 -19
- package/dist/editor/paragraphPlacement.d.ts +11 -0
- package/dist/editor/paragraphPlacement.js +18 -0
- package/dist/editor/plugins/displayDerivation.d.ts +47 -0
- package/dist/editor/plugins/displayDerivation.js +78 -0
- package/dist/editor/plugins/imagePaste.js +11 -7
- package/dist/editor/plugins/keymap.js +18 -3
- package/dist/editor/plugins/numberingDecorations.d.ts +14 -14
- package/dist/editor/plugins/numberingDecorations.js +50 -19
- package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
- package/dist/editor/plugins/paragraphDisplay.js +57 -0
- package/dist/editor/plugins/tabLayout.js +1 -1
- package/dist/editor/plugins/tableDisplay.d.ts +6 -0
- package/dist/editor/plugins/tableDisplay.js +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/model/format.d.ts +80 -8
- package/dist/model/format.js +100 -22
- package/dist/model/tabStops.d.ts +9 -0
- package/dist/model/tabStops.js +18 -0
- package/dist/numbering/listRegistry.d.ts +37 -0
- package/dist/numbering/listRegistry.js +112 -0
- package/dist/numbering/listTemplate.d.ts +26 -17
- package/dist/numbering/listTemplate.js +88 -25
- package/dist/numbering/markers.d.ts +15 -6
- package/dist/numbering/markers.js +26 -59
- package/dist/numbering/parseNumbering.d.ts +84 -6
- package/dist/numbering/parseNumbering.js +131 -44
- package/dist/numbering/spellers.d.ts +15 -0
- package/dist/numbering/spellers.js +96 -0
- package/dist/numbering/writeNumbering.d.ts +8 -7
- package/dist/numbering/writeNumbering.js +28 -39
- package/dist/ooxml/childOrder.d.ts +34 -0
- package/dist/ooxml/childOrder.js +496 -0
- package/dist/ooxml/conformance.d.ts +28 -0
- package/dist/ooxml/conformance.js +20 -0
- package/dist/ooxml/element.d.ts +24 -11
- package/dist/ooxml/element.js +31 -12
- package/dist/ooxml/errors.d.ts +6 -5
- package/dist/ooxml/image.d.ts +4 -0
- package/dist/ooxml/image.js +2 -5
- package/dist/ooxml/names.d.ts +9 -0
- package/dist/ooxml/names.js +8 -1
- package/dist/ooxml/partSplice.d.ts +67 -0
- package/dist/ooxml/partSplice.js +176 -0
- package/dist/ooxml/props.d.ts +112 -0
- package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
- package/dist/ooxml/simpleTypes.d.ts +103 -0
- package/dist/ooxml/simpleTypes.js +182 -0
- package/dist/ooxml/tabStops.js +8 -27
- package/dist/ooxml/tagScan.d.ts +34 -0
- package/dist/ooxml/tagScan.js +108 -0
- package/dist/ooxml/units.d.ts +25 -13
- package/dist/ooxml/units.js +65 -31
- package/dist/ooxml/xml.d.ts +35 -15
- package/dist/ooxml/xml.js +43 -11
- package/dist/page/PageGuides.d.ts +1 -1
- package/dist/page/PageGuides.js +0 -13
- package/dist/page/blockKinds.d.ts +61 -0
- package/dist/page/blockKinds.js +11 -0
- package/dist/page/kinds/index.d.ts +6 -0
- package/dist/page/kinds/index.js +10 -0
- package/dist/page/kinds/paragraphKind.d.ts +10 -0
- package/dist/page/kinds/paragraphKind.js +71 -0
- package/dist/page/kinds/tableKind.d.ts +10 -0
- package/dist/page/kinds/tableKind.js +178 -0
- package/dist/page/measureBlocks.d.ts +3 -14
- package/dist/page/measureBlocks.js +24 -45
- package/dist/page/pageDecorations.d.ts +27 -44
- package/dist/page/pageDecorations.js +70 -152
- package/dist/page/pageLayout.d.ts +2 -29
- package/dist/page/pageLayout.js +39 -16
- package/dist/page/usePageLayout.d.ts +2 -24
- package/dist/page/usePageLayout.js +5 -48
- package/dist/schema/attrRoles.d.ts +25 -18
- package/dist/schema/attrRoles.js +110 -68
- package/dist/schema/displayDerivation.d.ts +82 -0
- package/dist/schema/displayDerivation.js +130 -0
- package/dist/schema/docxSchema.d.ts +3 -0
- package/dist/schema/docxSchema.js +58 -17
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.d.ts +37 -14
- package/dist/schema/guards.js +29 -3
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/locks.d.ts +11 -44
- package/dist/schema/locks.js +0 -9
- package/dist/schema/preservedGuards.d.ts +26 -6
- package/dist/schema/preservedGuards.js +31 -1
- package/dist/schema/protection.d.ts +7 -1
- package/dist/schema/protection.js +2 -1
- package/dist/schema/sourceEquality.d.ts +1 -9
- package/dist/schema/sourceEquality.js +1 -27
- package/dist/styles/classNames.d.ts +13 -2
- package/dist/styles/classNames.js +13 -2
- package/dist/styles/inlineStyle.js +15 -6
- package/dist/styles.css +16 -18
- package/dist/table/cellFormatting.d.ts +8 -1
- package/dist/table/cellFormatting.js +11 -20
- package/dist/table/commands.js +20 -18
- package/dist/table/format.d.ts +3 -0
- package/dist/table/format.js +3 -9
- package/dist/table/gridBorders.d.ts +24 -30
- package/dist/table/gridBorders.js +35 -59
- package/dist/table/merge.d.ts +2 -6
- package/dist/table/merge.js +5 -5
- package/package.json +7 -3
- package/dist/docx/comments/contentTypes.d.ts +0 -7
- package/dist/docx/comments/contentTypes.js +0 -38
- package/dist/docx/comments/verifying.js +0 -206
- package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
- package/dist/docx/formatting/effectiveParagraph.js +0 -81
- package/dist/docx/propsXml.d.ts +0 -67
- package/dist/docx/uniqueControls.d.ts +0 -14
- package/dist/docx/uniqueControls.js +0 -62
- package/dist/editor/plugins/commentReservations.d.ts +0 -5
- package/dist/editor/plugins/commentReservations.js +0 -26
- package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
- package/dist/editor/plugins/styledParagraphs.js +0 -65
- package/dist/page/tableMeasurements.d.ts +0 -18
- package/dist/page/tableMeasurements.js +0 -119
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/docx/comments/people.ts
|
|
2
2
|
import { xmlnsAttr } from "../../ooxml/element.js";
|
|
3
|
-
import { DocxExportError } from "../../ooxml/errors.js";
|
|
4
3
|
import { xmlnsDecl } from "../../ooxml/names.js";
|
|
4
|
+
import { splicePart } from "../../ooxml/partSplice.js";
|
|
5
5
|
import {
|
|
6
6
|
attributeByLocalName,
|
|
7
7
|
childByLocalName,
|
|
@@ -10,20 +10,9 @@ import {
|
|
|
10
10
|
encodeUtf8,
|
|
11
11
|
parseXml
|
|
12
12
|
} from "../../ooxml/xml.js";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
relsPathOf,
|
|
17
|
-
resolveTarget
|
|
18
|
-
} from "../relationships.js";
|
|
19
|
-
import {
|
|
20
|
-
COMMENT_AUTHOR_PROVIDER,
|
|
21
|
-
CONTENT_TYPES_PATH,
|
|
22
|
-
PEOPLE_CONTENT_TYPE,
|
|
23
|
-
PEOPLE_REL_TYPE,
|
|
24
|
-
W15_NS
|
|
25
|
-
} from "./constants.js";
|
|
26
|
-
import { withContentType } from "./contentTypes.js";
|
|
13
|
+
import { relatedPartPath } from "../packageParts.js";
|
|
14
|
+
import { directoryOf } from "../relationships.js";
|
|
15
|
+
import { COMMENT_AUTHOR_PROVIDER, PEOPLE_REL_TYPE, W15_NS } from "./constants.js";
|
|
27
16
|
import { renderPerson } from "./grammar.js";
|
|
28
17
|
var NO_PEOPLE = {
|
|
29
18
|
partPath: null,
|
|
@@ -32,11 +21,8 @@ var NO_PEOPLE = {
|
|
|
32
21
|
byAuthor: /* @__PURE__ */ new Map()
|
|
33
22
|
};
|
|
34
23
|
function readPeople(parts, mainPartPath) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
);
|
|
38
|
-
if (!relationship) return NO_PEOPLE;
|
|
39
|
-
const partPath = resolveTarget(mainPartPath, relationship.target);
|
|
24
|
+
const partPath = relatedPartPath(parts, mainPartPath, PEOPLE_REL_TYPE);
|
|
25
|
+
if (partPath === null) return NO_PEOPLE;
|
|
40
26
|
const bytes = parts.get(partPath);
|
|
41
27
|
if (!bytes) return { ...NO_PEOPLE, partPath };
|
|
42
28
|
const { text, hadBom } = decodeUtf8(bytes);
|
|
@@ -85,43 +71,6 @@ function w15Prefix(root) {
|
|
|
85
71
|
const prefix = declaration.name.slice("xmlns:".length);
|
|
86
72
|
return prefix === "" ? "" : `${prefix}:`;
|
|
87
73
|
}
|
|
88
|
-
function rootTagStart(xml) {
|
|
89
|
-
let at = 0;
|
|
90
|
-
for (; ; ) {
|
|
91
|
-
const opens = xml.indexOf("<", at);
|
|
92
|
-
if (opens === -1) return -1;
|
|
93
|
-
if (xml.startsWith("<!--", opens)) {
|
|
94
|
-
at = xml.indexOf("-->", opens + 4) + 3;
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
if (xml.startsWith("<?", opens)) {
|
|
98
|
-
at = xml.indexOf("?>", opens + 2) + 2;
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
return opens;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function openTagEnd(xml, at) {
|
|
105
|
-
let quote = null;
|
|
106
|
-
for (let i = at; i < xml.length; i += 1) {
|
|
107
|
-
const character = xml[i];
|
|
108
|
-
if (quote !== null) {
|
|
109
|
-
if (character === quote) quote = null;
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
if (character === '"' || character === "'") {
|
|
113
|
-
quote = character;
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
if (character === ">") {
|
|
117
|
-
return { end: i + 1, selfClosing: xml[i - 1] === "/" };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
function malformed(detail) {
|
|
123
|
-
return new DocxExportError("malformed-xml", `the people part ${detail}`);
|
|
124
|
-
}
|
|
125
74
|
function peopleXml(people, added) {
|
|
126
75
|
const xml = people.xml;
|
|
127
76
|
if (xml === null) {
|
|
@@ -131,11 +80,7 @@ function peopleXml(people, added) {
|
|
|
131
80
|
);
|
|
132
81
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w15:people ${xmlnsDecl("w15")}>${persons2.join("")}</w15:people>`;
|
|
133
82
|
}
|
|
134
|
-
const
|
|
135
|
-
if (root.localName !== "people") {
|
|
136
|
-
throw malformed("has no people root element");
|
|
137
|
-
}
|
|
138
|
-
const prefix = w15Prefix(root);
|
|
83
|
+
const prefix = w15Prefix(parseXml(xml).documentElement);
|
|
139
84
|
const persons = Array.from(
|
|
140
85
|
added,
|
|
141
86
|
([author, userId]) => renderPerson(
|
|
@@ -145,46 +90,24 @@ function peopleXml(people, added) {
|
|
|
145
90
|
prefix === null ? xmlnsAttr("w15") : null
|
|
146
91
|
)
|
|
147
92
|
).join("");
|
|
148
|
-
|
|
149
|
-
const open = start === -1 ? null : openTagEnd(xml, start);
|
|
150
|
-
if (open === null) throw malformed("has no people root element");
|
|
151
|
-
if (open.selfClosing) {
|
|
152
|
-
return `${xml.slice(0, open.end - 2)}>${persons}</${root.nodeName}>` + xml.slice(open.end);
|
|
153
|
-
}
|
|
154
|
-
const close = xml.lastIndexOf(`</${root.nodeName}`);
|
|
155
|
-
if (close === -1) throw malformed("has no closing people tag");
|
|
156
|
-
return xml.slice(0, close) + persons + xml.slice(close);
|
|
157
|
-
}
|
|
158
|
-
function availablePeoplePath(session) {
|
|
159
|
-
const directory = directoryOf(session.mainPartPath);
|
|
160
|
-
for (let suffix = 0; ; suffix += 1) {
|
|
161
|
-
const name = suffix === 0 ? "people.xml" : `people${suffix + 1}.xml`;
|
|
162
|
-
const path = directory + name;
|
|
163
|
-
if (!session.parts.has(path)) return path;
|
|
164
|
-
}
|
|
93
|
+
return splicePart(xml, { root: "people", append: persons });
|
|
165
94
|
}
|
|
166
|
-
function planPeoplePart(bodies, session,
|
|
95
|
+
function planPeoplePart(part, bodies, session, context) {
|
|
167
96
|
const people = session.comments.people;
|
|
168
97
|
const added = unrecordedAuthors(bodies, people);
|
|
169
98
|
if (added.size === 0) return null;
|
|
170
99
|
const parts = /* @__PURE__ */ new Map();
|
|
171
|
-
const addingPart =
|
|
172
|
-
const partPath =
|
|
100
|
+
const addingPart = part.pathIn(session) === null;
|
|
101
|
+
const partPath = part.writePathIn(session);
|
|
173
102
|
if (addingPart) {
|
|
174
|
-
relationships.add({
|
|
175
|
-
type:
|
|
103
|
+
context.relationships.add({
|
|
104
|
+
type: part.relType,
|
|
176
105
|
target: partPath.slice(directoryOf(session.mainPartPath).length)
|
|
177
106
|
});
|
|
178
107
|
}
|
|
179
108
|
parts.set(partPath, encodeUtf8(peopleXml(people, added), people.hadBom));
|
|
180
109
|
if (addingPart || people.xml === null) {
|
|
181
|
-
|
|
182
|
-
session.parts,
|
|
183
|
-
partPath,
|
|
184
|
-
PEOPLE_CONTENT_TYPE,
|
|
185
|
-
currentContentTypes
|
|
186
|
-
);
|
|
187
|
-
if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
|
|
110
|
+
context.contentTypes.addOverride(partPath, part.contentType);
|
|
188
111
|
}
|
|
189
112
|
return parts;
|
|
190
113
|
}
|
|
@@ -192,5 +115,6 @@ export {
|
|
|
192
115
|
NO_PEOPLE,
|
|
193
116
|
commentAuthorId,
|
|
194
117
|
planPeoplePart,
|
|
195
|
-
readPeople
|
|
118
|
+
readPeople,
|
|
119
|
+
unrecordedAuthors
|
|
196
120
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The protection that takes comments and nothing else, as the policy both the part planners and
|
|
3
|
+
* the server verifier read (`../protectionPolicy`).
|
|
4
|
+
*/
|
|
5
|
+
type StoryReason = "body-changed" | "comment-not-owned" | "comment-author-forged";
|
|
6
|
+
export declare const commentsPolicy: import("../protectionPolicy").ProtectionPolicy<StoryReason, "comment-markup-rejected">;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/docx/comments/policy.ts
|
|
2
|
+
import {
|
|
3
|
+
commentAdditionsBy,
|
|
4
|
+
commentEditsOwned,
|
|
5
|
+
commentIdentitiesKept,
|
|
6
|
+
withoutComments
|
|
7
|
+
} from "../../schema/protection.js";
|
|
8
|
+
import {
|
|
9
|
+
registerProtectionPolicy
|
|
10
|
+
} from "../protectionPolicy.js";
|
|
11
|
+
import { comparableStory } from "../storyProjection.js";
|
|
12
|
+
import { COMMENT_STORY_PARTS } from "./parts.js";
|
|
13
|
+
var refused = (reason) => ({ ok: false, reason });
|
|
14
|
+
function sameBody(before, after) {
|
|
15
|
+
const was = comparableStory(before, withoutComments);
|
|
16
|
+
const now = comparableStory(after, withoutComments);
|
|
17
|
+
return was !== null && now !== null && was.length === now.length && was.every((block, at) => block === now[at]);
|
|
18
|
+
}
|
|
19
|
+
function commentsStoryKept(before, after, authorId, { editableComments }) {
|
|
20
|
+
if (!sameBody(before, after)) return refused("body-changed");
|
|
21
|
+
if (!commentIdentitiesKept(before.doc, after.doc) || !commentAdditionsBy(before.doc, after.doc, authorId)) {
|
|
22
|
+
return refused("comment-author-forged");
|
|
23
|
+
}
|
|
24
|
+
if (!commentEditsOwned(before.doc, after.doc, {
|
|
25
|
+
protection: "comments",
|
|
26
|
+
authorId,
|
|
27
|
+
editableComments
|
|
28
|
+
})) {
|
|
29
|
+
return refused("comment-not-owned");
|
|
30
|
+
}
|
|
31
|
+
return { ok: true };
|
|
32
|
+
}
|
|
33
|
+
var commentsPolicy = registerProtectionPolicy(
|
|
34
|
+
{
|
|
35
|
+
level: "comments",
|
|
36
|
+
parts: COMMENT_STORY_PARTS,
|
|
37
|
+
rejectedMarkup: "comment-markup-rejected",
|
|
38
|
+
storyKept: commentsStoryKept
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
export {
|
|
42
|
+
commentsPolicy
|
|
43
|
+
};
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
serializeXml,
|
|
8
8
|
W_NS
|
|
9
9
|
} from "../../ooxml/xml.js";
|
|
10
|
-
import {
|
|
10
|
+
import { relatedPartPath } from "../packageParts.js";
|
|
11
11
|
import { COMMENTS_EXTENDED_REL_TYPE, COMMENTS_REL_TYPE } from "./constants.js";
|
|
12
12
|
import { lastBodyParagraph } from "./grammar.js";
|
|
13
13
|
import {
|
|
@@ -43,10 +43,12 @@ function lastParagraphId(comment) {
|
|
|
43
43
|
return last === null ? null : attributeByLocalName(last, "paraId");
|
|
44
44
|
}
|
|
45
45
|
function readCommentExtensions(parts, mainPartPath) {
|
|
46
|
-
const
|
|
47
|
-
|
|
46
|
+
const partPath = relatedPartPath(
|
|
47
|
+
parts,
|
|
48
|
+
mainPartPath,
|
|
49
|
+
COMMENTS_EXTENDED_REL_TYPE
|
|
48
50
|
);
|
|
49
|
-
if (
|
|
51
|
+
if (partPath === null) {
|
|
50
52
|
return {
|
|
51
53
|
partPath: null,
|
|
52
54
|
xml: null,
|
|
@@ -55,7 +57,6 @@ function readCommentExtensions(parts, mainPartPath) {
|
|
|
55
57
|
ordered: []
|
|
56
58
|
};
|
|
57
59
|
}
|
|
58
|
-
const partPath = resolveTarget(mainPartPath, relationship.target);
|
|
59
60
|
const bytes = parts.get(partPath);
|
|
60
61
|
if (!bytes) {
|
|
61
62
|
return {
|
|
@@ -97,11 +98,8 @@ function readComments(parts, mainPartPath) {
|
|
|
97
98
|
extendedHadBom: extensions.hadBom,
|
|
98
99
|
extendedOrdered: extensions.ordered
|
|
99
100
|
};
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
);
|
|
103
|
-
if (!relationship) return { ...NO_COMMENTS, ...aside };
|
|
104
|
-
const partPath = resolveTarget(mainPartPath, relationship.target);
|
|
101
|
+
const partPath = relatedPartPath(parts, mainPartPath, COMMENTS_REL_TYPE);
|
|
102
|
+
if (partPath === null) return { ...NO_COMMENTS, ...aside };
|
|
105
103
|
const bytes = parts.get(partPath);
|
|
106
104
|
if (!bytes) return { ...NO_COMMENTS, partPath, ...aside };
|
|
107
105
|
const { text, hadBom } = decodeUtf8(bytes);
|
|
@@ -2,13 +2,25 @@
|
|
|
2
2
|
* Plans changed comment package parts while preserving untouched XML.
|
|
3
3
|
*/
|
|
4
4
|
import type { Node as PMNode } from "prosemirror-model";
|
|
5
|
-
import {
|
|
5
|
+
import type { PartPlanner } from "../partPlan";
|
|
6
6
|
import type { SessionStore } from "../session";
|
|
7
|
-
|
|
8
|
-
parts: ReadonlyMap<string, Uint8Array>;
|
|
9
|
-
}
|
|
7
|
+
import { type CommentReferenceData, type CommentReplyData } from "./model";
|
|
10
8
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Whether the Comments part has to be rewritten: a comment or reply came, went, or changed, or an
|
|
10
|
+
* entry has to gain the key its thread state hangs off. The export invariants ask this as well, so
|
|
11
|
+
* a part the writer would leave alone is one they do not read.
|
|
13
12
|
*/
|
|
14
|
-
export declare function
|
|
13
|
+
export declare function commentsChanged(doc: PMNode, session: SessionStore): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Why the Comments part cannot be rewritten around its root, or null when it can.
|
|
16
|
+
*
|
|
17
|
+
* The same question stands in the export invariant list, so a refusal the writer raises is one a
|
|
18
|
+
* caller could have read there first, in the same words.
|
|
19
|
+
*/
|
|
20
|
+
export declare function commentsRootProblem(xml: string): string | null;
|
|
21
|
+
/** Why the extended part cannot be rewritten around its root, or null when it can */
|
|
22
|
+
export declare function extensionsRootProblem(xml: string): string | null;
|
|
23
|
+
/** Whether the extended part has to be rewritten: thread state arrived, changed, or went with a deleted comment */
|
|
24
|
+
export declare function extensionsChanged(doc: PMNode, session: SessionStore): boolean;
|
|
25
|
+
export declare function currentCommentBodies(references: ReadonlyMap<string, CommentReferenceData>): ReadonlyMap<string, CommentReferenceData | CommentReplyData>;
|
|
26
|
+
export declare const commentsPlanner: PartPlanner;
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
// src/docx/comments/writing.ts
|
|
2
|
-
import { elementXml
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { elementXml } from "../../ooxml/element.js";
|
|
3
|
+
import { NAMESPACES, wName, xmlnsDecl } from "../../ooxml/names.js";
|
|
4
|
+
import {
|
|
5
|
+
ensureRootDeclarations,
|
|
6
|
+
partRootProblem,
|
|
7
|
+
splicePart
|
|
8
|
+
} from "../../ooxml/partSplice.js";
|
|
5
9
|
import { encodeUtf8 } from "../../ooxml/xml.js";
|
|
6
10
|
import { directoryOf } from "../relationships.js";
|
|
7
|
-
import {
|
|
8
|
-
COMMENTS_CONTENT_TYPE,
|
|
9
|
-
COMMENTS_EXTENDED_CONTENT_TYPE,
|
|
10
|
-
COMMENTS_EXTENDED_REL_TYPE,
|
|
11
|
-
COMMENTS_REL_TYPE,
|
|
12
|
-
CONTENT_TYPES_PATH
|
|
13
|
-
} from "./constants.js";
|
|
14
|
-
import { withContentType } from "./contentTypes.js";
|
|
15
11
|
import {
|
|
16
12
|
arrivedEntries,
|
|
17
13
|
renderCommentBody,
|
|
@@ -21,6 +17,7 @@ import {
|
|
|
21
17
|
import {
|
|
22
18
|
commentReferencesIn
|
|
23
19
|
} from "./model.js";
|
|
20
|
+
import { commentsExtendedPart, commentsPart, peoplePart } from "./parts.js";
|
|
24
21
|
import { planPeoplePart } from "./people.js";
|
|
25
22
|
function needsThreadKey(id, comment, session) {
|
|
26
23
|
return comment.imported && carriesThreadMetadata(comment) && (session.comments.byId.get(id)?.paraId ?? null) === null;
|
|
@@ -77,34 +74,21 @@ function extensionsXml(references, comments, originallyReferenced) {
|
|
|
77
74
|
if (comments.extendedXml === null) {
|
|
78
75
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w15:commentsEx ${xmlnsDecl("w15")}>${pieces.join("")}</w15:commentsEx>`;
|
|
79
76
|
}
|
|
80
|
-
|
|
81
|
-
comments.extendedXml
|
|
77
|
+
return ensureRootDeclarations(
|
|
78
|
+
splicePart(comments.extendedXml, {
|
|
79
|
+
root: EXTENSIONS_ROOT,
|
|
80
|
+
replaceChildren: pieces.join("")
|
|
81
|
+
}),
|
|
82
|
+
{ namespaces: { w15: NAMESPACES.w15 } }
|
|
82
83
|
);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
throw new DocxExportError(
|
|
92
|
-
"malformed-xml",
|
|
93
|
-
"the Comments Extended part has no commentsEx root element"
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
const bodyAt = open.index + open[0].length;
|
|
97
|
-
if (open[0].endsWith("/>")) {
|
|
98
|
-
return comments.extendedXml.slice(0, open.index) + `${open[0].slice(0, -2)}>${pieces.join("")}</${name}>` + comments.extendedXml.slice(bodyAt);
|
|
99
|
-
}
|
|
100
|
-
const close = comments.extendedXml.lastIndexOf(`</${name}>`);
|
|
101
|
-
if (close === -1) {
|
|
102
|
-
throw new DocxExportError(
|
|
103
|
-
"malformed-xml",
|
|
104
|
-
"the Comments Extended part has no closing commentsEx tag"
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
return comments.extendedXml.slice(0, bodyAt) + pieces.join("") + comments.extendedXml.slice(close);
|
|
84
|
+
}
|
|
85
|
+
var COMMENTS_ROOT = "comments";
|
|
86
|
+
var EXTENSIONS_ROOT = "commentsEx";
|
|
87
|
+
function commentsRootProblem(xml) {
|
|
88
|
+
return partRootProblem(xml, COMMENTS_ROOT);
|
|
89
|
+
}
|
|
90
|
+
function extensionsRootProblem(xml) {
|
|
91
|
+
return partRootProblem(xml, EXTENSIONS_ROOT);
|
|
108
92
|
}
|
|
109
93
|
function extensionsChanged(doc, session) {
|
|
110
94
|
const current = commentReferencesIn(doc);
|
|
@@ -136,7 +120,6 @@ function renderedComment(comment, arrivedKeyed, arrived) {
|
|
|
136
120
|
) : comment.commentXml;
|
|
137
121
|
}
|
|
138
122
|
const attrs = [
|
|
139
|
-
xmlnsAttr("w"),
|
|
140
123
|
[wName("id"), comment.id],
|
|
141
124
|
comment.author === null ? null : [wName("author"), comment.author],
|
|
142
125
|
comment.date === null ? null : [wName("date"), comment.date],
|
|
@@ -150,23 +133,11 @@ function renderedComment(comment, arrivedKeyed, arrived) {
|
|
|
150
133
|
[body]
|
|
151
134
|
);
|
|
152
135
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (!/\sxmlns:mc\s*=/.test(updated)) {
|
|
159
|
-
updated = updated.replace(/>$/, ` ${xmlnsDecl("mc")}>`);
|
|
160
|
-
}
|
|
161
|
-
const ignorable = /\smc:Ignorable\s*=\s*(["'])([^"']*)\1/.exec(updated);
|
|
162
|
-
if (!ignorable) {
|
|
163
|
-
return updated.replace(/>$/, ' mc:Ignorable="w14">');
|
|
164
|
-
}
|
|
165
|
-
const tokens = ignorable[2].split(/\s+/).filter(Boolean);
|
|
166
|
-
if (tokens.includes("w14")) return updated;
|
|
167
|
-
const replacement = ` mc:Ignorable=${ignorable[1]}${[...tokens, "w14"].join(" ")}${ignorable[1]}`;
|
|
168
|
-
return updated.slice(0, ignorable.index) + replacement + updated.slice(ignorable.index + ignorable[0].length);
|
|
169
|
-
}
|
|
136
|
+
var COMMENT_MARKUP = { namespaces: { w: NAMESPACES.w } };
|
|
137
|
+
var THREAD_MARKUP = {
|
|
138
|
+
namespaces: { w: NAMESPACES.w, w14: NAMESPACES.w14, mc: NAMESPACES.mc },
|
|
139
|
+
ignorable: ["w14"]
|
|
140
|
+
};
|
|
170
141
|
function currentCommentBodies(references) {
|
|
171
142
|
const comments = /* @__PURE__ */ new Map();
|
|
172
143
|
for (const [id, comment] of references) {
|
|
@@ -224,51 +195,27 @@ function commentsXml(references, comments, originallyReferenced) {
|
|
|
224
195
|
const compatibility = hasThreadMetadata ? ` ${xmlnsDecl("w14")} ${xmlnsDecl("mc")} mc:Ignorable="w14"` : "";
|
|
225
196
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:comments ${xmlnsDecl("w")}${compatibility}>${pieces.join("")}</w:comments>`;
|
|
226
197
|
}
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const close = name ? comments.xml.lastIndexOf(`</${name}>`) : -1;
|
|
236
|
-
if (close === -1) {
|
|
237
|
-
throw new DocxExportError(
|
|
238
|
-
"malformed-xml",
|
|
239
|
-
"the Comments part has no closing comments tag"
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
const openTag = hasThreadMetadata ? withThreadMarkupCompatibility(open[0]) : open[0];
|
|
243
|
-
return comments.xml.slice(0, open.index) + openTag + pieces.join("") + comments.xml.slice(close);
|
|
244
|
-
}
|
|
245
|
-
function availableCommentsPath(session) {
|
|
246
|
-
const directory = directoryOf(session.mainPartPath);
|
|
247
|
-
for (let suffix = 0; ; suffix += 1) {
|
|
248
|
-
const name = suffix === 0 ? "comments.xml" : `comments${suffix + 1}.xml`;
|
|
249
|
-
const path = directory + name;
|
|
250
|
-
if (!session.parts.has(path)) return path;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
function availableCommentsExtendedPath(session) {
|
|
254
|
-
const directory = directoryOf(session.mainPartPath);
|
|
255
|
-
for (let suffix = 0; ; suffix += 1) {
|
|
256
|
-
const name = suffix === 0 ? "commentsExtended.xml" : `commentsExtended${suffix + 1}.xml`;
|
|
257
|
-
const path = directory + name;
|
|
258
|
-
if (!session.parts.has(path)) return path;
|
|
259
|
-
}
|
|
198
|
+
const rewritten = splicePart(comments.xml, {
|
|
199
|
+
root: COMMENTS_ROOT,
|
|
200
|
+
replaceChildren: pieces.join("")
|
|
201
|
+
});
|
|
202
|
+
return ensureRootDeclarations(
|
|
203
|
+
rewritten,
|
|
204
|
+
hasThreadMetadata ? THREAD_MARKUP : COMMENT_MARKUP
|
|
205
|
+
);
|
|
260
206
|
}
|
|
261
|
-
function planCommentParts(doc, session,
|
|
207
|
+
function planCommentParts(doc, session, context) {
|
|
262
208
|
const bodyChanged = commentsChanged(doc, session);
|
|
263
209
|
const threadChanged = extensionsChanged(doc, session);
|
|
264
210
|
if (!bodyChanged && !threadChanged) return null;
|
|
211
|
+
const { relationships, contentTypes } = context;
|
|
265
212
|
const references = commentReferencesIn(doc);
|
|
266
|
-
const addingPart = session
|
|
267
|
-
const partPath =
|
|
213
|
+
const addingPart = commentsPart.pathIn(session) === null;
|
|
214
|
+
const partPath = commentsPart.writePathIn(session);
|
|
268
215
|
const parts = /* @__PURE__ */ new Map();
|
|
269
216
|
if (addingPart) {
|
|
270
217
|
const target = partPath.slice(directoryOf(session.mainPartPath).length);
|
|
271
|
-
relationships.add({ type:
|
|
218
|
+
relationships.add({ type: commentsPart.relType, target });
|
|
272
219
|
}
|
|
273
220
|
if (bodyChanged) {
|
|
274
221
|
parts.set(
|
|
@@ -280,22 +227,16 @@ function planCommentParts(doc, session, relationships, currentContentTypes) {
|
|
|
280
227
|
);
|
|
281
228
|
}
|
|
282
229
|
if (addingPart || session.comments.xml === null) {
|
|
283
|
-
|
|
284
|
-
session.parts,
|
|
285
|
-
partPath,
|
|
286
|
-
COMMENTS_CONTENT_TYPE,
|
|
287
|
-
currentContentTypes
|
|
288
|
-
);
|
|
289
|
-
if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
|
|
230
|
+
contentTypes.addOverride(partPath, commentsPart.contentType);
|
|
290
231
|
}
|
|
291
232
|
if (threadChanged && (references.size > 0 || session.comments.extendedPartPath !== null)) {
|
|
292
|
-
const addingExtendedPart = session
|
|
293
|
-
const extendedPartPath =
|
|
233
|
+
const addingExtendedPart = commentsExtendedPart.pathIn(session) === null;
|
|
234
|
+
const extendedPartPath = commentsExtendedPart.writePathIn(session);
|
|
294
235
|
if (addingExtendedPart) {
|
|
295
236
|
const target = extendedPartPath.slice(
|
|
296
237
|
directoryOf(session.mainPartPath).length
|
|
297
238
|
);
|
|
298
|
-
relationships.add({ type:
|
|
239
|
+
relationships.add({ type: commentsExtendedPart.relType, target });
|
|
299
240
|
}
|
|
300
241
|
parts.set(
|
|
301
242
|
extendedPartPath,
|
|
@@ -309,26 +250,32 @@ function planCommentParts(doc, session, relationships, currentContentTypes) {
|
|
|
309
250
|
)
|
|
310
251
|
);
|
|
311
252
|
if (addingExtendedPart || session.comments.extendedXml === null) {
|
|
312
|
-
|
|
313
|
-
session.parts,
|
|
253
|
+
contentTypes.addOverride(
|
|
314
254
|
extendedPartPath,
|
|
315
|
-
|
|
316
|
-
parts.get(CONTENT_TYPES_PATH) ?? currentContentTypes
|
|
255
|
+
commentsExtendedPart.contentType
|
|
317
256
|
);
|
|
318
|
-
if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
|
|
319
257
|
}
|
|
320
258
|
}
|
|
321
259
|
if (bodyChanged) {
|
|
322
260
|
const people = planPeoplePart(
|
|
261
|
+
peoplePart,
|
|
323
262
|
currentCommentBodies(references).values(),
|
|
324
263
|
session,
|
|
325
|
-
|
|
326
|
-
parts.get(CONTENT_TYPES_PATH) ?? currentContentTypes
|
|
264
|
+
context
|
|
327
265
|
);
|
|
328
266
|
for (const [path, bytes] of people ?? []) parts.set(path, bytes);
|
|
329
267
|
}
|
|
330
|
-
return
|
|
268
|
+
return parts;
|
|
331
269
|
}
|
|
270
|
+
var commentsPlanner = {
|
|
271
|
+
name: "comments",
|
|
272
|
+
plan: planCommentParts
|
|
273
|
+
};
|
|
332
274
|
export {
|
|
333
|
-
|
|
275
|
+
commentsChanged,
|
|
276
|
+
commentsPlanner,
|
|
277
|
+
commentsRootProblem,
|
|
278
|
+
currentCommentBodies,
|
|
279
|
+
extensionsChanged,
|
|
280
|
+
extensionsRootProblem
|
|
334
281
|
};
|
|
@@ -2,3 +2,10 @@
|
|
|
2
2
|
export declare const DEFAULT_TAB_STOP_PT = 36;
|
|
3
3
|
/** Reads the document-wide automatic tab interval from settings.xml. */
|
|
4
4
|
export declare function readDefaultTabStop(settings: Document | null): number | null;
|
|
5
|
+
/** The compatibility settings (`w:compat`) the display reads */
|
|
6
|
+
export interface CompatSettings {
|
|
7
|
+
/** Part 4 §14.8.3.31: no custom tab stop is created at a hanging indent */
|
|
8
|
+
noTabHangInd: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const NO_COMPAT: CompatSettings;
|
|
11
|
+
export declare function readCompatSettings(settings: Document | null): CompatSettings;
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
// src/docx/documentSettings.ts
|
|
2
|
-
import {
|
|
2
|
+
import { ST_TwipsMeasure } from "../ooxml/simpleTypes.js";
|
|
3
|
+
import { isOn, twipsToPt, wAttr } from "../ooxml/units.js";
|
|
3
4
|
import { childByLocalName } from "../ooxml/xml.js";
|
|
4
5
|
var DEFAULT_TAB_STOP_PT = 36;
|
|
5
6
|
function readDefaultTabStop(settings) {
|
|
6
7
|
if (!settings) return null;
|
|
7
8
|
const setting = childByLocalName(settings.documentElement, "defaultTabStop");
|
|
8
|
-
const value = setting ? twipsToPt(wAttr(setting, "val")) : null;
|
|
9
|
+
const value = setting ? twipsToPt(ST_TwipsMeasure.parse(wAttr(setting, "val"))) : null;
|
|
9
10
|
return value !== null && value > 0 ? value : null;
|
|
10
11
|
}
|
|
12
|
+
var NO_COMPAT = { noTabHangInd: false };
|
|
13
|
+
function readCompatSettings(settings) {
|
|
14
|
+
const compat = settings ? childByLocalName(settings.documentElement, "compat") : null;
|
|
15
|
+
return { noTabHangInd: compat !== null && isOn(compat, "noTabHangInd") };
|
|
16
|
+
}
|
|
11
17
|
export {
|
|
12
18
|
DEFAULT_TAB_STOP_PT,
|
|
19
|
+
NO_COMPAT,
|
|
20
|
+
readCompatSettings,
|
|
13
21
|
readDefaultTabStop
|
|
14
22
|
};
|
|
@@ -1,15 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Turns the edited document back into docx bytes.
|
|
3
3
|
*
|
|
4
|
-
* The body (document.xml) is always rebuilt from preserved and edited blocks.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The body (document.xml) is always rebuilt from preserved and edited blocks. Every other part is
|
|
5
|
+
* written by a planner (`./partPlan`) that answers only when the document gives it something to
|
|
6
|
+
* write: numbering.xml when a list was newly started, the comment parts when comments changed,
|
|
7
|
+
* media parts when an image was inserted. Content types and relationships change only when one
|
|
8
|
+
* of those additions declares itself through the context every planner shares.
|
|
8
9
|
*
|
|
9
10
|
* The body is written before that relationships part, because a link asks for its relationship as
|
|
10
11
|
* it is written (`docx/hyperlink`), and both writers hand out ids through the one writer so that
|
|
11
12
|
* they cannot pick the same one.
|
|
12
13
|
*/
|
|
13
14
|
import type { Node as PMNode } from "prosemirror-model";
|
|
15
|
+
import { type XmlParser } from "../ooxml/xml";
|
|
16
|
+
import { type FidelityNote } from "./fidelity";
|
|
17
|
+
import { type PartPlanner } from "./partPlan";
|
|
14
18
|
import { type DocxSession } from "./session";
|
|
15
|
-
|
|
19
|
+
/** What a caller may say about a write beyond handing over the document and its session */
|
|
20
|
+
export interface ExportOptions {
|
|
21
|
+
/**
|
|
22
|
+
* The parser the original XML kept in the session is read back through. Left out, the
|
|
23
|
+
* `DOMParser` global is used, and a runtime carrying none refuses the write with
|
|
24
|
+
* `no-xml-parser`.
|
|
25
|
+
*/
|
|
26
|
+
xmlParser?: XmlParser;
|
|
27
|
+
}
|
|
28
|
+
export declare function exportDocx(doc: PMNode, session: DocxSession, options?: ExportOptions): Uint8Array;
|
|
29
|
+
/**
|
|
30
|
+
* The file to write, and what writing it could not carry across as it stood.
|
|
31
|
+
*
|
|
32
|
+
* The notes are the ones `documentFidelity` reads off the same document, followed by whatever the
|
|
33
|
+
* writer had to approximate on the way out. A host that hands a file to somebody else can say what
|
|
34
|
+
* that file no longer holds without opening it again.
|
|
35
|
+
*
|
|
36
|
+
* The first problem `exportProblems` reports is thrown before anything is written, so a refusal a
|
|
37
|
+
* caller could have asked about ahead of time arrives with the same code and message it would
|
|
38
|
+
* have read there.
|
|
39
|
+
*/
|
|
40
|
+
export declare function exportDocxReport(doc: PMNode, session: DocxSession, options?: ExportOptions): {
|
|
41
|
+
bytes: Uint8Array;
|
|
42
|
+
notes: FidelityNote[];
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The same export, folding a planner list of the caller's choosing in place of `PART_PLANNERS`.
|
|
46
|
+
*
|
|
47
|
+
* On no entry point. No document can make a correct planner write a part that does not read back,
|
|
48
|
+
* so this is how a test hands the fold such a planner and watches the export refuse it.
|
|
49
|
+
*/
|
|
50
|
+
export declare function exportThroughPlanners(planners: readonly PartPlanner[], doc: PMNode, session: DocxSession, options?: ExportOptions): Uint8Array;
|