ansimax 1.3.2 → 1.3.4
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 +282 -0
- package/README.es.md +93 -11
- package/README.md +93 -11
- package/dist/index.d.mts +452 -196
- package/dist/index.d.ts +452 -196
- package/dist/index.js +396 -46
- package/dist/index.mjs +388 -46
- package/examples/all-in-one.cjs +1 -1
- package/examples/all-in-one.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,288 @@
|
|
|
3
3
|
All notable changes to **ansimax** are documented in this file.
|
|
4
4
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [1.3.4] — Feature additions across animations, configure, utils
|
|
7
|
+
|
|
8
|
+
Patch release adding small but useful features to several modules. No
|
|
9
|
+
breaking changes — every addition is opt-in.
|
|
10
|
+
|
|
11
|
+
### Added — `animations` module
|
|
12
|
+
|
|
13
|
+
**`animate.shake(text, opts)`** — horizontal tremble effect for errors or alerts:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import { animate } from 'ansimax';
|
|
17
|
+
|
|
18
|
+
await animate.shake('Connection failed', {
|
|
19
|
+
times: 5,
|
|
20
|
+
intensity: 2,
|
|
21
|
+
interval: 50,
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**`animate.countUp(from, to, opts)`** — numeric animation for counters:
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
await animate.countUp(0, 100, {
|
|
29
|
+
duration: 1500,
|
|
30
|
+
decimals: 0,
|
|
31
|
+
format: (n) => `$${n.toLocaleString()}`,
|
|
32
|
+
easing: (t) => 1 - (1 - t) ** 3, // ease-out cubic
|
|
33
|
+
});
|
|
34
|
+
// Animates from "$0" → "$100" over 1.5 seconds
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Both functions support the standard animation pattern: `signal`, `reducedMotion`,
|
|
38
|
+
`onFrame`, `onDone`, `onAbort`.
|
|
39
|
+
|
|
40
|
+
### Added — `configure` module
|
|
41
|
+
|
|
42
|
+
**`setConfigValue(key, value)`** — single-key shortcut:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import { setConfigValue } from 'ansimax';
|
|
46
|
+
|
|
47
|
+
setConfigValue('theme', 'dracula');
|
|
48
|
+
setConfigValue('animationSpeed', 'fast');
|
|
49
|
+
// equivalent to: configure({ theme: 'dracula' })
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**`subscribeConfig(listener)`** — alias for `onConfigChange` matching the
|
|
53
|
+
naming convention used by `themes.onChange`:
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
import { subscribeConfig } from 'ansimax';
|
|
57
|
+
|
|
58
|
+
const unsubscribe = subscribeConfig((newCfg, oldCfg) => {
|
|
59
|
+
console.log('Config changed:', newCfg);
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Added — `utils/ansi` module
|
|
64
|
+
|
|
65
|
+
**`hyperlink(url, label?)`** — OSC 8 escape sequence for clickable terminal links:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
import { hyperlink } from 'ansimax';
|
|
69
|
+
|
|
70
|
+
console.log(`Visit ${hyperlink('https://github.com/Brashkie/ansimax', 'the repo')}`);
|
|
71
|
+
console.log(`Email: ${hyperlink('mailto:hi@example.com')}`);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Supported terminals: VS Code, iTerm2, WezTerm, Kitty, Hyper, Alacritty, modern
|
|
75
|
+
Windows Terminal. Terminals without support just show the label text.
|
|
76
|
+
|
|
77
|
+
**`clearLine()`** — convenience for clearing current line + carriage return:
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
import { clearLine } from 'ansimax';
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i <= 100; i++) {
|
|
83
|
+
process.stdout.write(clearLine() + `Progress: ${i}%`);
|
|
84
|
+
await sleep(30);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Added — `utils/helpers` module
|
|
89
|
+
|
|
90
|
+
**`gradientStops(start, end, count)`** — interpolate N hex stops between two colors:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
import { gradientStops } from 'ansimax';
|
|
94
|
+
|
|
95
|
+
const stops = gradientStops('#ff0000', '#0000ff', 5);
|
|
96
|
+
// → ['#ff0000', '#bf003f', '#7f007f', '#3f00bf', '#0000ff']
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**`escapeForRegex(str)`** — escape regex meta-characters in user input:
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
import { escapeForRegex } from 'ansimax';
|
|
103
|
+
|
|
104
|
+
const userInput = 'hello.world+code';
|
|
105
|
+
const re = new RegExp(escapeForRegex(userInput));
|
|
106
|
+
// Matches the literal string, not as a regex pattern
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**`measureBlock(block)`** — get dimensions of a multi-line string (ANSI-aware):
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
import { measureBlock, ascii } from 'ansimax';
|
|
113
|
+
|
|
114
|
+
const box = ascii.box('Hello world!');
|
|
115
|
+
const { width, height } = measureBlock(box);
|
|
116
|
+
// → { width: 15, height: 3 }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Improved — `node-globals.d.ts`
|
|
120
|
+
|
|
121
|
+
Added ambient declarations for `AsyncIterator`, `AsyncIterable`, `AsyncGenerator`,
|
|
122
|
+
and `Symbol.asyncIterator`. Lets code using `for await...of` type-check without
|
|
123
|
+
needing `@types/node` installed at consumer projects.
|
|
124
|
+
|
|
125
|
+
### Improved — Tests
|
|
126
|
+
|
|
127
|
+
- `+6` tests for `gradientStops`
|
|
128
|
+
- `+5` tests for `escapeForRegex`
|
|
129
|
+
- `+7` tests for `measureBlock`
|
|
130
|
+
- `+5` tests for `hyperlink`
|
|
131
|
+
- `+2` tests for `clearLine`
|
|
132
|
+
- `+4` tests for `setConfigValue`
|
|
133
|
+
- `+3` tests for `subscribeConfig`
|
|
134
|
+
- `+5` tests for `animate.shake`
|
|
135
|
+
- `+8` tests for `animate.countUp`
|
|
136
|
+
|
|
137
|
+
Total: **+45 tests** across utils, ansi, configure, animations.
|
|
138
|
+
|
|
139
|
+
### Notes
|
|
140
|
+
|
|
141
|
+
- No runtime dependencies — still zero
|
|
142
|
+
- No breaking changes — drop-in replacement for `1.3.3`
|
|
143
|
+
- All new exports backward-compatible by default
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## [1.3.3] — Feature additions to panels, json, ascii
|
|
148
|
+
|
|
149
|
+
Patch release adding new functionality to three modules. No breaking changes —
|
|
150
|
+
all additions are opt-in via new options/exports.
|
|
151
|
+
|
|
152
|
+
### Added — `panels.grid(blocks, opts)`
|
|
153
|
+
|
|
154
|
+
N-column grid layout with auto-flow (reading order). Each row auto-sizes to
|
|
155
|
+
the tallest block; each column auto-sizes to its widest member.
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
import { panels, ascii } from 'ansimax';
|
|
159
|
+
|
|
160
|
+
const cards = [
|
|
161
|
+
ascii.box('FILES\n42', { padding: 1 }),
|
|
162
|
+
ascii.box('LINES\n1247', { padding: 1 }),
|
|
163
|
+
ascii.box('TESTS\n38', { padding: 1 }),
|
|
164
|
+
ascii.box('COV\n98%', { padding: 1 }),
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
// 2×2 grid
|
|
168
|
+
console.log(panels.grid(cards, { columns: 2, gapX: 2, gapY: 1 }));
|
|
169
|
+
|
|
170
|
+
// 3-column with auto-flow (7 items → 3 rows: [3, 3, 1])
|
|
171
|
+
console.log(panels.grid(items, { columns: 3, gapX: 4 }));
|
|
172
|
+
|
|
173
|
+
// Fixed cell width for uniform appearance
|
|
174
|
+
console.log(panels.grid(blocks, {
|
|
175
|
+
columns: 4,
|
|
176
|
+
cellWidth: 15,
|
|
177
|
+
alignX: 'center',
|
|
178
|
+
}));
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Options: `columns` (required), `gapX`, `gapY`, `alignX`, `alignY`, `cellWidth`.
|
|
182
|
+
|
|
183
|
+
### Added — `panels.frame` option `titleAlign`
|
|
184
|
+
|
|
185
|
+
Frame titles can now be aligned `'left'`, `'center'` (default), or `'right'`.
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
panels.frame('Body', { title: 'Section', titleAlign: 'left' });
|
|
189
|
+
// ─ Section ───────────
|
|
190
|
+
//
|
|
191
|
+
// Body
|
|
192
|
+
// ────────────────────
|
|
193
|
+
|
|
194
|
+
panels.frame('Body', { title: 'Section', titleAlign: 'right' });
|
|
195
|
+
// ─────────── Section ─
|
|
196
|
+
//
|
|
197
|
+
// Body
|
|
198
|
+
// ────────────────────
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Added — `ascii.box` options `title` + `titleAlign`
|
|
202
|
+
|
|
203
|
+
Boxes can now have a title in the top border. When the title is wider than the
|
|
204
|
+
content, the box expands to fit it.
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
console.log(ascii.box('Body content', {
|
|
208
|
+
title: 'Header',
|
|
209
|
+
titleAlign: 'left', // 'left' | 'center' (default) | 'right'
|
|
210
|
+
borderStyle: 'rounded',
|
|
211
|
+
}));
|
|
212
|
+
|
|
213
|
+
// ╭─ Header ──────╮
|
|
214
|
+
// │ Body content │
|
|
215
|
+
// ╰───────────────╯
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Added — `ascii.divider` option `align`
|
|
219
|
+
|
|
220
|
+
Divider labels can now be aligned similar to box titles.
|
|
221
|
+
|
|
222
|
+
```js
|
|
223
|
+
ascii.divider({ label: 'Section', align: 'left', width: 40 });
|
|
224
|
+
// ─ Section ──────────────────────────────
|
|
225
|
+
ascii.divider({ label: 'Section', align: 'center', width: 40 });
|
|
226
|
+
// ─────────────── Section ────────────────
|
|
227
|
+
ascii.divider({ label: 'Section', align: 'right', width: 40 });
|
|
228
|
+
// ────────────────────────────── Section ─
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Added — `json.pretty` native types support: `Map`, `Set`, `Date`
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
import { json } from 'ansimax';
|
|
235
|
+
|
|
236
|
+
const data = {
|
|
237
|
+
created: new Date('2026-06-13'),
|
|
238
|
+
cache: new Map([['user1', 'Alice'], ['user2', 'Bob']]),
|
|
239
|
+
tags: new Set(['frontend', 'react']),
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
console.log(json.pretty(data));
|
|
243
|
+
// {
|
|
244
|
+
// "created": Date(2026-06-13T00:00:00.000Z),
|
|
245
|
+
// "cache": Map(2) [...],
|
|
246
|
+
// "tags": Set(2) ["frontend", "react"]
|
|
247
|
+
// }
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Added — `json.pretty` option `mode: 'json'`
|
|
251
|
+
|
|
252
|
+
Produces **strict, parseable JSON** instead of display-only output. Useful
|
|
253
|
+
for piping to files, scripts, or other tools.
|
|
254
|
+
|
|
255
|
+
```js
|
|
256
|
+
const out = json.pretty(myData, { mode: 'json' });
|
|
257
|
+
const parsed = JSON.parse(out); // ✓ works
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
In `'json'` mode:
|
|
261
|
+
- Colors are forced off (output is always plain text)
|
|
262
|
+
- `undefined` / functions / symbols are dropped from objects, become `null` in arrays
|
|
263
|
+
- `NaN` / `Infinity` / `-Infinity` become `null`
|
|
264
|
+
- `BigInt` becomes a number (if safe) or a string (if out of safe range)
|
|
265
|
+
- `Date` becomes its ISO string
|
|
266
|
+
- `Map` becomes a plain object (string-keys only)
|
|
267
|
+
- `Set` becomes an array
|
|
268
|
+
- Circular references throw `TypeError` (matches `JSON.stringify` behavior)
|
|
269
|
+
|
|
270
|
+
Default `'display'` mode preserves all v1.3.2 behavior. **No breaking changes.**
|
|
271
|
+
|
|
272
|
+
### Improved — Tests
|
|
273
|
+
|
|
274
|
+
- `+8` tests for `panels.grid`
|
|
275
|
+
- `+3` tests for `panels.frame` titleAlign
|
|
276
|
+
- `+5` tests for `ascii.box` title/titleAlign
|
|
277
|
+
- `+4` tests for `ascii.divider` align
|
|
278
|
+
- `+18` tests for `json` Map/Set/Date/mode
|
|
279
|
+
|
|
280
|
+
### Notes
|
|
281
|
+
|
|
282
|
+
- No runtime dependencies — still zero
|
|
283
|
+
- No breaking changes — drop-in replacement for `1.3.2`
|
|
284
|
+
- All new options have backward-compatible defaults
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
6
288
|
## [1.3.2] — Documentation polish for frames + images
|
|
7
289
|
|
|
8
290
|
Patch release improving JSDoc + IntelliSense coverage for the two largest
|
package/README.es.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
_Colores • Gradientes • Animaciones • ASCII Art • Pixel Art • Árboles • Componentes • Temas_
|
|
8
8
|
|
|
9
9
|
[](LICENSE)
|
|
10
|
-
[](https://www.npmjs.com/package/ansimax)
|
|
11
11
|
[](tsconfig.json)
|
|
12
12
|
[](#testing)
|
|
13
13
|
[](#testing)
|
|
@@ -215,7 +215,7 @@ console.log(rainbow('preset rainbow integrado'));
|
|
|
215
215
|
|
|
216
216
|
### Gradientes animados (v1.2.0)
|
|
217
217
|
|
|
218
|
-
<img src="media/
|
|
218
|
+
<img src="media/animated-gradients.gif" alt="Vista previa de gradientes animados" />
|
|
219
219
|
|
|
220
220
|
```js
|
|
221
221
|
import { animateGradient, sleep } from 'ansimax';
|
|
@@ -275,7 +275,7 @@ console.log(gradientRect({
|
|
|
275
275
|
|
|
276
276
|
### Gradientes reusables (v1.2.3)
|
|
277
277
|
|
|
278
|
-
<img src="media/
|
|
278
|
+
<img src="media/reusable-gradients.gif" alt="Vista previa de gradientes reusables" />
|
|
279
279
|
|
|
280
280
|
```js
|
|
281
281
|
import { createGradient, reverseGradient, ascii } from 'ansimax';
|
|
@@ -323,7 +323,32 @@ console.log(ascii.box('¡Caja arcoiris!', { padding: 1, borderStyle: 'rounded' }
|
|
|
323
323
|
|
|
324
324
|
### Imagen → ASCII (v1.2.5)
|
|
325
325
|
|
|
326
|
-
<
|
|
326
|
+
<div align="center">
|
|
327
|
+
<img src="media/image-ascii-original.png" alt="Foto original" width="40%" />
|
|
328
|
+
</div>
|
|
329
|
+
|
|
330
|
+
<table>
|
|
331
|
+
<tr>
|
|
332
|
+
<td align="center">
|
|
333
|
+
<img src="media/image-ascii-1.png" alt="Modo monocromo" /><br/>
|
|
334
|
+
<sub><b>1. Monocromo</b></sub>
|
|
335
|
+
</td>
|
|
336
|
+
<td align="center">
|
|
337
|
+
<img src="media/image-ascii-2.png" alt="Color + dithering Floyd-Steinberg" /><br/>
|
|
338
|
+
<sub><b>2. Color + Floyd-Steinberg</b></sub>
|
|
339
|
+
</td>
|
|
340
|
+
</tr>
|
|
341
|
+
<tr>
|
|
342
|
+
<td align="center">
|
|
343
|
+
<img src="media/image-ascii-3.png" alt="Detección de bordes (Sobel)" /><br/>
|
|
344
|
+
<sub><b>3. Detección de bordes (Sobel)</b></sub>
|
|
345
|
+
</td>
|
|
346
|
+
<td align="center">
|
|
347
|
+
<img src="media/image-ascii-4.png" alt="Modo rostro para retratos" /><br/>
|
|
348
|
+
<sub><b>4. Modo rostro (retratos)</b></sub>
|
|
349
|
+
</td>
|
|
350
|
+
</tr>
|
|
351
|
+
</table>
|
|
327
352
|
|
|
328
353
|
```js
|
|
329
354
|
import { ascii } from 'ansimax';
|
|
@@ -348,10 +373,10 @@ for (let y = 0; y < info.height; y++) {
|
|
|
348
373
|
|
|
349
374
|
// Ahora usa ansimax — varias formas:
|
|
350
375
|
|
|
351
|
-
// Monocromo
|
|
376
|
+
// 1. Monocromo
|
|
352
377
|
console.log(ascii.fromImage(pixels, { width: 80 }));
|
|
353
378
|
|
|
354
|
-
// Color + dithering Floyd-Steinberg + ramp detallado
|
|
379
|
+
// 2. Color + dithering Floyd-Steinberg + ramp detallado
|
|
355
380
|
console.log(ascii.fromImage(pixels, {
|
|
356
381
|
width: 100,
|
|
357
382
|
color: true,
|
|
@@ -359,7 +384,7 @@ console.log(ascii.fromImage(pixels, {
|
|
|
359
384
|
ramp: 'detailed',
|
|
360
385
|
}));
|
|
361
386
|
|
|
362
|
-
// Modo detección de bordes (line art)
|
|
387
|
+
// 3. Modo detección de bordes (line art)
|
|
363
388
|
console.log(ascii.fromImage(pixels, {
|
|
364
389
|
width: 80,
|
|
365
390
|
edgeDetect: 'sobel',
|
|
@@ -367,7 +392,7 @@ console.log(ascii.fromImage(pixels, {
|
|
|
367
392
|
ramp: 'blocks',
|
|
368
393
|
}));
|
|
369
394
|
|
|
370
|
-
// Modo rostro para retratos (mejora contraste de tonos medios)
|
|
395
|
+
// 4. Modo rostro para retratos (mejora contraste de tonos medios)
|
|
371
396
|
console.log(ascii.fromImage(pixels, {
|
|
372
397
|
width: 60,
|
|
373
398
|
ramp: 'detailed',
|
|
@@ -453,7 +478,7 @@ console.log(components.table([
|
|
|
453
478
|
['loaders', color.green('● listo'), '100%'],
|
|
454
479
|
], { borderStyle: 'rounded' }));
|
|
455
480
|
|
|
456
|
-
console.log(components.badge('VERSION', 'v1.3.
|
|
481
|
+
console.log(components.badge('VERSION', 'v1.3.4'));
|
|
457
482
|
console.log(components.badge('BUILD', 'passing'));
|
|
458
483
|
```
|
|
459
484
|
|
|
@@ -505,7 +530,7 @@ await loader.tasks([
|
|
|
505
530
|
|
|
506
531
|
### Animaciones
|
|
507
532
|
|
|
508
|
-
<img src="media/animations.
|
|
533
|
+
<img src="media/animations-1.gif" alt="Vista previa de animaciones" />
|
|
509
534
|
|
|
510
535
|
```js
|
|
511
536
|
import { animate, gradient, sleep } from 'ansimax';
|
|
@@ -615,10 +640,12 @@ console.log(json.pretty({
|
|
|
615
640
|
}));
|
|
616
641
|
|
|
617
642
|
// Límite de profundidad — colapsa objetos profundos a {...}
|
|
643
|
+
const deeplyNested = { a: { b: { c: { d: { e: 'muy profundo' } } } } };
|
|
618
644
|
console.log(json.pretty(deeplyNested, { maxDepth: 2 }));
|
|
619
645
|
|
|
620
646
|
// Límite de items — arrays grandes muestran "... (N more)"
|
|
621
|
-
|
|
647
|
+
const largeArray = Array.from({ length: 50 }, (_, i) => `item_${i}`);
|
|
648
|
+
console.log(json.pretty(largeArray, { maxItems: 5 }));
|
|
622
649
|
|
|
623
650
|
// Referencias circulares manejadas con gracia
|
|
624
651
|
const obj = { name: 'foo' };
|
|
@@ -1038,6 +1065,61 @@ ansimax/
|
|
|
1038
1065
|
|
|
1039
1066
|
## 📝 Changelog
|
|
1040
1067
|
|
|
1068
|
+
### v1.3.4 — Features para animations, configure, utils
|
|
1069
|
+
|
|
1070
|
+
Release patch con features opt-in en varios módulos. Cero breaking changes:
|
|
1071
|
+
|
|
1072
|
+
- 🎬 **`animate.shake(text, opts)`** — efecto tremor horizontal para errores
|
|
1073
|
+
- 🔢 **`animate.countUp(from, to, opts)`** — contadores numéricos animados con format/easing
|
|
1074
|
+
- ⚙️ **`setConfigValue(key, value)`** — atajo single-key + alias `subscribeConfig`
|
|
1075
|
+
- 🔗 **`hyperlink(url, label)`** — links clickables vía OSC 8 (VS Code, iTerm2, WezTerm, Kitty...)
|
|
1076
|
+
- 🧹 **`clearLine()`** — helper conveniente para render loops
|
|
1077
|
+
- 🎨 **`gradientStops(start, end, count)`** — N stops procedurales entre dos colores
|
|
1078
|
+
- 🛡️ **`escapeForRegex(str)`** — escapa input de usuario para regex literals
|
|
1079
|
+
- 📏 **`measureBlock(block)`** — dimensiones ANSI-aware de texto multi-línea
|
|
1080
|
+
- 📐 **`node-globals.d.ts`** — añadidos tipos `AsyncIterator`/`AsyncIterable`/`AsyncGenerator`
|
|
1081
|
+
- 🧪 **+45 tests** entre animations, configure, utils
|
|
1082
|
+
|
|
1083
|
+
```js
|
|
1084
|
+
import { animate, hyperlink } from 'ansimax';
|
|
1085
|
+
|
|
1086
|
+
await animate.countUp(0, 1000, {
|
|
1087
|
+
duration: 1500,
|
|
1088
|
+
format: (n) => `$${n.toLocaleString()}`,
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
console.log(`Ver ${hyperlink('https://npmjs.com/ansimax', 'la página de npm')}`);
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
Drop-in replacement para `1.3.3`.
|
|
1095
|
+
|
|
1096
|
+
### v1.3.3 — Features para panels, json, ascii
|
|
1097
|
+
|
|
1098
|
+
Release patch con nuevas features opt-in. Cero breaking changes:
|
|
1099
|
+
|
|
1100
|
+
- 📐 **`panels.grid(blocks, opts)`** — layout de grid en N columnas con auto-flow, gaps, alineación, y opción de ancho uniforme de celda
|
|
1101
|
+
- 🎯 **`panels.frame` + `ascii.box` + `ascii.divider`** todos reciben opción `titleAlign` (o `align`): `'left'`, `'center'` (default), `'right'`
|
|
1102
|
+
- 🏷️ **`ascii.box` nueva opción `title`** — muestra un label en el borde superior (expande el box si el title es más ancho que el contenido)
|
|
1103
|
+
- 📅 **`json.pretty` soporta Map / Set / Date nativamente** — `Date(...)`, `Map(N) [...]`, `Set(N) [...]` en modo display
|
|
1104
|
+
- 📤 **`json.pretty` nueva opción `mode: 'json'`** — produce JSON estricto y parseable (sin colores, descarta undefined/functions/symbols, lanza en circulares)
|
|
1105
|
+
- 🧪 **+38 tests** entre panels + json + ascii
|
|
1106
|
+
|
|
1107
|
+
```js
|
|
1108
|
+
import { panels, json, ascii } from 'ansimax';
|
|
1109
|
+
|
|
1110
|
+
// Grid de 2×2 con metric cards
|
|
1111
|
+
console.log(panels.grid(cards, { columns: 2, gapX: 2 }));
|
|
1112
|
+
|
|
1113
|
+
// Title en el borde del box
|
|
1114
|
+
console.log(ascii.box('content', { title: 'Section', titleAlign: 'left' }));
|
|
1115
|
+
|
|
1116
|
+
// Output JSON estricto (parseable)
|
|
1117
|
+
const out = json.pretty(data, { mode: 'json' });
|
|
1118
|
+
JSON.parse(out); // ✓ funciona
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
Drop-in replacement para `1.3.2`.
|
|
1122
|
+
|
|
1041
1123
|
### v1.3.2 — Pulido de documentación para frames + images
|
|
1042
1124
|
|
|
1043
1125
|
Release patch con cobertura JSDoc + IntelliSense significativamente mejorada:
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
_Colors • Gradients • Animations • ASCII Art • Pixel Art • Trees • Components • Themes_
|
|
8
8
|
|
|
9
9
|
[](LICENSE)
|
|
10
|
-
[](https://www.npmjs.com/package/ansimax)
|
|
11
11
|
[](tsconfig.json)
|
|
12
12
|
[](#testing)
|
|
13
13
|
[](#testing)
|
|
@@ -215,7 +215,7 @@ console.log(rainbow('built-in rainbow preset'));
|
|
|
215
215
|
|
|
216
216
|
### Animated Gradients (v1.2.0)
|
|
217
217
|
|
|
218
|
-
<img src="media/
|
|
218
|
+
<img src="media/animated-gradients.gif" alt="Animated gradients preview" />
|
|
219
219
|
|
|
220
220
|
```js
|
|
221
221
|
import { animateGradient, sleep } from 'ansimax';
|
|
@@ -275,7 +275,7 @@ console.log(gradientRect({
|
|
|
275
275
|
|
|
276
276
|
### Reusable Gradients (v1.2.3)
|
|
277
277
|
|
|
278
|
-
<img src="media/
|
|
278
|
+
<img src="media/reusable-gradients.gif" alt="Reusable gradients preview" />
|
|
279
279
|
|
|
280
280
|
```js
|
|
281
281
|
import { createGradient, reverseGradient, ascii } from 'ansimax';
|
|
@@ -323,7 +323,32 @@ console.log(ascii.box('Rainbow box!', { padding: 1, borderStyle: 'rounded' }));
|
|
|
323
323
|
|
|
324
324
|
### Image → ASCII (v1.2.5)
|
|
325
325
|
|
|
326
|
-
<
|
|
326
|
+
<div align="center">
|
|
327
|
+
<img src="media/image-ascii-original.png" alt="Original photo" width="40%" />
|
|
328
|
+
</div>
|
|
329
|
+
|
|
330
|
+
<table>
|
|
331
|
+
<tr>
|
|
332
|
+
<td align="center">
|
|
333
|
+
<img src="media/image-ascii-1.png" alt="Monochrome mode" /><br/>
|
|
334
|
+
<sub><b>1. Monochrome</b></sub>
|
|
335
|
+
</td>
|
|
336
|
+
<td align="center">
|
|
337
|
+
<img src="media/image-ascii-2.png" alt="Color + Floyd-Steinberg dithering" /><br/>
|
|
338
|
+
<sub><b>2. Color + Floyd-Steinberg</b></sub>
|
|
339
|
+
</td>
|
|
340
|
+
</tr>
|
|
341
|
+
<tr>
|
|
342
|
+
<td align="center">
|
|
343
|
+
<img src="media/image-ascii-3.png" alt="Edge detection (Sobel)" /><br/>
|
|
344
|
+
<sub><b>3. Edge detection (Sobel)</b></sub>
|
|
345
|
+
</td>
|
|
346
|
+
<td align="center">
|
|
347
|
+
<img src="media/image-ascii-4.png" alt="Face mode for portraits" /><br/>
|
|
348
|
+
<sub><b>4. Face mode (portraits)</b></sub>
|
|
349
|
+
</td>
|
|
350
|
+
</tr>
|
|
351
|
+
</table>
|
|
327
352
|
|
|
328
353
|
```js
|
|
329
354
|
import { ascii } from 'ansimax';
|
|
@@ -348,10 +373,10 @@ for (let y = 0; y < info.height; y++) {
|
|
|
348
373
|
|
|
349
374
|
// Now use ansimax — multiple ways:
|
|
350
375
|
|
|
351
|
-
// Monochrome
|
|
376
|
+
// 1. Monochrome
|
|
352
377
|
console.log(ascii.fromImage(pixels, { width: 80 }));
|
|
353
378
|
|
|
354
|
-
// Color + Floyd-Steinberg dithering + detailed ramp
|
|
379
|
+
// 2. Color + Floyd-Steinberg dithering + detailed ramp
|
|
355
380
|
console.log(ascii.fromImage(pixels, {
|
|
356
381
|
width: 100,
|
|
357
382
|
color: true,
|
|
@@ -359,7 +384,7 @@ console.log(ascii.fromImage(pixels, {
|
|
|
359
384
|
ramp: 'detailed',
|
|
360
385
|
}));
|
|
361
386
|
|
|
362
|
-
// Edge-detection mode (line art)
|
|
387
|
+
// 3. Edge-detection mode (line art)
|
|
363
388
|
console.log(ascii.fromImage(pixels, {
|
|
364
389
|
width: 80,
|
|
365
390
|
edgeDetect: 'sobel',
|
|
@@ -367,7 +392,7 @@ console.log(ascii.fromImage(pixels, {
|
|
|
367
392
|
ramp: 'blocks',
|
|
368
393
|
}));
|
|
369
394
|
|
|
370
|
-
// Face mode for portraits (boosts midtone contrast)
|
|
395
|
+
// 4. Face mode for portraits (boosts midtone contrast)
|
|
371
396
|
console.log(ascii.fromImage(pixels, {
|
|
372
397
|
width: 60,
|
|
373
398
|
ramp: 'detailed',
|
|
@@ -453,7 +478,7 @@ console.log(components.table([
|
|
|
453
478
|
['loaders', color.green('● ready'), '100%'],
|
|
454
479
|
], { borderStyle: 'rounded' }));
|
|
455
480
|
|
|
456
|
-
console.log(components.badge('VERSION', 'v1.3.
|
|
481
|
+
console.log(components.badge('VERSION', 'v1.3.4'));
|
|
457
482
|
console.log(components.badge('BUILD', 'passing'));
|
|
458
483
|
```
|
|
459
484
|
|
|
@@ -505,7 +530,7 @@ await loader.tasks([
|
|
|
505
530
|
|
|
506
531
|
### Animations
|
|
507
532
|
|
|
508
|
-
<img src="media/animations.
|
|
533
|
+
<img src="media/animations-1.gif" alt="Animations preview" />
|
|
509
534
|
|
|
510
535
|
```js
|
|
511
536
|
import { animate, gradient, sleep } from 'ansimax';
|
|
@@ -615,10 +640,12 @@ console.log(json.pretty({
|
|
|
615
640
|
}));
|
|
616
641
|
|
|
617
642
|
// Depth limit — collapses deep objects to {...}
|
|
643
|
+
const deeplyNested = { a: { b: { c: { d: { e: 'too deep' } } } } };
|
|
618
644
|
console.log(json.pretty(deeplyNested, { maxDepth: 2 }));
|
|
619
645
|
|
|
620
646
|
// Item limit — huge arrays show "... (N more)"
|
|
621
|
-
|
|
647
|
+
const largeArray = Array.from({ length: 50 }, (_, i) => `item_${i}`);
|
|
648
|
+
console.log(json.pretty(largeArray, { maxItems: 5 }));
|
|
622
649
|
|
|
623
650
|
// Circular references handled gracefully
|
|
624
651
|
const obj = { name: 'foo' };
|
|
@@ -1038,6 +1065,61 @@ ansimax/
|
|
|
1038
1065
|
|
|
1039
1066
|
## 📝 Changelog
|
|
1040
1067
|
|
|
1068
|
+
### v1.3.4 — Feature additions across animations, configure, utils
|
|
1069
|
+
|
|
1070
|
+
Patch release with opt-in additions to several modules. Zero breaking changes:
|
|
1071
|
+
|
|
1072
|
+
- 🎬 **`animate.shake(text, opts)`** — horizontal tremble effect for error feedback
|
|
1073
|
+
- 🔢 **`animate.countUp(from, to, opts)`** — animated numeric counters with format/easing
|
|
1074
|
+
- ⚙️ **`setConfigValue(key, value)`** — single-key config shortcut + `subscribeConfig` alias
|
|
1075
|
+
- 🔗 **`hyperlink(url, label)`** — OSC 8 clickable terminal links (VS Code, iTerm2, WezTerm, Kitty...)
|
|
1076
|
+
- 🧹 **`clearLine()`** — convenience helper for render loops
|
|
1077
|
+
- 🎨 **`gradientStops(start, end, count)`** — procedural N-color stops
|
|
1078
|
+
- 🛡️ **`escapeForRegex(str)`** — escape user input for regex literals
|
|
1079
|
+
- 📏 **`measureBlock(block)`** — get ANSI-aware dimensions of multi-line text
|
|
1080
|
+
- 📐 **`node-globals.d.ts`** — added `AsyncIterator`/`AsyncIterable`/`AsyncGenerator` ambient types
|
|
1081
|
+
- 🧪 **+45 tests** across animations, configure, utils
|
|
1082
|
+
|
|
1083
|
+
```js
|
|
1084
|
+
import { animate, hyperlink } from 'ansimax';
|
|
1085
|
+
|
|
1086
|
+
await animate.countUp(0, 1000, {
|
|
1087
|
+
duration: 1500,
|
|
1088
|
+
format: (n) => `$${n.toLocaleString()}`,
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
console.log(`See ${hyperlink('https://npmjs.com/ansimax', 'the npm page')}`);
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
Drop-in replacement for `1.3.3`.
|
|
1095
|
+
|
|
1096
|
+
### v1.3.3 — Features for panels, json, ascii
|
|
1097
|
+
|
|
1098
|
+
Patch release with new opt-in features. Zero breaking changes:
|
|
1099
|
+
|
|
1100
|
+
- 📐 **`panels.grid(blocks, opts)`** — N-column grid layout with auto-flow, gaps, alignment, and optional uniform cell width
|
|
1101
|
+
- 🎯 **`panels.frame` + `ascii.box` + `ascii.divider`** all get a `titleAlign` (or `align`) option: `'left'`, `'center'` (default), `'right'`
|
|
1102
|
+
- 🏷️ **`ascii.box` new `title` option** — show a label in the top border (expands box if title is wider than content)
|
|
1103
|
+
- 📅 **`json.pretty` supports Map / Set / Date natively** — `Date(...)`, `Map(N) [...]`, `Set(N) [...]` in display mode
|
|
1104
|
+
- 📤 **`json.pretty` new `mode: 'json'`** — produces strict, parseable JSON (no colors, drops undefined/functions/symbols, throws on circular)
|
|
1105
|
+
- 🧪 **+38 tests** across panels + json + ascii
|
|
1106
|
+
|
|
1107
|
+
```js
|
|
1108
|
+
import { panels, json, ascii } from 'ansimax';
|
|
1109
|
+
|
|
1110
|
+
// 2×2 grid of metric cards
|
|
1111
|
+
console.log(panels.grid(cards, { columns: 2, gapX: 2 }));
|
|
1112
|
+
|
|
1113
|
+
// Title in box top border
|
|
1114
|
+
console.log(ascii.box('content', { title: 'Section', titleAlign: 'left' }));
|
|
1115
|
+
|
|
1116
|
+
// Strict JSON output (parseable)
|
|
1117
|
+
const out = json.pretty(data, { mode: 'json' });
|
|
1118
|
+
JSON.parse(out); // ✓ works
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
Drop-in replacement for `1.3.2`.
|
|
1122
|
+
|
|
1041
1123
|
### v1.3.2 — Documentation polish for frames + images
|
|
1042
1124
|
|
|
1043
1125
|
Patch release with significantly improved JSDoc + IntelliSense coverage:
|