odf-kit 0.9.7 → 0.9.9

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,6 +5,23 @@ 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.9.8] - 2026-04-10
9
+
10
+ ### Added
11
+
12
+ - **`readOds()`** — Parse an ODS file into a structured `OdsDocumentModel`. Returns typed JavaScript values — `string`, `number`, `boolean`, `Date` — never display-formatted strings. Available via `odf-kit/ods-reader`.
13
+ - **`odsToHtml()`** — Convert an ODS file directly to an HTML string. Each sheet rendered as a `<table>` with inline styles. Available via `odf-kit/ods-reader`.
14
+ - **`OdsDocumentModel`** — sheets → rows → cells with `value`, `type`, `formula?`, `displayText?`, `colSpan?`, `rowSpan?`, `formatting?`.
15
+ - **Cell types:** `"string"`, `"float"`, `"date"`, `"boolean"`, `"formula"`, `"empty"`, `"covered"`.
16
+ - **Formula cells** — `value` is the cached result, `formula` is the original formula string (e.g. `"=SUM(A1:A10)"`).
17
+ - **Merged cell handling** — primary cell has `colSpan`/`rowSpan`, covered cells have `type: "covered"` and `value: null` at correct physical column indices.
18
+ - **Cell formatting** — `OdsCellFormatting` with bold, italic, underline, fontSize, fontFamily, color, backgroundColor, textAlign, verticalAlign, numberFormat, dateFormat. Set `includeFormatting: false` for faster parsing when only values are needed.
19
+ - **Sheet metadata** — tab color, freeze rows/columns read from settings.xml.
20
+ - **Document metadata** — title, creator, description from meta.xml.
21
+ - **`odf-kit/ods-reader`** sub-export added.
22
+ - **`odf-kit/odt-reader`** alias added for `odf-kit/reader` — consistent naming with `odf-kit/ods-reader`.
23
+ - 40 new tests (889 total).
24
+
8
25
  ## [0.9.7] - 2026-04-10
9
26
 
10
27
  ### Added
@@ -169,6 +186,7 @@ Initial release. Complete ODT generation support.
169
186
  - Tables, page layout, headers/footers, page breaks, lists, tab stops.
170
187
  - Method chaining. Full TypeScript types. ESM-only, Node.js 22+. 102 tests.
171
188
 
189
+ [0.9.8]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.8
172
190
  [0.9.7]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.7
173
191
  [0.9.6]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.6
174
192
  [0.9.5]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.5
package/README.md CHANGED
@@ -8,7 +8,7 @@ Generate, fill, read, and convert OpenDocument Format files (.odt, .ods) in Type
8
8
  npm install odf-kit
9
9
  ```
10
10
 
11
- ## Eight ways to work with ODF files
11
+ ## Nine ways to work with ODF files
12
12
 
13
13
  ```typescript
14
14
  // 1. Build an ODT document from scratch
@@ -119,7 +119,16 @@ const html = odtToHtml(bytes); // styled HTML string
119
119
  ```
120
120
 
121
121
  ```typescript
122
- // 8. Convert .odt to Typst for PDF generation
122
+ // 8. Read an existing .ods spreadsheet
123
+ import { readOds, odsToHtml } from "odf-kit/ods-reader";
124
+
125
+ const bytes = readFileSync("data.ods");
126
+ const model = readOds(bytes); // structured model — typed values
127
+ const html = odsToHtml(bytes); // HTML table string
128
+ ```
129
+
130
+ ```typescript
131
+ // 9. Convert .odt to Typst for PDF generation
123
132
  import { odtToTypst } from "odf-kit/typst";
124
133
  import { execSync } from "child_process";
125
134
 
@@ -140,7 +149,8 @@ Node.js 22+ required. ESM only. Sub-exports:
140
149
 
