ansimax 1.4.0 → 1.4.2

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.mjs CHANGED
@@ -412,6 +412,15 @@ var clampInt = (value, min, max, fallback = 0) => {
412
412
  }
413
413
  return Math.max(min, Math.min(max, Math.floor(value)));
414
414
  };
415
+ var ensureString2 = (v) => typeof v === "string" ? v : String(v ?? "");
416
+ var clampNonNeg = (n, fallback = 0) => {
417
+ if (!isFiniteNumber2(n)) return Math.max(0, Math.floor(fallback));
418
+ return Math.max(0, Math.floor(n));
419
+ };
420
+ var clampPositiveInt = (n, fallback = 1) => {
421
+ if (!isFiniteNumber2(n)) return Math.max(1, Math.floor(fallback));
422
+ return Math.max(1, Math.floor(n));
423
+ };
415
424
  var HEX_RE = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
416
425
  var isHexColor = (hex) => typeof hex === "string" && HEX_RE.test(hex.trim());
417
426
  var hexToRgb = (hex) => {
@@ -2364,7 +2373,7 @@ var clearRenderCache = () => {
2364
2373
  _renderCache.clear();
2365
2374
  };
2366
2375
  var getRenderCacheSize = () => _renderCache.size;
2367
- var ensureString2 = (value, paramName) => {
2376
+ var ensureString3 = (value, paramName) => {
2368
2377
  if (typeof value !== "string") {
2369
2378
  throw new TypeError(
2370
2379
  `ascii: ${paramName} must be a string, got ${typeof value}`
@@ -2503,15 +2512,15 @@ var BOX_STYLES = {
2503
2512
  ascii: { tl: "+", tr: "+", bl: "+", br: "+", h: "-", v: "|" }
2504
2513
  };
2505
2514
  var big = (text) => {
2506
- const safe = ensureString2(text, "big(text)");
2515
+ const safe = ensureString3(text, "big(text)");
2507
2516
  return renderFont(safe, BLOCK, { _fontKey: "big" });
2508
2517
  };
2509
2518
  var small = (text) => {
2510
- const safe = ensureString2(text, "small(text)");
2519
+ const safe = ensureString3(text, "small(text)");
2511
2520
  return renderFont(safe, SMALL, { _fontKey: "small" });
2512
2521
  };
2513
2522
  var figlet = (text, opts = {}) => {
2514
- const safe = ensureString2(text, "figlet(text)");
2523
+ const safe = ensureString3(text, "figlet(text)");
2515
2524
  const fontName = opts.font ?? "big";
2516
2525
  const fontMap = FONTS[fontName] ?? BLOCK;
2517
2526
  return renderFont(safe, fontMap, {
@@ -2521,7 +2530,7 @@ var figlet = (text, opts = {}) => {
2521
2530
  });
2522
2531
  };
2523
2532
  var stageRender = (text, font, letterSpacing) => {
2524
- const safe = ensureString2(text, "stageRender(text)");
2533
+ const safe = ensureString3(text, "stageRender(text)");
2525
2534
  const fontMap = FONTS[font] ?? BLOCK;
2526
2535
  const renderOpts = { _fontKey: typeof font === "string" ? font : "big" };
2527
2536
  if (letterSpacing !== void 0) renderOpts.letterSpacing = letterSpacing;
@@ -2563,7 +2572,7 @@ var stageColorize = (rendered, colorFn, perCharColor) => {
2563
2572
  return rendered.split("\n").map(colorFn).join("\n");
2564
2573
  };
2565
2574
  var banner = (text, opts = {}) => {
2566
- const safe = ensureString2(text, "banner(text)");
2575
+ const safe = ensureString3(text, "banner(text)");
2567
2576
  const {
2568
2577
  font = "big",
2569
2578
  colorFn = null,
@@ -2577,7 +2586,7 @@ var banner = (text, opts = {}) => {
2577
2586
  return result;
2578
2587
  };
2579
2588
  var box = (text, opts = {}) => {
2580
- const safe = ensureString2(text, "box(text)");
2589
+ const safe = ensureString3(text, "box(text)");
2581
2590
  const {
2582
2591
  padding = 1,
2583
2592
  borderStyle = "rounded",
@@ -2658,7 +2667,7 @@ var divider = (opts = {}) => {
2658
2667
  return fill.repeat(w);
2659
2668
  };
2660
2669
  var logo = (text, opts = {}) => {
2661
- const safe = ensureString2(text, "logo(text)");
2670
+ const safe = ensureString3(text, "logo(text)");
2662
2671
  const { gradient: gfn = null, boxStyle = "double", centered = true } = opts;
2663
2672
  if (!safe.length) return box("", { borderStyle: boxStyle, padding: 1 });
2664
2673
  const art = big(safe);
@@ -2672,7 +2681,7 @@ var logo = (text, opts = {}) => {
2672
2681
  return box(lines.join("\n"), { borderStyle: boxStyle, padding: 1 });
2673
2682
  };
2674
2683
  var measure = (text, font = "big", letterSpacing) => {
2675
- const safe = ensureString2(text, "measure(text)");
2684
+ const safe = ensureString3(text, "measure(text)");
2676
2685
  if (!safe.length) return { width: 0, height: 0 };
2677
2686
  const rendered = stageRender(safe, font, letterSpacing);
2678
2687
  const lines = rendered.split("\n");
@@ -2680,7 +2689,7 @@ var measure = (text, font = "big", letterSpacing) => {
2680
2689
  return { width, height: lines.length };
2681
2690
  };
2682
2691
  var stream = async function* (text, opts = {}) {
2683
- const safe = ensureString2(text, "stream(text)");
2692
+ const safe = ensureString3(text, "stream(text)");
2684
2693
  const { font = "big", letterSpacing, granularity = "row", signal } = opts;
2685
2694
  if (!safe.length) return;
2686
2695
  if (signal?.aborted) return;
@@ -3046,11 +3055,6 @@ var ascii = {
3046
3055
 
3047
3056
  // src/loaders/index.ts
3048
3057
  var canAnimate2 = () => Boolean(process.stdout?.isTTY) && supportsColor() !== "none";
3049
- var ensureString3 = (v) => typeof v === "string" ? v : String(v ?? "");
3050
- var clampPositiveInt = (n, fallback) => {
3051
- if (!isFiniteNumber2(n)) return fallback;
3052
- return Math.max(1, Math.floor(n));
3053
- };
3054
3058
  var isUnicodeCapable = () => {
3055
3059
  const env = process.env;
3056
3060
  if (env["CI"]) return true;
@@ -3167,9 +3171,9 @@ var spin = (text = "Loading", opts = {}) => {
3167
3171
  signal,
3168
3172
  reducedMotion = false
3169
3173
  } = opts;
3170
- const safeText = ensureString3(text);
3171
- const safePrefix = ensureString3(prefix);
3172
- const safeSuffix = ensureString3(suffix);
3174
+ const safeText = ensureString2(text);
3175
+ const safePrefix = ensureString2(prefix);
3176
+ const safeSuffix = ensureString2(suffix);
3173
3177
  const safeInterval = clampPositiveInt(interval, 80);
3174
3178
  registerCrashHandlers2();
3175
3179
  const frames2 = resolveSpinnerFrames(type);
@@ -3181,7 +3185,7 @@ var spin = (text = "Loading", opts = {}) => {
3181
3185
  return (finalText, success) => {
3182
3186
  if (finalText !== void 0) {
3183
3187
  const icon = success === false ? "\u2717" : success === true ? "\u2713" : "";
3184
- write(`${safePrefix}${icon ? icon + " " : ""}${ensureString3(finalText)}${safeSuffix}`);
3188
+ write(`${safePrefix}${icon ? icon + " " : ""}${ensureString2(finalText)}${safeSuffix}`);
3185
3189
  if (persist) writeln();
3186
3190
  }
3187
3191
  };
@@ -3222,7 +3226,7 @@ var spin = (text = "Loading", opts = {}) => {
3222
3226
  if (finalText !== void 0) {
3223
3227
  const icon = success === false ? sgr(FG.red) + "\u2717" + reset() : success === true ? sgr(FG.green) + "\u2713" + reset() : "";
3224
3228
  const line = padToTerminalWidth(
3225
- `${safePrefix}${icon ? icon + " " : ""}${ensureString3(finalText)}${safeSuffix}`
3229
+ `${safePrefix}${icon ? icon + " " : ""}${ensureString2(finalText)}${safeSuffix}`
3226
3230
  );
3227
3231
  write(line);
3228
3232
  if (persist) writeln();
@@ -3251,7 +3255,7 @@ var progress = (percent, label = "", opts = {}) => {
3251
3255
  const safeWidth = clampPositiveInt(width, 30);
3252
3256
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u2588";
3253
3257
  const safeEmpty = typeof emptyChar === "string" && emptyChar.length > 0 ? emptyChar : "\u2591";
3254
- const safeLabel = ensureString3(label);
3258
+ const safeLabel = ensureString2(label);
3255
3259
  const clamped = clampPercent(percent);
3256
3260
  const filled = Math.floor(clamped / 100 * safeWidth);
3257
3261
  const empty = Math.max(0, safeWidth - filled);
@@ -3441,7 +3445,7 @@ var custom = (frames2, text = "", opts = {}) => {
3441
3445
  var countdown = async (seconds, opts = {}) => {
3442
3446
  const { label = "Starting in", color: hex, signal } = opts;
3443
3447
  const safeSeconds = isFiniteNumber2(seconds) ? Math.max(0, Math.floor(seconds)) : 0;
3444
- const safeLabel = ensureString3(label);
3448
+ const safeLabel = ensureString2(label);
3445
3449
  const colorToUse = safeColor(hex) ? hex : "#ffd700";
3446
3450
  if (!canAnimate2() || signal?.aborted) {
3447
3451
  const final = applyColor(String(safeSeconds), colorToUse);
@@ -3648,7 +3652,6 @@ var loader = {
3648
3652
  };
3649
3653
 
3650
3654
  // src/frames/index.ts
3651
- var ensureString4 = (v) => typeof v === "string" ? v : String(v ?? "");
3652
3655
  var MAX_FPS = 60;
3653
3656
  var clampFps = (fps, fallback) => {
3654
3657
  if (!isFiniteNumber2(fps)) return fallback;
@@ -3789,7 +3792,7 @@ var play = (frames2, opts = {}) => {
3789
3792
  } catch {
3790
3793
  rendered = frame2;
3791
3794
  }
3792
- const safe = ensureString4(rendered);
3795
+ const safe = ensureString2(rendered);
3793
3796
  try {
3794
3797
  write(safe);
3795
3798
  } catch {
@@ -3899,7 +3902,7 @@ var generate = (count, fn) => {
3899
3902
  if (typeof fn !== "function") return Array(safeCount).fill("");
3900
3903
  return Array.from({ length: safeCount }, (_, i) => {
3901
3904
  try {
3902
- return ensureString4(fn(i, safeCount));
3905
+ return ensureString2(fn(i, safeCount));
3903
3906
  } catch {
3904
3907
  return "";
3905
3908
  }
@@ -3957,15 +3960,15 @@ var live = (opts = {}) => {
3957
3960
  if (wasRunning) showCursorSafe2();
3958
3961
  };
3959
3962
  const update = (newFrame) => {
3960
- currentFrame = ensureString4(newFrame);
3963
+ currentFrame = ensureString2(newFrame);
3961
3964
  if (running) render2();
3962
3965
  };
3963
3966
  if (autoStart) start();
3964
3967
  return { start, stop, update, isRunning: () => running };
3965
3968
  };
3966
3969
  var morph = (frameA, frameB, steps = 8, charset = "\u2591\u2592\u2593\u2588\u2593\u2592\u2591") => {
3967
- const a0 = ensureString4(frameA);
3968
- const b0 = ensureString4(frameB);
3970
+ const a0 = ensureString2(frameA);
3971
+ const b0 = ensureString2(frameB);
3969
3972
  if (!a0 && !b0) return [""];
3970
3973
  const n = Math.max(2, isFiniteNumber2(steps) ? Math.floor(steps) : 8);
3971
3974
  const len = Math.max(a0.length, b0.length);
@@ -3992,7 +3995,7 @@ var presets2 = {
3992
3995
  const safeWidth = Math.max(0, isFiniteNumber2(width) ? Math.floor(width) : 20);
3993
3996
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u2588";
3994
3997
  const safeEmpty = typeof empty === "string" && empty.length > 0 ? empty : "\u2591";
3995
- const safeLabel = ensureString4(label);
3998
+ const safeLabel = ensureString2(label);
3996
3999
  return generate(safeWidth + 1, (i) => {
3997
4000
  const filled = safeChar.repeat(i);
3998
4001
  const rest = safeEmpty.repeat(safeWidth - i);
@@ -4012,7 +4015,7 @@ var presets2 = {
4012
4015
  /* istanbul ignore next — default opts {} */
4013
4016
  breathe: (text, opts = {}) => {
4014
4017
  const { steps = 8 } = opts;
4015
- const safeText = ensureString4(text);
4018
+ const safeText = ensureString2(text);
4016
4019
  const safeSteps2 = Math.max(1, isFiniteNumber2(steps) ? Math.floor(steps) : 8);
4017
4020
  const shades = ["\u2591", "\u2592", "\u2593", "\u2588"];
4018
4021
  return generate(safeSteps2 * 2, (i) => {
@@ -4024,7 +4027,7 @@ var presets2 = {
4024
4027
  /* istanbul ignore next — default opts {} */
4025
4028
  typeDelete: (text, opts = {}) => {
4026
4029
  const { cursor: cur = "\u258C" } = opts;
4027
- const safeText = ensureString4(text);
4030
+ const safeText = ensureString2(text);
4028
4031
  const safeCur = typeof cur === "string" ? cur : "\u258C";
4029
4032
  const typed = generate(safeText.length + 1, (i) => safeText.slice(0, i) + safeCur);
4030
4033
  const deleted = generate(safeText.length + 1, (i) => safeText.slice(0, safeText.length - i) + safeCur);
@@ -4034,15 +4037,6 @@ var presets2 = {
4034
4037
  var frames = { play, generate, live, morph, presets: presets2 };
4035
4038
 
4036
4039
  // src/components/index.ts
4037
- var ensureString5 = (v) => typeof v === "string" ? v : String(v ?? "");
4038
- var clampNonNeg = (n, fallback) => {
4039
- if (!isFiniteNumber2(n)) return fallback;
4040
- return Math.max(0, Math.floor(n));
4041
- };
4042
- var clampPositive2 = (n, fallback) => {
4043
- if (!isFiniteNumber2(n)) return fallback;
4044
- return Math.max(1, Math.floor(n));
4045
- };
4046
4040
  var safeSgrCode = (code, fallback) => {
4047
4041
  if (!isFiniteNumber2(code)) return fallback;
4048
4042
  return Math.max(0, Math.min(255, Math.floor(code)));
@@ -4089,7 +4083,7 @@ var table = (rows, opts = {}) => {
4089
4083
  if (cols === 0) return "";
4090
4084
  const processedRows = validRows.map(
4091
4085
  (row) => Array.from({ length: cols }, (_, ci) => {
4092
- const raw = ensureString5(row[ci]);
4086
+ const raw = ensureString2(row[ci]);
4093
4087
  const lines2 = raw.split("\n");
4094
4088
  return safeMaxCol !== null ? lines2.map((l) => truncateVisible(l, safeMaxCol)) : lines2;
4095
4089
  })
@@ -4140,8 +4134,8 @@ var badge = (label, value, opts = {}) => {
4140
4134
  padding = 1,
4141
4135
  border = false
4142
4136
  } = opts;
4143
- const safeLabel = ensureString5(label);
4144
- const safeValue = ensureString5(value);
4137
+ const safeLabel = ensureString2(label);
4138
+ const safeValue = ensureString2(value);
4145
4139
  const safePadding = clampNonNeg(padding, 1);
4146
4140
  const pad = " ".repeat(safePadding);
4147
4141
  const lhs = sgr(safeSgrCode(labelBg, BG.blue), safeSgrCode(labelFg, FG.white)) + pad + safeLabel + pad + reset();
@@ -4165,10 +4159,10 @@ var progressBar = (percent, opts = {}) => {
4165
4159
  color: color2 = null,
4166
4160
  gradient: gradientStops2 = null
4167
4161
  } = opts;
4168
- const safeWidth = clampPositive2(width, 30);
4162
+ const safeWidth = clampPositiveInt(width, 30);
4169
4163
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u2588";
4170
4164
  const safeEmpty = typeof emptyChar === "string" && emptyChar.length > 0 ? emptyChar : "\u2591";
4171
- const safeLabel = ensureString5(label);
4165
+ const safeLabel = ensureString2(label);
4172
4166
  const clamped = clampPercent(percent);
4173
4167
  const filled = Math.floor(clamped / 100 * safeWidth);
4174
4168
  const empty = Math.max(0, safeWidth - filled);
@@ -4195,7 +4189,7 @@ var status = (type, message, opts = {}) => {
4195
4189
  const def = STATUS_MAP[type] ?? STATUS_MAP.info;
4196
4190
  const colorCode = opts.color !== void 0 ? safeSgrCode(opts.color, def.color) : def.color;
4197
4191
  const useIcon = opts.icon === void 0 ? def.icon : opts.icon ?? "";
4198
- const safeMsg = ensureString5(message);
4192
+ const safeMsg = ensureString2(message);
4199
4193
  const iconPart = useIcon ? sgr(colorCode) + useIcon + reset() + " " : "";
4200
4194
  if (safeMsg.includes("\n")) {
4201
4195
  const indent = " ".repeat(useIcon ? visibleLen(useIcon) + 1 : 0);
@@ -4207,7 +4201,7 @@ var status = (type, message, opts = {}) => {
4207
4201
  var section = (title, opts = {}) => {
4208
4202
  const { char = "\u2500", width = null, color: colorCode = FG.cyan } = opts;
4209
4203
  const { cols } = termSize();
4210
- const safeTitle = ensureString5(title);
4204
+ const safeTitle = ensureString2(title);
4211
4205
  const safeChar = typeof char === "string" && char.length > 0 ? char : "\u2500";
4212
4206
  const safeColor2 = safeSgrCode(colorCode, FG.cyan);
4213
4207
  const titleLen = visibleLen(safeTitle);
@@ -4222,7 +4216,7 @@ var section = (title, opts = {}) => {
4222
4216
  var columns = (items, opts = {}) => {
4223
4217
  if (!Array.isArray(items) || items.length === 0) return "";
4224
4218
  const { cols: numCols = 2, gap = 2, width = null, overflow = "truncate" } = opts;
4225
- const safeCols = clampPositive2(numCols, 2);
4219
+ const safeCols = clampPositiveInt(numCols, 2);
4226
4220
  const safeGap = clampNonNeg(gap, 2);
4227
4221
  const { cols: termCols } = termSize();
4228
4222
  const totalW = width !== null && isFiniteNumber2(width) ? Math.max(safeCols, Math.floor(width)) : termCols;
@@ -4232,7 +4226,7 @@ var columns = (items, opts = {}) => {
4232
4226
  for (let i = 0; i < items.length; i += safeCols) {
4233
4227
  const chunk = items.slice(i, i + safeCols);
4234
4228
  if (overflow === "wrap") {
4235
- const cellLines = chunk.map((it) => wrapVisible(ensureString5(it), colW));
4229
+ const cellLines = chunk.map((it) => wrapVisible(ensureString2(it), colW));
4236
4230
  const rowHeight = Math.max(...cellLines.map((c) => c.length), 1);
4237
4231
  for (let line = 0; line < rowHeight; line++) {
4238
4232
  rows.push(
@@ -4242,7 +4236,7 @@ var columns = (items, opts = {}) => {
4242
4236
  } else {
4243
4237
  rows.push(
4244
4238
  chunk.map((item) => {
4245
- const t = truncateVisible(ensureString5(item), colW);
4239
+ const t = truncateVisible(ensureString2(item), colW);
4246
4240
  return padEnd(t, colW);
4247
4241
  }).join(gapStr)
4248
4242
  );
@@ -4265,15 +4259,15 @@ var timeline = (events, opts = {}) => {
4265
4259
  const safeColor2 = safeSgrCode(colorCode, FG.cyan);
4266
4260
  const safeDoneColor = safeSgrCode(doneColor, FG.green);
4267
4261
  const safePendingColor = safeSgrCode(pendingColor, FG.brightBlack);
4268
- 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));
4262
+ const computedTimeWidth = timeColumnWidth !== null && isFiniteNumber2(timeColumnWidth) ? Math.max(0, Math.floor(timeColumnWidth)) : Math.max(0, ...events.map((e) => e.time ? visibleLen(ensureString2(e.time)) : 0));
4269
4263
  const lines = [];
4270
4264
  events.forEach((ev, i) => {
4271
4265
  const isLast = i === events.length - 1;
4272
- const evLabel = ensureString5(ev.label);
4266
+ const evLabel = ensureString2(ev.label);
4273
4267
  const clr = ev.done ? safeDoneColor : i === 0 ? safeColor2 : safePendingColor;
4274
4268
  const nodeStr = sgr(clr) + safeNode + reset();
4275
4269
  const textStr = ev.done ? sgr(STYLE.bold) + evLabel + reset() : sgr(safePendingColor) + evLabel + reset();
4276
- const timePart = ev.time && computedTimeWidth > 0 ? " " + sgr(FG.brightBlack) + padEnd(ensureString5(ev.time), computedTimeWidth) + reset() : "";
4270
+ const timePart = ev.time && computedTimeWidth > 0 ? " " + sgr(FG.brightBlack) + padEnd(ensureString2(ev.time), computedTimeWidth) + reset() : "";
4277
4271
  lines.push(`${nodeStr} ${textStr}${timePart}`);
4278
4272
  if (!isLast) lines.push(sgr(safePendingColor) + safeConnector + reset());
4279
4273
  });
@@ -4295,8 +4289,8 @@ var menu = (items, opts = {}) => {
4295
4289
  if (!inp.isTTY) return Promise.resolve(multiSelect ? [] : 0);
4296
4290
  const safeColor2 = safeSgrCode(colorCode, FG.cyan);
4297
4291
  const safePointer = typeof pointer === "string" && pointer.length > 0 ? pointer : "\u25B6";
4298
- const safeTitle = title === null ? null : ensureString5(title);
4299
- const safeItems = items.map(ensureString5);
4292
+ const safeTitle = title === null ? null : ensureString2(title);
4293
+ const safeItems = items.map(ensureString2);
4300
4294
  let cursorPos = 0;
4301
4295
  let lastRenderedLines = 0;
4302
4296
  let cursorHidden = false;
@@ -4457,19 +4451,14 @@ var STYLES = {
4457
4451
  heavy: { branch: "\u2523\u2501\u2501 ", last: "\u2517\u2501\u2501 ", vert: "\u2503 ", space: " " },
4458
4452
  ascii: { branch: "+-- ", last: "`-- ", vert: "| ", space: " " }
4459
4453
  };
4460
- var ensureString6 = (v) => typeof v === "string" ? v : String(v ?? "");
4461
- var clampNonNeg2 = (n, fallback) => {
4462
- if (!isFiniteNumber2(n)) return fallback;
4463
- return Math.max(0, Math.floor(n));
4464
- };
4465
4454
  var normalizeNewlines = (s) => s.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
4466
4455
  var toTreeData = (child) => {
4467
4456
  if (typeof child === "string") return { label: child, children: [] };
4468
4457
  if (typeof child !== "object" || child === null || Array.isArray(child)) {
4469
- return { label: ensureString6(child), children: [] };
4458
+ return { label: ensureString2(child), children: [] };
4470
4459
  }
4471
4460
  return {
4472
- label: ensureString6(child.label ?? ""),
4461
+ label: ensureString2(child.label ?? ""),
4473
4462
  children: [],
4474
4463
  ...child
4475
4464
  };
@@ -4505,8 +4494,8 @@ var paletteAt = (palette, depth) => {
4505
4494
  };
4506
4495
  var formatNode = (node, depth, palette) => {
4507
4496
  const colorFn = node.color ?? paletteAt(palette, depth);
4508
- const safeLabel = normalizeNewlines(ensureString6(node.label));
4509
- const iconPrefix = node.icon ? ensureString6(node.icon) + " " : "";
4497
+ const safeLabel = normalizeNewlines(ensureString2(node.label));
4498
+ const iconPrefix = node.icon ? ensureString2(node.icon) + " " : "";
4510
4499
  const labelLines = safeLabel.split("\n");
4511
4500
  return labelLines.map((line, i) => {
4512
4501
  const text = i === 0 ? iconPrefix + line : line;
@@ -4600,7 +4589,7 @@ var renderTree = (root, opts = {}) => {
4600
4589
  indent = 0
4601
4590
  } = opts;
4602
4591
  const safeStyle = style && STYLES[style] ? style : "normal";
4603
- const safeIndent = clampNonNeg2(indent, 0);
4592
+ const safeIndent = clampNonNeg(indent, 0);
4604
4593
  const safeMaxDepth = isFiniteNumber2(maxDepth) ? Math.max(0, Math.floor(maxDepth)) : Infinity;
4605
4594
  const indentStr = " ".repeat(safeIndent);
4606
4595
  const lines = [];
@@ -5946,37 +5935,105 @@ var grid = (blocks, opts) => {
5946
5935
  const alignX = opts.alignX ?? "start";
5947
5936
  const alignY = opts.alignY ?? "start";
5948
5937
  const cellW = opts.cellWidth != null ? Math.max(0, Math.floor(opts.cellWidth)) : null;
5949
- const rows = [];
5950
- for (let i = 0; i < blocks.length; i += columns2) {
5951
- rows.push(blocks.slice(i, i + columns2));
5938
+ const cellH = opts.cellHeight != null ? Math.max(1, Math.floor(opts.cellHeight)) : null;
5939
+ const flow = opts.flow === "column" ? "column" : "row";
5940
+ const spans = blocks.map((_, i) => {
5941
+ const raw = opts.colSpan?.[i];
5942
+ if (typeof raw !== "number" || !Number.isFinite(raw) || raw < 1) return 1;
5943
+ return Math.min(columns2, Math.floor(raw));
5944
+ });
5945
+ const hasSpans = spans.some((s) => s > 1);
5946
+ const cellRows = [];
5947
+ if (flow === "column" && !hasSpans) {
5948
+ const rowCount = Math.ceil(blocks.length / columns2);
5949
+ for (let r = 0; r < rowCount; r++) cellRows.push([]);
5950
+ for (let i = 0; i < blocks.length; i++) {
5951
+ const c = Math.floor(i / rowCount);
5952
+ const r = i % rowCount;
5953
+ cellRows[r].push({ block: blocks[i], span: 1, col: c });
5954
+ }
5955
+ } else {
5956
+ let row = [];
5957
+ let colInRow = 0;
5958
+ for (let i = 0; i < blocks.length; i++) {
5959
+ const span = spans[i];
5960
+ if (colInRow + span > columns2 && row.length > 0) {
5961
+ cellRows.push(row);
5962
+ row = [];
5963
+ colInRow = 0;
5964
+ }
5965
+ row.push({ block: blocks[i], span, col: colInRow });
5966
+ colInRow += span;
5967
+ }
5968
+ if (row.length > 0) cellRows.push(row);
5952
5969
  }
5953
- let widths = null;
5970
+ let widths;
5954
5971
  if (cellW != null) {
5955
5972
  widths = Array(columns2).fill(cellW);
5956
5973
  } else {
5957
5974
  widths = Array(columns2).fill(0);
5958
- for (const row of rows) {
5959
- for (let c = 0; c < row.length; c++) {
5960
- const { maxWidth } = _splitBlock(row[c]);
5961
- if (maxWidth > widths[c]) {
5962
- widths[c] = maxWidth;
5975
+ for (const r of cellRows) {
5976
+ for (const cell of r) {
5977
+ if (cell.span === 1) {
5978
+ const { maxWidth } = _splitBlock(cell.block);
5979
+ if (maxWidth > widths[cell.col]) {
5980
+ widths[cell.col] = maxWidth;
5981
+ }
5963
5982
  }
5964
5983
  }
5965
5984
  }
5966
- }
5967
- const renderedRows = rows.map((row) => {
5968
- const padded = [];
5969
5985
  for (let c = 0; c < columns2; c++) {
5970
- padded.push(row[c] ?? "");
5986
+ if (widths[c] === 0) {
5987
+ for (const r of cellRows) {
5988
+ for (const cell of r) {
5989
+ if (cell.col <= c && cell.col + cell.span > c) {
5990
+ const { maxWidth } = _splitBlock(cell.block);
5991
+ const each = Math.ceil(maxWidth / cell.span);
5992
+ if (each > widths[c]) widths[c] = each;
5993
+ }
5994
+ }
5995
+ }
5996
+ }
5971
5997
  }
5972
- return vsplit(padded, {
5998
+ }
5999
+ const renderedRows = cellRows.map((row) => {
6000
+ const mergedBlocks = [];
6001
+ const mergedWidths = [];
6002
+ let nextCol = 0;
6003
+ for (const cell of row) {
6004
+ let w = 0;
6005
+ for (let k = 0; k < cell.span; k++) {
6006
+ w += widths[cell.col + k];
6007
+ }
6008
+ w += Math.max(0, cell.span - 1) * gapX;
6009
+ let blockToRender = cell.block;
6010
+ if (cellH != null) {
6011
+ blockToRender = _fitHeight(cell.block, cellH);
6012
+ }
6013
+ mergedBlocks.push(blockToRender);
6014
+ mergedWidths.push(w);
6015
+ nextCol += cell.span;
6016
+ }
6017
+ while (nextCol < columns2) {
6018
+ mergedBlocks.push("");
6019
+ mergedWidths.push(widths[nextCol]);
6020
+ nextCol++;
6021
+ }
6022
+ return vsplit(mergedBlocks, {
5973
6023
  gap: gapX,
5974
6024
  align: alignY,
5975
- widths
6025
+ widths: mergedWidths
5976
6026
  });
5977
6027
  });
5978
6028
  return hsplit(renderedRows, { gap: gapY, align: alignX });
5979
6029
  };
6030
+ var _fitHeight = (block, targetH) => {
6031
+ const lines = block.split("\n");
6032
+ if (lines.length === targetH) return block;
6033
+ if (lines.length > targetH) return lines.slice(0, targetH).join("\n");
6034
+ const pad = Array(targetH - lines.length).fill("");
6035
+ return [...lines, ...pad].join("\n");
6036
+ };
5980
6037
  var panels = {
5981
6038
  vsplit,
5982
6039
  hsplit,
@@ -6134,8 +6191,8 @@ var _renderValue = (value, depth, config) => {
6134
6191
  inlineItems.push(_c(`... (${remaining} more)`, COLORS.comment, useColor));
6135
6192
  }
6136
6193
  const candidate = _c("[", COLORS.bracket, useColor) + inlineItems.join(", ") + _c("]", COLORS.bracket, useColor);
6137
- const visibleLen3 = candidate.replace(/\x1b\[[0-9;]*m/g, "").length;
6138
- if (visibleLen3 <= inlineArrayMaxLength) {
6194
+ const visibleLen2 = candidate.replace(/\x1b\[[0-9;]*m/g, "").length;
6195
+ if (visibleLen2 <= inlineArrayMaxLength) {
6139
6196
  return candidate;
6140
6197
  }
6141
6198
  }
@@ -6214,38 +6271,7 @@ var json = {
6214
6271
  pretty
6215
6272
  };
6216
6273
 
6217
- // src/markdown/index.ts
6218
- var THEMES = {
6219
- dark: {
6220
- h1: ["#ff79c6", "#bd93f9", "#8be9fd"],
6221
- h2: "#bd93f9",
6222
- h3: "#8be9fd",
6223
- h4: "#50fa7b",
6224
- h5: "#f1fa8c",
6225
- h6: "#ffb86c",
6226
- code: "#ff79c6",
6227
- codeBlockBorder: "#6272a4",
6228
- link: "#8be9fd",
6229
- blockquote: "#6272a4",
6230
- hr: "#6272a4",
6231
- tableHeader: "#bd93f9"
6232
- },
6233
- light: {
6234
- h1: ["#d63384", "#6f42c1", "#0d6efd"],
6235
- h2: "#6f42c1",
6236
- h3: "#0d6efd",
6237
- h4: "#198754",
6238
- h5: "#664d03",
6239
- h6: "#fd7e14",
6240
- code: "#d63384",
6241
- codeBlockBorder: "#adb5bd",
6242
- link: "#0d6efd",
6243
- blockquote: "#6c757d",
6244
- hr: "#adb5bd",
6245
- tableHeader: "#6f42c1"
6246
- }
6247
- };
6248
- var _normalize = (text) => typeof text === "string" ? text.replace(/\r\n/g, "\n").replace(/\r/g, "\n") : "";
6274
+ // src/markdown/block-parser.ts
6249
6275
  var HEADING_RE = /^(#{1,6})\s+(.+?)\s*#*\s*$/;
6250
6276
  var ORDERED_LIST_RE = /^(\s*)(\d+)[.)]\s+(.+)$/;
6251
6277
  var UNORDERED_LIST_RE = /^(\s*)[-*+]\s+(.+)$/;
@@ -6255,6 +6281,11 @@ var CODEBLOCK_CLOSE_RE = /^```\s*$/;
6255
6281
  var BLOCKQUOTE_RE = /^>\s?(.*)$/;
6256
6282
  var TABLE_SEPARATOR_RE = /^\|?[ \t]*:?-{2,}:?[ \t]*(\|[ \t]*:?-{2,}:?[ \t]*)+\|?[ \t]*$/;
6257
6283
  var TABLE_ROW_RE = /^\|.*\|[ \t]*$/;
6284
+ var _normalize = (text) => typeof text === "string" ? text.replace(/\r\n/g, "\n").replace(/\r/g, "\n") : "";
6285
+ var _splitTableRow = (row) => {
6286
+ const stripped = row.trim().replace(/^\|/, "").replace(/\|[ \t]*$/, "");
6287
+ return stripped.split("|").map((c) => c.trim());
6288
+ };
6258
6289
  var parseBlocks = (source) => {
6259
6290
  if (typeof source !== "string" || source.length === 0) return [];
6260
6291
  const lines = _normalize(source).split("\n");
@@ -6350,14 +6381,41 @@ var parseBlocks = (source) => {
6350
6381
  }
6351
6382
  return out;
6352
6383
  };
6353
- var _splitTableRow = (row) => {
6354
- const stripped = row.trim().replace(/^\|/, "").replace(/\|[ \t]*$/, "");
6355
- return stripped.split("|").map((c) => c.trim());
6384
+
6385
+ // src/markdown/theme.ts
6386
+ var THEMES = {
6387
+ dark: {
6388
+ h1: ["#ff79c6", "#bd93f9", "#8be9fd"],
6389
+ h2: "#bd93f9",
6390
+ h3: "#8be9fd",
6391
+ h4: "#50fa7b",
6392
+ h5: "#f1fa8c",
6393
+ h6: "#ffb86c",
6394
+ code: "#ff79c6",
6395
+ codeBlockBorder: "#6272a4",
6396
+ link: "#8be9fd",
6397
+ blockquote: "#6272a4",
6398
+ hr: "#6272a4",
6399
+ tableHeader: "#bd93f9"
6400
+ },
6401
+ light: {
6402
+ h1: ["#d63384", "#6f42c1", "#0d6efd"],
6403
+ h2: "#6f42c1",
6404
+ h3: "#0d6efd",
6405
+ h4: "#198754",
6406
+ h5: "#664d03",
6407
+ h6: "#fd7e14",
6408
+ code: "#d63384",
6409
+ codeBlockBorder: "#adb5bd",
6410
+ link: "#0d6efd",
6411
+ blockquote: "#6c757d",
6412
+ hr: "#adb5bd",
6413
+ tableHeader: "#6f42c1"
6414
+ }
6356
6415
  };
6357
- var parseInline = (text, opts = {
6358
- theme: "dark",
6359
- inlineCodeBackground: true
6360
- }) => {
6416
+
6417
+ // src/markdown/inline-parser.ts
6418
+ var parseInline = (text, opts = { theme: "dark", inlineCodeBackground: true }) => {
6361
6419
  if (typeof text !== "string" || text.length === 0) return "";
6362
6420
  const t = THEMES[opts.theme];
6363
6421
  const codeSlots = [];
@@ -6377,6 +6435,8 @@ var parseInline = (text, opts = {
6377
6435
  s = s.replace(/\x00CODE(\d+)\x00/g, (_m, idx) => codeSlots[Number(idx)] ?? "");
6378
6436
  return s;
6379
6437
  };
6438
+
6439
+ // src/markdown/renderer.ts
6380
6440
  var _detectWidth = () => {
6381
6441
  const w = process.stdout?.columns;
6382
6442
  return isFiniteNumber2(w) && w > 10 ? w : 80;
@@ -6471,6 +6531,8 @@ var render = (source, opts = {}) => {
6471
6531
  while (out.length > 0 && out[out.length - 1] === "") out.pop();
6472
6532
  return out.join("\n");
6473
6533
  };
6534
+
6535
+ // src/markdown/index.ts
6474
6536
  var markdown = {
6475
6537
  render,
6476
6538
  parseBlocks,
@@ -6835,7 +6897,9 @@ export {
6835
6897
  clamp,
6836
6898
  clampByte2 as clampByte,
6837
6899
  clampInt,
6900
+ clampNonNeg,
6838
6901
  clampPercent,
6902
+ clampPositiveInt,
6839
6903
  clearAnsiCache,
6840
6904
  clearColorCache,
6841
6905
  clearLine,
@@ -6857,6 +6921,7 @@ export {
6857
6921
  index_default as default,
6858
6922
  diffLines,
6859
6923
  easings,
6924
+ ensureString2 as ensureString,
6860
6925
  escapeForRegex,
6861
6926
  escapeRegex,
6862
6927
  fg256,
@@ -118,7 +118,7 @@ async function main() {
118
118
  console.log(components.section('🏷️ Badges & Status', { width: 60 }));
119
119
  console.log();
120
120
  console.log(' ',
121
- components.badge('VERSION', 'v1.4.0'),
121
+ components.badge('VERSION', 'v1.4.2'),
122
122
  components.badge('BUILD', 'passing'),
123
123
  components.badge('LICENSE', 'Apache 2.0'));
124
124
  console.log();
@@ -117,7 +117,7 @@ console.log();
117
117
  console.log(components.section('🏷️ Badges & Status', { width: 60 }));
118
118
  console.log();
119
119
  console.log(' ',
120
- components.badge('VERSION', 'v1.4.0'),
120
+ components.badge('VERSION', 'v1.4.2'),
121
121
  components.badge('BUILD', 'passing'),
122
122
  components.badge('LICENSE', 'Apache 2.0'));
123
123
  console.log();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ansimax",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Zero-dependency CLI rendering library: colors, gradients, animations, ASCII art, pixel art, components, and themes \u2014 all in TypeScript.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",