odf-kit 0.9.9 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +49 -2
  3. package/dist/docx/body-reader.d.ts +54 -0
  4. package/dist/docx/body-reader.d.ts.map +1 -0
  5. package/dist/docx/body-reader.js +1124 -0
  6. package/dist/docx/body-reader.js.map +1 -0
  7. package/dist/docx/converter.d.ts +51 -0
  8. package/dist/docx/converter.d.ts.map +1 -0
  9. package/dist/docx/converter.js +799 -0
  10. package/dist/docx/converter.js.map +1 -0
  11. package/dist/docx/index.d.ts +81 -0
  12. package/dist/docx/index.d.ts.map +1 -0
  13. package/dist/docx/index.js +69 -0
  14. package/dist/docx/index.js.map +1 -0
  15. package/dist/docx/numbering.d.ts +42 -0
  16. package/dist/docx/numbering.d.ts.map +1 -0
  17. package/dist/docx/numbering.js +236 -0
  18. package/dist/docx/numbering.js.map +1 -0
  19. package/dist/docx/reader.d.ts +38 -0
  20. package/dist/docx/reader.d.ts.map +1 -0
  21. package/dist/docx/reader.js +512 -0
  22. package/dist/docx/reader.js.map +1 -0
  23. package/dist/docx/relationships.d.ts +27 -0
  24. package/dist/docx/relationships.d.ts.map +1 -0
  25. package/dist/docx/relationships.js +89 -0
  26. package/dist/docx/relationships.js.map +1 -0
  27. package/dist/docx/styles.d.ts +46 -0
  28. package/dist/docx/styles.d.ts.map +1 -0
  29. package/dist/docx/styles.js +383 -0
  30. package/dist/docx/styles.js.map +1 -0
  31. package/dist/docx/types.d.ts +266 -0
  32. package/dist/docx/types.d.ts.map +1 -0
  33. package/dist/docx/types.js +38 -0
  34. package/dist/docx/types.js.map +1 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -0
  38. package/dist/index.js.map +1 -1
  39. package/package.json +5 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ 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.9] - 2026-04-11
9
+
10
+ ### Added
11
+
12
+ - **`xlsxToOds()`** — Convert an `.xlsx` file to an `.ods` file. Available via `odf-kit/xlsx`. Zero new dependencies — parses XLSX XML directly using fflate (already present) and odf-kit's existing XML parser.
13
+ - **XLSX parser** — Reads `xl/workbook.xml`, `xl/_rels/workbook.xml.rels`, `xl/sharedStrings.xml`, `xl/styles.xml`, and `xl/worksheets/sheet*.xml`. No dependency on SheetJS or any external library.
14
+ - **Cell types supported:** string, number, boolean, date (with Excel serial → `Date` conversion including Lotus 1900 leap year bug correction), formula (cached result + formula string), error (as string).
15
+ - **Date detection** — Built-in XLSX date format IDs (14–17, 22, 27–36, 45–47, 50–58) plus custom format code analysis.
16
+ - **Merged cells** — `colSpan`/`rowSpan` preserved via `<mergeCells>` parsing.
17
+ - **Freeze rows/columns** — Detected from `<pane state="frozen">` in sheet XML.
18
+ - **Multi-sheet workbooks** — All sheets converted in tab order.
19
+ - **`readXlsx()`** — Lower-level function returning an `XlsxWorkbook` intermediate model. Exported from `odf-kit/xlsx` for callers who need the parsed model directly.
20
+ - **`odf-kit/xlsx`** sub-export added.
21
+ - Supports `.xlsx` and `.xlsm` (macro-enabled, same XML structure). Does not support legacy `.xls` (binary) or `.xlsb` (binary XML).
22
+ - 47 new tests (936 total).
23
+
8
24
  ## [0.9.8] - 2026-04-10
9
25
 
10
26
  ### Added
@@ -186,6 +202,7 @@ Initial release. Complete ODT generation support.
186
202
  - Tables, page layout, headers/footers, page breaks, lists, tab stops.
187
203
  - Method chaining. Full TypeScript types. ESM-only, Node.js 22+. 102 tests.
188
204
 
205
+ [0.9.9]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.9
189
206
  [0.9.8]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.8
190
207
  [0.9.7]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.7
191
208
  [0.9.6]: https://github.com/GitHubNewbie0/odf-kit/releases/tag/v0.9.6
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
- ## Nine ways to work with ODF files
11
+ ## Ten ways to work with ODF files
12
12
 
13
13
  ```typescript
14
14
  // 1. Build an ODT document from scratch
@@ -128,7 +128,15 @@ const html = odsToHtml(bytes); // HTML table string
128
128
  ```
129
129
 
130
130
  ```typescript
131
- // 9. Convert .odt to Typst for PDF generation
131
+ // 9. Convert .xlsx to .ods no external dependencies
132
+ import { xlsxToOds } from "odf-kit/xlsx"
133
+
134
+ const bytes = await xlsxToOds(readFileSync("report.xlsx"))
135
+ writeFileSync("report.ods", bytes)
136
+ ```
137
+
138
+ ```typescript
139
+ // 10. Convert .odt to Typst for PDF generation
132
140
  import { odtToTypst } from "odf-kit/typst";
133
141
  import { execSync } from "child_process";
134
142
 
@@ -680,6 +688,43 @@ Primary cells have `colSpan` and/or `rowSpan`. Covered cells have `type: "covere
680
688
 
681
689
  ---
682
690
 