141
150
  ```typescript
142
151
  import { OdtDocument, OdsDocument, htmlToOdt, markdownToOdt, tiptapToOdt, fillTemplate } from "odf-kit";
143
- import { readOdt, odtToHtml } from "odf-kit/reader";
152
+ import { readOdt, odtToHtml } from "odf-kit/odt-reader";
153
+ import { readOds, odsToHtml } from "odf-kit/ods-reader";
144
154
  import { odtToTypst, modelToTypst } from "odf-kit/typst";
145
155
  ```
146
156
 
@@ -597,7 +607,7 @@ Falsy values (`false`, `null`, `undefined`, `0`, `""`, `[]`) remove the block. T
597
607
  `odf-kit/reader` parses `.odt` files into a structured model and renders to HTML.
598
608
 
599
609
  ```typescript
600
- import { readOdt, odtToHtml } from "odf-kit/reader";
610
+ import { readOdt, odtToHtml } from "odf-kit/odt-reader";
601
611
 
602
612
  const bytes = readFileSync("report.odt");
603
613
  const model = readOdt(bytes);
@@ -611,6 +621,65 @@ const marked = odtToHtml(bytes, {}, { trackedChanges: "changes" });
611
621
 
612
622
  ---
613
623
 
624
+ ## Read: ODS Spreadsheets
625
+
626
+ `odf-kit/ods-reader` parses `.ods` files into a structured model and renders to HTML.
627
+
628
+ ```typescript
629
+ import { readOds, odsToHtml } from "odf-kit/ods-reader";
630
+ import { readFileSync } from "fs";
631
+
632
+ const bytes = readFileSync("data.ods");
633
+
634
+ // Structured model — typed JavaScript values
635
+ const model = readOds(bytes);
636
+ for (const sheet of model.sheets) {
637
+ console.log(sheet.name);
638
+ for (const row of sheet.rows) {
639
+ for (const cell of row.cells) {
640
+ console.log(cell.colIndex, cell.type, cell.value);
641
+ // e.g. 0 "float" 1234.56
642
+ // e.g. 1 "string" "Hello"
643
+ // e.g. 2 "date" Date { 2026-01-15 }
644
+ // e.g. 3 "formula" 100 (cell.formula = "=SUM(A1:A10)")
645
+ // e.g. 4 "covered" null (part of a merged cell)
646
+ }
647
+ }
648
+ }
649
+
650
+ // HTML table
651
+ const html = odsToHtml(bytes);
652
+
653
+ // Fast mode — values only, no formatting
654
+ const model2 = readOds(bytes, { includeFormatting: false });
655
+ ```
656
+
657
+ ### Cell types
658
+
659
+ | Type | `value` | Notes |
660
+ |------|---------|-------|
661
+ | `"string"` | `string` | |
662
+ | `"float"` | `number` | Includes percentage and currency cells |
663
+ | `"date"` | `Date` (UTC) | |
664
+ | `"boolean"` | `boolean` | |
665
+ | `"formula"` | cached result | `cell.formula` has original string e.g. `"=SUM(A1:A10)"` |
666
+ | `"empty"` | `null` | |
667
+ | `"covered"` | `null` | Covered by a merge — correct `colIndex` always maintained |
668
+
669
+ ### Merged cells
670
+
671
+ Primary cells have `colSpan` and/or `rowSpan`. Covered cells have `type: "covered"`, `value: null`, and the correct physical `colIndex` — no offset confusion.
672
+
673
+ ```typescript
674
+ // A1:C1 merged — reading row 0:
675
+ // cell 0: { type: "string", value: "Header", colSpan: 3 }
676
+ // cell 1: { type: "covered", value: null, colIndex: 1 }
677
+ // cell 2: { type: "covered", value: null, colIndex: 2 }
678
+ // cell 3: { type: "string", value: "D1", colIndex: 3 } ← always correct
679
+ ```
680
+
681
+ ---
682
+
614
683
  ## Typst: ODT to PDF
615
684
 
616
685
  ```typescript
@@ -783,6 +852,8 @@ odf-kit targets ODF 1.2 (ISO/IEC 26300). Generated files include proper ZIP pack
783
852
 
784
853
  ## Version history
785
854
 
