@mrkt_frwd/leaf
v0.1.1
Published
Leaf — take a self-contained HTML page apart into editable CSS and JS, put it back, and prove it is the same file.
Readme
@mrkt_frwd/leaf
Take a self-contained HTML page apart into editable CSS and JS, put it back, and prove it is the same bytes.
npx @mrkt_frwd/leaf unpack page.html --output-dir ./out
npx @mrkt_frwd/leaf pack ./out --out page.htmlWhat it is for
Single-file pages are wonderful to ship and miserable to edit — one 40 KB file with the stylesheet, the shaders and the app logic in it. Leaf splits that into real files you can open in an editor, and puts it back together byte for byte.
The claim, and the evidence for it
Run against a real 22,891-byte page:
$ npx @mrkt_frwd/leaf unpack engines/job.html --output-dir ./out
unpacked job.html → ./out
sha256 7d3437b28d34… 4 part(s)
parts/00-script-importmap.json 104 B
parts/01-style.css 7970 B
parts/02-script.js 2128 B
parts/03-script-module.js 3671 B
$ npx @mrkt_frwd/leaf pack ./out --out rebuilt.html
packed → rebuilt.html
sha256 7d3437b28d34… 22891 B
identical to the source it was unpacked fromSame digest on both ends, confirmed independently with shasum and cmp.
Why byte-exact and not "close enough"
A round trip that is nearly right is the worst available outcome. It returns a page that still loads, still looks plausible, and has quietly lost a newline inside a shader or a tab inside a template literal. You find out weeks later.
So Leaf does not re-serialise a parse tree. It records where each block sat and what surrounded it, edits nothing, and reassembles from the original shell. And it reports the digest rather than a success message — when the bytes do not match, it says so instead of claiming victory.
This replaced twenty-one hand-written repack scripts that each failed the same way: nearly.
Commands
leaf unpack <page.html> --output-dir <dir> take it apart
leaf pack <dir> [--out <page.html>] put it back, report the digest
leaf check <page.html> is it genuinely self-contained?check answers a different question worth asking: does this page actually fetch
nothing from another origin, or does it only look like it?
Requirements
Node 18+. No dependencies.
MIT © Joe Asare. Built at Joe Asare Studio.
