@portone/docx-editor 0.2.0 → 0.3.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 +174 -0
- package/CONTRIBUTING.md +9 -1
- package/dist/DocxEditor.d.ts +6 -0
- package/dist/DocxEditor.js +12 -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 +14 -7
- package/dist/docx/commentOnlyChange.js +9 -139
- package/dist/docx/comments/constants.d.ts +3 -4
- package/dist/docx/comments/constants.js +4 -5
- package/dist/docx/comments/grammar.d.ts +86 -0
- package/dist/docx/comments/grammar.js +223 -0
- package/dist/docx/comments/parts.d.ts +52 -0
- package/dist/docx/comments/parts.js +279 -0
- package/dist/docx/comments/people.d.ts +11 -2
- package/dist/docx/comments/people.js +28 -106
- package/dist/docx/comments/policy.d.ts +7 -0
- package/dist/docx/comments/policy.js +43 -0
- package/dist/docx/comments/reading.d.ts +5 -3
- package/dist/docx/comments/reading.js +30 -29
- package/dist/docx/comments/writing.d.ts +19 -7
- package/dist/docx/comments/writing.js +105 -137
- 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 +71 -72
- 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 +27 -0
- package/dist/docx/formatting/attrs.js +31 -0
- package/dist/docx/formatting/context.d.ts +31 -0
- package/dist/docx/formatting/context.js +42 -0
- package/dist/docx/formatting/direct.d.ts +6 -5
- package/dist/docx/formatting/direct.js +52 -81
- package/dist/docx/formatting/resolve.d.ts +45 -0
- package/dist/docx/formatting/resolve.js +140 -0
- package/dist/docx/formatting/runProperties.d.ts +93 -0
- package/dist/docx/formatting/runProperties.js +316 -0
- package/dist/docx/formatting/styles.js +3 -3
- 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 +13 -22
- 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 +72 -79
- package/dist/docx/importParagraph.d.ts +1 -1
- package/dist/docx/importParagraph.js +4 -3
- package/dist/docx/importTable.d.ts +1 -1
- package/dist/docx/importTable.js +17 -1
- package/dist/docx/invariants.d.ts +33 -0
- package/dist/docx/invariants.js +256 -0
- package/dist/docx/media.d.ts +6 -4
- package/dist/docx/media.js +6 -37
- package/dist/docx/newLists.d.ts +20 -0
- package/dist/docx/newLists.js +36 -0
- package/dist/docx/notes.js +6 -12
- package/dist/docx/numberingPlanner.d.ts +8 -0
- package/dist/docx/numberingPlanner.js +19 -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 +75 -99
- 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 +15 -15
- 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 +14 -37
- 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 +9 -7
- package/dist/docx/serializeParagraph.d.ts +2 -1
- package/dist/docx/serializeParagraph.js +25 -14
- package/dist/docx/serializeTable.js +63 -32
- package/dist/docx/session.d.ts +42 -14
- package/dist/docx/session.js +43 -17
- package/dist/docx/storyProjection.d.ts +36 -0
- package/dist/docx/storyProjection.js +23 -0
- package/dist/docx/tableFormatting/editing.js +130 -185
- package/dist/docx/tableFormatting/reading.d.ts +16 -6
- package/dist/docx/tableFormatting/reading.js +40 -20
- package/dist/docx/tableTemplate.js +37 -5
- package/dist/docx/theme.d.ts +0 -6
- package/dist/docx/theme.js +0 -8
- package/dist/download.d.ts +8 -5
- package/dist/download.js +2 -0
- package/dist/editor/clipboard/images.js +17 -3
- package/dist/editor/clipboard/inlineFormatting.d.ts +7 -0
- package/dist/editor/clipboard/inlineFormatting.js +20 -30
- package/dist/editor/commands/breakCommands.js +4 -3
- package/dist/editor/commands/canRunCommand.d.ts +2 -2
- package/dist/editor/commands/canRunCommand.js +1 -1
- package/dist/editor/commands/comments/editing.d.ts +6 -2
- package/dist/editor/commands/comments/editing.js +21 -36
- 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 +103 -0
- package/dist/editor/commands/formatting/shared.d.ts +3 -3
- package/dist/editor/commands/formatting/shared.js +5 -2
- package/dist/editor/commands/historyCommands.js +2 -1
- 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.js +8 -10
- package/dist/editor/commands/lockCommands.d.ts +7 -1
- package/dist/editor/commands/lockCommands.js +35 -37
- package/dist/editor/commands/paragraphCommands.js +28 -31
- package/dist/editor/commands/spacingCommands.js +1 -1
- package/dist/editor/commands/tabCommands.js +4 -3
- package/dist/editor/createEditor.d.ts +17 -29
- package/dist/editor/createEditor.js +61 -67
- package/dist/editor/documentStyles.d.ts +11 -35
- package/dist/editor/documentStyles.js +9 -52
- package/dist/editor/editorDocument.d.ts +56 -0
- package/dist/editor/editorDocument.js +74 -0
- package/dist/editor/externalClipboard.js +166 -33
- package/dist/editor/insertImage.js +4 -3
- package/dist/editor/insertTable.js +4 -3
- package/dist/editor/paragraphEdits.d.ts +11 -18
- package/dist/editor/paragraphEdits.js +7 -16
- package/dist/editor/plugins/displayDerivation.d.ts +47 -0
- package/dist/editor/plugins/displayDerivation.js +78 -0
- package/dist/editor/plugins/documentProtection.d.ts +3 -3
- package/dist/editor/plugins/imagePaste.js +4 -3
- package/dist/editor/plugins/keymap.js +18 -3
- package/dist/editor/plugins/lockedContent.d.ts +4 -4
- package/dist/editor/plugins/lockedContent.js +1 -1
- package/dist/editor/plugins/numberingDecorations.d.ts +5 -11
- package/dist/editor/plugins/numberingDecorations.js +7 -17
- package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
- package/dist/editor/plugins/paragraphDisplay.js +51 -0
- package/dist/editor/plugins/tabLayout.js +1 -1
- package/dist/editor/plugins/tableDisplay.d.ts +6 -0
- package/dist/editor/plugins/tableDisplay.js +16 -0
- package/dist/index.d.ts +2 -0
- package/dist/model/format.d.ts +30 -8
- package/dist/model/format.js +35 -22
- package/dist/model/tabStops.d.ts +9 -0
- package/dist/model/tabStops.js +18 -0
- package/dist/numbering/listTemplate.js +49 -10
- package/dist/numbering/parseNumbering.d.ts +14 -1
- package/dist/numbering/parseNumbering.js +35 -22
- package/dist/numbering/writeNumbering.d.ts +3 -4
- package/dist/numbering/writeNumbering.js +14 -25
- package/dist/ooxml/childOrder.d.ts +34 -0
- package/dist/ooxml/childOrder.js +496 -0
- package/dist/ooxml/element.d.ts +65 -0
- package/dist/ooxml/element.js +68 -0
- package/dist/ooxml/errors.d.ts +3 -2
- package/dist/ooxml/fragment.d.ts +53 -0
- package/dist/ooxml/fragment.js +76 -0
- package/dist/ooxml/image.d.ts +4 -0
- package/dist/ooxml/image.js +3 -5
- package/dist/ooxml/names.d.ts +27 -0
- package/dist/ooxml/names.js +29 -0
- package/dist/ooxml/partSplice.d.ts +67 -0
- package/dist/ooxml/partSplice.js +169 -0
- package/dist/ooxml/precedence.d.ts +31 -0
- package/dist/ooxml/precedence.js +51 -0
- package/dist/ooxml/props.d.ts +112 -0
- package/dist/ooxml/props.js +214 -0
- 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 +52 -0
- package/dist/ooxml/xml.js +64 -5
- package/dist/page/blockKinds.d.ts +103 -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 -1
- package/dist/page/measureBlocks.js +24 -25
- package/dist/page/pageDecorations.d.ts +27 -28
- package/dist/page/pageDecorations.js +70 -151
- package/dist/page/pageLayout.d.ts +10 -62
- package/dist/page/pageLayout.js +60 -53
- package/dist/page/usePageLayout.d.ts +2 -2
- package/dist/page/usePageLayout.js +3 -11
- package/dist/schema/attrRoles.d.ts +42 -0
- package/dist/schema/attrRoles.js +141 -0
- package/dist/schema/displayDerivation.d.ts +82 -0
- package/dist/schema/displayDerivation.js +130 -0
- package/dist/schema/docxSchema.d.ts +9 -0
- package/dist/schema/docxSchema.js +237 -114
- package/dist/schema/editGuard.d.ts +99 -0
- package/dist/schema/editGuard.js +43 -0
- package/dist/schema/guards.d.ts +91 -0
- package/dist/schema/guards.js +108 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/locks.d.ts +17 -77
- package/dist/schema/locks.js +26 -70
- package/dist/schema/preservedGuards.d.ts +50 -0
- package/dist/schema/preservedGuards.js +80 -0
- package/dist/schema/protection.d.ts +17 -4
- package/dist/schema/protection.js +4 -2
- package/dist/schema/sourceEquality.d.ts +19 -0
- package/dist/schema/sourceEquality.js +39 -0
- package/dist/styles/inlineStyle.js +15 -6
- package/dist/table/cellFormatting.d.ts +8 -1
- package/dist/table/cellFormatting.js +10 -17
- package/dist/table/commands.d.ts +2 -2
- 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 +14 -16
- package/dist/table/gridBorders.js +3 -41
- package/dist/table/index.d.ts +2 -2
- package/dist/table/merge.d.ts +4 -8
- package/dist/table/merge.js +5 -5
- package/package.json +10 -3
- package/dist/docx/comments/contentTypes.d.ts +0 -7
- package/dist/docx/comments/contentTypes.js +0 -38
- package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
- package/dist/docx/formatting/effectiveParagraph.js +0 -81
- package/dist/docx/propsXml.d.ts +0 -49
- package/dist/docx/propsXml.js +0 -302
- package/dist/docx/uniqueControls.d.ts +0 -14
- package/dist/docx/uniqueControls.js +0 -62
- package/dist/editor/plugins/bookmarkProtection.d.ts +0 -3
- package/dist/editor/plugins/bookmarkProtection.js +0 -28
- package/dist/editor/plugins/commentReservations.d.ts +0 -5
- package/dist/editor/plugins/commentReservations.js +0 -26
- package/dist/editor/plugins/noteProtection.d.ts +0 -3
- package/dist/editor/plugins/noteProtection.js +0 -25
- package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
- package/dist/editor/plugins/styledParagraphs.js +0 -65
- package/dist/page/tableMeasurements.d.ts +0 -10
- package/dist/page/tableMeasurements.js +0 -115
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// src/docx/identities.ts
|
|
2
|
+
import { Fragment } from "prosemirror-model";
|
|
3
|
+
import { DocxExportError } from "../ooxml/errors.js";
|
|
4
|
+
import { qualify } from "../ooxml/names.js";
|
|
5
|
+
import { parseAttrs } from "../ooxml/tagScan.js";
|
|
6
|
+
import { docxSchema } from "../schema/index.js";
|
|
7
|
+
import { withoutParagraphIds } from "./cloning.js";
|
|
8
|
+
import { copiedControlPrefix, newControlId } from "./sdt.js";
|
|
9
|
+
var sourceBlockRule = {
|
|
10
|
+
name: "sourceBlock",
|
|
11
|
+
visit(block, written) {
|
|
12
|
+
const srcId = block.attrs.srcId;
|
|
13
|
+
if (typeof srcId !== "string" && typeof srcId !== "number") return block;
|
|
14
|
+
const name = String(srcId);
|
|
15
|
+
if (!written.has(name)) {
|
|
16
|
+
written.add(name);
|
|
17
|
+
return block;
|
|
18
|
+
}
|
|
19
|
+
if (block.type.isInGroup("preserved")) return null;
|
|
20
|
+
return block.type.create(
|
|
21
|
+
{ ...block.attrs, srcId: null },
|
|
22
|
+
block.content,
|
|
23
|
+
block.marks
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var PARA_ID = qualify("w14", "paraId");
|
|
28
|
+
var LONG_HEX = /^[0-9A-Fa-f]{8}$/;
|
|
29
|
+
function paragraphIdOf(pAttrs) {
|
|
30
|
+
if (typeof pAttrs !== "string") return null;
|
|
31
|
+
const value = parseAttrs(pAttrs)?.find(([name]) => name === PARA_ID)?.[1];
|
|
32
|
+
if (value === void 0 || !LONG_HEX.test(value)) return null;
|
|
33
|
+
const id = Number.parseInt(value, 16);
|
|
34
|
+
return id > 0 && id < 2147483648 ? id : null;
|
|
35
|
+
}
|
|
36
|
+
var paragraphIdRule = {
|
|
37
|
+
name: "paragraphId",
|
|
38
|
+
visit(block, written) {
|
|
39
|
+
if (block.type !== docxSchema.nodes.paragraph) return block;
|
|
40
|
+
const id = paragraphIdOf(block.attrs.pAttrs);
|
|
41
|
+
if (id === null) return block;
|
|
42
|
+
const name = String(id);
|
|
43
|
+
if (!written.has(name)) {
|
|
44
|
+
written.add(name);
|
|
45
|
+
return block;
|
|
46
|
+
}
|
|
47
|
+
return block.type.create(
|
|
48
|
+
{ ...block.attrs, pAttrs: withoutParagraphIds(block.attrs.pAttrs) },
|
|
49
|
+
block.content,
|
|
50
|
+
block.marks
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
function sdtMarkOf(node) {
|
|
55
|
+
return node.marks.find((mark) => mark.type === docxSchema.marks.sdt) ?? null;
|
|
56
|
+
}
|
|
57
|
+
function controlName(mark) {
|
|
58
|
+
const key = mark.attrs.sdtKey;
|
|
59
|
+
const prefix = mark.attrs.sdtPrefix;
|
|
60
|
+
return `${typeof key === "number" ? key : 0} ${typeof prefix === "string" ? prefix : ""}`;
|
|
61
|
+
}
|
|
62
|
+
function copiedMark(mark) {
|
|
63
|
+
const prefix = mark.attrs.sdtPrefix;
|
|
64
|
+
if (typeof prefix !== "string") return mark;
|
|
65
|
+
return mark.type.create({
|
|
66
|
+
...mark.attrs,
|
|
67
|
+
sdtPrefix: copiedControlPrefix(prefix, newControlId())
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function claim(mark, written) {
|
|
71
|
+
const name = controlName(mark);
|
|
72
|
+
const copy = written.has(name) ? copiedMark(mark) : null;
|
|
73
|
+
written.add(name);
|
|
74
|
+
return { mark, copy };
|
|
75
|
+
}
|
|
76
|
+
function rewriteParagraph(paragraph, written) {
|
|
77
|
+
const inline = [];
|
|
78
|
+
let running = null;
|
|
79
|
+
let renamed = false;
|
|
80
|
+
paragraph.forEach((child) => {
|
|
81
|
+
const mark = sdtMarkOf(child);
|
|
82
|
+
if (!mark) {
|
|
83
|
+
running = null;
|
|
84
|
+
inline.push(child);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const control = running?.mark.eq(mark) ? running : claim(mark, written);
|
|
88
|
+
running = control;
|
|
89
|
+
if (!control.copy) {
|
|
90
|
+
inline.push(child);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
renamed = true;
|
|
94
|
+
inline.push(
|
|
95
|
+
child.mark(control.copy.addToSet(mark.removeFromSet(child.marks)))
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
return renamed ? paragraph.copy(Fragment.fromArray(inline)) : paragraph;
|
|
99
|
+
}
|
|
100
|
+
var controlRule = {
|
|
101
|
+
name: "control",
|
|
102
|
+
visit(block, written) {
|
|
103
|
+
return block.type === docxSchema.nodes.paragraph ? rewriteParagraph(block, written) : block;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var IDENTITY_RULES = [
|
|
107
|
+
sourceBlockRule,
|
|
108
|
+
paragraphIdRule,
|
|
109
|
+
controlRule
|
|
110
|
+
];
|
|
111
|
+
function refusalOf(block, pos) {
|
|
112
|
+
return {
|
|
113
|
+
code: "unsupported-content",
|
|
114
|
+
message: `a preserved block stands in two places (${block.type.name})`,
|
|
115
|
+
pos
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function visitBlock(block, pos, walk) {
|
|
119
|
+
let current = block;
|
|
120
|
+
for (const [index, rule] of walk.rules.entries()) {
|
|
121
|
+
const next = rule.visit(current, walk.written[index]);
|
|
122
|
+
if (next === null) {
|
|
123
|
+
walk.refuse(refusalOf(block, pos));
|
|
124
|
+
return current;
|
|
125
|
+
}
|
|
126
|
+
current = next;
|
|
127
|
+
}
|
|
128
|
+
return current;
|
|
129
|
+
}
|
|
130
|
+
function rewriteBlock(block, pos, walk) {
|
|
131
|
+
const visited = visitBlock(block, pos, walk);
|
|
132
|
+
if (visited.inlineContent || visited.childCount === 0) return visited;
|
|
133
|
+
const children = [];
|
|
134
|
+
let changed = false;
|
|
135
|
+
visited.forEach((child, offset) => {
|
|
136
|
+
const next = rewriteBlock(child, pos + 1 + offset, walk);
|
|
137
|
+
changed ||= next !== child;
|
|
138
|
+
children.push(next);
|
|
139
|
+
});
|
|
140
|
+
return changed ? visited.copy(Fragment.fromArray(children)) : visited;
|
|
141
|
+
}
|
|
142
|
+
function walkBlocks(doc, rules, refuse) {
|
|
143
|
+
const walk = {
|
|
144
|
+
rules,
|
|
145
|
+
written: rules.map(() => /* @__PURE__ */ new Set()),
|
|
146
|
+
refuse
|
|
147
|
+
};
|
|
148
|
+
const blocks = [];
|
|
149
|
+
let changed = false;
|
|
150
|
+
doc.forEach((block, offset) => {
|
|
151
|
+
const next = rewriteBlock(block, offset, walk);
|
|
152
|
+
changed ||= next !== block;
|
|
153
|
+
blocks.push(next);
|
|
154
|
+
});
|
|
155
|
+
return changed ? doc.copy(Fragment.fromArray(blocks)) : doc;
|
|
156
|
+
}
|
|
157
|
+
function withUniqueIdentities(doc, rules = IDENTITY_RULES) {
|
|
158
|
+
return walkBlocks(doc, rules, (problem) => {
|
|
159
|
+
throw new DocxExportError(problem.code, problem.message);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function identityProblems(doc, rules = IDENTITY_RULES) {
|
|
163
|
+
const problems = [];
|
|
164
|
+
walkBlocks(doc, rules, (problem) => problems.push(problem));
|
|
165
|
+
return problems;
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
IDENTITY_RULES,
|
|
169
|
+
controlRule,
|
|
170
|
+
identityProblems,
|
|
171
|
+
paragraphIdRule,
|
|
172
|
+
sourceBlockRule,
|
|
173
|
+
withUniqueIdentities
|
|
174
|
+
};
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* This module knows nothing about the screen. All it knows is the file and the document model.
|
|
5
5
|
*/
|
|
6
6
|
import { type Node as PMNode } from "prosemirror-model";
|
|
7
|
+
import { type XmlParser } from "../ooxml/xml";
|
|
8
|
+
import { type FidelityNote } from "./fidelity";
|
|
7
9
|
import { SessionStore } from "./session";
|
|
8
10
|
/** A docx file as bytes, however it arrived (file input, fetch, filesystem) */
|
|
9
11
|
export type DocxBytes = ArrayBuffer | Uint8Array;
|
|
@@ -15,7 +17,16 @@ export type DocxBytes = ArrayBuffer | Uint8Array;
|
|
|
15
17
|
* engine on `./core` stays synchronous and bytes-only.
|
|
16
18
|
*/
|
|
17
19
|
export type DocxSource = DocxBytes | Blob;
|
|
18
|
-
|
|
20
|
+
/** What a caller may say about a read beyond handing over the bytes */
|
|
21
|
+
export interface ImportOptions {
|
|
22
|
+
/**
|
|
23
|
+
* The parser every part of the package is read through. Left out, the `DOMParser` global is
|
|
24
|
+
* used, and a runtime carrying none refuses the read with `no-xml-parser`.
|
|
25
|
+
*/
|
|
26
|
+
xmlParser?: XmlParser;
|
|
27
|
+
}
|
|
28
|
+
export declare function importDocx(input: DocxBytes, options?: ImportOptions): {
|
|
19
29
|
doc: PMNode;
|
|
20
30
|
session: SessionStore;
|
|
31
|
+
notes: FidelityNote[];
|
|
21
32
|
};
|
package/dist/docx/importDocx.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// src/docx/importDocx.ts
|
|
2
2
|
import { Fragment } from "prosemirror-model";
|
|
3
|
-
import { toRunFormat } from "../model/format.js";
|
|
4
3
|
import { parseNumbering } from "../numbering/parseNumbering.js";
|
|
5
4
|
import { DocxImportError } from "../ooxml/errors.js";
|
|
6
5
|
import {
|
|
@@ -9,24 +8,26 @@ import {
|
|
|
9
8
|
elementChildren,
|
|
10
9
|
localPart,
|
|
11
10
|
parseXml,
|
|
12
|
-
R_NS
|
|
11
|
+
R_NS,
|
|
12
|
+
withXmlParser
|
|
13
13
|
} from "../ooxml/xml.js";
|
|
14
14
|
import { docxSchema } from "../schema/index.js";
|
|
15
15
|
import { commentReferencesIn, readComments } from "./comments.js";
|
|
16
16
|
import { openParts } from "./container.js";
|
|
17
|
-
import { DEFAULT_TAB_STOP_PT, readDefaultTabStop } from "./documentSettings.js";
|
|
18
17
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
DEFAULT_TAB_STOP_PT,
|
|
19
|
+
readCompatSettings,
|
|
20
|
+
readDefaultTabStop
|
|
21
|
+
} from "./documentSettings.js";
|
|
22
|
+
import { fidelityNotesOf } from "./fidelity.js";
|
|
23
|
+
import {
|
|
24
|
+
formattingContextOf,
|
|
24
25
|
NO_DOCUMENT_DEFAULTS,
|
|
25
|
-
|
|
26
|
-
readDefaultParagraphFormat,
|
|
26
|
+
paragraphAttrsOf,
|
|
27
27
|
readDocumentDefaults,
|
|
28
28
|
readParagraphStyles,
|
|
29
|
-
|
|
29
|
+
resolveParagraph,
|
|
30
|
+
runMarkUnder
|
|
30
31
|
} from "./formatting.js";
|
|
31
32
|
import { readHeadersFooters } from "./headersFooters.js";
|
|
32
33
|
import { readLinkTargets } from "./hyperlink.js";
|
|
@@ -34,28 +35,26 @@ import { buildParagraph } from "./importParagraph.js";
|
|
|
34
35
|
import { buildTable } from "./importTable.js";
|
|
35
36
|
import { readImageSources } from "./media.js";
|
|
36
37
|
import { readNotes } from "./notes.js";
|
|
38
|
+
import { readPart, relatedPartPath } from "./packageParts.js";
|
|
37
39
|
import { readBodyGeometry } from "./pageGeometry.js";
|
|
38
|
-
import {
|
|
40
|
+
import { readRelationships } from "./relationships.js";
|
|
39
41
|
import { scanBody } from "./scan.js";
|
|
40
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
BODY_STORY_KEY,
|
|
44
|
+
blockKey,
|
|
45
|
+
newSessionId,
|
|
46
|
+
SessionStore
|
|
47
|
+
} from "./session.js";
|
|
41
48
|
import { NO_THEME_FONTS, readThemeFonts } from "./theme.js";
|
|
42
49
|
var OFFICE_DOCUMENT_REL = `${R_NS}/officeDocument`;
|
|
43
50
|
var STYLES_REL = `${R_NS}/styles`;
|
|
44
51
|
var NUMBERING_REL = `${R_NS}/numbering`;
|
|
45
52
|
var THEME_REL = `${R_NS}/theme`;
|
|
46
53
|
var SETTINGS_REL = `${R_NS}/settings`;
|
|
47
|
-
function relationshipTarget(parts, relsPath, type) {
|
|
48
|
-
const rels = parts.get(relsPath);
|
|
49
|
-
if (!rels) return null;
|
|
50
|
-
for (const rel of elementChildren(
|
|
51
|
-
parseXml(decodeUtf8(rels).text).documentElement
|
|
52
|
-
)) {
|
|
53
|
-
if (rel.getAttribute("Type") === type) return rel.getAttribute("Target");
|
|
54
|
-
}
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
54
|
function findMainPartPath(parts) {
|
|
58
|
-
const target =
|
|
55
|
+
const target = readRelationships(parts, "_rels/.rels").find(
|
|
56
|
+
(rel) => rel.type === OFFICE_DOCUMENT_REL
|
|
57
|
+
)?.target;
|
|
59
58
|
if (!target) {
|
|
60
59
|
throw new DocxImportError(
|
|
61
60
|
"missing-part",
|
|
@@ -64,22 +63,7 @@ function findMainPartPath(parts) {
|
|
|
64
63
|
}
|
|
65
64
|
return target.replace(/^\//, "");
|
|
66
65
|
}
|
|
67
|
-
function
|
|
68
|
-
const directory = mainPartPath.replace(/[^/]+$/, "");
|
|
69
|
-
const fileName = mainPartPath.slice(directory.length);
|
|
70
|
-
const target = relationshipTarget(
|
|
71
|
-
parts,
|
|
72
|
-
`${directory}_rels/${fileName}.rels`,
|
|
73
|
-
type
|
|
74
|
-
);
|
|
75
|
-
if (!target) return null;
|
|
76
|
-
return resolveTarget(mainPartPath, target);
|
|
77
|
-
}
|
|
78
|
-
function readPart(parts, path) {
|
|
79
|
-
const bytes = path === null ? void 0 : parts.get(path);
|
|
80
|
-
return bytes ? decodeUtf8(bytes).text : null;
|
|
81
|
-
}
|
|
82
|
-
function buildBlock(el, srcId, sources, styles, defaultTableStyleId) {
|
|
66
|
+
function buildBlock(el, srcId, sources, context) {
|
|
83
67
|
if (el.localName === "bookmarkStart" || el.localName === "bookmarkEnd") {
|
|
84
68
|
return docxSchema.nodes.bookmarkBlock.create({
|
|
85
69
|
srcId,
|
|
@@ -91,27 +75,34 @@ function buildBlock(el, srcId, sources, styles, defaultTableStyleId) {
|
|
|
91
75
|
if (paragraph) return paragraph;
|
|
92
76
|
}
|
|
93
77
|
if (el.localName === "tbl") {
|
|
94
|
-
const table = buildTable(
|
|
78
|
+
const table = buildTable(
|
|
79
|
+
el,
|
|
80
|
+
srcId,
|
|
81
|
+
sources,
|
|
82
|
+
context.styles,
|
|
83
|
+
context.defaultTableStyleId
|
|
84
|
+
);
|
|
95
85
|
if (table) return table;
|
|
96
86
|
}
|
|
97
87
|
return docxSchema.nodes.docxRaw.create({ srcId, name: el.nodeName });
|
|
98
88
|
}
|
|
99
|
-
function styledInline(node, style) {
|
|
100
|
-
const mark = node.marks.find((entry) => entry.type === docxSchema.marks.run);
|
|
101
|
-
if (!mark) return node;
|
|
102
|
-
const format = layerRunFormat(style, toRunFormat(mark.attrs.format));
|
|
103
|
-
const next = mark.type.create({ ...mark.attrs, format });
|
|
104
|
-
return node.mark(next.addToSet(node.marks));
|
|
105
|
-
}
|
|
106
89
|
function styledParagraph(node, context) {
|
|
107
|
-
const
|
|
108
|
-
const
|
|
90
|
+
const pPr = node.attrs.pPr;
|
|
91
|
+
const paragraph = resolveParagraph(
|
|
92
|
+
typeof pPr === "string" ? pPr : null,
|
|
93
|
+
context
|
|
94
|
+
);
|
|
95
|
+
const inline = node.children.map((child) => {
|
|
96
|
+
const mark = runMarkUnder(
|
|
97
|
+
child.marks.find((entry) => entry.type === docxSchema.marks.run) ?? null,
|
|
98
|
+
child.isText,
|
|
99
|
+
paragraph,
|
|
100
|
+
context
|
|
101
|
+
);
|
|
102
|
+
return mark ? child.mark(mark.addToSet(child.marks)) : child;
|
|
103
|
+
});
|
|
109
104
|
return node.type.create(
|
|
110
|
-
{
|
|
111
|
-
...node.attrs,
|
|
112
|
-
format: effectiveParagraphFormat(node.attrs.pPr, context),
|
|
113
|
-
styleRun: style ? layerRunFormat(style.run, null) : null
|
|
114
|
-
},
|
|
105
|
+
{ ...node.attrs, ...paragraphAttrsOf(paragraph) },
|
|
115
106
|
Fragment.fromArray(inline),
|
|
116
107
|
node.marks
|
|
117
108
|
);
|
|
@@ -153,7 +144,10 @@ function foldTrailingSectPr(scan) {
|
|
|
153
144
|
suffix: last.xml + scan.suffix
|
|
154
145
|
};
|
|
155
146
|
}
|
|
156
|
-
function importDocx(input) {
|
|
147
|
+
function importDocx(input, options) {
|
|
148
|
+
return withXmlParser(options?.xmlParser, () => readDocx(input));
|
|
149
|
+
}
|
|
150
|
+
function readDocx(input) {
|
|
157
151
|
const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
158
152
|
const parts = openParts(bytes);
|
|
159
153
|
const mainPartPath = findMainPartPath(parts);
|
|
@@ -182,25 +176,21 @@ function importDocx(input) {
|
|
|
182
176
|
parts,
|
|
183
177
|
relatedPartPath(parts, mainPartPath, SETTINGS_REL)
|
|
184
178
|
);
|
|
185
|
-
const
|
|
179
|
+
const settingsDom = settingsXml === null ? null : parseXml(settingsXml);
|
|
180
|
+
const defaultTabStopPt = readDefaultTabStop(settingsDom) ?? DEFAULT_TAB_STOP_PT;
|
|
186
181
|
const numberingPartPath = relatedPartPath(parts, mainPartPath, NUMBERING_REL);
|
|
187
182
|
const themeXml = readPart(
|
|
188
183
|
parts,
|
|
189
184
|
relatedPartPath(parts, mainPartPath, THEME_REL)
|
|
190
185
|
);
|
|
191
186
|
const themeFonts = themeXml === null ? NO_THEME_FONTS : readThemeFonts(parseXml(themeXml));
|
|
192
|
-
const styles = stylesDom ? readStyles(stylesDom, themeFonts) : NO_STYLES;
|
|
193
|
-
const defaultTableStyleId = stylesDom ? defaultTableStyleIdOf(stylesDom) : null;
|
|
194
|
-
const defaultParagraphStyleId = stylesDom ? defaultParagraphStyleIdOf(stylesDom) : null;
|
|
195
|
-
const paragraphDefaults = stylesDom ? readDefaultParagraphFormat(stylesDom) : {};
|
|
196
187
|
const numberingXml = readPart(parts, numberingPartPath);
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
};
|
|
188
|
+
const formatting = formattingContextOf(
|
|
189
|
+
stylesDom,
|
|
190
|
+
parseNumbering(numberingXml),
|
|
191
|
+
themeFonts,
|
|
192
|
+
readCompatSettings(settingsDom)
|
|
193
|
+
);
|
|
204
194
|
const comments = readComments(parts, mainPartPath);
|
|
205
195
|
const notes = readNotes(parts, mainPartPath);
|
|
206
196
|
const noteLabels = {
|
|
@@ -224,15 +214,24 @@ function importDocx(input) {
|
|
|
224
214
|
notes,
|
|
225
215
|
noteLabel
|
|
226
216
|
};
|
|
217
|
+
const sessionId = newSessionId();
|
|
227
218
|
const blockNodes = blockElements.map(
|
|
228
219
|
(el, i) => withStyleFormats(
|
|
229
|
-
buildBlock(
|
|
230
|
-
|
|
220
|
+
buildBlock(
|
|
221
|
+
el,
|
|
222
|
+
blockKey({ sessionId }, BODY_STORY_KEY, i),
|
|
223
|
+
sources,
|
|
224
|
+
formatting
|
|
225
|
+
),
|
|
226
|
+
formatting
|
|
231
227
|
)
|
|
232
228
|
);
|
|
229
|
+
const doc = docxSchema.nodes.doc.create(null, blockNodes);
|
|
233
230
|
return {
|
|
234
|
-
doc
|
|
231
|
+
doc,
|
|
232
|
+
notes: fidelityNotesOf(doc, mainPartPath),
|
|
235
233
|
session: new SessionStore({
|
|
234
|
+
sessionId,
|
|
236
235
|
parts,
|
|
237
236
|
mainPartPath,
|
|
238
237
|
documentPrefix: scan.prefix,
|
|
@@ -241,19 +240,13 @@ function importDocx(input) {
|
|
|
241
240
|
blocks: blockNodes.map((node, i) => ({ xml: scan.blocks[i].xml, node })),
|
|
242
241
|
defaults: stylesDom ? readDocumentDefaults(stylesDom, themeFonts) : NO_DOCUMENT_DEFAULTS,
|
|
243
242
|
defaultTabStopPt,
|
|
244
|
-
paragraphDefaults,
|
|
245
243
|
geometry,
|
|
246
|
-
|
|
244
|
+
formatting,
|
|
247
245
|
paragraphStyles: stylesDom ? readParagraphStyles(stylesDom) : [],
|
|
248
|
-
defaultParagraphStyleId,
|
|
249
246
|
numberingXml,
|
|
250
247
|
numberingPartPath,
|
|
251
248
|
comments,
|
|
252
|
-
commentReferenceIds: new Set(
|
|
253
|
-
commentReferencesIn(
|
|
254
|
-
docxSchema.nodes.doc.create(null, blockNodes)
|
|
255
|
-
).keys()
|
|
256
|
-
),
|
|
249
|
+
commentReferenceIds: new Set(commentReferencesIn(doc).keys()),
|
|
257
250
|
headersFooters
|
|
258
251
|
})
|
|
259
252
|
};
|
|
@@ -29,4 +29,4 @@ export interface ImportSources {
|
|
|
29
29
|
}
|
|
30
30
|
export declare const NO_IMPORT_SOURCES: ImportSources;
|
|
31
31
|
/** Moves a paragraph into an editable node. null if it holds content we do not model */
|
|
32
|
-
export declare function buildParagraph(el: Element, srcId:
|
|
32
|
+
export declare function buildParagraph(el: Element, srcId: string | null, sources?: ImportSources): PMNode | null;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/docx/importParagraph.ts
|
|
2
2
|
import { readDrawingPicture } from "../ooxml/image.js";
|
|
3
|
+
import { ST_OnOff } from "../ooxml/simpleTypes.js";
|
|
3
4
|
import {
|
|
5
|
+
attributeByLocalName,
|
|
4
6
|
attrString,
|
|
5
7
|
childByLocalName,
|
|
6
8
|
elementChildren,
|
|
@@ -104,9 +106,8 @@ function buildRunChild(el, marks, images, comments, notes, noteLabel) {
|
|
|
104
106
|
if (id === null) return null;
|
|
105
107
|
const kind = el.localName === "footnoteReference" ? "footnote" : "endnote";
|
|
106
108
|
const note = noteById(notes, kind, id);
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
);
|
|
109
|
+
const written = attributeByLocalName(el, "customMarkFollows");
|
|
110
|
+
const customMarkFollows = written !== null && (ST_OnOff.parse(written) ?? true);
|
|
110
111
|
return [
|
|
111
112
|
docxSchema.nodes.noteReference.create(
|
|
112
113
|
{
|
|
@@ -6,4 +6,4 @@ import type { Node as PMNode } from "prosemirror-model";
|
|
|
6
6
|
import { type StyleTable } from "./formatting";
|
|
7
7
|
import { type ImportSources } from "./importParagraph";
|
|
8
8
|
/** Moves a `<w:tbl>` into a table node. null if it cannot be modelled */
|
|
9
|
-
export declare function buildTable(el: Element, srcId:
|
|
9
|
+
export declare function buildTable(el: Element, srcId: string | null, sources?: ImportSources, styles?: StyleTable, defaultTableStyleId?: string | null): PMNode | null;
|
package/dist/docx/importTable.js
CHANGED
|
@@ -86,9 +86,23 @@ function readRow(el) {
|
|
|
86
86
|
}
|
|
87
87
|
return cells.length > 0 ? { el, tblPrEx, cells } : null;
|
|
88
88
|
}
|
|
89
|
+
function gridRevisionXml(grid) {
|
|
90
|
+
const revision = childByLocalName(grid, "tblGridChange");
|
|
91
|
+
if (revision === null) return null;
|
|
92
|
+
const declarations = Array.from(grid.attributes).filter(
|
|
93
|
+
(attr) => attr.namespaceURI === "http://www.w3.org/2000/xmlns/" && !revision.hasAttribute(attr.name)
|
|
94
|
+
);
|
|
95
|
+
if (declarations.length === 0) return serializeXml(revision);
|
|
96
|
+
const preserved = revision.ownerDocument.importNode(revision, true);
|
|
97
|
+
for (const attr of declarations) {
|
|
98
|
+
preserved.setAttributeNS(attr.namespaceURI, attr.name, attr.value);
|
|
99
|
+
}
|
|
100
|
+
return serializeXml(preserved);
|
|
101
|
+
}
|
|
89
102
|
function readTableParts(el) {
|
|
90
103
|
let tblPr = null;
|
|
91
104
|
let tblGrid = null;
|
|
105
|
+
let gridChange = null;
|
|
92
106
|
const rows = [];
|
|
93
107
|
for (const child of elementChildren(el)) {
|
|
94
108
|
if (child.localName === "tblPr") {
|
|
@@ -97,6 +111,7 @@ function readTableParts(el) {
|
|
|
97
111
|
}
|
|
98
112
|
if (child.localName === "tblGrid") {
|
|
99
113
|
tblGrid = child;
|
|
114
|
+
gridChange = gridRevisionXml(child);
|
|
100
115
|
continue;
|
|
101
116
|
}
|
|
102
117
|
if (child.localName !== "tr") return null;
|
|
@@ -104,7 +119,7 @@ function readTableParts(el) {
|
|
|
104
119
|
if (!row) return null;
|
|
105
120
|
rows.push(row);
|
|
106
121
|
}
|
|
107
|
-
return rows.length > 0 ? { tblPr, tblGrid, rows } : null;
|
|
122
|
+
return rows.length > 0 ? { tblPr, tblGrid, gridChange, rows } : null;
|
|
108
123
|
}
|
|
109
124
|
function resolveVerticalMerges(rows, width) {
|
|
110
125
|
const drafts = [];
|
|
@@ -262,6 +277,7 @@ function buildTable(el, srcId, sources = NO_IMPORT_SOURCES, styles = NO_STYLES,
|
|
|
262
277
|
tblPr: parts.tblPr ? serializeXml(parts.tblPr) : null,
|
|
263
278
|
tblW: readTableWidth(parts.tblPr, "tblW"),
|
|
264
279
|
gridCols,
|
|
280
|
+
gridChange: parts.gridChange,
|
|
265
281
|
format: tableFormat,
|
|
266
282
|
// The cells need these again whenever an edit derives their display values afresh
|
|
267
283
|
styleInside: toInsideBorders(style?.tableInside),
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known export refusals, asked of the document before anything is written.
|
|
3
|
+
*
|
|
4
|
+
* Each invariant reads what the writer would refuse over and reports it with the code the writer
|
|
5
|
+
* would throw, so a screen can ask at edit time what `exportDocx` would say. The list is walked in
|
|
6
|
+
* order and `exportDocx` throws its first entry, which is what keeps the two from disagreeing.
|
|
7
|
+
*
|
|
8
|
+
* The checks inspect model attrs and preserved XML without running the writers. Bookmark
|
|
9
|
+
* fragments and list definitions use the export parser. `assertBookmarkPairs` in `./exportDocx`
|
|
10
|
+
* and `assertPartsParse` in `./partPlan` remain the final checks over the parts as actually written.
|
|
11
|
+
*/
|
|
12
|
+
import type { Node as PMNode } from "prosemirror-model";
|
|
13
|
+
import type { DocxExportErrorCode } from "../ooxml/errors";
|
|
14
|
+
import type { ExportOptions } from "./exportDocx";
|
|
15
|
+
import { type DocxSession, type SessionStore } from "./session";
|
|
16
|
+
/** One reason the document cannot be written back, with the code `exportDocx` would throw it under */
|
|
17
|
+
export interface ExportProblem {
|
|
18
|
+
readonly code: DocxExportErrorCode;
|
|
19
|
+
readonly message: string;
|
|
20
|
+
/** Where the problem stands in the document. Absent for a problem of the package or of the session */
|
|
21
|
+
readonly pos?: number;
|
|
22
|
+
}
|
|
23
|
+
/** The problems as the writer sees them, for a caller already inside the writer's parser scope */
|
|
24
|
+
export declare function problemsOf(doc: PMNode, session: SessionStore): readonly ExportProblem[];
|
|
25
|
+
/**
|
|
26
|
+
* Known reasons writing this document back would be refused, in the order `exportDocx` would
|
|
27
|
+
* raise them. An empty list does not rule out failures while writing. Each entry carries the code and message the
|
|
28
|
+
* `DocxExportError` would carry, and the position in the document where there is one.
|
|
29
|
+
*
|
|
30
|
+
* The list definitions are read to tell a new list from one the document already had, so this
|
|
31
|
+
* needs an XML parser the way `exportDocx` does and takes the same option.
|
|
32
|
+
*/
|
|
33
|
+
export declare function exportProblems(doc: PMNode, session: DocxSession, options?: ExportOptions): readonly ExportProblem[];
|