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.
Files changed (86) hide show
  1. package/README.md +22 -2
  2. package/dist/{cascade-BDkyOmoo.d.cts → cascade-BpMwrjkB.d.cts} +1 -1
  3. package/dist/{cascade-CaVinmvp.d.ts → cascade-PDS3hgrP.d.ts} +1 -1
  4. package/dist/{codec-B72LApRl.d.cts → codec-BnzBd5_I.d.cts} +10 -8
  5. package/dist/{codec-rbZGlr37.d.ts → codec-Dg_HWuH1.d.ts} +10 -8
  6. package/dist/codec.d.cts +1 -1
  7. package/dist/codec.d.ts +1 -1
  8. package/dist/{embedded-UQQNFd5U.js → embedded-BONPxvS3.js} +1 -2
  9. package/dist/{embedded-BsO-SvtW.cjs → embedded-wrtHCJ68.cjs} +1 -2
  10. package/dist/index.cjs +20 -1
  11. package/dist/index.d.cts +12 -10
  12. package/dist/index.d.ts +12 -10
  13. package/dist/index.js +9 -7
  14. package/dist/{list-DwTyo_B2.d.cts → list-Bttwr1mk.d.cts} +7 -1
  15. package/dist/{list-X_GJY7P3.d.ts → list-vhXd0Jf6.d.ts} +7 -1
  16. package/dist/metadata-BUzwE_-u.d.ts +10 -0
  17. package/dist/metadata-CYXgXL_h.d.cts +10 -0
  18. package/dist/ooo1/read.cjs +1 -1
  19. package/dist/ooo1/read.js +1 -1
  20. package/dist/package-io/scaffold.cjs +64 -0
  21. package/dist/package-io/scaffold.d.cts +2 -0
  22. package/dist/package-io/scaffold.d.ts +2 -0
  23. package/dist/package-io/scaffold.js +61 -0
  24. package/dist/paragraph-BdwsQisB.d.cts +28 -0
  25. package/dist/paragraph-BoVy1LrN.d.ts +28 -0
  26. package/dist/{registry-Dajfxsbz.d.ts → registry-C_16-N6i.d.ts} +2 -0
  27. package/dist/{registry-B-ZkdQv1.d.cts → registry-PoQIRgbY.d.cts} +2 -0
  28. package/dist/scaffold-44EIMGll.d.cts +8 -0
  29. package/dist/scaffold-ehGsIpZ5.d.ts +8 -0
  30. package/dist/{shapes-BCjeY90t.d.cts → shapes-BQhXAk0D.d.cts} +1 -1
  31. package/dist/{shapes-QkOsc-WT.d.ts → shapes-DUzrrf7b.d.ts} +1 -1
  32. package/dist/styles/properties.cjs +1 -1
  33. package/dist/styles/properties.js +2 -2
  34. package/dist/styles/registry.cjs +9 -6
  35. package/dist/styles/registry.d.cts +1 -1
  36. package/dist/styles/registry.d.ts +1 -1
  37. package/dist/styles/registry.js +9 -6
  38. package/dist/{table-CYvFMlP6.d.cts → table-ByhqRnSG.d.cts} +3 -1
  39. package/dist/{table-DclDgC5h.d.ts → table-DElqGcT0.d.ts} +3 -1
  40. package/dist/text-B8350HA2.d.ts +17 -0
  41. package/dist/text-pmlTqzgi.d.cts +17 -0
  42. package/dist/typed/draw/embedded.cjs +1 -1
  43. package/dist/typed/draw/embedded.js +1 -1
  44. package/dist/typed/draw/shapes.d.cts +1 -1
  45. package/dist/typed/draw/shapes.d.ts +1 -1
  46. package/dist/typed/odb/form.cjs +1 -1
  47. package/dist/typed/odb/form.js +1 -1
  48. package/dist/typed/ods/read.cjs +1 -1
  49. package/dist/typed/ods/read.js +1 -1
  50. package/dist/typed/odt/read.cjs +1 -1
  51. package/dist/typed/odt/read.js +1 -1
  52. package/dist/typed/odt/write.cjs +409 -0
  53. package/dist/typed/odt/write.d.cts +2 -0
  54. package/dist/typed/odt/write.d.ts +2 -0
  55. package/dist/typed/odt/write.js +406 -0
  56. package/dist/typed/shared/cascade.d.cts +1 -1
  57. package/dist/typed/shared/cascade.d.ts +1 -1
  58. package/dist/typed/shared/list.cjs +49 -0
  59. package/dist/typed/shared/list.d.cts +2 -2
  60. package/dist/typed/shared/list.d.ts +2 -2
  61. package/dist/typed/shared/list.js +48 -1
  62. package/dist/typed/shared/metadata.cjs +41 -0
  63. package/dist/typed/shared/metadata.d.cts +2 -2
  64. package/dist/typed/shared/metadata.d.ts +2 -2
  65. package/dist/typed/shared/metadata.js +41 -2
  66. package/dist/typed/shared/paragraph.cjs +118 -2
  67. package/dist/typed/shared/paragraph.d.cts +2 -2
  68. package/dist/typed/shared/paragraph.d.ts +2 -2
  69. package/dist/typed/shared/paragraph.js +117 -5
  70. package/dist/typed/shared/table.cjs +81 -0
  71. package/dist/typed/shared/table.d.cts +2 -2
  72. package/dist/typed/shared/table.d.ts +2 -2
  73. package/dist/typed/shared/table.js +84 -4
  74. package/dist/typed/shared/text.cjs +60 -0
  75. package/dist/typed/shared/text.d.cts +2 -2
  76. package/dist/typed/shared/text.d.ts +2 -2
  77. package/dist/typed/shared/text.js +60 -2
  78. package/dist/write-7Uu_wlkL.d.cts +13 -0
  79. package/dist/write-DGcI9W7Z.d.ts +13 -0
  80. package/package.json +1 -1
  81. package/dist/metadata-01SgHkRR.d.cts +0 -7
  82. package/dist/metadata-D1SOBTh8.d.ts +0 -7
  83. package/dist/paragraph-ByTzS8Li.d.ts +0 -18
  84. package/dist/paragraph-CVULactG.d.cts +0 -18
  85. package/dist/text-Bn3C7lnm.d.ts +0 -10
  86. 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-BDkyOmoo.cjs";
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-CaVinmvp.js";
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 resolveOdfListKind, i as readOdfListParagraphs, n as OdfListParagraphReader, r as mintOdfListNumId, t as OdfListIdState } from "../../list-DwTyo_B2.cjs";
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 resolveOdfListKind, i as readOdfListParagraphs, n as OdfListParagraphReader, r as mintOdfListNumId, t as OdfListIdState } from "../../list-X_GJY7P3.js";
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-01SgHkRR.cjs";
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-D1SOBTh8.js";
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 { decodeXmlText } from "../../xml/entities.js";
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 };