icf.js
v1.2.2
Published
Zero-dependency browser & Node library (TypeScript) to parse, validate, build, write, and index Indent Comma Format (ICF) and generate ICX companion indexes. Implements ICF spec v1.1 and ICX spec v1.2.
Maintainers
Readme
icf.js
A small, zero-dependency browser & Node library (written in TypeScript) to parse, validate, build, write, and index Indent Comma Format (ICF) text, and to generate ICX companion indexes.
icf.js is a faithful behavioral port of the Java library icfj: inputs and outputs are plain strings (no file or stream I/O), and checksums are async (Web Crypto). It ships as ESM + CommonJS with bundled type declarations, plus a standalone IIFE global for <script> use — the same package serves browsers, Node and TypeScript projects.
- 📦 Zero runtime dependencies
- 🌳 JSON-tree-style data model with safe
path(...)navigation - 🧱 Schema-driven parse / write with full round-trip fidelity
- 📝 ICF v1.1: schema annotations (
!indexes!defaults!constraints!expressions), row!overrides, primary objects, primary-first reference resolution, multiline rows - 🔐 Self-describing checksums (
sha256,crc32built in; pluggable registry) - 🗂️ ICX index generation as a normal ICF document
- 🏷️ ICX v1.2: auto-harvested
Tags+Summaryindex fields for AI-harness search,writeResolvedexport - 📜 ICF v1.1 + ICX v1.2 — see the specifications
ICF combines the compactness of CSV, the readability of YAML, and the hierarchy of JSON — by declaring a schema once and storing records positionally. It is well suited to OCR pipelines, invoice/ERP interchange, document archives, and AI/RAG datasets.
Install
npm install icf.jsESM (Node, bundler or <script type="module">)
import { parse, write, writeWithChecksum, generateIcx } from 'icf.js';CommonJS (Node require)
const { parse, write, writeWithChecksum, generateIcx } = require('icf.js');
const doc = parse(icfText);
console.log(doc.toPrettyString());Plain <script> via jsDelivr (IIFE global window.ICF)
<script src="https://cdn.jsdelivr.net/npm/icf.js@1"></script>
<script>
const doc = ICF.parse(text);
console.log(doc.toJsonString());
</script>The package exposes unpkg / jsdelivr fields, so https://cdn.jsdelivr.net/npm/icf.js@1 (or https://unpkg.com/icf.js@1) resolves to the minified global build. Drop the @1 to always track the latest release.
Quick start
1. Parse and navigate
import { parse } from 'icf.js';
const doc = parse(icfText);
const data = doc.toIcfNode();
// path(...) returns a "missing" node instead of throwing, so chains are safe
const city = data.path('indexdata').path('masterindex')
.path('Project').path('Location').asText();
// records and attributes
const record = doc.getRecord(0);
console.log(record.getId(), record.getAttribute('note'));2. Validate
import { validate, isValid } from 'icf.js';
const result = validate(icfText);
if (!result.isValid()) {
for (const err of result.getErrors()) console.warn(err.toString());
}
if (isValid(icfText)) { /* ... */ }3. Build a node from scratch and write it
import { IcfNode, write } from 'icf.js';
const root = IcfNode.object();
root.putObject('vendor').put('id', 'V001').put('email', '[email protected]');
root.putArray('items').addObject().put('sku', 'A1').put('qty', 100);
const icf = write(root); // schema is inferred from the node shape4. Generate an ICX companion index
import { parse, generateIcx, write } from 'icf.js';
const doc = parse(icfText);
const icx = generateIcx(doc, 'invoice_archive.icf'); // an IcfDocument
const icxText = write(icx); // serialize to .icx text5. Checksums (async)
import { parse, writeWithChecksum, generateIcxWithChecksums } from 'icf.js';
const doc = parse(icfText);
// Emit a fresh @checksum over the canonical content (spec §19)
const signed = await writeWithChecksum(doc);
// Build an ICX with per-record checksums + advisory line/offset/size
const icx = await generateIcxWithChecksums(doc, {
sourceFileName: 'invoice_archive.icf',
sourceText: icfText,
});
// Invariant: the ICF's @checksum equals the ICX's @sourcechecksum6. Fetch helper
import { fetchIcf } from 'icf.js';
const doc = await fetchIcf('/data/invoice_archive.icf');A taste of ICF
@kind icf
@version 1.0
@schema
documentindex:
[InvoiceNo, InvoiceDate, VendorRef]
lineindex:
BillItems[]:
[SNo, Item, Quantity, Amount]
@data
@record id=DOC1001
documentindex:
= INV-2026-001, 2026-05-01, Vendor:VEN100
lineindex:
BillItems:
- 1, Cement, 100, 42000
- 2, Steel Rod, 50, 42500Key ideas: a schema declares the shape once; records store values positionally; Name[]: marks a collection (rows start with -), a plain leaf gets a single = row; Type:Id is a master reference; <<TAG ... TAG>> stores verbatim text blocks. See DOCUMENTATION.md for the full API and ICF semantics.
API surface
parse · parseLenient · validate · isValid · write · writeWithChecksum · generateIcx · generateIcxWithChecksums · fetchIcf
Model: IcfNode (IcfObject, IcfArray, IcfString, IcfNull, IcfMissing) · IcfDocument · IcfRecord · IcfMetadata · IcfMasters · IcfSchema / IcfSchemas / SchemaNode.
Lower level: IcfParser · ParseResult · IcfValidator · IcfWriter / WriterOptions · SchemaInference · IcxGenerator · IcfEscaper · Checksums.
Full reference: DOCUMENTATION.md.
Browser deltas vs. icfj
| icfj (Java) | icf.js (browser) |
|---|---|
| Path / Reader / InputStream overloads | strings only; plus fetchIcf(url) |
| sha256 / md5 / crc32 built in | sha256 + crc32 built in; md5 is reserved (registry-only) alongside crc32c / xxh3 |
| synchronous checksums | async (writeWithChecksum, generateIcxWithChecksums, Checksums.compute) |
| WriterOptions fluent builder | JS-idiomatic class: plain fields, fluent setters, WriterOptions.from(partial) |
Everything else — parse, build, validate, write, generateIcx, the data model, and the ICX structure — mirrors icfj 1:1.
Development
npm install
npm test # vitest (happy-dom)
npm run typecheck # tsc --noEmit (src + tests)
npm run build # tsup -> dist/icf.js (ESM), dist/icf.global.js + dist/icf.min.js (IIFE), dist/index.d.tsThe test/fixtures/ directory holds the four canonical fixtures; the round-trip tests (parse → write → parse) are the strongest correctness check. See CLAUDE.md for architecture and the spec gotchas.
License
MIT © 2026 Edison Williams.
The ICF and ICX specifications are © 2026 Edison Williams, licensed under CC BY 4.0.
