ascii-img-react — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ascii-img-react (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
ascii-img-react renders an image as ASCII art in React via an <AsciiImage> component. It matches each grid cell to the character whose shape fits best (6D shape vectors + nearest-neighbour), so edges stay crisp — unlike a brightness ramp. Pin a version: the package is young (0.1.0, MIT). Install + props live below; the full API is in references/component-api.md, the algorithm in references/technique.md.
per cell form a 6D vector; the nearest character (Euclidean distance) wins. That is why diagonals and curves render as /, \, _ rather than a blocky ramp.
<canvas>, so the **image must besame-origin or CORS-enabled** (img.crossOrigin = "anonymous"). A cross-origin image without CORS headers renders blank.
<pre> of monospace text. Monospace fonts only — proportionalfonts break the grid.
contrast and directionalContrast props are exactly the global anddirectional contrast-enhancement exponents from the technique (see references/technique.md).
npm add [email protected] # or: bun add / pnpm add / yarn addPeer deps: React 18 or 19 (react, react-dom).
import { AsciiImage } from 'ascii-img-react';
export function Hero() {
return (
<AsciiImage
src="/portrait.jpg" // same-origin or CORS-enabled
width={100} // output width in CHARACTERS
color="#39ff14" // green
backgroundColor="#000"
enableRipple={false}
/>
);
}width/height are in characters. cellWidth/cellHeight (px, default 6×12) set the sampling resolution. Defaults that matter: contrast={1.5}, directionalContrast={2}, enableDirectionalContrast, enableRipple, fontSize={10}, lineHeight={0.8}. Full prop table in references/component-api.md.
Set the --ascii-* variables on a shared class and pass it via className to theme every instance at once (props still win per-instance):
.ascii {
--ascii-font-family: 'Fira Code', monospace;
--ascii-font-size: 12px;
--ascii-line-height: 0.85;
--ascii-color: #c8d3f5;
--ascii-background: #1a1b26;
}
@media (prefers-color-scheme: light) {
.ascii { --ascii-color: #1a1b26; --ascii-background: #e1e2e7; }
}<AsciiImage src="/portrait.jpg" width={120} className="ascii" />--ascii-font-family works even though it looks commented out in the source — the container falls back through var(--ascii-font-family, monospace).
Internal edges look soft? Raise contrast (global, default 1.5) and/or directionalContrast (default 2, needs enableDirectionalContrast). Global contrast separates light/dark across the whole cell; directional contrast samples neighbouring cells to fix staircasing at hard boundaries. See the global-vs-directional explanation in references/technique.md.
enableRipple (default true) makes clicks send a wave that perturbs the samplingvectors. Tune rippleCount and rippleConfig (speed, amplitude, decay, wavelength, duration).
enableRain (default false) auto-spawns drops; tune rainConfig (intensity,variation).
Animation has a cost: grids wider than ~150 columns can stutter. For large output, shrink width or set enableRipple={false}.
For a custom pipeline (your own canvas, caching, or non-React use), import from the package root: sampleCell / sampleGrid / sampleExternalCircles, rgbToLightness, DEFAULT_GRID_CONFIG, findBestCharacter / CachedCharacterLookup / cachedLookup, CHARACTERS / NORMALIZED_CHARACTERS, applyGlobalContrast / applyDirectionalContrast / applyFullContrast. Reach for these only when <AsciiImage> can't express what you need; otherwise the component is the path. Full signatures in references/component-api.md.
<AsciiImage> is a client component (uses useEffect,<canvas>). In Next App Router add "use client"; in Astro give it a client:load/client:visible directive. Serve the image same-origin (e.g. from /public) to avoid CORS entirely.
image-to-ascii.
shaders, VJ visuals) → use textmode-js.
Technique: Alex Harri, "ASCII characters are not pixels". Library: MIT-licensed ascii-img-react.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.