ASCIInator/README.md
dev e904cdb3cb feat: full GUI, test API, auto-convert, aspect-ratio sliders
- Auto-convert on image load (0ms) and flag change (400ms debounce)
- SizeControl: linked width/height sliders with aspect-ratio lock and 0.5 font correction factor
- Full flag exposure for all 4 tools (chafa, jp2a, ascii-image-converter, img2txt)
- ChafaOptions: symbols/fill dropdowns, dither controls, work/threshold/font-ratio sliders, format select, toggles
- Jp2aOptions: color-depth, RGB weight sliders, edge controls, 8 toggles
- ImgTxtOptions: dither select with valid libcaca values, gamma slider
- OutputDisplay: ansi-to-html rendering for colored chafa output
- ShellBridge: abort-previous pattern, conversion-start/end lifecycle events
- Test API (ENABLE_TEST_API=true): /test/health, /test/convert, /test/flags/:tool, /test/imagemagick
- buildArgs: space-separated args (not = format); full schemas in SCHEMAS export
- runChafa: width/height destructured and combined into --size WxH
- Port changed to 3050; Vite on 0.0.0.0 with allowedHosts for production domain
- 98 unit tests passing across 12 test files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 10:29:45 +00:00

331 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ASCIInator
```
█████╗ ███████╗ ██████╗██╗██╗███╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗
██╔══██╗██╔════╝██╔════╝██║██║████╗ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗
███████║███████╗██║ ██║██║██╔██╗ ██║███████║ ██║ ██║ ██║██████╔╝
██╔══██║╚════██║██║ ██║██║██║╚██╗██║██╔══██║ ██║ ██║ ██║██╔══██╗
██║ ██║███████║╚██████╗██║██║██║ ╚████║██║ ██║ ██║ ╚██████╔╝██║ ██║
╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
```
> Turn any image into ASCII art. Headless Vue 3 front-end for your system's ASCII conversion binaries.
---
## What It Does
ASCIInator is a local-first GUI wrapper around the ASCII conversion tools already on your system. Drop an image in, pick your tool, tune the flags, get plain-text ASCII out. No cloud, no SaaS, no telemetry — just your binaries, a thin Fastify bridge, and a Vue 3 interface.
Built as a test bed for **Neovim IDE v2.1.x**.
---
## Supported Converters
| Tool | Notes |
|------|-------|
| **chafa** | Default. Best quality, full flag exposure |
| **jp2a** | JPEG-focused, classic output |
| **ascii-image-converter** | Braille support, good for fine detail |
| **img2txt** | libcaca-based, multiple output formats |
All tools must be installed on your system. ASCIInator does not install them for you.
---
## Stack
| Layer | Tech |
|-------|------|
| Frontend | Vue 3 + Vite |
| Styling | Tailwind CSS (no component lib) |
| API server | Fastify |
| Shell invocation | execa |
| Image processing | ImageMagick v7 (`magick`) |
---
## Architecture
```
┌─────────────────────────────────────────┐
│ Vue 3 Frontend │
│ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ ImageInput │ │ ToolSelector │ │
│ │ │ │ │ │
│ │ • Upload │ │ • chafa │ │
│ │ • Paste │ │ • jp2a │ │
│ │ • Drag-drop │ │ • ascii-i-c │ │
│ └──────┬──────┘ │ • img2txt │ │
│ │ └────────┬────────┘ │
│ └────────┬──────────┘ │
│ ▼ │
│ ┌───────────────┐ │
│ │ ShellBridge │ (renderless) │
│ └───────┬───────┘ │
│ │ POST /convert │
└──────────────────┼──────────────────────┘
┌──────────────────┼──────────────────────┐
│ Fastify :3050 │ │
│ ▼ │
│ ImageMagick preprocessing │
│ ↓ │
│ execa → binary │
│ ↓ │
│ stdout → response │
└─────────────────────────────────────────┘
┌──────────────────┼──────────────────────┐
│ Vue 3 Frontend │
│ │
│ ┌────────────────────┐ ┌───────────┐ │
│ │ OutputDisplay │ │ ErrorLog │ │
│ │ │ │ │ │
│ │ <pre> ASCII art │ │ stderr │ │
│ │ copy / download │ │ warnings │ │
│ └────────────────────┘ └───────────┘ │
└─────────────────────────────────────────┘
```
---
## Prerequisites
**System binaries** (install via your package manager):
```bash
# macOS
brew install chafa jp2a libcaca imagemagick
brew install ascii-image-converter
# Debian/Ubuntu
apt install chafa jp2a caca-utils imagemagick
# ascii-image-converter: see https://github.com/TheZoraiz/ascii-image-converter
# Arch
pacman -S chafa jp2a libcaca imagemagick
yay -S ascii-image-converter # AUR
```
**Node** — v20.19+ or v22.12+ required
**Vite** — installed via npm
---
## Installation
```bash
git clone <repo-url>
cd asciinator
npm install
```
---
## IDE Setup
**Neovim** (primary — this is a Neovim v2.1.x test bed):
- Volar LSP in Takeover mode (disable tsserver for `.vue` files)
- `tailwindcss-language-server` for class intellisense
- `eslint-lsp` + `prettier` for format on save
- See `CLAUDE.md §7` for the full Neovim config checklist
**Browser DevTools:**
- [Vue DevTools for Chrome/Brave](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
- [Vue DevTools for Firefox](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
- Enable Custom Object Formatters in DevTools for readable Vue reactive state
---
## Running
You need two terminals (or one split — you're using Neovim, you know the drill).
```bash
# Terminal 1 — Fastify API server
node server/index.js
# Terminal 2 — Vite dev server
npm run dev
```
| Service | URL |
|---------|-----|
| Vue app | http://localhost:5173 |
| Fastify API | http://localhost:3050 |
---
## Project Structure
```
asciinator/
├── CLAUDE.md ← Full spec for Claude Code
├── README.md ← You are here
├── index.html
├── vite.config.js
├── tailwind.config.js
├── src/
│ ├── main.js
│ ├── App.vue
│ ├── assets/
│ │ └── main.css
│ └── components/
│ ├── ImageInput.vue ← Upload / paste / drag-drop
│ ├── ToolSelector.vue ← Tool picker + flag controls
│ ├── ShellBridge.vue ← GUI state → API call (renderless)
│ ├── OutputDisplay.vue ← Plain-text ASCII result
│ ├── ErrorLog.vue ← stderr / error surface
│ └── options/
│ ├── ChafaOptions.vue
│ ├── Jp2aOptions.vue
│ ├── AsciiOptions.vue
│ └── ImgTxtOptions.vue
└── server/
├── index.js
├── routes/
│ └── convert.js ← POST /convert handler
└── lib/
├── imagemagick.js ← Pre/post processing
└── converters.js ← Per-tool execa invocations
```
---
## npm Scripts
```bash
npm run dev # Vite dev server (HMR)
npm run build # Production build
npm run preview # Preview production build
npm run server # Fastify API server
npm run server:dev # Fastify with --watch (auto-restart)
npm run lint # oxlint + ESLint (with autofix)
npm run format # Prettier
npm run test:unit # Vitest unit tests
npm run test:e2e # Playwright end-to-end tests
```
For e2e tests, build first if running on CI:
```bash
npm run build
npm run test:e2e
npm run test:e2e -- --project=chromium # Chromium only
npm run test:e2e -- --debug # Debug mode
```
---
## API
### `POST /convert`
**Request**`multipart/form-data`
| Field | Type | Description |
|-------|------|-------------|
| `image` | file | Image file to convert |
| `tool` | string | `chafa` \| `jp2a` \| `ascii-image-converter` \| `img2txt` |
| `flags` | JSON string | Tool-specific flags object |
**Response**`text/plain` — raw ASCII output on success, stderr on 422.
**curl example:**
```bash
curl -s -X POST http://localhost:3050/convert \
-F "image=@/path/to/photo.jpg" \
-F "tool=chafa" \
-F 'flags={"width":"80","colors":"256"}'
```
---
## Flag Reference
All flags are optional. Omitting a flag lets the binary use its own default.
### chafa
| Flag | Type | Values | Description |
|------|------|--------|-------------|
| `width` | integer | e.g. `80` | Output width in characters (combined into `--size=WxH`) |
| `height` | integer | e.g. `40` | Output height in characters (combined into `--size=WxH`) |
| `colors` | enum | `none` `2` `8` `16/8` `16` `240` `256` `full` | Color depth |
| `symbols` | string | e.g. `block+border+extra` | Symbol sets to use |
| `dither` | enum | `none` `ordered` `diffusion` `noise` | Dithering algorithm |
| `threshold` | float | `0.0``1.0` | Alpha threshold |
| `font-ratio` | float | e.g. `0.5` | Terminal font width/height ratio |
### jp2a
| Flag | Type | Values | Description |
|------|------|--------|-------------|
| `width` | integer | e.g. `80` | Output width in characters |
| `height` | integer | e.g. `40` | Output height in characters |
| `background` | enum | `light` `dark` | Assumed terminal background |
| `chars` | string | e.g. `.:-=+*#%@` | Character ramp to use |
### ascii-image-converter
| Flag | Type | Values | Description |
|------|------|--------|-------------|
| `width` | integer | e.g. `80` | Output width in characters |
| `height` | integer | e.g. `40` | Output height in characters |
| `color` | boolean | `true` | Emit ANSI color codes |
| `braille` | boolean | `true` | Use braille dot patterns |
| `threshold` | integer | `0``255` | Brightness threshold |
### img2txt
| Flag | Type | Values | Description |
|------|------|--------|-------------|
| `width` | integer | e.g. `80` | Output width in characters |
| `height` | integer | e.g. `40` | Output height in characters |
| `format` | enum | `ansi` `utf8` `html` | Output format |
| `dither` | string | e.g. `fstein` | Dithering mode |
| `gamma` | float | e.g. `1.0` | Gamma correction |
---
## Troubleshooting
**`command not found: chafa` (or jp2a, img2txt, ascii-image-converter)**
The binary isn't on PATH. Install it via your package manager — see Prerequisites above.
**`convert: command not found`**
ImageMagick isn't installed. It's required for all conversions regardless of tool.
**CORS error in the browser console**
The Fastify server isn't running, or it's on a different port. Start it with `npm run server` and confirm it logs `Server listening at http://127.0.0.1:3050`.
**422 from the server**
The binary returned a non-zero exit code. The full stderr is in the response body and shown in the ErrorLog panel.
**Blank or truncated output**
Some tools default to terminal width detection which may return 0 in a non-TTY context. Set an explicit `--width` flag.
---
## Design
- Always dark — light mode not wired (planned)
- No component library — raw Tailwind only
- Monospace output: JetBrains Mono
- UI font: IBM Plex Sans
- Accent: `#39ff14` (neon green — because ASCII)
---
## Neovim v2 Test Bed
This project exists partly to stress-test the **Neovim IDE v2.1.x** setup across a real Vue 3 + JS project. See `CLAUDE.md §7` for the full test checklist covering Volar, Tailwind LSP, ESLint, DAP, and more.
---
## License
MIT