odf-kit 0.9.4 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,57 +5,155 @@ All notable changes to odf-kit will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.3.0] - 2026-02-23
8
+ ## [0.9.5] - 2026-04-09
9
+
10
+ ### Added
11
+
12
+ - **`markdownToOdt()`** — Convert Markdown directly to ODT. Accepts any CommonMark Markdown string and returns a valid `.odt` file as `Uint8Array`. Supports all `HtmlToOdtOptions` (page format, margins, orientation, metadata). Internally converts Markdown → HTML via `marked`, then HTML → ODT via `htmlToOdt()`.
13
+ - **`marked`** added as first runtime dependency (23kB, zero transitive dependencies).
14
+ - 17 new tests.
15
+
16
+ ## [0.9.4] - 2026-04-06
17
+
18
+ ### Fixed
9
19
 
10
- Template engine.
20
+ - **ODS datetime detection** — `Date` objects with a nonzero UTC time component now render as datetime (`YYYY-MM-DDTHH:MM:SS`) rather than date-only (`YYYY-MM-DD`). Auto-detected: if `getUTCHours()`, `getUTCMinutes()`, `getUTCSeconds()`, or `getUTCMilliseconds()` are nonzero, the cell uses `office:date-value` with full datetime format and a matching `number:date-style`.
21
+ - **ODS formula namespace** — Added `xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2"` to the `office:document-content` root element. Previously the `of:` prefix used in formula values was undeclared, causing LibreOffice to display `Err:510` in formula cells.
22
+
23
+ ## [0.9.2] - 2026-04-05
11
24
 
12
25
  ### Added
13
26
 
14
- - **Template engine** Fill existing `.odt` templates with data using `fillTemplate()`. Load a `.odt` file created in LibreOffice, replace `{placeholders}` with values from a JSON/object data source, and get a new `.odt` file back.
15
- - **Simple replacement** — `{tag}` placeholders replaced with values, with automatic XML escaping of `& < > " '`
16
- - **Loops** — `{#items}...{/items}` repeats content for each item in an array. Items inherit parent data; item properties override.
17
- - **Conditionals** `{#showSection}...{/showSection}` includes or removes content based on truthy/falsy values.
18
- - **Dot notation** `{user.address.city}` resolves nested object paths.
19
- - **Placeholder healer** Automatically reassembles placeholders that LibreOffice fragments across multiple `<text:span>` elements. Handles 2-span, multi-span, every-character, shared-segment, and bare-text fragmentation patterns. Removes editing artifacts (`<text:s/>`, `<text:bookmark/>`) trapped inside fragments.
20
- - **Boundary expansion** — Section markers (`{#tag}`, `{/tag}`) expand outward through wrapping XML elements to prevent orphaned empty tags after removal.
21
- - **Header/footer templates** — Placeholders in `styles.xml` (headers and footers) are processed alongside `content.xml`.
22
- - **120 new tests** — healer (51), replacer (56), template pipeline and integration (13). Total: 222 tests.
27
+ - **`htmlToOdt()`**Convert HTML to ODT. Accepts any HTML string (full document or fragment) and returns a valid `.odt` file as `Uint8Array`. Supports headings (h1–h6), paragraphs, bold, italic, underline, strikethrough, lists (ordered and unordered, nested), tables, hyperlinks, blockquotes, code blocks, horizontal rules, and inline CSS (color, font-size, font-family, text-align, background-color on cells).
28
+ - **Page format presets** — `A4` (default), `letter`, `legal`, `A3`, `A5`. Individual margin overrides apply on top of preset defaults.
29
+ - **`HtmlToOdtOptions`** — `pageFormat`, `orientation`, `marginTop/Bottom/Left/Right`, `metadata` (title, creator, description).
30
+ - **`addLineBreak()`** on `ParagraphBuilder` inserts a `text:line-break` within a paragraph.
31
+ - **`borderBottom`** on `ParagraphOptions` bottom border on a paragraph (useful for horizontal rules and section dividers).
32
+ - 62 new tests (769 total).
23
33
 
24
- ### Credits
34
+ ## [0.9.1] - 2026-04-04
25
35
 
