ansimax 1.2.4 → 1.2.6

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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  _Colors • Gradients • Animations • ASCII Art • Pixel Art • Trees • Components • Themes_
8
8
 
9
9
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat-square)](LICENSE)
10
- [![npm](https://img.shields.io/badge/npm-v1.2.4-cb3837.svg?style=flat-square)](https://www.npmjs.com/package/ansimax)
10
+ [![npm](https://img.shields.io/badge/npm-v1.2.6-cb3837.svg?style=flat-square)](https://www.npmjs.com/package/ansimax)
11
11
  [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178c6.svg?style=flat-square)](tsconfig.json)
12
12
  [![Coverage](https://img.shields.io/badge/coverage-98%25-brightgreen.svg?style=flat-square)](#testing)
13
13
  [![Tests](https://img.shields.io/badge/tests-1700%2B%20passing-brightgreen.svg?style=flat-square)](#testing)
@@ -49,7 +49,7 @@ Ansimax is a **batteries-included rendering library** for building beautiful ter
49
49
  npm install ansimax
50
50
  ```
51
51
 
52
- ```ts
52
+ ```js
53
53
  import { color, gradient, ascii, loader, sleep } from 'ansimax';
54
54
 
55
55
  console.log(ascii.banner('hello', {
@@ -122,7 +122,7 @@ yarn add ansimax
122
122
 
123
123
  ## ⚡ 30-second example
124
124
 
125
- ```ts
125
+ ```js
126
126
  import { color, gradient, loader, ascii, sleep } from 'ansimax';
127
127
 
128
128
  console.log(ascii.banner('deploy', {
@@ -140,7 +140,7 @@ console.log(color.green('✓') + ' Ready in ' + color.bold('1.4s'));
140
140
 
141
141
  ## 🚀 Quick Start
142
142
 
143
- ```ts
143
+ ```js
144
144
  import { configure, color, themes, gradient } from 'ansimax';
145
145
 
146
146
  // Global configuration
@@ -186,7 +186,7 @@ console.log(themes.primary('cyberpunk primary'));
186
186
 
187
187
  <img src="media/colors.png" alt="Colors and gradients" />
188
188
 
189
- ```ts
189
+ ```js
190
190
  import { color, gradient, rainbow } from 'ansimax';
191
191
 
192
192
  // Basic colors
@@ -204,7 +204,7 @@ console.log(rainbow('built-in rainbow preset'));
204
204
 
205
205
  ### Animated Gradients (v1.2.0)
206
206
 
207
- ```ts
207
+ ```js
208
208
  import { animateGradient, sleep } from 'ansimax';
209
209
 
210
210
  // Color flow animation — runs until you call stop()
@@ -227,7 +227,7 @@ await animateGradient('Done!', ['#50fa7b', '#bd93f9'], {
227
227
 
228
228
  <img src="media/easing_curves.png" alt="Colors and gradients" />
229
229
 
230
- ```ts
230
+ ```js
231
231
  import { gradient } from 'ansimax';
232
232
 
233
233
  const stops = ['#ff79c6', '#bd93f9', '#8be9fd'];
@@ -247,7 +247,7 @@ console.log(gradient('hello world', stops, { easing: (t) => t * t * t }));
247
247
 
248
248
  <img src="media/conic_gradients.png" alt="Colors and gradients" />
249
249
 
250
- ```ts
250
+ ```js
251
251
  import { gradientRect } from 'ansimax';
252
252
 
253
253
  // Radial sweep around center — rainbow wheel
@@ -262,7 +262,7 @@ console.log(gradientRect({
262
262
 
263
263
  ### Reusable Gradients (v1.2.3)
264
264
 
265
- ```ts
265
+ ```js
266
266
  import { createGradient, reverseGradient, ascii } from 'ansimax';
267
267
 
268
268
  // Pre-resolve hex stops once — significantly faster for repeated use
@@ -294,7 +294,7 @@ for (let p = 0; p < 1; p += 0.05) {
294
294
 
295
295
  <img src="media/ascii_art.png" alt="ASCII art" />
296
296
 
297
- ```ts
297
+ ```js
298
298
  import { ascii, gradient } from 'ansimax';
299
299
 
300
300
  console.log(ascii.banner('HELLO', {
@@ -306,11 +306,80 @@ console.log(ascii.banner('HELLO', {
306
306
  console.log(ascii.box('Rainbow box!', { padding: 1, borderStyle: 'rounded' }));
307
307
  ```
308
308
 
309
+ ### Image → ASCII (v1.2.5)
310
+
311
+ ```js
312
+ import { ascii } from 'ansimax';
313
+ import sharp from 'sharp';
314
+
315
+ // Get raw RGB pixels from any image library — example using `sharp`.
316
+ // You can use jimp, pngjs, canvas, or any decoder. Ansimax stays zero-deps.
317
+ const { data, info } = await sharp('./photo.png')
318
+ .raw()
319
+ .toBuffer({ resolveWithObject: true });
320
+
321
+ // Convert raw RGB buffer → PixelGrid (a 2D array of { r, g, b } objects)
322
+ const pixels = [];
323
+ for (let y = 0; y < info.height; y++) {
324
+ const row = [];
325
+ for (let x = 0; x < info.width; x++) {
326
+ const i = (y * info.width + x) * info.channels;
327
+ row.push({ r: data[i], g: data[i + 1], b: data[i + 2] });
328
+ }
329
+ pixels.push(row);
330
+ }
331
+
332
+ // Now use ansimax — multiple ways:
333
+
334
+ // Monochrome
335
+ console.log(ascii.fromImage(pixels, { width: 80 }));
336
+
337
+ // Color + Floyd-Steinberg dithering + detailed ramp
338
+ console.log(ascii.fromImage(pixels, {
339
+ width: 100,
340
+ color: true,
341
+ dither: 'floyd-steinberg',
342
+ ramp: 'detailed',
343
+ }));
344
+
345
+ // Edge-detection mode (line art)
346
+ console.log(ascii.fromImage(pixels, {
347
+ width: 80,
348
+ edgeDetect: 'sobel',
349
+ edgeThreshold: 50,
350
+ ramp: 'blocks',
351
+ }));
352
+
353
+ // Face mode for portraits (boosts midtone contrast)
354
+ console.log(ascii.fromImage(pixels, {
355
+ width: 60,
356
+ ramp: 'detailed',
357
+ faceMode: true,
358
+ }));
359
+ ```
360
+
361
+ ### Figlet Fonts (v1.2.5)
362
+
363
+ ```js
364
+ import { readFileSync } from 'node:fs';
365
+ import { parseFiglet, ascii, gradient } from 'ansimax';
366
+
367
+ // Download fonts from http://www.figlet.org/fontdb.cgi
368
+ const font = parseFiglet(readFileSync('./standard.flf', 'utf8'));
369
+
370
+ console.log(ascii.figletText('Hello!', font));
371
+
372
+ // With color
373
+ console.log(ascii.figletText('STYLE', font, {
374
+ colorFn: (t) => gradient(t, ['#ff79c6', '#bd93f9', '#8be9fd']),
375
+ }));
376
+ ```
377
+
309
378
  ### Trees
310
379
 
311
380
  <img src="media/trees.png" alt="Trees" />
312
381
 
313
- ```ts
382
+ ```js
314
383
  import { tree, color } from 'ansimax';
315
384
 
316
385
  const project = tree({ label: 'my-app', icon: '📦', color: color.bold });
@@ -329,7 +398,7 @@ console.log(project.render({
329
398
 
330
399
  <img src="media/pixel_art.png" alt="Pixel art" />
331
400
 
332
- ```ts
401
+ ```js
333
402
  import { images, createCanvas, gradientRect, SPRITES } from 'ansimax';
334
403
 
335
404
  // Built-in sprite
@@ -355,7 +424,7 @@ c.print();
355
424
 
356
425
  <img src="media/components.png" alt="Components" />
357
426
 
358
- ```ts
427
+ ```js
359
428
  import { components, color } from 'ansimax';
360
429
 
361
430
  console.log(components.table([
@@ -365,7 +434,7 @@ console.log(components.table([
365
434
  ['loaders', color.green('● ready'), '100%'],
366
435
  ], { borderStyle: 'rounded' }));
367
436
 
368
- console.log(components.badge('VERSION', 'v1.2.4'));
437
+ console.log(components.badge('VERSION', 'v1.2.6'));
369
438
  console.log(components.badge('BUILD', 'passing'));
370
439
  ```
371
440
 
@@ -373,7 +442,7 @@ console.log(components.badge('BUILD', 'passing'));
373
442
 
374
443
  <img src="media/timeline.png" alt="Timeline" />
375
444
 
376
- ```ts
445
+ ```js
377
446
  import { components } from 'ansimax';
378
447
 
379
448
  console.log(components.timeline([
@@ -386,7 +455,7 @@ console.log(components.timeline([
386
455
 
387
456
  ### Loaders & Progress
388
457
 
389
- ```ts
458
+ ```js
390
459
  import { loader, sleep } from 'ansimax';
391
460
 
392
461
  // Spinner with success/failure
@@ -415,7 +484,7 @@ await loader.tasks([
415
484
 
416
485
  ### Animations
417
486
 
418
- ```ts
487
+ ```js
419
488
  import { animate, gradient, sleep } from 'ansimax';
420
489
 
421
490
  await animate.typewriter('Welcome to the deployment wizard...', {
@@ -437,7 +506,7 @@ await animate.parallel([
437
506
 
438
507
  <img src="media/themes.png" alt="Themes" />
439
508
 
440
- ```ts
509
+ ```js
441
510
  import { themes, createTheme } from 'ansimax';
442
511
 
443
512
  // Built-in themes
@@ -526,7 +595,7 @@ node examples/all-in-one.cjs
526
595
 
527
596
  Global config affects every module that respects it (colors, themes, animation speed, etc.):
528
597
 
529
- ```ts
598
+ ```js
530
599
  import { configure, getConfig, withConfig, onConfigKeyChange } from 'ansimax';
531
600
 
532
601
  configure({
@@ -579,7 +648,7 @@ The roadmap intentionally targets — and aims to surpass — gaps that even mat
579
648
  - [x] **Gradient interpolation curves** — `linear` / `ease-in` / `ease-out` / `ease-in-out` / `cubic-bezier` / custom (v1.2.0)
580
649
  - [x] **Conic gradients** — radial sweep with `style: 'conic'` (v1.2.0)
581
650
 
582
- ### 🟡 Phase 3 — ASCII engine
651
+ ### Phase 3 — ASCII engine
583
652
  - [x] Block fonts (`big`, `small`)
584
653
  - [x] Banner with gradient + alignment + per-char coloring
585
654
  - [x] Box drawing (6 border styles)
@@ -587,11 +656,12 @@ The roadmap intentionally targets — and aims to surpass — gaps that even mat
587
656
  - [x] Logo composer (gradient + box wrapping)
588
657
  - [x] Custom font registry (`registerFont`, `hasFont`, `listFonts`)
589
658
  - [x] Stream API (`ascii.stream()` with AbortSignal)
590
- - [ ] **Image → ASCII** converter (with edge detection, Sobel/Canny)
591
- - [ ] **Color ASCII** rendering (preserve image colors)
592
- - [ ] **Image dithering** for better tonal range (Floyd-Steinberg)
593
- - [ ] **Face-optimized ASCII** (high-detail mode for portraits)
594
- - [ ] **Figlet font support** (.flf file loader 250+ community fonts)
659
+ - [x] **Image → ASCII** converter — `ascii.fromImage()` with luminance mapping (v1.2.5)
660
+ - [x] **Color ASCII** rendering preserve image colors via `color: true` (v1.2.5)
661
+ - [x] **Image dithering** Floyd-Steinberg error diffusion (v1.2.5)
662
+ - [x] **Face-optimized ASCII** histogram stretching for portraits (v1.2.5)
663
+ - [x] **Figlet font support** — `.flf` parser + renderer (`parseFiglet` + `ascii.figletText`) (v1.2.5)
664
+ - [x] **Edge detection** — Sobel operator integrated in `fromImage` (v1.2.5, bonus)
595
665
 
596
666
  ### ✅ Phase 4 — Terminal UI primitives
597
667
  - [x] Tables (irregular rows, multi-line cells, ANSI-aware)
@@ -767,6 +837,74 @@ ansimax/
767
837
 
768
838
  ## 📝 Changelog
769
839
 
840
+ ### v1.2.6 — ASCII module improvements
841
+
842
+ Patch release with ASCII engine improvements:
843
+
844
+ - 🎨 **4 new built-in ramps** — `binary`, `dots`, `shades`, `ascii64`
845
+ - 🖼️ **`bgColor` option** in `fromImage` — colors go on background (great with `ramp: 'binary'` for photo effect)
846
+ - 🔆 **`brightness` and `contrast`** pre-adjustment in `fromImage` — tune tonal range without re-processing
847
+ - 📏 **`kerning` option** in `figletText` — control space between glyphs
848
+ - 📄 **Multi-line `figletText`** — input with `\n` renders multiple FIGfont blocks with optional `lineSpacing`
849
+
850
+ ```js
851
+ import { ascii, ASCII_RAMPS } from 'ansimax';
852
+
853
+ // Photo-like rendering with colored background blocks
854
+ console.log(ascii.fromImage(pixels, {
855
+ width: 80,
856
+ bgColor: true,
857
+ ramp: 'binary',
858
+ brightness: 0.1,
859
+ contrast: 0.2,
860
+ }));
861
+
862
+ // Multi-line figlet with spacing
863
+ console.log(ascii.figletText('TITLE\nSUBTITLE', font, {
864
+ kerning: 1,
865
+ lineSpacing: 1,
866
+ }));
867
+ ```
868
+
869
+ Drop-in replacement for `1.2.5`.
870
+
871
+ ### v1.2.5 — Phase 3 complete: image-to-ASCII engine
872
+
873
+ Minor release closing the ASCII engine roadmap with 5 new features:
874
+
875
+ - 🖼️ **`ascii.fromImage(pixels, opts)`** — Image → ASCII converter (input: `PixelGrid`)
876
+ - 🎨 **Color ASCII rendering** — `color: true` preserves source colors
877
+ - 📐 **Floyd-Steinberg dithering** — `dither: 'floyd-steinberg'` for smoother tonal gradients
878
+ - 👤 **Face-optimized mode** — `faceMode: true` boosts midtone contrast for portraits
879
+ - 🔠 **Figlet (.flf) support** — `parseFiglet()` + `ascii.figletText()` for 250+ community fonts
880
+ - ⚡ **Bonus: Sobel edge detection** — `edgeDetect: 'sobel'` for line-art effects
881
+
882
+ ```js
883
+ import { readFileSync } from 'node:fs';
884
+ import { ascii, parseFiglet } from 'ansimax';
885
+
886
+ // Build a small PixelGrid by hand (use sharp/jimp/etc for real images —
887
+ // see Image → ASCII section above)
888
+ const pixels = [
889
+ [{ r: 255, g: 0, b: 0 }, { r: 0, g: 255, b: 0 }],
890
+ [{ r: 0, g: 0, b: 255 }, { r: 255, g: 255, b: 0 }],
891
+ ];
892
+
893
+ // Image to ASCII (input from sharp/jimp/etc, no decoder dependency)
894
+ console.log(ascii.fromImage(pixels, {
895
+ width: 80,
896
+ color: true,
897
+ dither: 'floyd-steinberg',
898
+ ramp: 'detailed',
899
+ }));
900
+
901
+ // Figlet rendering
902
+ const font = parseFiglet(readFileSync('./standard.flf', 'utf8'));
903
+ console.log(ascii.figletText('Hello!', font));
904
+ ```
905
+
906
+ Drop-in replacement for `1.2.4`.
907
+
770
908
  ### v1.2.4 — Gradient utilities + inspectability
771
909
 
772
910
  Patch release adding inspection metadata and a `reverseGradient()` helper:
@@ -775,7 +913,7 @@ Patch release adding inspection metadata and a `reverseGradient()` helper:
775
913
  - 🔄 **`reverseGradient()` helper** — flips a gradient's stop order (works with arrays or `ReusableGradient`)
776
914
  - 🎯 **`presets` exported as canonical name** — alongside the existing `colorPresets` alias
777
915
 
778
- ```ts
916
+ ```js
779
917
  import { createGradient, reverseGradient } from 'ansimax';
780
918
 
781
919
  const fire = createGradient(['#ff5555', '#ffb86c', '#f1fa8c']);
@@ -796,8 +934,8 @@ Patch release adding a performance-oriented API:
796
934
  - 📖 More JSDoc with runnable examples
797
935
  - 🎯 Matches the `ColorFn` signature — works as `colorFn` in `ascii.banner`, themes, etc.
798
936
 
799
- ```ts
800
- import { createGradient } from 'ansimax';
937
+ ```js
938
+ import { createGradient, ascii } from 'ansimax';
801
939
 
802
940
  const fire = createGradient(['#ff5555', '#ffb86c', '#f1fa8c']);
803
941
  console.log(fire('Reused colors!'));
@@ -826,7 +964,7 @@ Minor release closing the gradient engine roadmap with three powerful features:
826
964
  - 📐 **Easing curves** — `linear` / `ease-in` / `ease-out` / `ease-in-out` / `cubic-bezier` / custom functions
827
965
  - ⭕ **Conic gradients** — `gradientRect({ style: 'conic', startAngle })` for radial sweeps
828
966
 
829
- ```ts
967
+ ```js
830
968
  import { animateGradient } from 'ansimax';
831
969
 
832
970
  const ctrl = animateGradient('Loading...', ['#ff79c6', '#bd93f9', '#8be9fd']);