toolcraft-openapi 0.0.18 → 0.0.19

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.
Files changed (29) hide show
  1. package/node_modules/@poe-code/design-system/dist/acp/components.js +15 -13
  2. package/node_modules/@poe-code/design-system/dist/components/color.d.ts +31 -0
  3. package/node_modules/@poe-code/design-system/dist/components/color.js +101 -0
  4. package/node_modules/@poe-code/design-system/dist/components/index.d.ts +4 -0
  5. package/node_modules/@poe-code/design-system/dist/components/index.js +2 -0
  6. package/node_modules/@poe-code/design-system/dist/components/logger.js +2 -2
  7. package/node_modules/@poe-code/design-system/dist/components/symbols.js +3 -3
  8. package/node_modules/@poe-code/design-system/dist/components/table.js +191 -40
  9. package/node_modules/@poe-code/design-system/dist/components/template.d.ts +6 -0
  10. package/node_modules/@poe-code/design-system/dist/components/template.js +271 -0
  11. package/node_modules/@poe-code/design-system/dist/components/text.js +3 -3
  12. package/node_modules/@poe-code/design-system/dist/dashboard/buffer.js +12 -12
  13. package/node_modules/@poe-code/design-system/dist/index.d.ts +4 -0
  14. package/node_modules/@poe-code/design-system/dist/index.js +2 -0
  15. package/node_modules/@poe-code/design-system/dist/internal/color-support.d.ts +9 -0
  16. package/node_modules/@poe-code/design-system/dist/internal/color-support.js +12 -0
  17. package/node_modules/@poe-code/design-system/dist/prompts/index.js +2 -2
  18. package/node_modules/@poe-code/design-system/dist/prompts/primitives/cancel.js +2 -2
  19. package/node_modules/@poe-code/design-system/dist/prompts/primitives/intro.js +2 -2
  20. package/node_modules/@poe-code/design-system/dist/prompts/primitives/log.js +4 -4
  21. package/node_modules/@poe-code/design-system/dist/prompts/primitives/note.js +5 -5
  22. package/node_modules/@poe-code/design-system/dist/prompts/primitives/outro.js +2 -2
  23. package/node_modules/@poe-code/design-system/dist/prompts/primitives/spinner.js +3 -3
  24. package/node_modules/@poe-code/design-system/dist/static/menu.js +5 -5
  25. package/node_modules/@poe-code/design-system/dist/static/spinner.js +8 -8
  26. package/node_modules/@poe-code/design-system/dist/tokens/colors.js +29 -29
  27. package/node_modules/@poe-code/design-system/dist/tokens/typography.js +6 -6
  28. package/node_modules/@poe-code/design-system/package.json +5 -3
  29. package/package.json +2 -4
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../components/color.js";
2
2
  import { resolveOutputFormat } from "../internal/output-format.js";
3
3
  import { renderMarkdown } from "../terminal-markdown/index.js";
4
4
  import { getAcpWriter } from "./writer.js";
@@ -10,20 +10,22 @@ function truncate(text, maxLength) {
10
10
  return `${text.slice(0, maxLength - 3)}...`;
11
11
  }
12
12
  const KIND_COLORS = {
13
- exec: (text) => chalk.yellow(text),
14
- edit: (text) => chalk.magenta(text),
15
- read: (text) => chalk.cyan(text),
16
- search: (text) => chalk.blue(text),
17
- think: (text) => chalk.dim(text),
18
- other: (text) => chalk.dim(text)
13
+ exec: (text) => color.yellow(text),
14
+ edit: (text) => color.magenta(text),
15
+ read: (text) => color.cyan(text),
16
+ search: (text) => color.blue(text),
17
+ think: (text) => color.dim(text),
18
+ other: (text) => color.dim(text)
19
19
  };
20
20
  function colorForKind(kind) {
21
- return KIND_COLORS[kind] ?? ((text) => chalk.dim(text));
21
+ return KIND_COLORS[kind] ?? ((text) => color.dim(text));
22
22
  }
23
23
  function writeLine(line) {
24
24
  getAcpWriter()(line);
25
25
  }