26
- Template syntax follows [Mustache](https://mustache.github.io/) conventions (`{tag}`, `{#section}{/section}`), proven in document templating by [docxtemplater](https://docxtemplater.com/). odf-kit's template engine is a clean-room implementation purpose-built for ODF — no code from either project was used.
36
+ ### Fixed
27
37
 
28
- ## [0.2.0] - 2026-02-21
38
+ - Added `"./ods"` sub-export to `package.json` exports map. v0.9.0 was published without this entry, making `import { OdsDocument } from "odf-kit/ods"` fail with a module resolution error.
39
+
40
+ ## [0.9.0] - 2026-04-04
41
+
42
+ ### Added
43
+
44
+ - **ODS spreadsheet generation** — `OdsDocument` and `OdsSheet` for creating `.ods` files.
45
+ - **`OdsDocument`** — `addSheet(name)`, `setDateFormat()`, `save()`.
46
+ - **`OdsSheet`** — `addRow(values, options?)`, `setColumnWidth(index, width)`, `setRowHeight(index, height)`.
47
+ - **Auto-typed cells** — `number` → float, `Date` → date, `boolean` → boolean, `null`/`undefined` → empty. String values are always string type; formula cells require explicit `{ value, type: "formula" }`.
48
+ - **Date formatting** — Three built-in formats: `"YYYY-MM-DD"` (ISO, default), `"DD/MM/YYYY"` (European), `"MM/DD/YYYY"` (US). Set document-level default via `setDateFormat()` or override per-cell via `dateFormat` in cell options.
49
+ - **Cell formatting** — `bold`, `italic`, `fontSize`, `fontFamily`, `color`, `backgroundColor`, `border`, `borderTop/Bottom/Left/Right`, `align`, `verticalAlign`, `padding`, `wrap`.
50
+ - **Row formatting** — Pass formatting options as second argument to `addRow()` — applies to all cells in the row as defaults. Cell-level options override row defaults.
51
+ - **Multiple sheets** — `addSheet()` creates additional tabs.
52
+ - **Style deduplication** — Identical cell styles across all sheets share a single ODF style element.
53
+ - **Package restructure** — New sub-exports: `odf-kit/odt`, `odf-kit/ods`, `odf-kit/template`, `odf-kit/reader`, `odf-kit/typst`. Existing `import { OdtDocument } from "odf-kit"` continues to work unchanged.
54
+ - 57 new tests (707 total).
55
+
56
+ ## [0.8.4] - 2026-04-03
57
+
58
+ ### Fixed
59
+
60
+ - **ReDoS in healer/replacer** — Replaced catastrophic backtracking regex patterns with linear alternatives.
61
+ - **Double-escaping in xml-parser** — Fixed entity double-encoding when parsing XML with pre-escaped content.
62
+ - **CI permissions** — Tightened GitHub Actions workflow permissions.
63
+
64
+ ## [0.8.3] - 2026-03-26
65
+
66
+ ### Added
67
+
68
+ - **Image wrap mode** — `wrapMode: "left" | "right" | "none"` on `ImageOptions`. Left/right wrap positions the image with text flowing around it. Requires graphic style subsystem (new in this release).
69
+ - **Image margins** — `marginTop`, `marginBottom`, `marginLeft`, `marginRight` on `ImageOptions`.
70
+ - **Image border** — `border` on `ImageOptions` (CSS shorthand, e.g. `"0.5pt solid #000000"`).
71
+ - **Image opacity** — `opacity` on `ImageOptions` (0–1).
72
+
73
+ ## [0.8.2] - 2026-03-26
74
+
75
+ ### Added
76
+
77
+ - **Image accessibility** — `alt` → `<svg:title>`, `description` → `<svg:desc>` inside `draw:frame`.
78
+ - **`name`** override for `draw:name` on images.
79
+ - **`anchor: "page"`** support on `ImageOptions`.
80
+ - 6 new tests.
29
81
 
30
- Zero-dependency migration.
82
+ ## [0.8.1] - 2026-03-20
31
83
 
32
84
  ### Changed
33
85
 
34
- - **Replaced jszip with fflate** — Zero transitive runtime dependencies. Faster compression/decompression, smaller bundle (~8kB). MIT license.
35
- - All 102 existing tests re-validated with fflate. Generated files verified in LibreOffice.
86
+ - **README overhaul** — Full rewrite covering all four modes (build, fill, read, typst). Added Guides section with links to all guide and tool pages.
87
+ - Fixed `package.json` description field.
88
+ - Fixed dev vulnerabilities (ajv, flatted).
36
89
 
37
- ## [0.1.0] - 2026-02-11
90
+ ## [0.8.0] - 2026-03-20
91
+
92
+ ### Added
93
+
94
+ - **Typst emitter** — `odtToTypst()` and `modelToTypst()` via new `odf-kit/typst` sub-export. Converts ODT files to [Typst](https://typst.app) markup. Zero-dependency, pure TypeScript, browser-safe. Returns a `.typ` string.
95
+
96
+ ## [0.7.0] - 2026-03-15
97
+
98
+ ### Added
99
+
100
+ - **ODT reader** — `readOdt()` parses `.odt` files into a structured `OdtDocumentModel`. Tier 1 (raw XML), Tier 2 (semantic model), and Tier 3 (rendered output). Available via `odf-kit/reader`.
101
+ - **`odtToHtml()`** — Convert ODT to an HTML string.
102
+ - **HTML renderer** — Full fidelity rendering of headings, paragraphs, formatting, lists, tables, images (as base64 data URIs), hyperlinks.
103
+
104
+ ## [0.4.0] - 2026-03-05
105
+
106
+ ### Added
107
+
108
+ - **Advanced text formatting** — Underline, strikethrough, superscript, subscript, highlight color (hex and named CSS colors).
109
+ - **Hyperlinks** — External URLs (`https://...`) and internal bookmark links (`#name`). Optional text formatting on links.
110
+ - **Bookmarks** — `addBookmark(name)` on `ParagraphBuilder`.
111
+ - **Images** — Embedded PNG, JPEG, GIF, SVG, WebP, BMP, TIFF. Standalone (paragraph anchor) or inline (as-character). Stored in ZIP under `Pictures/` with correct MIME types in manifest.
112
+ - **`draw` and `xlink` namespaces** added to content.xml.
113
+ - 109 new tests.
38
114
 
39
- Initial release. Complete ODT (text document) support.
115
+ ## [0.3.0] - 2026-02-23
40
116
 
41
117
  ### Added
42
118
 
43
- - **Core** — ODF ZIP packaging (mimetype stored uncompressed as first entry), XML generation, namespace management, manifest, metadata
44
- - **Paragraphs and headings** — Plain text or formatted via builder callback, heading levels 1–6
45
- - **Text formatting** — Bold, italic, underline, strikethrough, superscript, subscript, font size, font family, text color, highlight color. Boolean shortcuts (`bold: true`) and CSS-style properties (`fontWeight: "bold"`) both accepted. Style deduplication for identical formatting.
46
- - **Tables** — Array-of-arrays for simple tables, builder callback for full control. Column widths, cell borders (table-level, cell-level, per-side), background colors (hex and named CSS colors), cell merging (colSpan/rowSpan), rich text in cells.
47
- - **Page layout** — Page size (A4 default), margins, orientation (portrait/landscape). Landscape auto-swaps A4 dimensions.
48
- - **Headers and footers** — Plain text (with `###` for page numbers) or formatted via builder callback with `addPageNumber()`.
49
- - **Page breaks** — `addPageBreak()` inserts a new page.
50
- - **Lists** Bullet and numbered lists. String array for simple lists, builder callback for formatting and nesting (up to 6 levels).
51
- - **Tab stops** — Left, center, right alignment with configurable positions.
52
- - **Images** — Embedded PNG, JPEG, GIF, SVG, WebP, BMP, TIFF. Standalone (paragraph anchor) or inline (as-character anchor). Images stored in ZIP under `Pictures/` with correct MIME types in manifest.
53
- - **Hyperlinks** — External URLs and internal bookmark links (`#name`). Optional text formatting on links.
54
- - **Bookmarks** — Named anchor points for internal navigation via `addBookmark()`.
55
- - **Method chaining** — All methods return `this` for fluent API usage.
56
- - **TypeScript** — Full type definitions with JSDoc comments. ESM-only, Node.js 22+.
57
- - **Testing** — 102 tests covering all features. Validated against LibreOffice 24.2.
119
+ - **Template engine** — Fill existing `.odt` templates with data using `fillTemplate()`. Replaces `{placeholders}` with values from a data object.
120
+ - **Simple replacement** — `{tag}` placeholders with automatic XML escaping.
121
+ - **Loops** — `{#items}...{/items}` repeats content for each array item.
122
+ - **Conditionals** — `{#showSection}...{/showSection}` includes or removes content.
123
+ - **Dot notation** — `{user.address.city}` resolves nested object paths.
124
+ - **Placeholder healer** — Reassembles placeholders fragmented by LibreOffice across multiple `<text:span>` elements.
125
+ - **Header/footer templates** — Placeholders in `styles.xml` processed alongside `content.xml`.
126
+ - 120 new tests (222 total).
127
+
128
+ ## [0.2.0] - 2026-02-21
129
+
130
+ ### Changed
131
+
132
+ - **Replaced jszip with fflate** — Zero transitive runtime dependencies. Faster, smaller (~8kB). MIT license.
133
+
134
+ ## [0.1.0] - 2026-02-11
135
+
136
+ Initial release. Complete ODT generation support.
137
+
138
+ ### Added
58
139
 
140
+ - Core ODF ZIP packaging, XML generation, namespace management, manifest, metadata.
141
+ - Paragraphs, headings (levels 1–6), text formatting (bold, italic, font size, color, etc.).
142
+ - Tables, page layout, headers/footers, page breaks, lists, tab stops.
143
+ - Method chaining. Full TypeScript types. ESM-only, Node.js 22+. 102 tests.
144
+
145
+ [0.9.5]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.5
146
+ [0.9.4]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.4
147
+ [0.9.2]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.2
148
+ [0.9.1]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.1
149
+ [0.9.0]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.0
150
+ [0.8.4]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.8.4
151
+ [0.8.3]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.8.3
152
+ [0.8.2]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.8.2
153
+ [0.8.1]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.8.1
154
+ [0.8.0]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.8.0
155
+ [0.7.0]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.7.0
156
+ [0.4.0]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.4.0
59
157
  [0.3.0]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.3.0
60
158
  [0.2.0]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.2.0
61
159
  [0.1.0]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.1.0
package/dist/index.d.ts CHANGED
@@ -4,7 +4,9 @@ export { HeaderFooterBuilder } from "./odt/index.js";
4
4
  export { TableBuilder, RowBuilder, CellBuilder } from "./odt/index.js";
5
5
  export { ListBuilder } from "./odt/index.js";
6
6
  export { htmlToOdt } from "./odt/index.js";
7
- export type { ContentElement, TextFormatting, TextRun, TableOptions, CellOptions, PageLayout, ParagraphOptions, TabStop, ListOptions, ImageOptions, ImageData, HtmlToOdtOptions, } from "./odt/index.js";
7
+ export { markdownToOdt } from "./odt/index.js";
8
+ export { tiptapToOdt } from "./odt/index.js";
9
+ export type { ContentElement, TextFormatting, TextRun, TableOptions, CellOptions, PageLayout, ParagraphOptions, TabStop, ListOptions, ImageOptions, ImageData, HtmlToOdtOptions, TiptapNode, TiptapMark, TiptapToOdtOptions, } from "./odt/index.js";
8
10
  export type { MetadataOptions } from "./core/index.js";
9
11
  export { fillTemplate, healPlaceholders, replaceAll } from "./template/index.js";
10
12
  export type { TemplateData } from "./template/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACV,cAAc,EACd,cAAc,EACd,OAAO,EACP,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,GACd,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EACV,cAAc,EACd,cAAc,EACd,OAAO,EACP,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,GACd,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ export { HeaderFooterBuilder } from "./odt/index.js";
6
6
  export { TableBuilder, RowBuilder, CellBuilder } from "./odt/index.js";
7
7
  export { ListBuilder } from "./odt/index.js";
8
8
  export { htmlToOdt } from "./odt/index.js";
9
+ export { markdownToOdt } from "./odt/index.js";
10
+ export { tiptapToOdt } from "./odt/index.js";
9
11
  export { fillTemplate, healPlaceholders, replaceAll } from "./template/index.js";
10
12
  export { OdsDocument } from "./ods/index.js";
11
13
  export { OdsSheet } from "./ods/index.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,2CAA2C;AAE3C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAgB3C,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,2CAA2C;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAmB7C,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
@@ -4,7 +4,10 @@ export { HeaderFooterBuilder } from "./header-footer-builder.js";
4
4
  export { TableBuilder, RowBuilder, CellBuilder } from "./table-builder.js";
5
5
  export { ListBuilder } from "./list-builder.js";
6
6
  export { htmlToOdt } from "./html-to-odt.js";
7
+ export { markdownToOdt } from "./markdown-to-odt.js";
8
+ export { tiptapToOdt } from "./tiptap-to-odt.js";
7
9
  export type { ContentElement } from "./content.js";
8
10
  export type { HtmlToOdtOptions } from "./html-to-odt.js";
11
+ export type { TiptapNode, TiptapMark, TiptapToOdtOptions } from "./tiptap-to-odt.js";
9
12
  export type { TextFormatting, TextRun, TableOptions, CellOptions, PageLayout, ParagraphOptions, TabStop, ListOptions, ImageOptions, ImageData, } from "./types.js";
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/odt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,YAAY,EACV,cAAc,EACd,OAAO,EACP,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,GACV,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/odt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACrF,YAAY,EACV,cAAc,EACd,OAAO,EACP,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,GACV,MAAM,YAAY,CAAC"}
package/dist/odt/index.js CHANGED
@@ -4,4 +4,6 @@ export { HeaderFooterBuilder } from "./header-footer-builder.js";
4
4
  export { TableBuilder, RowBuilder, CellBuilder } from "./table-builder.js";
5
5
  export { ListBuilder } from "./list-builder.js";
6
6
  export { htmlToOdt } from "./html-to-odt.js";
7
+ export { markdownToOdt } from "./markdown-to-odt.js";
8
+ export { tiptapToOdt } from "./tiptap-to-odt.js";
7
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/odt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/odt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { HtmlToOdtOptions } from "./html-to-odt.js";
2
+ /**
3
+ * Convert a Markdown string to an ODT file.
4
+ *
5
+ * Internally converts Markdown → HTML via `marked`, then HTML → ODT
6
+ * via {@link htmlToOdt}. All {@link HtmlToOdtOptions} apply — page format,
7
+ * orientation, margins, and metadata.
8
+ *
9
+ * **Supported Markdown:** CommonMark spec — headings, paragraphs, bold,
10
+ * italic, strikethrough, unordered and ordered lists, nested lists, tables,
11
+ * blockquotes, fenced code blocks, inline code, horizontal rules, and links.
12
+ *
13
+ * **Page format:** Defaults to A4, the ISO standard for Europe and most of
14
+ * the world. Pass `{ pageFormat: "letter" }` for US/Canadian users.
15
+ *
16
+ * @param markdown - Markdown string to convert.
17
+ * @param options - Optional page format, margins, orientation, and metadata.
18
+ * @returns Promise resolving to a valid `.odt` file as a `Uint8Array`.
19
+ *
20
+ * @example
21
+ * // Basic usage — A4 page (default)
22
+ * import { markdownToOdt } from "odf-kit";
23
+ * const bytes = await markdownToOdt("# Hello\n\nWorld");
24
+ *
25
+ * @example
26
+ * // US letter with metadata
27
+ * const bytes = await markdownToOdt(markdownString, {
28
+ * pageFormat: "letter",
29
+ * metadata: { title: "My Document", creator: "Alice" },
30
+ * });
31
+ */
32
+ export declare function markdownToOdt(markdown: string, options?: HtmlToOdtOptions): Promise<Uint8Array>;
33
+ //# sourceMappingURL=markdown-to-odt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-to-odt.d.ts","sourceRoot":"","sources":["../../src/odt/markdown-to-odt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,UAAU,CAAC,CAGrB"}
@@ -0,0 +1,37 @@
1
+ import { marked } from "marked";
2
+ import { htmlToOdt } from "./html-to-odt.js";
3
+ /**
4
+ * Convert a Markdown string to an ODT file.
5
+ *
6
+ * Internally converts Markdown → HTML via `marked`, then HTML → ODT
7
+ * via {@link htmlToOdt}. All {@link HtmlToOdtOptions} apply — page format,
8
+ * orientation, margins, and metadata.
9
+ *
10
+ * **Supported Markdown:** CommonMark spec — headings, paragraphs, bold,
11
+ * italic, strikethrough, unordered and ordered lists, nested lists, tables,
12
+ * blockquotes, fenced code blocks, inline code, horizontal rules, and links.
13
+ *
14
+ * **Page format:** Defaults to A4, the ISO standard for Europe and most of
15
+ * the world. Pass `{ pageFormat: "letter" }` for US/Canadian users.
16
+ *
17
+ * @param markdown - Markdown string to convert.
18
+ * @param options - Optional page format, margins, orientation, and metadata.
19
+ * @returns Promise resolving to a valid `.odt` file as a `Uint8Array`.
20
+ *
21
+ * @example
22
+ * // Basic usage — A4 page (default)
23
+ * import { markdownToOdt } from "odf-kit";
24
+ * const bytes = await markdownToOdt("# Hello\n\nWorld");
25
+ *
26
+ * @example
27
+ * // US letter with metadata
28
+ * const bytes = await markdownToOdt(markdownString, {
29
+ * pageFormat: "letter",
30
+ * metadata: { title: "My Document", creator: "Alice" },
31
+ * });
32
+ */
33
+ export async function markdownToOdt(markdown, options) {
34
+ const html = await marked.parse(markdown);
35
+ return htmlToOdt(html, options);
36
+ }
37
+ //# sourceMappingURL=markdown-to-odt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-to-odt.js","sourceRoot":"","sources":["../../src/odt/markdown-to-odt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,OAA0B;IAE1B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * TipTap/ProseMirror JSON to ODT converter.
3
+ *
4
+ * Walks a TipTap JSONContent document tree and maps nodes to OdtDocument
5
+ * API calls. No dependency on @tiptap/core — just plain JSON walking.
6
+ *
7
+ * Supported block nodes: doc, paragraph, heading (1–6), bulletList,
8
+ * orderedList, listItem, blockquote, codeBlock, horizontalRule, hardBreak,
9
+ * image (data URI or pre-fetched via images option), table, tableRow,
10
+ * tableCell, tableHeader.
11
+ *
12
+ * Supported marks: bold, italic, underline, strike, code, link, textStyle
13
+ * (color, fontSize, fontFamily), highlight, superscript, subscript.
14
+ *
15
+ * Unknown node types are silently skipped unless unknownNodeHandler is
16
+ * provided in options.
17
+ */
18
+ import type { OdtDocument } from "./document.js";
19
+ import type { HtmlToOdtOptions } from "./html-to-odt.js";
20
+ /** A TipTap/ProseMirror JSON document node. */
21
+ export interface TiptapNode {
22
+ /** Node type name (e.g. "doc", "paragraph", "heading", "text"). */
23
+ type: string;
24
+ /** Text content — present only on text nodes. */
25
+ text?: string;
26
+ /** Node attributes (e.g. { level: 1 } for headings, { href: "..." } for links). */
27
+ attrs?: Record<string, unknown>;
28
+ /** Child nodes — present on block and inline container nodes. */
29
+ content?: TiptapNode[];
30
+ /** Inline formatting marks — present on text nodes. */
31
+ marks?: TiptapMark[];
32
+ }
33
+ /** A TipTap/ProseMirror inline mark. */
34
+ export interface TiptapMark {
35
+ /** Mark type name (e.g. "bold", "italic", "link", "textStyle"). */
36
+ type: string;
37
+ /** Mark attributes (e.g. { href: "..." } for link, { color: "#ff0000" } for textStyle). */
38
+ attrs?: Record<string, unknown>;
39
+ }
40
+ /**
41
+ * Options for {@link tiptapToOdt}.
42
+ *
43
+ * Extends {@link HtmlToOdtOptions} — all page format, margin, orientation,
44
+ * and metadata options apply.
45
+ */
46
+ export interface TiptapToOdtOptions extends HtmlToOdtOptions {
47
+ /**
48
+ * Pre-fetched image bytes keyed by src URL.
49
+ *
50
+ * TipTap image nodes with `attrs.src` are looked up in this map.
51
+ * If found, the image is embedded in the ODT. If not found (and the src
52
+ * is not a data URI), a placeholder paragraph is emitted instead.
53
+ *
54
+ * Data URIs (`data:image/...;base64,...`) are always decoded and embedded
55
+ * regardless of this map.
56
+ *
57
+ * @example
58
+ * const images = {
59
+ * "https://example.com/photo.jpg": jpegBytes,
60
+ * "ipfs://Qm...": ipfsImageBytes,
61
+ * }
62
+ * const bytes = await tiptapToOdt(json, { images })
63
+ */
64
+ images?: Record<string, Uint8Array>;
65
+ /**
66
+ * Handler for unknown node types — custom TipTap extensions not
67
+ * recognized by odf-kit.
68
+ *
69
+ * Called once per unrecognized node. The handler receives the node and
70
+ * the OdtDocument instance and may call any OdtDocument methods to add
71
+ * content. If not provided, unknown nodes are silently skipped.
72
+ *
73
+ * @example
74
+ * // Handle a custom "callout" node
75
+ * unknownNodeHandler: (node, doc) => {
76
+ * if (node.type === 'callout') {
77
+ * const text = node.content?.[0]?.content?.[0]?.text ?? ''
78
+ * doc.addParagraph(`⚠️ ${text}`)
79
+ * }
80
+ * }
81
+ */
82
+ unknownNodeHandler?: (node: TiptapNode, doc: OdtDocument) => void;
83
+ }
84
+ /**
85
+ * Convert a TipTap/ProseMirror JSON document to an ODT file.
86
+ *
87
+ * Accepts the JSON object returned by `editor.getJSON()` in TipTap.
88
+ * No dependency on @tiptap/core — the JSON is walked as a plain object.
89
+ *
90
+ * @param json - TipTap JSONContent document (must have type "doc").
91
+ * @param options - Page format, margins, metadata, images, unknownNodeHandler.
92
+ * @returns Promise resolving to a valid `.odt` file as a `Uint8Array`.
93
+ *
94
+ * @example
95
+ * import { tiptapToOdt } from "odf-kit"
96
+ *
97
+ * const json = editor.getJSON()
98
+ * const bytes = await tiptapToOdt(json, { pageFormat: "A4" })
99
+ *
100
+ * @example
101
+ * // With pre-fetched images
102
+ * const images = { "https://example.com/photo.jpg": jpegBytes }
103
+ * const bytes = await tiptapToOdt(json, { images })
104
+ *
105
+ * @example
106
+ * // With custom node handler
107
+ * const bytes = await tiptapToOdt(json, {
108
+ * unknownNodeHandler: (node, doc) => {
109
+ * if (node.type === "callout") {
110
+ * doc.addParagraph(`⚠️ ${extractText(node)}`)
111
+ * }
112
+ * }
113
+ * })
114
+ */
115
+ export declare function tiptapToOdt(json: TiptapNode, options?: TiptapToOdtOptions): Promise<Uint8Array>;
116
+ //# sourceMappingURL=tiptap-to-odt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiptap-to-odt.d.ts","sourceRoot":"","sources":["../../src/odt/tiptap-to-odt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAKzD,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,iEAAiE;IACjE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,uDAAuD;IACvD,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEpC;;;;;;;;;;;;;;;;OAgBG;IACH,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;CACnE;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,UAAU,CAAC,CAsCrB"}
@@ -0,0 +1,447 @@
1
+ /**
2
+ * TipTap/ProseMirror JSON to ODT converter.
3
+ *
4
+ * Walks a TipTap JSONContent document tree and maps nodes to OdtDocument
5
+ * API calls. No dependency on @tiptap/core — just plain JSON walking.
6
+ *
7
+ * Supported block nodes: doc, paragraph, heading (1–6), bulletList,
8
+ * orderedList, listItem, blockquote, codeBlock, horizontalRule, hardBreak,
9
+ * image (data URI or pre-fetched via images option), table, tableRow,
10
+ * tableCell, tableHeader.
11
+ *
12
+ * Supported marks: bold, italic, underline, strike, code, link, textStyle
13
+ * (color, fontSize, fontFamily), highlight, superscript, subscript.
14
+ *
15
+ * Unknown node types are silently skipped unless unknownNodeHandler is
16
+ * provided in options.
17
+ */
18
+ // ─── Constants ────────────────────────────────────────────────────────
19
+ const HR_BORDER = "0.5pt solid #000000";
20
+ const BLOCKQUOTE_INDENT = "1cm";
21
+ const MONOSPACE_FONT = "Courier New";
22
+ // ─── Public API ───────────────────────────────────────────────────────
23
+ /**
24
+ * Convert a TipTap/ProseMirror JSON document to an ODT file.
25
+ *
26
+ * Accepts the JSON object returned by `editor.getJSON()` in TipTap.
27
+ * No dependency on @tiptap/core — the JSON is walked as a plain object.
28
+ *
29
+ * @param json - TipTap JSONContent document (must have type "doc").
30
+ * @param options - Page format, margins, metadata, images, unknownNodeHandler.
31
+ * @returns Promise resolving to a valid `.odt` file as a `Uint8Array`.
32
+ *
33
+ * @example
34
+ * import { tiptapToOdt } from "odf-kit"
35
+ *
36
+ * const json = editor.getJSON()
37
+ * const bytes = await tiptapToOdt(json, { pageFormat: "A4" })
38
+ *
39
+ * @example
40
+ * // With pre-fetched images
41
+ * const images = { "https://example.com/photo.jpg": jpegBytes }
42
+ * const bytes = await tiptapToOdt(json, { images })
43
+ *
44
+ * @example
45
+ * // With custom node handler
46
+ * const bytes = await tiptapToOdt(json, {
47
+ * unknownNodeHandler: (node, doc) => {
48
+ * if (node.type === "callout") {
49
+ * doc.addParagraph(`⚠️ ${extractText(node)}`)
50
+ * }
51
+ * }
52
+ * })
53
+ */
54
+ export async function tiptapToOdt(json, options) {
55
+ // We reuse htmlToOdt's page layout setup by creating the document
56
+ // through it with an empty HTML string, then walking the TipTap JSON
57
+ // to populate. However, htmlToOdt is not designed for this — instead
58
+ // we duplicate the page setup logic here for a clean implementation.
59
+ // Import OdtDocument dynamically to avoid circular dependency issues
60
+ const { OdtDocument } = await import("./document.js");
61
+ const doc = new OdtDocument();
62
+ // Apply metadata
63
+ if (options?.metadata) {
64
+ doc.setMetadata(options.metadata);
65
+ }
66
+ // Resolve page format (mirrors html-to-odt.ts)
67
+ const PAGE_FORMATS = {
68
+ A4: { width: "21cm", height: "29.7cm", margin: "2.5cm" },
69
+ letter: { width: "21.59cm", height: "27.94cm", margin: "2.54cm" },
70
+ legal: { width: "21.59cm", height: "35.56cm", margin: "2.54cm" },
71
+ A3: { width: "29.7cm", height: "42cm", margin: "2.5cm" },
72
+ A5: { width: "14.8cm", height: "21cm", margin: "2cm" },
73
+ };
74
+ const format = PAGE_FORMATS[options?.pageFormat ?? "A4"];
75
+ doc.setPageLayout({
76
+ width: format.width,
77
+ height: format.height,
78
+ orientation: options?.orientation,
79
+ marginTop: options?.marginTop ?? format.margin,
80
+ marginBottom: options?.marginBottom ?? format.margin,
81
+ marginLeft: options?.marginLeft ?? format.margin,
82
+ marginRight: options?.marginRight ?? format.margin,
83
+ });
84
+ // Walk the document tree
85
+ walkNode(json, doc, options ?? {});
86
+ return doc.save();
87
+ }
88
+ // ─── Node Walking ─────────────────────────────────────────────────────
89
+ /**
90
+ * Walk a single TipTap node and emit the corresponding ODT content.
91
+ */
92
+ function walkNode(node, doc, options) {
93
+ switch (node.type) {
94
+ case "doc":
95
+ for (const child of node.content ?? []) {
96
+ walkNode(child, doc, options);
97
+ }
98
+ break;
99
+ case "paragraph": {
100
+ const runs = extractRuns(node.content ?? [], {});
101
+ if (runs.length === 0 || runs.every((r) => !r.text && !r.lineBreak)) {
102
+ // Empty paragraph — still emit it to preserve spacing
103
+ doc.addParagraph("");
104
+ }
105
+ else {
106
+ doc.addParagraph((p) => applyRuns(p, runs));
107
+ }
108
+ break;
109
+ }
110
+ case "heading": {
111
+ const level = node.attrs?.level ?? 1;
112
+ const runs = extractRuns(node.content ?? [], {});
113
+ doc.addHeading((p) => applyRuns(p, runs), level);
114
+ break;
115
+ }
116
+ case "blockquote": {
117
+ const opts = { indentLeft: BLOCKQUOTE_INDENT };
118
+ for (const child of node.content ?? []) {
119
+ walkNodeWithParaOpts(child, doc, options, opts);
120
+ }
121
+ break;
122
+ }
123
+ case "codeBlock": {
124
+ const text = extractText(node);
125
+ const lines = text.split("\n");
126
+ doc.addParagraph((p) => {
127
+ lines.forEach((line, i) => {
128
+ p.addText(line, { fontFamily: MONOSPACE_FONT });
129
+ if (i < lines.length - 1)
130
+ p.addLineBreak();
131
+ });
132
+ });
133
+ break;
134
+ }
135
+ case "horizontalRule": {
136
+ doc.addParagraph("", { borderBottom: HR_BORDER });
137
+ break;
138
+ }
139
+ case "bulletList": {
140
+ doc.addList((l) => fillList(l, node, options), { type: "bullet" });
141
+ break;
142
+ }
143
+ case "orderedList": {
144
+ doc.addList((l) => fillList(l, node, options), { type: "numbered" });
145
+ break;
146
+ }
147
+ case "table": {
148
+ walkTable(node, doc);
149
+ break;
150
+ }
151
+ case "image": {
152
+ walkImage(node, doc, options);
153
+ break;
154
+ }
155
+ // Transparent containers — walk children
156
+ case "listItem":
157
+ case "tableRow":
158
+ case "tableCell":
159
+ case "tableHeader": {
160
+ for (const child of node.content ?? []) {
161
+ walkNode(child, doc, options);
162
+ }
163
+ break;
164
+ }
165
+ // Text node — should not appear at block level, emit as paragraph
166
+ case "text": {
167
+ const runs = extractRuns([node], {});
168
+ if (runs.length > 0) {
169
+ doc.addParagraph((p) => applyRuns(p, runs));
170
+ }
171
+ break;
172
+ }
173
+ default: {
174
+ if (options.unknownNodeHandler) {
175
+ options.unknownNodeHandler(node, doc);
176
+ }
177
+ // If no handler, silently skip
178
+ break;
179
+ }
180
+ }
181
+ }
182
+ /**
183
+ * Walk a node with inherited paragraph options (used for blockquote).
184
+ */
185
+ function walkNodeWithParaOpts(node, doc, options, paraOpts) {
186
+ if (node.type === "paragraph") {
187
+ const runs = extractRuns(node.content ?? [], {});
188
+ if (runs.length === 0 || runs.every((r) => !r.text && !r.lineBreak)) {
189
+ doc.addParagraph("", paraOpts);
190
+ }
191
+ else {
192
+ doc.addParagraph((p) => applyRuns(p, runs), paraOpts);
193
+ }
194
+ }
195
+ else {
196
+ walkNode(node, doc, options);
197
+ }
198
+ }
199
+ // ─── List Walking ─────────────────────────────────────────────────────
200
+ /**
201
+ * Populate a ListBuilder from a bulletList or orderedList node.
202
+ * Called recursively for nested lists.
203
+ */
204
+ function fillList(l, listNode, options) {
205
+ for (const item of listNode.content ?? []) {
206
+ if (item.type !== "listItem")
207
+ continue;
208
+ // A listItem contains one or more paragraphs and optionally nested lists
209
+ const paragraphs = (item.content ?? []).filter((c) => c.type === "paragraph");
210
+ const nestedList = (item.content ?? []).find((c) => c.type === "bulletList" || c.type === "orderedList");
211
+ // Use text from first paragraph as the item content
212
+ const firstPara = paragraphs[0];
213
+ const runs = firstPara ? extractRuns(firstPara.content ?? [], {}) : [];
214
+ if (runs.length > 0 && runs.some((r) => r.text || r.lineBreak)) {
215
+ l.addItem((p) => applyRuns(p, runs));
216
+ }
217
+ else {
218
+ l.addItem("");
219
+ }
220
+ if (nestedList) {
221
+ l.addNested((sub) => fillList(sub, nestedList, options));
222
+ }
223
+ }
224
+ }
225
+ // ─── Table Walking ────────────────────────────────────────────────────
226
+ /**
227
+ * Walk a table node and add a table to the document.
228
+ */
229
+ function walkTable(node, doc) {
230
+ const rows = node.content ?? [];
231
+ if (rows.length === 0)
232
+ return;
233
+ doc.addTable((t) => {
234
+ for (const row of rows) {
235
+ if (row.type !== "tableRow")
236
+ continue;
237
+ t.addRow((r) => {
238
+ for (const cell of row.content ?? []) {
239
+ if (cell.type !== "tableCell" && cell.type !== "tableHeader")
240
+ continue;
241
+ const isHeader = cell.type === "tableHeader";
242
+ const baseFormatting = isHeader ? { bold: true } : {};
243
+ // Extract text from all paragraphs in the cell
244
+ const allRuns = [];
245
+ for (const child of cell.content ?? []) {
246
+ if (child.type === "paragraph") {
247
+ const runs = extractRuns(child.content ?? [], baseFormatting);
248
+ if (allRuns.length > 0 && runs.length > 0) {
249
+ allRuns.push({ text: " " }); // space between paragraphs
250
+ }
251
+ allRuns.push(...runs);
252
+ }
253
+ }
254
+ if (allRuns.length > 0) {
255
+ r.addCell((c) => applyRuns(c, allRuns));
256
+ }
257
+ else {
258
+ r.addCell("");
259
+ }
260
+ }
261
+ });
262
+ }
263
+ });
264
+ }
265
+ // ─── Image Handling ───────────────────────────────────────────────────
266
+ /**
267
+ * Handle a TipTap image node.
268
+ * - Data URIs are decoded and embedded directly.
269
+ * - Other URLs are looked up in options.images. If found, embedded.
270
+ * - If not found, a placeholder paragraph is emitted.
271
+ */
272
+ function walkImage(node, doc, options) {
273
+ const src = node.attrs?.src ?? "";
274
+ const alt = node.attrs?.alt ?? "Image";
275
+ const width = node.attrs?.width;
276
+ const height = node.attrs?.height;
277
+ // Resolve image bytes
278
+ let bytes;
279
+ let mimeType = "image/png";
280
+ if (src.startsWith("data:")) {
281
+ // Data URI — decode directly
282
+ const match = src.match(/^data:([^;]+);base64,(.+)$/);
283
+ if (match) {
284
+ mimeType = match[1];
285
+ bytes = base64ToUint8Array(match[2]);
286
+ }
287
+ }
288
+ else if (options.images?.[src]) {
289
+ // Pre-fetched image
290
+ bytes = options.images[src];
291
+ mimeType = guessMimeType(src);
292
+ }
293
+ if (bytes) {
294
+ const widthCm = width ? `${Math.round((width / 96) * 2.54)}cm` : "10cm";
295
+ const heightCm = height ? `${Math.round((height / 96) * 2.54)}cm` : "auto";
296
+ doc.addImage(bytes, {
297
+ mimeType: mimeType,
298
+ width: widthCm,
299
+ height: heightCm,
300
+ });
301
+ }
302
+ else {
303
+ // Placeholder
304
+ doc.addParagraph(`[Image: ${alt}]`);
305
+ }
306
+ }
307
+ /** Decode a base64 string to Uint8Array. Pure implementation, no Buffer or atob needed. */
308
+ function base64ToUint8Array(b64) {
309
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
310
+ const lookup = new Uint8Array(256);
311
+ for (let i = 0; i < chars.length; i++)
312
+ lookup[chars.charCodeAt(i)] = i;
313
+ const clean = b64.replace(/[^A-Za-z0-9+/]/g, "");
314
+ const len = clean.length;
315
+ const bytes = new Uint8Array((len * 3) >> 2);
316
+ let pos = 0;
317
+ for (let i = 0; i < len; i += 4) {
318
+ const a = lookup[clean.charCodeAt(i)];
319
+ const b = lookup[clean.charCodeAt(i + 1)];
320
+ const c = lookup[clean.charCodeAt(i + 2)];
321
+ const d = lookup[clean.charCodeAt(i + 3)];
322
+ bytes[pos++] = (a << 2) | (b >> 4);
323
+ if (i + 2 < len)
324
+ bytes[pos++] = ((b & 0xf) << 4) | (c >> 2);
325
+ if (i + 3 < len)
326
+ bytes[pos++] = ((c & 0x3) << 6) | d;
327
+ }
328
+ return bytes.slice(0, pos);
329
+ }
330
+ /** Guess MIME type from file extension. */
331
+ function guessMimeType(src) {
332
+ const ext = src.split(".").pop()?.toLowerCase() ?? "";
333
+ const map = {
334
+ png: "image/png",
335
+ jpg: "image/jpeg",
336
+ jpeg: "image/jpeg",
337
+ gif: "image/gif",
338
+ svg: "image/svg+xml",
339
+ webp: "image/webp",
340
+ };
341
+ return map[ext] ?? "image/png";
342
+ }
343
+ // ─── Inline Content Extraction ────────────────────────────────────────
344
+ /**
345
+ * Recursively extract TextRun objects from TipTap inline content nodes.
346
+ * Handles text nodes with marks and hardBreak nodes.
347
+ */
348
+ function extractRuns(nodes, inherited) {
349
+ const runs = [];
350
+ for (const node of nodes) {
351
+ if (node.type === "text") {
352
+ const text = node.text ?? "";
353
+ if (!text)
354
+ continue;
355
+ const formatting = mergeMarks(node.marks ?? [], inherited);
356
+ const linkMark = node.marks?.find((m) => m.type === "link");
357
+ const hasFormatting = Object.keys(formatting).length > 0;
358
+ if (linkMark) {
359
+ const href = linkMark.attrs?.href ?? "";
360
+ runs.push({ text, link: href, formatting: hasFormatting ? formatting : undefined });
361
+ }
362
+ else {
363
+ runs.push({ text, formatting: hasFormatting ? formatting : undefined });
364
+ }
365
+ }
366
+ else if (node.type === "hardBreak") {
367
+ runs.push({ text: "", lineBreak: true });
368
+ }
369
+ else if (node.content) {
370
+ runs.push(...extractRuns(node.content, inherited));
371
+ }
372
+ }
373
+ return runs;
374
+ }
375
+ /**
376
+ * Convert an array of TipTap marks to TextFormatting, merged with inherited.
377
+ */
378
+ function mergeMarks(marks, inherited) {
379
+ let f = { ...inherited };
380
+ for (const mark of marks) {
381
+ switch (mark.type) {
382
+ case "bold":
383
+ f = { ...f, bold: true };
384
+ break;
385
+ case "italic":
386
+ f = { ...f, italic: true };
387
+ break;
388
+ case "underline":
389
+ f = { ...f, underline: true };
390
+ break;
391
+ case "strike":
392
+ f = { ...f, strikethrough: true };
393
+ break;
394
+ case "code":
395
+ f = { ...f, fontFamily: MONOSPACE_FONT };
396
+ break;
397
+ case "superscript":
398
+ f = { ...f, superscript: true };
399
+ break;
400
+ case "subscript":
401
+ f = { ...f, subscript: true };
402
+ break;
403
+ case "highlight": {
404
+ const color = mark.attrs?.color ?? "yellow";
405
+ f = { ...f, highlightColor: color };
406
+ break;
407
+ }
408
+ case "textStyle": {
409
+ if (mark.attrs?.color)
410
+ f = { ...f, color: mark.attrs.color };
411
+ if (mark.attrs?.fontSize)
412
+ f = { ...f, fontSize: mark.attrs.fontSize };
413
+ if (mark.attrs?.fontFamily)
414
+ f = { ...f, fontFamily: mark.attrs.fontFamily };
415
+ break;
416
+ }
417
+ // "link" handled in extractRuns — not a formatting property
418
+ }
419
+ }
420
+ return f;
421
+ }
422
+ // ─── Helpers ──────────────────────────────────────────────────────────
423
+ /**
424
+ * Apply an array of TextRun objects to a ParagraphBuilder.
425
+ */
426
+ function applyRuns(p, runs) {
427
+ for (const run of runs) {
428
+ if (run.lineBreak) {
429
+ p.addLineBreak();
430
+ }
431
+ else if (run.link) {
432
+ p.addLink(run.text ?? "", run.link, run.formatting);
433
+ }
434
+ else {
435
+ p.addText(run.text ?? "", run.formatting);
436
+ }
437
+ }
438
+ }
439
+ /**
440
+ * Extract all plain text from a node tree (used for codeBlock).
441
+ */
442
+ function extractText(node) {
443
+ if (node.type === "text")
444
+ return node.text ?? "";
445
+ return (node.content ?? []).map(extractText).join("");
446
+ }
447
+ //# sourceMappingURL=tiptap-to-odt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiptap-to-odt.js","sourceRoot":"","sources":["../../src/odt/tiptap-to-odt.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "odf-kit",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "description": "Generate, fill, read, and convert OpenDocument Format (.odt) files in JavaScript and TypeScript. Works in Node.js and browsers.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -66,7 +66,8 @@
66
66
  "url": "git+https://github.com/GitHubNewbie0/odf-kit.git"
67
67
  },
68
68
  "dependencies": {
69
- "fflate": "^0.8.2"
69
+ "fflate": "^0.8.2",
70
+ "marked": "^18.0.0"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@eslint/js": "^9.18.0",