@portone/docx-editor 0.2.1 → 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 +109 -0
- package/CONTRIBUTING.md +5 -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 +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 +52 -111
- 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 +69 -71
- 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 -78
- 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 +6 -13
- 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 +3 -7
- 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 +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 +43 -17
- package/dist/docx/tableFormatting/editing.js +108 -139
- package/dist/docx/tableFormatting/reading.d.ts +16 -6
- package/dist/docx/tableFormatting/reading.js +40 -20
- package/dist/docx/tableTemplate.js +18 -7
- 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 +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/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 -46
- package/dist/editor/commands/paragraphCommands.js +28 -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 +56 -0
- package/dist/editor/editorDocument.js +74 -0
- package/dist/editor/externalClipboard.js +16 -45
- 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/imagePaste.js +4 -3
- package/dist/editor/plugins/keymap.js +18 -3
- 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 +24 -7
- 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 +24 -11
- package/dist/ooxml/element.js +31 -12
- package/dist/ooxml/errors.d.ts +3 -2
- package/dist/ooxml/image.d.ts +4 -0
- package/dist/ooxml/image.js +2 -5
- package/dist/ooxml/partSplice.d.ts +67 -0
- package/dist/ooxml/partSplice.js +169 -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 +27 -6
- package/dist/ooxml/xml.js +37 -5
- 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 -19
- package/dist/page/pageLayout.js +36 -6
- package/dist/page/usePageLayout.d.ts +2 -17
- package/dist/page/usePageLayout.js +3 -39
- package/dist/schema/attrRoles.d.ts +25 -18
- package/dist/schema/attrRoles.js +102 -67
- 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 +26 -14
- 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/inlineStyle.js +15 -6
- package/dist/table/cellFormatting.d.ts +8 -1
- package/dist/table/cellFormatting.js +10 -18
- 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/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,18 +1,23 @@
|
|
|
1
1
|
// src/docx/tableFormatting/editing.ts
|
|
2
|
-
import {
|
|
2
|
+
import { elementXml, wAttrValue } from "../../ooxml/element.js";
|
|
3
3
|
import { wName } from "../../ooxml/names.js";
|
|
4
4
|
import { setAttr } from "../../ooxml/precedence.js";
|
|
5
|
-
import { normalizeHex, wAttr } from "../../ooxml/units.js";
|
|
6
|
-
import { childByLocalName } from "../../ooxml/xml.js";
|
|
7
5
|
import {
|
|
6
|
+
childElement,
|
|
7
|
+
editChild,
|
|
8
8
|
parseProps,
|
|
9
9
|
parsePropsXml,
|
|
10
10
|
propsChild,
|
|
11
11
|
renderProps,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
setChild,
|
|
13
|
+
withAttrs
|
|
14
|
+
} from "../../ooxml/props.js";
|
|
15
|
+
import {
|
|
16
|
+
ST_EighthPointMeasure,
|
|
17
|
+
ST_TwipsMeasure,
|
|
18
|
+
TWIPS_PER_PT
|
|
19
|
+
} from "../../ooxml/simpleTypes.js";
|
|
20
|
+
import { normalizeHex } from "../../ooxml/units.js";
|
|
16
21
|
import {
|
|
17
22
|
NO_BORDER_DEFAULTS,
|
|
18
23
|
NO_CELL_MARGINS,
|
|
@@ -25,18 +30,6 @@ var ALL_CELL_SIDES = [
|
|
|
25
30
|
"left",
|
|
26
31
|
"right"
|
|
27
32
|
];
|
|
28
|
-
var TC_BORDERS_ORDER = [
|
|
29
|
-
"top",
|
|
30
|
-
"start",
|
|
31
|
-
"left",
|
|
32
|
-
"bottom",
|
|
33
|
-
"end",
|
|
34
|
-
"right",
|
|
35
|
-
"insideH",
|
|
36
|
-
"insideV",
|
|
37
|
-
"tl2br",
|
|
38
|
-
"tr2bl"
|
|
39
|
-
];
|
|
40
33
|
var SIDE_NAMES = {
|
|
41
34
|
top: ["top"],
|
|
42
35
|
bottom: ["bottom"],
|
|
@@ -46,22 +39,24 @@ var SIDE_NAMES = {
|
|
|
46
39
|
var PRESET_BORDER_EIGHTHS = 4;
|
|
47
40
|
var EMPTY_TC_PR = { tag: "w:tcPr", attrs: null, children: [] };
|
|
48
41
|
function drawsLine(side) {
|
|
49
|
-
if (
|
|
50
|
-
const val =
|
|
42
|
+
if (side.tag === null) return false;
|
|
43
|
+
const val = wAttrValue(side.attrs, "val");
|
|
51
44
|
return val !== null && val !== "nil" && val !== "none";
|
|
52
45
|
}
|
|
53
46
|
function sideAttrs(name, current, edit, fallback = null) {
|
|
54
47
|
if (edit.kind === "color") {
|
|
55
48
|
if (!drawsLine(current)) {
|
|
56
|
-
if (current ||
|
|
49
|
+
if (current.tag !== null || fallback === null || fallback.val === "none") {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
57
52
|
return inheritedBorderAttrs(fallback, edit.hex);
|
|
58
53
|
}
|
|
59
|
-
return setAttr(
|
|
54
|
+
return setAttr(current.attrs, name, "color", edit.hex ?? "auto");
|
|
60
55
|
}
|
|
61
56
|
if (edit.line === "none") {
|
|
62
|
-
return current ? setAttr(
|
|
57
|
+
return current.tag !== null ? setAttr(current.attrs, name, "val", "none") : [[wName("val"), "none"]];
|
|
63
58
|
}
|
|
64
|
-
if (
|
|
59
|
+
if (current.tag === null) {
|
|
65
60
|
return [
|
|
66
61
|
[wName("val"), "single"],
|
|
67
62
|
[wName("sz"), `${PRESET_BORDER_EIGHTHS}`],
|
|
@@ -70,217 +65,191 @@ function sideAttrs(name, current, edit, fallback = null) {
|
|
|
70
65
|
];
|
|
71
66
|
}
|
|
72
67
|
return setAttr(
|
|
73
|
-
setAttr(
|
|
68
|
+
setAttr(current.attrs, name, "val", "single"),
|
|
74
69
|
name,
|
|
75
70
|
"sz",
|
|
76
71
|
`${PRESET_BORDER_EIGHTHS}`
|
|
77
72
|
);
|
|
78
73
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
};
|
|
85
|
-
function inheritedBorderAttrs(border, hex) {
|
|
86
|
-
const matched = border.match(
|
|
87
|
-
/^(\d+(?:\.\d+)?)pt (solid|double|dashed|dotted) (#[0-9a-f]{6})$/i
|
|
88
|
-
);
|
|
89
|
-
if (!matched) return null;
|
|
90
|
-
const [, widthText, style, currentColor] = matched;
|
|
91
|
-
if (hex !== null && normalizeHex(currentColor) === hex) return null;
|
|
92
|
-
const eighths = Math.round(Number.parseFloat(widthText) * 8);
|
|
93
|
-
if (!Number.isSafeInteger(eighths) || eighths <= 0) return null;
|
|
74
|
+
function inheritedBorderAttrs(line, hex) {
|
|
75
|
+
const current = line.color.kind === "rgb" ? normalizeHex(line.color.hex) : null;
|
|
76
|
+
if (hex !== null && current === hex) return null;
|
|
77
|
+
const thickness = ST_EighthPointMeasure.format(line.eighths);
|
|
78
|
+
if (thickness === null) return null;
|
|
94
79
|
return [
|
|
95
|
-
[wName("val"),
|
|
96
|
-
[wName("sz"),
|
|
80
|
+
[wName("val"), line.val],
|
|
81
|
+
[wName("sz"), thickness],
|
|
97
82
|
[wName("space"), "0"],
|
|
98
83
|
[wName("color"), hex ?? "auto"]
|
|
99
84
|
];
|
|
100
85
|
}
|
|
101
86
|
function sideNames(borders, side) {
|
|
102
87
|
const [primary, alternate] = SIDE_NAMES[side];
|
|
103
|
-
const usesAlternate = alternate !== void 0 &&
|
|
88
|
+
const usesAlternate = alternate !== void 0 && propsChild(borders.children, primary) === void 0 && propsChild(borders.children, alternate) !== void 0;
|
|
104
89
|
if (usesAlternate) return { write: alternate, drop: null };
|
|
105
90
|
return { write: primary, drop: alternate ?? null };
|
|
106
91
|
}
|
|
107
|
-
function
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
92
|
+
function leafElement(tag, attrs) {
|
|
93
|
+
return withAttrs({ tag, attrs: null, children: [] }, attrs);
|
|
94
|
+
}
|
|
95
|
+
function containerOf(props, name) {
|
|
96
|
+
const current = propsChild(props.children, name)?.xml;
|
|
97
|
+
if (current === void 0) {
|
|
98
|
+
return { tag: wName(name), attrs: null, children: [] };
|
|
99
|
+
}
|
|
100
|
+
return parseProps(current);
|
|
101
|
+
}
|
|
102
|
+
function editedBorders(props, edit, defaults) {
|
|
103
|
+
const borders = containerOf(props, "tcBorders");
|
|
104
|
+
if (!borders) return null;
|
|
111
105
|
const sides = edit.kind === "line" ? edit.sides : ALL_CELL_SIDES;
|
|
112
|
-
|
|
106
|
+
return sides.reduce((kept, side) => {
|
|
107
|
+
if (kept === null) return null;
|
|
113
108
|
const { write, drop } = sideNames(borders, side);
|
|
114
|
-
const currentSide =
|
|
109
|
+
const currentSide = childElement(borders, write);
|
|
110
|
+
if (!currentSide) return null;
|
|
115
111
|
const attrs = sideAttrs(write, currentSide, edit, defaults[side]);
|
|
116
112
|
if (!attrs) return kept;
|
|
117
|
-
const
|
|
118
|
-
const written = setPropsChild(
|
|
113
|
+
const written = editChild(
|
|
119
114
|
kept,
|
|
120
|
-
write,
|
|
121
|
-
|
|
122
|
-
TC_BORDERS_ORDER
|
|
115
|
+
["tcBorders", write],
|
|
116
|
+
() => leafElement(currentSide.tag ?? wName(write), attrs)
|
|
123
117
|
);
|
|
124
|
-
|
|
118
|
+
if (written === null || drop === null) return written;
|
|
119
|
+
return editChild(written, ["tcBorders", drop], () => null);
|
|
125
120
|
}, props);
|
|
126
|
-
const xml = renderProps(edited);
|
|
127
|
-
return { xml: xml === "" ? null : xml };
|
|
128
121
|
}
|
|
129
122
|
function hasPattern(shd) {
|
|
130
|
-
const val =
|
|
123
|
+
const val = wAttrValue(shd.attrs, "val");
|
|
131
124
|
return val !== null && val !== "clear" && val !== "nil";
|
|
132
125
|
}
|
|
133
126
|
function editedShading(current, fill) {
|
|
134
|
-
const tag = current
|
|
127
|
+
const tag = current.tag ?? wName("shd");
|
|
135
128
|
if (fill === null) {
|
|
136
129
|
if (!hasPattern(current)) return null;
|
|
137
|
-
return elementXml(tag, setAttr(
|
|
130
|
+
return elementXml(tag, setAttr(current.attrs, "shd", "fill", "auto"));
|
|
138
131
|
}
|
|
139
|
-
if (
|
|
132
|
+
if (current.tag === null) {
|
|
140
133
|
return elementXml(tag, [
|
|
141
134
|
[wName("val"), "clear"],
|
|
142
135
|
[wName("color"), "auto"],
|
|
143
136
|
[wName("fill"), fill]
|
|
144
137
|
]);
|
|
145
138
|
}
|
|
146
|
-
const painting = hasPattern(current) ?
|
|
139
|
+
const painting = hasPattern(current) ? current.attrs : setAttr(current.attrs, "shd", "val", "clear");
|
|
147
140
|
return elementXml(tag, setAttr(painting, "shd", "fill", fill));
|
|
148
141
|
}
|
|
149
|
-
function bordersChange(props, edit, defaults) {
|
|
150
|
-
const current = propsChild(props.children, "tcBorders")?.xml ?? null;
|
|
151
|
-
const edited = editedBorders(current, edit, defaults);
|
|
152
|
-
return edited === null ? null : { name: "tcBorders", xml: edited.xml };
|
|
153
|
-
}
|
|
154
|
-
var TC_MAR_ORDER = [
|
|
155
|
-
"top",
|
|
156
|
-
"start",
|
|
157
|
-
"left",
|
|
158
|
-
"bottom",
|
|
159
|
-
"end",
|
|
160
|
-
"right"
|
|
161
|
-
];
|
|
162
142
|
var MARGIN_SIDE_NAMES = {
|
|
163
143
|
top: ["top"],
|
|
164
144
|
right: ["end", "right"],
|
|
165
145
|
bottom: ["bottom"],
|
|
166
146
|
left: ["start", "left"]
|
|
167
147
|
};
|
|
168
|
-
function
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (!parsed || current !== null && !margins) return null;
|
|
173
|
-
let edited = parsed;
|
|
148
|
+
function editedPadding(props, values) {
|
|
149
|
+
const margins = containerOf(props, "tcMar");
|
|
150
|
+
if (!margins) return null;
|
|
151
|
+
let edited = props;
|
|
174
152
|
let wrote = false;
|
|
175
153
|
for (const side of ALL_CELL_SIDES) {
|
|
176
154
|
const points = values[side];
|
|
177
155
|
if (points === void 0) continue;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
156
|
+
if (points < 0) return null;
|
|
157
|
+
const twips = ST_TwipsMeasure.format(Math.round(points * TWIPS_PER_PT));
|
|
158
|
+
if (twips === null) return null;
|
|
159
|
+
const name = MARGIN_SIDE_NAMES[side].find(
|
|
160
|
+
(spelling) => propsChild(margins.children, spelling) !== void 0
|
|
161
|
+
) ?? side;
|
|
162
|
+
const existing = childElement(margins, name);
|
|
163
|
+
if (existing === null || edited === null) return null;
|
|
184
164
|
const attrs = setAttr(
|
|
185
|
-
setAttr(
|
|
165
|
+
setAttr(existing.attrs, name, "w", twips),
|
|
186
166
|
name,
|
|
187
167
|
"type",
|
|
188
168
|
"dxa"
|
|
189
169
|
);
|
|
190
|
-
edited =
|
|
170
|
+
edited = editChild(
|
|
191
171
|
edited,
|
|
192
|
-
name,
|
|
193
|
-
|
|
194
|
-
TC_MAR_ORDER
|
|
172
|
+
["tcMar", name],
|
|
173
|
+
() => leafElement(existing.tag ?? wName(side), attrs)
|
|
195
174
|
);
|
|
196
175
|
wrote = true;
|
|
197
176
|
}
|
|
198
|
-
|
|
199
|
-
return { name: "tcMar", xml: renderProps(edited) };
|
|
177
|
+
return wrote ? edited : null;
|
|
200
178
|
}
|
|
201
|
-
function
|
|
179
|
+
function editedProps(edit, props, defaults) {
|
|
202
180
|
switch (edit.kind) {
|
|
203
181
|
case "background": {
|
|
204
182
|
const fill = edit.hex === null ? null : normalizeHex(edit.hex);
|
|
205
183
|
if (edit.hex !== null && fill === null) return null;
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return { name: "shd", xml: editedShading(shd, fill) };
|
|
184
|
+
const shd = childElement(props, "shd");
|
|
185
|
+
if (!shd) return null;
|
|
186
|
+
return setChild(props, "shd", editedShading(shd, fill));
|
|
210
187
|
}
|
|
211
188
|
case "borders":
|
|
212
|
-
return
|
|
189
|
+
return editedBorders(
|
|
213
190
|
props,
|
|
214
|
-
{
|
|
215
|
-
kind: "line",
|
|
216
|
-
line: edit.line,
|
|
217
|
-
sides: edit.sides
|
|
218
|
-
},
|
|
191
|
+
{ kind: "line", line: edit.line, sides: edit.sides },
|
|
219
192
|
defaults
|
|
220
193
|
);
|
|
221
194
|
case "borderColor": {
|
|
222
195
|
const hex = edit.hex === null ? null : normalizeHex(edit.hex);
|
|
223
196
|
if (edit.hex !== null && hex === null) return null;
|
|
224
|
-
return
|
|
197
|
+
return editedBorders(props, { kind: "color", hex }, defaults);
|
|
225
198
|
}
|
|
226
199
|
case "verticalAlign": {
|
|
227
|
-
const current =
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
setAttr(
|
|
200
|
+
const current = childElement(props, "vAlign");
|
|
201
|
+
if (!current) return null;
|
|
202
|
+
return setChild(
|
|
203
|
+
props,
|
|
204
|
+
"vAlign",
|
|
205
|
+
elementXml(
|
|
206
|
+
current.tag ?? wName("vAlign"),
|
|
207
|
+
setAttr(current.attrs, "vAlign", "val", edit.align)
|
|
235
208
|
)
|
|
236
|
-
|
|
209
|
+
);
|
|
237
210
|
}
|
|
238
211
|
case "padding":
|
|
239
|
-
return
|
|
212
|
+
return editedPadding(props, edit.values);
|
|
240
213
|
}
|
|
241
214
|
}
|
|
242
215
|
function editCellProps(tcPr, edit, defaults = NO_BORDER_DEFAULTS, margins = NO_CELL_MARGINS) {
|
|
243
216
|
const props = tcPr === null ? EMPTY_TC_PR : parseProps(tcPr);
|
|
244
217
|
if (!props) return null;
|
|
245
|
-
const
|
|
246
|
-
if (!
|
|
247
|
-
const rendered = renderProps(
|
|
248
|
-
setPropsChild(props, change.name, change.xml, TC_PR_ORDER)
|
|
249
|
-
);
|
|
218
|
+
const edited = editedProps(edit, props, defaults);
|
|
219
|
+
if (!edited) return null;
|
|
220
|
+
const rendered = renderProps(edited);
|
|
250
221
|
const next = rendered === "" ? null : rendered;
|
|
251
222
|
if (next === tcPr) return null;
|
|
252
223
|
return { tcPr: next, format: readCellProps(next, defaults, margins) };
|
|
253
224
|
}
|
|
254
225
|
function drawsOwnCellBorder(tcPr) {
|
|
255
|
-
const
|
|
256
|
-
const borders =
|
|
226
|
+
const props = tcPr === null ? null : parseProps(tcPr);
|
|
227
|
+
const borders = props && containerOf(props, "tcBorders");
|
|
257
228
|
if (!borders) return false;
|
|
258
229
|
return ALL_CELL_SIDES.some(
|
|
259
|
-
(side) => SIDE_NAMES[side].some((name) =>
|
|
230
|
+
(side) => SIDE_NAMES[side].some((name) => {
|
|
231
|
+
const element = childElement(borders, name);
|
|
232
|
+
return element !== null && drawsLine(element);
|
|
233
|
+
})
|
|
260
234
|
);
|
|
261
235
|
}
|
|
262
236
|
function editRowHeight(trPr, heightPt) {
|
|
263
|
-
const twips = Math.round(heightPt *
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
const props = trPr === null ? { tag: "w:trPr", attrs: null, children: [] } : parseProps(trPr);
|
|
237
|
+
const twips = heightPt > 0 ? ST_TwipsMeasure.format(Math.round(heightPt * TWIPS_PER_PT)) : null;
|
|
238
|
+
if (twips === null) return null;
|
|
239
|
+
const props = trPr === null ? { tag: wName("trPr"), attrs: null, children: [] } : parseProps(trPr);
|
|
268
240
|
if (!props) return null;
|
|
269
|
-
const current =
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
const attrs = setAttr(attrPairs(element), "trHeight", "val", `${twips}`);
|
|
241
|
+
const current = childElement(props, "trHeight");
|
|
242
|
+
if (!current) return null;
|
|
243
|
+
const writtenRule = wAttrValue(current.attrs, "hRule");
|
|
244
|
+
const attrs = setAttr(current.attrs, "trHeight", "val", twips);
|
|
274
245
|
const nextAttrs = setAttr(
|
|
275
246
|
attrs,
|
|
276
247
|
"trHeight",
|
|
277
248
|
"hRule",
|
|
278
249
|
writtenRule === "exact" ? "exact" : "atLeast"
|
|
279
250
|
);
|
|
280
|
-
const child = elementXml(
|
|
281
|
-
const rendered = renderProps(
|
|
282
|
-
setPropsChild(props, "trHeight", child, TR_PR_ORDER)
|
|
283
|
-
);
|
|
251
|
+
const child = elementXml(current.tag ?? wName("trHeight"), nextAttrs);
|
|
252
|
+
const rendered = renderProps(setChild(props, "trHeight", child));
|
|
284
253
|
if (rendered === trPr) return null;
|
|
285
254
|
const parsed = parsePropsXml(rendered);
|
|
286
255
|
const format = parsed ? readRowFormat(parsed) : null;
|
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
* collapsed-border resolution matches OOXML inheritance without changing exported XML.
|
|
4
4
|
*/
|
|
5
5
|
import type { CellFormat, CellMargins, InsideBorders, RowFormat, TableFormat, TableWidth } from "../../model/format";
|
|
6
|
+
import { type BorderLine } from "../../ooxml/units";
|
|
6
7
|
export type { CellMargins, InsideBorders } from "../../model/format";
|
|
8
|
+
/** The parts of a table a table style formats conditionally (`w:tblStylePr/@w:type`, ST_TblStyleOverrideType) */
|
|
9
|
+
export type TableStyleOverrideType = "wholeTable" | "firstRow" | "lastRow" | "firstCol" | "lastCol" | "band1Vert" | "band2Vert" | "band1Horz" | "band2Horz" | "neCell" | "nwCell" | "seCell" | "swCell";
|
|
7
10
|
/**
|
|
8
11
|
* The width written down by `<w:tblW>` or `<w:tcW>`.
|
|
9
12
|
* If we cannot make out what it means it is null, and such a width goes back out unchanged on export.
|
|
10
13
|
*
|
|
11
|
-
* `auto` and `nil` leave the width to the layout
|
|
14
|
+
* `auto` and `nil` leave the width to the layout unless the value carries an explicit percentage.
|
|
12
15
|
* A percentage may be written in fiftieths of a percent, as in `w:w="2500"`, or as `w:w="50%"`.
|
|
13
16
|
* Both have to be gathered into the same unit, or the table collapses into a thin strip on screen.
|
|
17
|
+
* Word lets an explicit `%` override `w:type` (MS-OI29500 §2.1.185(b)); see
|
|
18
|
+
* spec/notes/simpleTypes.md. A universal measure under `pct` remains unreadable here.
|
|
14
19
|
*/
|
|
15
20
|
export declare function readTableWidth(parent: Element | null, name: "tblW" | "tcW"): TableWidth | null;
|
|
16
21
|
/** The sequence of column widths (dxa) set by `<w:tblGrid>`. Revision markup (tblGridChange) is skipped */
|
|
@@ -32,12 +37,17 @@ export declare function readCellMarginsOf(parent: Element | null, name: "tblCell
|
|
|
32
37
|
* their cell padding from.
|
|
33
38
|
*/
|
|
34
39
|
export declare function layerCellMargins(style: CellMargins, direct: CellMargins): CellMargins;
|
|
35
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* The lines a cell falls back on, one per side, already resolved for its spot in the grid.
|
|
42
|
+
*
|
|
43
|
+
* They are held as the markup records them rather than as CSS, because a cell that takes one of
|
|
44
|
+
* them over as a border of its own writes it back into `w:tcBorders`.
|
|
45
|
+
*/
|
|
36
46
|
export interface CellBorderDefaults {
|
|
37
|
-
top:
|
|
38
|
-
bottom:
|
|
39
|
-
left:
|
|
40
|
-
right:
|
|
47
|
+
top: BorderLine | null;
|
|
48
|
+
bottom: BorderLine | null;
|
|
49
|
+
left: BorderLine | null;
|
|
50
|
+
right: BorderLine | null;
|
|
41
51
|
}
|
|
42
52
|
export declare const NO_BORDER_DEFAULTS: CellBorderDefaults;
|
|
43
53
|
/** Which sides of a cell lie on the edge of the table's grid */
|
|
@@ -1,31 +1,43 @@
|
|
|
1
1
|
// src/docx/tableFormatting/reading.ts
|
|
2
|
+
import { parsePropsXml } from "../../ooxml/props.js";
|
|
3
|
+
import {
|
|
4
|
+
ST_MeasurementOrPercent,
|
|
5
|
+
ST_SignedTwipsMeasure,
|
|
6
|
+
ST_TwipsMeasure
|
|
7
|
+
} from "../../ooxml/simpleTypes.js";
|
|
2
8
|
import {
|
|
3
9
|
ALIGN_BY_JC,
|
|
10
|
+
borderLineCss,
|
|
11
|
+
borderLineOfCss,
|
|
4
12
|
borderSide,
|
|
5
13
|
childValue,
|
|
6
14
|
isOn,
|
|
7
15
|
shadingOf,
|
|
8
|
-
toNumber,
|
|
9
16
|
twipsToPt,
|
|
10
17
|
wAttr
|
|
11
18
|
} from "../../ooxml/units.js";
|
|
12
19
|
import { childByLocalName } from "../../ooxml/xml.js";
|
|
13
|
-
|
|
20
|
+
var FIFTIETHS_PER_PERCENT = 50;
|
|
14
21
|
function readTableWidth(parent, name) {
|
|
15
22
|
const el = parent ? childByLocalName(parent, name) : null;
|
|
16
23
|
if (!el) return null;
|
|
17
24
|
const type = wAttr(el, "type") ?? "dxa";
|
|
25
|
+
const width = ST_MeasurementOrPercent.parse(wAttr(el, "w"));
|
|
26
|
+
if (width?.kind === "percent") {
|
|
27
|
+
const fiftieths = Math.round(width.value * FIFTIETHS_PER_PERCENT);
|
|
28
|
+
return Number.isFinite(fiftieths) ? { type: "pct", fiftieths } : null;
|
|
29
|
+
}
|
|
18
30
|
if (type === "auto") return { type: "auto" };
|
|
19
31
|
if (type === "nil") return { type: "nil" };
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
if (width === null) return null;
|
|
33
|
+
if (type === "dxa") {
|
|
34
|
+
return { type: "dxa", twips: width.value };
|
|
35
|
+
}
|
|
24
36
|
if (type === "pct") {
|
|
25
|
-
|
|
37
|
+
if (width.kind === "twips") return null;
|
|
26
38
|
return {
|
|
27
39
|
type: "pct",
|
|
28
|
-
fiftieths:
|
|
40
|
+
fiftieths: width.value
|
|
29
41
|
};
|
|
30
42
|
}
|
|
31
43
|
return null;
|
|
@@ -35,7 +47,7 @@ function readGridCols(tblGrid) {
|
|
|
35
47
|
const cols = [];
|
|
36
48
|
for (const child of Array.from(tblGrid.children)) {
|
|
37
49
|
if (child.localName !== "gridCol") continue;
|
|
38
|
-
const w =
|
|
50
|
+
const w = ST_TwipsMeasure.parse(wAttr(child, "w"));
|
|
39
51
|
if (w !== null) cols.push(w);
|
|
40
52
|
}
|
|
41
53
|
return cols;
|
|
@@ -69,7 +81,7 @@ function marginSide(margins, names) {
|
|
|
69
81
|
if (!el) continue;
|
|
70
82
|
const type = wAttr(el, "type") ?? "dxa";
|
|
71
83
|
if (type === "nil") return 0;
|
|
72
|
-
return type === "dxa" ? twipsToPt(wAttr(el, "w")) : null;
|
|
84
|
+
return type === "dxa" ? twipsToPt(ST_TwipsMeasure.parse(wAttr(el, "w"))) : null;
|
|
73
85
|
}
|
|
74
86
|
return null;
|
|
75
87
|
}
|
|
@@ -107,10 +119,18 @@ function gridEdgesOf(rect, grid) {
|
|
|
107
119
|
}
|
|
108
120
|
function cellBorderDefaults(edges, outer, inside) {
|
|
109
121
|
return {
|
|
110
|
-
top:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
122
|
+
top: borderLineOfCss(
|
|
123
|
+
edges.top ? outer?.borderTop ?? null : inside.horizontal
|
|
124
|
+
),
|
|
125
|
+
bottom: borderLineOfCss(
|
|
126
|
+
edges.bottom ? outer?.borderBottom ?? null : inside.horizontal
|
|
127
|
+
),
|
|
128
|
+
left: borderLineOfCss(
|
|
129
|
+
edges.left ? outer?.borderLeft ?? null : inside.vertical
|
|
130
|
+
),
|
|
131
|
+
right: borderLineOfCss(
|
|
132
|
+
edges.right ? outer?.borderRight ?? null : inside.vertical
|
|
133
|
+
)
|
|
114
134
|
};
|
|
115
135
|
}
|
|
116
136
|
function tblStyleIdOf(tblPr) {
|
|
@@ -133,12 +153,12 @@ function readTableFormat(tblPr) {
|
|
|
133
153
|
const align = ALIGN_BY_JC[childValue(tblPr, "jc") ?? ""];
|
|
134
154
|
if (align) format.align = align;
|
|
135
155
|
const tblInd = childByLocalName(tblPr, "tblInd");
|
|
136
|
-
const indentLeftPt = tblInd ? twipsToPt(wAttr(tblInd, "w")) : null;
|
|
156
|
+
const indentLeftPt = tblInd ? twipsToPt(ST_SignedTwipsMeasure.parse(wAttr(tblInd, "w"))) : null;
|
|
137
157
|
if (indentLeftPt !== null) format.indentLeftPt = indentLeftPt;
|
|
138
158
|
return format;
|
|
139
159
|
}
|
|
140
160
|
function readRowHeight(trHeight) {
|
|
141
|
-
const pt = twipsToPt(wAttr(trHeight, "val"));
|
|
161
|
+
const pt = twipsToPt(ST_TwipsMeasure.parse(wAttr(trHeight, "val")));
|
|
142
162
|
if (pt === null || pt <= 0) return null;
|
|
143
163
|
const rule = wAttr(trHeight, "hRule") === "exact" ? "exact" : "atLeast";
|
|
144
164
|
return { rule, pt };
|
|
@@ -170,13 +190,13 @@ function readCellPadding(tcPr, margins) {
|
|
|
170
190
|
function readCellFormat(tcPr, defaults, margins = NO_CELL_MARGINS) {
|
|
171
191
|
const borders = tcPr ? childByLocalName(tcPr, "tcBorders") : null;
|
|
172
192
|
const format = {};
|
|
173
|
-
const top = borderSide(borders, "top") ?? defaults.top;
|
|
193
|
+
const top = borderSide(borders, "top") ?? borderLineCss(defaults.top);
|
|
174
194
|
if (top) format.borderTop = top;
|
|
175
|
-
const bottom = borderSide(borders, "bottom") ?? defaults.bottom;
|
|
195
|
+
const bottom = borderSide(borders, "bottom") ?? borderLineCss(defaults.bottom);
|
|
176
196
|
if (bottom) format.borderBottom = bottom;
|
|
177
|
-
const left = borderSide(borders, "left") ?? borderSide(borders, "start") ?? defaults.left;
|
|
197
|
+
const left = borderSide(borders, "left") ?? borderSide(borders, "start") ?? borderLineCss(defaults.left);
|
|
178
198
|
if (left) format.borderLeft = left;
|
|
179
|
-
const right = borderSide(borders, "right") ?? borderSide(borders, "end") ?? defaults.right;
|
|
199
|
+
const right = borderSide(borders, "right") ?? borderSide(borders, "end") ?? borderLineCss(defaults.right);
|
|
180
200
|
if (right) format.borderRight = right;
|
|
181
201
|
if (tcPr) {
|
|
182
202
|
const background = shadingOf(tcPr);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/docx/tableTemplate.ts
|
|
2
2
|
import { elementXml } from "../ooxml/element.js";
|
|
3
3
|
import { wName } from "../ooxml/names.js";
|
|
4
|
+
import { orderedElement, parsePropsXml } from "../ooxml/props.js";
|
|
4
5
|
import { docxSchema } from "../schema/index.js";
|
|
5
6
|
import { A4_PORTRAIT, bodyWidth } from "./pageGeometry.js";
|
|
6
|
-
import { parsePropsXml } from "./propsXml.js";
|
|
7
7
|
import {
|
|
8
8
|
cellBorderDefaults,
|
|
9
9
|
gridEdgesOf,
|
|
@@ -35,14 +35,21 @@ function borderXml(side) {
|
|
|
35
35
|
]);
|
|
36
36
|
}
|
|
37
37
|
function tablePropsXml(width) {
|
|
38
|
-
const borders =
|
|
39
|
-
|
|
38
|
+
const borders = orderedElement(
|
|
39
|
+
wName("tblBorders"),
|
|
40
|
+
[],
|
|
41
|
+
BORDER_SIDES.map((side) => ({ name: side, xml: borderXml(side) }))
|
|
42
|
+
);
|
|
43
|
+
return orderedElement(
|
|
40
44
|
wName("tblPr"),
|
|
41
45
|
[],
|
|
42
46
|
[
|
|
43
|
-
widthXml("tblW", width),
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
{ name: "tblW", xml: widthXml("tblW", width) },
|
|
48
|
+
{ name: "tblBorders", xml: borders },
|
|
49
|
+
{
|
|
50
|
+
name: "tblLayout",
|
|
51
|
+
xml: elementXml(wName("tblLayout"), [[wName("type"), "fixed"]])
|
|
52
|
+
}
|
|
46
53
|
]
|
|
47
54
|
);
|
|
48
55
|
}
|
|
@@ -53,7 +60,11 @@ function widthXml(name, width) {
|
|
|
53
60
|
]);
|
|
54
61
|
}
|
|
55
62
|
function cellPropsXml(width) {
|
|
56
|
-
return
|
|
63
|
+
return orderedElement(
|
|
64
|
+
wName("tcPr"),
|
|
65
|
+
[],
|
|
66
|
+
[{ name: "tcW", xml: widthXml("tcW", width) }]
|
|
67
|
+
);
|
|
57
68
|
}
|
|
58
69
|
function evenGridCols(cols, total) {
|
|
59
70
|
const base = Math.floor(total / cols);
|
package/dist/download.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Node as PMNode } from "prosemirror-model";
|
|
8
8
|
import type { DocxEditorHandle } from "./DocxEditor";
|
|
9
|
+
import type { ExportProblem } from "./docx/invariants";
|
|
9
10
|
export declare const DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
10
11
|
export interface DownloadDocxOptions {
|
|
11
12
|
/** The name to save under. The `.docx` suffix may be there or not */
|
|
@@ -19,6 +20,9 @@ export type DownloadDocxResult = {
|
|
|
19
20
|
status: "unavailable";
|
|
20
21
|
} | {
|
|
21
22
|
status: "empty";
|
|
23
|
+
} | {
|
|
24
|
+
status: "blocked";
|
|
25
|
+
problems: readonly ExportProblem[];
|
|
22
26
|
};
|
|
23
27
|
/** Settles the end of the name on exactly one `.docx` */
|
|
24
28
|
export declare function withDocxExtension(fileName: string): string;
|
|
@@ -48,10 +52,9 @@ export declare function hasExportableContent(doc: PMNode): boolean;
|
|
|
48
52
|
* Downloads the edited document as a docx file.
|
|
49
53
|
*
|
|
50
54
|
* `unavailable` when the editor is not mounted yet or the document could not be
|
|
51
|
-
* opened, `empty` when there is nothing to export,
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* is rethrown as is.
|
|
55
|
+
* opened, `empty` when there is nothing to export, `blocked` with every reason
|
|
56
|
+
* when the document cannot be written back (a new list in a document without
|
|
57
|
+
* numbering.xml, and the like), and `exported` once a file has gone out.
|
|
58
|
+
* A refusal the check did not foresee is still thrown as `DocxExportError`.
|
|
56
59
|
*/
|
|
57
60
|
export declare function downloadDocx(editor: DocxEditorHandle | null | undefined, options: DownloadDocxOptions): DownloadDocxResult;
|
package/dist/download.js
CHANGED
|
@@ -29,6 +29,8 @@ function hasExportableContent(doc) {
|
|
|
29
29
|
function downloadDocx(editor, options) {
|
|
30
30
|
if (!editor) return { status: "unavailable" };
|
|
31
31
|
if (!hasExportableContent(editor.view.state.doc)) return { status: "empty" };
|
|
32
|
+
const problems = editor.exportProblems();
|
|
33
|
+
if (problems.length > 0) return { status: "blocked", problems };
|
|
32
34
|
const bytes = editor.exportBytes();
|
|
33
35
|
const fileName = withDocxExtension(options.fileName);
|
|
34
36
|
downloadBlob(createDocxBlob(bytes), fileName);
|