26
- const AGENT_PREFIX = `${chalk.green.bold("✓")} agent: `;
26
+ function agentPrefix() {
27
+ return `${color.green.bold("✓")} agent: `;
28
+ }
27
29
  function formatCost(costUsd) {
28
30
  return new Intl.NumberFormat("en-US", {
29
31
  style: "currency",
@@ -43,7 +45,7 @@ export function renderAgentMessage(text) {
43
45
  return;
44
46
  }
45
47
  const rendered = renderMarkdown(text).trimEnd();
46
- writeLine(`${AGENT_PREFIX}${rendered}`);
48
+ writeLine(`${agentPrefix()}${rendered}`);
47
49
  }
48
50
  export function renderToolStart(kind, title) {
49
51
  const format = resolveOutputFormat();
@@ -81,7 +83,7 @@ export function renderReasoning(text) {
81
83
  writeLine(JSON.stringify({ event: "reasoning", text }));
82
84
  return;
83
85
  }
84
- writeLine(chalk.dim(` ✓ ${truncate(text, 80)}`));
86
+ writeLine(color.dim(` ✓ ${truncate(text, 80)}`));
85
87
  }
86
88
  export function renderUsage(tokens) {
87
89
  const format = resolveOutputFormat();
@@ -105,7 +107,7 @@ export function renderUsage(tokens) {
105
107
  return;
106
108
  }
107
109
  writeLine("");
108
- writeLine(chalk.green(`✓ tokens: ${tokens.input} in${cached} → ${tokens.output} out${cost}`));
110
+ writeLine(color.green(`✓ tokens: ${tokens.input} in${cached} → ${tokens.output} out${cost}`));
109
111
  }
110
112
  export function renderError(message) {
111
113
  const format = resolveOutputFormat();
@@ -117,5 +119,5 @@ export function renderError(message) {
117
119
  writeLine(JSON.stringify({ event: "error", message }));
118
120
  return;
119
121
  }
120
- writeLine(chalk.red(`✗ ${message}`));
122
+ writeLine(color.red(`✗ ${message}`));
121
123
  }
@@ -0,0 +1,31 @@
1
+ export interface Color {
2
+ (text: string): string;
3
+ reset: Color;
4
+ bold: Color;
5
+ dim: Color;
6
+ italic: Color;
7
+ underline: Color;
8
+ inverse: Color;
9
+ strikethrough: Color;
10
+ black: Color;
11
+ red: Color;
12
+ green: Color;
13
+ yellow: Color;
14
+ blue: Color;
15
+ magenta: Color;
16
+ cyan: Color;
17
+ white: Color;
18
+ gray: Color;
19
+ magentaBright: Color;
20
+ cyanBright: Color;
21
+ bgRed: Color;
22
+ bgGreen: Color;
23
+ bgYellow: Color;
24
+ bgBlue: Color;
25
+ bgMagenta: Color;
26
+ hex: (value: string) => Color;
27
+ rgb: (red: number, green: number, blue: number) => Color;
28
+ bgHex: (value: string) => Color;
29
+ bgRgb: (red: number, green: number, blue: number) => Color;
30
+ }
31
+ export declare const color: Color;
@@ -0,0 +1,101 @@
1
+ import { supportsColor } from "../internal/color-support.js";
2
+ const reset = "\x1b[0m";
3
+ const ansiStyles = {
4
+ reset: { open: reset },
5
+ bold: { open: "\x1b[1m" },
6
+ dim: { open: "\x1b[2m" },
7
+ italic: { open: "\x1b[3m" },
8
+ underline: { open: "\x1b[4m" },
9
+ inverse: { open: "\x1b[7m" },
10
+ strikethrough: { open: "\x1b[9m" },
11
+ black: { open: "\x1b[30m" },
12
+ red: { open: "\x1b[31m" },
13
+ green: { open: "\x1b[32m" },
14
+ yellow: { open: "\x1b[33m" },
15
+ blue: { open: "\x1b[34m" },
16
+ magenta: { open: "\x1b[35m" },
17
+ cyan: { open: "\x1b[36m" },
18
+ white: { open: "\x1b[37m" },
19
+ gray: { open: "\x1b[90m" },
20
+ magentaBright: { open: "\x1b[95m" },
21
+ cyanBright: { open: "\x1b[96m" },
22
+ bgRed: { open: "\x1b[41m" },
23
+ bgGreen: { open: "\x1b[42m" },
24
+ bgYellow: { open: "\x1b[43m" },
25
+ bgBlue: { open: "\x1b[44m" },
26
+ bgMagenta: { open: "\x1b[45m" }
27
+ };
28
+ const styleNames = Object.keys(ansiStyles);
29
+ function replaceAll(value, search, replacement) {
30
+ return value.split(search).join(replacement);
31
+ }
32
+ function applyStyles(text, styles) {
33
+ if (!supportsColor() || styles.length === 0) {
34
+ return text;
35
+ }
36
+ const open = styles.map((style) => style.open).join("");
37
+ const output = text.includes(reset) ? replaceAll(text, reset, `${reset}${open}`) : text;
38
+ return `${open}${output}${reset}`;
39
+ }
40
+ function clampRgb(value) {
41
+ if (Number.isNaN(value)) {
42
+ return 0;
43
+ }
44
+ return Math.min(255, Math.max(0, Math.round(value)));
45
+ }
46
+ function hexChannel(value, offset) {
47
+ return Number.parseInt(value.slice(offset, offset + 2), 16);
48
+ }
49
+ function normalizeHex(value) {
50
+ const normalized = value.startsWith("#") ? value.slice(1) : value;
51
+ if (normalized.length === 3) {
52
+ const red = normalized[0];
53
+ const green = normalized[1];
54
+ const blue = normalized[2];
55
+ return [
56
+ Number.parseInt(`${red}${red}`, 16),
57
+ Number.parseInt(`${green}${green}`, 16),
58
+ Number.parseInt(`${blue}${blue}`, 16)
59
+ ];
60
+ }
61
+ if (normalized.length === 6) {
62
+ return [
63
+ hexChannel(normalized, 0),
64
+ hexChannel(normalized, 2),
65
+ hexChannel(normalized, 4)
66
+ ];
67
+ }
68
+ return [0, 0, 0];
69
+ }
70
+ function rgbStyle(red, green, blue) {
71
+ return {
72
+ open: `\x1b[38;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`
73
+ };
74
+ }
75
+ function bgRgbStyle(red, green, blue) {
76
+ return {
77
+ open: `\x1b[48;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`
78
+ };
79
+ }
80
+ function createColor(styles = []) {
81
+ const builder = ((text) => applyStyles(String(text), styles));
82
+ for (const name of styleNames) {
83
+ Object.defineProperty(builder, name, {
84
+ configurable: true,
85
+ enumerable: true,
86
+ get: () => createColor([...styles, ansiStyles[name]])
87
+ });
88
+ }
89
+ builder.hex = (value) => {
90
+ const [red, green, blue] = normalizeHex(value);
91
+ return createColor([...styles, rgbStyle(red, green, blue)]);
92
+ };
93
+ builder.rgb = (red, green, blue) => createColor([...styles, rgbStyle(red, green, blue)]);
94
+ builder.bgHex = (value) => {
95
+ const [red, green, blue] = normalizeHex(value);
96
+ return createColor([...styles, bgRgbStyle(red, green, blue)]);
97
+ };
98
+ builder.bgRgb = (red, green, blue) => createColor([...styles, bgRgbStyle(red, green, blue)]);
99
+ return builder;
100
+ }
101
+ export const color = createColor();
@@ -1,4 +1,6 @@
1
1
  export { text } from "./text.js";
2
+ export { color } from "./color.js";
3
+ export type { Color } from "./color.js";
2
4
  export { symbols } from "./symbols.js";
3
5
  export { createLogger, logger } from "./logger.js";
4
6
  export type { LoggerOutput } from "./logger.js";
@@ -8,3 +10,5 @@ export { formatCommandNotFound } from "./command-errors.js";
8
10
  export { formatCommandNotFoundPanel } from "./command-errors.js";
9
11
  export { renderTable } from "./table.js";
10
12
  export type { TableColumn, RenderTableOptions } from "./table.js";
13
+ export { renderTemplate } from "./template.js";
14
+ export type { RenderTemplateOptions, TemplateEscape } from "./template.js";
@@ -1,7 +1,9 @@
1
1
  export { text } from "./text.js";
2
+ export { color } from "./color.js";
2
3
  export { symbols } from "./symbols.js";
3
4
  export { createLogger, logger } from "./logger.js";
4
5
  export { helpFormatter, formatColumns, formatCommand, formatUsage, formatOption, formatCommandList, formatOptionList } from "./help-formatter.js";
5
6
  export { formatCommandNotFound } from "./command-errors.js";
6
7
  export { formatCommandNotFoundPanel } from "./command-errors.js";
7
8
  export { renderTable } from "./table.js";
9
+ export { renderTemplate } from "./template.js";
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "./color.js";
2
2
  import { log } from "../prompts/primitives/log.js";
3
3
  import { symbols } from "./symbols.js";
4
4
  export function createLogger(emitter) {
@@ -53,7 +53,7 @@ export function createLogger(emitter) {
53
53
  emitter(message);
54
54
  return;
55
55
  }
56
- log.message(message, { symbol: symbol ?? chalk.gray("│") });
56
+ log.message(message, { symbol: symbol ?? color.gray("│") });
57
57
  }
58
58
  };
59
59
  }
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "./color.js";
2
2
  import { resolveOutputFormat } from "../internal/output-format.js";
3
3
  import { getTheme } from "../internal/theme-detect.js";
