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.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ASCII_RAMPS: () => ASCII_RAMPS,
|
|
33
34
|
BEL: () => BEL,
|
|
34
35
|
BG: () => BG,
|
|
35
36
|
CONFIG_DEFAULTS: () => DEFAULTS,
|
|
@@ -80,11 +81,13 @@ __export(index_exports, {
|
|
|
80
81
|
escapeRegex: () => escapeRegex,
|
|
81
82
|
fg256: () => fg256,
|
|
82
83
|
fgRgb: () => fgRgb,
|
|
84
|
+
figletText: () => figletText,
|
|
83
85
|
filterTree: () => filterTree,
|
|
84
86
|
findInTree: () => findInTree,
|
|
85
87
|
flipHorizontal: () => flipHorizontal,
|
|
86
88
|
flipVertical: () => flipVertical,
|
|
87
89
|
frames: () => frames,
|
|
90
|
+
fromImage: () => fromImage,
|
|
88
91
|
getConfig: () => getConfig,
|
|
89
92
|
getConfigValue: () => getConfigValue,
|
|
90
93
|
getRenderCacheSize: () => getRenderCacheSize,
|
|
@@ -118,8 +121,10 @@ __export(index_exports, {
|
|
|
118
121
|
padBoth: () => padBoth,
|
|
119
122
|
padEnd: () => padEnd,
|
|
120
123
|
padStart: () => padStart,
|
|
124
|
+
parseFiglet: () => parseFiglet,
|
|
121
125
|
pauseListeners: () => pauseListeners,
|
|
122
126
|
presetNames: () => presetNames,
|
|
127
|
+
presets: () => presets,
|
|
123
128
|
rainbow: () => rainbow,
|
|
124
129
|
registerFont: () => registerFont,
|
|
125
130
|
registerPreset: () => registerPreset,
|
|
@@ -136,6 +141,7 @@ __export(index_exports, {
|
|
|
136
141
|
resetLoaderCursorCount: () => resetLoaderCursorCount,
|
|
137
142
|
resetNoColor: () => resetNoColor,
|
|
138
143
|
resumeListeners: () => resumeListeners,
|
|
144
|
+
reverseGradient: () => reverseGradient,
|
|
139
145
|
rgbTo256: () => rgbTo256,
|
|
140
146
|
rgbToHex: () => rgbToHex,
|
|
141
147
|
rotate90: () => rotate90,
|
|
@@ -1167,10 +1173,11 @@ var gradient = (text, stops, opts = {}) => {
|
|
|
1167
1173
|
return _gradientAnsiAware(s, colors, easingFn, phaseN);
|
|
1168
1174
|
};
|
|
1169
1175
|
var createGradient = (stops, defaultOpts = {}) => {
|
|
1170
|
-
const
|
|
1176
|
+
const originalStops = Array.isArray(stops) ? [...stops] : [];
|
|
1177
|
+
const colors = originalStops.map(safeHex).filter((c) => c !== null);
|
|
1171
1178
|
const defaultEasingFn = resolveEasing(defaultOpts.easing);
|
|
1172
1179
|
const defaultPreserveAnsi = defaultOpts.preserveAnsi ?? false;
|
|
1173
|
-
|
|
1180
|
+
const fn = ((text, opts = {}) => {
|
|
1174
1181
|
const s = coerceText(text);
|
|
1175
1182
|
if (!s || isNoColor()) return s;
|
|
1176
1183
|
if (colors.length === 0) return s;
|
|
@@ -1186,8 +1193,31 @@ var createGradient = (stops, defaultOpts = {}) => {
|
|
|
1186
1193
|
return _gradientPlain(s, colors, easingFn, phaseN);
|
|
1187
1194
|
}
|
|
1188
1195
|
return _gradientAnsiAware(s, colors, easingFn, phaseN);
|
|
1189
|
-
};
|
|
1196
|
+
});
|
|
1197
|
+
Object.defineProperty(fn, "stops", {
|
|
1198
|
+
value: Object.freeze(originalStops),
|
|
1199
|
+
enumerable: true,
|
|
1200
|
+
writable: false
|
|
1201
|
+
});
|
|
1202
|
+
Object.defineProperty(fn, "resolvedStops", {
|
|
1203
|
+
value: Object.freeze(colors.map((c) => Object.freeze({ ...c }))),
|
|
1204
|
+
enumerable: true,
|
|
1205
|
+
writable: false
|
|
1206
|
+
});
|
|
1207
|
+
Object.defineProperty(fn, "defaultOptions", {
|
|
1208
|
+
value: Object.freeze({ ...defaultOpts }),
|
|
1209
|
+
enumerable: true,
|
|
1210
|
+
writable: false
|
|
1211
|
+
});
|
|
1212
|
+
return fn;
|
|
1190
1213
|
};
|
|
1214
|
+
function reverseGradient(input) {
|
|
1215
|
+
if (Array.isArray(input)) {
|
|
1216
|
+
return [...input].reverse();
|
|
1217
|
+
}
|
|
1218
|
+
const reversedStops = [...input.stops].reverse();
|
|
1219
|
+
return createGradient(reversedStops, input.defaultOptions);
|
|
1220
|
+
}
|
|
1191
1221
|
var _gradientPlain = (text, colors, easingFn, phase) => {
|
|
1192
1222
|
const chars = [...text];
|
|
1193
1223
|
const visible = chars.filter((c) => c !== " ").length;
|
|
@@ -2489,6 +2519,251 @@ var stream = async function* (text, opts = {}) {
|
|
|
2489
2519
|
yield i === lines.length - 1 ? line : line + "\n";
|
|
2490
2520
|
}
|
|
2491
2521
|
};
|
|
2522
|
+
var ASCII_RAMPS = {
|
|
2523
|
+
standard: " .:-=+*#%@",
|
|
2524
|
+
detailed: " .'`^\",:;Il!i><~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$",
|
|
2525
|
+
blocks: " \u2591\u2592\u2593\u2588",
|
|
2526
|
+
simple: " .+#"
|
|
2527
|
+
};
|
|
2528
|
+
var _resolveRamp = (r) => {
|
|
2529
|
+
if (typeof r === "string" && r.length > 0) {
|
|
2530
|
+
if (r in ASCII_RAMPS) return ASCII_RAMPS[r];
|
|
2531
|
+
return r;
|
|
2532
|
+
}
|
|
2533
|
+
return ASCII_RAMPS.standard;
|
|
2534
|
+
};
|
|
2535
|
+
var _luminance = (p) => {
|
|
2536
|
+
if (!p) return 0;
|
|
2537
|
+
return 0.2126 * p.r + 0.7152 * p.g + 0.0722 * p.b;
|
|
2538
|
+
};
|
|
2539
|
+
var _sobelEdges = (pixels) => {
|
|
2540
|
+
const h = pixels.length;
|
|
2541
|
+
const w = h > 0 ? pixels[0].length : 0;
|
|
2542
|
+
const out = Array.from({ length: h }, () => new Array(w).fill(0));
|
|
2543
|
+
for (let y = 1; y < h - 1; y++) {
|
|
2544
|
+
const rowPrev = pixels[y - 1];
|
|
2545
|
+
const row = pixels[y];
|
|
2546
|
+
const rowNext = pixels[y + 1];
|
|
2547
|
+
const outRow = out[y];
|
|
2548
|
+
for (let x = 1; x < w - 1; x++) {
|
|
2549
|
+
const tl = _luminance(rowPrev[x - 1]);
|
|
2550
|
+
const t = _luminance(rowPrev[x]);
|
|
2551
|
+
const tr = _luminance(rowPrev[x + 1]);
|
|
2552
|
+
const l = _luminance(row[x - 1]);
|
|
2553
|
+
const r = _luminance(row[x + 1]);
|
|
2554
|
+
const bl = _luminance(rowNext[x - 1]);
|
|
2555
|
+
const b = _luminance(rowNext[x]);
|
|
2556
|
+
const br = _luminance(rowNext[x + 1]);
|
|
2557
|
+
const gx = -tl + tr - 2 * l + 2 * r - bl + br;
|
|
2558
|
+
const gy = -tl - 2 * t - tr + bl + 2 * b + br;
|
|
2559
|
+
const mag = Math.sqrt(gx * gx + gy * gy);
|
|
2560
|
+
outRow[x] = Math.min(255, mag);
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
return out;
|
|
2564
|
+
};
|
|
2565
|
+
var _floydSteinberg = (lum, levels) => {
|
|
2566
|
+
const h = lum.length;
|
|
2567
|
+
if (h === 0) return lum;
|
|
2568
|
+
const w = lum[0].length;
|
|
2569
|
+
if (w === 0) return lum;
|
|
2570
|
+
const out = lum.map((row) => [...row]);
|
|
2571
|
+
const step = 255 / Math.max(1, levels - 1);
|
|
2572
|
+
for (let y = 0; y < h; y++) {
|
|
2573
|
+
const row = out[y];
|
|
2574
|
+
for (let x = 0; x < w; x++) {
|
|
2575
|
+
const oldPixel = row[x];
|
|
2576
|
+
const quantLevel = Math.round(oldPixel / step);
|
|
2577
|
+
const newPixel = quantLevel * step;
|
|
2578
|
+
row[x] = newPixel;
|
|
2579
|
+
const err = oldPixel - newPixel;
|
|
2580
|
+
if (x + 1 < w) {
|
|
2581
|
+
row[x + 1] = row[x + 1] + err * 7 / 16;
|
|
2582
|
+
}
|
|
2583
|
+
if (y + 1 < h) {
|
|
2584
|
+
const next = out[y + 1];
|
|
2585
|
+
if (x > 0) next[x - 1] = next[x - 1] + err * 3 / 16;
|
|
2586
|
+
next[x] = next[x] + err * 5 / 16;
|
|
2587
|
+
if (x + 1 < w) next[x + 1] = next[x + 1] + err * 1 / 16;
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
return out;
|
|
2592
|
+
};
|
|
2593
|
+
var _resizePixels = (pixels, targetW, targetH) => {
|
|
2594
|
+
const srcH = pixels.length;
|
|
2595
|
+
if (srcH === 0) return [];
|
|
2596
|
+
const srcW = pixels[0].length;
|
|
2597
|
+
if (srcW === 0) return [];
|
|
2598
|
+
const out = [];
|
|
2599
|
+
for (let y = 0; y < targetH; y++) {
|
|
2600
|
+
const sy = Math.min(srcH - 1, Math.floor(y / targetH * srcH));
|
|
2601
|
+
const srcRow = pixels[sy];
|
|
2602
|
+
const newRow = new Array(targetW);
|
|
2603
|
+
for (let x = 0; x < targetW; x++) {
|
|
2604
|
+
const sx = Math.min(srcW - 1, Math.floor(x / targetW * srcW));
|
|
2605
|
+
newRow[x] = srcRow[sx];
|
|
2606
|
+
}
|
|
2607
|
+
out.push(newRow);
|
|
2608
|
+
}
|
|
2609
|
+
return out;
|
|
2610
|
+
};
|
|
2611
|
+
var _toLuminanceGrid = (pixels) => {
|
|
2612
|
+
return pixels.map((row) => row.map((p) => _luminance(p)));
|
|
2613
|
+
};
|
|
2614
|
+
var _enhanceForFace = (lum) => {
|
|
2615
|
+
const flat = [];
|
|
2616
|
+
for (const row of lum) for (const v of row) flat.push(v);
|
|
2617
|
+
if (flat.length === 0) return lum;
|
|
2618
|
+
flat.sort((a, b) => a - b);
|
|
2619
|
+
const lo = flat[Math.floor(flat.length * 0.1)];
|
|
2620
|
+
const hi = flat[Math.floor(flat.length * 0.9)];
|
|
2621
|
+
const range = Math.max(1, hi - lo);
|
|
2622
|
+
return lum.map(
|
|
2623
|
+
(row) => row.map((v) => {
|
|
2624
|
+
const stretched = (v - lo) / range * 255;
|
|
2625
|
+
return Math.max(0, Math.min(255, stretched));
|
|
2626
|
+
})
|
|
2627
|
+
);
|
|
2628
|
+
};
|
|
2629
|
+
var fromImage = (pixels, opts = {}) => {
|
|
2630
|
+
if (!Array.isArray(pixels) || pixels.length === 0) return "";
|
|
2631
|
+
const firstRow = pixels[0];
|
|
2632
|
+
if (!Array.isArray(firstRow) || firstRow.length === 0) return "";
|
|
2633
|
+
const {
|
|
2634
|
+
width = 80,
|
|
2635
|
+
ramp = "standard",
|
|
2636
|
+
invert = false,
|
|
2637
|
+
dither = "none",
|
|
2638
|
+
edgeDetect = "none",
|
|
2639
|
+
edgeThreshold = 40,
|
|
2640
|
+
color: color2 = false,
|
|
2641
|
+
faceMode = false
|
|
2642
|
+
} = opts;
|
|
2643
|
+
const srcH = pixels.length;
|
|
2644
|
+
const srcW = pixels[0].length;
|
|
2645
|
+
const safeW = Math.max(1, Math.floor(width));
|
|
2646
|
+
const computedH = Math.max(1, Math.round(srcH / srcW * safeW * 0.5));
|
|
2647
|
+
const safeH = opts.height != null ? Math.max(1, Math.floor(opts.height)) : computedH;
|
|
2648
|
+
const resized = _resizePixels(pixels, safeW, safeH);
|
|
2649
|
+
let lum = _toLuminanceGrid(resized);
|
|
2650
|
+
if (faceMode) lum = _enhanceForFace(lum);
|
|
2651
|
+
let edgeGrid = null;
|
|
2652
|
+
if (edgeDetect === "sobel") {
|
|
2653
|
+
edgeGrid = _sobelEdges(resized);
|
|
2654
|
+
}
|
|
2655
|
+
const rampStr = _resolveRamp(ramp);
|
|
2656
|
+
const rampLen = rampStr.length;
|
|
2657
|
+
if (dither === "floyd-steinberg" && !edgeGrid) {
|
|
2658
|
+
lum = _floydSteinberg(lum, rampLen);
|
|
2659
|
+
}
|
|
2660
|
+
const useColor = color2 && !isNoColor();
|
|
2661
|
+
const lines = [];
|
|
2662
|
+
for (let y = 0; y < safeH; y++) {
|
|
2663
|
+
const lumRow = lum[y];
|
|
2664
|
+
const pxRow = resized[y];
|
|
2665
|
+
const edgeRow = edgeGrid ? edgeGrid[y] : null;
|
|
2666
|
+
let line = "";
|
|
2667
|
+
for (let x = 0; x < safeW; x++) {
|
|
2668
|
+
let charIdx;
|
|
2669
|
+
if (edgeRow) {
|
|
2670
|
+
const edge = edgeRow[x];
|
|
2671
|
+
const t = edge >= edgeThreshold ? Math.min(1, edge / 255) : 0;
|
|
2672
|
+
charIdx = invert ? Math.round((1 - t) * (rampLen - 1)) : Math.round(t * (rampLen - 1));
|
|
2673
|
+
} else {
|
|
2674
|
+
const l = lumRow[x] / 255;
|
|
2675
|
+
const tNorm = invert ? 1 - l : l;
|
|
2676
|
+
charIdx = Math.min(rampLen - 1, Math.max(0, Math.round(tNorm * (rampLen - 1))));
|
|
2677
|
+
}
|
|
2678
|
+
const ch = rampStr[charIdx];
|
|
2679
|
+
if (useColor) {
|
|
2680
|
+
const p = pxRow[x];
|
|
2681
|
+
if (p) {
|
|
2682
|
+
line += fgRgb(p.r, p.g, p.b) + ch;
|
|
2683
|
+
} else {
|
|
2684
|
+
line += ch;
|
|
2685
|
+
}
|
|
2686
|
+
} else {
|
|
2687
|
+
line += ch;
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
if (useColor) line += reset();
|
|
2691
|
+
lines.push(line);
|
|
2692
|
+
}
|
|
2693
|
+
return lines.join("\n");
|
|
2694
|
+
};
|
|
2695
|
+
var parseFiglet = (flfContent) => {
|
|
2696
|
+
if (typeof flfContent !== "string" || flfContent.length === 0) {
|
|
2697
|
+
throw new TypeError("parseFiglet: input must be a non-empty string");
|
|
2698
|
+
}
|
|
2699
|
+
const lines = flfContent.split(/\r?\n/);
|
|
2700
|
+
if (lines.length === 0) {
|
|
2701
|
+
throw new TypeError("parseFiglet: empty content");
|
|
2702
|
+
}
|
|
2703
|
+
const header = lines[0];
|
|
2704
|
+
const m = /^flf2.\s*(\S)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(\d+)/.exec(header);
|
|
2705
|
+
if (!m) {
|
|
2706
|
+
throw new TypeError('parseFiglet: invalid FIGfont header (expected "flf2a$..." line)');
|
|
2707
|
+
}
|
|
2708
|
+
const hardblank = m[1];
|
|
2709
|
+
const height = parseInt(m[2], 10);
|
|
2710
|
+
const commentLines = parseInt(m[6], 10);
|
|
2711
|
+
if (!Number.isFinite(height) || height <= 0) {
|
|
2712
|
+
throw new TypeError(`parseFiglet: invalid height ${m[2]}`);
|
|
2713
|
+
}
|
|
2714
|
+
let cursor2 = 1 + Math.max(0, commentLines);
|
|
2715
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
2716
|
+
for (let code = 32; code <= 126; code++) {
|
|
2717
|
+
if (cursor2 + height > lines.length) break;
|
|
2718
|
+
const rows = [];
|
|
2719
|
+
for (let r = 0; r < height; r++) {
|
|
2720
|
+
const raw = lines[cursor2 + r];
|
|
2721
|
+
const endmark = raw.charAt(raw.length - 1);
|
|
2722
|
+
let stripped = raw;
|
|
2723
|
+
while (stripped.length > 0 && stripped.charAt(stripped.length - 1) === endmark) {
|
|
2724
|
+
stripped = stripped.slice(0, -1);
|
|
2725
|
+
}
|
|
2726
|
+
rows.push(stripped);
|
|
2727
|
+
}
|
|
2728
|
+
glyphs.set(code, rows);
|
|
2729
|
+
cursor2 += height;
|
|
2730
|
+
}
|
|
2731
|
+
return { hardblank, height, glyphs };
|
|
2732
|
+
};
|
|
2733
|
+
var figletText = (text, font, opts = {}) => {
|
|
2734
|
+
if (typeof text !== "string") return "";
|
|
2735
|
+
if (!font || !font.glyphs || font.height <= 0) return "";
|
|
2736
|
+
const { trim = true, colorFn = null } = opts;
|
|
2737
|
+
const glyphsForText = [];
|
|
2738
|
+
for (const ch of text) {
|
|
2739
|
+
const code = ch.codePointAt(0) ?? 32;
|
|
2740
|
+
const glyph = font.glyphs.get(code);
|
|
2741
|
+
if (glyph) {
|
|
2742
|
+
glyphsForText.push(glyph);
|
|
2743
|
+
} else {
|
|
2744
|
+
const fallback = font.glyphs.get(32);
|
|
2745
|
+
glyphsForText.push(fallback ?? new Array(font.height).fill(""));
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
const hardblankRe = new RegExp(_escapeRe(font.hardblank), "g");
|
|
2749
|
+
const rows = [];
|
|
2750
|
+
for (let r = 0; r < font.height; r++) {
|
|
2751
|
+
let row = "";
|
|
2752
|
+
for (const g of glyphsForText) {
|
|
2753
|
+
row += g[r] ?? "";
|
|
2754
|
+
}
|
|
2755
|
+
row = row.replace(hardblankRe, " ");
|
|
2756
|
+
rows.push(row);
|
|
2757
|
+
}
|
|
2758
|
+
let result = rows.join("\n");
|
|
2759
|
+
if (trim) {
|
|
2760
|
+
const trimmed = rows.filter((row) => row.trim().length > 0);
|
|
2761
|
+
result = trimmed.length > 0 ? trimmed.join("\n") : rows.join("\n");
|
|
2762
|
+
}
|
|
2763
|
+
if (colorFn) result = colorFn(result);
|
|
2764
|
+
return result;
|
|
2765
|
+
};
|
|
2766
|
+
var _escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2492
2767
|
var ascii = {
|
|
2493
2768
|
big,
|
|
2494
2769
|
small,
|
|
@@ -2499,6 +2774,10 @@ var ascii = {
|
|
|
2499
2774
|
logo,
|
|
2500
2775
|
stream,
|
|
2501
2776
|
measure,
|
|
2777
|
+
// v1.2.5 — Phase 3 closure
|
|
2778
|
+
fromImage,
|
|
2779
|
+
figletText,
|
|
2780
|
+
parseFiglet,
|
|
2502
2781
|
// Pipeline stages — exposed for custom compositions
|
|
2503
2782
|
stageRender,
|
|
2504
2783
|
stageAlign,
|
|
@@ -5471,6 +5750,7 @@ var ansimax = { color, animate, ascii, loader, frames, components, trees, themes
|
|
|
5471
5750
|
var index_default = ansimax;
|
|
5472
5751
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5473
5752
|
0 && (module.exports = {
|
|
5753
|
+
ASCII_RAMPS,
|
|
5474
5754
|
BEL,
|
|
5475
5755
|
BG,
|
|
5476
5756
|
CONFIG_DEFAULTS,
|
|
@@ -5520,11 +5800,13 @@ var index_default = ansimax;
|
|
|
5520
5800
|
escapeRegex,
|
|
5521
5801
|
fg256,
|
|
5522
5802
|
fgRgb,
|
|
5803
|
+
figletText,
|
|
5523
5804
|
filterTree,
|
|
5524
5805
|
findInTree,
|
|
5525
5806
|
flipHorizontal,
|
|
5526
5807
|
flipVertical,
|
|
5527
5808
|
frames,
|
|
5809
|
+
fromImage,
|
|
5528
5810
|
getConfig,
|
|
5529
5811
|
getConfigValue,
|
|
5530
5812
|
getRenderCacheSize,
|
|
@@ -5558,8 +5840,10 @@ var index_default = ansimax;
|
|
|
5558
5840
|
padBoth,
|
|
5559
5841
|
padEnd,
|
|
5560
5842
|
padStart,
|
|
5843
|
+
parseFiglet,
|
|
5561
5844
|
pauseListeners,
|
|
5562
5845
|
presetNames,
|
|
5846
|
+
presets,
|
|
5563
5847
|
rainbow,
|
|
5564
5848
|
registerFont,
|
|
5565
5849
|
registerPreset,
|
|
@@ -5576,6 +5860,7 @@ var index_default = ansimax;
|
|
|
5576
5860
|
resetLoaderCursorCount,
|
|
5577
5861
|
resetNoColor,
|
|
5578
5862
|
resumeListeners,
|
|
5863
|
+
reverseGradient,
|
|
5579
5864
|
rgbTo256,
|
|
5580
5865
|
rgbToHex,
|
|
5581
5866
|
rotate90,
|