ASCIInator/README.md

331 lines
12 KiB
Markdown
Raw Normal View History

# 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 :3001 │ │
│ ▼ │
│ 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:3001 |
---
## 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:3001/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:3001`.
**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