@portone/docx-editor 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +155 -0
- package/CONTRIBUTING.md +5 -1
- package/dist/DocxEditor.d.ts +6 -0
- package/dist/DocxEditor.js +13 -29
- package/dist/core.d.ts +23 -8
- package/dist/core.js +9 -4
- package/dist/docx/cloning.d.ts +38 -0
- package/dist/docx/cloning.js +74 -0
- package/dist/docx/commentOnlyChange.d.ts +12 -7
- package/dist/docx/commentOnlyChange.js +9 -156
- package/dist/docx/comments/constants.d.ts +0 -1
- package/dist/docx/comments/constants.js +0 -2
- package/dist/docx/comments/grammar.d.ts +10 -4
- package/dist/docx/comments/grammar.js +12 -2
- package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
- package/dist/docx/comments/parts.js +279 -0
- package/dist/docx/comments/people.d.ts +11 -2
- package/dist/docx/comments/people.js +16 -92
- package/dist/docx/comments/policy.d.ts +7 -0
- package/dist/docx/comments/policy.js +43 -0
- package/dist/docx/comments/reading.js +8 -10
- package/dist/docx/comments/writing.d.ts +19 -7
- package/dist/docx/comments/writing.js +59 -112
- package/dist/docx/documentSettings.d.ts +7 -0
- package/dist/docx/documentSettings.js +10 -2
- package/dist/docx/exportDocx.d.ts +40 -5
- package/dist/docx/exportDocx.js +88 -74
- package/dist/docx/exportRefs.d.ts +5 -2
- package/dist/docx/exportRefs.js +3 -1
- package/dist/docx/fidelity.d.ts +43 -0
- package/dist/docx/fidelity.js +64 -0
- package/dist/docx/formatting/attrs.d.ts +45 -0
- package/dist/docx/formatting/attrs.js +86 -0
- package/dist/docx/formatting/context.d.ts +39 -0
- package/dist/docx/formatting/context.js +60 -0
- package/dist/docx/formatting/direct.d.ts +6 -5
- package/dist/docx/formatting/direct.js +52 -78
- package/dist/docx/formatting/resolve.d.ts +51 -0
- package/dist/docx/formatting/resolve.js +160 -0
- package/dist/docx/formatting/runProperties.d.ts +93 -0
- package/dist/docx/formatting/runProperties.js +316 -0
- package/dist/docx/formatting/styles.d.ts +25 -2
- package/dist/docx/formatting/styles.js +87 -6
- package/dist/docx/formatting/tabStops.js +7 -22
- package/dist/docx/formatting.d.ts +4 -1
- package/dist/docx/formatting.js +4 -1
- package/dist/docx/headersFooters.js +6 -13
- package/dist/docx/hyperlink.d.ts +14 -4
- package/dist/docx/hyperlink.js +4 -1
- package/dist/docx/identities.d.ts +67 -0
- package/dist/docx/identities.js +174 -0
- package/dist/docx/importDocx.d.ts +12 -1
- package/dist/docx/importDocx.js +90 -88
- package/dist/docx/importParagraph.d.ts +1 -1
- package/dist/docx/importParagraph.js +4 -3
- package/dist/docx/importTable.d.ts +2 -2
- package/dist/docx/importTable.js +69 -56
- package/dist/docx/invariants.d.ts +33 -0
- package/dist/docx/invariants.js +269 -0
- package/dist/docx/media.d.ts +6 -4
- package/dist/docx/media.js +6 -37
- package/dist/docx/newLists.d.ts +50 -0
- package/dist/docx/newLists.js +59 -0
- package/dist/docx/notes.js +3 -7
- package/dist/docx/numberingPlanner.d.ts +11 -0
- package/dist/docx/numberingPlanner.js +50 -0
- package/dist/docx/packageParts.d.ts +42 -0
- package/dist/docx/packageParts.js +135 -0
- package/dist/docx/pageGeometry.d.ts +2 -0
- package/dist/docx/pageGeometry.js +18 -9
- package/dist/docx/paraProps.d.ts +10 -22
- package/dist/docx/paraProps.js +47 -76
- package/dist/docx/partPlan.d.ts +36 -0
- package/dist/docx/partPlan.js +59 -0
- package/dist/docx/protectionPolicy.d.ts +127 -0
- package/dist/docx/protectionPolicy.js +169 -0
- package/dist/docx/relationships.d.ts +1 -1
- package/dist/docx/relationships.js +8 -13
- package/dist/docx/runProps.d.ts +9 -22
- package/dist/docx/runProps.js +15 -168
- package/dist/docx/scan.js +20 -52
- package/dist/docx/sdt.js +9 -34
- package/dist/docx/sdtProps.d.ts +8 -1
- package/dist/docx/sdtProps.js +10 -0
- package/dist/docx/serializeBlock.d.ts +2 -0
- package/dist/docx/serializeBlock.js +8 -5
- package/dist/docx/serializeTable.js +32 -15
- package/dist/docx/session.d.ts +42 -14
- package/dist/docx/session.js +53 -17
- package/dist/docx/tableFormatting/conditions.d.ts +76 -0
- package/dist/docx/tableFormatting/conditions.js +196 -0
- package/dist/docx/tableFormatting/editing.d.ts +7 -3
- package/dist/docx/tableFormatting/editing.js +111 -143
- package/dist/docx/tableFormatting/reading.d.ts +63 -23
- package/dist/docx/tableFormatting/reading.js +132 -38
- package/dist/docx/tableFormatting.d.ts +1 -0
- package/dist/docx/tableFormatting.js +1 -0
- package/dist/docx/tableTemplate.js +30 -19
- package/dist/download.d.ts +8 -5
- package/dist/download.js +2 -0
- package/dist/editor/clipboard/inlineFormatting.js +19 -30
- package/dist/editor/commands/comments/editing.d.ts +6 -2
- package/dist/editor/commands/comments/editing.js +19 -31
- package/dist/editor/commands/exportQueries.d.ts +15 -0
- package/dist/editor/commands/exportQueries.js +14 -0
- package/dist/editor/commands/fidelityQueries.d.ts +12 -0
- package/dist/editor/commands/fidelityQueries.js +8 -0
- package/dist/editor/commands/formatting/editing.d.ts +2 -2
- package/dist/editor/commands/formatting/editing.js +26 -108
- package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
- package/dist/editor/commands/formatting/propertyCommands.js +108 -0
- package/dist/editor/commands/formatting/shared.d.ts +3 -3
- package/dist/editor/commands/formatting/shared.js +5 -2
- package/dist/editor/commands/indentCommands.js +5 -4
- package/dist/editor/commands/index.d.ts +11 -0
- package/dist/editor/commands/index.js +5 -0
- package/dist/editor/commands/linkCommands.js +5 -6
- package/dist/editor/commands/listCommands.d.ts +6 -3
- package/dist/editor/commands/listCommands.js +73 -30
- package/dist/editor/commands/lockCommands.d.ts +7 -1
- package/dist/editor/commands/lockCommands.js +35 -46
- package/dist/editor/commands/paragraphCommands.js +33 -31
- package/dist/editor/commands/spacingCommands.js +1 -1
- package/dist/editor/createEditor.d.ts +17 -29
- package/dist/editor/createEditor.js +58 -58
- package/dist/editor/documentStyles.d.ts +11 -35
- package/dist/editor/documentStyles.js +9 -52
- package/dist/editor/editorDocument.d.ts +57 -0
- package/dist/editor/editorDocument.js +86 -0
- package/dist/editor/externalClipboard.d.ts +13 -2
- package/dist/editor/externalClipboard.js +76 -75
- package/dist/editor/insertTable.js +4 -3
- package/dist/editor/paragraphEdits.d.ts +27 -19
- package/dist/editor/paragraphEdits.js +18 -19
- package/dist/editor/paragraphPlacement.d.ts +11 -0
- package/dist/editor/paragraphPlacement.js +18 -0
- package/dist/editor/plugins/displayDerivation.d.ts +47 -0
- package/dist/editor/plugins/displayDerivation.js +78 -0
- package/dist/editor/plugins/imagePaste.js +11 -7
- package/dist/editor/plugins/keymap.js +18 -3
- package/dist/editor/plugins/numberingDecorations.d.ts +14 -14
- package/dist/editor/plugins/numberingDecorations.js +50 -19
- package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
- package/dist/editor/plugins/paragraphDisplay.js +57 -0
- package/dist/editor/plugins/tabLayout.js +1 -1
- package/dist/editor/plugins/tableDisplay.d.ts +6 -0
- package/dist/editor/plugins/tableDisplay.js +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/model/format.d.ts +80 -8
- package/dist/model/format.js +100 -22
- package/dist/model/tabStops.d.ts +9 -0
- package/dist/model/tabStops.js +18 -0
- package/dist/numbering/listRegistry.d.ts +37 -0
- package/dist/numbering/listRegistry.js +112 -0
- package/dist/numbering/listTemplate.d.ts +26 -17
- package/dist/numbering/listTemplate.js +88 -25
- package/dist/numbering/markers.d.ts +15 -6
- package/dist/numbering/markers.js +26 -59
- package/dist/numbering/parseNumbering.d.ts +84 -6
- package/dist/numbering/parseNumbering.js +131 -44
- package/dist/numbering/spellers.d.ts +15 -0
- package/dist/numbering/spellers.js +96 -0
- package/dist/numbering/writeNumbering.d.ts +8 -7
- package/dist/numbering/writeNumbering.js +28 -39
- package/dist/ooxml/childOrder.d.ts +34 -0
- package/dist/ooxml/childOrder.js +496 -0
- package/dist/ooxml/conformance.d.ts +28 -0
- package/dist/ooxml/conformance.js +20 -0
- package/dist/ooxml/element.d.ts +24 -11
- package/dist/ooxml/element.js +31 -12
- package/dist/ooxml/errors.d.ts +6 -5
- package/dist/ooxml/image.d.ts +4 -0
- package/dist/ooxml/image.js +2 -5
- package/dist/ooxml/names.d.ts +9 -0
- package/dist/ooxml/names.js +8 -1
- package/dist/ooxml/partSplice.d.ts +67 -0
- package/dist/ooxml/partSplice.js +176 -0
- package/dist/ooxml/props.d.ts +112 -0
- package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
- package/dist/ooxml/simpleTypes.d.ts +103 -0
- package/dist/ooxml/simpleTypes.js +182 -0
- package/dist/ooxml/tabStops.js +8 -27
- package/dist/ooxml/tagScan.d.ts +34 -0
- package/dist/ooxml/tagScan.js +108 -0
- package/dist/ooxml/units.d.ts +25 -13
- package/dist/ooxml/units.js +65 -31
- package/dist/ooxml/xml.d.ts +35 -15
- package/dist/ooxml/xml.js +43 -11
- package/dist/page/PageGuides.d.ts +1 -1
- package/dist/page/PageGuides.js +0 -13
- package/dist/page/blockKinds.d.ts +61 -0
- package/dist/page/blockKinds.js +11 -0
- package/dist/page/kinds/index.d.ts +6 -0
- package/dist/page/kinds/index.js +10 -0
- package/dist/page/kinds/paragraphKind.d.ts +10 -0
- package/dist/page/kinds/paragraphKind.js +71 -0
- package/dist/page/kinds/tableKind.d.ts +10 -0
- package/dist/page/kinds/tableKind.js +178 -0
- package/dist/page/measureBlocks.d.ts +3 -14
- package/dist/page/measureBlocks.js +24 -45
- package/dist/page/pageDecorations.d.ts +27 -44
- package/dist/page/pageDecorations.js +70 -152
- package/dist/page/pageLayout.d.ts +2 -29
- package/dist/page/pageLayout.js +39 -16
- package/dist/page/usePageLayout.d.ts +2 -24
- package/dist/page/usePageLayout.js +5 -48
- package/dist/schema/attrRoles.d.ts +25 -18
- package/dist/schema/attrRoles.js +110 -68
- package/dist/schema/displayDerivation.d.ts +82 -0
- package/dist/schema/displayDerivation.js +130 -0
- package/dist/schema/docxSchema.d.ts +3 -0
- package/dist/schema/docxSchema.js +58 -17
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.d.ts +37 -14
- package/dist/schema/guards.js +29 -3
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/locks.d.ts +11 -44
- package/dist/schema/locks.js +0 -9
- package/dist/schema/preservedGuards.d.ts +26 -6
- package/dist/schema/preservedGuards.js +31 -1
- package/dist/schema/protection.d.ts +7 -1
- package/dist/schema/protection.js +2 -1
- package/dist/schema/sourceEquality.d.ts +1 -9
- package/dist/schema/sourceEquality.js +1 -27
- package/dist/styles/classNames.d.ts +13 -2
- package/dist/styles/classNames.js +13 -2
- package/dist/styles/inlineStyle.js +15 -6
- package/dist/styles.css +16 -18
- package/dist/table/cellFormatting.d.ts +8 -1
- package/dist/table/cellFormatting.js +11 -20
- package/dist/table/commands.js +20 -18
- package/dist/table/format.d.ts +3 -0
- package/dist/table/format.js +3 -9
- package/dist/table/gridBorders.d.ts +24 -30
- package/dist/table/gridBorders.js +35 -59
- package/dist/table/merge.d.ts +2 -6
- package/dist/table/merge.js +5 -5
- package/package.json +7 -3
- package/dist/docx/comments/contentTypes.d.ts +0 -7
- package/dist/docx/comments/contentTypes.js +0 -38
- package/dist/docx/comments/verifying.js +0 -206
- package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
- package/dist/docx/formatting/effectiveParagraph.js +0 -81
- package/dist/docx/propsXml.d.ts +0 -67
- package/dist/docx/uniqueControls.d.ts +0 -14
- package/dist/docx/uniqueControls.js +0 -62
- package/dist/editor/plugins/commentReservations.d.ts +0 -5
- package/dist/editor/plugins/commentReservations.js +0 -26
- package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
- package/dist/editor/plugins/styledParagraphs.js +0 -65
- package/dist/page/tableMeasurements.d.ts +0 -18
- package/dist/page/tableMeasurements.js +0 -119
package/dist/docx/importTable.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
// src/docx/importTable.ts
|
|
2
|
-
import {
|
|
3
|
-
toCellMargins,
|
|
4
|
-
toInsideBorders
|
|
5
|
-
} from "../model/format.js";
|
|
6
2
|
import { childValue, wAttr } from "../ooxml/units.js";
|
|
7
3
|
import {
|
|
8
4
|
attrString,
|
|
@@ -13,7 +9,10 @@ import {
|
|
|
13
9
|
import { docxSchema } from "../schema/index.js";
|
|
14
10
|
import {
|
|
15
11
|
layerTableFormat,
|
|
16
|
-
|
|
12
|
+
NO_FORMATTING,
|
|
13
|
+
styledParagraph,
|
|
14
|
+
tableStyleAttrs,
|
|
15
|
+
tableStyleFor
|
|
17
16
|
} from "./formatting.js";
|
|
18
17
|
import {
|
|
19
18
|
buildParagraph,
|
|
@@ -21,18 +20,22 @@ import {
|
|
|
21
20
|
} from "./importParagraph.js";
|
|
22
21
|
import { readSdtWrapper } from "./sdt.js";
|
|
23
22
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
cellConditionsOf,
|
|
24
|
+
cellDefaultsFor,
|
|
25
|
+
layerBandSizes,
|
|
26
26
|
layerCellMargins,
|
|
27
27
|
layerInsideBorders,
|
|
28
|
+
NO_BAND_SIZES,
|
|
28
29
|
NO_CELL_MARGINS,
|
|
29
30
|
NO_INSIDE_BORDERS,
|
|
31
|
+
readBandSizes,
|
|
30
32
|
readCellFormat,
|
|
31
33
|
readCellMarginsOf,
|
|
32
34
|
readGridCols,
|
|
33
35
|
readInsideBorders,
|
|
34
36
|
readRowFormat,
|
|
35
37
|
readTableFormat,
|
|
38
|
+
readTableLook,
|
|
36
39
|
readTableWidth,
|
|
37
40
|
tblStyleIdOf
|
|
38
41
|
} from "./tableFormatting.js";
|
|
@@ -86,9 +89,23 @@ function readRow(el) {
|
|
|
86
89
|
}
|
|
87
90
|
return cells.length > 0 ? { el, tblPrEx, cells } : null;
|
|
88
91
|
}
|
|
92
|
+
function gridRevisionXml(grid) {
|
|
93
|
+
const revision = childByLocalName(grid, "tblGridChange");
|
|
94
|
+
if (revision === null) return null;
|
|
95
|
+
const declarations = Array.from(grid.attributes).filter(
|
|
96
|
+
(attr) => attr.namespaceURI === "http://www.w3.org/2000/xmlns/" && !revision.hasAttribute(attr.name)
|
|
97
|
+
);
|
|
98
|
+
if (declarations.length === 0) return serializeXml(revision);
|
|
99
|
+
const preserved = revision.ownerDocument.importNode(revision, true);
|
|
100
|
+
for (const attr of declarations) {
|
|
101
|
+
preserved.setAttributeNS(attr.namespaceURI, attr.name, attr.value);
|
|
102
|
+
}
|
|
103
|
+
return serializeXml(preserved);
|
|
104
|
+
}
|
|
89
105
|
function readTableParts(el) {
|
|
90
106
|
let tblPr = null;
|
|
91
107
|
let tblGrid = null;
|
|
108
|
+
let gridChange = null;
|
|
92
109
|
const rows = [];
|
|
93
110
|
for (const child of elementChildren(el)) {
|
|
94
111
|
if (child.localName === "tblPr") {
|
|
@@ -97,6 +114,7 @@ function readTableParts(el) {
|
|
|
97
114
|
}
|
|
98
115
|
if (child.localName === "tblGrid") {
|
|
99
116
|
tblGrid = child;
|
|
117
|
+
gridChange = gridRevisionXml(child);
|
|
100
118
|
continue;
|
|
101
119
|
}
|
|
102
120
|
if (child.localName !== "tr") return null;
|
|
@@ -104,7 +122,7 @@ function readTableParts(el) {
|
|
|
104
122
|
if (!row) return null;
|
|
105
123
|
rows.push(row);
|
|
106
124
|
}
|
|
107
|
-
return rows.length > 0 ? { tblPr, tblGrid, rows } : null;
|
|
125
|
+
return rows.length > 0 ? { tblPr, tblGrid, gridChange, rows } : null;
|
|
108
126
|
}
|
|
109
127
|
function resolveVerticalMerges(rows, width) {
|
|
110
128
|
const drafts = [];
|
|
@@ -147,37 +165,31 @@ function gridWidthOf(rows) {
|
|
|
147
165
|
const first = widths[0];
|
|
148
166
|
return widths.every((width) => width === first) ? first : null;
|
|
149
167
|
}
|
|
150
|
-
function buildCellBlock(el, sources) {
|
|
168
|
+
function buildCellBlock(el, sources, context, placement) {
|
|
151
169
|
if (el.localName === "p") {
|
|
152
170
|
const paragraph = buildParagraph(el, null, sources);
|
|
153
|
-
if (paragraph) return paragraph;
|
|
171
|
+
if (paragraph) return styledParagraph(paragraph, context, placement);
|
|
154
172
|
}
|
|
155
173
|
return docxSchema.nodes.rawBlock.create({
|
|
156
174
|
xml: serializeXml(el),
|
|
157
175
|
name: el.nodeName
|
|
158
176
|
});
|
|
159
177
|
}
|
|
160
|
-
function
|
|
161
|
-
return
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
right: draft.col + draft.colspan
|
|
168
|
-
},
|
|
169
|
-
lines
|
|
170
|
-
),
|
|
171
|
-
lines.outer,
|
|
172
|
-
lines.inside
|
|
173
|
-
);
|
|
178
|
+
function cellRect(draft) {
|
|
179
|
+
return {
|
|
180
|
+
top: draft.row,
|
|
181
|
+
bottom: draft.row + draft.rowspan,
|
|
182
|
+
left: draft.col,
|
|
183
|
+
right: draft.col + draft.colspan
|
|
184
|
+
};
|
|
174
185
|
}
|
|
175
|
-
function buildCell(draft,
|
|
186
|
+
function buildCell(draft, table, sources, context) {
|
|
176
187
|
const tcPr = childByLocalName(draft.el, "tcPr");
|
|
188
|
+
const defaults = cellDefaultsFor(cellRect(draft), table.grid, table.sources);
|
|
177
189
|
const blocks = [];
|
|
178
190
|
for (const child of elementChildren(draft.el)) {
|
|
179
191
|
if (child.localName === "tcPr") continue;
|
|
180
|
-
blocks.push(buildCellBlock(child, sources));
|
|
192
|
+
blocks.push(buildCellBlock(child, sources, context, defaults.placement));
|
|
181
193
|
}
|
|
182
194
|
if (blocks.length === 0) return null;
|
|
183
195
|
return docxSchema.nodes.tableCell.create(
|
|
@@ -188,11 +200,7 @@ function buildCell(draft, lines, sources) {
|
|
|
188
200
|
tcAttrs: attrString(draft.el),
|
|
189
201
|
tcPr: tcPr ? serializeXml(tcPr) : null,
|
|
190
202
|
tcW: readTableWidth(tcPr, "tcW"),
|
|
191
|
-
format: readCellFormat(
|
|
192
|
-
tcPr,
|
|
193
|
-
cellBorderDefaultsFor(draft, lines),
|
|
194
|
-
lines.margins
|
|
195
|
-
),
|
|
203
|
+
format: readCellFormat(tcPr, defaults),
|
|
196
204
|
sdtPrefix: draft.control?.prefix ?? null,
|
|
197
205
|
sdtContentsLocked: draft.control?.contentsLocked ?? false,
|
|
198
206
|
sdtDeletionLocked: draft.control?.deletionLocked ?? false
|
|
@@ -200,10 +208,10 @@ function buildCell(draft, lines, sources) {
|
|
|
200
208
|
blocks
|
|
201
209
|
);
|
|
202
210
|
}
|
|
203
|
-
function buildRow(row, drafts,
|
|
211
|
+
function buildRow(row, drafts, table, sources, context) {
|
|
204
212
|
const cells = [];
|
|
205
213
|
for (const draft of drafts) {
|
|
206
|
-
const cell = buildCell(draft,
|
|
214
|
+
const cell = buildCell(draft, table, sources, context);
|
|
207
215
|
if (!cell) return null;
|
|
208
216
|
cells.push(cell);
|
|
209
217
|
}
|
|
@@ -218,11 +226,7 @@ function buildRow(row, drafts, lines, sources) {
|
|
|
218
226
|
cells
|
|
219
227
|
);
|
|
220
228
|
}
|
|
221
|
-
function
|
|
222
|
-
const styleId = tblStyleIdOf(tblPr);
|
|
223
|
-
return (styleId !== null ? styles.get(styleId) : void 0) ?? (defaultTableStyleId !== null ? styles.get(defaultTableStyleId) : void 0);
|
|
224
|
-
}
|
|
225
|
-
function buildTable(el, srcId, sources = NO_IMPORT_SOURCES, styles = NO_STYLES, defaultTableStyleId = null) {
|
|
229
|
+
function buildTable(el, srcId, sources = NO_IMPORT_SOURCES, context = NO_FORMATTING) {
|
|
226
230
|
const parts = readTableParts(el);
|
|
227
231
|
if (!parts) return null;
|
|
228
232
|
const gridCols = readGridCols(parts.tblGrid);
|
|
@@ -231,27 +235,38 @@ function buildTable(el, srcId, sources = NO_IMPORT_SOURCES, styles = NO_STYLES,
|
|
|
231
235
|
if (gridCols.length > 0 && gridCols.length !== width) return null;
|
|
232
236
|
const drafts = resolveVerticalMerges(parts.rows, width);
|
|
233
237
|
if (!drafts) return null;
|
|
234
|
-
const
|
|
238
|
+
const styleId = tblStyleIdOf(parts.tblPr);
|
|
239
|
+
const style = tableStyleFor(styleId, context);
|
|
235
240
|
const tableFormat = layerTableFormat(
|
|
236
241
|
style?.table ?? {},
|
|
237
242
|
readTableFormat(parts.tblPr)
|
|
238
243
|
);
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
244
|
+
const bands = layerBandSizes(
|
|
245
|
+
style?.tableBands ?? NO_BAND_SIZES,
|
|
246
|
+
readBandSizes(parts.tblPr)
|
|
247
|
+
);
|
|
248
|
+
const conditions = cellConditionsOf(style?.tableConditions ?? {});
|
|
249
|
+
const table = {
|
|
250
|
+
grid: { rows: parts.rows.length, cols: width },
|
|
251
|
+
sources: {
|
|
252
|
+
outer: tableFormat,
|
|
253
|
+
inside: layerInsideBorders(
|
|
254
|
+
style?.tableInside ?? NO_INSIDE_BORDERS,
|
|
255
|
+
readInsideBorders(parts.tblPr)
|
|
256
|
+
),
|
|
257
|
+
margins: layerCellMargins(
|
|
258
|
+
style?.tableCellMargins ?? NO_CELL_MARGINS,
|
|
259
|
+
readCellMarginsOf(parts.tblPr, "tblCellMar")
|
|
260
|
+
),
|
|
261
|
+
look: readTableLook(parts.tblPr),
|
|
262
|
+
bands,
|
|
263
|
+
conditions,
|
|
264
|
+
styleId
|
|
265
|
+
}
|
|
251
266
|
};
|
|
252
267
|
const rows = [];
|
|
253
268
|
for (const [index, row] of parts.rows.entries()) {
|
|
254
|
-
const built = buildRow(row, drafts[index],
|
|
269
|
+
const built = buildRow(row, drafts[index], table, sources, context);
|
|
255
270
|
if (!built) return null;
|
|
256
271
|
rows.push(built);
|
|
257
272
|
}
|
|
@@ -262,10 +277,8 @@ 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,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
styleInside: toInsideBorders(style?.tableInside),
|
|
268
|
-
styleCellMargins: toCellMargins(style?.tableCellMargins)
|
|
280
|
+
gridChange: parts.gridChange,
|
|
281
|
+
...tableStyleAttrs(parts.tblPr, context)
|
|
269
282
|
},
|
|
270
283
|
rows
|
|
271
284
|
);
|
|
@@ -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[];
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// src/docx/invariants.ts
|
|
2
|
+
import { spanCount, toParagraphFormat } from "../model/format.js";
|
|
3
|
+
import {
|
|
4
|
+
attributeByLocalName,
|
|
5
|
+
parseXml,
|
|
6
|
+
W_NS,
|
|
7
|
+
withXmlParser
|
|
8
|
+
} from "../ooxml/xml.js";
|
|
9
|
+
import {
|
|
10
|
+
commentReferencesIn,
|
|
11
|
+
commentsChanged,
|
|
12
|
+
commentsRootProblem,
|
|
13
|
+
extensionsChanged,
|
|
14
|
+
extensionsRootProblem
|
|
15
|
+
} from "./comments.js";
|
|
16
|
+
import {
|
|
17
|
+
commentsExtendedPart,
|
|
18
|
+
commentsPart,
|
|
19
|
+
peoplePart
|
|
20
|
+
} from "./comments/parts.js";
|
|
21
|
+
import { unrecordedAuthors } from "./comments/people.js";
|
|
22
|
+
import { currentCommentBodies } from "./comments/writing.js";
|
|
23
|
+
import { identityProblems } from "./identities.js";
|
|
24
|
+
import { insertedImageSrcs } from "./media.js";
|
|
25
|
+
import { canDefineNewList, newNumIds, startedLists } from "./newLists.js";
|
|
26
|
+
import { CONTENT_TYPES_PATH } from "./packageParts.js";
|
|
27
|
+
import { lostOriginal } from "./serializeBlock.js";
|
|
28
|
+
import {
|
|
29
|
+
originalBlock,
|
|
30
|
+
sessionOf
|
|
31
|
+
} 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
|
+
var bookmarkPairs = {
|
|
42
|
+
name: "bookmarkPairs",
|
|
43
|
+
check(doc, session) {
|
|
44
|
+
const problems = [];
|
|
45
|
+
const open = /* @__PURE__ */ new Map();
|
|
46
|
+
const used = /* @__PURE__ */ new Set();
|
|
47
|
+
doc.descendants((node, pos) => {
|
|
48
|
+
const source = markerSourceOf(node, session);
|
|
49
|
+
if (source === null) return true;
|
|
50
|
+
if (!source.includes("bookmark")) return true;
|
|
51
|
+
let root;
|
|
52
|
+
try {
|
|
53
|
+
root = parseXml(
|
|
54
|
+
session.documentPrefix + source + session.documentSuffix
|
|
55
|
+
).documentElement;
|
|
56
|
+
} catch {
|
|
57
|
+
problems.push({
|
|
58
|
+
code: "malformed-xml",
|
|
59
|
+
message: "preserved bookmark XML could not be parsed",
|
|
60
|
+
pos
|
|
61
|
+
});
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
for (const marker of Array.from(root.getElementsByTagName("*"))) {
|
|
65
|
+
if (marker.namespaceURI !== W_NS || marker.localName !== "bookmarkStart" && marker.localName !== "bookmarkEnd")
|
|
66
|
+
continue;
|
|
67
|
+
const kind = marker.localName.slice("bookmark".length);
|
|
68
|
+
const value = attributeByLocalName(marker, "id");
|
|
69
|
+
if (value === null || value === "") {
|
|
70
|
+
problems.push({
|
|
71
|
+
code: "malformed-xml",
|
|
72
|
+
message: `a bookmark${kind} has no id`,
|
|
73
|
+
pos
|
|
74
|
+
});
|
|
75
|
+
} else if (kind === "Start") {
|
|
76
|
+
if (used.has(value)) {
|
|
77
|
+
problems.push({
|
|
78
|
+
code: "malformed-xml",
|
|
79
|
+
message: `bookmark ${value} has more than one start marker`,
|
|
80
|
+
pos
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
open.set(value, pos);
|
|
84
|
+
used.add(value);
|
|
85
|
+
}
|
|
86
|
+
} else if (!open.delete(value)) {
|
|
87
|
+
problems.push({
|
|
88
|
+
code: "malformed-xml",
|
|
89
|
+
message: `bookmark ${value} ends without an earlier start marker`,
|
|
90
|
+
pos
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
});
|
|
96
|
+
for (const [id, pos] of open) {
|
|
97
|
+
problems.push({
|
|
98
|
+
code: "malformed-xml",
|
|
99
|
+
message: `bookmark ${id} has no end marker`,
|
|
100
|
+
pos
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return problems;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
function mergeReachesPastLastRow(table) {
|
|
107
|
+
let overlong = false;
|
|
108
|
+
table.forEach((row, _offset, at) => {
|
|
109
|
+
row.forEach((cell) => {
|
|
110
|
+
if (at + spanCount(cell.attrs.rowspan) > table.childCount) {
|
|
111
|
+
overlong = true;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
return overlong;
|
|
116
|
+
}
|
|
117
|
+
var tableGrids = {
|
|
118
|
+
name: "tableGrids",
|
|
119
|
+
check(doc) {
|
|
120
|
+
const problems = [];
|
|
121
|
+
doc.descendants((node, pos) => {
|
|
122
|
+
if (node.type.name !== "table") return true;
|
|
123
|
+
if (mergeReachesPastLastRow(node)) {
|
|
124
|
+
problems.push({
|
|
125
|
+
code: "invalid-table",
|
|
126
|
+
message: "a vertical merge in the table reaches past the last row",
|
|
127
|
+
pos
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
});
|
|
132
|
+
return problems;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
function lostOriginalOf(node, session) {
|
|
136
|
+
if (node.type.name === "rawInline" || node.type.name === "rawBlock") {
|
|
137
|
+
return typeof node.attrs.xml === "string" ? null : "a preserved element has lost its original XML";
|
|
138
|
+
}
|
|
139
|
+
if (node.type.isInGroup("preserved")) {
|
|
140
|
+
return originalBlock(node, session) ? null : lostOriginal(node, session);
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
var preservedOriginals = {
|
|
145
|
+
name: "preservedOriginals",
|
|
146
|
+
check(doc, session) {
|
|
147
|
+
const problems = [];
|
|
148
|
+
doc.descendants((node, pos) => {
|
|
149
|
+
const message = lostOriginalOf(node, session);
|
|
150
|
+
if (message !== null)
|
|
151
|
+
problems.push({ code: "lost-original", message, pos });
|
|
152
|
+
return true;
|
|
153
|
+
});
|
|
154
|
+
return problems;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var uniqueIdentities = {
|
|
158
|
+
name: "uniqueIdentities",
|
|
159
|
+
check(doc) {
|
|
160
|
+
return identityProblems(doc);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
var listDefinitions = {
|
|
164
|
+
name: "listDefinitions",
|
|
165
|
+
check(doc, session) {
|
|
166
|
+
const undefinedIds = new Set(startedLists(doc, session).unregistered);
|
|
167
|
+
if (undefinedIds.size === 0) return [];
|
|
168
|
+
const problems = [];
|
|
169
|
+
doc.descendants((node, pos) => {
|
|
170
|
+
if (node.type.name !== "paragraph") return true;
|
|
171
|
+
const numId = toParagraphFormat(node.attrs.format)?.numbering?.numId;
|
|
172
|
+
if (numId === void 0 || !undefinedIds.delete(numId)) return false;
|
|
173
|
+
problems.push({
|
|
174
|
+
code: "unsupported-content",
|
|
175
|
+
message: `the list numbered ${numId} has no definition to be written`,
|
|
176
|
+
pos
|
|
177
|
+
});
|
|
178
|
+
return false;
|
|
179
|
+
});
|
|
180
|
+
return problems;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
function addsCommentsPart(doc, session) {
|
|
184
|
+
const bodyChanged = commentsChanged(doc, session);
|
|
185
|
+
const threadChanged = extensionsChanged(doc, session);
|
|
186
|
+
if (!bodyChanged && !threadChanged) return false;
|
|
187
|
+
if (commentsPart.pathIn(session) === null || session.comments.xml === null)
|
|
188
|
+
return true;
|
|
189
|
+
const references = commentReferencesIn(doc);
|
|
190
|
+
if (threadChanged && (references.size > 0 || session.comments.extendedPartPath !== null) && (commentsExtendedPart.pathIn(session) === null || session.comments.extendedXml === null))
|
|
191
|
+
return true;
|
|
192
|
+
return bodyChanged && (peoplePart.pathIn(session) === null || session.comments.people.xml === null) && unrecordedAuthors(
|
|
193
|
+
currentCommentBodies(references).values(),
|
|
194
|
+
session.comments.people
|
|
195
|
+
).size > 0;
|
|
196
|
+
}
|
|
197
|
+
var mediaContentTypes = {
|
|
198
|
+
name: "mediaContentTypes",
|
|
199
|
+
check(doc, session) {
|
|
200
|
+
if (session.parts.has(CONTENT_TYPES_PATH)) return [];
|
|
201
|
+
const problems = [];
|
|
202
|
+
if (insertedImageSrcs(doc).length > 0) {
|
|
203
|
+
problems.push({
|
|
204
|
+
code: "missing-content-types",
|
|
205
|
+
message: `cannot add an image to a package that has no ${CONTENT_TYPES_PATH}`
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
if (!canDefineNewList(session) && newNumIds(doc, session).length > 0) {
|
|
209
|
+
problems.push({
|
|
210
|
+
code: "missing-content-types",
|
|
211
|
+
message: `cannot add a part to a package that has no ${CONTENT_TYPES_PATH}`
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (addsCommentsPart(doc, session)) {
|
|
215
|
+
problems.push({
|
|
216
|
+
code: "missing-content-types",
|
|
217
|
+
message: `cannot add a part to a package that has no ${CONTENT_TYPES_PATH}`
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return problems;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
var commentPartRoots = {
|
|
224
|
+
name: "commentPartRoots",
|
|
225
|
+
check(doc, session) {
|
|
226
|
+
const problems = [];
|
|
227
|
+
const { xml, extendedXml, extendedPartPath } = session.comments;
|
|
228
|
+
if (xml !== null && commentsChanged(doc, session)) {
|
|
229
|
+
const problem = commentsRootProblem(xml);
|
|
230
|
+
if (problem !== null)
|
|
231
|
+
problems.push({ code: "malformed-xml", message: problem });
|
|
232
|
+
}
|
|
233
|
+
if (extendedXml !== null && extensionsChanged(doc, session) && (commentReferencesIn(doc).size > 0 || extendedPartPath !== null)) {
|
|
234
|
+
const problem = extensionsRootProblem(extendedXml);
|
|
235
|
+
if (problem !== null)
|
|
236
|
+
problems.push({ code: "malformed-xml", message: problem });
|
|
237
|
+
}
|
|
238
|
+
return problems;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
var EXPORT_INVARIANTS = [
|
|
242
|
+
bookmarkPairs,
|
|
243
|
+
tableGrids,
|
|
244
|
+
preservedOriginals,
|
|
245
|
+
uniqueIdentities,
|
|
246
|
+
listDefinitions,
|
|
247
|
+
mediaContentTypes,
|
|
248
|
+
commentPartRoots
|
|
249
|
+
];
|
|
250
|
+
var answered = /* @__PURE__ */ new WeakMap();
|
|
251
|
+
function problemsOf(doc, session) {
|
|
252
|
+
const known = answered.get(doc);
|
|
253
|
+
if (known && known.session === session) return known.problems;
|
|
254
|
+
const problems = EXPORT_INVARIANTS.flatMap(
|
|
255
|
+
(invariant) => invariant.check(doc, session)
|
|
256
|
+
);
|
|
257
|
+
answered.set(doc, { session, problems });
|
|
258
|
+
return problems;
|
|
259
|
+
}
|
|
260
|
+
function exportProblems(doc, session, options) {
|
|
261
|
+
return withXmlParser(
|
|
262
|
+
options?.xmlParser,
|
|
263
|
+
() => problemsOf(doc, sessionOf(session))
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
export {
|
|
267
|
+
exportProblems,
|
|
268
|
+
problemsOf
|
|
269
|
+
};
|
package/dist/docx/media.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* bytes without blob-URL lifetime management; `MAX_IMAGE_BYTES` bounds the memory tradeoff.
|
|
4
4
|
*/
|
|
5
5
|
import type { Node as PMNode } from "prosemirror-model";
|
|
6
|
-
import {
|
|
6
|
+
import type { PartPlanContext } from "./partPlan";
|
|
7
7
|
import type { SessionStore } from "./session";
|
|
8
8
|
/** The images the body can refer to, as data URLs keyed by relationship id */
|
|
9
9
|
export type ImageSources = ReadonlyMap<string, string>;
|
|
@@ -46,10 +46,12 @@ export interface MediaAdditions {
|
|
|
46
46
|
/** The parts to write into the zip alongside the body */
|
|
47
47
|
parts: ReadonlyMap<string, Uint8Array>;
|
|
48
48
|
}
|
|
49
|
+
/** The srcs of the images that were not in the document when it was opened, in document order */
|
|
50
|
+
export declare function insertedImageSrcs(doc: PMNode): string[];
|
|
49
51
|
/**
|
|
50
52
|
* What the package needs for the images that were inserted during editing: the media parts,
|
|
51
|
-
* the relationships pointing at them
|
|
52
|
-
* null when every image in the document came out of the document itself.
|
|
53
|
+
* with the relationships pointing at them and the content types declaring them asked of the
|
|
54
|
+
* context. null when every image in the document came out of the document itself.
|
|
53
55
|
*
|
|
54
56
|
* The relationships go through the writer the export shares between its writers
|
|
55
57
|
* (`docx/relationships`), so the part is written once with everything in it.
|
|
@@ -57,4 +59,4 @@ export interface MediaAdditions {
|
|
|
57
59
|
* Bytes that are already in the package are not written a second time: an inserted image
|
|
58
60
|
* whose fingerprint matches one that is already there reuses its relationship.
|
|
59
61
|
*/
|
|
60
|
-
export declare function planImageMedia(doc: PMNode, session: SessionStore,
|
|
62
|
+
export declare function planImageMedia(doc: PMNode, session: SessionStore, context: PartPlanContext): MediaAdditions | null;
|
package/dist/docx/media.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
imageMimeOf,
|
|
6
6
|
toImageSrc
|
|
7
7
|
} from "../ooxml/image.js";
|
|
8
|
-
import {
|
|
8
|
+
import { R_NS } from "../ooxml/xml.js";
|
|
9
9
|
import {
|
|
10
10
|
directoryOf,
|
|
11
11
|
readRelationships,
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
resolveTarget
|
|
14
14
|
} from "./relationships.js";
|
|
15
15
|
var IMAGE_REL_TYPE = `${R_NS}/image`;
|
|
16
|
-
var CONTENT_TYPES_PATH = "[Content_Types].xml";
|
|
17
16
|
var EXTENSION_BY_MIME = {
|
|
18
17
|
"image/png": "png",
|
|
19
18
|
"image/jpeg": "jpeg",
|
|
@@ -114,6 +113,7 @@ function decodeImage(src) {
|
|
|
114
113
|
const bytes = fromBase64(imageBase64Of(src));
|
|
115
114
|
return {
|
|
116
115
|
bytes,
|
|
116
|
+
mime,
|
|
117
117
|
extension: EXTENSION_BY_MIME[mime],
|
|
118
118
|
key: contentKey(bytes)
|
|
119
119
|
};
|
|
@@ -148,42 +148,14 @@ function maxDocPrId(session) {
|
|
|
148
148
|
}
|
|
149
149
|
return max;
|
|
150
150
|
}
|
|
151
|
-
|
|
152
|
-
function withImageContentTypes(parts, extensions) {
|
|
153
|
-
const original = parts.get(CONTENT_TYPES_PATH);
|
|
154
|
-
if (!original) {
|
|
155
|
-
throw new DocxExportError(
|
|
156
|
-
"missing-content-types",
|
|
157
|
-
`cannot add an image to a package that has no ${CONTENT_TYPES_PATH}`
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
const { text, hadBom } = decodeUtf8(original);
|
|
161
|
-
const missing = Array.from(extensions).filter(
|
|
162
|
-
(extension) => !new RegExp(`<Default[^>]+Extension="${extension}"`, "i").test(text)
|
|
163
|
-
);
|
|
164
|
-
if (missing.length === 0) return null;
|
|
165
|
-
const open = TYPES_OPEN_TAG.exec(text);
|
|
166
|
-
if (!open) {
|
|
167
|
-
throw new DocxExportError(
|
|
168
|
-
"malformed-xml",
|
|
169
|
-
`${CONTENT_TYPES_PATH} has no Types element`
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
const declarations = missing.map((extension) => {
|
|
173
|
-
const mime = MIME_BY_EXTENSION.get(extension);
|
|
174
|
-
return `<Default Extension="${extension}" ContentType="${mime}"/>`;
|
|
175
|
-
}).join("");
|
|
176
|
-
const at = open.index + open[0].length;
|
|
177
|
-
return encodeUtf8(text.slice(0, at) + declarations + text.slice(at), hadBom);
|
|
178
|
-
}
|
|
179
|
-
function planImageMedia(doc, session, relationships) {
|
|
151
|
+
function planImageMedia(doc, session, context) {
|
|
180
152
|
const srcs = insertedImageSrcs(doc);
|
|
181
153
|
if (srcs.length === 0) return null;
|
|
154
|
+
const { relationships, contentTypes } = context;
|
|
182
155
|
const relIdByContent = imageRelIdsByContent(session, relationships.opened);
|
|
183
156
|
const directory = directoryOf(session.mainPartPath);
|
|
184
157
|
const relIdBySrc = /* @__PURE__ */ new Map();
|
|
185
158
|
const parts = /* @__PURE__ */ new Map();
|
|
186
|
-
const extensions = /* @__PURE__ */ new Set();
|
|
187
159
|
for (const src of srcs) {
|
|
188
160
|
const image = decodeImage(src);
|
|
189
161
|
const reused = relIdByContent.get(image.key);
|
|
@@ -194,20 +166,17 @@ function planImageMedia(doc, session, relationships) {
|
|
|
194
166
|
const target = `media/image-${image.key}.${image.extension}`;
|
|
195
167
|
const relId = relationships.add({ type: IMAGE_REL_TYPE, target });
|
|
196
168
|
parts.set(directory + target, image.bytes);
|
|
197
|
-
|
|
169
|
+
contentTypes.addDefault(image.extension, image.mime);
|
|
198
170
|
relIdByContent.set(image.key, relId);
|
|
199
171
|
relIdBySrc.set(src, relId);
|
|
200
172
|
}
|
|
201
|
-
if (extensions.size > 0) {
|
|
202
|
-
const contentTypes = withImageContentTypes(session.parts, extensions);
|
|
203
|
-
if (contentTypes) parts.set(CONTENT_TYPES_PATH, contentTypes);
|
|
204
|
-
}
|
|
205
173
|
return { refs: imageRefs(relIdBySrc, maxDocPrId(session) + 1), parts };
|
|
206
174
|
}
|
|
207
175
|
export {
|
|
208
176
|
MAX_IMAGE_BYTES,
|
|
209
177
|
NO_IMAGES,
|
|
210
178
|
NO_IMAGE_REFS,
|
|
179
|
+
insertedImageSrcs,
|
|
211
180
|
planImageMedia,
|
|
212
181
|
readImageSources
|
|
213
182
|
};
|