caj2pdf-rust
Convert CNKI CAJ-family documents (CAJ, KDH, HN, C8) to PDF from the command
line, Node.js or the browser. MIT-licensed Rust with a WebAssembly build.
Memory stays bounded: input is read by range and output is written as a stream.
Releases are v0.x: CLI behavior and APIs may still change, and HN/C8 support
is experimental.
Quick start
Download the CLI archive for your platform from GitHub Releases, extract it, and run:
Or install it from crates.io with Rust 1.88 or newer:
Releases also carry a container image (Docker usage) and a JavaScript tarball for Node.js 22+ and browsers (JS API). The JavaScript package is also on npm:
Supported operating systems and CPUs are listed in the platform matrix.
The JavaScript API runs each conversion in a Worker. It reads a browser
File, Blob or OPFS file handle, or a Node.js path, descriptor or Blob,
and writes to a stream:
import from "caj2pdf-rust";
const writer = .;
await ;
await writer.;
What converts
| Input | Status |
|---|---|
| Supported: copied, with documented repairs. | |
| CAJ | Supported, with its bookmarks. |
| KDH | Supported for embedded PDFs. |
| HN-A | Experimental: scanned page images and bookmarks; no text layer. |
| C8, HN-B | Experimental: image pages, and native text pages with installed or given fonts (below). No bookmarks yet. |
| CAA (unreleased) | Recognized target descriptor: inspection only; obtain the referenced document to convert it. |
| TEB | Rejected: a DRM-encrypted container. |
The support matrix is the source of truth, with the verified profiles and remaining differences. Unsupported content fails with a located error instead of dropping pages.
Extensions do not determine the format: the measured .nh sample contains
HN-A bytes and converts through that path (433 pages, 365 bookmarks;
validation). Historical
CAJViewer documentation also names CAS, but no authentic sample has been found;
CAS research remains open.
Fonts for C8 and HN-B text pages
Native C8/HN-B text pages need a CJK and a Latin font. Nothing is bundled. Without font options the CLI uses installed fonts from a fixed list and names them on standard error. This free pair covers every tested document:
To choose fonts yourself, pass --font-cjk FILE --font-latin FILE or
--fonts DIR; --no-system-fonts turns the search off. The
CLI reference lists the searched directories
and faces, the measured comparison, the optional font roles and the fallback
rule. Node and the browser take fonts only as explicit options.
Limits
- C8/HN-B outlines are not verified, so those PDFs have no outline and the CLI
prints a warning.
--no-bookmarkssilences it. - HN-A pages are images. Run an OCR tool such as
ocrmypdffor search. - Substitute fonts do not reproduce the CAJViewer typography pixel for pixel. A measured HN-B private-use glyph may use a visual approximation with an explicit warning; its private-use code is retained in PDF ActualText.
- TEB files cannot be converted.
Library
Add the Rust library with cargo add caj2pdf-core.
The caj2pdf-core crate is the engine behind the CLI and the WASM build. It
reads any RangedSource (SeekableSource over a File, or a byte slice)
and writes any std::io::Write:
use ;
use ;
let mut input = new?;
let mut output = new;
let report = convert?;
convert detects the format and converts it; inspect returns the format,
page count, outline and structure. ConversionOptions selects bookmarks,
damaged-CAJ substitution and C8/HN-B fonts; a Progress receives the
detected format and read progress and can cancel. The
I/O architecture describes the contract.
More
- CLI reference: every command, option, exit status and the
inspectJSON schema. - I/O architecture and JS validation.
- Release policy and build provenance for verifying downloads.
- Research notes: the format investigations behind the decoders, kept with the oracles and conformance harnesses in caj2pdf-samples.
Contributing, provenance and license
Source code is MIT. Code must be original: do not copy from the Python or Go converters or from decoders under other licenses. The provenance record lists format references, the external test corpus rules and the dependency review. Sample documents are not part of this repository; the separate CAJSamples collection is an optional compatibility corpus. See CONTRIBUTING.md for checks, commit style and the merge gate, and CHANGELOG.md for changes. The project's public language is English.