4
4
  export const symbols = {
@@ -8,7 +8,7 @@ export const symbols = {
8
8
  return "info";
9
9
  if (format === "markdown")
10
10
  return "(i)";
11
- return chalk.magenta("●");
11
+ return color.magenta("●");
12
12
  },
13
13
  get success() {
14
14
  const format = resolveOutputFormat();
@@ -16,7 +16,7 @@ export const symbols = {
16
16
  return "success";
17
17
  if (format === "markdown")
18
18
  return "[ok]";
19
- return chalk.magenta("◆");
19
+ return color.magenta("◆");
20
20
  },
21
21
  get resolved() {
22
22
  const format = resolveOutputFormat();
@@ -1,52 +1,203 @@
1
- import { Table } from "console-table-printer";
2
1
  import { resolveOutputFormat } from "../internal/output-format.js";
3
2
  import { stripAnsi } from "../internal/strip-ansi.js";
3
+ const reset = "\x1b[0m";
4
+ const ellipsis = "…";
5
+ const graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
6
+ function isAnsiSequence(value, index) {
7
+ return value[index] === "\u001b" && value[index + 1] === "[";
8
+ }
9
+ function readAnsiSequence(value, index) {
10
+ let nextIndex = index + 2;
11
+ while (nextIndex < value.length && value[nextIndex] !== "m") {
12
+ nextIndex += 1;
13
+ }
14
+ if (nextIndex < value.length) {
15
+ nextIndex += 1;
16
+ }
17
+ return { sequence: value.slice(index, nextIndex), nextIndex };
18
+ }
19
+ function isCombiningCodePoint(codePoint) {
20
+ return ((codePoint >= 0x0300 && codePoint <= 0x036f) ||
21
+ (codePoint >= 0x1ab0 && codePoint <= 0x1aff) ||
22
+ (codePoint >= 0x1dc0 && codePoint <= 0x1dff) ||
23
+ (codePoint >= 0x20d0 && codePoint <= 0x20ff) ||
24
+ (codePoint >= 0xfe20 && codePoint <= 0xfe2f));
25
+ }
26
+ function isWideCodePoint(codePoint) {
27
+ return ((codePoint >= 0x1100 && codePoint <= 0x115f) ||
28
+ codePoint === 0x2329 ||
29
+ codePoint === 0x232a ||
30
+ (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||
31
+ (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
32
+ (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
33
+ (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
34
+ (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
35
+ (codePoint >= 0xff00 && codePoint <= 0xff60) ||
36
+ (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
37
+ (codePoint >= 0x2600 && codePoint <= 0x27bf) ||
38
+ (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||
39
+ (codePoint >= 0x20000 && codePoint <= 0x3fffd));
40
+ }
41
+ function isEmojiClusterCodePoint(codePoint) {
42
+ return ((codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff) ||
43
+ (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||
44
+ (codePoint >= 0x2600 && codePoint <= 0x27bf));
45
+ }
46
+ function codePointWidth(char) {
47
+ const codePoint = char.codePointAt(0) ?? 0;
48
+ if (codePoint === 0 || codePoint < 0x20 || (codePoint >= 0x7f && codePoint < 0xa0)) {
49
+ return 0;
50
+ }
51
+ if (codePoint === 0x200d ||
52
+ (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||
53
+ isCombiningCodePoint(codePoint)) {
54
+ return 0;
55
+ }
56
+ return isWideCodePoint(codePoint) ? 2 : 1;
57
+ }
58
+ function readPrintableCluster(value, index) {
59
+ const nextAnsiIndex = value.indexOf("\u001b[", index);
60
+ const plainText = value.slice(index, nextAnsiIndex === -1 ? undefined : nextAnsiIndex);
61
+ const firstSegment = graphemeSegmenter.segment(plainText)[Symbol.iterator]().next().value;
62
+ return firstSegment?.segment ?? Array.from(plainText)[0] ?? "";
63
+ }
64
+ function clusterWidth(cluster) {
65
+ const codePoints = Array.from(cluster).map((char) => char.codePointAt(0) ?? 0);
66
+ const isEmojiCluster = codePoints.length > 1 &&
67
+ codePoints.some((codePoint) => codePoint === 0x200d ||
68
+ (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||
69
+ isEmojiClusterCodePoint(codePoint));
70
+ if (isEmojiCluster) {
71
+ return 2;
72
+ }
73
+ return codePoints.reduce((width, codePoint) => width + codePointWidth(String.fromCodePoint(codePoint)), 0);
74
+ }
75
+ function displayWidth(value) {
76
+ let width = 0;
77
+ let index = 0;
78
+ while (index < value.length) {
79
+ if (isAnsiSequence(value, index)) {
80
+ index = readAnsiSequence(value, index).nextIndex;
81
+ continue;
82
+ }
83
+ const cluster = readPrintableCluster(value, index);
84
+ width += clusterWidth(cluster);
85
+ index += cluster.length;
86
+ }
87
+ return width;
88
+ }
89
+ function truncateToWidth(value, width) {
90
+ if (displayWidth(value) <= width) {
91
+ return value;
92
+ }
93
+ if (width <= 0) {
94
+ return "";
95
+ }
96
+ const targetWidth = width <= 1 ? 0 : width - displayWidth(ellipsis);
97
+ let output = "";
98
+ let currentWidth = 0;
99
+ let index = 0;
100
+ let sawAnsi = false;
101
+ while (index < value.length) {
102
+ if (isAnsiSequence(value, index)) {
103
+ const ansi = readAnsiSequence(value, index);
104
+ sawAnsi = true;
105
+ output += ansi.sequence;
106
+ index = ansi.nextIndex;
107
+ continue;
108
+ }
109
+ const cluster = readPrintableCluster(value, index);
110
+ const width = clusterWidth(cluster);
111
+ if (currentWidth + width > targetWidth) {
112
+ break;
113
+ }
114
+ output += cluster;
115
+ currentWidth += width;
116
+ index += cluster.length;
117
+ }
118
+ return `${output}${ellipsis}${sawAnsi ? reset : ""}`;
119
+ }
120
+ function padCell(value, width, alignment) {
121
+ const visibleWidth = displayWidth(value);
122
+ const padding = Math.max(0, width - visibleWidth);
123
+ if (alignment === "right") {
124
+ return `${" ".repeat(padding)}${value}`;
125
+ }
126
+ if (alignment === "center") {
127
+ const left = Math.floor(padding / 2);
128
+ const right = padding - left;
129
+ return `${" ".repeat(left)}${value}${" ".repeat(right)}`;
130
+ }
131
+ return `${value}${" ".repeat(padding)}`;
132
+ }
133
+ function getAlignment(column) {
134
+ const alignment = column.alignment;
135
+ return alignment === "right" || alignment === "center" ? alignment : "left";
136
+ }
137
+ function getColumnWidth(column) {
138
+ const configuredMin = column.minLen;
139
+ const minWidth = Math.max(1, configuredMin ?? 1);
140
+ return Math.max(minWidth, column.maxLen);
141
+ }
142
+ function computeColumns(columns) {
143
+ return columns.map((column) => ({
144
+ name: column.name,
145
+ title: column.title,
146
+ alignment: getAlignment(column),
147
+ width: getColumnWidth(column)
148
+ }));
149
+ }
150
+ function renderBorder(columns, theme, parts) {
151
+ const horizontal = theme.muted("─");
152
+ const segments = columns.map((column) => horizontal.repeat(column.width + 2));
153
+ return [
154
+ theme.muted(parts.left),
155
+ segments.join(theme.muted(parts.mid)),
156
+ theme.muted(parts.right)
157
+ ].join("");
158
+ }
159
+ function renderTerminalRow(values, columns, theme) {
160
+ const vertical = theme.muted("│");
161
+ const cells = values.map((value, index) => {
162
+ const column = columns[index];
163
+ const truncated = truncateToWidth(value, column.width);
164
+ return ` ${padCell(truncated, column.width, column.alignment)} `;
165
+ });
166
+ return `${vertical}${cells.join(vertical)}${vertical}`;
167
+ }
4
168
  function renderTableTerminal(options) {
5
169
  const { theme, columns, rows } = options;
6
- const table = new Table({
7
- style: {
8
- headerTop: {
9
- left: theme.muted("┌"),
10
- mid: theme.muted("┬"),
11
- right: theme.muted(""),
12
- other: theme.muted("")
13
- },
14
- headerBottom: {
15
- left: theme.muted("├"),
16
- mid: theme.muted("┼"),
17
- right: theme.muted("┤"),
18
- other: theme.muted("")
19
- },
20
- tableBottom: {
21
- left: theme.muted("└"),
22
- mid: theme.muted("┴"),
23
- right: theme.muted("┘"),
24
- other: theme.muted("─")
25
- },
26
- vertical: theme.muted("│"),
27
- rowSeparator: {
28
- left: theme.muted("├"),
29
- mid: theme.muted("┼"),
30
- right: theme.muted("┤"),
31
- other: theme.muted("─")
32
- }
33
- },
34
- columns: columns.map((col) => ({
35
- name: col.name,
36
- title: theme.header(col.title),
37
- alignment: col.alignment,
38
- maxLen: col.maxLen
39
- }))
40
- });
41
- for (const row of rows) {
42
- table.addRow(row);
170
+ const computedColumns = computeColumns(columns);
171
+ const separatorOptions = options;
172
+ const includeRowSeparators = separatorOptions.rowSeparator === true || separatorOptions.rowSeparators === true;
173
+ const top = renderBorder(computedColumns, theme, { left: "┌", mid: "┬", right: "┐" });
174
+ const header = renderTerminalRow(computedColumns.map((column) => theme.header(column.title)), computedColumns, theme);
175
+ const headerBottom = renderBorder(computedColumns, theme, { left: "├", mid: "┼", right: "" });
176
+ const bottom = renderBorder(computedColumns, theme, { left: "", mid: "┴", right: "┘" });
177
+ const renderedRows = [];
178
+ for (const [index, row] of rows.entries()) {
179
+ if (includeRowSeparators && index > 0) {
180
+ renderedRows.push(headerBottom);
181
+ }
182
+ renderedRows.push(renderTerminalRow(computedColumns.map((column) => row[column.name] ?? ""), computedColumns, theme));
43
183
  }
44
- return table.render();
184
+ return [top, header, headerBottom, ...renderedRows, bottom].join("\n");
45
185
  }
46
186
  function renderTableMarkdown(options) {
47
187
  const { columns, rows } = options;
48
188
  const header = `| ${columns.map((c) => c.title).join(" | ")} |`;
49
- const separator = `| ${columns.map((c) => (c.alignment === "right" ? "---:" : ":---")).join(" | ")} |`;
189
+ const separator = `| ${columns
190
+ .map((c) => {
191
+ const alignment = getAlignment(c);
192
+ if (alignment === "right") {
193
+ return "---:";
194
+ }
195
+ if (alignment === "center") {
196
+ return ":---:";
197
+ }
198
+ return ":---";
199
+ })
200
+ .join(" | ")} |`;
50
201
  const dataRows = rows.map((row) => `| ${columns.map((c) => stripAnsi(row[c.name] ?? "").replace(/\|/g, "\\|")).join(" | ")} |`);
51
202
  return [header, separator, ...dataRows].join("\n");
52
203
  }
@@ -0,0 +1,6 @@
1
+ export type TemplateEscape = "html" | "none";
2
+ export interface RenderTemplateOptions {
3
+ escape?: TemplateEscape;
4
+ yield?: string;
5
+ }
6
+ export declare function renderTemplate(template: string, view: Record<string, unknown>, options?: RenderTemplateOptions): string;
@@ -0,0 +1,271 @@
1
+ const HTML_ESCAPE = {
2
+ "&": "&amp;",
3
+ "<": "&lt;",
4
+ ">": "&gt;",
5
+ '"': "&quot;",
6
+ "'": "&#39;",
7
+ "/": "&#x2F;",
8
+ "`": "&#x60;",
9
+ "=": "&#x3D;"
10
+ };
11
+ export function renderTemplate(template, view, options = {}) {
12
+ const prepared = options.yield === undefined
13
+ ? template
14
+ : template.split("{{yield}}").join(options.yield);
15
+ const tokens = parseTemplate(prepared);
16
+ const escape = options.escape === "none" ? String : escapeHtml;
17
+ const preserveMissing = options.yield !== undefined && options.escape === "none";
18
+ return renderTokens(tokens, { view }, prepared, escape, preserveMissing);
19
+ }
20
+ function renderTemplateInContext(template, context, escape, preserveMissing) {
21
+ return renderTokens(parseTemplate(template), context, template, escape, preserveMissing);
22
+ }
23
+ function parseTemplate(template) {
24
+ const root = [];
25
+ const stack = [];
26
+ let tokens = root;
27
+ let index = 0;
28
+ while (index < template.length) {
29
+ const open = template.indexOf("{{", index);
30
+ if (open === -1) {
31
+ appendText(tokens, template.slice(index), index);
32
+ break;
33
+ }
34
+ appendText(tokens, template.slice(index, open), index);
35
+ const parsed = parseTag(template, open);
36
+ const standalone = getStandalone(template, open, parsed.end, parsed.kind);
37
+ if (standalone !== undefined) {
38
+ trimTextAfter(tokens, standalone.lineStart);
39
+ }
40
+ if (parsed.kind === "comment") {
41
+ index = standalone?.nextIndex ?? parsed.end;
42
+ continue;
43
+ }
44
+ if (parsed.kind === "partial") {
45
+ throw new Error(`Partials are not supported: "${parsed.name}"`);
46
+ }
47
+ if (parsed.kind === "delimiter") {
48
+ throw new Error("Custom delimiters are not supported");
49
+ }
50
+ if (parsed.kind === "section" || parsed.kind === "inverted") {
51
+ const token = {
52
+ type: parsed.kind,
53
+ name: parsed.name,
54
+ children: [],
55
+ rawStart: parsed.end,
56
+ rawEnd: standalone?.lineStart ?? open
57
+ };
58
+ tokens.push(token);
59
+ stack.push({ token, parent: tokens });
60
+ tokens = token.children;
61
+ index = standalone?.nextIndex ?? parsed.end;
62
+ continue;
63
+ }
64
+ if (parsed.kind === "close") {
65
+ const frame = stack.pop();
66
+ if (frame === undefined) {
67
+ throw new Error(`Closing unopened section "${parsed.name}"`);
68
+ }
69
+ if (frame.token.name !== parsed.name) {
70
+ throw new Error(`Unclosed section "${frame.token.name}" before closing "${parsed.name}"`);
71
+ }
72
+ frame.token.rawEnd = open;
73
+ tokens = frame.parent;
74
+ index = standalone?.nextIndex ?? parsed.end;
75
+ continue;
76
+ }
77
+ tokens.push({ type: parsed.kind, name: parsed.name, raw: template.slice(open, parsed.end) });
78
+ index = parsed.end;
79
+ }
80
+ const frame = stack.pop();
81
+ if (frame !== undefined) {
82
+ throw new Error(`Unclosed section "${frame.token.name}"`);
83
+ }
84
+ return root;
85
+ }
86
+ function parseTag(template, open) {
87
+ if (template.startsWith("{{{", open)) {
88
+ const close = template.indexOf("}}}", open + 3);
89
+ if (close === -1) {
90
+ throw new Error("Unclosed unescaped tag");
91
+ }
92
+ return { kind: "unescaped", name: template.slice(open + 3, close).trim(), end: close + 3 };
93
+ }
94
+ const close = template.indexOf("}}", open + 2);
95
+ if (close === -1) {
96
+ throw new Error("Unclosed tag");
97
+ }
98
+ const raw = template.slice(open + 2, close).trim();
99
+ const sigil = raw[0];
100
+ const name = sigil === undefined ? "" : raw.slice(1).trim();
101
+ const end = close + 2;
102
+ if (sigil === "#")
103
+ return { kind: "section", name, end };
104
+ if (sigil === "^")
105
+ return { kind: "inverted", name, end };
106
+ if (sigil === "/")
107
+ return { kind: "close", name, end };
108
+ if (sigil === "!")
109
+ return { kind: "comment", name, end };
110
+ if (sigil === "&")
111
+ return { kind: "unescaped", name, end };
112
+ if (sigil === ">")
113
+ return { kind: "partial", name, end };
114
+ if (sigil === "=" && raw.endsWith("="))
115
+ return { kind: "delimiter", name, end };
116
+ return { kind: "name", name: raw, end };
117
+ }
118
+ function getStandalone(template, tagStart, tagEnd, kind) {
119
+ if (!["section", "inverted", "close", "comment", "partial", "delimiter"].includes(kind)) {
120
+ return undefined;
121
+ }
122
+ const lineStart = template.lastIndexOf("\n", tagStart - 1) + 1;
123
+ if (!isWhitespace(template.slice(lineStart, tagStart))) {
124
+ return undefined;
125
+ }
126
+ let cursor = tagEnd;
127
+ while (cursor < template.length && (template[cursor] === " " || template[cursor] === "\t")) {
128
+ cursor += 1;
129
+ }
130
+ if (template.startsWith("\r\n", cursor)) {
131
+ return { lineStart, nextIndex: cursor + 2 };
132
+ }
133
+ if (template[cursor] === "\n") {
134
+ return { lineStart, nextIndex: cursor + 1 };
135
+ }
136
+ if (cursor === template.length) {
137
+ return { lineStart, nextIndex: cursor };
138
+ }
139
+ return undefined;
140
+ }
141
+ function renderTokens(tokens, context, template, escape, preserveMissing) {
142
+ let output = "";
143
+ for (const token of tokens) {
144
+ switch (token.type) {
145
+ case "text":
146
+ output += token.value;
147
+ continue;
148
+ case "name":
149
+ case "unescaped": {
150
+ const value = lookup(context, token.name);
151
+ if (value == null) {
152
+ if (preserveMissing) {
153
+ output += token.raw;
154
+ }
155
+ continue;
156
+ }
157
+ const rendered = String(value);
158
+ output += token.type === "name" ? escape(rendered) : rendered;
159
+ continue;
160
+ }
161
+ case "inverted": {
162
+ const value = lookup(context, token.name);
163
+ if (!value || (Array.isArray(value) && value.length === 0)) {
164
+ output += renderTokens(token.children, context, template, escape, preserveMissing);
165
+ }
166
+ continue;
167
+ }
168
+ case "section": {
169
+ const value = lookup(context, token.name);
170
+ if (!value) {
171
+ continue;
172
+ }
173
+ if (Array.isArray(value)) {
174
+ for (const item of value) {
175
+ output += renderTokens(token.children, pushContext(context, item), template, escape, preserveMissing);
176
+ }
177
+ continue;
178
+ }
179
+ if (typeof value === "function") {
180
+ const raw = template.slice(token.rawStart, token.rawEnd);
181
+ const rendered = value.call(context.view, raw, (nextTemplate) => renderTemplateInContext(nextTemplate, context, escape, preserveMissing));
182
+ if (rendered != null) {
183
+ output += String(rendered);
184
+ }
185
+ continue;
186
+ }
187
+ if (typeof value === "object" || typeof value === "string" || typeof value === "number") {
188
+ output += renderTokens(token.children, pushContext(context, value), template, escape, preserveMissing);
189
+ continue;
190
+ }
191
+ output += renderTokens(token.children, context, template, escape, preserveMissing);
192
+ }
193
+ }
194
+ }
195
+ return output;
196
+ }
197
+ function lookup(context, name) {
198
+ if (name === ".") {
199
+ return callLambda(context.view, context.view);
200
+ }
201
+ let cursor = context;
202
+ while (cursor !== undefined) {
203
+ const result = name.includes(".")
204
+ ? lookupDotted(cursor.view, name)
205
+ : lookupName(cursor.view, name);
206
+ if (result.hit) {
207
+ return callLambda(result.value, cursor.view);
208
+ }
209
+ cursor = cursor.parent;
210
+ }
211
+ return undefined;
212
+ }
213
+ function lookupName(view, name) {
214
+ if (!isPropertyContainer(view) || !hasProperty(view, name)) {
215
+ return { hit: false, value: undefined };
216
+ }
217
+ return { hit: true, value: view[name] };
218
+ }
219
+ function lookupDotted(view, name) {
220
+ const parts = name.split(".");
221
+ let value = view;
222
+ let hit = false;
223
+ for (let index = 0; value != null && index < parts.length; index += 1) {
224
+ const part = parts[index] ?? "";
225
+ if (index === parts.length - 1) {
226
+ hit = hasProperty(Object(value), part);
227
+ }
228
+ value = Object(value)[part];
229
+ }
230
+ return { hit, value };
231
+ }
232
+ function callLambda(value, view) {
233
+ return typeof value === "function" ? value.call(view) : value;
234
+ }
235
+ function pushContext(parent, view) {
236
+ return { view, parent };
237
+ }
238
+ function appendText(tokens, value, start) {
239
+ if (value === "") {
240
+ return;
241
+ }
242
+ const previous = tokens[tokens.length - 1];
243
+ if (previous?.type === "text") {
244
+ previous.value += value;
245
+ return;
246
+ }
247
+ tokens.push({ type: "text", value, start });
248
+ }
249
+ function trimTextAfter(tokens, lineStart) {
250
+ const previous = tokens[tokens.length - 1];
251
+ if (previous?.type !== "text") {
252
+ return;
253
+ }
254
+ const keep = Math.max(0, lineStart - previous.start);
255
+ previous.value = previous.value.slice(0, keep);
256
+ if (previous.value === "") {
257
+ tokens.pop();
258
+ }
259
+ }
260
+ function escapeHtml(value) {
261
+ return value.replace(/[&<>"'`=/]/g, (char) => HTML_ESCAPE[char] ?? char);
262
+ }
263
+ function isWhitespace(value) {
264
+ return value.trim() === "";
265
+ }
266
+ function isPropertyContainer(value) {
267
+ return (typeof value === "object" && value !== null) || typeof value === "function";
268
+ }
269
+ function hasProperty(value, key) {
270
+ return key in value;
271
+ }
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "./color.js";
2
2
  import { resolveOutputFormat } from "../internal/output-format.js";
3
3
  import { getTheme } from "../internal/theme-detect.js";
4
4
  import { typography } from "../tokens/typography.js";
@@ -57,7 +57,7 @@ export const text = {
57
57
  return content;
58
58
  if (format === "markdown")
59
59
  return `\`${content}\``;
60
- return chalk.yellow(content);
60
+ return color.yellow(content);
61
61
  },
62
62
  example(content) {
63
63
  const format = resolveOutputFormat();
@@ -73,7 +73,7 @@ export const text = {
73
73
  return content;
74
74
  if (format === "markdown")
75
75
  return `\`${content}\``;
76
- return chalk.green(content);
76
+ return color.green(content);
77
77
  },
78
78
  link(content) {
79
79
  const format = resolveOutputFormat();
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../components/color.js";
2
2
  const EMPTY_CELL = { ch: " ", style: {} };
3
3
  export class ScreenBuffer {
4
4
  _width;
@@ -119,7 +119,7 @@ export function diff(prev, next) {
119
119
  }
120
120
  export function cellToAnsi(cell) {
121
121
  const style = cell.style ?? {};
122
- let painter = chalk;
122
+ let painter = color;
123
123
  if (style.bold) {
124
124
  painter = painter.bold;
125
125
  }
@@ -177,20 +177,20 @@ function cellsEqual(left, right) {
177
177
  && left.style.dim === right.style.dim
178
178
  && left.style.underline === right.style.underline;
179
179
  }
180
- function applyForegroundColor(instance, color) {
181
- if (color.startsWith("#")) {
182
- return instance.hex(color);
180
+ function applyForegroundColor(instance, ansiColor) {
181
+ if (ansiColor.startsWith("#")) {
182
+ return instance.hex(ansiColor);
183
183
  }
184
- const painter = instance[color];
184
+ const painter = instance[ansiColor];
185
185
  return typeof painter === "function" ? painter : instance;
186
186
  }
187
- function applyBackgroundColor(instance, color) {
188
- if (color.startsWith("#")) {
189
- return instance.bgHex(color);
187
+ function applyBackgroundColor(instance, ansiColor) {
188
+ if (ansiColor.startsWith("#")) {
189
+ return instance.bgHex(ansiColor);
190
190
  }
191
- const methodName = color.startsWith("bg")
192
- ? color
193
- : `bg${color.charAt(0).toUpperCase()}${color.slice(1)}`;
191
+ const methodName = ansiColor.startsWith("bg")
192
+ ? ansiColor
193
+ : `bg${ansiColor.charAt(0).toUpperCase()}${ansiColor.slice(1)}`;
194
194
  const painter = instance[methodName];
195
195
  return typeof painter === "function" ? painter : instance;
196
196
  }
@@ -5,6 +5,8 @@ export { spacing } from "./tokens/spacing.js";
5
5
  export { typography } from "./tokens/typography.js";
6
6
  export { widths } from "./tokens/widths.js";
7
7
  export { text } from "./components/text.js";
8
+ export { color } from "./components/color.js";
9
+ export type { Color } from "./components/color.js";
8
10
  export { symbols } from "./components/symbols.js";
9
11
  export { createLogger, logger } from "./components/logger.js";
10
12
  export type { LoggerOutput } from "./components/logger.js";
@@ -15,6 +17,8 @@ export { formatCommandNotFound } from "./components/command-errors.js";
15
17
  export { formatCommandNotFoundPanel } from "./components/command-errors.js";
16
18
  export { renderTable } from "./components/table.js";
17
19
  export type { TableColumn, RenderTableOptions } from "./components/table.js";
20
+ export { renderTemplate } from "./components/template.js";
21
+ export type { RenderTemplateOptions, TemplateEscape } from "./components/template.js";
18
22
  export * as acp from "./acp/index.js";
19
23
  export * as dashboard from "./dashboard/index.js";
20
24
  export { createDashboard, shouldUseInteractiveDashboard } from "./dashboard/index.js";
@@ -6,6 +6,7 @@ export { typography } from "./tokens/typography.js";
6
6
  export { widths } from "./tokens/widths.js";
7
7
  // Components
8
8
  export { text } from "./components/text.js";
9
+ export { color } from "./components/color.js";
9
10
  export { symbols } from "./components/symbols.js";
10
11
  export { createLogger, logger } from "./components/logger.js";
11
12
  export { helpFormatter, formatColumns, formatCommand, formatUsage, formatOption, formatCommandList, formatOptionList } from "./components/help-formatter.js";
@@ -13,6 +14,7 @@ export * as helpFormatterPlain from "./components/help-formatter-plain.js";
13
14
  export { formatCommandNotFound } from "./components/command-errors.js";
14
15
  export { formatCommandNotFoundPanel } from "./components/command-errors.js";
15
16
  export { renderTable } from "./components/table.js";
17
+ export { renderTemplate } from "./components/template.js";
16
18
  // ACP rendering
17
19
  export * as acp from "./acp/index.js";
18
20
  // Dashboard
@@ -0,0 +1,9 @@
1
+ export interface ColorSupportEnv {
2
+ NO_COLOR?: string;
3
+ FORCE_COLOR?: string;
4
+ TERM?: string;
5
+ }
6
+ export interface ColorSupportStream {
7
+ isTTY?: boolean;
8
+ }
9
+ export declare function supportsColor(env?: ColorSupportEnv, stream?: ColorSupportStream): boolean;
@@ -0,0 +1,12 @@
1
+ export function supportsColor(env = process.env, stream = process.stdout) {
2
+ if (env.FORCE_COLOR !== undefined && env.FORCE_COLOR !== "0") {
3
+ return true;
4
+ }
5
+ if (env.NO_COLOR !== undefined) {
6
+ return false;
7
+ }
8
+ if (stream.isTTY !== true) {
9
+ return false;
10
+ }
11
+ return typeof env.TERM === "string" && env.TERM.length > 0 && env.TERM !== "dumb";
12
+ }
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../components/color.js";
2
2
  import * as clack from "@clack/prompts";
3
3
  import { resolveOutputFormat } from "../internal/output-format.js";
4
4
  import { stripAnsi } from "../internal/strip-ansi.js";
@@ -19,7 +19,7 @@ export function introPlain(title) {
19
19
  if (format === "json") {
20
20
  return;
21
21
  }
22
- process.stdout.write(`${chalk.gray("┌")} ${title}\n`);
22
+ process.stdout.write(`${color.gray("┌")} ${title}\n`);
23
23
  }
24
24
  export async function select(opts) {
25
25
  return clack.select(opts);
@@ -1,9 +1,9 @@
1
- import chalk from "chalk";
1
+ import { color } from "../../components/color.js";
2
2
  export { isCancel } from "@clack/prompts";
3
3
  import { resolveOutputFormat } from "../../internal/output-format.js";
4
4
  export function cancel(msg = "") {
5
5
  if (resolveOutputFormat() !== "terminal") {
6
6
  return;
7
7
  }
8
- process.stdout.write(`${chalk.gray("└")} ${chalk.red(msg)}\n\n`);
8
+ process.stdout.write(`${color.gray("└")} ${color.red(msg)}\n\n`);
9
9
  }
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../../components/color.js";
2
2
  import { text } from "../../components/text.js";
3
3
  import { resolveOutputFormat } from "../../internal/output-format.js";
4
4
  import { stripAnsi } from "../../internal/strip-ansi.js";
@@ -11,5 +11,5 @@ export function intro(title) {
11
11
  process.stdout.write(`# ${stripAnsi(title)}\n\n`);
12
12
  return;
13
13
  }
14
- process.stdout.write(`${chalk.gray("┌")} ${text.intro(title)}\n`);
14
+ process.stdout.write(`${color.gray("┌")} ${text.intro(title)}\n`);
15
15
  }
@@ -1,8 +1,8 @@
1
- import chalk from "chalk";
1
+ import { color } from "../../components/color.js";
2
2
  import { symbols } from "../../components/symbols.js";
3
3
  import { resolveOutputFormat } from "../../internal/output-format.js";
4
4
  import { stripAnsi } from "../../internal/strip-ansi.js";
5
- function writeTerminalMessage(msg, { symbol = chalk.gray("│"), secondarySymbol = chalk.gray("│"), spacing = 1, withGuide = true } = {}) {
5
+ function writeTerminalMessage(msg, { symbol = color.gray("│"), secondarySymbol = color.gray("│"), spacing = 1, withGuide = true } = {}) {
6
6
  const lines = [];
7
7
  const showGuide = withGuide !== false;
8
8
  const contentLines = msg.split("\n");
@@ -78,7 +78,7 @@ export function warn(msg) {
78
78
  process.stdout.write(`${JSON.stringify({ level: "warn", message: stripAnsi(msg) })}\n`);
79
79
  return;
80
80
  }
81
- message(msg, { symbol: chalk.yellow("▲") });
81
+ message(msg, { symbol: color.yellow("▲") });
82
82
  }
83
83
  export function error(msg) {
84
84
  const format = resolveOutputFormat();
@@ -90,7 +90,7 @@ export function error(msg) {
90
90
  process.stdout.write(`${JSON.stringify({ level: "error", message: stripAnsi(msg) })}\n`);
91
91
  return;
92
92
  }
93
- message(msg, { symbol: chalk.red("■") });
93
+ message(msg, { symbol: color.red("■") });
94
94
  }
95
95
  export const log = {
96
96
  info,
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../../components/color.js";
2
2
  import { resolveOutputFormat } from "../../internal/output-format.js";
3
3
  import { stripAnsi } from "../../internal/strip-ansi.js";
4
4
  function getVisibleWidth(value) {
@@ -8,13 +8,13 @@ function renderTerminalNote(message, title) {
8
8
  const contentLines = ["", ...message.split("\n"), ""];
9
9
  const visibleTitle = stripAnsi(title ?? "");
10
10
  const contentWidth = Math.max(visibleTitle.length, ...contentLines.map((line) => getVisibleWidth(line))) + 2;
11
- const titleLine = `${chalk.green("◇")} ${chalk.reset(title ?? "")} ${chalk.gray(`${"─".repeat(Math.max(contentWidth - visibleTitle.length - 1, 1))}╮`)}`;
11
+ const titleLine = `${color.green("◇")} ${color.reset(title ?? "")} ${color.gray(`${"─".repeat(Math.max(contentWidth - visibleTitle.length - 1, 1))}╮`)}`;
12
12
  const content = contentLines.map((line) => {
13
13
  const padding = " ".repeat(contentWidth - getVisibleWidth(line));
14
- return `${chalk.gray("│")} ${line}${padding}${chalk.gray("│")}`;
14
+ return `${color.gray("│")} ${line}${padding}${color.gray("│")}`;
15
15
  });
16
- const bottom = chalk.gray(`├${"─".repeat(contentWidth + 2)}╯`);
17
- return [chalk.gray("│"), titleLine, ...content, bottom].join("\n");
16
+ const bottom = color.gray(`├${"─".repeat(contentWidth + 2)}╯`);
17
+ return [color.gray("│"), titleLine, ...content, bottom].join("\n");
18
18
  }
19
19
  export function note(message, title) {
20
20
  const format = resolveOutputFormat();
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../../components/color.js";
2
2
  import { resolveOutputFormat } from "../../internal/output-format.js";
3
3
  import { stripAnsi } from "../../internal/strip-ansi.js";
4
4
  export function outro(message) {
@@ -12,5 +12,5 @@ export function outro(message) {
12
12
  process.stdout.write(`${JSON.stringify({ type: "outro", message: stripped })}\n`);
13
13
  return;
14
14
  }
15
- process.stdout.write(`${chalk.gray("│")}\n${chalk.gray("└")} ${message}\n\n`);
15
+ process.stdout.write(`${color.gray("│")}\n${color.gray("└")} ${message}\n\n`);
16
16
  }
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../../components/color.js";
2
2
  import { resolveOutputFormat } from "../../internal/output-format.js";
3
3
  import { stripAnsi } from "../../internal/strip-ansi.js";
4
4
  import { SPINNER_FRAMES } from "../../static/spinner.js";
@@ -62,8 +62,8 @@ export function spinner() {
62
62
  }
63
63
  clearTimer();
64
64
  const symbol = code === undefined || code === 0
65
- ? chalk.green("◆")
66
- : chalk.red("■");
65
+ ? color.green("◆")
66
+ : color.red("■");
67
67
  if (fallback) {
68
68
  process.stdout.write(`${symbol} ${currentMessage}\n`);
69
69
  return;
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../components/color.js";
2
2
  import { symbols } from "../components/symbols.js";
3
3
  import { resolveOutputFormat } from "../internal/output-format.js";
4
4
  import { getTheme } from "../internal/theme-detect.js";
@@ -20,15 +20,15 @@ export function renderMenu(opts) {
20
20
  });
21
21
  }
22
22
  const theme = getTheme();
23
- const bar = chalk.gray(symbols.bar);
23
+ const bar = color.gray(symbols.bar);
24
24
  const lines = [];
25
- lines.push(`${chalk.cyan(symbols.active)} ${opts.message}`);
25
+ lines.push(`${color.cyan(symbols.active)} ${opts.message}`);
26
26
  lines.push(bar);
27
27
  opts.options.forEach((option, index) => {
28
28
  const isSelected = index === selectedIndex;
29
- const prefix = isSelected ? chalk.cyan(symbols.active) : chalk.gray(symbols.inactive);
29
+ const prefix = isSelected ? color.cyan(symbols.active) : color.gray(symbols.inactive);
30
30
  const label = isSelected ? theme.accent(option.label) : option.label;
31
- const hint = option.hint ? chalk.dim(` (${option.hint})`) : "";
31
+ const hint = option.hint ? color.dim(` (${option.hint})`) : "";
32
32
  lines.push(`${bar} ${prefix} ${label}${hint}`);
33
33
  });
34
34
  lines.push(`${bar}`);
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import { color } from "../components/color.js";
2
2
  import { symbols } from "../components/symbols.js";
3
3
  import { resolveOutputFormat } from "../internal/output-format.js";
4
4
  export const SPINNER_FRAMES = ["◒", "◐", "◓", "◑"];
@@ -16,9 +16,9 @@ export function renderSpinnerFrame(options) {
16
16
  })}\n`;
17
17
  }
18
18
  const frame = options.frame ?? 0;
19
- const spinnerChar = chalk.magenta(SPINNER_FRAMES[frame % SPINNER_FRAMES.length]);
20
- const timerSuffix = options.timer ? chalk.dim(` [${options.timer}]`) : "";
21
- const bar = chalk.gray(symbols.bar);
19
+ const spinnerChar = color.magenta(SPINNER_FRAMES[frame % SPINNER_FRAMES.length]);
20
+ const timerSuffix = options.timer ? color.dim(` [${options.timer}]`) : "";
21
+ const bar = color.gray(symbols.bar);
22
22
  return `${spinnerChar} ${options.message}${timerSuffix}\n${bar}`;
23
23
  }
24
24
  export function renderSpinnerStopped(options) {
@@ -35,12 +35,12 @@ export function renderSpinnerStopped(options) {
35
35
  })}\n`;
36
36
  }
37
37
  const code = options.code ?? 0;
38
- const symbol = code === 0 ? chalk.green("◆") : chalk.red("■");
39
- const timerSuffix = options.timer ? chalk.dim(` [${options.timer}]`) : "";
40
- const bar = chalk.gray(symbols.bar);
38
+ const symbol = code === 0 ? color.green("◆") : color.red("■");
39
+ const timerSuffix = options.timer ? color.dim(` [${options.timer}]`) : "";
40
+ const bar = color.gray(symbols.bar);
41
41
  let output = `${symbol} ${options.message}${timerSuffix}`;
42
42
  if (options.subtext) {
43
- output += `\n${bar} ${chalk.dim(options.subtext)}`;
43
+ output += `\n${bar} ${color.dim(options.subtext)}`;
44
44
  }
45
45
  return output;
46
46
  }
@@ -1,34 +1,34 @@
1
- import chalk from "chalk";
1
+ import { color } from "../components/color.js";
2
2
  export const brand = "#a200ff";
3
3
  export const dark = {
4
- header: (text) => chalk.magentaBright.bold(text),
5
- divider: (text) => chalk.dim(text),
6
- prompt: (text) => chalk.cyan(text),
7
- number: (text) => chalk.cyanBright(text),
8
- intro: (text) => chalk.bgMagenta.white(` Poe - ${text} `),
9
- resolvedSymbol: chalk.magenta("◇"),
10
- errorSymbol: chalk.red("■"),
11
- accent: (text) => chalk.cyan(text),
12
- muted: (text) => chalk.dim(text),
13
- success: (text) => chalk.green(text),
14
- warning: (text) => chalk.yellow(text),
15
- error: (text) => chalk.red(text),
16
- info: (text) => chalk.magenta(text),
17
- badge: (text) => chalk.bgYellow.black(` ${text} `)
4
+ header: (text) => color.magentaBright.bold(text),
5
+ divider: (text) => color.dim(text),
6
+ prompt: (text) => color.cyan(text),
7
+ number: (text) => color.cyanBright(text),
8
+ intro: (text) => color.bgMagenta.white(` Poe - ${text} `),
9
+ resolvedSymbol: color.magenta("◇"),
10
+ errorSymbol: color.red("■"),
11
+ accent: (text) => color.cyan(text),
12
+ muted: (text) => color.dim(text),
13
+ success: (text) => color.green(text),
14
+ warning: (text) => color.yellow(text),
15
+ error: (text) => color.red(text),
16
+ info: (text) => color.magenta(text),
17
+ badge: (text) => color.bgYellow.black(` ${text} `)
18
18
  };
19
19
  export const light = {
20
- header: (text) => chalk.hex("#a200ff").bold(text),
21
- divider: (text) => chalk.hex("#666666")(text),
22
- prompt: (text) => chalk.hex("#006699").bold(text),
23
- number: (text) => chalk.hex("#0077cc").bold(text),
24
- intro: (text) => chalk.bgHex("#a200ff").white(` Poe - ${text} `),
25
- resolvedSymbol: chalk.hex("#a200ff")("◇"),
26
- errorSymbol: chalk.hex("#cc0000")("■"),
27
- accent: (text) => chalk.hex("#006699").bold(text),
28
- muted: (text) => chalk.hex("#666666")(text),
29
- success: (text) => chalk.hex("#008800")(text),
30
- warning: (text) => chalk.hex("#cc6600")(text),
31
- error: (text) => chalk.hex("#cc0000")(text),
32
- info: (text) => chalk.hex("#a200ff")(text),
33
- badge: (text) => chalk.bgHex("#cc6600").white(` ${text} `)
20
+ header: (text) => color.hex("#a200ff").bold(text),
21
+ divider: (text) => color.hex("#666666")(text),
22
+ prompt: (text) => color.hex("#006699").bold(text),
23
+ number: (text) => color.hex("#0077cc").bold(text),
24
+ intro: (text) => color.bgHex("#a200ff").white(` Poe - ${text} `),
25
+ resolvedSymbol: color.hex("#a200ff")("◇"),
26
+ errorSymbol: color.hex("#cc0000")("■"),
27
+ accent: (text) => color.hex("#006699").bold(text),
28
+ muted: (text) => color.hex("#666666")(text),
29
+ success: (text) => color.hex("#008800")(text),
30
+ warning: (text) => color.hex("#cc6600")(text),
31
+ error: (text) => color.hex("#cc0000")(text),
32
+ info: (text) => color.hex("#a200ff")(text),
33
+ badge: (text) => color.bgHex("#cc6600").white(` ${text} `)
34
34
  };
@@ -1,8 +1,8 @@
1
- import chalk from "chalk";
1
+ import { color } from "../components/color.js";
2
2
  export const typography = {
3
- bold: (text) => chalk.bold(text),
4
- dim: (text) => chalk.dim(text),
5
- italic: (text) => chalk.italic(text),
6
- underline: (text) => chalk.underline(text),
7
- strikethrough: (text) => chalk.strikethrough(text)
3
+ bold: (text) => color.bold(text),
4
+ dim: (text) => color.dim(text),
5
+ italic: (text) => color.italic(text),
6
+ underline: (text) => color.underline(text),
7
+ strikethrough: (text) => color.strikethrough(text)
8
8
  };
@@ -19,8 +19,10 @@
19
19
  "dist"
20
20
  ],
21
21
  "peerDependencies": {
22
- "@clack/prompts": "^1.0.0",
23
- "chalk": "^5.3.0",
24
- "console-table-printer": "^2.15.0"
22
+ "@clack/prompts": "^1.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/mustache": "^4.2.6",
26
+ "mustache": "^4.2.0"
25
27
  }
26
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft-openapi",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -32,9 +32,7 @@
32
32
  "@clack/prompts": "^1.0.0",
33
33
  "@poe-code/design-system": "^0.0.2",
34
34
  "auth-store": "^0.0.1",
35
- "chalk": "^5.6.2",
36
- "console-table-printer": "^2.15.0",
37
- "toolcraft": "^0.0.18",
35
+ "toolcraft": "^0.0.19",
38
36
  "yaml": "^2.8.2"
39
37
  },
40
38
  "engines": {