691
+ ## Convert: XLSX → ODS
692
+
693
+ `odf-kit/xlsx` converts `.xlsx` spreadsheets to `.ods` with no external dependencies — parses XLSX XML directly using fflate (already in odf-kit) and our own XML parser. Supports `.xlsx` and `.xlsm`. Does not support legacy `.xls` (binary format).
694
+
695
+ ```typescript
696
+ import { xlsxToOds } from "odf-kit/xlsx"
697
+ import { readFileSync, writeFileSync } from "fs"
698
+
699
+ // Simple conversion
700
+ const bytes = await xlsxToOds(readFileSync("report.xlsx"))
701
+ writeFileSync("report.ods", bytes)
702
+
703
+ // With options
704
+ const bytes2 = await xlsxToOds(readFileSync("report.xlsx"), {
705
+ dateFormat: "DD/MM/YYYY",
706
+ metadata: { title: "Q4 Report", creator: "Alice" },
707
+ })
708
+
709
+ // Works with ArrayBuffer too (browser-friendly)
710
+ const bytes3 = await xlsxToOds(arrayBuffer)
711
+ ```
712
+
713
+ **What is preserved:**
714
+ - All sheets in tab order, with their names
715
+ - Cell values: strings, numbers, booleans, dates, formula cached results
716
+ - Formula strings
717
+ - Merged cells (colSpan/rowSpan)
718
+ - Freeze rows/columns
719
+ - Multiple sheets
720
+
721
+ **What is not preserved** (out of scope for v0.9.9):
722
+ - Cell formatting (colors, fonts, borders)
723
+ - Column widths and row heights
724
+ - Charts, images, pivot tables
725
+
726
+ ---
727
+
683
728
  ## Typst: ODT to PDF
684
729
 
685
730
  ```typescript
@@ -852,6 +897,8 @@ odf-kit targets ODF 1.2 (ISO/IEC 26300). Generated files include proper ZIP pack
852
897
 
853
898
  ## Version history
854
899
 
900
+ **v0.9.9** — `xlsxToOds()` via `odf-kit/xlsx`. XLSX→ODS conversion with zero new dependencies. 936 tests passing.
901
+
855
902
  **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
903
 
857
904
  **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.
@@ -0,0 +1,54 @@
1
+ /**
2
+ * odf-kit — DOCX body reader
3
+ *
4
+ * Walks the w:body element from word/document.xml and converts it into the
5
+ * DocxBodyElement[] model. Also used to parse footnote/endnote/header/footer
6
+ * XML bodies, which share the same paragraph/table structure.
7
+ *
8
+ * Design decisions:
9
+ * - Only explicitly present XML properties are stored — no style inheritance
10
+ * resolution. The converter walks the basedOn chain at conversion time.
11
+ * - Mid-paragraph page breaks split the paragraph:
12
+ * [DocxParagraph (before), DocxPageBreak, DocxParagraph (after)]
13
+ * - Field state machine runs on every paragraph — handles both w:hyperlink
14
+ * elements and complex HYPERLINK fields (w:fldChar / w:instrText).
15
+ * - w:pict (legacy VML) images are fully handled via v:imagedata + v:shape.
16
+ * - w:sdt content is always processed; checkboxes get special rendering.
17
+ * - Tracked changes: w:ins / w:moveTo children are processed;
18
+ * w:del / w:moveFrom children are skipped.
19
+ * - Two-pass bookmark resolution: pass 1 collects all bookmark id→name
20
+ * mappings across the entire body; pass 2 emits bookmark elements using
21
+ * the pre-built map. This correctly handles cross-paragraph bookmarks.
22
+ * - Spec reference: ECMA-376 5th edition Part 1, §17 (WordprocessingML).
23
+ * CT_Body child elements validated against §17.2.2.
24
+ */
25
+ import type { DocxBodyElement, DocxNote, RelationshipMap, StyleMap, NumberingMap } from "./types.js";
26
+ export interface BodyReaderContext {
27
+ styles: StyleMap;
28
+ numbering: NumberingMap;
29
+ relationships: RelationshipMap;
30
+ /** id → name map built by collectBookmarkNames() before the main walk. */
31
+ bookmarkNames: Map<string, string>;
32
+ warnings: string[];
33
+ }
34
+ /**
35
+ * Parse a body XML string into a DocxBodyElement array.
36
+ *
37
+ * Used for: word/document.xml (rootTag="body"), word/header*.xml (rootTag="hdr"),
38
+ * word/footer*.xml (rootTag="ftr"). Footnote/endnote XML uses readNotes().
39
+ *
40
+ * @param xml - Raw XML string.
41
+ * @param rootTag - Local name of the container element, e.g. "body", "hdr", "ftr".
42
+ * @param ctx - Shared reader context.
43
+ */
44
+ export declare function readBody(xml: string, rootTag: string, ctx: BodyReaderContext): DocxBodyElement[];
45
+ /**
46
+ * Parse footnote/endnote XML into a Map<id, DocxNote>.
47
+ * Handles both word/footnotes.xml and word/endnotes.xml.
48
+ *
49
+ * @param xml - Raw XML string.
50
+ * @param noteTag - "footnote" | "endnote".
51
+ * @param ctx - Shared reader context.
52
+ */
53
+ export declare function readNotes(xml: string, noteTag: "footnote" | "endnote", ctx: BodyReaderContext): Map<string, DocxNote>;
54
+ //# sourceMappingURL=body-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-reader.d.ts","sourceRoot":"","sources":["../../src/docx/body-reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,OAAO,KAAK,EACV,eAAe,EAcf,QAAQ,EAGR,eAAe,EACf,QAAQ,EACR,YAAY,EACb,MAAM,YAAY,CAAC;AAOpB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,EAAE,YAAY,CAAC;IACxB,aAAa,EAAE,eAAe,CAAC;IAC/B,0EAA0E;IAC1E,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,eAAe,EAAE,CAShG;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,UAAU,GAAG,SAAS,EAC/B,GAAG,EAAE,iBAAiB,GACrB,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CA0BvB"}