odf-kit 0.7.0 → 0.8.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.
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Typst emitter for the ODT document model.
3
+ *
4
+ * Converts the structured document model produced by the ODT parser into
5
+ * a Typst markup string (.typ). Zero runtime dependencies — the emitter is
6
+ * a pure function over OdtDocumentModel and produces output suitable for
7
+ * any Typst 0.11+ installation:
8
+ *
9
+ * typst compile document.typ document.pdf
10
+ *
11
+ * Structural coverage:
12
+ * - Headings levels 1–6 (= through ======)
13
+ * - Paragraphs with text-align via #align()
14
+ * - Bold, italic, underline, strikethrough, superscript, subscript
15
+ * - Hyperlinks via #link()
16
+ * - Footnotes and endnotes via #footnote[]
17
+ * - Bookmarks as Typst labels (<name>) for point and start positions
18
+ * - Text fields: pageNumber and pageCount mapped to Typst counters;
19
+ * all others rendered as their stored evaluated value
20
+ * - Unordered and ordered lists with nested sub-lists
21
+ * - Tables via #table() with column widths where available
22
+ * - Named sections with comment headers
23
+ * - Tracked changes: final (default), original, and changes modes
24
+ *
25
+ * Tier 2 character style coverage (SpanStyle):
26
+ * - fontColor → #text(fill: rgb("..."))[]
27
+ * - fontSize → #text(size: Npt)[]
28
+ * - fontFamily → #text(font: "...")[]
29
+ * - highlightColor → #highlight(fill: rgb("..."))[]
30
+ *
31
+ * Page geometry (PageLayout) → #set page(width:, height:, margin: (...))
32
+ *
33
+ * Images: base64 image data cannot be embedded inline in Typst without
34
+ * filesystem access. Each image is emitted as a comment placeholder
35
+ * preserving its document position:
36
+ *
37
+ * // [image: name 17cm × 5.74cm]
38
+ *
39
+ * Consumers that need images in the PDF should extract ImageNode.data
40
+ * (base64) from the model, write the files alongside the .typ output,
41
+ * and substitute the placeholders with #image("filename") calls.
42
+ *
43
+ * Text content is escaped for Typst markup mode. The following characters
44
+ * are prefixed with a backslash: \ * _ # < @ ` ~ $ [ ]
45
+ * A leading = on any line is also escaped to prevent heading misinterpretation.
46
+ */
47
+ import type { OdtDocumentModel } from "../reader/types.js";
48
+ import type { ReadOdtOptions } from "../reader/types.js";
49
+ /**
50
+ * Options for the Typst emitter.
51
+ */
52
+ export interface TypstEmitOptions {
53
+ /**
54
+ * Controls how tracked changes are emitted. Mirrors ReadOdtOptions.trackedChanges.
55
+ *
56
+ * "final" (default): TrackedChangeNode values render as their insertion body;
57
+ * deletions produce no output. Matches the "final" parse mode behavior.
58
+ * "original": TrackedChangeNode values render as their deletion body;
59
+ * insertions produce no output. Matches the "original" parse mode behavior.
60
+ * "changes": insertions → #underline[], deletions → #strike[],
61
+ * format-change → body content only with no wrapper.
62
+ *
63
+ * Set readOdt and modelToTypst to the same mode for consistent results.
64
+ * When readOdt is called with "final" (default), no TrackedChangeNode values
65
+ * are emitted by the parser and this option has no effect.
66
+ */
67
+ trackedChanges?: "final" | "original" | "changes";
68
+ }
69
+ /**
70
+ * Convert an OdtDocumentModel to a Typst markup string.
71
+ *
72
+ * This is the primary emitter function. It accepts a pre-parsed document
73
+ * model and returns a .typ string with no side effects and no filesystem
74
+ * access. Use this when you already have a model from readOdt() or when
75
+ * you need fine-grained control over read options.
76
+ *
77
+ * @param model - The parsed ODT document model from readOdt().
78
+ * @param options - Typst emitter options.
79
+ * @returns Typst markup string (.typ).
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * import { readOdt } from "odf-kit/reader";
84
+ * import { modelToTypst } from "odf-kit/typst";
85
+ * import { readFileSync, writeFileSync } from "node:fs";
86
+ *
87
+ * const bytes = new Uint8Array(readFileSync("document.odt"));
88
+ * const model = readOdt(bytes);
89
+ * const typ = modelToTypst(model);
90
+ * writeFileSync("document.typ", typ);
91
+ * // then: typst compile document.typ document.pdf
92
+ * ```
93
+ */
94
+ export declare function modelToTypst(model: OdtDocumentModel, options?: TypstEmitOptions): string;
95
+ /**
96
+ * Convert an .odt file directly to a Typst markup string.
97
+ *
98
+ * Convenience wrapper around readOdt() + modelToTypst(). Use modelToTypst()
99
+ * directly when you need access to the document model, metadata, or want to
100
+ * share a single readOdt() call between multiple emitters.
101
+ *
102
+ * @param bytes - The raw .odt file as a Uint8Array.
103
+ * @param options - Combined emitter and read options. The trackedChanges
104
+ * field is forwarded to both readOdt() and modelToTypst() — set it once
105
+ * for consistent results across both steps.
106
+ * @returns Typst markup string (.typ).
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * import { odtToTypst } from "odf-kit/typst";
111
+ * import { readFileSync, writeFileSync } from "node:fs";
112
+ *
113
+ * const bytes = new Uint8Array(readFileSync("document.odt"));
114
+ * const typ = odtToTypst(bytes);
115
+ * writeFileSync("document.typ", typ);
116
+ * // then: typst compile document.typ document.pdf
117
+ * ```
118
+ */
119
+ export declare function odtToTypst(bytes: Uint8Array, options?: TypstEmitOptions & ReadOdtOptions): string;
120
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/typst/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAajB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAMzD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;CACnD;AAkXD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAUxF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,cAAc,GAAG,MAAM,CAGjG"}
@@ -0,0 +1,458 @@
1
+ /**
2
+ * Typst emitter for the ODT document model.
3
+ *
4
+ * Converts the structured document model produced by the ODT parser into
5
+ * a Typst markup string (.typ). Zero runtime dependencies — the emitter is
6
+ * a pure function over OdtDocumentModel and produces output suitable for
7
+ * any Typst 0.11+ installation:
8
+ *
9
+ * typst compile document.typ document.pdf
10
+ *
11
+ * Structural coverage:
12
+ * - Headings levels 1–6 (= through ======)
13
+ * - Paragraphs with text-align via #align()
14
+ * - Bold, italic, underline, strikethrough, superscript, subscript
15
+ * - Hyperlinks via #link()
16
+ * - Footnotes and endnotes via #footnote[]
17
+ * - Bookmarks as Typst labels (<name>) for point and start positions
18
+ * - Text fields: pageNumber and pageCount mapped to Typst counters;
19
+ * all others rendered as their stored evaluated value
20
+ * - Unordered and ordered lists with nested sub-lists
21
+ * - Tables via #table() with column widths where available
22
+ * - Named sections with comment headers
23
+ * - Tracked changes: final (default), original, and changes modes
24
+ *
25
+ * Tier 2 character style coverage (SpanStyle):
26
+ * - fontColor → #text(fill: rgb("..."))[]
27
+ * - fontSize → #text(size: Npt)[]
28
+ * - fontFamily → #text(font: "...")[]
29
+ * - highlightColor → #highlight(fill: rgb("..."))[]
30
+ *
31
+ * Page geometry (PageLayout) → #set page(width:, height:, margin: (...))
32
+ *
33
+ * Images: base64 image data cannot be embedded inline in Typst without
34
+ * filesystem access. Each image is emitted as a comment placeholder
35
+ * preserving its document position:
36
+ *
37
+ * // [image: name 17cm × 5.74cm]
38
+ *
39
+ * Consumers that need images in the PDF should extract ImageNode.data
40
+ * (base64) from the model, write the files alongside the .typ output,
41
+ * and substitute the placeholders with #image("filename") calls.
42
+ *
43
+ * Text content is escaped for Typst markup mode. The following characters
44
+ * are prefixed with a backslash: \ * _ # < @ ` ~ $ [ ]
45
+ * A leading = on any line is also escaped to prevent heading misinterpretation.
46
+ */
47
+ import { readOdt } from "../reader/parser.js";
48
+ // ============================================================
49
+ // Typst escaping
50
+ // ============================================================
51
+ /** Characters with special meaning in Typst markup mode. */
52
+ const TYPST_ESCAPE_RE = /[\\*_#<@`~$[\]]/g;
53
+ /**
54
+ * Escape characters that carry special meaning in Typst markup mode.
55
+ *
56
+ * Each matched character is prefixed with a backslash. A leading = on any
57
+ * line is also escaped so text content is never misinterpreted as a heading.
58
+ */
59
+ function escapeTypst(text) {
60
+ return text.replace(TYPST_ESCAPE_RE, (ch) => `\\${ch}`).replace(/^=/gm, "\\=");
61
+ }
62
+ // ============================================================
63
+ // Page setup
64
+ // ============================================================
65
+ /**
66
+ * Emit a #set page(...) directive from a PageLayout.
67
+ *
68
+ * Returns an empty string when pageLayout is absent so the caller can
69
+ * skip it without emitting a blank directive.
70
+ */
71
+ function emitPageSetup(model) {
72
+ const layout = model.pageLayout;
73
+ if (layout === undefined)
74
+ return "";
75
+ const parts = [];
76
+ if (layout.width !== undefined)
77
+ parts.push(`width: ${layout.width}`);
78
+ if (layout.height !== undefined)
79
+ parts.push(`height: ${layout.height}`);
80
+ const marginParts = [];
81
+ if (layout.marginTop !== undefined)
82
+ marginParts.push(`top: ${layout.marginTop}`);
83
+ if (layout.marginBottom !== undefined)
84
+ marginParts.push(`bottom: ${layout.marginBottom}`);
85
+ if (layout.marginLeft !== undefined)
86
+ marginParts.push(`left: ${layout.marginLeft}`);
87
+ if (layout.marginRight !== undefined)
88
+ marginParts.push(`right: ${layout.marginRight}`);
89
+ if (marginParts.length > 0)
90
+ parts.push(`margin: (${marginParts.join(", ")})`);
91
+ if (parts.length === 0)
92
+ return "";
93
+ return `#set page(${parts.join(", ")})`;
94
+ }
95
+ // ============================================================
96
+ // Tier 2 — SpanStyle helper
97
+ // ============================================================
98
+ /**
99
+ * Wrap Typst content with #text() and #highlight() calls for any SpanStyle
100
+ * properties that have Typst equivalents.
101
+ *
102
+ * Applied after all semantic formatting (#underline, #strike, _italic_,
103
+ * *bold*) so SpanStyle is the outermost wrapper below the hyperlink anchor.
104
+ *
105
+ * Properties without a clean Typst mapping (textTransform, fontVariant,
106
+ * textShadow, letterSpacing) are intentionally omitted — they have no
107
+ * standard built-in Typst equivalent and faking them would produce incorrect
108
+ * output.
109
+ */
110
+ function applySpanStyle(style, content) {
111
+ let out = content;
112
+ // highlight() wraps first so #text() sits outside it
113
+ if (style.highlightColor !== undefined) {
114
+ out = `#highlight(fill: rgb("${style.highlightColor}"))[${out}]`;
115
+ }
116
+ const textArgs = [];
117
+ if (style.fontColor !== undefined)
118
+ textArgs.push(`fill: rgb("${style.fontColor}")`);
119
+ if (style.fontSize !== undefined)
120
+ textArgs.push(`size: ${style.fontSize}pt`);
121
+ if (style.fontFamily !== undefined)
122
+ textArgs.push(`font: "${style.fontFamily}"`);
123
+ if (textArgs.length > 0) {
124
+ out = `#text(${textArgs.join(", ")})[${out}]`;
125
+ }
126
+ return out;
127
+ }
128
+ // ============================================================
129
+ // Inline node renderers
130
+ // ============================================================
131
+ /**
132
+ * Emit a TextSpan to a Typst markup string.
133
+ *
134
+ * Hidden spans (text:display="none") produce an empty string.
135
+ * Hard line breaks produce a Typst forced line break: \
136
+ *
137
+ * Formatting nesting order (innermost first, outermost last):
138
+ * superscript/subscript → strikethrough → underline → italic → bold
139
+ * → SpanStyle → hyperlink anchor.
140
+ */
141
+ function emitTextSpan(span) {
142
+ if (span.lineBreak)
143
+ return "\\\n";
144
+ if (span.hidden)
145
+ return "";
146
+ let out = escapeTypst(span.text);
147
+ if (span.superscript)
148
+ out = `#super[${out}]`;
149
+ if (span.subscript)
150
+ out = `#sub[${out}]`;
151
+ if (span.strikethrough)
152
+ out = `#strike[${out}]`;
153
+ if (span.underline)
154
+ out = `#underline[${out}]`;
155
+ if (span.italic)
156
+ out = `_${out}_`;
157
+ if (span.bold)
158
+ out = `*${out}*`;
159
+ if (span.style !== undefined) {
160
+ out = applySpanStyle(span.style, out);
161
+ }
162
+ if (span.href !== undefined) {
163
+ out = `#link("${span.href}")[${out}]`;
164
+ }
165
+ return out;
166
+ }
167
+ /**
168
+ * Emit an ImageNode as a comment placeholder.
169
+ *
170
+ * Typst does not support inline base64 image data without filesystem access.
171
+ * The placeholder preserves the image's document position and carries its
172
+ * name and dimensions so consumers can locate and substitute it.
173
+ *
174
+ * See module-level documentation for the recommended substitution workflow.
175
+ */
176
+ function emitImage(node) {
177
+ const label = node.name ?? node.title ?? "image";
178
+ const dims = node.width !== undefined && node.height !== undefined
179
+ ? ` ${node.width} \u00d7 ${node.height}`
180
+ : "";
181
+ return `/* [image: ${label}${dims}] */`;
182
+ }
183
+ /**
184
+ * Emit a NoteNode as a Typst #footnote[].
185
+ *
186
+ * Both footnote and endnote classes are emitted as #footnote[] — Typst does
187
+ * not have a built-in endnote construct. Consumers that need distinct endnote
188
+ * placement should post-process the .typ output.
189
+ */
190
+ function emitNote(node, options) {
191
+ const body = emitBodyNodes(node.body, options);
192
+ return `#footnote[${body}]`;
193
+ }
194
+ /**
195
+ * Emit a BookmarkNode as a Typst label.
196
+ *
197
+ * point and start positions emit <name> — Typst's label syntax for
198
+ * cross-reference anchors. end positions produce no output (the span
199
+ * has already been closed implicitly).
200
+ */
201
+ function emitBookmark(node) {
202
+ if (node.position === "end")
203
+ return "";
204
+ return `<${node.name}>`;
205
+ }
206
+ /**
207
+ * Emit a FieldNode to a Typst string.
208
+ *
209
+ * pageNumber and pageCount are mapped to their Typst counter equivalents.
210
+ * All other field types fall back to the stored evaluated value, which is
211
+ * always present per the ODF spec.
212
+ */
213
+ function emitField(node) {
214
+ switch (node.fieldType) {
215
+ case "pageNumber":
216
+ return "#counter(page).display()";
217
+ case "pageCount":
218
+ return "#counter(page).final().first()";
219
+ default:
220
+ return escapeTypst(node.value);
221
+ }
222
+ }
223
+ /**
224
+ * Dispatch an InlineNode to the appropriate emitter.
225
+ *
226
+ * TextSpan has no `kind` property; all other InlineNode types do.
227
+ * This mirrors the narrowing pattern used in the HTML renderer.
228
+ */
229
+ function emitInlineNode(node, options) {
230
+ if ("kind" in node) {
231
+ switch (node.kind) {
232
+ case "image":
233
+ return emitImage(node);
234
+ case "note":
235
+ return emitNote(node, options);
236
+ case "bookmark":
237
+ return emitBookmark(node);
238
+ case "field":
239
+ return emitField(node);
240
+ }
241
+ }
242
+ return emitTextSpan(node);
243
+ }
244
+ /** Emit an array of InlineNode objects to a concatenated Typst string. */
245
+ function emitSpans(spans, options) {
246
+ return spans.map((n) => emitInlineNode(n, options)).join("");
247
+ }
248
+ // ============================================================
249
+ // Block node renderers
250
+ // ============================================================
251
+ /**
252
+ * Map an ODF/CSS text-align value to the Typst alignment keyword.
253
+ *
254
+ * ODF spec values "start" and "end" are passed through — Typst supports them
255
+ * natively for bidirectional text. "justify" maps to Typst's "justify" keyword.
256
+ */
257
+ function mapTextAlign(textAlign) {
258
+ switch (textAlign) {
259
+ case "left":
260
+ return "left";
261
+ case "right":
262
+ return "right";
263
+ case "center":
264
+ return "center";
265
+ case "justify":
266
+ return "justify";
267
+ case "start":
268
+ return "start";
269
+ case "end":
270
+ return "end";
271
+ default:
272
+ return "left";
273
+ }
274
+ }
275
+ /**
276
+ * Emit a ListNode to a Typst list string.
277
+ *
278
+ * Unordered items use the - marker; ordered items use +. Nested sub-lists
279
+ * are indented with two spaces per level as required by the Typst parser.
280
+ */
281
+ function emitList(list, options, depth = 0) {
282
+ const marker = list.ordered ? "+" : "-";
283
+ const indent = " ".repeat(depth);
284
+ return list.items
285
+ .map((item) => {
286
+ const content = emitSpans(item.spans, options);
287
+ const nested = item.children !== undefined ? "\n" + emitList(item.children, options, depth + 1) : "";
288
+ return `${indent}${marker} ${content}${nested}`;
289
+ })
290
+ .join("\n");
291
+ }
292
+ /**
293
+ * Emit a TableNode as a Typst #table() call.
294
+ *
295
+ * Column widths are taken from the first row's CellStyle.columnWidth values
296
+ * when present, producing a columns: (Xcm, Ycm, ...) tuple. When no widths
297
+ * are available, columns: N (equal-width auto layout) is used instead.
298
+ *
299
+ * Cell content is emitted as Typst content blocks [...]. colspan and rowspan
300
+ * are not yet expressible in standard Typst table syntax and are silently
301
+ * ignored; the cell content is still emitted.
302
+ */
303
+ function emitTable(table, options) {
304
+ if (table.rows.length === 0)
305
+ return "";
306
+ const cols = table.rows[0].cells.length;
307
+ const firstRow = table.rows[0];
308
+ const colWidths = firstRow.cells.map((cell) => cell.cellStyle?.columnWidth);
309
+ const hasWidths = colWidths.some((w) => w !== undefined);
310
+ const columnsArg = hasWidths
311
+ ? `columns: (${colWidths.map((w) => w ?? "1fr").join(", ")})`
312
+ : `columns: ${cols}`;
313
+ const cells = table.rows
314
+ .flatMap((row) => row.cells.map((cell) => `[${emitSpans(cell.spans, options)}]`))
315
+ .join(", ");
316
+ return `#table(\n ${columnsArg},\n ${cells}\n)`;
317
+ }
318
+ /**
319
+ * Emit a SectionNode as a Typst comment header followed by its body content.
320
+ *
321
+ * Typst has no built-in section construct. The name is preserved as a comment
322
+ * so consumers can identify section boundaries in the .typ output.
323
+ */
324
+ function emitSection(node, options) {
325
+ const header = node.name !== undefined ? `// Section: ${node.name}` : "// Section";
326
+ const body = emitBodyNodes(node.body, options);
327
+ return `${header}\n${body}`;
328
+ }
329
+ /**
330
+ * Emit a TrackedChangeNode.
331
+ *
332
+ * When TypstEmitOptions.trackedChanges is "changes":
333
+ * insertion → #underline[body]
334
+ * deletion → #strike[body]
335
+ * format-change → body content only (no formatting wrapper; style changed,
336
+ * not content)
337
+ *
338
+ * In other modes ("final", "original") the parser does not emit
339
+ * TrackedChangeNode values. If one is encountered anyway (e.g. the consumer
340
+ * constructed the model manually), it is rendered transparently as its body
341
+ * content with no annotation wrapper — matching the HTML renderer's behavior.
342
+ */
343
+ function emitTrackedChange(node, options) {
344
+ const body = emitBodyNodes(node.body, options);
345
+ if (options?.trackedChanges !== "changes") {
346
+ return body;
347
+ }
348
+ switch (node.changeType) {
349
+ case "insertion":
350
+ return `#underline[${body}]`;
351
+ case "deletion":
352
+ return `#strike[${body}]`;
353
+ case "format-change":
354
+ return body;
355
+ }
356
+ }
357
+ /** Emit a single BodyNode to a Typst markup string. */
358
+ function emitBodyNode(node, options) {
359
+ switch (node.kind) {
360
+ case "paragraph": {
361
+ const content = emitSpans(node.spans, options);
362
+ if (node.paragraphStyle?.textAlign !== undefined) {
363
+ const align = mapTextAlign(node.paragraphStyle.textAlign);
364
+ return `#align(${align})[${content}]`;
365
+ }
366
+ return content;
367
+ }
368
+ case "heading": {
369
+ const prefix = "=".repeat(node.level);
370
+ const content = emitSpans(node.spans, options);
371
+ return `${prefix} ${content}`;
372
+ }
373
+ case "list":
374
+ return emitList(node, options);
375
+ case "table":
376
+ return emitTable(node, options);
377
+ case "section":
378
+ return emitSection(node, options);
379
+ case "tracked-change":
380
+ return emitTrackedChange(node, options);
381
+ }
382
+ }
383
+ /**
384
+ * Emit an array of BodyNode objects separated by blank lines.
385
+ *
386
+ * Blank-line separation is the standard Typst paragraph delimiter and
387
+ * ensures distinct blocks do not run together in the output.
388
+ */
389
+ function emitBodyNodes(body, options) {
390
+ return body.map((n) => emitBodyNode(n, options)).join("\n\n");
391
+ }
392
+ // ============================================================
393
+ // Public API
394
+ // ============================================================
395
+ /**
396
+ * Convert an OdtDocumentModel to a Typst markup string.
397
+ *
398
+ * This is the primary emitter function. It accepts a pre-parsed document
399
+ * model and returns a .typ string with no side effects and no filesystem
400
+ * access. Use this when you already have a model from readOdt() or when
401
+ * you need fine-grained control over read options.
402
+ *
403
+ * @param model - The parsed ODT document model from readOdt().
404
+ * @param options - Typst emitter options.
405
+ * @returns Typst markup string (.typ).
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * import { readOdt } from "odf-kit/reader";
410
+ * import { modelToTypst } from "odf-kit/typst";
411
+ * import { readFileSync, writeFileSync } from "node:fs";
412
+ *
413
+ * const bytes = new Uint8Array(readFileSync("document.odt"));
414
+ * const model = readOdt(bytes);
415
+ * const typ = modelToTypst(model);
416
+ * writeFileSync("document.typ", typ);
417
+ * // then: typst compile document.typ document.pdf
418
+ * ```
419
+ */
420
+ export function modelToTypst(model, options) {
421
+ const sections = [];
422
+ const pageSetup = emitPageSetup(model);
423
+ if (pageSetup)
424
+ sections.push(pageSetup);
425
+ const body = emitBodyNodes(model.body, options);
426
+ if (body)
427
+ sections.push(body);
428
+ return sections.join("\n\n");
429
+ }
430
+ /**
431
+ * Convert an .odt file directly to a Typst markup string.
432
+ *
433
+ * Convenience wrapper around readOdt() + modelToTypst(). Use modelToTypst()
434
+ * directly when you need access to the document model, metadata, or want to
435
+ * share a single readOdt() call between multiple emitters.
436
+ *
437
+ * @param bytes - The raw .odt file as a Uint8Array.
438
+ * @param options - Combined emitter and read options. The trackedChanges
439
+ * field is forwarded to both readOdt() and modelToTypst() — set it once
440
+ * for consistent results across both steps.
441
+ * @returns Typst markup string (.typ).
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * import { odtToTypst } from "odf-kit/typst";
446
+ * import { readFileSync, writeFileSync } from "node:fs";
447
+ *
448
+ * const bytes = new Uint8Array(readFileSync("document.odt"));
449
+ * const typ = odtToTypst(bytes);
450
+ * writeFileSync("document.typ", typ);
451
+ * // then: typst compile document.typ document.pdf
452
+ * ```
453
+ */
454
+ export function odtToTypst(bytes, options) {
455
+ const model = readOdt(bytes, options);
456
+ return modelToTypst(model, options);
457
+ }
458
+ //# sourceMappingURL=emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../src/typst/emitter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Typst emitter for odf-kit.
3
+ *
4
+ * Converts ODT documents to Typst markup (.typ), which can then be compiled
5
+ * to PDF by any Typst 0.11+ installation:
6
+ *
7
+ * typst compile document.typ document.pdf
8
+ *
9
+ * Import from "odf-kit/typst" (separate from the main "odf-kit" import
10
+ * so the emitter is only bundled when explicitly needed):
11
+ *
12
+ * ```typescript
13
+ * import { modelToTypst, odtToTypst } from "odf-kit/typst";
14
+ * ```
15
+ *
16
+ * modelToTypst() accepts a pre-parsed OdtDocumentModel and is the primary
17
+ * function. odtToTypst() is a convenience wrapper that calls readOdt() +
18
+ * modelToTypst() in a single step.
19
+ *
20
+ * Both functions are zero-dependency pure functions — no filesystem access,
21
+ * no child process spawning, no Typst installation required at import time.
22
+ * The consumer decides how to use the returned .typ string.
23
+ */
24
+ export { modelToTypst, odtToTypst } from "./emitter.js";
25
+ export type { TypstEmitOptions } from "./emitter.js";
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/typst/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Typst emitter for odf-kit.
3
+ *
4
+ * Converts ODT documents to Typst markup (.typ), which can then be compiled
5
+ * to PDF by any Typst 0.11+ installation:
6
+ *
7
+ * typst compile document.typ document.pdf
8
+ *
9
+ * Import from "odf-kit/typst" (separate from the main "odf-kit" import
10
+ * so the emitter is only bundled when explicitly needed):
11
+ *
12
+ * ```typescript
13
+ * import { modelToTypst, odtToTypst } from "odf-kit/typst";
14
+ * ```
15
+ *
16
+ * modelToTypst() accepts a pre-parsed OdtDocumentModel and is the primary
17
+ * function. odtToTypst() is a convenience wrapper that calls readOdt() +
18
+ * modelToTypst() in a single step.
19
+ *
20
+ * Both functions are zero-dependency pure functions — no filesystem access,
21
+ * no child process spawning, no Typst installation required at import time.
22
+ * The consumer decides how to use the returned .typ string.
23
+ */
24
+ export { modelToTypst, odtToTypst } from "./emitter.js";
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/typst/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "odf-kit",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Create OpenDocument Format files (.odt, .ods, .odp, .odg) in TypeScript/JavaScript. Works in Node.js and browsers.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -13,6 +13,10 @@
13
13
  "./reader": {
14
14
  "types": "./dist/reader/index.d.ts",
15
15
  "import": "./dist/reader/index.js"
16
+ },
17
+ "./typst": {
18
+ "types": "./dist/typst/index.d.ts",
19
+ "import": "./dist/typst/index.js"
16
20
  }
17
21
  },
18
22
  "files": [