855
+ **v0.9.8** — ODS reader: `readOds()` and `odsToHtml()` via `odf-kit/ods-reader`. Typed values, formula strings, merged cell handling, formatting, metadata. `odf-kit/odt-reader` alias added. 889 tests passing.
856
+
786
857
  **v0.9.7** — ODS enhancements: number formats (integer, decimal:N, percentage, currency), merged cells (colSpan/rowSpan), freeze rows/columns, hyperlinks in cells, sheet tab color. 849 tests passing.
787
858
 
788
859
  **v0.9.6** — `tiptapToOdt()`: TipTap/ProseMirror JSON→ODT conversion. `TiptapNode`, `TiptapMark`, `TiptapToOdtOptions` types. `unknownNodeHandler` for custom extensions. Image support via pre-fetched bytes map. 817 tests passing.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ODS HTML renderer — converts an OdsDocumentModel to an HTML string.
3
+ *
4
+ * Each sheet is rendered as an HTML <table>. Merged cells use colspan/rowspan.
5
+ * Covered cells are omitted. Cell formatting is applied as inline styles.
6
+ */
7
+ import type { OdsDocumentModel, OdsHtmlOptions } from "./types.js";
8
+ /**
9
+ * Render an OdsDocumentModel as an HTML string.
10
+ *
11
+ * Each sheet is rendered as a `<table>`. Merged cells use `colspan`/`rowspan`.
12
+ * Covered cells are omitted. Cell formatting applied as inline styles.
13
+ *
14
+ * @param model - Parsed document model from readOds().
15
+ * @param options - Optional rendering options.
16
+ * @returns HTML string.
17
+ */
18
+ export declare function renderOdsHtml(model: OdsDocumentModel, options?: OdsHtmlOptions): string;
19
+ //# sourceMappingURL=html-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-renderer.d.ts","sourceRoot":"","sources":["../../src/ods-reader/html-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAKhB,cAAc,EACf,MAAM,YAAY,CAAC;AA2GpB;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CASvF"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * ODS HTML renderer — converts an OdsDocumentModel to an HTML string.
3
+ *
4
+ * Each sheet is rendered as an HTML <table>. Merged cells use colspan/rowspan.
5
+ * Covered cells are omitted. Cell formatting is applied as inline styles.
6
+ */
7
+ // ─── Style Building ───────────────────────────────────────────────────
8
+ function buildInlineStyle(fmt) {
9
+ const parts = [];
10
+ if (fmt.bold)
11
+ parts.push("font-weight:bold");
12
+ if (fmt.italic)
13
+ parts.push("font-style:italic");
14
+ if (fmt.underline)
15
+ parts.push("text-decoration:underline");
16
+ if (fmt.fontSize)
17
+ parts.push(`font-size:${fmt.fontSize}`);
18
+ if (fmt.fontFamily)
19
+ parts.push(`font-family:${fmt.fontFamily}`);
20
+ if (fmt.color)
21
+ parts.push(`color:${fmt.color}`);
22
+ if (fmt.backgroundColor)
23
+ parts.push(`background-color:${fmt.backgroundColor}`);
24
+ if (fmt.textAlign)
25
+ parts.push(`text-align:${fmt.textAlign}`);
26
+ if (fmt.verticalAlign)
27
+ parts.push(`vertical-align:${fmt.verticalAlign}`);
28
+ return parts.join(";");
29
+ }
30
+ // ─── HTML Escaping ────────────────────────────────────────────────────
31
+ function escapeHtml(text) {
32
+ return text
33
+ .replace(/&/g, "&amp;")
34
+ .replace(/</g, "&lt;")
35
+ .replace(/>/g, "&gt;")
36
+ .replace(/"/g, "&quot;");
37
+ }
38
+ // ─── Cell Rendering ───────────────────────────────────────────────────
39
+ function renderCellValue(cell) {
40
+ // Prefer display text when available
41
+ if (cell.displayText !== undefined && cell.displayText !== "") {
42
+ return escapeHtml(cell.displayText);
43
+ }
44
+ if (cell.value === null || cell.value === undefined)
45
+ return "";
46
+ if (cell.value instanceof Date) {
47
+ return escapeHtml(cell.value.toISOString().slice(0, 10));
48
+ }
49
+ return escapeHtml(String(cell.value));
50
+ }
51
+ function renderCell(cell, includeStyles, prefix) {
52
+ const attrs = [`class="${prefix}-cell"`];
53
+ if (cell.colSpan && cell.colSpan > 1)
54
+ attrs.push(`colspan="${cell.colSpan}"`);
55
+ if (cell.rowSpan && cell.rowSpan > 1)
56
+ attrs.push(`rowspan="${cell.rowSpan}"`);
57
+ if (includeStyles && cell.formatting) {
58
+ const style = buildInlineStyle(cell.formatting);
59
+ if (style)
60
+ attrs.push(`style="${style}"`);
61
+ }
62
+ // Right-align numbers by default if no explicit alignment
63
+ if (includeStyles &&
64
+ !cell.formatting?.textAlign &&
65
+ (cell.type === "float" || cell.type === "formula")) {
66
+ const existingStyle = attrs.find((a) => a.startsWith("style="));
67
+ if (existingStyle) {
68
+ const idx = attrs.indexOf(existingStyle);
69
+ attrs[idx] = existingStyle.replace('"', '"text-align:right;');
70
+ }
71
+ else {
72
+ attrs.push(`style="text-align:right"`);
73
+ }
74
+ }
75
+ const content = renderCellValue(cell);
76
+ return `<td ${attrs.join(" ")}>${content}</td>`;
77
+ }
78
+ // ─── Row Rendering ────────────────────────────────────────────────────
79
+ function renderRow(row, includeStyles, prefix) {
80
+ const cells = row.cells
81
+ .filter((c) => c.type !== "covered")
82
+ .map((c) => renderCell(c, includeStyles, prefix))
83
+ .join("");
84
+ const style = includeStyles && row.height ? ` style="height:${row.height}"` : "";
85
+ return `<tr class="${prefix}-row"${style}>${cells}</tr>`;
86
+ }
87
+ // ─── Sheet Rendering ──────────────────────────────────────────────────
88
+ function renderSheet(sheet, includeStyles, prefix) {
89
+ if (sheet.rows.length === 0) {
90
+ return `<h2 class="${prefix}-sheet-name">${escapeHtml(sheet.name)}</h2>\n<table class="${prefix}-sheet"></table>`;
91
+ }
92
+ const rows = sheet.rows
93
+ .map((r) => renderRow(r, includeStyles, prefix))
94
+ .join("\n ");
95
+ return [
96
+ `<h2 class="${prefix}-sheet-name">${escapeHtml(sheet.name)}</h2>`,
97
+ `<table class="${prefix}-sheet">`,
98
+ ` <tbody>`,
99
+ ` ${rows}`,
100
+ ` </tbody>`,
101
+ `</table>`,
102
+ ].join("\n");
103
+ }
104
+ // ─── Public API ───────────────────────────────────────────────────────
105
+ /**
106
+ * Render an OdsDocumentModel as an HTML string.
107
+ *
108
+ * Each sheet is rendered as a `<table>`. Merged cells use `colspan`/`rowspan`.
109
+ * Covered cells are omitted. Cell formatting applied as inline styles.
110
+ *
111
+ * @param model - Parsed document model from readOds().
112
+ * @param options - Optional rendering options.
113
+ * @returns HTML string.
114
+ */
115
+ export function renderOdsHtml(model, options) {
116
+ const includeStyles = options?.includeStyles ?? true;
117
+ const prefix = options?.classPrefix ?? "ods";
118
+ const sheets = model.sheets
119
+ .map((s) => renderSheet(s, includeStyles, prefix))
120
+ .join("\n\n");
121
+ return `<div class="${prefix}-document">\n${sheets}\n</div>`;
122
+ }
123
+ //# sourceMappingURL=html-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-renderer.js","sourceRoot":"","sources":["../../src/ods-reader/html-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ReadOdsOptions, OdsHtmlOptions } from "./types.js";
2
+ export { readOds } from "./parser.js";
3
+ export type { OdsDocumentModel, OdsMetadata, OdsSheetModel, OdsRowModel, OdsCellModel, OdsCellFormatting, ReadOdsOptions, OdsHtmlOptions, } from "./types.js";
4
+ /**
5
+ * Convert an ODS file directly to an HTML string.
6
+ *
7
+ * Convenience wrapper around readOds() + renderOdsHtml().
8
+ *
9
+ * @param bytes - Raw .ods file bytes.
10
+ * @param htmlOptions - Optional HTML rendering options.
11
+ * @param readOptions - Optional parsing options.
12
+ * @returns HTML string with one <table> per sheet.
13
+ *
14
+ * @example
15
+ * import { odsToHtml } from "odf-kit/ods-reader"
16
+ * const html = odsToHtml(readFileSync("data.ods"))
17
+ */
18
+ export declare function odsToHtml(bytes: Uint8Array, htmlOptions?: OdsHtmlOptions, readOptions?: ReadOdsOptions): string;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ods-reader/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EACjB,WAAW,CAAC,EAAE,cAAc,EAC5B,WAAW,CAAC,EAAE,cAAc,GAC3B,MAAM,CAGR"}
@@ -0,0 +1,22 @@
1
+ import { readOds } from "./parser.js";
2
+ import { renderOdsHtml } from "./html-renderer.js";
3
+ export { readOds } from "./parser.js";
4
+ /**
5
+ * Convert an ODS file directly to an HTML string.
6
+ *
7
+ * Convenience wrapper around readOds() + renderOdsHtml().
8
+ *
9
+ * @param bytes - Raw .ods file bytes.
10
+ * @param htmlOptions - Optional HTML rendering options.
11
+ * @param readOptions - Optional parsing options.
12
+ * @returns HTML string with one <table> per sheet.
13
+ *
14
+ * @example
15
+ * import { odsToHtml } from "odf-kit/ods-reader"
16
+ * const html = odsToHtml(readFileSync("data.ods"))
17
+ */
18
+ export function odsToHtml(bytes, htmlOptions, readOptions) {
19
+ const model = readOds(bytes, readOptions);
20
+ return renderOdsHtml(model, htmlOptions);
21
+ }
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ods-reader/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAYtC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CACvB,KAAiB,EACjB,WAA4B,EAC5B,WAA4B;IAE5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * ODS parser — reads an .ods file and builds an OdsDocumentModel.
3
+ *
4
+ * Pipeline:
5
+ * 1. Unzip the .ods bytes with fflate
6
+ * 2. Parse content.xml — walk office:spreadsheet → table:table → table:table-row → table:table-cell
7
+ * 3. Resolve cell types and values from office:value-type attributes
8
+ * 4. Handle table:number-columns-repeated / table:number-rows-repeated (LibreOffice compression)
9
+ * 5. Handle merged cells — colSpan/rowSpan on primary, covered cells at correct indices
10
+ * 6. Resolve cell styles from automatic-styles → OdsCellFormatting
11
+ * 7. Parse settings.xml for freeze row/column configuration
12
+ * 8. Parse meta.xml for document metadata
13
+ * 9. Return OdsDocumentModel
14
+ */
15
+ import type { OdsDocumentModel, ReadOdsOptions } from "./types.js";
16
+ /**
17
+ * Parse an ODS file into a structured document model.
18
+ *
19
+ * @param bytes - Raw .ods file bytes (Uint8Array).
20
+ * @param options - Optional parsing options.
21
+ * @returns Structured OdsDocumentModel.
22
+ */
23
+ export declare function readOds(bytes: Uint8Array, options?: ReadOdsOptions): OdsDocumentModel;
24
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/ods-reader/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EACV,gBAAgB,EAMhB,cAAc,EACf,MAAM,YAAY,CAAC;AAsfpB;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAwErF"}