@portone/docx-editor 0.4.0 → 0.5.1
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 +201 -0
- package/CONTRIBUTING.md +2 -0
- package/assets/editor.png +0 -0
- package/dist/DocxEditor.d.ts +1 -1
- package/dist/DocxEditor.js +44 -25
- package/dist/docx/cloning.js +4 -9
- package/dist/docx/commentOnlyChange.d.ts +5 -3
- package/dist/docx/comments/grammar.d.ts +27 -10
- package/dist/docx/comments/grammar.js +18 -67
- package/dist/docx/comments/model.d.ts +5 -6
- package/dist/docx/comments/model.js +0 -9
- package/dist/docx/comments/parts.d.ts +16 -10
- package/dist/docx/comments/parts.js +65 -13
- package/dist/docx/comments/people.d.ts +11 -3
- package/dist/docx/comments/people.js +20 -6
- package/dist/docx/comments/policy.js +7 -1
- package/dist/docx/comments/reading.d.ts +4 -2
- package/dist/docx/comments/reading.js +1 -14
- package/dist/docx/comments/writing.js +65 -28
- package/dist/docx/exportDocx.js +10 -14
- package/dist/docx/exportRefs.d.ts +8 -3
- package/dist/docx/exportRefs.js +2 -1
- package/dist/docx/fidelity.js +24 -10
- package/dist/docx/fields.d.ts +42 -0
- package/dist/docx/fields.js +76 -0
- package/dist/docx/formatting/styles.d.ts +0 -2
- package/dist/docx/formatting/styles.js +2 -15
- package/dist/docx/headersFooters.d.ts +89 -20
- package/dist/docx/headersFooters.js +163 -172
- package/dist/docx/identities.js +17 -26
- package/dist/docx/importDocx.d.ts +1 -1
- package/dist/docx/importDocx.js +100 -48
- package/dist/docx/importParagraph.d.ts +18 -5
- package/dist/docx/importParagraph.js +75 -128
- package/dist/docx/importPolicy.d.ts +70 -0
- package/dist/docx/importPolicy.js +195 -0
- package/dist/docx/importPreserved.d.ts +30 -0
- package/dist/docx/importPreserved.js +54 -0
- package/dist/docx/importTable.js +56 -12
- package/dist/docx/invariants.js +16 -18
- package/dist/docx/notes.d.ts +6 -1
- package/dist/docx/notes.js +6 -16
- package/dist/docx/pageGeometry.d.ts +5 -14
- package/dist/docx/pageGeometry.js +0 -12
- package/dist/docx/protectionPolicy.d.ts +13 -5
- package/dist/docx/protectionPolicy.js +32 -22
- package/dist/docx/scan.d.ts +18 -8
- package/dist/docx/scan.js +17 -11
- package/dist/docx/sections.d.ts +126 -0
- package/dist/docx/sections.js +207 -0
- package/dist/docx/serializeBlock.d.ts +13 -4
- package/dist/docx/serializeBlock.js +16 -18
- package/dist/docx/serializeParagraph.d.ts +9 -4
- package/dist/docx/serializeParagraph.js +23 -58
- package/dist/docx/serializePreserved.d.ts +14 -0
- package/dist/docx/serializePreserved.js +24 -0
- package/dist/docx/serializeStory.d.ts +17 -0
- package/dist/docx/serializeStory.js +17 -0
- package/dist/docx/serializeTable.js +10 -13
- package/dist/docx/session.d.ts +23 -6
- package/dist/docx/session.js +26 -5
- package/dist/docx/story.d.ts +140 -0
- package/dist/docx/story.js +237 -0
- package/dist/docx/storyProjection.js +6 -1
- package/dist/docx/tableTemplate.d.ts +25 -0
- package/dist/docx/tableTemplate.js +30 -16
- package/dist/docx/wrappers.d.ts +67 -0
- package/dist/docx/wrappers.js +117 -0
- package/dist/editor/clipboard/blockReaders.d.ts +74 -0
- package/dist/editor/clipboard/blockReaders.js +193 -0
- package/dist/editor/clipboard/htmlReader.d.ts +26 -0
- package/dist/editor/clipboard/htmlReader.js +376 -0
- package/dist/editor/clipboard/inlineFormatting.d.ts +0 -7
- package/dist/editor/clipboard/inlineFormatting.js +1 -7
- package/dist/editor/clipboard/internalChannel.d.ts +57 -0
- package/dist/editor/clipboard/internalChannel.js +58 -0
- package/dist/editor/clipboard/normalizers.d.ts +99 -0
- package/dist/editor/clipboard/normalizers.js +199 -0
- package/dist/editor/clipboard/parser.d.ts +34 -0
- package/dist/editor/clipboard/parser.js +58 -0
- package/dist/editor/clipboard/plugin.d.ts +21 -0
- package/dist/editor/clipboard/plugin.js +188 -0
- package/dist/editor/clipboard/readContext.d.ts +34 -0
- package/dist/editor/clipboard/readContext.js +25 -0
- package/dist/editor/clipboard/readers.d.ts +33 -0
- package/dist/editor/clipboard/readers.js +37 -0
- package/dist/editor/clipboard/source.d.ts +12 -0
- package/dist/editor/clipboard/source.js +21 -0
- package/dist/editor/commands/comments/editing.d.ts +26 -6
- package/dist/editor/commands/comments/editing.js +177 -106
- package/dist/editor/commands/comments/model.d.ts +34 -17
- package/dist/editor/commands/comments/model.js +11 -0
- package/dist/editor/commands/comments/reading.d.ts +5 -3
- package/dist/editor/commands/comments/reading.js +8 -58
- package/dist/editor/commands/index.d.ts +2 -2
- package/dist/editor/commands/index.js +2 -0
- package/dist/editor/commands/linkCommands.js +20 -5
- package/dist/editor/commands/listCommands.d.ts +6 -0
- package/dist/editor/commands/listCommands.js +3 -2
- package/dist/editor/commands/lockCommands.js +59 -16
- package/dist/editor/commands/noteQueries.d.ts +22 -5
- package/dist/editor/commands/noteQueries.js +34 -6
- package/dist/editor/commands/paragraphCommands.js +2 -2
- package/dist/editor/createEditor.js +13 -3
- package/dist/editor/documentStyles.d.ts +26 -4
- package/dist/editor/documentStyles.js +9 -4
- package/dist/editor/imageFiles.d.ts +2 -2
- package/dist/editor/imageFiles.js +2 -0
- package/dist/editor/insertTable.d.ts +1 -1
- package/dist/editor/insertTable.js +2 -2
- package/dist/editor/plainText.d.ts +12 -0
- package/dist/editor/plainText.js +2 -1
- package/dist/editor/plugins/columnResize.js +6 -3
- package/dist/editor/plugins/commentComposer.d.ts +28 -0
- package/dist/editor/plugins/commentComposer.js +46 -0
- package/dist/editor/plugins/commentDecorations.d.ts +29 -2
- package/dist/editor/plugins/commentDecorations.js +89 -15
- package/dist/editor/plugins/documentProjection.d.ts +31 -0
- package/dist/editor/plugins/documentProjection.js +22 -0
- package/dist/editor/plugins/imagePaste.js +15 -8
- package/dist/editor/plugins/linkPanel.d.ts +7 -3
- package/dist/editor/plugins/linkPanel.js +13 -27
- package/dist/editor/plugins/panelState.d.ts +67 -0
- package/dist/editor/plugins/panelState.js +54 -0
- package/dist/editor/plugins/tableContextMenu.d.ts +1 -1
- package/dist/editor/plugins/tableContextMenu.js +30 -47
- package/dist/editor/plugins/textContextMenu.d.ts +1 -1
- package/dist/editor/plugins/textContextMenu.js +30 -47
- package/dist/ooxml/fragment.d.ts +11 -0
- package/dist/ooxml/fragment.js +14 -4
- package/dist/ooxml/image.d.ts +3 -4
- package/dist/ooxml/image.js +50 -5
- package/dist/ooxml/names.d.ts +6 -0
- package/dist/ooxml/names.js +2 -0
- package/dist/ooxml/props.d.ts +10 -0
- package/dist/ooxml/props.js +28 -4
- package/dist/ooxml/rangeMarkers.d.ts +5 -0
- package/dist/ooxml/rangeMarkers.js +24 -0
- package/dist/page/PageGuides.d.ts +7 -3
- package/dist/page/PageGuides.js +13 -24
- package/dist/page/pageLayout.d.ts +64 -5
- package/dist/page/pageLayout.js +90 -29
- package/dist/page/usePageLayout.d.ts +14 -4
- package/dist/page/usePageLayout.js +19 -20
- package/dist/schema/attrRoles.js +46 -23
- package/dist/schema/clipboard.d.ts +72 -0
- package/dist/schema/clipboard.js +288 -0
- package/dist/schema/docxSchema.d.ts +9 -1
- package/dist/schema/docxSchema.js +217 -165
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.js +2 -2
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/locks.d.ts +3 -0
- package/dist/schema/locks.js +29 -12
- package/dist/schema/preservedFragments.d.ts +12 -0
- package/dist/schema/preservedFragments.js +38 -0
- package/dist/schema/preservedGuards.d.ts +9 -7
- package/dist/schema/preservedGuards.js +112 -11
- package/dist/schema/protection.d.ts +34 -5
- package/dist/schema/protection.js +42 -14
- package/dist/schema/rendering.d.ts +14 -0
- package/dist/schema/rendering.js +27 -12
- package/dist/schema/stories.d.ts +49 -0
- package/dist/schema/stories.js +78 -0
- package/dist/schema/wrappers.d.ts +58 -0
- package/dist/schema/wrappers.js +77 -0
- package/dist/styles/classNames.d.ts +3 -5
- package/dist/styles/classNames.js +3 -5
- package/dist/styles.css +74 -12
- package/dist/table/resize.d.ts +5 -3
- package/dist/ui/CommentsPanel.d.ts +1 -3
- package/dist/ui/CommentsPanel.js +24 -15
- package/dist/ui/NotesPanel.js +2 -2
- package/dist/ui/TextMenu.d.ts +1 -3
- package/dist/ui/TextMenu.js +10 -6
- package/dist/ui/comments/CommentComposer.d.ts +6 -1
- package/dist/ui/comments/CommentComposer.js +26 -3
- package/package.json +5 -4
- package/dist/editor/externalClipboard.d.ts +0 -22
- package/dist/editor/externalClipboard.js +0 -486
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// src/docx/importPolicy.ts
|
|
2
|
+
import { M_NS, W_NS } from "../ooxml/names.js";
|
|
3
|
+
import {
|
|
4
|
+
COMMENT_RANGE_MARKERS,
|
|
5
|
+
PERMISSION_MARKERS,
|
|
6
|
+
RANGE_MARKERS
|
|
7
|
+
} from "../ooxml/rangeMarkers.js";
|
|
8
|
+
import { WRAPPER_KINDS } from "./wrappers.js";
|
|
9
|
+
var MODEL = { tier: "model" };
|
|
10
|
+
var HIDDEN_MARKER = {
|
|
11
|
+
tier: "marker",
|
|
12
|
+
display: "hidden",
|
|
13
|
+
guarded: true
|
|
14
|
+
};
|
|
15
|
+
var IGNORABLE = {
|
|
16
|
+
tier: "ignorable",
|
|
17
|
+
display: "hidden",
|
|
18
|
+
guarded: false
|
|
19
|
+
};
|
|
20
|
+
function chip(tier) {
|
|
21
|
+
return { tier, display: "chip", guarded: false };
|
|
22
|
+
}
|
|
23
|
+
var RUN_CHIP = chip("runContent");
|
|
24
|
+
var INLINE_CHIP = chip("inline");
|
|
25
|
+
var BLOCK_CHIP = chip("block");
|
|
26
|
+
var FIELD_PIECE = {
|
|
27
|
+
tier: "runContent",
|
|
28
|
+
display: "chip",
|
|
29
|
+
guarded: true
|
|
30
|
+
};
|
|
31
|
+
function clarkName(el) {
|
|
32
|
+
return `{${el.namespaceURI ?? ""}}${el.localName}`;
|
|
33
|
+
}
|
|
34
|
+
function wml(localName) {
|
|
35
|
+
return `{${W_NS}}${localName}`;
|
|
36
|
+
}
|
|
37
|
+
function rules(entries) {
|
|
38
|
+
return new Map(
|
|
39
|
+
entries.flatMap(
|
|
40
|
+
([names, policy]) => names.map((name) => [wml(name), policy])
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
var REVISION_CONTAINERS = ["ins", "del", "moveFrom", "moveTo"];
|
|
45
|
+
var MATH = [`{${M_NS}}oMath`, `{${M_NS}}oMathPara`];
|
|
46
|
+
var RUN_LEVEL = rules([
|
|
47
|
+
[["rPr", "t", "br", "tab", "drawing"], MODEL],
|
|
48
|
+
[["commentReference", "footnoteReference", "endnoteReference"], MODEL],
|
|
49
|
+
[["lastRenderedPageBreak"], IGNORABLE],
|
|
50
|
+
[["softHyphen"], { tier: "runContent", display: "hidden", guarded: false }],
|
|
51
|
+
[
|
|
52
|
+
["noBreakHyphen"],
|
|
53
|
+
{ tier: "runContent", display: "text", text: "\u2011", guarded: false }
|
|
54
|
+
],
|
|
55
|
+
[["cr"], { tier: "runContent", display: "break", guarded: false }],
|
|
56
|
+
// §17.16.18: a complex field is the begin, the instruction and the end read in order, so a
|
|
57
|
+
// piece taken away leaves the rest saying something the file never said
|
|
58
|
+
[["fldChar", "instrText", "delInstrText"], FIELD_PIECE],
|
|
59
|
+
[
|
|
60
|
+
[
|
|
61
|
+
"sym",
|
|
62
|
+
"ptab",
|
|
63
|
+
"pgNum",
|
|
64
|
+
"pict",
|
|
65
|
+
"object",
|
|
66
|
+
"ruby",
|
|
67
|
+
"contentPart",
|
|
68
|
+
"annotationRef",
|
|
69
|
+
"footnoteRef",
|
|
70
|
+
"endnoteRef",
|
|
71
|
+
"separator",
|
|
72
|
+
"continuationSeparator",
|
|
73
|
+
"delText",
|
|
74
|
+
"dayShort",
|
|
75
|
+
"monthShort",
|
|
76
|
+
"yearShort",
|
|
77
|
+
"dayLong",
|
|
78
|
+
"monthLong",
|
|
79
|
+
"yearLong"
|
|
80
|
+
],
|
|
81
|
+
RUN_CHIP
|
|
82
|
+
]
|
|
83
|
+
]);
|
|
84
|
+
var PARAGRAPH_CHILDREN = [
|
|
85
|
+
[RANGE_MARKERS, HIDDEN_MARKER],
|
|
86
|
+
[PERMISSION_MARKERS, HIDDEN_MARKER],
|
|
87
|
+
[["proofErr"], IGNORABLE],
|
|
88
|
+
[REVISION_CONTAINERS, INLINE_CHIP],
|
|
89
|
+
[["fldSimple", "smartTag", "customXml", "dir", "bdo", "subDoc"], INLINE_CHIP]
|
|
90
|
+
];
|
|
91
|
+
var WRAPPER_ELEMENTS = WRAPPER_KINDS.map(
|
|
92
|
+
(kind) => kind.element
|
|
93
|
+
);
|
|
94
|
+
var PARAGRAPH_LEVEL = new Map([
|
|
95
|
+
...rules([
|
|
96
|
+
[["pPr", "r"], MODEL],
|
|
97
|
+
[COMMENT_RANGE_MARKERS, MODEL],
|
|
98
|
+
...PARAGRAPH_CHILDREN,
|
|
99
|
+
[WRAPPER_ELEMENTS, MODEL]
|
|
100
|
+
]),
|
|
101
|
+
...MATH.map((name) => [name, INLINE_CHIP])
|
|
102
|
+
]);
|
|
103
|
+
var WRAPPER_LEVEL = new Map([
|
|
104
|
+
...rules([
|
|
105
|
+
[["r"], MODEL],
|
|
106
|
+
[COMMENT_RANGE_MARKERS, MODEL],
|
|
107
|
+
...PARAGRAPH_CHILDREN,
|
|
108
|
+
[WRAPPER_ELEMENTS, MODEL]
|
|
109
|
+
]),
|
|
110
|
+
...MATH.map((name) => [name, INLINE_CHIP])
|
|
111
|
+
]);
|
|
112
|
+
var BLOCK_CHILDREN = [
|
|
113
|
+
[["p", "tbl"], MODEL],
|
|
114
|
+
[RANGE_MARKERS, HIDDEN_MARKER],
|
|
115
|
+
[COMMENT_RANGE_MARKERS, HIDDEN_MARKER],
|
|
116
|
+
[PERMISSION_MARKERS, HIDDEN_MARKER],
|
|
117
|
+
[["proofErr"], IGNORABLE],
|
|
118
|
+
[REVISION_CONTAINERS, BLOCK_CHIP],
|
|
119
|
+
[["sdt", "customXml", "altChunk"], BLOCK_CHIP]
|
|
120
|
+
];
|
|
121
|
+
var BODY_LEVEL = new Map([
|
|
122
|
+
...rules([...BLOCK_CHILDREN, [["sectPr"], BLOCK_CHIP]]),
|
|
123
|
+
...MATH.map((name) => [name, BLOCK_CHIP])
|
|
124
|
+
]);
|
|
125
|
+
var CELL_LEVEL = new Map([
|
|
126
|
+
...rules([...BLOCK_CHILDREN, [["tcPr"], MODEL]]),
|
|
127
|
+
...MATH.map((name) => [name, BLOCK_CHIP])
|
|
128
|
+
]);
|
|
129
|
+
var TABLE_LEVEL = rules([
|
|
130
|
+
[["tblPr", "tblGrid", "tr"], MODEL],
|
|
131
|
+
[RANGE_MARKERS, HIDDEN_MARKER],
|
|
132
|
+
[COMMENT_RANGE_MARKERS, HIDDEN_MARKER],
|
|
133
|
+
[PERMISSION_MARKERS, HIDDEN_MARKER],
|
|
134
|
+
[["proofErr"], IGNORABLE]
|
|
135
|
+
]);
|
|
136
|
+
var ROW_LEVEL = rules([
|
|
137
|
+
[["tblPrEx", "trPr", "tc", "sdt"], MODEL],
|
|
138
|
+
[RANGE_MARKERS, HIDDEN_MARKER],
|
|
139
|
+
[COMMENT_RANGE_MARKERS, HIDDEN_MARKER],
|
|
140
|
+
[PERMISSION_MARKERS, HIDDEN_MARKER],
|
|
141
|
+
[["proofErr"], IGNORABLE]
|
|
142
|
+
]);
|
|
143
|
+
var WML_POLICY = {
|
|
144
|
+
r: RUN_LEVEL,
|
|
145
|
+
p: PARAGRAPH_LEVEL,
|
|
146
|
+
wrapper: WRAPPER_LEVEL,
|
|
147
|
+
body: BODY_LEVEL,
|
|
148
|
+
tc: CELL_LEVEL,
|
|
149
|
+
tbl: TABLE_LEVEL,
|
|
150
|
+
tr: ROW_LEVEL
|
|
151
|
+
};
|
|
152
|
+
var LEVEL_PRESERVATION = {
|
|
153
|
+
r: RUN_CHIP,
|
|
154
|
+
p: INLINE_CHIP,
|
|
155
|
+
wrapper: INLINE_CHIP,
|
|
156
|
+
body: BLOCK_CHIP,
|
|
157
|
+
tc: BLOCK_CHIP
|
|
158
|
+
};
|
|
159
|
+
function defaultPreservation(level) {
|
|
160
|
+
return LEVEL_PRESERVATION[level];
|
|
161
|
+
}
|
|
162
|
+
var LEVEL_DEFAULTS = {
|
|
163
|
+
...LEVEL_PRESERVATION,
|
|
164
|
+
tbl: { tier: "demote" },
|
|
165
|
+
tr: { tier: "demote" }
|
|
166
|
+
};
|
|
167
|
+
function policyFor(el, level) {
|
|
168
|
+
return WML_POLICY[level].get(clarkName(el)) ?? LEVEL_DEFAULTS[level];
|
|
169
|
+
}
|
|
170
|
+
function runContentText(el) {
|
|
171
|
+
const policy = policyFor(el, "r");
|
|
172
|
+
if (policy.tier === "model") {
|
|
173
|
+
switch (el.localName) {
|
|
174
|
+
case "t":
|
|
175
|
+
return el.textContent ?? "";
|
|
176
|
+
case "tab":
|
|
177
|
+
return " ";
|
|
178
|
+
case "br":
|
|
179
|
+
return "\n";
|
|
180
|
+
// A drawing and the three annotation references draw something that is not text
|
|
181
|
+
default:
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (policy.tier === "demote") return null;
|
|
186
|
+
if (policy.display === "break") return "\n";
|
|
187
|
+
return policy.display === "text" ? policy.text ?? null : null;
|
|
188
|
+
}
|
|
189
|
+
export {
|
|
190
|
+
WML_POLICY,
|
|
191
|
+
clarkName,
|
|
192
|
+
defaultPreservation,
|
|
193
|
+
policyFor,
|
|
194
|
+
runContentText
|
|
195
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One element kept exactly as it came, at whatever level of the document it stood.
|
|
3
|
+
*
|
|
4
|
+
* `./importPolicy` says what an element is worth keeping as; this is where that answer becomes a
|
|
5
|
+
* node. Every level has a node of its own - inside a run, beside the runs of a paragraph, and in
|
|
6
|
+
* the place of a block - so the three readers build them the same way and cannot drift apart in
|
|
7
|
+
* what a chip shows or which fragments a guard answers for.
|
|
8
|
+
*/
|
|
9
|
+
import type { Mark, Node as PMNode } from "prosemirror-model";
|
|
10
|
+
import { type DemotionPolicy, type ElementPolicy, type PreservationRule, type PreservingLevel } from "./importPolicy";
|
|
11
|
+
/**
|
|
12
|
+
* The rule an element is kept under.
|
|
13
|
+
*
|
|
14
|
+
* The level's own narrowest preservation stands in wherever the table said `model` and the reader
|
|
15
|
+
* could not read the element after all, so a structure it could not take apart costs that element
|
|
16
|
+
* and no more.
|
|
17
|
+
*/
|
|
18
|
+
export declare function preservationOf(policy: ElementPolicy | DemotionPolicy, level: PreservingLevel): PreservationRule;
|
|
19
|
+
/** One child of a run kept as it came, wearing the run mark so it goes back inside that run */
|
|
20
|
+
export declare function buildPreservedRunContent(el: Element, marks: readonly Mark[], rule: PreservationRule): PMNode;
|
|
21
|
+
/** One child of a paragraph, or of a wrapper inside it, kept as it came */
|
|
22
|
+
export declare function buildPreservedInline(el: Element, wrappers: readonly Mark[], rule: PreservationRule): PMNode;
|
|
23
|
+
/**
|
|
24
|
+
* One block kept as it came, standing where it stood.
|
|
25
|
+
*
|
|
26
|
+
* A body block is one of the fragments the session holds, so it names that fragment and the bytes
|
|
27
|
+
* it arrived as go back out untouched. A block inside a cell was never a fragment of its own, so
|
|
28
|
+
* it carries its XML along with it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildPreservedBlock(el: Element, srcId: string | null, level: "body" | "tc"): PMNode;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/docx/importPreserved.ts
|
|
2
|
+
import { serializeXml } from "../ooxml/xml.js";
|
|
3
|
+
import { docxSchema } from "../schema/index.js";
|
|
4
|
+
import {
|
|
5
|
+
defaultPreservation,
|
|
6
|
+
policyFor
|
|
7
|
+
} from "./importPolicy.js";
|
|
8
|
+
function preservedText(el, rule) {
|
|
9
|
+
if (rule.display === "text") return rule.text ?? null;
|
|
10
|
+
if (rule.display !== "chip") return null;
|
|
11
|
+
return el.textContent === "" ? null : el.textContent ?? null;
|
|
12
|
+
}
|
|
13
|
+
function preservedAttrs(el, rule) {
|
|
14
|
+
return {
|
|
15
|
+
xml: serializeXml(el),
|
|
16
|
+
element: el.localName,
|
|
17
|
+
display: rule.display,
|
|
18
|
+
text: preservedText(el, rule),
|
|
19
|
+
guarded: rule.guarded
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function preservationOf(policy, level) {
|
|
23
|
+
return policy.tier === "model" || policy.tier === "demote" ? defaultPreservation(level) : policy;
|
|
24
|
+
}
|
|
25
|
+
function buildPreservedRunContent(el, marks, rule) {
|
|
26
|
+
return docxSchema.nodes.rawRunContent.create(
|
|
27
|
+
preservedAttrs(el, rule),
|
|
28
|
+
null,
|
|
29
|
+
marks
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
function buildPreservedInline(el, wrappers, rule) {
|
|
33
|
+
return docxSchema.nodes.rawInline.create(
|
|
34
|
+
preservedAttrs(el, rule),
|
|
35
|
+
null,
|
|
36
|
+
wrappers
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
function buildPreservedBlock(el, srcId, level) {
|
|
40
|
+
const rule = preservationOf(policyFor(el, level), level);
|
|
41
|
+
return docxSchema.nodes.rawBlock.create({
|
|
42
|
+
xml: srcId === null ? serializeXml(el) : null,
|
|
43
|
+
srcId,
|
|
44
|
+
name: el.nodeName,
|
|
45
|
+
display: rule.display,
|
|
46
|
+
guarded: rule.guarded
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
buildPreservedBlock,
|
|
51
|
+
buildPreservedInline,
|
|
52
|
+
buildPreservedRunContent,
|
|
53
|
+
preservationOf
|
|
54
|
+
};
|
package/dist/docx/importTable.js
CHANGED
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
buildParagraph,
|
|
19
19
|
NO_IMPORT_SOURCES
|
|
20
20
|
} from "./importParagraph.js";
|
|
21
|
+
import { policyFor } from "./importPolicy.js";
|
|
22
|
+
import { buildPreservedBlock } from "./importPreserved.js";
|
|
21
23
|
import { readSdtWrapper } from "./sdt.js";
|
|
22
24
|
import {
|
|
23
25
|
cellConditionsOf,
|
|
@@ -39,6 +41,13 @@ import {
|
|
|
39
41
|
readTableWidth,
|
|
40
42
|
tblStyleIdOf
|
|
41
43
|
} from "./tableFormatting.js";
|
|
44
|
+
function isTransparent(el, level) {
|
|
45
|
+
const tier = policyFor(el, level).tier;
|
|
46
|
+
return tier === "marker" || tier === "ignorable";
|
|
47
|
+
}
|
|
48
|
+
function takeGathered(gathered) {
|
|
49
|
+
return gathered.length === 0 ? null : gathered.splice(0).join("");
|
|
50
|
+
}
|
|
42
51
|
function readGridSpan(tcPr) {
|
|
43
52
|
const value = tcPr ? childValue(tcPr, "gridSpan") : null;
|
|
44
53
|
const parsed = value === null ? null : Number.parseInt(value, 10);
|
|
@@ -67,27 +76,45 @@ function readSdtCell(el) {
|
|
|
67
76
|
}
|
|
68
77
|
};
|
|
69
78
|
}
|
|
79
|
+
function trailCell(cells, gathered) {
|
|
80
|
+
const xml = takeGathered(gathered);
|
|
81
|
+
if (xml === null) return true;
|
|
82
|
+
const last = cells.at(-1);
|
|
83
|
+
if (!last || last.vMerge === "continue") return false;
|
|
84
|
+
last.trailingXml = (last.trailingXml ?? "") + xml;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
70
87
|
function readRow(el) {
|
|
71
88
|
const cells = [];
|
|
89
|
+
const gathered = [];
|
|
72
90
|
let tblPrEx = null;
|
|
91
|
+
let leadingXml = null;
|
|
73
92
|
for (const child of elementChildren(el)) {
|
|
74
93
|
if (child.localName === "trPr") continue;
|
|
75
94
|
if (child.localName === "tblPrEx") {
|
|
76
95
|
tblPrEx = child;
|
|
77
96
|
continue;
|
|
78
97
|
}
|
|
98
|
+
if (isTransparent(child, "tr")) {
|
|
99
|
+
gathered.push(serializeXml(child));
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
79
102
|
const sdt = child.localName === "sdt" ? readSdtCell(child) : null;
|
|
80
103
|
if (!sdt && child.localName !== "tc") return null;
|
|
104
|
+
if (cells.length === 0) leadingXml = takeGathered(gathered);
|
|
105
|
+
else if (!trailCell(cells, gathered)) return null;
|
|
81
106
|
const tc = sdt ? sdt.el : child;
|
|
82
107
|
const tcPr = childByLocalName(tc, "tcPr");
|
|
83
108
|
cells.push({
|
|
84
109
|
el: tc,
|
|
85
110
|
gridSpan: readGridSpan(tcPr),
|
|
86
111
|
vMerge: readVerticalMerge(tcPr),
|
|
87
|
-
control: sdt ? sdt.control : null
|
|
112
|
+
control: sdt ? sdt.control : null,
|
|
113
|
+
trailingXml: null
|
|
88
114
|
});
|
|
89
115
|
}
|
|
90
|
-
|
|
116
|
+
if (cells.length === 0 || !trailCell(cells, gathered)) return null;
|
|
117
|
+
return { el, tblPrEx, cells, leadingXml, trailingXml: null };
|
|
91
118
|
}
|
|
92
119
|
function gridRevisionXml(grid) {
|
|
93
120
|
const revision = childByLocalName(grid, "tblGridChange");
|
|
@@ -107,6 +134,8 @@ function readTableParts(el) {
|
|
|
107
134
|
let tblGrid = null;
|
|
108
135
|
let gridChange = null;
|
|
109
136
|
const rows = [];
|
|
137
|
+
const gathered = [];
|
|
138
|
+
let leadingXml = null;
|
|
110
139
|
for (const child of elementChildren(el)) {
|
|
111
140
|
if (child.localName === "tblPr") {
|
|
112
141
|
tblPr = child;
|
|
@@ -117,12 +146,22 @@ function readTableParts(el) {
|
|
|
117
146
|
gridChange = gridRevisionXml(child);
|
|
118
147
|
continue;
|
|
119
148
|
}
|
|
149
|
+
if (isTransparent(child, "tbl")) {
|
|
150
|
+
gathered.push(serializeXml(child));
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
120
153
|
if (child.localName !== "tr") return null;
|
|
121
154
|
const row = readRow(child);
|
|
122
155
|
if (!row) return null;
|
|
156
|
+
const previous = rows.at(-1);
|
|
157
|
+
if (previous) previous.trailingXml = takeGathered(gathered);
|
|
158
|
+
else leadingXml = takeGathered(gathered);
|
|
123
159
|
rows.push(row);
|
|
124
160
|
}
|
|
125
|
-
|
|
161
|
+
const last = rows.at(-1);
|
|
162
|
+
if (!last) return null;
|
|
163
|
+
last.trailingXml = takeGathered(gathered);
|
|
164
|
+
return { tblPr, tblGrid, gridChange, rows, leadingXml };
|
|
126
165
|
}
|
|
127
166
|
function resolveVerticalMerges(rows, width) {
|
|
128
167
|
const drafts = [];
|
|
@@ -144,7 +183,8 @@ function resolveVerticalMerges(rows, width) {
|
|
|
144
183
|
col,
|
|
145
184
|
colspan: cell.gridSpan,
|
|
146
185
|
rowspan: 1,
|
|
147
|
-
control: cell.control
|
|
186
|
+
control: cell.control,
|
|
187
|
+
trailingXml: cell.trailingXml
|
|
148
188
|
};
|
|
149
189
|
rowDrafts.push(draft);
|
|
150
190
|
if (cell.vMerge === "restart") next.set(col, draft);
|
|
@@ -167,13 +207,13 @@ function gridWidthOf(rows) {
|
|
|
167
207
|
}
|
|
168
208
|
function buildCellBlock(el, sources, context, placement) {
|
|
169
209
|
if (el.localName === "p") {
|
|
170
|
-
|
|
171
|
-
|
|
210
|
+
return styledParagraph(
|
|
211
|
+
buildParagraph(el, null, sources),
|
|
212
|
+
context,
|
|
213
|
+
placement
|
|
214
|
+
);
|
|
172
215
|
}
|
|
173
|
-
return
|
|
174
|
-
xml: serializeXml(el),
|
|
175
|
-
name: el.nodeName
|
|
176
|
-
});
|
|
216
|
+
return buildPreservedBlock(el, null, "tc");
|
|
177
217
|
}
|
|
178
218
|
function cellRect(draft) {
|
|
179
219
|
return {
|
|
@@ -203,7 +243,8 @@ function buildCell(draft, table, sources, context) {
|
|
|
203
243
|
format: readCellFormat(tcPr, defaults),
|
|
204
244
|
sdtPrefix: draft.control?.prefix ?? null,
|
|
205
245
|
sdtContentsLocked: draft.control?.contentsLocked ?? false,
|
|
206
|
-
sdtDeletionLocked: draft.control?.deletionLocked ?? false
|
|
246
|
+
sdtDeletionLocked: draft.control?.deletionLocked ?? false,
|
|
247
|
+
trailingXml: draft.trailingXml
|
|
207
248
|
},
|
|
208
249
|
blocks
|
|
209
250
|
);
|
|
@@ -221,7 +262,9 @@ function buildRow(row, drafts, table, sources, context) {
|
|
|
221
262
|
trAttrs: attrString(row.el),
|
|
222
263
|
tblPrEx: row.tblPrEx ? serializeXml(row.tblPrEx) : null,
|
|
223
264
|
trPr: trPr ? serializeXml(trPr) : null,
|
|
224
|
-
format: readRowFormat(trPr)
|
|
265
|
+
format: readRowFormat(trPr),
|
|
266
|
+
leadingXml: row.leadingXml,
|
|
267
|
+
trailingXml: row.trailingXml
|
|
225
268
|
},
|
|
226
269
|
cells
|
|
227
270
|
);
|
|
@@ -278,6 +321,7 @@ function buildTable(el, srcId, sources = NO_IMPORT_SOURCES, context = NO_FORMATT
|
|
|
278
321
|
tblW: readTableWidth(parts.tblPr, "tblW"),
|
|
279
322
|
gridCols,
|
|
280
323
|
gridChange: parts.gridChange,
|
|
324
|
+
leadingXml: parts.leadingXml,
|
|
281
325
|
...tableStyleAttrs(parts.tblPr, context)
|
|
282
326
|
},
|
|
283
327
|
rows
|
package/dist/docx/invariants.js
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
W_NS,
|
|
7
7
|
withXmlParser
|
|
8
8
|
} from "../ooxml/xml.js";
|
|
9
|
+
import { visitPreservedFragments } from "../schema/preservedFragments.js";
|
|
10
|
+
import { unattributedCommentAuthors } from "../schema/protection.js";
|
|
9
11
|
import {
|
|
10
12
|
commentReferencesIn,
|
|
11
13
|
commentsChanged,
|
|
@@ -24,30 +26,21 @@ import { identityProblems } from "./identities.js";
|
|
|
24
26
|
import { insertedImageSrcs } from "./media.js";
|
|
25
27
|
import { canDefineNewList, newNumIds, startedLists } from "./newLists.js";
|
|
26
28
|
import { CONTENT_TYPES_PATH } from "./packageParts.js";
|
|
27
|
-
import { lostOriginal } from "./
|
|
29
|
+
import { lostOriginal } from "./serializePreserved.js";
|
|
28
30
|
import {
|
|
29
31
|
originalBlock,
|
|
30
32
|
sessionOf
|
|
31
33
|
} from "./session.js";
|
|
32
|
-
function markerSourceOf(node, session) {
|
|
33
|
-
if (node.type.name === "rawInline" || node.type.name === "rawBlock") {
|
|
34
|
-
return typeof node.attrs.xml === "string" ? node.attrs.xml : null;
|
|
35
|
-
}
|
|
36
|
-
if (node.type.isInGroup("preserved")) {
|
|
37
|
-
return originalBlock(node, session)?.xml ?? null;
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
34
|
var bookmarkPairs = {
|
|
42
35
|
name: "bookmarkPairs",
|
|
43
36
|
check(doc, session) {
|
|
44
37
|
const problems = [];
|
|
45
38
|
const open = /* @__PURE__ */ new Map();
|
|
46
39
|
const used = /* @__PURE__ */ new Set();
|
|
47
|
-
doc
|
|
48
|
-
const source =
|
|
49
|
-
if (source === null) return
|
|
50
|
-
if (!source.includes("bookmark")) return
|
|
40
|
+
visitPreservedFragments(doc, (node, pos, xml) => {
|
|
41
|
+
const source = xml ?? originalBlock(node, session)?.xml ?? null;
|
|
42
|
+
if (source === null) return;
|
|
43
|
+
if (!source.includes("bookmark")) return;
|
|
51
44
|
let root;
|
|
52
45
|
try {
|
|
53
46
|
root = parseXml(
|
|
@@ -59,7 +52,7 @@ var bookmarkPairs = {
|
|
|
59
52
|
message: "preserved bookmark XML could not be parsed",
|
|
60
53
|
pos
|
|
61
54
|
});
|
|
62
|
-
return
|
|
55
|
+
return;
|
|
63
56
|
}
|
|
64
57
|
for (const marker of Array.from(root.getElementsByTagName("*"))) {
|
|
65
58
|
if (marker.namespaceURI !== W_NS || marker.localName !== "bookmarkStart" && marker.localName !== "bookmarkEnd")
|
|
@@ -91,7 +84,6 @@ var bookmarkPairs = {
|
|
|
91
84
|
});
|
|
92
85
|
}
|
|
93
86
|
}
|
|
94
|
-
return true;
|
|
95
87
|
});
|
|
96
88
|
for (const [id, pos] of open) {
|
|
97
89
|
problems.push({
|
|
@@ -132,11 +124,16 @@ var tableGrids = {
|
|
|
132
124
|
return problems;
|
|
133
125
|
}
|
|
134
126
|
};
|
|
127
|
+
var CARRIES_ITS_XML = /* @__PURE__ */ new Set([
|
|
128
|
+
"rawInline",
|
|
129
|
+
"rawRunContent"
|
|
130
|
+
]);
|
|
135
131
|
function lostOriginalOf(node, session) {
|
|
136
|
-
if (
|
|
132
|
+
if (CARRIES_ITS_XML.has(node.type.name)) {
|
|
137
133
|
return typeof node.attrs.xml === "string" ? null : "a preserved element has lost its original XML";
|
|
138
134
|
}
|
|
139
135
|
if (node.type.isInGroup("preserved")) {
|
|
136
|
+
if (typeof node.attrs.xml === "string") return null;
|
|
140
137
|
return originalBlock(node, session) ? null : lostOriginal(node, session);
|
|
141
138
|
}
|
|
142
139
|
return null;
|
|
@@ -191,7 +188,8 @@ function addsCommentsPart(doc, session) {
|
|
|
191
188
|
return true;
|
|
192
189
|
return bodyChanged && (peoplePart.pathIn(session) === null || session.comments.people.xml === null) && unrecordedAuthors(
|
|
193
190
|
currentCommentBodies(references).values(),
|
|
194
|
-
session.comments.people
|
|
191
|
+
session.comments.people,
|
|
192
|
+
unattributedCommentAuthors(session.comments.ordered)
|
|
195
193
|
).size > 0;
|
|
196
194
|
}
|
|
197
195
|
var mediaContentTypes = {
|
package/dist/docx/notes.d.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/** Reads footnote and endnote bodies related from the main document story. */
|
|
2
2
|
export type NoteKind = "footnote" | "endnote";
|
|
3
|
+
/**
|
|
4
|
+
* One entry of a notes part as it arrived. What the note says is a story of its own, held on the
|
|
5
|
+
* document node under `footnote:<id>` or `endnote:<id>` (`docx/story`).
|
|
6
|
+
*/
|
|
3
7
|
export interface ImportedNote {
|
|
4
8
|
kind: NoteKind;
|
|
5
9
|
id: string;
|
|
6
10
|
label: string;
|
|
7
|
-
text: string;
|
|
8
11
|
type: string | null;
|
|
9
12
|
}
|
|
10
13
|
export interface ImportedNotePart {
|
|
11
14
|
partPath: string | null;
|
|
15
|
+
/** The raw text of the part, which is what the note stories are sliced out of. null for none */
|
|
16
|
+
xml: string | null;
|
|
12
17
|
ordered: readonly ImportedNote[];
|
|
13
18
|
byId: ReadonlyMap<string, ImportedNote>;
|
|
14
19
|
}
|
package/dist/docx/notes.js
CHANGED
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
decodeUtf8,
|
|
5
5
|
elementChildren,
|
|
6
6
|
parseXml,
|
|
7
|
-
R_NS
|
|
8
|
-
W_NS
|
|
7
|
+
R_NS
|
|
9
8
|
} from "../ooxml/xml.js";
|
|
10
9
|
import { relatedPartPath } from "./packageParts.js";
|
|
11
10
|
var EMPTY_PART = {
|
|
12
11
|
partPath: null,
|
|
12
|
+
xml: null,
|
|
13
13
|
ordered: [],
|
|
14
14
|
byId: /* @__PURE__ */ new Map()
|
|
15
15
|
};
|
|
@@ -17,23 +17,13 @@ var NO_NOTES = {
|
|
|
17
17
|
footnotes: EMPTY_PART,
|
|
18
18
|
endnotes: EMPTY_PART
|
|
19
19
|
};
|
|
20
|
-
function inlineText(node) {
|
|
21
|
-
if (node.localName === "t") return node.textContent ?? "";
|
|
22
|
-
if (node.localName === "tab") return " ";
|
|
23
|
-
if (node.localName === "br" || node.localName === "cr") return "\n";
|
|
24
|
-
if (node.localName === "noBreakHyphen") return "\u2011";
|
|
25
|
-
if (node.localName === "softHyphen") return "\xAD";
|
|
26
|
-
return elementChildren(node).map(inlineText).join("");
|
|
27
|
-
}
|
|
28
|
-
function noteText(el) {
|
|
29
|
-
return Array.from(el.getElementsByTagNameNS(W_NS, "p")).map(inlineText).join("\n");
|
|
30
|
-
}
|
|
31
20
|
function notePart(parts, mainPartPath, kind) {
|
|
32
21
|
const partPath = relatedPartPath(parts, mainPartPath, `${R_NS}/${kind}s`);
|
|
33
22
|
if (partPath === null) return EMPTY_PART;
|
|
34
23
|
const bytes = parts.get(partPath);
|
|
35
24
|
if (!bytes) return { ...EMPTY_PART, partPath };
|
|
36
|
-
const
|
|
25
|
+
const xml = decodeUtf8(bytes).text;
|
|
26
|
+
const root = parseXml(xml).documentElement;
|
|
37
27
|
const elements = elementChildren(root).filter((el) => el.localName === kind);
|
|
38
28
|
const ordered = elements.flatMap((el) => {
|
|
39
29
|
const id = attributeByLocalName(el, "id");
|
|
@@ -41,13 +31,13 @@ function notePart(parts, mainPartPath, kind) {
|
|
|
41
31
|
const type = attributeByLocalName(el, "type");
|
|
42
32
|
const regular = type === null || type === "normal";
|
|
43
33
|
const label = regular ? "?" : "";
|
|
44
|
-
return [{ kind, id, label,
|
|
34
|
+
return [{ kind, id, label, type }];
|
|
45
35
|
});
|
|
46
36
|
const byId = /* @__PURE__ */ new Map();
|
|
47
37
|
for (const note of ordered) {
|
|
48
38
|
if (!byId.has(note.id)) byId.set(note.id, note);
|
|
49
39
|
}
|
|
50
|
-
return { partPath, ordered, byId };
|
|
40
|
+
return { partPath, xml, ordered, byId };
|
|
51
41
|
}
|
|
52
42
|
function readNotes(parts, mainPartPath) {
|
|
53
43
|
return {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The paper a document is written on: its size and its margins.
|
|
3
3
|
*
|
|
4
|
-
* A document says so in
|
|
5
|
-
* only: the `w:sectPr` itself rides out
|
|
4
|
+
* A document says so in a `w:sectPr`, one per section (`./sections`). The values are read for the
|
|
5
|
+
* screen only: the `w:sectPr` itself rides out as the text it arrived as, so what a document
|
|
6
6
|
* declares is never rewritten from these numbers.
|
|
7
7
|
*
|
|
8
8
|
* Everything here is in twips (1/1440 inch), the unit `w:pgSz` and `w:pgMar` are written in.
|
|
@@ -35,6 +35,9 @@ export declare const A4_PORTRAIT: PageGeometry;
|
|
|
35
35
|
/**
|
|
36
36
|
* The geometry a `w:sectPr` element lays down, with anything it leaves unsaid taken from A4.
|
|
37
37
|
*
|
|
38
|
+
* The reading is deliberately forgiving: it runs against a document already opened, and a
|
|
39
|
+
* `w:sectPr` that cannot be read is a reason to draw A4, never a reason to refuse the file.
|
|
40
|
+
*
|
|
38
41
|
* `w:orient` is not applied on top of the size: Word writes the width and the height already
|
|
39
42
|
* swapped for a landscape section, so honouring both would turn the paper back upright.
|
|
40
43
|
*/
|
|
@@ -63,15 +66,3 @@ export declare function bodyWidth(geometry: PageGeometry): BodyWidth;
|
|
|
63
66
|
* It is what a caller with no document to ask still gets: 11906 - 1247 * 2 = 9412 dxa.
|
|
64
67
|
*/
|
|
65
68
|
export declare const A4_BODY_WIDTH: BodyWidth;
|
|
66
|
-
/**
|
|
67
|
-
* The geometry of the first section of an already parsed body.
|
|
68
|
-
*
|
|
69
|
-
* A document may hold a `w:sectPr` per section, each with a paper of its own. The screen draws
|
|
70
|
-
* one paper for the whole document, so the first section decides it; the rest ride out
|
|
71
|
-
* untouched in their preserved blocks and are drawn on the first section's paper.
|
|
72
|
-
* `site/content/docs/features.mdx` records that limit.
|
|
73
|
-
*
|
|
74
|
-
* The reading is deliberately forgiving: this runs against a document already opened, and a
|
|
75
|
-
* `w:sectPr` we cannot read is a reason to draw A4, never a reason to refuse the file.
|
|
76
|
-
*/
|
|
77
|
-
export declare function readBodyGeometry(body: Element): PageGeometry;
|
|
@@ -73,17 +73,6 @@ function bodyWidth(geometry) {
|
|
|
73
73
|
return { twips, px: twipsToPx(twips) };
|
|
74
74
|
}
|
|
75
75
|
var A4_BODY_WIDTH = bodyWidth(A4_PORTRAIT);
|
|
76
|
-
function readBodyGeometry(body) {
|
|
77
|
-
return readPageGeometry(firstSectPrIn(body));
|
|
78
|
-
}
|
|
79
|
-
function firstSectPrIn(root) {
|
|
80
|
-
const found = root.getElementsByTagName("w:sectPr").item(0);
|
|
81
|
-
if (found) return found;
|
|
82
|
-
for (const el of root.getElementsByTagName("*")) {
|
|
83
|
-
if (el.localName === "sectPr") return el;
|
|
84
|
-
}
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
76
|
export {
|
|
88
77
|
A4_BODY_WIDTH,
|
|
89
78
|
A4_PORTRAIT,
|
|
@@ -91,7 +80,6 @@ export {
|
|
|
91
80
|
bodyHeightTwips,
|
|
92
81
|
bodyWidth,
|
|
93
82
|
bodyWidthTwips,
|
|
94
|
-
readBodyGeometry,
|
|
95
83
|
readPageGeometry,
|
|
96
84
|
twipsToPx
|
|
97
85
|
};
|