
Flashot is the blazing-fast image generation tool for code snippets with elegant design and flawless performance
- π₯οΈ Used from CLI: Use Flashot as a command-line tool for quick image generation
- π₯ Used from import: Use Flashot as an importable module in your code:
- π©βπ» Inline code support: Easily convert inline code snippets to images
- π URL support: Fetch code snippets directly from URLs
- ποΈ File path support: Convert code snippets from local files
- ποΈ Buffer support: Convert code snippets from buffers
- π¨ Customizable styles: Choose from various options to match your style
- π¦ Lightweight: Minimal dependencies to keep your project lean
- π Line numbers: Support for displaying & customizing line numbers
- ποΈ Highlighting: Support for custom syntax highlighting
- ποΈ Render caching: Efficiently handles caching for improved performance (render, tokens, sizes, fonts)
- πͺ Multi-format support: Generate images in various formats (png, jpeg, webp, avif)
- πΌοΈ High-quality output: Generates crisp and clear images which keep the original code's formatting intact
- β‘ Blazing fast: Optimized for speed, ensuring quick image generation
- π οΈ Easy to use: Easy to integrate into your projects with a simple API
- π· TypeScript support: Fully typed for better developer experience
- π Extensive testing: Thoroughly tested with a comprehensive suite of unit tests
- π Easy integration: Simple API for seamless integration into your projects
- π§ Flexible environment support: Works seamlessly in various environments (Node.js, Bun, Deno, Workers, β¦)
npm install flashot
yarn add flashot
pnpm add flashot
bun install flashot
deno add jsr:@thuongtruong109/flashot
npx jsr add @thuongtruong/flashot
npm install -g flashot
Then quick check from terminal with CLI runner
flashot -h
import { writeFile } from "node:fs/promises";
import { codeToImg } from "flashot";
const buffer = await codeToImg('console.log("hello, world!");', {
/* add more options*/
});
await writeFile("inline.webp", buffer);
import { writeFile } from "node:fs/promises";
import { urlToImg } from "flashot";
const buffer = await urlToImg("https://randomfox.ca/floof", {
/* add more options*/
format: OutputFormat.Png,
});
await writeFile("url.png", buffer);
import { writeFile } from "node:fs/promises";
import { bufferToImg } from "flashot";
const buffer =
"<Buffer 54 68 69 73 20 69 73 20 61 20 62 75 66 66 65 72 20 65 78 61 6d 70 6c 65 2e>";
const img = await bufferToImg(buffer, {
/* add more options*/
});
await writeFile("buffer.png", img);
import { writeFile } from "node:fs/promises";
import { pathToImg } from "flashot";
const img = await pathToImg("../package.json", {
/* add more options*/
});
await writeFile("path.png", img);
flashot code "console.log('Hello world')" <...options>
flashot url "https://randomfox.ca/floof" <...options>
flashot buffer "<Buffer 54 68 69 73 20 69 73 20 61 20 62 75 66 66 65 72 20 65 78 61 6d 70 6c 65 2e>" <...options>
flashot path "../package.json" <...options>
Usage: flashot [command] [options]
Commands:
code <code> Convert code string to image
file <file> Convert code file to image
url <url> Convert code from URL to image
buffer <buffer> Convert hex buffer string to image
help [command] display help for command
Options:
-V, --version output the version number
-o, --output <file> output image file path (default: "tmp.webp")
-l, --lang <language> programming language (default: "js")
-t, --theme <theme> syntax highlighting theme (default: "dracula")
-f, --font <font> font family to use (default: "https://fonts.bunny.net/jetbrains-mono/files/jetbrains-mono-latin-400-normal.woff2")
--format <format> output image format (png, jpeg, webp, avif) (default: "webp")
-q, --quality <percent> image quality (1-100) (only for jpeg) (default: "100")
-g, --gap <pixels> gap between lines (default: "1")
-p, --style-padding <pixels> padding around code (default: "25")
--style-border-radius <pixels> border radius (default: "8")
-b, --bg <color> background color (default: "not needed!")
-w, --width <pixels> image width (default: "not needed!")
-H, --height <pixels> image height (default: "not needed!")
-L, --line-numbers-enabled enable line numbers (default: false)
--line-numbers-start-from <number> line number start (default: "1")
--line-numbers-color <color> line number color (default: "#7b7f8b")
--line-numbers-margin-right <pixels> line number margin right (default: "0")
--highlight-enabled enable line highlighting (default: false)
--highlight-background-color <color> highlight background color (default: "#347faa23")
--highlight-border-radius <pixels> highlight border radius (default: "0")
--highlight-at <line> highlight line number (default: "1")
--highlight-depth <number> highlight depth (shadow effect) (default: "1")
-v, --verbose enable verbose output
-h, --help display help for command
const defaultOptions = {
lang: "ts", // default is javascript
theme: "ayu-dark", // default is github-dark
font: "https://fonts.bunny.net/ubuntu-sans-mono/files/ubuntu-sans-mono-latin-400-normal.woff2", // default is bunny.net/jetbrains-mono.
format: "png", // default is "webp" (options: png, jpeg, webp, avif)
quality: 100, // default is 100 (1-100), only applies to jpeg formats
width: 800, // default is system's width
height: 400, // default is system's height
bg: "transparent", // default is system's background
gap: 1, // gap between lines (default is 1)
style: {
borderRadius: 10, // default is 8
padding: 30, // default is 25
// ... more custom styles
},
lineNumbers: {
enabled: true, // default is false
startFrom: 5, // default is 1
color: "#d64141ff", // default is #7b7f8b
marginRight: 2, // default is 0
},
highlight: {
enabled: true, // default is false
backgroundColor: "#25ce5da1", // default is #347faa23,
borderRadius: 2, // default is 0
at: 2, // start from at line - default is 1
depth: 3, // total lines - default is 1
},
};
Option | Description | Default |
---|---|---|
lang |
Code language (supported) | "js" |
theme |
Rendering theme (supported) | "github-dark" |
font |
Font for rendering (URL/Buffer/ArrayBuffer) | Jetbrains Mono |
format |
Output image format (png , jpeg , webp , avif ) |
webp |
quality |
Image quality (1-100) for JPEG formats | 100 |
width |
Image width | System default |
height |
Image height | System default |
bg |
Background color | Theme's background |
gap |
Gap between lines | 1 |
style |
Additional container styles (docs) | { borderRadius: 8, padding: 25 } |
lineNumbers |
Line number styles | { enabled: false, color: '#7b7f8b', marginRight: 0 } |
highlight |
Syntax highlighting styles | { enabled: false, backgroundColor: '#347faa23', borderRadius: 0, at: 1, depth: 1 } |
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---|---|---|---|---|---|
All files | 99.17 | 81.25 | 100 | 99.17 | |
core.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
shared.ts | 100 | 100 | 100 | 100 | |
utils.ts | 98.36 | 78.57 | 100 | 98.36 | 67 |
No | Task name | Latency avg (ns) | Latency med (ns) | Throughput avg (ops/s) | Throughput med (ops/s) | Samples |
---|---|---|---|---|---|---|
1 | 1 lines | 10175455 Β± 1.43% | 10075900 Β± 106800 | 99 Β± 1.05% | 99 Β± 1 | 99 |
2 | 10 lines | 39056303 Β± 0.45% | 38845500 Β± 405750 | 26 Β± 0.44% | 26 Β± 0 | 64 |
3 | 100 lines | 343126433 Β± 0.29% | 343616650 Β± 2711850 | 3 Β± 0.29% | 3 Β± 0 | 64 |
4 | 1000 lines | 1726190939 Β± 0.46% | 1715535300 Β± 13138650 | 1 Β± 0.45% | 1 Β± 0 | 64 |
Flashot API is available as Docker images on both GitHub Container Registry and Docker Hub.
# Pull from GitHub Container Registry
docker pull ghcr.io/thuongtruong109/flashot-api:latest
# Or pull from Docker Hub
docker pull thuongtruong109/flashot-api:latest
# Run the container
docker run -p 8080:8080 ghcr.io/thuongtruong109/flashot-api:latest
# Clone the repository
git clone https://github.com/thuongtruong109/flashot.git
cd flashot
# Start with Docker Compose
docker-compose up -d
- GitHub Container Registry:
ghcr.io/thuongtruong109/flashot-api
- Docker Hub:
thuongtruong109/flashot-api
latest
- Latest stable releasemain
- Latest development buildmain-<sha>
- Specific commit builds
Once running, the API provides several endpoints:
POST /
- Convert code string to imagePOST /url
- Convert code from URL to imagePOST /file
- Convert code from file path to imagePOST /buffer
- Convert code from hex buffer to imageGET /options
- Get available configuration optionsGET /health
- Health check endpoint
Example usage:
curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"code": "console.log(\"Hello, World!\");",
"options": {
"lang": "javascript",
"theme": "github-dark",
"format": "png"
}
}' \
--output hello-world.png
For detailed deployment instructions, see api/DEPLOYMENT.md.
- β‘ Bun - Fast all-in-one JavaScript runtime and toolkit
- ποΈ TypeScript - Type-safe development with strict mode enabled
- π¦ Vite - Lightning-fast build tool with optimized bundling
- πͺ Tsdown - A powerful tool for TypeScript package
- π§ͺ Vitest - Blazing fast unit testing & interactive test UI framework
- π¨ Shiki and Takumi - Render container highlight
- π Biome - Fast formatter and linter for consistent code style
- π Dual Module Support - ESM and CommonJS output with proper type definitions
- π₯ ESLint - Advanced linting with TypeScript and SonarJS rules
- π§© Lefthook and Commitlint - Automated Git hooks for linting and formatting
- π οΈ Tinybench - A tiny benchmarking library for measuring performance
- π₯οΈ Commander - A popular library for building command-line interfaces
Contributions are welcome! This starter kit uses:
- Automated code formatting and linting
- Comprehensive test coverage requirements
Please ensure all tests pass and code quality checks succeed before submitting a PR.
Check CONTRIBUTING.md for more information.
Head over to the discussions to share your ideas.