Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ jobs:
path: ./artifacts
merge-multiple: true
- name: Stage attribution files for release
# Per LGPL §4 we ship LGPL-3.0.txt + NOTICES alongside every binary;
# NOTICES is the canonical attribution surface for PDFium (BSD-3),
# jpeg-js (BSD-3), highlight.js (BSD-3), and libheif (LGPL).
run: cp LICENSE LGPL-3.0.txt NOTICES ./artifacts/
# LICENSE + NOTICES ship alongside every binary; NOTICES is the
# canonical attribution surface the BSD-3 components require: PDFium,
# jpeg-js, and highlight.js.
run: cp LICENSE NOTICES ./artifacts/
- name: Stage install.sh for release
# Shipped as a release asset (not served from a branch) so the documented install
# command pins to a tag and is covered by SHA256SUMS below. It lives in the skill
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ src/
jsx/ # Fragment, namespace() + tag namespaces (w, a, wp, pic, cp, dc, …), auto-runtime
ast/ # types + DocView + XML→AST reader; text.ts (paragraph helpers), sym.ts (<w:sym> decode)
locators/ # parse "p3:5-20" → Locator + resolve to refs
image/ # drawing.tsx (<Image> + addImagePart + collectImageRuns), source.ts (load path/data:/http + HEIC→JPEG), formats.ts (one mime↔ext table)
image/ # drawing.tsx (<Image> + addImagePart + collectImageRuns), source.ts (load path/data:/http; refuses HEIC with a conversion hint), formats.ts (one mime↔ext table)
equation/ # latexToOmml / ommlToLatex bidirectional (temml + own MathML↔OMML adapter)
markdown/ # MarkdownImport lens: remark-parse + remark-gfm + remark-math + CriticMarkup plugin → walker → emitters
raw/ # Raw lens: fragment gate pipeline (element-order, namespaces+dcx:raw marker, reference audit) + libxml2-wasm XSD engine over bundled ECMA-376 schemas (schemas/)
Expand Down Expand Up @@ -90,7 +90,6 @@ See [CLAUDE.md](CLAUDE.md) and the nested `CLAUDE.md` files under `src/` for con
- **Diff**: [`diff`](https://www.npmjs.com/package/diff) (jsdiff, BSD-3) backs `docx diff` — unified line hunks + HTML-aware word-level refinement of the read view
- **Math**: [`temml`](https://www.npmjs.com/package/temml) (MIT) compiles LaTeX → MathML; an in-house MathML → OMML adapter handles the OOXML side bidirectionally
- **Render**: [`@hyzyla/pdfium`](https://www.npmjs.com/package/@hyzyla/pdfium) (MIT wrapper; PDFium WASM redistributed under BSD-3-Clause) for the PDF → PNG/JPG step, plus [`pngjs`](https://www.npmjs.com/package/pngjs) / [`jpeg-js`](https://www.npmjs.com/package/jpeg-js) for image encoding
- **Images**: [`heic-convert`](https://www.npmjs.com/package/heic-convert) (wasm libheif, LGPL-3.0) transcodes HEIC/HEIF input to JPEG on insert
- **Validation**: [`libxml2-wasm`](https://www.npmjs.com/package/libxml2-wasm) (MIT, libxml2 compiled to WASM) + the bundled ECMA-376 5th-edition transitional XSDs power `docx validate` and the `docx raw` schema gate — in-process, ~55 ms one-time schema compile, single-digit ms per document
- **Quality**: Biome + Knip + tsc; LibreOffice headless for round-trip integration tests
- **Standard**: ECMA-376 Part 1 §17 (WordprocessingML), Transitional profile
Expand Down
165 changes: 0 additions & 165 deletions LGPL-3.0.txt

This file was deleted.

38 changes: 4 additions & 34 deletions NOTICES
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ This file lists the third-party software docx-cli redistributes (statically
linked into the published binaries via `bun build --compile`, or bundled
into `dist/index.js`), along with the attribution each license requires.

docx-cli itself is licensed under the MIT License (see LICENSE). Linking
permissively-licensed libraries (MIT / Apache-2.0 / BSD-3-Clause) leaves
that license unchanged. Linking the LGPL-3.0 libheif-js library does NOT
make docx-cli copyleft either — LGPL §4 permits use by works under other
licenses provided the conditions in this NOTICES file (acknowledgement +
LGPL-3.0 text + the right to swap in a modified libheif by rebuilding
docx-cli from source) are met.
docx-cli itself is licensed under the MIT License (see LICENSE). Every
library it redistributes is permissively licensed (MIT / Apache-2.0 /
BSD-3-Clause, or a dual license under which docx-cli elects one of those),
which leaves that license unchanged.

Whenever a runtime dependency is added or changed in package.json,
re-audit whether the new entry needs an attribution here.
Expand Down Expand Up @@ -59,32 +56,6 @@ not included verbatim inside the @hyzyla/pdfium npm tarball; the wrapper's
own LICENSE.md covers only the MIT-licensed wrapper code.)


================================================================================
libheif-js (HEIC/HEIF input transcoding for `docx insert --image`)
================================================================================

License: LGPL-3.0-only (see LGPL-3.0.txt at the root of this distribution).
Copyright: libheif authors, https://github.com/strukturag/libheif.

docx-cli links libheif-js statically into its compiled binaries (`dist/docx`
and the GitHub Release artifacts). LGPL §4 imposes the following obligations
that this notice satisfies:

(a) Acknowledged here: libheif-js is incorporated into docx-cli's binaries.
(b) The full LGPL-3.0 text is distributed as LGPL-3.0.txt alongside this
file.
(c) docx-cli's own source code is publicly available at
https://github.com/kklimuk/docx-cli — anyone may rebuild the
binaries with a modified libheif by replacing the `libheif-js` /
`heic-convert` dependency in package.json and running
`bun run build:binary`. libheif's source is at
https://github.com/strukturag/libheif.

Linking LGPL-3.0 code does NOT make docx-cli a derivative work for the
purpose of LGPL §3 — docx-cli remains under the MIT License declared in
LICENSE.


================================================================================
BSD-3-Clause components
================================================================================
Expand Down Expand Up @@ -174,7 +145,6 @@ Other dependencies (license elections + MIT components)
remark-math MIT
unist-util-visit MIT
mdast-util-math MIT
heic-convert MIT (wrapper around LGPL libheif-js, attributed above)

Each package's own LICENSE file is distributed alongside its source inside
`node_modules/<pkg>/` for anyone consuming docx-cli via Bun's dependency
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,4 @@ Tested on every commit: about 1,900 unit tests, a LibreOffice round-trip of ever

## License

MIT. The standalone binaries statically link libheif (LGPL-3.0) for HEIC image support; see [NOTICES](NOTICES) for the attributions and your rights under the LGPL.
MIT. Every library docx-cli depends on is permissively licensed; [NOTICES](NOTICES) carries the attributions for the ones bundled into the npm package and the binaries.
2 changes: 1 addition & 1 deletion REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ docx track-changes apply doc.docx --accept rev0 --reject rev1 # finalize: acce

**Text boxes and markup compatibility.** Word writes every modern shape and text box as an `<mc:AlternateContent>` pair (a `wps` shape under `<mc:Choice>`, a legacy VML copy under `<mc:Fallback>`), and the markup-compatibility spec lets that wrapper sit at any level — around a block, a paragraph's runs, or a run's children — and nest. The reader resolves the wrapper wherever it appears (first `Choice`, else `Fallback`), so nothing under it is dropped, and every offset walker descends the same branch (a wrapper with several `Choice`s counts exactly the one the reader read); a `<w:txbxContent>` story surfaces as a `textBox` run whose blocks are addressable `tbxN:pK` paragraphs. Edits land in the `Choice` copy (the one Word reads) and a text box's `Fallback` twin is mirrored from it on save, exactly as Word does when it edits the box. A wrapper that is not a text box has no mirrorable story, so an edit inside it changes the `Choice` only — the same two-faced file Word leaves when it preserves a fallback it didn't regenerate.

**Rich content.** Images insert from a path, `data:` URI, or `http(s)` URL (bounded fetch; HEIC→JPEG transcode; SVG sanitized; non-public/metadata addresses refused at every redirect hop). Equations round-trip OOXML `<m:oMath>` ↔ LaTeX (reconstructed, not legacy plaintext) — authored via temml (LaTeX→MathML) plus an in-house MathML→OMML adapter (the math path pulls in no LGPL code). Code blocks emit one `CodeBlock`-styled paragraph per line with optional lowlight syntax highlighting (37 bundled languages); they collapse back to a GFM fenced block on read. GFM task lists round-trip Word's checkbox content control (and the Word-for-Web Wingdings-glyph variant), surfacing as `taskState` in the AST. Tables operate on a merge-aware logical grid so `gridSpan`/`vMerge` cells map onto physical `<w:tc>`, and structural edits refuse to bisect an existing merge.
**Rich content.** Images insert from a path, `data:` URI, or `http(s)` URL (bounded fetch; SVG sanitized; non-public/metadata addresses refused at every redirect hop). HEIC/HEIF input is refused, by extension, MIME type, or file header, with an `IMAGE_SOURCE` error whose hint gives the conversion command (`sips` on macOS, `heif-convert` or ImageMagick on Linux): Word can't display HEIC, and docx-cli bundles no HEVC decoder. Equations round-trip OOXML `<m:oMath>` ↔ LaTeX (reconstructed, not legacy plaintext) — authored via temml (LaTeX→MathML) plus an in-house MathML→OMML adapter. Code blocks emit one `CodeBlock`-styled paragraph per line with optional lowlight syntax highlighting (37 bundled languages); they collapse back to a GFM fenced block on read. GFM task lists round-trip Word's checkbox content control (and the Word-for-Web Wingdings-glyph variant), surfacing as `taskState` in the AST. Tables operate on a merge-aware logical grid so `gridSpan`/`vMerge` cells map onto physical `<w:tc>`, and structural edits refuse to bisect an existing merge.

**Markdown dialect.** `create --from`, `insert/edit --markdown`, and the note bodies all parse the same GFM + math + CriticMarkup + inline-HTML-formatting dialect (remark + remark-gfm + remark-math + an in-house inline-surgery transform), composing the existing OOXML emitters. `read` emits a compatible dialect, so the read → edit → write loop round-trips (lossless for paragraphs, lists, and nested blockquotes; code/tables/math/headings inside a blockquote intentionally escape to top level on import). `read --ast` is the fully lossless JSON form. The `[^tcN]` and `[^cN]` labels `read --current` / `--comments` add (and their definition lines) are read-time hints like the `<!-- … -->` comments: the importer drops them, so pasting a `--current` line back applies its CriticMarkup exactly as if the labels weren't there, and never mints a footnote. Real footnotes read as `[^fnN]`/`[^enN]`; name your own anything but `tcN`/`cN`.

Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Offline, bootstrap keeps the working binary and exits 0.
**Air-gapped or mirrored installs.**

1. On a connected machine, download `docx-<platform>` and `SHA256SUMS` from a tagged release and verify them with `shasum -a 256 -c SHA256SUMS --ignore-missing`.
2. Copy the binary, plus `NOTICES` and `LGPL-3.0.txt` from the same release, to each machine (or your software-distribution tool), mark the binary executable, and put it on `PATH`.
2. Copy the binary, plus `LICENSE` and `NOTICES` from the same release, to each machine (or your software-distribution tool), mark the binary executable, and put it on `PATH`.

Nothing in docx-cli phones home after that.

Expand All @@ -115,4 +115,4 @@ Nothing in docx-cli phones home after that.

**What the checksum does and doesn't prove.** `SHA256SUMS` is published in the same release as the binaries. It protects against a corrupted or swapped download, not against a compromised release. For higher assurance, build from source (`bun run build:binary`) at a reviewed tag.

**License.** MIT. The standalone binaries statically link libheif (LGPL-3.0) for HEIC support; [NOTICES](NOTICES) lists the attributions and your LGPL rights, and redistributing the binary internally is fine with those files alongside it.
**License.** MIT. Every library docx-cli depends on is permissively licensed; [NOTICES](NOTICES) lists the attributions for the ones bundled into the binary, and redistributing the binary internally is fine with `LICENSE` and `NOTICES` alongside it.
Loading
Loading