ansimax 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +195 -0
- package/README.es.md +122 -9
- package/README.md +122 -9
- package/dist/index.d.mts +287 -104
- package/dist/index.d.ts +287 -104
- package/dist/index.js +288 -3
- package/dist/index.mjs +282 -3
- package/examples/all-in-one.cjs +1 -1
- package/examples/all-in-one.mjs +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -993,10 +993,11 @@ var gradient = (text, stops, opts = {}) => {
|
|
|
993
993
|
return _gradientAnsiAware(s, colors, easingFn, phaseN);
|
|
994
994
|
};
|
|
995
995
|
var createGradient = (stops, defaultOpts = {}) => {
|
|
996
|
-
const
|
|
996
|
+
const originalStops = Array.isArray(stops) ? [...stops] : [];
|
|
997
|
+
const colors = originalStops.map(safeHex).filter((c) => c !== null);
|
|
997
998
|
const defaultEasingFn = resolveEasing(defaultOpts.easing);
|
|
998
999
|
const defaultPreserveAnsi = defaultOpts.preserveAnsi ?? false;
|
|
999
|
-
|
|
1000
|
+
const fn = ((text, opts = {}) => {
|
|
1000
1001
|
const s = coerceText(text);
|
|
1001
1002
|
if (!s || isNoColor()) return s;
|
|
1002
1003
|
if (colors.length === 0) return s;
|
|
@@ -1012,8 +1013,31 @@ var createGradient = (stops, defaultOpts = {}) => {
|
|
|
1012
1013
|
return _gradientPlain(s, colors, easingFn, phaseN);
|
|
1013
1014
|
}
|
|
1014
1015
|
return _gradientAnsiAware(s, colors, easingFn, phaseN);
|
|
1015
|
-
};
|
|
1016
|
+
});
|
|
1017
|
+
Object.defineProperty(fn, "stops", {
|
|
1018
|
+
value: Object.freeze(originalStops),
|
|
1019
|
+
enumerable: true,
|
|
1020
|
+
writable: false
|
|
1021
|
+
});
|
|
1022
|
+
Object.defineProperty(fn, "resolvedStops", {
|
|
1023
|
+
value: Object.freeze(colors.map((c) => Object.freeze({ ...c }))),
|
|
1024
|
+
enumerable: true,
|
|
1025
|
+
writable: false
|
|
1026
|
+
});
|
|
1027
|
+
Object.defineProperty(fn, "defaultOptions", {
|
|
1028
|
+
value: Object.freeze({ ...defaultOpts }),
|
|
1029
|
+
enumerable: true,
|
|
1030
|
+
writable: false
|
|
1031
|
+
});
|
|
1032
|
+
return fn;
|
|
1016
1033
|
};
|
|
1034
|
+
function reverseGradient(input) {
|
|
1035
|
+
if (Array.isArray(input)) {
|
|
1036
|
+
return [...input].reverse();
|
|
1037
|
+
}
|
|
1038
|
+
const reversedStops = [...input.stops].reverse();
|
|
1039
|
+
return createGradient(reversedStops, input.defaultOptions);
|
|
1040
|
+
}
|
|
1017
1041
|
var _gradientPlain = (text, colors, easingFn, phase) => {
|
|
1018
1042
|
const chars = [...text];
|
|
1019
1043
|
const visible = chars.filter((c) => c !== " ").length;
|
|
@@ -2315,6 +2339,251 @@ var stream = async function* (text, opts = {}) {
|
|
|
2315
2339
|
yield i === lines.length - 1 ? line : line + "\n";
|
|
2316
2340
|
}
|
|
2317
2341
|
};
|
|
2342
|
+
var ASCII_RAMPS = {
|
|
2343
|
+
standard: " .:-=+*#%@",
|
|
2344
|
+
detailed: " .'`^\",:;Il!i><~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$",
|
|
2345
|
+
blocks: " \u2591\u2592\u2593\u2588",
|
|
2346
|
+
simple: " .+#"
|
|
2347
|
+
};
|
|
2348
|
+
var _resolveRamp = (r) => {
|
|
2349
|
+
if (typeof r === "string" && r.length > 0) {
|
|
2350
|
+
if (r in ASCII_RAMPS) return ASCII_RAMPS[r];
|
|
2351
|
+
return r;
|
|
2352
|
+
}
|
|
2353
|
+
return ASCII_RAMPS.standard;
|
|
2354
|
+
};
|
|
2355
|
+
var _luminance = (p) => {
|
|
2356
|
+
if (!p) return 0;
|
|
2357
|
+
return 0.2126 * p.r + 0.7152 * p.g + 0.0722 * p.b;
|
|
2358
|
+
};
|
|
2359
|
+
var _sobelEdges = (pixels) => {
|
|
2360
|
+
const h = pixels.length;
|
|
2361
|
+
const w = h > 0 ? pixels[0].length : 0;
|
|
2362
|
+
const out = Array.from({ length: h }, () => new Array(w).fill(0));
|
|
2363
|
+
for (let y = 1; y < h - 1; y++) {
|
|
2364
|
+
const rowPrev = pixels[y - 1];
|
|
2365
|
+
const row = pixels[y];
|
|
2366
|
+
const rowNext = pixels[y + 1];
|
|
2367
|
+
const outRow = out[y];
|
|
2368
|
+
for (let x = 1; x < w - 1; x++) {
|
|
2369
|
+
const tl = _luminance(rowPrev[x - 1]);
|
|
2370
|
+
const t = _luminance(rowPrev[x]);
|
|
2371
|
+
const tr = _luminance(rowPrev[x + 1]);
|
|
2372
|
+
const l = _luminance(row[x - 1]);
|
|
2373
|
+
const r = _luminance(row[x + 1]);
|
|
2374
|
+
const bl = _luminance(rowNext[x - 1]);
|
|
2375
|
+
const b = _luminance(rowNext[x]);
|
|
2376
|
+
const br = _luminance(rowNext[x + 1]);
|
|
2377
|
+
const gx = -tl + tr - 2 * l + 2 * r - bl + br;
|
|
2378
|
+
const gy = -tl - 2 * t - tr + bl + 2 * b + br;
|
|
2379
|
+
const mag = Math.sqrt(gx * gx + gy * gy);
|
|
2380
|
+
outRow[x] = Math.min(255, mag);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
return out;
|
|
2384
|
+
};
|
|
2385
|
+
var _floydSteinberg = (lum, levels) => {
|
|
2386
|
+
const h = lum.length;
|
|
2387
|
+
if (h === 0) return lum;
|
|
2388
|
+
const w = lum[0].length;
|
|
2389
|
+
if (w === 0) return lum;
|
|
2390
|
+
const out = lum.map((row) => [...row]);
|
|
2391
|
+
const step = 255 / Math.max(1, levels - 1);
|
|
2392
|
+
for (let y = 0; y < h; y++) {
|
|
2393
|
+
const row = out[y];
|
|
2394
|
+
for (let x = 0; x < w; x++) {
|
|
2395
|
+
const oldPixel = row[x];
|
|
2396
|
+
const quantLevel = Math.round(oldPixel / step);
|
|
2397
|
+
const newPixel = quantLevel * step;
|
|
2398
|
+
row[x] = newPixel;
|
|
2399
|
+
const err = oldPixel - newPixel;
|
|
2400
|
+
if (x + 1 < w) {
|
|
2401
|
+
row[x + 1] = row[x + 1] + err * 7 / 16;
|
|
2402
|
+
}
|
|
2403
|
+
if (y + 1 < h) {
|
|
2404
|
+
const next = out[y + 1];
|
|
2405
|
+
if (x > 0) next[x - 1] = next[x - 1] + err * 3 / 16;
|
|
2406
|
+
next[x] = next[x] + err * 5 / 16;
|
|
2407
|
+
if (x + 1 < w) next[x + 1] = next[x + 1] + err * 1 / 16;
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
return out;
|
|
2412
|
+
};
|
|
2413
|
+
var _resizePixels = (pixels, targetW, targetH) => {
|
|
2414
|
+
const srcH = pixels.length;
|
|
2415
|
+
if (srcH === 0) return [];
|
|
2416
|
+
const srcW = pixels[0].length;
|
|
2417
|
+
if (srcW === 0) return [];
|
|
2418
|
+
const out = [];
|
|
2419
|
+
for (let y = 0; y < targetH; y++) {
|
|
2420
|
+
const sy = Math.min(srcH - 1, Math.floor(y / targetH * srcH));
|
|
2421
|
+
const srcRow = pixels[sy];
|
|
2422
|
+
const newRow = new Array(targetW);
|
|
2423
|
+
for (let x = 0; x < targetW; x++) {
|
|
2424
|
+
const sx = Math.min(srcW - 1, Math.floor(x / targetW * srcW));
|
|
2425
|
+
newRow[x] = srcRow[sx];
|
|
2426
|
+
}
|
|
2427
|
+
out.push(newRow);
|
|
2428
|
+
}
|
|
2429
|
+
return out;
|
|
2430
|
+
};
|
|
2431
|
+
var _toLuminanceGrid = (pixels) => {
|
|
2432
|
+
return pixels.map((row) => row.map((p) => _luminance(p)));
|
|
2433
|
+
};
|
|
2434
|
+
var _enhanceForFace = (lum) => {
|
|
2435
|
+
const flat = [];
|
|
2436
|
+
for (const row of lum) for (const v of row) flat.push(v);
|
|
2437
|
+
if (flat.length === 0) return lum;
|
|
2438
|
+
flat.sort((a, b) => a - b);
|
|
2439
|
+
const lo = flat[Math.floor(flat.length * 0.1)];
|
|
2440
|
+
const hi = flat[Math.floor(flat.length * 0.9)];
|
|
2441
|
+
const range = Math.max(1, hi - lo);
|
|
2442
|
+
return lum.map(
|
|
2443
|
+
(row) => row.map((v) => {
|
|
2444
|
+
const stretched = (v - lo) / range * 255;
|
|
2445
|
+
return Math.max(0, Math.min(255, stretched));
|
|
2446
|
+
})
|
|
2447
|
+
);
|
|
2448
|
+
};
|
|
2449
|
+
var fromImage = (pixels, opts = {}) => {
|
|
2450
|
+
if (!Array.isArray(pixels) || pixels.length === 0) return "";
|
|
2451
|
+
const firstRow = pixels[0];
|
|
2452
|
+
if (!Array.isArray(firstRow) || firstRow.length === 0) return "";
|
|
2453
|
+
const {
|
|
2454
|
+
width = 80,
|
|
2455
|
+
ramp = "standard",
|
|
2456
|
+
invert = false,
|
|
2457
|
+
dither = "none",
|
|
2458
|
+
edgeDetect = "none",
|
|
2459
|
+
edgeThreshold = 40,
|
|
2460
|
+
color: color2 = false,
|
|
2461
|
+
faceMode = false
|
|
2462
|
+
} = opts;
|
|
2463
|
+
const srcH = pixels.length;
|
|
2464
|
+
const srcW = pixels[0].length;
|
|
2465
|
+
const safeW = Math.max(1, Math.floor(width));
|
|
2466
|
+
const computedH = Math.max(1, Math.round(srcH / srcW * safeW * 0.5));
|
|
2467
|
+
const safeH = opts.height != null ? Math.max(1, Math.floor(opts.height)) : computedH;
|
|
2468
|
+
const resized = _resizePixels(pixels, safeW, safeH);
|
|
2469
|
+
let lum = _toLuminanceGrid(resized);
|
|
2470
|
+
if (faceMode) lum = _enhanceForFace(lum);
|
|
2471
|
+
let edgeGrid = null;
|
|
2472
|
+
if (edgeDetect === "sobel") {
|
|
2473
|
+
edgeGrid = _sobelEdges(resized);
|
|
2474
|
+
}
|
|
2475
|
+
const rampStr = _resolveRamp(ramp);
|
|
2476
|
+
const rampLen = rampStr.length;
|
|
2477
|
+
if (dither === "floyd-steinberg" && !edgeGrid) {
|
|
2478
|
+
lum = _floydSteinberg(lum, rampLen);
|
|
2479
|
+
}
|
|
2480
|
+
const useColor = color2 && !isNoColor();
|
|
2481
|
+
const lines = [];
|
|
2482
|
+
for (let y = 0; y < safeH; y++) {
|
|
2483
|
+
const lumRow = lum[y];
|
|
2484
|
+
const pxRow = resized[y];
|
|
2485
|
+
const edgeRow = edgeGrid ? edgeGrid[y] : null;
|
|
2486
|
+
let line = "";
|
|
2487
|
+
for (let x = 0; x < safeW; x++) {
|
|
2488
|
+
let charIdx;
|
|
2489
|
+
if (edgeRow) {
|
|
2490
|
+
const edge = edgeRow[x];
|
|
2491
|
+
const t = edge >= edgeThreshold ? Math.min(1, edge / 255) : 0;
|
|
2492
|
+
charIdx = invert ? Math.round((1 - t) * (rampLen - 1)) : Math.round(t * (rampLen - 1));
|
|
2493
|
+
} else {
|
|
2494
|
+
const l = lumRow[x] / 255;
|
|
2495
|
+
const tNorm = invert ? 1 - l : l;
|
|
2496
|
+
charIdx = Math.min(rampLen - 1, Math.max(0, Math.round(tNorm * (rampLen - 1))));
|
|
2497
|
+
}
|
|
2498
|
+
const ch = rampStr[charIdx];
|
|
2499
|
+
if (useColor) {
|
|
2500
|
+
const p = pxRow[x];
|
|
2501
|
+
if (p) {
|
|
2502
|
+
line += fgRgb(p.r, p.g, p.b) + ch;
|
|
2503
|
+
} else {
|
|
2504
|
+
line += ch;
|
|
2505
|
+
}
|
|
2506
|
+
} else {
|
|
2507
|
+
line += ch;
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
if (useColor) line += reset();
|
|
2511
|
+
lines.push(line);
|
|
2512
|
+
}
|
|
2513
|
+
return lines.join("\n");
|
|
2514
|
+
};
|
|
2515
|
+
var parseFiglet = (flfContent) => {
|
|
2516
|
+
if (typeof flfContent !== "string" || flfContent.length === 0) {
|
|
2517
|
+
throw new TypeError("parseFiglet: input must be a non-empty string");
|
|
2518
|
+
}
|
|
2519
|
+
const lines = flfContent.split(/\r?\n/);
|
|
2520
|
+
if (lines.length === 0) {
|
|
2521
|
+
throw new TypeError("parseFiglet: empty content");
|
|
2522
|
+
}
|
|
2523
|
+
const header = lines[0];
|
|
2524
|
+
const m = /^flf2.\s*(\S)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(\d+)/.exec(header);
|
|
2525
|
+
if (!m) {
|
|
2526
|
+
throw new TypeError('parseFiglet: invalid FIGfont header (expected "flf2a$..." line)');
|
|
2527
|
+
}
|
|
2528
|
+
const hardblank = m[1];
|
|
2529
|
+
const height = parseInt(m[2], 10);
|
|
2530
|
+
const commentLines = parseInt(m[6], 10);
|
|
2531
|
+
if (!Number.isFinite(height) || height <= 0) {
|
|
2532
|
+
throw new TypeError(`parseFiglet: invalid height ${m[2]}`);
|
|
2533
|
+
}
|
|
2534
|
+
let cursor2 = 1 + Math.max(0, commentLines);
|
|
2535
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
2536
|
+
for (let code = 32; code <= 126; code++) {
|
|
2537
|
+
if (cursor2 + height > lines.length) break;
|
|
2538
|
+
const rows = [];
|
|
2539
|
+
for (let r = 0; r < height; r++) {
|
|
2540
|
+
const raw = lines[cursor2 + r];
|
|
2541
|
+
const endmark = raw.charAt(raw.length - 1);
|
|
2542
|
+
let stripped = raw;
|
|
2543
|
+
while (stripped.length > 0 && stripped.charAt(stripped.length - 1) === endmark) {
|
|
2544
|
+
stripped = stripped.slice(0, -1);
|
|
2545
|
+
}
|
|
2546
|
+
rows.push(stripped);
|
|
2547
|
+
}
|
|
2548
|
+
glyphs.set(code, rows);
|
|
2549
|
+
cursor2 += height;
|
|
2550
|
+
}
|
|
2551
|
+
return { hardblank, height, glyphs };
|
|
2552
|
+
};
|
|
2553
|
+
var figletText = (text, font, opts = {}) => {
|
|
2554
|
+
if (typeof text !== "string") return "";
|
|
2555
|
+
if (!font || !font.glyphs || font.height <= 0) return "";
|
|
2556
|
+
const { trim = true, colorFn = null } = opts;
|
|
2557
|
+
const glyphsForText = [];
|
|
2558
|
+
for (const ch of text) {
|
|
2559
|
+
const code = ch.codePointAt(0) ?? 32;
|
|
2560
|
+
const glyph = font.glyphs.get(code);
|
|
2561
|
+
if (glyph) {
|
|
2562
|
+
glyphsForText.push(glyph);
|
|
2563
|
+
} else {
|
|
2564
|
+
const fallback = font.glyphs.get(32);
|
|
2565
|
+
glyphsForText.push(fallback ?? new Array(font.height).fill(""));
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
const hardblankRe = new RegExp(_escapeRe(font.hardblank), "g");
|
|
2569
|
+
const rows = [];
|
|
2570
|
+
for (let r = 0; r < font.height; r++) {
|
|
2571
|
+
let row = "";
|
|
2572
|
+
for (const g of glyphsForText) {
|
|
2573
|
+
row += g[r] ?? "";
|
|
2574
|
+
}
|
|
2575
|
+
row = row.replace(hardblankRe, " ");
|
|
2576
|
+
rows.push(row);
|
|
2577
|
+
}
|
|
2578
|
+
let result = rows.join("\n");
|
|
2579
|
+
if (trim) {
|
|
2580
|
+
const trimmed = rows.filter((row) => row.trim().length > 0);
|
|
2581
|
+
result = trimmed.length > 0 ? trimmed.join("\n") : rows.join("\n");
|
|
2582
|
+
}
|
|
2583
|
+
if (colorFn) result = colorFn(result);
|
|
2584
|
+
return result;
|
|
2585
|
+
};
|
|
2586
|
+
var _escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2318
2587
|
var ascii = {
|
|
2319
2588
|
big,
|
|
2320
2589
|
small,
|
|
@@ -2325,6 +2594,10 @@ var ascii = {
|
|
|
2325
2594
|
logo,
|
|
2326
2595
|
stream,
|
|
2327
2596
|
measure,
|
|
2597
|
+
// v1.2.5 — Phase 3 closure
|
|
2598
|
+
fromImage,
|
|
2599
|
+
figletText,
|
|
2600
|
+
parseFiglet,
|
|
2328
2601
|
// Pipeline stages — exposed for custom compositions
|
|
2329
2602
|
stageRender,
|
|
2330
2603
|
stageAlign,
|
|
@@ -5296,6 +5569,7 @@ var withConfig = (overrides, fn) => {
|
|
|
5296
5569
|
var ansimax = { color, animate, ascii, loader, frames, components, trees, themes, images, configure };
|
|
5297
5570
|
var index_default = ansimax;
|
|
5298
5571
|
export {
|
|
5572
|
+
ASCII_RAMPS,
|
|
5299
5573
|
BEL,
|
|
5300
5574
|
BG,
|
|
5301
5575
|
DEFAULTS as CONFIG_DEFAULTS,
|
|
@@ -5346,11 +5620,13 @@ export {
|
|
|
5346
5620
|
escapeRegex,
|
|
5347
5621
|
fg256,
|
|
5348
5622
|
fgRgb,
|
|
5623
|
+
figletText,
|
|
5349
5624
|
filterTree,
|
|
5350
5625
|
findInTree,
|
|
5351
5626
|
flipHorizontal,
|
|
5352
5627
|
flipVertical,
|
|
5353
5628
|
frames,
|
|
5629
|
+
fromImage,
|
|
5354
5630
|
getConfig,
|
|
5355
5631
|
getConfigValue,
|
|
5356
5632
|
getRenderCacheSize,
|
|
@@ -5384,8 +5660,10 @@ export {
|
|
|
5384
5660
|
padBoth,
|
|
5385
5661
|
padEnd,
|
|
5386
5662
|
padStart,
|
|
5663
|
+
parseFiglet,
|
|
5387
5664
|
pauseListeners,
|
|
5388
5665
|
presetNames,
|
|
5666
|
+
presets,
|
|
5389
5667
|
rainbow,
|
|
5390
5668
|
registerFont,
|
|
5391
5669
|
registerPreset,
|
|
@@ -5402,6 +5680,7 @@ export {
|
|
|
5402
5680
|
resetLoaderCursorCount,
|
|
5403
5681
|
resetNoColor,
|
|
5404
5682
|
resumeListeners,
|
|
5683
|
+
reverseGradient,
|
|
5405
5684
|
rgbTo256,
|
|
5406
5685
|
rgbToHex,
|
|
5407
5686
|
rotate90,
|
package/examples/all-in-one.cjs
CHANGED
|
@@ -118,7 +118,7 @@ async function main() {
|
|
|
118
118
|
console.log(components.section('🏷️ Badges & Status', { width: 60 }));
|
|
119
119
|
console.log();
|
|
120
120
|
console.log(' ',
|
|
121
|
-
components.badge('VERSION', 'v1.2.
|
|
121
|
+
components.badge('VERSION', 'v1.2.5'),
|
|
122
122
|
components.badge('BUILD', 'passing'),
|
|
123
123
|
components.badge('LICENSE', 'Apache 2.0'));
|
|
124
124
|
console.log();
|
package/examples/all-in-one.mjs
CHANGED
|
@@ -117,7 +117,7 @@ console.log();
|
|
|
117
117
|
console.log(components.section('🏷️ Badges & Status', { width: 60 }));
|
|
118
118
|
console.log();
|
|
119
119
|
console.log(' ',
|
|
120
|
-
components.badge('VERSION', 'v1.2.
|
|
120
|
+
components.badge('VERSION', 'v1.2.5'),
|
|
121
121
|
components.badge('BUILD', 'passing'),
|
|
122
122
|
components.badge('LICENSE', 'Apache 2.0'));
|
|
123
123
|
console.log();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ansimax",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Zero-dependency CLI rendering library: colors, gradients, animations, ASCII art, pixel art, components, and themes \u2014 all in TypeScript.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|