odf.js 6.2.1 → 6.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/README.md +22 -2
- package/dist/{cascade-BDkyOmoo.d.cts → cascade-BpMwrjkB.d.cts} +1 -1
- package/dist/{cascade-CaVinmvp.d.ts → cascade-PDS3hgrP.d.ts} +1 -1
- package/dist/{codec-B72LApRl.d.cts → codec-BnzBd5_I.d.cts} +10 -8
- package/dist/{codec-rbZGlr37.d.ts → codec-Dg_HWuH1.d.ts} +10 -8
- package/dist/codec.d.cts +1 -1
- package/dist/codec.d.ts +1 -1
- package/dist/{embedded-UQQNFd5U.js → embedded-BONPxvS3.js} +1 -2
- package/dist/{embedded-BsO-SvtW.cjs → embedded-wrtHCJ68.cjs} +1 -2
- package/dist/index.cjs +20 -1
- package/dist/index.d.cts +12 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.js +9 -7
- package/dist/{list-DwTyo_B2.d.cts → list-Bttwr1mk.d.cts} +7 -1
- package/dist/{list-X_GJY7P3.d.ts → list-vhXd0Jf6.d.ts} +7 -1
- package/dist/metadata-BUzwE_-u.d.ts +10 -0
- package/dist/metadata-CYXgXL_h.d.cts +10 -0
- package/dist/ooo1/read.cjs +1 -1
- package/dist/ooo1/read.js +1 -1
- package/dist/package-io/scaffold.cjs +64 -0
- package/dist/package-io/scaffold.d.cts +2 -0
- package/dist/package-io/scaffold.d.ts +2 -0
- package/dist/package-io/scaffold.js +61 -0
- package/dist/paragraph-BdwsQisB.d.cts +28 -0
- package/dist/paragraph-BoVy1LrN.d.ts +28 -0
- package/dist/{registry-Dajfxsbz.d.ts → registry-C_16-N6i.d.ts} +2 -0
- package/dist/{registry-B-ZkdQv1.d.cts → registry-PoQIRgbY.d.cts} +2 -0
- package/dist/scaffold-44EIMGll.d.cts +8 -0
- package/dist/scaffold-ehGsIpZ5.d.ts +8 -0
- package/dist/{shapes-BCjeY90t.d.cts → shapes-BQhXAk0D.d.cts} +1 -1
- package/dist/{shapes-QkOsc-WT.d.ts → shapes-DUzrrf7b.d.ts} +1 -1
- package/dist/styles/properties.cjs +1 -1
- package/dist/styles/properties.js +2 -2
- package/dist/styles/registry.cjs +9 -6
- package/dist/styles/registry.d.cts +1 -1
- package/dist/styles/registry.d.ts +1 -1
- package/dist/styles/registry.js +9 -6
- package/dist/{table-CYvFMlP6.d.cts → table-ByhqRnSG.d.cts} +3 -1
- package/dist/{table-DclDgC5h.d.ts → table-DElqGcT0.d.ts} +3 -1
- package/dist/text-B8350HA2.d.ts +17 -0
- package/dist/text-pmlTqzgi.d.cts +17 -0
- package/dist/typed/draw/embedded.cjs +1 -1
- package/dist/typed/draw/embedded.js +1 -1
- package/dist/typed/draw/shapes.d.cts +1 -1
- package/dist/typed/draw/shapes.d.ts +1 -1
- package/dist/typed/odb/form.cjs +1 -1
- package/dist/typed/odb/form.js +1 -1
- package/dist/typed/ods/read.cjs +1 -1
- package/dist/typed/ods/read.js +1 -1
- package/dist/typed/odt/read.cjs +1 -1
- package/dist/typed/odt/read.js +1 -1
- package/dist/typed/odt/write.cjs +409 -0
- package/dist/typed/odt/write.d.cts +2 -0
- package/dist/typed/odt/write.d.ts +2 -0
- package/dist/typed/odt/write.js +406 -0
- package/dist/typed/shared/cascade.d.cts +1 -1
- package/dist/typed/shared/cascade.d.ts +1 -1
- package/dist/typed/shared/list.cjs +49 -0
- package/dist/typed/shared/list.d.cts +2 -2
- package/dist/typed/shared/list.d.ts +2 -2
- package/dist/typed/shared/list.js +48 -1
- package/dist/typed/shared/metadata.cjs +41 -0
- package/dist/typed/shared/metadata.d.cts +2 -2
- package/dist/typed/shared/metadata.d.ts +2 -2
- package/dist/typed/shared/metadata.js +41 -2
- package/dist/typed/shared/paragraph.cjs +118 -2
- package/dist/typed/shared/paragraph.d.cts +2 -2
- package/dist/typed/shared/paragraph.d.ts +2 -2
- package/dist/typed/shared/paragraph.js +117 -5
- package/dist/typed/shared/table.cjs +81 -0
- package/dist/typed/shared/table.d.cts +2 -2
- package/dist/typed/shared/table.d.ts +2 -2
- package/dist/typed/shared/table.js +84 -4
- package/dist/typed/shared/text.cjs +60 -0
- package/dist/typed/shared/text.d.cts +2 -2
- package/dist/typed/shared/text.d.ts +2 -2
- package/dist/typed/shared/text.js +60 -2
- package/dist/write-7Uu_wlkL.d.cts +13 -0
- package/dist/write-DGcI9W7Z.d.ts +13 -0
- package/package.json +1 -1
- package/dist/metadata-01SgHkRR.d.cts +0 -7
- package/dist/metadata-D1SOBTh8.d.ts +0 -7
- package/dist/paragraph-ByTzS8Li.d.ts +0 -18
- package/dist/paragraph-CVULactG.d.cts +0 -18
- package/dist/text-Bn3C7lnm.d.ts +0 -10
- package/dist/text-CDUCcwje.d.cts +0 -10
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import { ODF_MEDIA_TYPES } from "../../media-type.js";
|
|
2
|
+
import { el, txt } from "../../xml/fragment.js";
|
|
3
|
+
import { encodeXmlText } from "../../xml/entities.js";
|
|
4
|
+
import { syncManifest } from "../../manifest.js";
|
|
5
|
+
import { formatOdfLength } from "../shared/units.js";
|
|
6
|
+
import { StyleRegistry } from "../../styles/registry.js";
|
|
7
|
+
import { writeOdfMetadata } from "../shared/metadata.js";
|
|
8
|
+
import { buildOdfListStyle, writeOdfList } from "../shared/list.js";
|
|
9
|
+
import { segmentOdfParagraphRuns, writeOdfParagraph } from "../shared/paragraph.js";
|
|
10
|
+
import { writeOdfTable } from "../shared/table.js";
|
|
11
|
+
import { createOdfPackage, odfPartContainer } from "../../package-io/scaffold.js";
|
|
12
|
+
import { colorToRgbHex, flattenTree, rgbHexToColor } from "document-schema.js";
|
|
13
|
+
//#region src/typed/odt/write.ts
|
|
14
|
+
const CONTENT_PART = "content.xml";
|
|
15
|
+
const STYLES_PART = "styles.xml";
|
|
16
|
+
const PICTURES_DIRECTORY = "Pictures";
|
|
17
|
+
function listKindOf(numId) {
|
|
18
|
+
if (numId === void 0) return;
|
|
19
|
+
if (numId.startsWith("ordered:")) return "ordered";
|
|
20
|
+
return numId.startsWith("bullet:") ? "bullet" : void 0;
|
|
21
|
+
}
|
|
22
|
+
const NO_NUM_ID_KEY = " ";
|
|
23
|
+
function canonicalNumId(incoming, ordinal) {
|
|
24
|
+
const kind = listKindOf(incoming);
|
|
25
|
+
return kind === void 0 ? `list${ordinal}` : `${kind}:list${ordinal}`;
|
|
26
|
+
}
|
|
27
|
+
function unsupported(what, where) {
|
|
28
|
+
return /* @__PURE__ */ new Error(`writeOdt: ${where} carries ${what}, which this writer does not write yet -- refusing rather than producing an .odt that silently lost it. See ExaDev/documents.js for the tracked follow-up covering the fidelity constructs and embedded objects.`);
|
|
29
|
+
}
|
|
30
|
+
function assertWritableParagraph(paragraph) {
|
|
31
|
+
if (paragraph.constructs !== void 0 && paragraph.constructs.length > 0) throw unsupported("run-level construct extents (a field, bookmark, note, annotation, or tracked change)", "a paragraph");
|
|
32
|
+
}
|
|
33
|
+
function assertWritableBlock(block) {
|
|
34
|
+
if (block.kind === "constructStart" || block.kind === "constructEnd") throw unsupported("a construct boundary marker", "a section's block flow");
|
|
35
|
+
if (block.kind === "embeddedObject") throw unsupported("an embedded object", "a section's block flow");
|
|
36
|
+
if (block.kind === "paragraph") assertWritableParagraph(block);
|
|
37
|
+
}
|
|
38
|
+
function canonicalColor(color) {
|
|
39
|
+
return rgbHexToColor(colorToRgbHex(color));
|
|
40
|
+
}
|
|
41
|
+
function canonicalRun(run) {
|
|
42
|
+
const canonical = { text: run.text };
|
|
43
|
+
if (run.bold !== void 0) canonical.bold = run.bold;
|
|
44
|
+
if (run.italic !== void 0) canonical.italic = run.italic;
|
|
45
|
+
if (run.underline !== void 0) canonical.underline = run.underline;
|
|
46
|
+
if (run.strike !== void 0) canonical.strike = run.strike;
|
|
47
|
+
if (run.fontFamily !== void 0) canonical.fontFamily = run.fontFamily;
|
|
48
|
+
if (run.sizePt !== void 0) canonical.sizePt = run.sizePt;
|
|
49
|
+
if (run.color !== void 0) canonical.color = canonicalColor(run.color);
|
|
50
|
+
if (run.hyperlink !== void 0) canonical.hyperlink = run.hyperlink;
|
|
51
|
+
return canonical;
|
|
52
|
+
}
|
|
53
|
+
function canonicalParagraph(paragraph, listNumId) {
|
|
54
|
+
const canonical = {
|
|
55
|
+
kind: "paragraph",
|
|
56
|
+
runs: segmentOdfParagraphRuns(paragraph.runs).map(canonicalRun)
|
|
57
|
+
};
|
|
58
|
+
if (paragraph.headingLevel !== void 0) {
|
|
59
|
+
canonical.headingLevel = paragraph.headingLevel;
|
|
60
|
+
canonical.styleId = `Heading${paragraph.headingLevel}`;
|
|
61
|
+
}
|
|
62
|
+
if (paragraph.alignment !== void 0) canonical.alignment = paragraph.alignment;
|
|
63
|
+
if (listNumId !== void 0 && paragraph.list !== void 0) canonical.list = {
|
|
64
|
+
numId: listNumId,
|
|
65
|
+
level: paragraph.list.level
|
|
66
|
+
};
|
|
67
|
+
if (paragraph.spacingBeforePt !== void 0) canonical.spacingBeforePt = paragraph.spacingBeforePt;
|
|
68
|
+
if (paragraph.spacingAfterPt !== void 0) canonical.spacingAfterPt = paragraph.spacingAfterPt;
|
|
69
|
+
if (paragraph.lineSpacing !== void 0) canonical.lineSpacing = paragraph.lineSpacing;
|
|
70
|
+
if (paragraph.indentLeftPt !== void 0) canonical.indentLeftPt = paragraph.indentLeftPt;
|
|
71
|
+
if (paragraph.indentFirstLinePt !== void 0) canonical.indentFirstLinePt = paragraph.indentFirstLinePt;
|
|
72
|
+
if (paragraph.pageBreakBefore !== void 0) canonical.pageBreakBefore = paragraph.pageBreakBefore;
|
|
73
|
+
if (paragraph.pageBreakAfter !== void 0) canonical.pageBreakAfter = paragraph.pageBreakAfter;
|
|
74
|
+
return canonical;
|
|
75
|
+
}
|
|
76
|
+
function emptyAnchorParagraph(pageBreakBefore) {
|
|
77
|
+
return pageBreakBefore ? {
|
|
78
|
+
kind: "paragraph",
|
|
79
|
+
runs: [],
|
|
80
|
+
pageBreakBefore: true
|
|
81
|
+
} : {
|
|
82
|
+
kind: "paragraph",
|
|
83
|
+
runs: []
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function planSection(section, needsLeadingParagraph, listState) {
|
|
87
|
+
const blocks = [];
|
|
88
|
+
let pendingPageBreak = false;
|
|
89
|
+
const pushParagraph = (paragraph) => {
|
|
90
|
+
blocks.push({
|
|
91
|
+
kind: "paragraph",
|
|
92
|
+
paragraph
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
const hasPlannedParagraph = () => {
|
|
96
|
+
for (let index = blocks.length - 1; index >= 0; index -= 1) if (blocks[index].kind === "paragraph") return true;
|
|
97
|
+
return false;
|
|
98
|
+
};
|
|
99
|
+
const closeListRun = () => {
|
|
100
|
+
listState.openNumId = void 0;
|
|
101
|
+
listState.openCanonicalNumId = void 0;
|
|
102
|
+
};
|
|
103
|
+
const flushPendingPageBreak = () => {
|
|
104
|
+
if (pendingPageBreak) {
|
|
105
|
+
pushParagraph(emptyAnchorParagraph(true));
|
|
106
|
+
closeListRun();
|
|
107
|
+
pendingPageBreak = false;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
if (needsLeadingParagraph) {
|
|
111
|
+
if (section.blocks.find((block) => block.kind !== "constructStart" && block.kind !== "constructEnd")?.kind !== "paragraph") pushParagraph(emptyAnchorParagraph(false));
|
|
112
|
+
}
|
|
113
|
+
for (const block of section.blocks) {
|
|
114
|
+
assertWritableBlock(block);
|
|
115
|
+
if (block.kind === "pageBreak") {
|
|
116
|
+
flushPendingPageBreak();
|
|
117
|
+
pendingPageBreak = true;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (block.kind === "paragraph") {
|
|
121
|
+
const membership = block.list;
|
|
122
|
+
if (membership === void 0) closeListRun();
|
|
123
|
+
else {
|
|
124
|
+
const incomingKey = membership.numId ?? NO_NUM_ID_KEY;
|
|
125
|
+
if (listState.openNumId !== incomingKey) {
|
|
126
|
+
listState.openNumId = incomingKey;
|
|
127
|
+
listState.openCanonicalNumId = canonicalNumId(membership.numId, listState.next);
|
|
128
|
+
listState.next += 1;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const paragraph = canonicalParagraph(block, membership === void 0 ? void 0 : listState.openCanonicalNumId);
|
|
132
|
+
pushParagraph(pendingPageBreak ? {
|
|
133
|
+
...paragraph,
|
|
134
|
+
pageBreakBefore: true
|
|
135
|
+
} : paragraph);
|
|
136
|
+
pendingPageBreak = false;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (block.kind === "table") {
|
|
140
|
+
flushPendingPageBreak();
|
|
141
|
+
closeListRun();
|
|
142
|
+
blocks.push({
|
|
143
|
+
kind: "table",
|
|
144
|
+
table: block
|
|
145
|
+
});
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
flushPendingPageBreak();
|
|
149
|
+
if (!hasPlannedParagraph()) pushParagraph(emptyAnchorParagraph(false));
|
|
150
|
+
blocks.push({
|
|
151
|
+
kind: "image",
|
|
152
|
+
image: block
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
flushPendingPageBreak();
|
|
156
|
+
return {
|
|
157
|
+
pageSize: section.pageSize,
|
|
158
|
+
margins: section.margins,
|
|
159
|
+
blocks
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function planDocument(sections) {
|
|
163
|
+
if (sections.length === 0) throw new Error("writeOdt: a wordprocessing document with no sections has no page geometry to write -- an .odt always carries at least one page style, and inventing one would report back a section the document never had");
|
|
164
|
+
const listState = { next: 1 };
|
|
165
|
+
return sections.map((section, index) => planSection(section, index > 0, listState));
|
|
166
|
+
}
|
|
167
|
+
function canonicalCell(cell, covered) {
|
|
168
|
+
if (covered) return { blocks: [] };
|
|
169
|
+
const canonical = { blocks: cell.blocks.map((block) => {
|
|
170
|
+
if (block.kind !== "paragraph") throw unsupported(`a "${block.kind}" block`, "a table cell");
|
|
171
|
+
assertWritableParagraph(block);
|
|
172
|
+
return canonicalParagraph(block, void 0);
|
|
173
|
+
}) };
|
|
174
|
+
if (cell.colSpan !== void 0) canonical.colSpan = cell.colSpan;
|
|
175
|
+
if (cell.rowSpan !== void 0) canonical.rowSpan = cell.rowSpan;
|
|
176
|
+
if (cell.background !== void 0) canonical.background = canonicalColor(cell.background);
|
|
177
|
+
if (cell.borders !== void 0) {
|
|
178
|
+
const borders = {};
|
|
179
|
+
for (const edge of [
|
|
180
|
+
"left",
|
|
181
|
+
"right",
|
|
182
|
+
"top",
|
|
183
|
+
"bottom"
|
|
184
|
+
]) {
|
|
185
|
+
const border = cell.borders[edge];
|
|
186
|
+
if (border !== void 0) borders[edge] = {
|
|
187
|
+
color: canonicalColor(border.color),
|
|
188
|
+
widthPt: border.widthPt,
|
|
189
|
+
style: border.style ?? "solid"
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
canonical.borders = borders;
|
|
193
|
+
}
|
|
194
|
+
return canonical;
|
|
195
|
+
}
|
|
196
|
+
function canonicalTable(table) {
|
|
197
|
+
const covered = /* @__PURE__ */ new Set();
|
|
198
|
+
return {
|
|
199
|
+
kind: "table",
|
|
200
|
+
columnWidthsPt: [...table.columnWidthsPt],
|
|
201
|
+
rows: table.rows.map((row, rowIndex) => {
|
|
202
|
+
const cells = row.cells.map((cell, columnIndex) => {
|
|
203
|
+
const key = `${rowIndex},${columnIndex}`;
|
|
204
|
+
const isCovered = covered.has(key);
|
|
205
|
+
if (!isCovered) {
|
|
206
|
+
const colSpan = cell.colSpan ?? 1;
|
|
207
|
+
const rowSpan = cell.rowSpan ?? 1;
|
|
208
|
+
for (let r = rowIndex; r < rowIndex + rowSpan; r += 1) for (let c = columnIndex; c < columnIndex + colSpan; c += 1) if (r !== rowIndex || c !== columnIndex) covered.add(`${r},${c}`);
|
|
209
|
+
}
|
|
210
|
+
return canonicalCell(cell, isCovered);
|
|
211
|
+
});
|
|
212
|
+
return row.heightPt === void 0 ? { cells } : {
|
|
213
|
+
cells,
|
|
214
|
+
heightPt: row.heightPt
|
|
215
|
+
};
|
|
216
|
+
})
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function canonicalImage(image) {
|
|
220
|
+
const canonical = {
|
|
221
|
+
kind: "image",
|
|
222
|
+
format: image.format,
|
|
223
|
+
base64: image.base64,
|
|
224
|
+
widthPt: image.widthPt,
|
|
225
|
+
heightPt: image.heightPt
|
|
226
|
+
};
|
|
227
|
+
if (image.altText !== void 0) canonical.altText = image.altText;
|
|
228
|
+
return canonical;
|
|
229
|
+
}
|
|
230
|
+
function canonicalMetadata(metadata) {
|
|
231
|
+
const canonical = {};
|
|
232
|
+
if (metadata.title !== void 0) canonical.title = metadata.title;
|
|
233
|
+
if (metadata.author !== void 0) canonical.author = metadata.author;
|
|
234
|
+
if (metadata.subject !== void 0) canonical.subject = metadata.subject;
|
|
235
|
+
if (metadata.keywords !== void 0 && metadata.keywords.length > 0) canonical.keywords = [...metadata.keywords];
|
|
236
|
+
if (metadata.creator !== void 0) canonical.creator = metadata.creator;
|
|
237
|
+
if (metadata.createdIso !== void 0) canonical.createdIso = metadata.createdIso;
|
|
238
|
+
if (metadata.modifiedIso !== void 0) canonical.modifiedIso = metadata.modifiedIso;
|
|
239
|
+
return canonical;
|
|
240
|
+
}
|
|
241
|
+
function normaliseOdtContent(document) {
|
|
242
|
+
if (document.kind !== "wordprocessing") throw new Error(`normaliseOdtContent: expected a 'wordprocessing' document, got '${document.kind}'`);
|
|
243
|
+
const planned = planDocument(document.sections);
|
|
244
|
+
return {
|
|
245
|
+
kind: "wordprocessing",
|
|
246
|
+
metadata: canonicalMetadata(document.metadata),
|
|
247
|
+
sections: planned.map((section, index) => {
|
|
248
|
+
const blocks = section.blocks.map((block) => {
|
|
249
|
+
switch (block.kind) {
|
|
250
|
+
case "paragraph": return block.paragraph;
|
|
251
|
+
case "table": return canonicalTable(block.table);
|
|
252
|
+
case "image": return canonicalImage(block.image);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
return index === 0 ? {
|
|
256
|
+
pageSize: section.pageSize,
|
|
257
|
+
margins: section.margins,
|
|
258
|
+
blocks
|
|
259
|
+
} : {
|
|
260
|
+
pageSize: section.pageSize,
|
|
261
|
+
margins: section.margins,
|
|
262
|
+
blocks,
|
|
263
|
+
breakType: "nextPage"
|
|
264
|
+
};
|
|
265
|
+
})
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function pageLayoutElement(name, pageSize, margins) {
|
|
269
|
+
return el("style:page-layout", { "style:name": encodeXmlText(name) }, [el("style:page-layout-properties", {
|
|
270
|
+
"fo:page-width": formatOdfLength(pageSize.widthPt),
|
|
271
|
+
"fo:page-height": formatOdfLength(pageSize.heightPt),
|
|
272
|
+
"style:print-orientation": pageSize.widthPt > pageSize.heightPt ? "landscape" : "portrait",
|
|
273
|
+
"fo:margin-top": formatOdfLength(margins.topPt),
|
|
274
|
+
"fo:margin-right": formatOdfLength(margins.rightPt),
|
|
275
|
+
"fo:margin-bottom": formatOdfLength(margins.bottomPt),
|
|
276
|
+
"fo:margin-left": formatOdfLength(margins.leftPt)
|
|
277
|
+
})]);
|
|
278
|
+
}
|
|
279
|
+
function sectionBreakStyleElement(name, masterPageName) {
|
|
280
|
+
return el("style:style", {
|
|
281
|
+
"style:name": encodeXmlText(name),
|
|
282
|
+
"style:family": "paragraph",
|
|
283
|
+
"style:master-page-name": encodeXmlText(masterPageName)
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function listStyleNameFor(kind, state) {
|
|
287
|
+
const existing = state.listStyleByKind.get(kind);
|
|
288
|
+
if (existing !== void 0) return existing;
|
|
289
|
+
const name = `L${state.nextListStyle}`;
|
|
290
|
+
state.nextListStyle += 1;
|
|
291
|
+
state.listStyleByKind.set(kind, name);
|
|
292
|
+
state.contentAutomaticStyles.children.push(buildOdfListStyle(name, kind));
|
|
293
|
+
return name;
|
|
294
|
+
}
|
|
295
|
+
function writeImageFrame(image, state) {
|
|
296
|
+
const extension = image.format === "png" ? "png" : "jpg";
|
|
297
|
+
const path = `${PICTURES_DIRECTORY}/image${state.nextImage}.${extension}`;
|
|
298
|
+
state.nextImage += 1;
|
|
299
|
+
state.pkg.parts[path] = {
|
|
300
|
+
kind: "binary",
|
|
301
|
+
base64: image.base64
|
|
302
|
+
};
|
|
303
|
+
const children = [el("draw:image", {
|
|
304
|
+
"xlink:href": encodeXmlText(path),
|
|
305
|
+
"xlink:type": "simple",
|
|
306
|
+
"xlink:show": "embed",
|
|
307
|
+
"xlink:actuate": "onLoad"
|
|
308
|
+
})];
|
|
309
|
+
if (image.altText !== void 0) children.push(el("svg:title", {}, [txt(encodeXmlText(image.altText))]));
|
|
310
|
+
return el("draw:frame", {
|
|
311
|
+
"text:anchor-type": "as-char",
|
|
312
|
+
"svg:width": formatOdfLength(image.widthPt),
|
|
313
|
+
"svg:height": formatOdfLength(image.heightPt)
|
|
314
|
+
}, children);
|
|
315
|
+
}
|
|
316
|
+
function writeSectionBlocks(section, parentStyleName, state, out) {
|
|
317
|
+
let anchorParagraph;
|
|
318
|
+
let openList;
|
|
319
|
+
const closeList = () => {
|
|
320
|
+
if (openList === void 0) return;
|
|
321
|
+
const kind = listKindOf(openList.numId);
|
|
322
|
+
const built = writeOdfList(openList.entries, kind === void 0 ? void 0 : listStyleNameFor(kind, state));
|
|
323
|
+
openList.element.attributes = built.attributes;
|
|
324
|
+
openList.element.children = built.children;
|
|
325
|
+
openList = void 0;
|
|
326
|
+
};
|
|
327
|
+
for (const [index, block] of section.blocks.entries()) {
|
|
328
|
+
if (block.kind === "paragraph") {
|
|
329
|
+
const paragraph = block.paragraph;
|
|
330
|
+
const element = writeOdfParagraph(paragraph, state.registry, { ...index === 0 && parentStyleName !== void 0 ? { parentStyleName } : {} });
|
|
331
|
+
anchorParagraph = element;
|
|
332
|
+
const membership = paragraph.list;
|
|
333
|
+
if (membership?.numId === void 0) {
|
|
334
|
+
closeList();
|
|
335
|
+
out.push(element);
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
if (openList !== void 0 && openList.numId !== membership.numId) closeList();
|
|
339
|
+
if (openList === void 0) {
|
|
340
|
+
const listElement = el("text:list");
|
|
341
|
+
openList = {
|
|
342
|
+
numId: membership.numId,
|
|
343
|
+
entries: [],
|
|
344
|
+
element: listElement
|
|
345
|
+
};
|
|
346
|
+
out.push(listElement);
|
|
347
|
+
}
|
|
348
|
+
openList.entries.push({
|
|
349
|
+
level: membership.level,
|
|
350
|
+
element
|
|
351
|
+
});
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (block.kind === "table") {
|
|
355
|
+
closeList();
|
|
356
|
+
anchorParagraph = void 0;
|
|
357
|
+
out.push(writeOdfTable(block.table, state.registry, `Table${state.nextTable}`));
|
|
358
|
+
state.nextTable += 1;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (anchorParagraph === void 0) throw new Error("writeOdt: internal error -- an image block reached the writer with no anchor paragraph before it, which planSection is supposed to guarantee");
|
|
362
|
+
anchorParagraph.children.push(writeImageFrame(block.image, state));
|
|
363
|
+
}
|
|
364
|
+
closeList();
|
|
365
|
+
}
|
|
366
|
+
function writeOdtContent(document, options = {}) {
|
|
367
|
+
if (document.kind !== "wordprocessing") throw new Error(`writeOdtContent: expected a 'wordprocessing' document, got '${document.kind}' -- odf.js writes .odt from the wordprocessing arm only`);
|
|
368
|
+
const version = options.version ?? "1.3";
|
|
369
|
+
const textElement = el("office:text");
|
|
370
|
+
const pkg = createOdfPackage(ODF_MEDIA_TYPES.odt, textElement, version);
|
|
371
|
+
const state = {
|
|
372
|
+
pkg,
|
|
373
|
+
registry: StyleRegistry.forPart(pkg, CONTENT_PART, { otherPart: {
|
|
374
|
+
pkg,
|
|
375
|
+
partPath: STYLES_PART
|
|
376
|
+
} }),
|
|
377
|
+
contentAutomaticStyles: odfPartContainer(pkg, CONTENT_PART, "office:automatic-styles"),
|
|
378
|
+
stylesNamedStyles: odfPartContainer(pkg, STYLES_PART, "office:styles"),
|
|
379
|
+
stylesAutomaticStyles: odfPartContainer(pkg, STYLES_PART, "office:automatic-styles"),
|
|
380
|
+
masterStyles: odfPartContainer(pkg, STYLES_PART, "office:master-styles"),
|
|
381
|
+
nextTable: 1,
|
|
382
|
+
nextImage: 1,
|
|
383
|
+
nextListStyle: 1,
|
|
384
|
+
listStyleByKind: /* @__PURE__ */ new Map()
|
|
385
|
+
};
|
|
386
|
+
const planned = planDocument(document.sections);
|
|
387
|
+
for (const [index, section] of planned.entries()) {
|
|
388
|
+
const masterPageName = `MP${index + 1}`;
|
|
389
|
+
const pageLayoutName = `PM${index + 1}`;
|
|
390
|
+
state.stylesAutomaticStyles.children.push(pageLayoutElement(pageLayoutName, section.pageSize, section.margins));
|
|
391
|
+
state.masterStyles.children.push(el("style:master-page", {
|
|
392
|
+
"style:name": encodeXmlText(masterPageName),
|
|
393
|
+
"style:page-layout-name": encodeXmlText(pageLayoutName)
|
|
394
|
+
}));
|
|
395
|
+
if (index > 0) state.stylesNamedStyles.children.push(sectionBreakStyleElement(`${masterPageName}Start`, masterPageName));
|
|
396
|
+
}
|
|
397
|
+
for (const [index, section] of planned.entries()) writeSectionBlocks(section, index === 0 ? void 0 : `MP${index + 1}Start`, state, textElement.children);
|
|
398
|
+
writeOdfMetadata(pkg, document.metadata, version);
|
|
399
|
+
syncManifest(pkg, { version });
|
|
400
|
+
return pkg;
|
|
401
|
+
}
|
|
402
|
+
function writeOdt(document, options = {}) {
|
|
403
|
+
return writeOdtContent(flattenTree(document), options);
|
|
404
|
+
}
|
|
405
|
+
//#endregion
|
|
406
|
+
export { normaliseOdtContent, writeOdt, writeOdtContent };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as resolveStyle, i as findStyleElement, n as StyleCascadeResult, o as resolveStyleElementChain, r as StyleElementChainResult, t as CascadeDiagnostic } from "../../cascade-
|
|
1
|
+
import { a as resolveStyle, i as findStyleElement, n as StyleCascadeResult, o as resolveStyleElementChain, r as StyleElementChainResult, t as CascadeDiagnostic } from "../../cascade-BpMwrjkB.cjs";
|
|
2
2
|
export { CascadeDiagnostic, StyleCascadeResult, StyleElementChainResult, findStyleElement, resolveStyle, resolveStyleElementChain };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as resolveStyle, i as findStyleElement, n as StyleCascadeResult, o as resolveStyleElementChain, r as StyleElementChainResult, t as CascadeDiagnostic } from "../../cascade-
|
|
1
|
+
import { a as resolveStyle, i as findStyleElement, n as StyleCascadeResult, o as resolveStyleElementChain, r as StyleElementChainResult, t as CascadeDiagnostic } from "../../cascade-PDS3hgrP.js";
|
|
2
2
|
export { CascadeDiagnostic, StyleCascadeResult, StyleElementChainResult, findStyleElement, resolveStyle, resolveStyleElementChain };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_xml_fragment = require("../../xml/fragment.cjs");
|
|
3
|
+
const require_xml_entities = require("../../xml/entities.cjs");
|
|
4
|
+
const require_typed_shared_units = require("./units.cjs");
|
|
2
5
|
const require_xml_query = require("../../xml/query.cjs");
|
|
3
6
|
//#region src/typed/shared/list.ts
|
|
4
7
|
function resolveOdfListKind(pkg, styleName) {
|
|
@@ -26,6 +29,50 @@ function mintOdfListNumId(pkg, listElement, state) {
|
|
|
26
29
|
state.next += 1;
|
|
27
30
|
return numId;
|
|
28
31
|
}
|
|
32
|
+
const ODF_LIST_LEVELS = 10;
|
|
33
|
+
const LIST_INDENT_STEP_PT = 18;
|
|
34
|
+
const LIST_BULLET_CHARACTER = "•";
|
|
35
|
+
function buildOdfListStyle(styleName, kind) {
|
|
36
|
+
const levels = [];
|
|
37
|
+
for (let level = 1; level <= ODF_LIST_LEVELS; level += 1) {
|
|
38
|
+
const properties = require_xml_fragment.el("style:list-level-properties", {
|
|
39
|
+
"text:space-before": require_typed_shared_units.formatOdfLength(level * LIST_INDENT_STEP_PT),
|
|
40
|
+
"text:min-label-width": require_typed_shared_units.formatOdfLength(LIST_INDENT_STEP_PT)
|
|
41
|
+
});
|
|
42
|
+
levels.push(kind === "ordered" ? require_xml_fragment.el("text:list-level-style-number", {
|
|
43
|
+
"text:level": String(level),
|
|
44
|
+
"style:num-suffix": ".",
|
|
45
|
+
"style:num-format": "1"
|
|
46
|
+
}, [properties]) : require_xml_fragment.el("text:list-level-style-bullet", {
|
|
47
|
+
"text:level": String(level),
|
|
48
|
+
"text:bullet-char": LIST_BULLET_CHARACTER
|
|
49
|
+
}, [properties]));
|
|
50
|
+
}
|
|
51
|
+
return require_xml_fragment.el("text:list-style", { "style:name": require_xml_entities.encodeXmlText(styleName) }, levels);
|
|
52
|
+
}
|
|
53
|
+
function writeOdfList(entries, styleName) {
|
|
54
|
+
const root = require_xml_fragment.el("text:list", styleName === void 0 ? {} : { "text:style-name": require_xml_entities.encodeXmlText(styleName) });
|
|
55
|
+
const openLists = [root];
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
const level = Math.max(0, Math.trunc(entry.level));
|
|
58
|
+
while (openLists.length - 1 > level) openLists.pop();
|
|
59
|
+
while (openLists.length - 1 < level) {
|
|
60
|
+
const enclosing = openLists[openLists.length - 1];
|
|
61
|
+
const lastChild = enclosing.children[enclosing.children.length - 1];
|
|
62
|
+
let host;
|
|
63
|
+
if (lastChild?.type === "element" && lastChild.tag === "text:list-item") host = lastChild;
|
|
64
|
+
else {
|
|
65
|
+
host = require_xml_fragment.el("text:list-item");
|
|
66
|
+
enclosing.children.push(host);
|
|
67
|
+
}
|
|
68
|
+
const nested = require_xml_fragment.el("text:list");
|
|
69
|
+
host.children.push(nested);
|
|
70
|
+
openLists.push(nested);
|
|
71
|
+
}
|
|
72
|
+
openLists[openLists.length - 1].children.push(require_xml_fragment.el("text:list-item", {}, [entry.element]));
|
|
73
|
+
}
|
|
74
|
+
return root;
|
|
75
|
+
}
|
|
29
76
|
function readOdfListParagraphs(listElement, membership, readParagraph) {
|
|
30
77
|
const paragraphs = [];
|
|
31
78
|
for (const item of listElement.children) {
|
|
@@ -45,6 +92,8 @@ function readOdfListParagraphs(listElement, membership, readParagraph) {
|
|
|
45
92
|
return paragraphs;
|
|
46
93
|
}
|
|
47
94
|
//#endregion
|
|
95
|
+
exports.buildOdfListStyle = buildOdfListStyle;
|
|
48
96
|
exports.mintOdfListNumId = mintOdfListNumId;
|
|
49
97
|
exports.readOdfListParagraphs = readOdfListParagraphs;
|
|
50
98
|
exports.resolveOdfListKind = resolveOdfListKind;
|
|
99
|
+
exports.writeOdfList = writeOdfList;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { OdfListIdState, OdfListParagraphReader, mintOdfListNumId, readOdfListParagraphs, resolveOdfListKind };
|
|
1
|
+
import { a as mintOdfListNumId, c as writeOdfList, i as buildOdfListStyle, n as OdfListIdState, o as readOdfListParagraphs, r as OdfListParagraphReader, s as resolveOdfListKind, t as OdfListEntry } from "../../list-Bttwr1mk.cjs";
|
|
2
|
+
export { OdfListEntry, OdfListIdState, OdfListParagraphReader, buildOdfListStyle, mintOdfListNumId, readOdfListParagraphs, resolveOdfListKind, writeOdfList };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { OdfListIdState, OdfListParagraphReader, mintOdfListNumId, readOdfListParagraphs, resolveOdfListKind };
|
|
1
|
+
import { a as mintOdfListNumId, c as writeOdfList, i as buildOdfListStyle, n as OdfListIdState, o as readOdfListParagraphs, r as OdfListParagraphReader, s as resolveOdfListKind, t as OdfListEntry } from "../../list-vhXd0Jf6.js";
|
|
2
|
+
export { OdfListEntry, OdfListIdState, OdfListParagraphReader, buildOdfListStyle, mintOdfListNumId, readOdfListParagraphs, resolveOdfListKind, writeOdfList };
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { el } from "../../xml/fragment.js";
|
|
2
|
+
import { encodeXmlText } from "../../xml/entities.js";
|
|
3
|
+
import { formatOdfLength } from "./units.js";
|
|
1
4
|
import { attrValue, childrenWithTag, findChildElement, rootElement } from "../../xml/query.js";
|
|
2
5
|
//#region src/typed/shared/list.ts
|
|
3
6
|
function resolveOdfListKind(pkg, styleName) {
|
|
@@ -25,6 +28,50 @@ function mintOdfListNumId(pkg, listElement, state) {
|
|
|
25
28
|
state.next += 1;
|
|
26
29
|
return numId;
|
|
27
30
|
}
|
|
31
|
+
const ODF_LIST_LEVELS = 10;
|
|
32
|
+
const LIST_INDENT_STEP_PT = 18;
|
|
33
|
+
const LIST_BULLET_CHARACTER = "•";
|
|
34
|
+
function buildOdfListStyle(styleName, kind) {
|
|
35
|
+
const levels = [];
|
|
36
|
+
for (let level = 1; level <= ODF_LIST_LEVELS; level += 1) {
|
|
37
|
+
const properties = el("style:list-level-properties", {
|
|
38
|
+
"text:space-before": formatOdfLength(level * LIST_INDENT_STEP_PT),
|
|
39
|
+
"text:min-label-width": formatOdfLength(LIST_INDENT_STEP_PT)
|
|
40
|
+
});
|
|
41
|
+
levels.push(kind === "ordered" ? el("text:list-level-style-number", {
|
|
42
|
+
"text:level": String(level),
|
|
43
|
+
"style:num-suffix": ".",
|
|
44
|
+
"style:num-format": "1"
|
|
45
|
+
}, [properties]) : el("text:list-level-style-bullet", {
|
|
46
|
+
"text:level": String(level),
|
|
47
|
+
"text:bullet-char": LIST_BULLET_CHARACTER
|
|
48
|
+
}, [properties]));
|
|
49
|
+
}
|
|
50
|
+
return el("text:list-style", { "style:name": encodeXmlText(styleName) }, levels);
|
|
51
|
+
}
|
|
52
|
+
function writeOdfList(entries, styleName) {
|
|
53
|
+
const root = el("text:list", styleName === void 0 ? {} : { "text:style-name": encodeXmlText(styleName) });
|
|
54
|
+
const openLists = [root];
|
|
55
|
+
for (const entry of entries) {
|
|
56
|
+
const level = Math.max(0, Math.trunc(entry.level));
|
|
57
|
+
while (openLists.length - 1 > level) openLists.pop();
|
|
58
|
+
while (openLists.length - 1 < level) {
|
|
59
|
+
const enclosing = openLists[openLists.length - 1];
|
|
60
|
+
const lastChild = enclosing.children[enclosing.children.length - 1];
|
|
61
|
+
let host;
|
|
62
|
+
if (lastChild?.type === "element" && lastChild.tag === "text:list-item") host = lastChild;
|
|
63
|
+
else {
|
|
64
|
+
host = el("text:list-item");
|
|
65
|
+
enclosing.children.push(host);
|
|
66
|
+
}
|
|
67
|
+
const nested = el("text:list");
|
|
68
|
+
host.children.push(nested);
|
|
69
|
+
openLists.push(nested);
|
|
70
|
+
}
|
|
71
|
+
openLists[openLists.length - 1].children.push(el("text:list-item", {}, [entry.element]));
|
|
72
|
+
}
|
|
73
|
+
return root;
|
|
74
|
+
}
|
|
28
75
|
function readOdfListParagraphs(listElement, membership, readParagraph) {
|
|
29
76
|
const paragraphs = [];
|
|
30
77
|
for (const item of listElement.children) {
|
|
@@ -44,4 +91,4 @@ function readOdfListParagraphs(listElement, membership, readParagraph) {
|
|
|
44
91
|
return paragraphs;
|
|
45
92
|
}
|
|
46
93
|
//#endregion
|
|
47
|
-
export { mintOdfListNumId, readOdfListParagraphs, resolveOdfListKind };
|
|
94
|
+
export { buildOdfListStyle, mintOdfListNumId, readOdfListParagraphs, resolveOdfListKind, writeOdfList };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_ns = require("../../ns.cjs");
|
|
3
|
+
const require_xml_fragment = require("../../xml/fragment.cjs");
|
|
2
4
|
const require_xml_entities = require("../../xml/entities.cjs");
|
|
3
5
|
const require_xml_query = require("../../xml/query.cjs");
|
|
4
6
|
//#region src/typed/shared/metadata.ts
|
|
@@ -37,6 +39,45 @@ function readOdfMetadata(pkg) {
|
|
|
37
39
|
if (modifiedIso !== void 0) metadata.modifiedIso = modifiedIso;
|
|
38
40
|
return metadata;
|
|
39
41
|
}
|
|
42
|
+
function metaElement(tag, value) {
|
|
43
|
+
return require_xml_fragment.el(tag, {}, [require_xml_fragment.txt(require_xml_entities.encodeXmlText(value))]);
|
|
44
|
+
}
|
|
45
|
+
function buildOdfMetaNodes(metadata, version) {
|
|
46
|
+
const children = [];
|
|
47
|
+
if (metadata.creator !== void 0) children.push(metaElement("meta:generator", metadata.creator));
|
|
48
|
+
if (metadata.title !== void 0) children.push(metaElement("dc:title", metadata.title));
|
|
49
|
+
if (metadata.subject !== void 0) children.push(metaElement("dc:subject", metadata.subject));
|
|
50
|
+
for (const keyword of metadata.keywords ?? []) children.push(metaElement("meta:keyword", keyword));
|
|
51
|
+
if (metadata.author !== void 0) children.push(metaElement("meta:initial-creator", metadata.author));
|
|
52
|
+
if (metadata.createdIso !== void 0) children.push(metaElement("meta:creation-date", metadata.createdIso));
|
|
53
|
+
if (metadata.modifiedIso !== void 0) children.push(metaElement("dc:date", metadata.modifiedIso));
|
|
54
|
+
if (metadata.language !== void 0) children.push(metaElement("dc:language", metadata.language));
|
|
55
|
+
return [{
|
|
56
|
+
type: "declaration",
|
|
57
|
+
attributes: [{
|
|
58
|
+
name: "version",
|
|
59
|
+
value: "1.0"
|
|
60
|
+
}, {
|
|
61
|
+
name: "encoding",
|
|
62
|
+
value: "UTF-8"
|
|
63
|
+
}]
|
|
64
|
+
}, require_xml_fragment.el("office:document-meta", {
|
|
65
|
+
...require_ns.xmlnsAttributes([
|
|
66
|
+
"office",
|
|
67
|
+
"meta",
|
|
68
|
+
"dc"
|
|
69
|
+
]),
|
|
70
|
+
"office:version": require_xml_entities.encodeXmlText(version)
|
|
71
|
+
}, [require_xml_fragment.el("office:meta", {}, children)])];
|
|
72
|
+
}
|
|
73
|
+
function writeOdfMetadata(pkg, metadata, version) {
|
|
74
|
+
pkg.parts[META_PART] = {
|
|
75
|
+
kind: "xml",
|
|
76
|
+
nodes: buildOdfMetaNodes(metadata, version)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
40
79
|
//#endregion
|
|
41
80
|
exports.META_PART = META_PART;
|
|
81
|
+
exports.buildOdfMetaNodes = buildOdfMetaNodes;
|
|
42
82
|
exports.readOdfMetadata = readOdfMetadata;
|
|
83
|
+
exports.writeOdfMetadata = writeOdfMetadata;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as readOdfMetadata, t as META_PART } from "../../metadata-
|
|
2
|
-
export { META_PART, readOdfMetadata };
|
|
1
|
+
import { i as writeOdfMetadata, n as buildOdfMetaNodes, r as readOdfMetadata, t as META_PART } from "../../metadata-CYXgXL_h.cjs";
|
|
2
|
+
export { META_PART, buildOdfMetaNodes, readOdfMetadata, writeOdfMetadata };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as readOdfMetadata, t as META_PART } from "../../metadata-
|
|
2
|
-
export { META_PART, readOdfMetadata };
|
|
1
|
+
import { i as writeOdfMetadata, n as buildOdfMetaNodes, r as readOdfMetadata, t as META_PART } from "../../metadata-BUzwE_-u.js";
|
|
2
|
+
export { META_PART, buildOdfMetaNodes, readOdfMetadata, writeOdfMetadata };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { xmlnsAttributes } from "../../ns.js";
|
|
2
|
+
import { el, txt } from "../../xml/fragment.js";
|
|
3
|
+
import { decodeXmlText, encodeXmlText } from "../../xml/entities.js";
|
|
2
4
|
import { childrenWithTag, findChildElement, rootElement } from "../../xml/query.js";
|
|
3
5
|
//#region src/typed/shared/metadata.ts
|
|
4
6
|
const META_PART = "meta.xml";
|
|
@@ -36,5 +38,42 @@ function readOdfMetadata(pkg) {
|
|
|
36
38
|
if (modifiedIso !== void 0) metadata.modifiedIso = modifiedIso;
|
|
37
39
|
return metadata;
|
|
38
40
|
}
|
|
41
|
+
function metaElement(tag, value) {
|
|
42
|
+
return el(tag, {}, [txt(encodeXmlText(value))]);
|
|
43
|
+
}
|
|
44
|
+
function buildOdfMetaNodes(metadata, version) {
|
|
45
|
+
const children = [];
|
|
46
|
+
if (metadata.creator !== void 0) children.push(metaElement("meta:generator", metadata.creator));
|
|
47
|
+
if (metadata.title !== void 0) children.push(metaElement("dc:title", metadata.title));
|
|
48
|
+
if (metadata.subject !== void 0) children.push(metaElement("dc:subject", metadata.subject));
|
|
49
|
+
for (const keyword of metadata.keywords ?? []) children.push(metaElement("meta:keyword", keyword));
|
|
50
|
+
if (metadata.author !== void 0) children.push(metaElement("meta:initial-creator", metadata.author));
|
|
51
|
+
if (metadata.createdIso !== void 0) children.push(metaElement("meta:creation-date", metadata.createdIso));
|
|
52
|
+
if (metadata.modifiedIso !== void 0) children.push(metaElement("dc:date", metadata.modifiedIso));
|
|
53
|
+
if (metadata.language !== void 0) children.push(metaElement("dc:language", metadata.language));
|
|
54
|
+
return [{
|
|
55
|
+
type: "declaration",
|
|
56
|
+
attributes: [{
|
|
57
|
+
name: "version",
|
|
58
|
+
value: "1.0"
|
|
59
|
+
}, {
|
|
60
|
+
name: "encoding",
|
|
61
|
+
value: "UTF-8"
|
|
62
|
+
}]
|
|
63
|
+
}, el("office:document-meta", {
|
|
64
|
+
...xmlnsAttributes([
|
|
65
|
+
"office",
|
|
66
|
+
"meta",
|
|
67
|
+
"dc"
|
|
68
|
+
]),
|
|
69
|
+
"office:version": encodeXmlText(version)
|
|
70
|
+
}, [el("office:meta", {}, children)])];
|
|
71
|
+
}
|
|
72
|
+
function writeOdfMetadata(pkg, metadata, version) {
|
|
73
|
+
pkg.parts[META_PART] = {
|
|
74
|
+
kind: "xml",
|
|
75
|
+
nodes: buildOdfMetaNodes(metadata, version)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
39
78
|
//#endregion
|
|
40
|
-
export { META_PART, readOdfMetadata };
|
|
79
|
+
export { META_PART, buildOdfMetaNodes, readOdfMetadata, writeOdfMetadata };
|