ansimax 1.3.6 → 1.4.0

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/dist/index.js CHANGED
@@ -61,6 +61,8 @@ __export(index_exports, {
61
61
  charWidth: () => charWidth,
62
62
  clamp: () => clamp,
63
63
  clampByte: () => clampByte2,
64
+ clampInt: () => clampInt,
65
+ clampPercent: () => clampPercent,
64
66
  clearAnsiCache: () => clearAnsiCache,
65
67
  clearColorCache: () => clearColorCache,
66
68
  clearLine: () => clearLine,
@@ -125,6 +127,7 @@ __export(index_exports, {
125
127
  listPresets: () => listPresets,
126
128
  loader: () => loader,
127
129
  mapTree: () => mapTree,
130
+ markdown: () => markdown,
128
131
  measureBlock: () => measureBlock,
129
132
  measureTree: () => measureTree,
130
133
  memoize: () => memoize,
@@ -140,6 +143,8 @@ __export(index_exports, {
140
143
  padStart: () => padStart,
141
144
  panels: () => panels,
142
145
  parseFiglet: () => parseFiglet,
146
+ parseMarkdownBlocks: () => parseBlocks,
147
+ parseMarkdownInline: () => parseInline,
143
148
  pauseListeners: () => pauseListeners,
144
149
  presetNames: () => presetNames,
145
150
  presets: () => presets,
@@ -147,6 +152,7 @@ __export(index_exports, {
147
152
  rainbow: () => rainbow,
148
153
  registerFont: () => registerFont,
149
154
  registerPreset: () => registerPreset,
155
+ renderMarkdown: () => render,
150
156
  renderPixelArt: () => renderPixelArt,
151
157
  renderTree: () => renderTree,
152
158
  renderTreeStream: () => renderTreeStream,
@@ -608,6 +614,16 @@ var safeInt = (value, fallback = 0, min = -Infinity, max = Infinity) => {
608
614
  var clamp = (n, min, max) => Math.min(Math.max(n, min), max);
609
615
  var lerp = (a, b, t) => a + (b - a) * t;
610
616
  var clampByte2 = (v) => clamp(Math.round(v), 0, 255);
617
+ var clampPercent = (p) => {
618
+ if (!isFiniteNumber2(p)) return 0;
619
+ return Math.max(0, Math.min(100, p));
620
+ };
621
+ var clampInt = (value, min, max, fallback = 0) => {
622
+ if (!isFiniteNumber2(value)) {
623
+ return Math.max(min, Math.min(max, Math.floor(fallback)));
624
+ }
625
+ return Math.max(min, Math.min(max, Math.floor(value)));
626
+ };
611
627
  var HEX_RE = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
612
628
  var isHexColor = (hex) => typeof hex === "string" && HEX_RE.test(hex.trim());
613
629
  var hexToRgb = (hex) => {
@@ -3242,16 +3258,11 @@ var ascii = {
3242
3258
 
3243
3259
  // src/loaders/index.ts
3244
3260
  var canAnimate2 = () => Boolean(process.stdout?.isTTY) && supportsColor() !== "none";
3245
- var isFiniteNumber3 = (n) => typeof n === "number" && Number.isFinite(n);
3246
3261
  var ensureString3 = (v) => typeof v === "string" ? v : String(v ?? "");
3247
3262
  var clampPositiveInt = (n, fallback) => {
3248
- if (!isFiniteNumber3(n)) return fallback;
3263
+ if (!isFiniteNumber2(n)) return fallback;
3249
3264
  return Math.max(1, Math.floor(n));
3250
3265
  };
3251
- var clampPercent = (p) => {
3252
- if (!isFiniteNumber3(p)) return 0;
3253
- return Math.max(0, Math.min(100, p));
3254
- };
3255
3266
  var isUnicodeCapable = () => {
3256
3267
  const env = process.env;
3257
3268
  if (env["CI"]) return true;
@@ -3393,7 +3404,7 @@ var spin = (text = "Loading", opts = {}) => {
3393
3404
  const animInterval = Math.max(FRAME_MS, safeInterval);
3394
3405
  acquireCursor();
3395
3406
  const startTime = Date.now();
3396
- const render = () => {
3407
+ const render2 = () => {
3397
3408
  if (stopped) return;
3398
3409
  const elapsed = Date.now() - startTime;
3399
3410
  frame2 = Math.floor(elapsed / animInterval) % frames2.length;
@@ -3403,8 +3414,8 @@ var spin = (text = "Loading", opts = {}) => {
3403
3414
  const buf = createOutputBuffer().push("\r").push(screen.clearLine()).push(line).toString();
3404
3415
  write(buf);
3405
3416
  };
3406
- render();
3407
- timer = setInterval(render, animInterval);
3417
+ render2();
3418
+ timer = setInterval(render2, animInterval);
3408
3419
  let abortedBySignal = false;
3409
3420
  const onAbort = () => {
3410
3421
  abortedBySignal = true;
@@ -3575,15 +3586,15 @@ var dots = (text = "Processing", opts = {}) => {
3575
3586
  let count = 0;
3576
3587
  let stopped = false;
3577
3588
  let timer = null;
3578
- const render = () => {
3589
+ const render2 = () => {
3579
3590
  if (stopped) return;
3580
3591
  const dotStr = ".".repeat(count);
3581
3592
  const colored = applyColor(dotStr, hex);
3582
3593
  write("\r" + screen.clearLine() + text + colored);
3583
3594
  count = (count + 1) % (max + 1);
3584
3595
  };
3585
- render();
3586
- timer = setInterval(render, Math.max(FRAME_MS, interval));
3596
+ render2();
3597
+ timer = setInterval(render2, Math.max(FRAME_MS, interval));
3587
3598
  const onAbort = () => stopFn();
3588
3599
  if (signal) signal.addEventListener("abort", onAbort, { once: true });
3589
3600
  const stopFn = () => {
@@ -3615,15 +3626,15 @@ var custom = (frames2, text = "", opts = {}) => {
3615
3626
  let timer = null;
3616
3627
  const safeInterval = Math.max(FRAME_MS, interval);
3617
3628
  const startTime = Date.now();
3618
- const render = () => {
3629
+ const render2 = () => {
3619
3630
  if (stopped) return;
3620
3631
  const elapsed = Date.now() - startTime;
3621
3632
  frame2 = Math.floor(elapsed / safeInterval) % frames2.length;
3622
3633
  const f = frames2[frame2] ?? "";
3623
3634
  write("\r" + screen.clearLine() + applyColor(f, hex) + " " + text);
3624
3635
  };
3625
- render();
3626
- timer = setInterval(render, safeInterval);
3636
+ render2();
3637
+ timer = setInterval(render2, safeInterval);
3627
3638
  const onAbort = () => stopFn();
3628
3639
  if (signal) signal.addEventListener("abort", onAbort, { once: true });
3629
3640
  const stopFn = () => {
@@ -3641,7 +3652,7 @@ var custom = (frames2, text = "", opts = {}) => {
3641
3652
  };
3642
3653
  var countdown = async (seconds, opts = {}) => {
3643
3654
  const { label = "Starting in", color: hex, signal } = opts;
3644
- const safeSeconds = isFiniteNumber3(seconds) ? Math.max(0, Math.floor(seconds)) : 0;
3655
+ const safeSeconds = isFiniteNumber2(seconds) ? Math.max(0, Math.floor(seconds)) : 0;
3645
3656
  const safeLabel = ensureString3(label);
3646
3657
  const colorToUse = safeColor(hex) ? hex : "#ffd700";
3647
3658
  if (!canAnimate2() || signal?.aborted) {
@@ -3730,7 +3741,7 @@ var multi = (opts = {}) => {
3730
3741
  let frame2 = 0;
3731
3742
  let timer = null;
3732
3743
  let lastLineCount = 0;
3733
- const render = () => {
3744
+ const render2 = () => {
3734
3745
  if (lastLineCount > 0) {
3735
3746
  write("\r" + cursor.up(lastLineCount) + screen.clearDown());
3736
3747
  }
@@ -3752,8 +3763,8 @@ var multi = (opts = {}) => {
3752
3763
  const start = () => {
3753
3764
  if (timer) return;
3754
3765
  acquireCursor();
3755
- render();
3756
- timer = setInterval(render, interval);
3766
+ render2();
3767
+ timer = setInterval(render2, interval);
3757
3768
  };
3758
3769
  const tick = () => {
3759
3770
  if (!timer) start();
@@ -3777,35 +3788,35 @@ var multi = (opts = {}) => {
3777
3788
  },
3778
3789
  set text(v) {
3779
3790
  item.text = v;
3780
- render();
3791
+ render2();
3781
3792
  },
3782
3793
  update(newText) {
3783
3794
  item.text = newText;
3784
- render();
3795
+ render2();
3785
3796
  },
3786
3797
  succeed(t) {
3787
3798
  item.state = "success";
3788
3799
  if (t !== void 0) item.finalText = t;
3789
- render();
3800
+ render2();
3790
3801
  setTimeout(() => {
3791
3802
  items.delete(id);
3792
- render();
3803
+ render2();
3793
3804
  checkEmpty();
3794
3805
  }, interval);
3795
3806
  },
3796
3807
  fail(t) {
3797
3808
  item.state = "fail";
3798
3809
  if (t !== void 0) item.finalText = t;
3799
- render();
3810
+ render2();
3800
3811
  setTimeout(() => {
3801
3812
  items.delete(id);
3802
- render();
3813
+ render2();
3803
3814
  checkEmpty();
3804
3815
  }, interval);
3805
3816
  },
3806
3817
  stop() {
3807
3818
  items.delete(id);
3808
- render();
3819
+ render2();
3809
3820
  checkEmpty();
3810
3821
  }
3811
3822
  };
@@ -3849,11 +3860,10 @@ var loader = {
3849
3860
  };
3850
3861
 
3851
3862
  // src/frames/index.ts
3852
- var isFiniteNumber4 = (n) => typeof n === "number" && Number.isFinite(n);
3853
3863
  var ensureString4 = (v) => typeof v === "string" ? v : String(v ?? "");
3854
3864
  var MAX_FPS = 60;
3855
3865
  var clampFps = (fps, fallback) => {
3856
- if (!isFiniteNumber4(fps)) return fallback;
3866
+ if (!isFiniteNumber2(fps)) return fallback;
3857
3867
  return Math.max(1, Math.min(MAX_FPS, Math.floor(fps)));
3858
3868
  };
3859
3869
  var _cursorHiddenCount2 = 0;
@@ -3952,14 +3962,14 @@ var play = (frames2, opts = {}) => {
3952
3962
  if (fps !== void 0) {
3953
3963
  const safeFps = clampFps(fps, 60);
3954
3964
  tickMs = Math.max(FRAME_MS, Math.floor(1e3 / safeFps));
3955
- } else if (isFiniteNumber4(interval)) {
3965
+ } else if (isFiniteNumber2(interval)) {
3956
3966
  tickMs = Math.max(FRAME_MS, Math.floor(interval));
3957
3967
  } else {
3958
3968
  tickMs = 100;
3959
3969
  }
3960
3970
  let safeRepeat;
3961
3971
  let infinite;
3962
- if (!isFiniteNumber4(repeat)) {
3972
+ if (!isFiniteNumber2(repeat)) {
3963
3973
  safeRepeat = 1;
3964
3974
  infinite = false;
3965
3975
  } else if (repeat === 0) {
@@ -4084,7 +4094,7 @@ var play = (frames2, opts = {}) => {
4084
4094
  paused = false;
4085
4095
  },
4086
4096
  seek: (idx) => {
4087
- if (!isFiniteNumber4(idx)) return;
4097
+ if (!isFiniteNumber2(idx)) return;
4088
4098
  const safe = Math.max(0, Math.floor(idx));
4089
4099
  frameIdx = frames2.length > 0 ? safe % frames2.length : 0;
4090
4100
  },
@@ -4097,7 +4107,7 @@ var play = (frames2, opts = {}) => {
4097
4107
  };
4098
4108
  };
4099
4109
  var generate = (count, fn) => {
4100
- const safeCount = isFiniteNumber4(count) ? Math.max(0, Math.floor(count)) : 0;
4110
+ const safeCount = isFiniteNumber2(count) ? Math.max(0, Math.floor(count)) : 0;
4101
4111
  if (typeof fn !== "function") return Array(safeCount).fill("");
4102
4112
  return Array.from({ length: safeCount }, (_, i) => {
4103
4113
  try {
@@ -4116,7 +4126,7 @@ var live = (opts = {}) => {
4116
4126
  let running = false;
4117
4127
  let timer = null;
4118
4128
  let abortHandler = null;
4119
- const render = () => {
4129
+ const render2 = () => {
4120
4130
  if (lastLines > 0) clearLines(lastLines);
4121
4131
  const frame2 = isColorless2() ? stripAnsi(currentFrame) : currentFrame;
4122
4132
  try {
@@ -4131,7 +4141,7 @@ var live = (opts = {}) => {
4131
4141
  running = true;
4132
4142
  registerCrashHandlers3();
4133
4143
  hideCursorSafe2();
4134
- timer = setInterval(render, interval);
4144
+ timer = setInterval(render2, interval);
4135
4145
  if (signal && !abortHandler) {
4136
4146
  abortHandler = () => stop({ clear: false });
4137
4147
  if (signal.aborted) abortHandler();
@@ -4160,7 +4170,7 @@ var live = (opts = {}) => {
4160
4170
  };
4161
4171
  const update = (newFrame) => {
4162
4172
  currentFrame = ensureString4(newFrame);
4163
- if (running) render();
4173
+ if (running) render2();
4164
4174
  };
4165
4175
  if (autoStart) start();
4166
4176
  return { start, stop, update, isRunning: () => running };
@@ -4169,7 +4179,7 @@ var morph = (frameA, frameB, steps = 8, charset = "\u2591\u2592\u2593\u2588\u259
4169
4179
  const a0 = ensureString4(frameA);
4170
4180
  const b0 = ensureString4(frameB);
4171
4181
  if (!a0 && !b0) return [""];
4172
- const n = Math.max(2, isFiniteNumber4(steps) ? Math.floor(steps) : 8);
4182
+ const n = Math.max(2, isFiniteNumber2(steps) ? Math.floor(steps) : 8);
4173
4183
  const len = Math.max(a0.length, b0.length);
4174
4184
  const a = a0.padEnd(len);
4175
4185
  const b = b0.padEnd(len);
@@ -4191,7 +4201,7 @@ var morph = (frameA, frameB, steps = 8, charset = "\u2591\u2592\u2593\u2588\u259
4191
4201
  var presets2 = {
4192
4202
  loadingBar: (opts = {}) => {
4193
4203
  const { width = 20, char = "\u2588", empty = "\u2591", label = "Loading" } = opts;
4194
- const safeWidth = Math.max(0, isFiniteNumber4(width) ? Math.floor(width) : 20);
4204
+ const safeWidth = Math.max(0, isFiniteNumber2(width) ? Math.floor(width) : 20);
4195
4205
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u2588";
4196
4206
  const safeEmpty = typeof empty === "string" && empty.length > 0 ? empty : "\u2591";
4197
4207
  const safeLabel = ensureString4(label);
@@ -4205,7 +4215,7 @@ var presets2 = {
4205
4215
  /* istanbul ignore next — default opts {} */
4206
4216
  ball: (opts = {}) => {
4207
4217
  const { width = 20, char = "\u25CF" } = opts;
4208
- const safeWidth = Math.max(1, isFiniteNumber4(width) ? Math.floor(width) : 20);
4218
+ const safeWidth = Math.max(1, isFiniteNumber2(width) ? Math.floor(width) : 20);
4209
4219
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u25CF";
4210
4220
  const forward = generate(safeWidth, (i) => " ".repeat(i) + safeChar);
4211
4221
  const backward = generate(safeWidth, (i) => " ".repeat(safeWidth - i - 1) + safeChar);
@@ -4215,7 +4225,7 @@ var presets2 = {
4215
4225
  breathe: (text, opts = {}) => {
4216
4226
  const { steps = 8 } = opts;
4217
4227
  const safeText = ensureString4(text);
4218
- const safeSteps2 = Math.max(1, isFiniteNumber4(steps) ? Math.floor(steps) : 8);
4228
+ const safeSteps2 = Math.max(1, isFiniteNumber2(steps) ? Math.floor(steps) : 8);
4219
4229
  const shades = ["\u2591", "\u2592", "\u2593", "\u2588"];
4220
4230
  return generate(safeSteps2 * 2, (i) => {
4221
4231
  const t = i < safeSteps2 ? i / safeSteps2 : 1 - (i - safeSteps2) / safeSteps2;
@@ -4236,22 +4246,17 @@ var presets2 = {
4236
4246
  var frames = { play, generate, live, morph, presets: presets2 };
4237
4247
 
4238
4248
  // src/components/index.ts
4239
- var isFiniteNumber5 = (n) => typeof n === "number" && Number.isFinite(n);
4240
4249
  var ensureString5 = (v) => typeof v === "string" ? v : String(v ?? "");
4241
- var clampPercent2 = (p) => {
4242
- if (!isFiniteNumber5(p)) return 0;
4243
- return Math.max(0, Math.min(100, p));
4244
- };
4245
4250
  var clampNonNeg = (n, fallback) => {
4246
- if (!isFiniteNumber5(n)) return fallback;
4251
+ if (!isFiniteNumber2(n)) return fallback;
4247
4252
  return Math.max(0, Math.floor(n));
4248
4253
  };
4249
4254
  var clampPositive2 = (n, fallback) => {
4250
- if (!isFiniteNumber5(n)) return fallback;
4255
+ if (!isFiniteNumber2(n)) return fallback;
4251
4256
  return Math.max(1, Math.floor(n));
4252
4257
  };
4253
4258
  var safeSgrCode = (code, fallback) => {
4254
- if (!isFiniteNumber5(code)) return fallback;
4259
+ if (!isFiniteNumber2(code)) return fallback;
4255
4260
  return Math.max(0, Math.min(255, Math.floor(code)));
4256
4261
  };
4257
4262
  var truncateVisible = (str, maxWidth, ellipsis = "\u2026") => {
@@ -4289,7 +4294,7 @@ var table = (rows, opts = {}) => {
4289
4294
  const b = TABLE_BORDERS[borderStyle] ?? TABLE_BORDERS.rounded;
4290
4295
  const safePadding = clampNonNeg(padding, 1);
4291
4296
  const pad = " ".repeat(safePadding);
4292
- const safeMaxCol = maxColWidth !== null && isFiniteNumber5(maxColWidth) ? Math.max(1, Math.floor(maxColWidth)) : null;
4297
+ const safeMaxCol = maxColWidth !== null && isFiniteNumber2(maxColWidth) ? Math.max(1, Math.floor(maxColWidth)) : null;
4293
4298
  const validRows = rows.filter((r) => Array.isArray(r));
4294
4299
  if (validRows.length === 0) return "";
4295
4300
  const cols = Math.max(...validRows.map((r) => r.length), 0);
@@ -4376,13 +4381,13 @@ var progressBar = (percent, opts = {}) => {
4376
4381
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u2588";
4377
4382
  const safeEmpty = typeof emptyChar === "string" && emptyChar.length > 0 ? emptyChar : "\u2591";
4378
4383
  const safeLabel = ensureString5(label);
4379
- const clamped = clampPercent2(percent);
4384
+ const clamped = clampPercent(percent);
4380
4385
  const filled = Math.floor(clamped / 100 * safeWidth);
4381
4386
  const empty = Math.max(0, safeWidth - filled);
4382
4387
  let filledStr = safeChar.repeat(filled);
4383
4388
  if (Array.isArray(gradientStops2) && gradientStops2.length >= 1 && filled > 0) {
4384
4389
  filledStr = gradient(filledStr, gradientStops2);
4385
- } else if (color2 !== null && isFiniteNumber5(color2)) {
4390
+ } else if (color2 !== null && isFiniteNumber2(color2)) {
4386
4391
  filledStr = sgr(safeSgrCode(color2, FG.white)) + filledStr + reset();
4387
4392
  }
4388
4393
  const emptyStr = safeEmpty.repeat(empty);
@@ -4418,7 +4423,7 @@ var section = (title, opts = {}) => {
4418
4423
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u2500";
4419
4424
  const safeColor2 = safeSgrCode(colorCode, FG.cyan);
4420
4425
  const titleLen = visibleLen(safeTitle);
4421
- const requestedWidth = width !== null && isFiniteNumber5(width) ? Math.max(1, Math.floor(width)) : cols;
4426
+ const requestedWidth = width !== null && isFiniteNumber2(width) ? Math.max(1, Math.floor(width)) : cols;
4422
4427
  const w = Math.max(requestedWidth, titleLen + 2);
4423
4428
  const side = Math.floor((w - titleLen - 2) / 2);
4424
4429
  const dividerL = sgr(safeColor2) + safeChar.repeat(Math.max(0, side)) + reset();
@@ -4432,7 +4437,7 @@ var columns = (items, opts = {}) => {
4432
4437
  const safeCols = clampPositive2(numCols, 2);
4433
4438
  const safeGap = clampNonNeg(gap, 2);
4434
4439
  const { cols: termCols } = termSize();
4435
- const totalW = width !== null && isFiniteNumber5(width) ? Math.max(safeCols, Math.floor(width)) : termCols;
4440
+ const totalW = width !== null && isFiniteNumber2(width) ? Math.max(safeCols, Math.floor(width)) : termCols;
4436
4441
  const colW = Math.max(1, Math.floor((totalW - safeGap * (safeCols - 1)) / safeCols));
4437
4442
  const gapStr = " ".repeat(safeGap);
4438
4443
  const rows = [];
@@ -4472,7 +4477,7 @@ var timeline = (events, opts = {}) => {
4472
4477
  const safeColor2 = safeSgrCode(colorCode, FG.cyan);
4473
4478
  const safeDoneColor = safeSgrCode(doneColor, FG.green);
4474
4479
  const safePendingColor = safeSgrCode(pendingColor, FG.brightBlack);
4475
- const computedTimeWidth = timeColumnWidth !== null && isFiniteNumber5(timeColumnWidth) ? Math.max(0, Math.floor(timeColumnWidth)) : Math.max(0, ...events.map((e) => e.time ? visibleLen(ensureString5(e.time)) : 0));
4480
+ const computedTimeWidth = timeColumnWidth !== null && isFiniteNumber2(timeColumnWidth) ? Math.max(0, Math.floor(timeColumnWidth)) : Math.max(0, ...events.map((e) => e.time ? visibleLen(ensureString5(e.time)) : 0));
4476
4481
  const lines = [];
4477
4482
  events.forEach((ev, i) => {
4478
4483
  const isLast = i === events.length - 1;
@@ -4514,7 +4519,7 @@ var menu = (items, opts = {}) => {
4514
4519
  } catch {
4515
4520
  }
4516
4521
  };
4517
- const render = () => {
4522
+ const render2 = () => {
4518
4523
  let totalLines = 0;
4519
4524
  const { cols: termCols } = termSize();
4520
4525
  const safeTermCols = Math.max(1, termCols);
@@ -4588,7 +4593,7 @@ var menu = (items, opts = {}) => {
4588
4593
  try {
4589
4594
  emit(cursor.hide());
4590
4595
  cursorHidden = true;
4591
- lastRenderedLines = render();
4596
+ lastRenderedLines = render2();
4592
4597
  } catch {
4593
4598
  cleanup(null);
4594
4599
  return Promise.resolve(MENU_CANCELLED);
@@ -4629,7 +4634,7 @@ var menu = (items, opts = {}) => {
4629
4634
  return;
4630
4635
  }
4631
4636
  clearLinesLocal();
4632
- lastRenderedLines = render();
4637
+ lastRenderedLines = render2();
4633
4638
  } catch {
4634
4639
  cleanup(onKey);
4635
4640
  safeResolve(MENU_CANCELLED);
@@ -4664,10 +4669,9 @@ var STYLES = {
4664
4669
  heavy: { branch: "\u2523\u2501\u2501 ", last: "\u2517\u2501\u2501 ", vert: "\u2503 ", space: " " },
4665
4670
  ascii: { branch: "+-- ", last: "`-- ", vert: "| ", space: " " }
4666
4671
  };
4667
- var isFiniteNumber6 = (n) => typeof n === "number" && Number.isFinite(n);
4668
4672
  var ensureString6 = (v) => typeof v === "string" ? v : String(v ?? "");
4669
4673
  var clampNonNeg2 = (n, fallback) => {
4670
- if (!isFiniteNumber6(n)) return fallback;
4674
+ if (!isFiniteNumber2(n)) return fallback;
4671
4675
  return Math.max(0, Math.floor(n));
4672
4676
  };
4673
4677
  var normalizeNewlines = (s) => s.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
@@ -4739,7 +4743,7 @@ var renderChildren = (children, parentContinuation, lines, indentStr, defaultSty
4739
4743
  if (!Array.isArray(children)) return;
4740
4744
  let visible = children;
4741
4745
  let collapsedCount = 0;
4742
- const safeCollapse = isFiniteNumber6(collapse) ? Math.floor(collapse) : 0;
4746
+ const safeCollapse = isFiniteNumber2(collapse) ? Math.floor(collapse) : 0;
4743
4747
  if (safeCollapse > 0 && safeCollapse < children.length) {
4744
4748
  visible = children.slice(safeCollapse);
4745
4749
  collapsedCount = safeCollapse;
@@ -4809,7 +4813,7 @@ var renderTree = (root, opts = {}) => {
4809
4813
  } = opts;
4810
4814
  const safeStyle = style && STYLES[style] ? style : "normal";
4811
4815
  const safeIndent = clampNonNeg2(indent, 0);
4812
- const safeMaxDepth = isFiniteNumber6(maxDepth) ? Math.max(0, Math.floor(maxDepth)) : Infinity;
4816
+ const safeMaxDepth = isFiniteNumber2(maxDepth) ? Math.max(0, Math.floor(maxDepth)) : Infinity;
4813
4817
  const indentStr = " ".repeat(safeIndent);
4814
4818
  const lines = [];
4815
4819
  const rootLabel = formatNode(root, 0, palette);
@@ -5428,13 +5432,8 @@ var themes = {
5428
5432
  var FULL_BLOCK = "\u2588";
5429
5433
  var UPPER_HALF = "\u2580";
5430
5434
  var LOWER_HALF = "\u2584";
5431
- var isFiniteNumber7 = (n) => typeof n === "number" && Number.isFinite(n);
5432
- var clampInt = (n, min, max, fallback) => {
5433
- if (!isFiniteNumber7(n)) return fallback;
5434
- return Math.max(min, Math.min(max, Math.floor(n)));
5435
- };
5436
5435
  var clampByte3 = (n) => {
5437
- if (!isFiniteNumber7(n)) return 0;
5436
+ if (!isFiniteNumber2(n)) return 0;
5438
5437
  return Math.max(0, Math.min(255, Math.round(n)));
5439
5438
  };
5440
5439
  var MAX_DIMENSION = 1e4;
@@ -5739,7 +5738,7 @@ var gradientRect = (opts = {}) => {
5739
5738
  const safeW = clampInt(width, 2, MAX_DIMENSION, 40);
5740
5739
  const safeH = clampInt(height, 2, MAX_DIMENSION, 10);
5741
5740
  let cosA = 1, sinA = 0;
5742
- if (isFiniteNumber7(angle)) {
5741
+ if (isFiniteNumber2(angle)) {
5743
5742
  const rad = angle * Math.PI / 180;
5744
5743
  cosA = Math.cos(rad);
5745
5744
  sinA = Math.sin(rad);
@@ -5749,7 +5748,7 @@ var gradientRect = (opts = {}) => {
5749
5748
  const line = [];
5750
5749
  for (let col = 0; col < safeW; col++) {
5751
5750
  let t;
5752
- if (isFiniteNumber7(angle)) {
5751
+ if (isFiniteNumber2(angle)) {
5753
5752
  const projection = col / (safeW - 1) * cosA + row / (safeH - 1) * sinA;
5754
5753
  t = clamp((projection + 1) / 2, 0, 1);
5755
5754
  } else if (style === "horizontal") t = col / (safeW - 1);
@@ -5806,7 +5805,7 @@ var createCanvas = (width, height, fillColor = null) => {
5806
5805
  if (y > dirtyMaxY) dirtyMaxY = y;
5807
5806
  };
5808
5807
  const setInternal = (x, y, color2) => {
5809
- if (!isFiniteNumber7(x) || !isFiniteNumber7(y)) return;
5808
+ if (!isFiniteNumber2(x) || !isFiniteNumber2(y)) return;
5810
5809
  const ix = Math.floor(x);
5811
5810
  const iy = Math.floor(y);
5812
5811
  if (iy < 0 || iy >= h || ix < 0 || ix >= w) return;
@@ -5821,7 +5820,7 @@ var createCanvas = (width, height, fillColor = null) => {
5821
5820
  },
5822
5821
  set: setInternal,
5823
5822
  get(x, y) {
5824
- if (!isFiniteNumber7(x) || !isFiniteNumber7(y)) return null;
5823
+ if (!isFiniteNumber2(x) || !isFiniteNumber2(y)) return null;
5825
5824
  const ix = Math.floor(x), iy = Math.floor(y);
5826
5825
  return cloneColor(pixels[iy]?.[ix] ?? null);
5827
5826
  },
@@ -5837,7 +5836,7 @@ var createCanvas = (width, height, fillColor = null) => {
5837
5836
  dirtyMaxY = h - 1;
5838
5837
  },
5839
5838
  drawRect(x, y, rw, rh, color2, fill = false) {
5840
- if (!isFiniteNumber7(x) || !isFiniteNumber7(y) || !isFiniteNumber7(rw) || !isFiniteNumber7(rh)) return;
5839
+ if (!isFiniteNumber2(x) || !isFiniteNumber2(y) || !isFiniteNumber2(rw) || !isFiniteNumber2(rh)) return;
5841
5840
  if (rw <= 0 || rh <= 0) return;
5842
5841
  const ix = Math.floor(x);
5843
5842
  const iy = Math.floor(y);
@@ -5859,7 +5858,7 @@ var createCanvas = (width, height, fillColor = null) => {
5859
5858
  }
5860
5859
  },
5861
5860
  drawCircle(cx, cy, radius, color2, fill = false) {
5862
- if (!isFiniteNumber7(cx) || !isFiniteNumber7(cy) || !isFiniteNumber7(radius)) return;
5861
+ if (!isFiniteNumber2(cx) || !isFiniteNumber2(cy) || !isFiniteNumber2(radius)) return;
5863
5862
  if (radius <= 0) return;
5864
5863
  const x0 = Math.max(0, Math.floor(cx - radius - 1));
5865
5864
  const y0 = Math.max(0, Math.floor(cy - radius - 1));
@@ -5882,7 +5881,7 @@ var createCanvas = (width, height, fillColor = null) => {
5882
5881
  }
5883
5882
  },
5884
5883
  drawSprite(x, y, sprite) {
5885
- if (!isFiniteNumber7(x) || !isFiniteNumber7(y)) return;
5884
+ if (!isFiniteNumber2(x) || !isFiniteNumber2(y)) return;
5886
5885
  if (!Array.isArray(sprite)) return;
5887
5886
  const sx = Math.floor(x);
5888
5887
  const sy = Math.floor(y);
@@ -6347,8 +6346,8 @@ var _renderValue = (value, depth, config) => {
6347
6346
  inlineItems.push(_c(`... (${remaining} more)`, COLORS.comment, useColor));
6348
6347
  }
6349
6348
  const candidate = _c("[", COLORS.bracket, useColor) + inlineItems.join(", ") + _c("]", COLORS.bracket, useColor);
6350
- const visibleLen2 = candidate.replace(/\x1b\[[0-9;]*m/g, "").length;
6351
- if (visibleLen2 <= inlineArrayMaxLength) {
6349
+ const visibleLen3 = candidate.replace(/\x1b\[[0-9;]*m/g, "").length;
6350
+ if (visibleLen3 <= inlineArrayMaxLength) {
6352
6351
  return candidate;
6353
6352
  }
6354
6353
  }
@@ -6427,6 +6426,269 @@ var json = {
6427
6426
  pretty
6428
6427
  };
6429
6428
 
6429
+ // src/markdown/index.ts
6430
+ var THEMES = {
6431
+ dark: {
6432
+ h1: ["#ff79c6", "#bd93f9", "#8be9fd"],
6433
+ h2: "#bd93f9",
6434
+ h3: "#8be9fd",
6435
+ h4: "#50fa7b",
6436
+ h5: "#f1fa8c",
6437
+ h6: "#ffb86c",
6438
+ code: "#ff79c6",
6439
+ codeBlockBorder: "#6272a4",
6440
+ link: "#8be9fd",
6441
+ blockquote: "#6272a4",
6442
+ hr: "#6272a4",
6443
+ tableHeader: "#bd93f9"
6444
+ },
6445
+ light: {
6446
+ h1: ["#d63384", "#6f42c1", "#0d6efd"],
6447
+ h2: "#6f42c1",
6448
+ h3: "#0d6efd",
6449
+ h4: "#198754",
6450
+ h5: "#664d03",
6451
+ h6: "#fd7e14",
6452
+ code: "#d63384",
6453
+ codeBlockBorder: "#adb5bd",
6454
+ link: "#0d6efd",
6455
+ blockquote: "#6c757d",
6456
+ hr: "#adb5bd",
6457
+ tableHeader: "#6f42c1"
6458
+ }
6459
+ };
6460
+ var _normalize = (text) => typeof text === "string" ? text.replace(/\r\n/g, "\n").replace(/\r/g, "\n") : "";
6461
+ var HEADING_RE = /^(#{1,6})\s+(.+?)\s*#*\s*$/;
6462
+ var ORDERED_LIST_RE = /^(\s*)(\d+)[.)]\s+(.+)$/;
6463
+ var UNORDERED_LIST_RE = /^(\s*)[-*+]\s+(.+)$/;
6464
+ var HR_RE = /^[ \t]*(?:-{3,}|\*{3,}|_{3,})[ \t]*$/;
6465
+ var CODEBLOCK_OPEN_RE = /^```[ \t]*(\S*)[ \t]*$/;
6466
+ var CODEBLOCK_CLOSE_RE = /^```\s*$/;
6467
+ var BLOCKQUOTE_RE = /^>\s?(.*)$/;
6468
+ var TABLE_SEPARATOR_RE = /^\|?[ \t]*:?-{2,}:?[ \t]*(\|[ \t]*:?-{2,}:?[ \t]*)+\|?[ \t]*$/;
6469
+ var TABLE_ROW_RE = /^\|.*\|[ \t]*$/;
6470
+ var parseBlocks = (source) => {
6471
+ if (typeof source !== "string" || source.length === 0) return [];
6472
+ const lines = _normalize(source).split("\n");
6473
+ const out = [];
6474
+ let i = 0;
6475
+ while (i < lines.length) {
6476
+ const line = lines[i];
6477
+ if (line.trim() === "") {
6478
+ out.push({ type: "blank" });
6479
+ i++;
6480
+ continue;
6481
+ }
6482
+ if (HR_RE.test(line)) {
6483
+ out.push({ type: "hr" });
6484
+ i++;
6485
+ continue;
6486
+ }
6487
+ const headingMatch = HEADING_RE.exec(line);
6488
+ if (headingMatch) {
6489
+ const level = headingMatch[1].length;
6490
+ const text = headingMatch[2].trim();
6491
+ out.push({ type: "heading", level, text });
6492
+ i++;
6493
+ continue;
6494
+ }
6495
+ const codeOpen = CODEBLOCK_OPEN_RE.exec(line);
6496
+ if (codeOpen) {
6497
+ const lang = codeOpen[1].trim();
6498
+ const codeLines = [];
6499
+ i++;
6500
+ while (i < lines.length && !CODEBLOCK_CLOSE_RE.test(lines[i])) {
6501
+ codeLines.push(lines[i]);
6502
+ i++;
6503
+ }
6504
+ if (i < lines.length) i++;
6505
+ out.push({ type: "codeblock", lang, code: codeLines.join("\n") });
6506
+ continue;
6507
+ }
6508
+ if (BLOCKQUOTE_RE.test(line)) {
6509
+ const qLines = [];
6510
+ while (i < lines.length && BLOCKQUOTE_RE.test(lines[i])) {
6511
+ const m = BLOCKQUOTE_RE.exec(lines[i]);
6512
+ qLines.push((m?.[1] ?? "").trim());
6513
+ i++;
6514
+ }
6515
+ out.push({ type: "blockquote", text: qLines.join("\n") });
6516
+ continue;
6517
+ }
6518
+ if (TABLE_ROW_RE.test(line) && i + 1 < lines.length && TABLE_SEPARATOR_RE.test(lines[i + 1])) {
6519
+ const headers = _splitTableRow(line);
6520
+ i += 2;
6521
+ const rows = [];
6522
+ while (i < lines.length && TABLE_ROW_RE.test(lines[i])) {
6523
+ rows.push(_splitTableRow(lines[i]));
6524
+ i++;
6525
+ }
6526
+ out.push({ type: "table", headers, rows });
6527
+ continue;
6528
+ }
6529
+ const ulMatch = UNORDERED_LIST_RE.exec(line);
6530
+ const olMatch = ORDERED_LIST_RE.exec(line);
6531
+ if (ulMatch || olMatch) {
6532
+ const ordered = olMatch != null;
6533
+ const items = [];
6534
+ while (i < lines.length) {
6535
+ const ln = lines[i];
6536
+ const u = UNORDERED_LIST_RE.exec(ln);
6537
+ const o = ORDERED_LIST_RE.exec(ln);
6538
+ if (ordered && o) {
6539
+ items.push(o[3].trim());
6540
+ i++;
6541
+ } else if (!ordered && u) {
6542
+ items.push(u[2].trim());
6543
+ i++;
6544
+ } else {
6545
+ break;
6546
+ }
6547
+ }
6548
+ out.push({ type: "list", ordered, items });
6549
+ continue;
6550
+ }
6551
+ const paraLines = [line];
6552
+ i++;
6553
+ while (i < lines.length) {
6554
+ const next = lines[i];
6555
+ if (next.trim() === "" || HEADING_RE.test(next) || HR_RE.test(next) || CODEBLOCK_OPEN_RE.test(next) || BLOCKQUOTE_RE.test(next) || UNORDERED_LIST_RE.test(next) || ORDERED_LIST_RE.test(next) || TABLE_ROW_RE.test(next)) {
6556
+ break;
6557
+ }
6558
+ paraLines.push(next);
6559
+ i++;
6560
+ }
6561
+ out.push({ type: "paragraph", text: paraLines.join(" ").trim() });
6562
+ }
6563
+ return out;
6564
+ };
6565
+ var _splitTableRow = (row) => {
6566
+ const stripped = row.trim().replace(/^\|/, "").replace(/\|[ \t]*$/, "");
6567
+ return stripped.split("|").map((c) => c.trim());
6568
+ };
6569
+ var parseInline = (text, opts = {
6570
+ theme: "dark",
6571
+ inlineCodeBackground: true
6572
+ }) => {
6573
+ if (typeof text !== "string" || text.length === 0) return "";
6574
+ const t = THEMES[opts.theme];
6575
+ const codeSlots = [];
6576
+ let s = text.replace(/`([^`\n]+)`/g, (_m, code) => {
6577
+ const styled = opts.inlineCodeBackground ? color.dim(color.hex(t.code)("\xA0" + code + "\xA0")) : color.dim(color.hex(t.code)(code));
6578
+ codeSlots.push(styled);
6579
+ return `\0CODE${codeSlots.length - 1}\0`;
6580
+ });
6581
+ s = s.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, (_m, label, url) => {
6582
+ return hyperlink(url, color.hex(t.link)(color.underline(label)));
6583
+ });
6584
+ s = s.replace(/~~([^~\n]+)~~/g, (_m, inner) => color.strikethrough(inner));
6585
+ s = s.replace(/\*\*([^*\n]+)\*\*/g, (_m, inner) => color.bold(inner));
6586
+ s = s.replace(/__([^_\n]+)__/g, (_m, inner) => color.bold(inner));
6587
+ s = s.replace(/(^|[^*])\*([^*\n]+)\*(?!\*)/g, (_m, pre, inner) => pre + color.italic(inner));
6588
+ s = s.replace(/(^|[^_])_([^_\n]+)_(?!_)/g, (_m, pre, inner) => pre + color.italic(inner));
6589
+ s = s.replace(/\x00CODE(\d+)\x00/g, (_m, idx) => codeSlots[Number(idx)] ?? "");
6590
+ return s;
6591
+ };
6592
+ var _detectWidth = () => {
6593
+ const w = process.stdout?.columns;
6594
+ return isFiniteNumber2(w) && w > 10 ? w : 80;
6595
+ };
6596
+ var render = (source, opts = {}) => {
6597
+ if (typeof source !== "string" || source.length === 0) return "";
6598
+ const {
6599
+ width = _detectWidth(),
6600
+ theme = "dark",
6601
+ headingGradient,
6602
+ boxCodeBlocks = true,
6603
+ inlineCodeBackground = true
6604
+ } = opts;
6605
+ const safeWidth = isFiniteNumber2(width) && width > 4 ? Math.floor(width) : 80;
6606
+ const t = THEMES[theme] ?? THEMES.dark;
6607
+ const h1Colors = headingGradient && headingGradient.length >= 2 ? headingGradient : t.h1;
6608
+ const blocks = parseBlocks(source);
6609
+ const inlineOpts = { theme, inlineCodeBackground };
6610
+ const out = [];
6611
+ for (const block of blocks) {
6612
+ switch (block.type) {
6613
+ case "blank":
6614
+ out.push("");
6615
+ break;
6616
+ case "hr":
6617
+ out.push(color.hex(t.hr)(ascii.divider({ width: safeWidth, char: "\u2500" })));
6618
+ break;
6619
+ case "heading": {
6620
+ const inline = parseInline(block.text, inlineOpts);
6621
+ if (block.level === 1) {
6622
+ out.push(color.bold(gradient(inline, h1Colors)));
6623
+ } else if (block.level === 2) {
6624
+ out.push(color.bold(color.underline(color.hex(t.h2)(inline))));
6625
+ } else {
6626
+ const colorKey = `h${block.level}`;
6627
+ const hex = t[colorKey];
6628
+ out.push(color.bold(color.hex(hex)(inline)));
6629
+ }
6630
+ break;
6631
+ }
6632
+ case "paragraph": {
6633
+ out.push(parseInline(block.text, inlineOpts));
6634
+ break;
6635
+ }
6636
+ case "codeblock": {
6637
+ const codeText = block.code.length > 0 ? block.code : " ";
6638
+ if (boxCodeBlocks) {
6639
+ const labeled = block.lang ? ` ${block.lang} ` : null;
6640
+ const box3 = ascii.box(codeText, {
6641
+ borderStyle: "rounded",
6642
+ padding: 1,
6643
+ title: labeled
6644
+ });
6645
+ out.push(color.hex(t.codeBlockBorder)(box3));
6646
+ } else {
6647
+ const indented = codeText.split("\n").map((l) => " " + l).join("\n");
6648
+ out.push(color.dim(indented));
6649
+ }
6650
+ break;
6651
+ }
6652
+ case "list": {
6653
+ const lines = [];
6654
+ for (let idx = 0; idx < block.items.length; idx++) {
6655
+ const marker = block.ordered ? `${idx + 1}.` : "\u2022";
6656
+ const rendered = parseInline(block.items[idx], inlineOpts);
6657
+ lines.push(` ${color.hex(t.h3)(marker)} ${rendered}`);
6658
+ }
6659
+ out.push(lines.join("\n"));
6660
+ break;
6661
+ }
6662
+ case "blockquote": {
6663
+ const rendered = parseInline(block.text, inlineOpts);
6664
+ const quoted = rendered.split("\n").map((l) => color.hex(t.blockquote)("\u2502 ") + color.dim(l)).join("\n");
6665
+ out.push(quoted);
6666
+ break;
6667
+ }
6668
+ case "table": {
6669
+ const styledHeaders = block.headers.map(
6670
+ (h) => color.bold(color.hex(t.tableHeader)(parseInline(h, inlineOpts)))
6671
+ );
6672
+ const styledRows = block.rows.map(
6673
+ (row) => row.map((cell) => parseInline(cell, inlineOpts))
6674
+ );
6675
+ out.push(components.table([styledHeaders, ...styledRows], {
6676
+ borderStyle: "rounded",
6677
+ padding: 1
6678
+ }));
6679
+ break;
6680
+ }
6681
+ }
6682
+ }
6683
+ while (out.length > 0 && out[out.length - 1] === "") out.pop();
6684
+ return out.join("\n");
6685
+ };
6686
+ var markdown = {
6687
+ render,
6688
+ parseBlocks,
6689
+ parseInline
6690
+ };
6691
+
6430
6692
  // src/configure.ts
6431
6693
  var DEFAULTS = Object.freeze({
6432
6694
  colorMode: "auto",
@@ -6734,7 +6996,23 @@ var resolveEasingByName = (e) => {
6734
6996
  };
6735
6997
 
6736
6998
  // src/index.ts
6737
- var ansimax = { color, animate, ascii, loader, frames, components, trees, themes, images, configure };
6999
+ var ansimax = {
7000
+ color,
7001
+ animate,
7002
+ ascii,
7003
+ loader,
7004
+ frames,
7005
+ components,
7006
+ trees,
7007
+ themes,
7008
+ images,
7009
+ configure,
7010
+ // v1.3.0+
7011
+ panels,
7012
+ json,
7013
+ // v1.4.0
7014
+ markdown
7015
+ };
6738
7016
  var index_default = ansimax;
6739
7017
  // Annotate the CommonJS export names for ESM import in node:
6740
7018
  0 && (module.exports = {
@@ -6769,6 +7047,8 @@ var index_default = ansimax;
6769
7047
  charWidth,
6770
7048
  clamp,
6771
7049
  clampByte,
7050
+ clampInt,
7051
+ clampPercent,
6772
7052
  clearAnsiCache,
6773
7053
  clearColorCache,
6774
7054
  clearLine,
@@ -6832,6 +7112,7 @@ var index_default = ansimax;
6832
7112
  listPresets,
6833
7113
  loader,
6834
7114
  mapTree,
7115
+ markdown,
6835
7116
  measureBlock,
6836
7117
  measureTree,
6837
7118
  memoize,
@@ -6847,6 +7128,8 @@ var index_default = ansimax;
6847
7128
  padStart,
6848
7129
  panels,
6849
7130
  parseFiglet,
7131
+ parseMarkdownBlocks,
7132
+ parseMarkdownInline,
6850
7133
  pauseListeners,
6851
7134
  presetNames,
6852
7135
  presets,
@@ -6854,6 +7137,7 @@ var index_default = ansimax;
6854
7137
  rainbow,
6855
7138
  registerFont,
6856
7139
  registerPreset,
7140
+ renderMarkdown,
6857
7141
  renderPixelArt,
6858
7142
  renderTree,
6859
7143
  renderTreeStream,