+1
-1
| { | ||
| "name": "kittyhtml", | ||
| "version": "0.2.0", | ||
| "version": "0.2.1", | ||
| "description": "Render HTML to an image and display it inline in Kitty/iTerm2-capable terminals. No browser — CSS layout via DropFlow.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+11
-7
@@ -12,9 +12,13 @@ # kittyhtml | ||
| ```sh | ||
| # from this directory, until published | ||
| npm install | ||
| npm link # exposes the `kittyhtml` binary on your PATH | ||
| npm install -g kittyhtml | ||
| ``` | ||
| Requires Node 20+. Pulls in [`@napi-rs/canvas`](https://www.npmjs.com/package/@napi-rs/canvas) (prebuilt native binary, no compile step) and `dropflow`. | ||
| Or one-shot, no install: | ||
| ```sh | ||
| npx kittyhtml --demo | ||
| ``` | ||
| Requires Node 20+. Pulls in [`@napi-rs/canvas`](https://www.npmjs.com/package/@napi-rs/canvas) (prebuilt native binary, no compile step) and `dropflow`. Two deps total, ~90 KB tarball. | ||
| ## Use | ||
@@ -74,11 +78,11 @@ | ||
| First run fetches Noto fonts from a CDN via DropFlow's bundled `register-noto-fonts.js`. Subsequent renders reuse what was loaded. Bundled offline fonts are on the roadmap. | ||
| `Noto Sans` (regular, bold, italic, bold-italic) and `Noto Sans Mono` (regular, bold) ship inside the package as latin-subset TTFs (~160 KB total). No CDN fetch on first run; works offline. Reference them in HTML with `font-family: 'Noto Sans', sans-serif` and `font-family: 'Noto Sans Mono', monospace`. | ||
| ## Claude Code skill | ||
| A bundled skill lets Claude Code render output as a styled inline image when you ask for it as "kittyhtml" or "khtml": | ||
| A bundled skill lets Claude Code render output as a styled inline image when you ask for it as "kittyhtml" or "khtml". After a global install: | ||
| ```sh | ||
| mkdir -p ~/.claude/skills | ||
| cp -r skill/kittyhtml ~/.claude/skills/kittyhtml | ||
| cp -r "$(npm root -g)/kittyhtml/skill/kittyhtml" ~/.claude/skills/ | ||
| ``` | ||
@@ -85,0 +89,0 @@ |
+12
-1
@@ -83,2 +83,13 @@ #!/usr/bin/env node | ||
| // readFileSync(0) crashes with EAGAIN when stdin is in non-blocking mode and | ||
| // the upstream process hasn't flushed yet (common with `claude -p ... | kittyhtml`). | ||
| // Async iteration over process.stdin yields back to the event loop and waits | ||
| // for data, so it handles any pipe pacing correctly. | ||
| async function readStdin() { | ||
| process.stdin.setEncoding('utf8'); | ||
| let buf = ''; | ||
| for await (const chunk of process.stdin) buf += chunk; | ||
| return buf; | ||
| } | ||
| async function main() { | ||
@@ -93,3 +104,3 @@ const opts = parseArgs(process.argv.slice(2)); | ||
| } else if (!process.stdin.isTTY) { | ||
| html = readFileSync(0, 'utf8'); | ||
| html = await readStdin(); | ||
| } else { | ||
@@ -96,0 +107,0 @@ process.stdout.write(HELP); |
180849
0.35%261
3.98%99
4.21%