@mdxui/terminal 2.0.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/README.md +571 -0
- package/dist/ansi-css-Sk5mWtdK.d.ts +119 -0
- package/dist/ansi-css-V6JIHGsM.d.ts +119 -0
- package/dist/ansi-css-_3eSEU9d.d.ts +119 -0
- package/dist/chunk-3EFDH7PK.js +5235 -0
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-3X5IR6WE.js +884 -0
- package/dist/chunk-4FV5ZDCE.js +5236 -0
- package/dist/chunk-4OVMSF2J.js +243 -0
- package/dist/chunk-63FEETIS.js +4048 -0
- package/dist/chunk-B43KP7XJ.js +884 -0
- package/dist/chunk-BMTJXWUV.js +655 -0
- package/dist/chunk-C3SVH4N7.js +882 -0
- package/dist/chunk-EVWR7Y47.js +874 -0
- package/dist/chunk-F6A5VWUC.js +1285 -0
- package/dist/chunk-FD7KW7GE.js +882 -0
- package/dist/chunk-GBQ6UD6I.js +655 -0
- package/dist/chunk-GMDD3M6U.js +5227 -0
- package/dist/chunk-JBHRXOXM.js +1058 -0
- package/dist/chunk-JFOO3EYO.js +1182 -0
- package/dist/chunk-JQ5H3WXL.js +1291 -0
- package/dist/chunk-JQD5NASE.js +234 -0
- package/dist/chunk-KRHJP5R7.js +592 -0
- package/dist/chunk-KWF6WVJE.js +962 -0
- package/dist/chunk-LHYQVN3H.js +1038 -0
- package/dist/chunk-M3TLQLGC.js +1032 -0
- package/dist/chunk-MVW4Q5OP.js +240 -0
- package/dist/chunk-NXCZSWLU.js +1294 -0
- package/dist/chunk-O25TNRO6.js +607 -0
- package/dist/chunk-PNECDA2I.js +884 -0
- package/dist/chunk-QIHWRLJR.js +962 -0
- package/dist/chunk-QW5YMQ7K.js +882 -0
- package/dist/chunk-R5U7XKVJ.js +16 -0
- package/dist/chunk-RP2MVQLR.js +962 -0
- package/dist/chunk-TP6RXGXA.js +1087 -0
- package/dist/chunk-TQQSTITZ.js +655 -0
- package/dist/chunk-X24GWXQV.js +1281 -0
- package/dist/components/index.d.ts +802 -0
- package/dist/components/index.js +149 -0
- package/dist/data/index.d.ts +2554 -0
- package/dist/data/index.js +51 -0
- package/dist/forms/index.d.ts +1596 -0
- package/dist/forms/index.js +464 -0
- package/dist/index-CQRFZntR.d.ts +867 -0
- package/dist/index.d.ts +579 -0
- package/dist/index.js +786 -0
- package/dist/interactive-D0JkWosD.d.ts +217 -0
- package/dist/keyboard/index.d.ts +2 -0
- package/dist/keyboard/index.js +43 -0
- package/dist/renderers/index.d.ts +546 -0
- package/dist/renderers/index.js +2157 -0
- package/dist/storybook/index.d.ts +396 -0
- package/dist/storybook/index.js +641 -0
- package/dist/theme/index.d.ts +1339 -0
- package/dist/theme/index.js +123 -0
- package/dist/types-Bxu5PAgA.d.ts +710 -0
- package/dist/types-CIlop5Ji.d.ts +701 -0
- package/dist/types-Ca8p_p5X.d.ts +710 -0
- package/package.json +90 -0
- package/src/__tests__/components/data/card.test.ts +458 -0
- package/src/__tests__/components/data/list.test.ts +473 -0
- package/src/__tests__/components/data/metrics.test.ts +541 -0
- package/src/__tests__/components/data/table.test.ts +448 -0
- package/src/__tests__/components/input/field.test.ts +555 -0
- package/src/__tests__/components/input/form.test.ts +870 -0
- package/src/__tests__/components/input/search.test.ts +1238 -0
- package/src/__tests__/components/input/select.test.ts +658 -0
- package/src/__tests__/components/navigation/breadcrumb.test.ts +923 -0
- package/src/__tests__/components/navigation/command-palette.test.ts +1095 -0
- package/src/__tests__/components/navigation/sidebar.test.ts +1018 -0
- package/src/__tests__/components/navigation/tabs.test.ts +995 -0
- package/src/__tests__/components.test.tsx +1197 -0
- package/src/__tests__/core/compiler.test.ts +986 -0
- package/src/__tests__/core/parser.test.ts +785 -0
- package/src/__tests__/core/tier-switcher.test.ts +1103 -0
- package/src/__tests__/core/types.test.ts +1398 -0
- package/src/__tests__/data/collections.test.ts +1337 -0
- package/src/__tests__/data/db.test.ts +1265 -0
- package/src/__tests__/data/reactive.test.ts +1010 -0
- package/src/__tests__/data/sync.test.ts +1614 -0
- package/src/__tests__/errors.test.ts +660 -0
- package/src/__tests__/forms/integration.test.ts +444 -0
- package/src/__tests__/integration.test.ts +905 -0
- package/src/__tests__/keyboard.test.ts +1791 -0
- package/src/__tests__/renderer.test.ts +489 -0
- package/src/__tests__/renderers/ansi-css.test.ts +948 -0
- package/src/__tests__/renderers/ansi.test.ts +1366 -0
- package/src/__tests__/renderers/ascii.test.ts +1360 -0
- package/src/__tests__/renderers/interactive.test.ts +2353 -0
- package/src/__tests__/renderers/markdown.test.ts +1483 -0
- package/src/__tests__/renderers/text.test.ts +1369 -0
- package/src/__tests__/renderers/unicode.test.ts +1307 -0
- package/src/__tests__/theme.test.ts +639 -0
- package/src/__tests__/utils/assertions.ts +685 -0
- package/src/__tests__/utils/index.ts +115 -0
- package/src/__tests__/utils/test-renderer.ts +381 -0
- package/src/__tests__/utils/utils.test.ts +560 -0
- package/src/components/containers/card.ts +56 -0
- package/src/components/containers/dialog.ts +53 -0
- package/src/components/containers/index.ts +9 -0
- package/src/components/containers/panel.ts +59 -0
- package/src/components/feedback/badge.ts +40 -0
- package/src/components/feedback/index.ts +8 -0
- package/src/components/feedback/spinner.ts +23 -0
- package/src/components/helpers.ts +81 -0
- package/src/components/index.ts +153 -0
- package/src/components/layout/breadcrumb.ts +31 -0
- package/src/components/layout/index.ts +10 -0
- package/src/components/layout/list.ts +29 -0
- package/src/components/layout/sidebar.ts +79 -0
- package/src/components/layout/table.ts +62 -0
- package/src/components/primitives/box.ts +95 -0
- package/src/components/primitives/button.ts +54 -0
- package/src/components/primitives/index.ts +11 -0
- package/src/components/primitives/input.ts +88 -0
- package/src/components/primitives/select.ts +97 -0
- package/src/components/primitives/text.ts +60 -0
- package/src/components/render.ts +155 -0
- package/src/components/templates/app.ts +43 -0
- package/src/components/templates/index.ts +8 -0
- package/src/components/templates/site.ts +54 -0
- package/src/components/types.ts +777 -0
- package/src/core/compiler.ts +718 -0
- package/src/core/parser.ts +127 -0
- package/src/core/tier-switcher.ts +607 -0
- package/src/core/types.ts +672 -0
- package/src/data/collection.ts +316 -0
- package/src/data/collections.ts +50 -0
- package/src/data/context.tsx +174 -0
- package/src/data/db.ts +127 -0
- package/src/data/hooks.ts +532 -0
- package/src/data/index.ts +138 -0
- package/src/data/reactive.ts +1225 -0
- package/src/data/saas-collections.ts +375 -0
- package/src/data/sync.ts +1213 -0
- package/src/data/types.ts +660 -0
- package/src/forms/converters.ts +512 -0
- package/src/forms/index.ts +133 -0
- package/src/forms/schemas.ts +403 -0
- package/src/forms/types.ts +476 -0
- package/src/index.ts +542 -0
- package/src/keyboard/focus.ts +748 -0
- package/src/keyboard/index.ts +96 -0
- package/src/keyboard/integration.ts +371 -0
- package/src/keyboard/manager.ts +377 -0
- package/src/keyboard/presets.ts +90 -0
- package/src/renderers/ansi-css.ts +576 -0
- package/src/renderers/ansi.ts +802 -0
- package/src/renderers/ascii.ts +680 -0
- package/src/renderers/breadcrumb.ts +480 -0
- package/src/renderers/command-palette.ts +802 -0
- package/src/renderers/components/field.ts +210 -0
- package/src/renderers/components/form.ts +327 -0
- package/src/renderers/components/index.ts +21 -0
- package/src/renderers/components/search.ts +449 -0
- package/src/renderers/components/select.ts +222 -0
- package/src/renderers/index.ts +101 -0
- package/src/renderers/interactive/component-handlers.ts +622 -0
- package/src/renderers/interactive/cursor-manager.ts +147 -0
- package/src/renderers/interactive/focus-manager.ts +279 -0
- package/src/renderers/interactive/index.ts +661 -0
- package/src/renderers/interactive/input-handler.ts +164 -0
- package/src/renderers/interactive/keyboard-handler.ts +212 -0
- package/src/renderers/interactive/mouse-handler.ts +167 -0
- package/src/renderers/interactive/state-manager.ts +109 -0
- package/src/renderers/interactive/types.ts +338 -0
- package/src/renderers/interactive-string.ts +299 -0
- package/src/renderers/interactive.ts +59 -0
- package/src/renderers/markdown.ts +950 -0
- package/src/renderers/sidebar.ts +549 -0
- package/src/renderers/tabs.ts +682 -0
- package/src/renderers/text.ts +791 -0
- package/src/renderers/unicode.ts +917 -0
- package/src/renderers/utils.ts +942 -0
- package/src/router/adapters.ts +383 -0
- package/src/router/types.ts +140 -0
- package/src/router/utils.ts +452 -0
- package/src/schemas.ts +205 -0
- package/src/storybook/index.ts +91 -0
- package/src/storybook/interactive-decorator.tsx +659 -0
- package/src/storybook/keyboard-simulator.ts +501 -0
- package/src/theme/ansi-codes.ts +80 -0
- package/src/theme/box-drawing.ts +132 -0
- package/src/theme/color-convert.ts +254 -0
- package/src/theme/color-support.ts +321 -0
- package/src/theme/index.ts +134 -0
- package/src/theme/strip-ansi.ts +50 -0
- package/src/theme/tailwind-map.ts +469 -0
- package/src/theme/text-styles.ts +206 -0
- package/src/theme/theme-system.ts +568 -0
- package/src/types.ts +103 -0
|
@@ -0,0 +1,2157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ASCII_BOX_CHARS,
|
|
3
|
+
ASCII_DOUBLE_BOX_CHARS,
|
|
4
|
+
DEFAULT_RENDER_CONTEXT,
|
|
5
|
+
DEFAULT_THEME_TOKENS,
|
|
6
|
+
SPINNER_FRAMES,
|
|
7
|
+
UNICODE_DOUBLE_BOX_CHARS,
|
|
8
|
+
UNICODE_ROUNDED_BOX_CHARS,
|
|
9
|
+
UNICODE_SINGLE_BOX_CHARS,
|
|
10
|
+
UNICODE_SYMBOLS,
|
|
11
|
+
ansiToCSS,
|
|
12
|
+
ansiToHTML,
|
|
13
|
+
boxDrawingToASCII,
|
|
14
|
+
buildBox,
|
|
15
|
+
buildTableRow,
|
|
16
|
+
buildTableSeparator,
|
|
17
|
+
calculateColumnWidths,
|
|
18
|
+
createCallbackRouterAdapter,
|
|
19
|
+
extractHeaders,
|
|
20
|
+
extractPathParams,
|
|
21
|
+
extractRowValues,
|
|
22
|
+
extractStringArray,
|
|
23
|
+
findActiveItemByPath,
|
|
24
|
+
findActiveItemInSections,
|
|
25
|
+
formatSegmentLabel,
|
|
26
|
+
generateBreadcrumbSegments,
|
|
27
|
+
getASCIIBoxChars,
|
|
28
|
+
getIndentStr,
|
|
29
|
+
getProp,
|
|
30
|
+
getTextWidth,
|
|
31
|
+
getUnicodeBoxChars,
|
|
32
|
+
joinParts,
|
|
33
|
+
joinPath,
|
|
34
|
+
matchPath,
|
|
35
|
+
matchPathPattern,
|
|
36
|
+
normalizePath,
|
|
37
|
+
padText,
|
|
38
|
+
parseAnsiToSpans,
|
|
39
|
+
renderText,
|
|
40
|
+
sanitizeToASCII,
|
|
41
|
+
spanToInlineStyle,
|
|
42
|
+
wrapText
|
|
43
|
+
} from "../chunk-F6A5VWUC.js";
|
|
44
|
+
import {
|
|
45
|
+
createInteractiveRenderer,
|
|
46
|
+
renderInteractive
|
|
47
|
+
} from "../chunk-LHYQVN3H.js";
|
|
48
|
+
import {
|
|
49
|
+
ANSI,
|
|
50
|
+
hexToRgb
|
|
51
|
+
} from "../chunk-MVW4Q5OP.js";
|
|
52
|
+
import "../chunk-3RG5ZIWI.js";
|
|
53
|
+
|
|
54
|
+
// src/renderers/markdown.ts
|
|
55
|
+
function escapePipes(content) {
|
|
56
|
+
return content.replace(/\|/g, "\\|");
|
|
57
|
+
}
|
|
58
|
+
function escapeBrackets(text) {
|
|
59
|
+
return text.replace(/\[/g, "\\[").replace(/\]/g, "\\]");
|
|
60
|
+
}
|
|
61
|
+
function clampHeaderLevel(level) {
|
|
62
|
+
if (level < 1) return 1;
|
|
63
|
+
if (level > 6) return 6;
|
|
64
|
+
return level;
|
|
65
|
+
}
|
|
66
|
+
function renderText2(node) {
|
|
67
|
+
const { content, bold, italic, code, strikethrough } = node.props;
|
|
68
|
+
if (content == null) return "";
|
|
69
|
+
let text = String(content);
|
|
70
|
+
if (code) {
|
|
71
|
+
text = `\`${text}\``;
|
|
72
|
+
} else {
|
|
73
|
+
if (bold && italic) {
|
|
74
|
+
text = `***${text}***`;
|
|
75
|
+
} else if (bold) {
|
|
76
|
+
text = `**${text}**`;
|
|
77
|
+
} else if (italic) {
|
|
78
|
+
text = `*${text}*`;
|
|
79
|
+
}
|
|
80
|
+
if (strikethrough) {
|
|
81
|
+
text = `~~${text}~~`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return text;
|
|
85
|
+
}
|
|
86
|
+
function renderHeader(node) {
|
|
87
|
+
const { level, content } = node.props;
|
|
88
|
+
const headerLevel = clampHeaderLevel(level ?? 2);
|
|
89
|
+
const prefix = "#".repeat(headerLevel);
|
|
90
|
+
return `${prefix} ${content ?? ""}
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
function renderList(node, state) {
|
|
94
|
+
const { items, numbered, taskList, children: propsChildren } = node.props;
|
|
95
|
+
const nestedChildren = node.children || propsChildren;
|
|
96
|
+
const indent = " ".repeat(state.indent);
|
|
97
|
+
const lines = [];
|
|
98
|
+
if (items && items.length > 0) {
|
|
99
|
+
items.forEach((item, index) => {
|
|
100
|
+
if (taskList && typeof item === "object" && "checked" in item) {
|
|
101
|
+
const checkbox = item.checked ? "[x]" : "[ ]";
|
|
102
|
+
lines.push(`${indent}- ${checkbox} ${item.text}`);
|
|
103
|
+
} else if (numbered) {
|
|
104
|
+
lines.push(`${indent}${index + 1}. ${typeof item === "string" ? item : item.text}`);
|
|
105
|
+
} else {
|
|
106
|
+
lines.push(`${indent}- ${typeof item === "string" ? item : item.text}`);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (nestedChildren && Array.isArray(nestedChildren) && nestedChildren.length > 0) {
|
|
111
|
+
nestedChildren.forEach((child, index) => {
|
|
112
|
+
if (child.type === "list-item") {
|
|
113
|
+
const content = child.props?.content ?? "";
|
|
114
|
+
const prefix = numbered ? `${index + 1}. ` : "- ";
|
|
115
|
+
lines.push(`${indent}${prefix}${content}`);
|
|
116
|
+
if (child.children && Array.isArray(child.children) && child.children.length > 0) {
|
|
117
|
+
child.children.forEach((nestedChild) => {
|
|
118
|
+
const nestedOutput = renderNode(nestedChild, { indent: state.indent + 2 });
|
|
119
|
+
if (nestedOutput) {
|
|
120
|
+
lines.push(nestedOutput.trimEnd());
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
const childOutput = renderNode(child, { indent: state.indent + 2 });
|
|
126
|
+
if (childOutput) {
|
|
127
|
+
lines.push(childOutput.trimEnd());
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (lines.length === 0) return "";
|
|
133
|
+
return lines.join("\n") + "\n";
|
|
134
|
+
}
|
|
135
|
+
function renderTable(node) {
|
|
136
|
+
const { columns } = node.props;
|
|
137
|
+
const data = node.data ?? node.props?.data;
|
|
138
|
+
if (!columns || columns.length === 0) return "";
|
|
139
|
+
const lines = [];
|
|
140
|
+
const headerCells = columns.map((col) => ` ${col.header} `);
|
|
141
|
+
lines.push(`|${headerCells.join("|")}|`);
|
|
142
|
+
const separatorCells = columns.map((col) => {
|
|
143
|
+
const base = "---";
|
|
144
|
+
if (col.align === "center") return `:${base}:`;
|
|
145
|
+
if (col.align === "right") return `${base}:`;
|
|
146
|
+
return `${base}`;
|
|
147
|
+
});
|
|
148
|
+
lines.push(`| ${separatorCells.join(" | ")} |`);
|
|
149
|
+
if (data && data.length > 0) {
|
|
150
|
+
for (const row of data) {
|
|
151
|
+
const cells = columns.map((col) => {
|
|
152
|
+
const value = row[col.key];
|
|
153
|
+
const cellContent = value != null ? String(value) : "";
|
|
154
|
+
return ` ${escapePipes(cellContent)} `;
|
|
155
|
+
});
|
|
156
|
+
lines.push(`|${cells.join("|")}|`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return lines.join("\n") + "\n";
|
|
160
|
+
}
|
|
161
|
+
function renderCode(node) {
|
|
162
|
+
const { code, language } = node.props;
|
|
163
|
+
if (code == null) return "";
|
|
164
|
+
const lang = language ?? "";
|
|
165
|
+
return `\`\`\`${lang}
|
|
166
|
+
${code}
|
|
167
|
+
\`\`\`
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
function renderLink(node) {
|
|
171
|
+
const { text, href } = node.props;
|
|
172
|
+
return `[${escapeBrackets(text ?? "")}](${href ?? ""})`;
|
|
173
|
+
}
|
|
174
|
+
function renderButton(node) {
|
|
175
|
+
const { label, action, hotkey } = node.props;
|
|
176
|
+
const labelText = hotkey ? `${label} (${hotkey})` : label ?? "";
|
|
177
|
+
return `[${labelText}](${action ?? ""})`;
|
|
178
|
+
}
|
|
179
|
+
function renderBox(node, state) {
|
|
180
|
+
const { title, border } = node.props;
|
|
181
|
+
const lines = [];
|
|
182
|
+
if (title) {
|
|
183
|
+
lines.push(`### ${title}
|
|
184
|
+
`);
|
|
185
|
+
}
|
|
186
|
+
if (border) {
|
|
187
|
+
lines.push("---\n");
|
|
188
|
+
}
|
|
189
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
190
|
+
const childContent = node.children.map((child) => renderNode(child, state)).join("\n");
|
|
191
|
+
lines.push(childContent);
|
|
192
|
+
}
|
|
193
|
+
if (border) {
|
|
194
|
+
lines.push("\n---");
|
|
195
|
+
}
|
|
196
|
+
return lines.join("") + "\n";
|
|
197
|
+
}
|
|
198
|
+
function renderPanel(node, state) {
|
|
199
|
+
const { title, collapsible, collapsed } = node.props;
|
|
200
|
+
const lines = [];
|
|
201
|
+
if (title) {
|
|
202
|
+
lines.push(`### ${title}
|
|
203
|
+
`);
|
|
204
|
+
}
|
|
205
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
206
|
+
const childContent = node.children.map((child) => renderNode(child, state)).join("\n");
|
|
207
|
+
lines.push(childContent);
|
|
208
|
+
}
|
|
209
|
+
return lines.join("") + "\n";
|
|
210
|
+
}
|
|
211
|
+
function renderCard(node, state) {
|
|
212
|
+
const { title, subtitle, badge, titleAction, pairs, actions } = node.props;
|
|
213
|
+
const lines = [];
|
|
214
|
+
if (title) {
|
|
215
|
+
let titleLine = `### ${title}`;
|
|
216
|
+
if (badge) {
|
|
217
|
+
titleLine += ` [${badge.content}]`;
|
|
218
|
+
}
|
|
219
|
+
lines.push(titleLine);
|
|
220
|
+
if (titleAction) {
|
|
221
|
+
lines.push(`[${titleAction.label}](${titleAction.action ?? ""})`);
|
|
222
|
+
}
|
|
223
|
+
lines.push("");
|
|
224
|
+
}
|
|
225
|
+
if (subtitle) {
|
|
226
|
+
lines.push(`*${subtitle}*
|
|
227
|
+
`);
|
|
228
|
+
}
|
|
229
|
+
if (pairs && pairs.length > 0) {
|
|
230
|
+
for (const pair of pairs) {
|
|
231
|
+
const val = pair.value != null ? String(pair.value) : "";
|
|
232
|
+
lines.push(`**${pair.key}:** ${val}`);
|
|
233
|
+
}
|
|
234
|
+
lines.push("");
|
|
235
|
+
}
|
|
236
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
237
|
+
const childContent = node.children.map((child) => renderNode(child, state)).join("\n");
|
|
238
|
+
lines.push(childContent);
|
|
239
|
+
}
|
|
240
|
+
if (actions && actions.length > 0) {
|
|
241
|
+
for (const action of actions) {
|
|
242
|
+
lines.push(`[${action.label}](${action.action ?? ""})`);
|
|
243
|
+
}
|
|
244
|
+
lines.push("");
|
|
245
|
+
}
|
|
246
|
+
return lines.join("\n");
|
|
247
|
+
}
|
|
248
|
+
function renderSidebar(node) {
|
|
249
|
+
const { nav, sections } = node.props;
|
|
250
|
+
const lines = [];
|
|
251
|
+
if (sections) {
|
|
252
|
+
for (const section of sections) {
|
|
253
|
+
lines.push(`### ${section.title}
|
|
254
|
+
`);
|
|
255
|
+
for (const item of section.items) {
|
|
256
|
+
lines.push(`- [${item.label}](${item.href ?? ""})`);
|
|
257
|
+
}
|
|
258
|
+
lines.push("");
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (nav) {
|
|
262
|
+
for (const item of nav) {
|
|
263
|
+
if (item.active) {
|
|
264
|
+
lines.push(`- **[${item.label}](${item.href ?? ""})**`);
|
|
265
|
+
} else {
|
|
266
|
+
lines.push(`- [${item.label}](${item.href ?? ""})`);
|
|
267
|
+
}
|
|
268
|
+
if (item.children) {
|
|
269
|
+
for (const child of item.children) {
|
|
270
|
+
lines.push(` - [${child.label}](${child.href ?? ""})`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
lines.push("");
|
|
275
|
+
}
|
|
276
|
+
return lines.join("\n");
|
|
277
|
+
}
|
|
278
|
+
function renderBreadcrumb(node) {
|
|
279
|
+
const { items, separator } = node.props;
|
|
280
|
+
if (!items || items.length === 0) return "";
|
|
281
|
+
const sep = separator ?? " > ";
|
|
282
|
+
const parts = items.map((item, index) => {
|
|
283
|
+
const isLast = index === items.length - 1;
|
|
284
|
+
if (isLast || !item.path) {
|
|
285
|
+
return item.label;
|
|
286
|
+
}
|
|
287
|
+
return `[${item.label}](${item.path})`;
|
|
288
|
+
});
|
|
289
|
+
return parts.join(sep) + "\n";
|
|
290
|
+
}
|
|
291
|
+
function renderBadge(node) {
|
|
292
|
+
const { children, variant } = node.props;
|
|
293
|
+
return `[${children ?? ""}]`;
|
|
294
|
+
}
|
|
295
|
+
function renderDialog(node, state) {
|
|
296
|
+
const { title, open, actions } = node.props;
|
|
297
|
+
if (open === false) return "";
|
|
298
|
+
const lines = [];
|
|
299
|
+
if (title) {
|
|
300
|
+
lines.push(`### ${title}
|
|
301
|
+
`);
|
|
302
|
+
}
|
|
303
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
304
|
+
const childContent = node.children.map((child) => renderNode(child, state)).join("\n");
|
|
305
|
+
lines.push(childContent);
|
|
306
|
+
}
|
|
307
|
+
if (actions && actions.length > 0) {
|
|
308
|
+
lines.push("");
|
|
309
|
+
for (const action of actions) {
|
|
310
|
+
lines.push(`[${action.label}](${action.action})`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return lines.join("") + "\n";
|
|
314
|
+
}
|
|
315
|
+
function renderSpinner(node) {
|
|
316
|
+
const { label } = node.props;
|
|
317
|
+
return label ?? "Loading...";
|
|
318
|
+
}
|
|
319
|
+
function renderMetrics(node) {
|
|
320
|
+
const { metrics } = node.props;
|
|
321
|
+
if (!metrics || metrics.length === 0) return "";
|
|
322
|
+
const lines = [];
|
|
323
|
+
for (const m of metrics) {
|
|
324
|
+
const val = m.value != null ? String(m.value) : "";
|
|
325
|
+
let formatted = val;
|
|
326
|
+
if (m.format === "percentage" && !val.includes("%")) {
|
|
327
|
+
formatted = `${val}%`;
|
|
328
|
+
}
|
|
329
|
+
if (m.unit) {
|
|
330
|
+
formatted = `${formatted} ${m.unit}`;
|
|
331
|
+
}
|
|
332
|
+
lines.push(`**${m.label}:** ${formatted}`);
|
|
333
|
+
}
|
|
334
|
+
return lines.join("\n") + "\n";
|
|
335
|
+
}
|
|
336
|
+
function renderSingleMetric(node) {
|
|
337
|
+
const { label, value, format, unit } = node.props;
|
|
338
|
+
if (!label) return "";
|
|
339
|
+
const val = value != null ? String(value) : "";
|
|
340
|
+
let formatted = val;
|
|
341
|
+
if (format === "percentage" && !val.includes("%")) {
|
|
342
|
+
formatted = `${val}%`;
|
|
343
|
+
}
|
|
344
|
+
if (unit) {
|
|
345
|
+
formatted = `${formatted} ${unit}`;
|
|
346
|
+
}
|
|
347
|
+
return `**${label}:** ${formatted}
|
|
348
|
+
`;
|
|
349
|
+
}
|
|
350
|
+
function renderDashboard(node, state) {
|
|
351
|
+
const { title, metrics } = node.props;
|
|
352
|
+
const lines = [];
|
|
353
|
+
if (title) {
|
|
354
|
+
lines.push(`# ${title}
|
|
355
|
+
`);
|
|
356
|
+
}
|
|
357
|
+
if (metrics && metrics.length > 0) {
|
|
358
|
+
lines.push("| Metric | Value | Trend |");
|
|
359
|
+
lines.push("| :--- | :--- | :--- |");
|
|
360
|
+
for (const metric of metrics) {
|
|
361
|
+
const trend = metric.trend === "up" ? "Up" : metric.trend === "down" ? "Down" : "";
|
|
362
|
+
lines.push(`| ${metric.label} | ${metric.value} | ${trend} |`);
|
|
363
|
+
}
|
|
364
|
+
lines.push("");
|
|
365
|
+
}
|
|
366
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
367
|
+
const childContent = node.children.map((child) => renderNode(child, state)).join("\n");
|
|
368
|
+
lines.push(childContent);
|
|
369
|
+
}
|
|
370
|
+
return lines.join("\n");
|
|
371
|
+
}
|
|
372
|
+
function renderSettings(node, state) {
|
|
373
|
+
const { sections } = node.props;
|
|
374
|
+
const lines = [];
|
|
375
|
+
if (sections && sections.length > 0) {
|
|
376
|
+
for (const section of sections) {
|
|
377
|
+
lines.push(`### ${section.charAt(0).toUpperCase() + section.slice(1)}
|
|
378
|
+
`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
382
|
+
const childContent = node.children.map((child) => renderNode(child, state)).join("\n");
|
|
383
|
+
lines.push(childContent);
|
|
384
|
+
}
|
|
385
|
+
return lines.join("\n");
|
|
386
|
+
}
|
|
387
|
+
function renderInput(node) {
|
|
388
|
+
const { label, value, placeholder, disabled } = node.props;
|
|
389
|
+
const displayValue = value ?? placeholder ?? "";
|
|
390
|
+
return `**${label ?? "Input"}:** ${displayValue}`;
|
|
391
|
+
}
|
|
392
|
+
function renderSelect(node) {
|
|
393
|
+
const { label, value, options } = node.props;
|
|
394
|
+
const lines = [];
|
|
395
|
+
if (label) {
|
|
396
|
+
lines.push(`**${label}:**`);
|
|
397
|
+
}
|
|
398
|
+
if (options && options.length > 0) {
|
|
399
|
+
const selectedOption = options.find((opt) => opt.value === value);
|
|
400
|
+
if (selectedOption) {
|
|
401
|
+
lines.push(`Selected: ${selectedOption.label}`);
|
|
402
|
+
}
|
|
403
|
+
lines.push("Options:");
|
|
404
|
+
for (const opt of options) {
|
|
405
|
+
lines.push(`- ${opt.label}`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return lines.join("\n") + "\n";
|
|
409
|
+
}
|
|
410
|
+
function renderNavFooter(node) {
|
|
411
|
+
const { actions } = node.props;
|
|
412
|
+
if (!actions || actions.length === 0) return "";
|
|
413
|
+
const parts = actions.map((action) => `\`${action.key}\` ${action.label}`);
|
|
414
|
+
return parts.join(" | ") + "\n";
|
|
415
|
+
}
|
|
416
|
+
function renderHero(node) {
|
|
417
|
+
const { title, subtitle, badge, callToAction, secondaryCallToAction, actions } = node.props;
|
|
418
|
+
const lines = [];
|
|
419
|
+
if (badge) {
|
|
420
|
+
lines.push(`[${badge}]
|
|
421
|
+
`);
|
|
422
|
+
}
|
|
423
|
+
if (title) {
|
|
424
|
+
lines.push(`# ${title}
|
|
425
|
+
`);
|
|
426
|
+
}
|
|
427
|
+
if (subtitle) {
|
|
428
|
+
lines.push(`${subtitle}
|
|
429
|
+
`);
|
|
430
|
+
}
|
|
431
|
+
if (callToAction) {
|
|
432
|
+
lines.push(`[${callToAction}](${actions?.primary ?? ""})`);
|
|
433
|
+
}
|
|
434
|
+
if (secondaryCallToAction) {
|
|
435
|
+
lines.push(`[${secondaryCallToAction}](${actions?.secondary ?? ""})`);
|
|
436
|
+
}
|
|
437
|
+
return lines.join("\n") + "\n";
|
|
438
|
+
}
|
|
439
|
+
function renderFeatures(node) {
|
|
440
|
+
const { title, features } = node.props;
|
|
441
|
+
const lines = [];
|
|
442
|
+
if (title) {
|
|
443
|
+
lines.push(`## ${title}
|
|
444
|
+
`);
|
|
445
|
+
}
|
|
446
|
+
if (features && features.length > 0) {
|
|
447
|
+
for (const feature of features) {
|
|
448
|
+
lines.push(`### ${feature.title}`);
|
|
449
|
+
lines.push(feature.description);
|
|
450
|
+
lines.push("");
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return lines.join("\n");
|
|
454
|
+
}
|
|
455
|
+
function renderPricing(node) {
|
|
456
|
+
const { tiers } = node.props;
|
|
457
|
+
if (!tiers || tiers.length === 0) return "";
|
|
458
|
+
const lines = [];
|
|
459
|
+
for (const tier of tiers) {
|
|
460
|
+
lines.push(`### ${tier.name}`);
|
|
461
|
+
lines.push(`**${tier.price}**`);
|
|
462
|
+
lines.push("");
|
|
463
|
+
if (tier.features && tier.features.length > 0) {
|
|
464
|
+
for (const feature of tier.features) {
|
|
465
|
+
lines.push(`- ${feature}`);
|
|
466
|
+
}
|
|
467
|
+
lines.push("");
|
|
468
|
+
}
|
|
469
|
+
if (tier.callToAction) {
|
|
470
|
+
lines.push(`[${tier.callToAction}]()
|
|
471
|
+
`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return lines.join("\n");
|
|
475
|
+
}
|
|
476
|
+
function renderFAQ(node) {
|
|
477
|
+
const { title, items } = node.props;
|
|
478
|
+
const lines = [];
|
|
479
|
+
if (title) {
|
|
480
|
+
lines.push(`## ${title}
|
|
481
|
+
`);
|
|
482
|
+
}
|
|
483
|
+
if (items && items.length > 0) {
|
|
484
|
+
for (const item of items) {
|
|
485
|
+
lines.push(`**${item.question}**`);
|
|
486
|
+
lines.push(item.answer);
|
|
487
|
+
lines.push("");
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return lines.join("\n");
|
|
491
|
+
}
|
|
492
|
+
function renderFooter(node) {
|
|
493
|
+
const { links, copyright, social } = node.props;
|
|
494
|
+
const lines = [];
|
|
495
|
+
lines.push("---\n");
|
|
496
|
+
if (links && links.length > 0) {
|
|
497
|
+
for (const section of links) {
|
|
498
|
+
lines.push(`### ${section.title}`);
|
|
499
|
+
for (const link of section.links) {
|
|
500
|
+
lines.push(`- [${link.label}](${link.href})`);
|
|
501
|
+
}
|
|
502
|
+
lines.push("");
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (social && social.length > 0) {
|
|
506
|
+
const socialLinks = social.map((s) => `[${s.platform}](${s.href})`).join(" | ");
|
|
507
|
+
lines.push(socialLinks);
|
|
508
|
+
lines.push("");
|
|
509
|
+
}
|
|
510
|
+
if (copyright) {
|
|
511
|
+
lines.push(`${copyright}
|
|
512
|
+
`);
|
|
513
|
+
}
|
|
514
|
+
return lines.join("\n");
|
|
515
|
+
}
|
|
516
|
+
function renderSiteHeader(node) {
|
|
517
|
+
const { nav, callToAction, actions, breadcrumbs } = node.props;
|
|
518
|
+
const lines = [];
|
|
519
|
+
if (nav && nav.length > 0) {
|
|
520
|
+
const navLinks = nav.map((item) => `[${item.label}](${item.href})`).join(" | ");
|
|
521
|
+
lines.push(navLinks);
|
|
522
|
+
}
|
|
523
|
+
if (callToAction) {
|
|
524
|
+
lines.push(`[${callToAction}](${actions?.primary ?? ""})`);
|
|
525
|
+
}
|
|
526
|
+
if (breadcrumbs && breadcrumbs.length > 0) {
|
|
527
|
+
const crumbs = breadcrumbs.map((b, i) => {
|
|
528
|
+
if (b.href && i < breadcrumbs.length - 1) {
|
|
529
|
+
return `[${b.label}](${b.href})`;
|
|
530
|
+
}
|
|
531
|
+
return b.label;
|
|
532
|
+
}).join(" > ");
|
|
533
|
+
lines.push(crumbs);
|
|
534
|
+
}
|
|
535
|
+
return lines.join("\n") + "\n";
|
|
536
|
+
}
|
|
537
|
+
function renderNode(node, state = { indent: 0 }) {
|
|
538
|
+
if (node.type === "header" && (node.props?.nav || node.props?.breadcrumbs || node.props?.callToAction)) {
|
|
539
|
+
return renderSiteHeader(node);
|
|
540
|
+
}
|
|
541
|
+
switch (node.type) {
|
|
542
|
+
case "text":
|
|
543
|
+
return renderText2(node);
|
|
544
|
+
case "header":
|
|
545
|
+
return renderHeader(node);
|
|
546
|
+
case "list":
|
|
547
|
+
return renderList(node, state);
|
|
548
|
+
case "table":
|
|
549
|
+
return renderTable(node);
|
|
550
|
+
case "code":
|
|
551
|
+
return renderCode(node);
|
|
552
|
+
case "link":
|
|
553
|
+
return renderLink(node);
|
|
554
|
+
case "button":
|
|
555
|
+
return renderButton(node);
|
|
556
|
+
case "box":
|
|
557
|
+
return renderBox(node, state);
|
|
558
|
+
case "panel":
|
|
559
|
+
return renderPanel(node, state);
|
|
560
|
+
case "card":
|
|
561
|
+
return renderCard(node, state);
|
|
562
|
+
case "sidebar":
|
|
563
|
+
return renderSidebar(node);
|
|
564
|
+
case "breadcrumb":
|
|
565
|
+
return renderBreadcrumb(node);
|
|
566
|
+
case "badge":
|
|
567
|
+
return renderBadge(node);
|
|
568
|
+
case "dialog":
|
|
569
|
+
return renderDialog(node, state);
|
|
570
|
+
case "spinner":
|
|
571
|
+
return renderSpinner(node);
|
|
572
|
+
case "metrics":
|
|
573
|
+
return renderMetrics(node);
|
|
574
|
+
case "metric":
|
|
575
|
+
return renderSingleMetric(node);
|
|
576
|
+
case "dashboard":
|
|
577
|
+
return renderDashboard(node, state);
|
|
578
|
+
case "settings":
|
|
579
|
+
return renderSettings(node, state);
|
|
580
|
+
case "input":
|
|
581
|
+
return renderInput(node);
|
|
582
|
+
case "select":
|
|
583
|
+
return renderSelect(node);
|
|
584
|
+
case "nav-footer":
|
|
585
|
+
return renderNavFooter(node);
|
|
586
|
+
case "hero":
|
|
587
|
+
return renderHero(node);
|
|
588
|
+
case "features":
|
|
589
|
+
return renderFeatures(node);
|
|
590
|
+
case "pricing":
|
|
591
|
+
return renderPricing(node);
|
|
592
|
+
case "faq":
|
|
593
|
+
return renderFAQ(node);
|
|
594
|
+
case "footer":
|
|
595
|
+
return renderFooter(node);
|
|
596
|
+
default: {
|
|
597
|
+
const defaultChildren = Array.isArray(node.children) ? node.children : [];
|
|
598
|
+
if (defaultChildren.length > 0) {
|
|
599
|
+
return defaultChildren.map((child) => renderNode(child, state)).join("\n");
|
|
600
|
+
}
|
|
601
|
+
return "";
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
function renderMarkdown(node, options) {
|
|
606
|
+
const result = renderNode(node, { indent: 0 });
|
|
607
|
+
const lines = result.split("\n").map((line) => line.trimEnd());
|
|
608
|
+
return lines.join("\n");
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// src/renderers/ascii.ts
|
|
612
|
+
var DEFAULT_WIDTH = DEFAULT_RENDER_CONTEXT.width;
|
|
613
|
+
var DEFAULT_HEIGHT = DEFAULT_RENDER_CONTEXT.height;
|
|
614
|
+
var DEFAULT_THEME = { ...DEFAULT_THEME_TOKENS };
|
|
615
|
+
function createDefaultContext() {
|
|
616
|
+
return {
|
|
617
|
+
tier: "ascii",
|
|
618
|
+
width: DEFAULT_WIDTH,
|
|
619
|
+
height: DEFAULT_HEIGHT,
|
|
620
|
+
depth: 0,
|
|
621
|
+
theme: DEFAULT_THEME,
|
|
622
|
+
interactive: false
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function renderASCII(node, context) {
|
|
626
|
+
const ctx = context ?? createDefaultContext();
|
|
627
|
+
return renderNode2(node, ctx);
|
|
628
|
+
}
|
|
629
|
+
function renderNode2(node, ctx) {
|
|
630
|
+
switch (node.type) {
|
|
631
|
+
case "text":
|
|
632
|
+
return renderText3(node, ctx);
|
|
633
|
+
case "box":
|
|
634
|
+
return renderBox2(node, ctx);
|
|
635
|
+
case "table":
|
|
636
|
+
return renderTable2(node, ctx);
|
|
637
|
+
case "list":
|
|
638
|
+
return renderList2(node, ctx);
|
|
639
|
+
case "progress":
|
|
640
|
+
return renderProgress(node, ctx);
|
|
641
|
+
case "spinner":
|
|
642
|
+
return renderSpinner2(node, ctx);
|
|
643
|
+
case "panel":
|
|
644
|
+
return renderPanel2(node, ctx);
|
|
645
|
+
case "card":
|
|
646
|
+
return renderCard2(node, ctx);
|
|
647
|
+
case "badge":
|
|
648
|
+
return renderBadge2(node, ctx);
|
|
649
|
+
case "button":
|
|
650
|
+
return renderButton2(node, ctx);
|
|
651
|
+
case "input":
|
|
652
|
+
return renderInput2(node, ctx);
|
|
653
|
+
case "select":
|
|
654
|
+
return renderSelect2(node, ctx);
|
|
655
|
+
case "dialog":
|
|
656
|
+
return renderDialog2(node, ctx);
|
|
657
|
+
case "breadcrumb":
|
|
658
|
+
return renderBreadcrumb2(node, ctx);
|
|
659
|
+
case "sidebar":
|
|
660
|
+
return renderSidebar2(node, ctx);
|
|
661
|
+
case "metrics":
|
|
662
|
+
return renderMetrics2(node, ctx);
|
|
663
|
+
case "metric":
|
|
664
|
+
return renderSingleMetric2(node, ctx);
|
|
665
|
+
default:
|
|
666
|
+
return renderChildren(node, ctx);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
function renderChildren(node, ctx) {
|
|
670
|
+
if (!node.children || node.children.length === 0) {
|
|
671
|
+
return "";
|
|
672
|
+
}
|
|
673
|
+
if (typeof node.children === "string") {
|
|
674
|
+
return node.children;
|
|
675
|
+
}
|
|
676
|
+
return node.children.map((child) => renderNode2(child, ctx)).join("\n");
|
|
677
|
+
}
|
|
678
|
+
function renderText3(node, ctx) {
|
|
679
|
+
const content = String(node.props?.content ?? "");
|
|
680
|
+
const sanitized = sanitizeToASCII(content);
|
|
681
|
+
const width = ctx.width > 0 ? ctx.width : DEFAULT_WIDTH;
|
|
682
|
+
const lines = wrapText(sanitized, width);
|
|
683
|
+
return lines.join("\n");
|
|
684
|
+
}
|
|
685
|
+
function renderBox2(node, ctx) {
|
|
686
|
+
const border = node.props?.border;
|
|
687
|
+
const explicitWidth = node.props?.width;
|
|
688
|
+
const padding = node.props?.padding ?? 0;
|
|
689
|
+
if (border === "none") {
|
|
690
|
+
return renderChildren(node, ctx);
|
|
691
|
+
}
|
|
692
|
+
const chars = getASCIIBoxChars(border);
|
|
693
|
+
const { horizontal, vertical } = chars;
|
|
694
|
+
const corner = chars.topLeft;
|
|
695
|
+
const availableWidth = explicitWidth ?? ctx.width;
|
|
696
|
+
const neededForBorders = 2 + padding * 2;
|
|
697
|
+
const childWidth = Math.max(1, availableWidth - neededForBorders);
|
|
698
|
+
const childCtx = {
|
|
699
|
+
...ctx,
|
|
700
|
+
depth: ctx.depth + 1,
|
|
701
|
+
width: childWidth
|
|
702
|
+
};
|
|
703
|
+
const childContent = renderChildren(node, childCtx);
|
|
704
|
+
const contentLines = childContent.split("\n").filter((line, idx, arr) => {
|
|
705
|
+
return line.length > 0 || idx > 0 && idx < arr.length - 1;
|
|
706
|
+
});
|
|
707
|
+
let contentWidth = 0;
|
|
708
|
+
for (const line of contentLines) {
|
|
709
|
+
contentWidth = Math.max(contentWidth, line.length);
|
|
710
|
+
}
|
|
711
|
+
let innerWidth;
|
|
712
|
+
if (explicitWidth !== void 0) {
|
|
713
|
+
innerWidth = explicitWidth - 2;
|
|
714
|
+
} else {
|
|
715
|
+
innerWidth = Math.max(contentWidth + padding * 2, 1);
|
|
716
|
+
}
|
|
717
|
+
if (ctx.width > 0 && innerWidth > ctx.width - 2) {
|
|
718
|
+
innerWidth = ctx.width - 2;
|
|
719
|
+
}
|
|
720
|
+
const lines = [];
|
|
721
|
+
const topBottom = corner + horizontal.repeat(Math.max(innerWidth, 1)) + corner;
|
|
722
|
+
lines.push(topBottom);
|
|
723
|
+
for (let i = 0; i < padding; i++) {
|
|
724
|
+
lines.push(vertical + " ".repeat(innerWidth) + vertical);
|
|
725
|
+
}
|
|
726
|
+
const linesToRender = contentLines.length > 0 ? contentLines : [""];
|
|
727
|
+
for (const line of linesToRender) {
|
|
728
|
+
const paddedLine = " ".repeat(padding) + line;
|
|
729
|
+
const truncated = paddedLine.length > innerWidth ? paddedLine.slice(0, innerWidth) : paddedLine;
|
|
730
|
+
const padded = truncated.padEnd(innerWidth);
|
|
731
|
+
lines.push(vertical + padded + vertical);
|
|
732
|
+
}
|
|
733
|
+
for (let i = 0; i < padding; i++) {
|
|
734
|
+
lines.push(vertical + " ".repeat(innerWidth) + vertical);
|
|
735
|
+
}
|
|
736
|
+
lines.push(topBottom);
|
|
737
|
+
return lines.join("\n");
|
|
738
|
+
}
|
|
739
|
+
function renderTable2(node, ctx) {
|
|
740
|
+
const columns = node.props?.columns;
|
|
741
|
+
const nodeData = node.data ?? node.props?.data;
|
|
742
|
+
let headers = [];
|
|
743
|
+
let rows = [];
|
|
744
|
+
if (columns && columns.length > 0) {
|
|
745
|
+
headers = columns.map((col) => col.header);
|
|
746
|
+
if (nodeData && nodeData.length > 0) {
|
|
747
|
+
rows = nodeData.map(
|
|
748
|
+
(row) => columns.map((col) => {
|
|
749
|
+
const val = row[col.key];
|
|
750
|
+
return val != null ? String(val) : "";
|
|
751
|
+
})
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
} else {
|
|
755
|
+
headers = node.props?.headers ?? [];
|
|
756
|
+
rows = node.props?.rows ?? [];
|
|
757
|
+
}
|
|
758
|
+
if (headers.length === 0 && rows.length === 0) {
|
|
759
|
+
return "";
|
|
760
|
+
}
|
|
761
|
+
const maxTableWidth = ctx.width > 0 ? ctx.width : DEFAULT_WIDTH;
|
|
762
|
+
const colWidths = calculateColumnWidths(headers, rows, maxTableWidth);
|
|
763
|
+
const separatorChars = { left: "+", middle: "+", right: "+", horizontal: "-" };
|
|
764
|
+
const lines = [];
|
|
765
|
+
lines.push(buildTableSeparator(colWidths, separatorChars));
|
|
766
|
+
if (headers.length > 0) {
|
|
767
|
+
lines.push(buildTableRow(headers, colWidths, "|"));
|
|
768
|
+
lines.push(buildTableSeparator(colWidths, separatorChars));
|
|
769
|
+
}
|
|
770
|
+
for (const row of rows) {
|
|
771
|
+
const processedRow = row.map((cell) => {
|
|
772
|
+
const firstLine = cell.split("\n")[0] ?? "";
|
|
773
|
+
return sanitizeToASCII(firstLine);
|
|
774
|
+
});
|
|
775
|
+
lines.push(buildTableRow(processedRow, colWidths, "|"));
|
|
776
|
+
}
|
|
777
|
+
if (rows.length > 0 || headers.length > 0) {
|
|
778
|
+
lines.push(buildTableSeparator(colWidths, separatorChars));
|
|
779
|
+
}
|
|
780
|
+
return lines.join("\n");
|
|
781
|
+
}
|
|
782
|
+
function renderList2(node, ctx) {
|
|
783
|
+
const items = node.props?.items ?? [];
|
|
784
|
+
const ordered = node.props?.ordered ?? false;
|
|
785
|
+
const numbered = node.props?.numbered ?? false;
|
|
786
|
+
const taskList = node.props?.taskList ?? false;
|
|
787
|
+
const bullet = node.props?.bullet ?? "*";
|
|
788
|
+
const lines = [];
|
|
789
|
+
const baseIndent = ctx.depth * 2;
|
|
790
|
+
const indent = " ".repeat(baseIndent);
|
|
791
|
+
if (items.length > 0) {
|
|
792
|
+
const maxNum = items.length;
|
|
793
|
+
const numWidth = String(maxNum).length;
|
|
794
|
+
for (let i = 0; i < items.length; i++) {
|
|
795
|
+
const item = items[i];
|
|
796
|
+
let text;
|
|
797
|
+
let prefix;
|
|
798
|
+
if (typeof item === "string") {
|
|
799
|
+
text = sanitizeToASCII(item);
|
|
800
|
+
if (ordered || numbered) {
|
|
801
|
+
const num = String(i + 1).padStart(numWidth);
|
|
802
|
+
prefix = `${num}. `;
|
|
803
|
+
} else {
|
|
804
|
+
prefix = `${bullet} `;
|
|
805
|
+
}
|
|
806
|
+
} else {
|
|
807
|
+
text = sanitizeToASCII(item.text ?? "");
|
|
808
|
+
if (taskList && "checked" in item) {
|
|
809
|
+
prefix = item.checked ? "[x] " : "[ ] ";
|
|
810
|
+
} else if (ordered || numbered) {
|
|
811
|
+
const num = String(i + 1).padStart(numWidth);
|
|
812
|
+
prefix = `${num}. `;
|
|
813
|
+
} else {
|
|
814
|
+
prefix = `${bullet} `;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
lines.push(`${indent}${prefix}${text}`);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if (node.children && Array.isArray(node.children) && node.children.length > 0) {
|
|
821
|
+
const nestedCtx = {
|
|
822
|
+
...ctx,
|
|
823
|
+
depth: ctx.depth + 1
|
|
824
|
+
};
|
|
825
|
+
node.children.forEach((child, index) => {
|
|
826
|
+
if (child.type === "list-item") {
|
|
827
|
+
const content = sanitizeToASCII(String(child.props?.content ?? ""));
|
|
828
|
+
const prefix = ordered || numbered ? `${index + 1}. ` : `${bullet} `;
|
|
829
|
+
lines.push(`${indent}${prefix}${content}`);
|
|
830
|
+
if (child.children && Array.isArray(child.children) && child.children.length > 0) {
|
|
831
|
+
child.children.forEach((nestedChild) => {
|
|
832
|
+
const nestedOutput = renderNode2(nestedChild, nestedCtx);
|
|
833
|
+
if (nestedOutput) {
|
|
834
|
+
lines.push(nestedOutput);
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
} else {
|
|
839
|
+
const nestedContent = renderNode2(child, nestedCtx);
|
|
840
|
+
if (nestedContent.length > 0) {
|
|
841
|
+
lines.push(nestedContent);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
return lines.join("\n");
|
|
847
|
+
}
|
|
848
|
+
function renderProgress(node, ctx) {
|
|
849
|
+
const value = Math.max(0, Math.min(100, Number(node.props?.value) ?? 0));
|
|
850
|
+
const barWidth = node.props?.width ?? 20;
|
|
851
|
+
const showLabel = node.props?.showLabel;
|
|
852
|
+
const label = node.props?.label;
|
|
853
|
+
const innerWidth = Math.max(1, barWidth - 2);
|
|
854
|
+
const filledCount = Math.round(value / 100 * innerWidth);
|
|
855
|
+
const emptyCount = innerWidth - filledCount;
|
|
856
|
+
const bar = "[" + "=".repeat(filledCount) + " ".repeat(emptyCount) + "]";
|
|
857
|
+
let result = bar;
|
|
858
|
+
if (showLabel) {
|
|
859
|
+
result += ` ${Math.round(value)}%`;
|
|
860
|
+
}
|
|
861
|
+
if (label) {
|
|
862
|
+
result += ` ${label}`;
|
|
863
|
+
}
|
|
864
|
+
return result;
|
|
865
|
+
}
|
|
866
|
+
function renderSpinner2(node, ctx) {
|
|
867
|
+
const label = node.props?.label;
|
|
868
|
+
const frame = "-";
|
|
869
|
+
if (label) {
|
|
870
|
+
return `${frame} ${label}`;
|
|
871
|
+
}
|
|
872
|
+
return frame;
|
|
873
|
+
}
|
|
874
|
+
function renderPanel2(node, ctx) {
|
|
875
|
+
const title = String(node.props?.title ?? "");
|
|
876
|
+
const childCtx = {
|
|
877
|
+
...ctx,
|
|
878
|
+
depth: ctx.depth + 1,
|
|
879
|
+
width: Math.max(1, ctx.width - 4)
|
|
880
|
+
};
|
|
881
|
+
const childContent = renderChildren(node, childCtx);
|
|
882
|
+
const contentLines = childContent.split("\n");
|
|
883
|
+
let contentWidth = title.length;
|
|
884
|
+
for (const line of contentLines) {
|
|
885
|
+
contentWidth = Math.max(contentWidth, line.length);
|
|
886
|
+
}
|
|
887
|
+
const innerWidth = Math.min(contentWidth + 2, ctx.width > 0 ? ctx.width - 2 : DEFAULT_WIDTH - 2);
|
|
888
|
+
const lines = [];
|
|
889
|
+
const topLine = "+" + "-".repeat(innerWidth) + "+";
|
|
890
|
+
lines.push(topLine);
|
|
891
|
+
if (title) {
|
|
892
|
+
const titlePadded = (" " + title).padEnd(innerWidth);
|
|
893
|
+
lines.push("|" + titlePadded + "|");
|
|
894
|
+
lines.push("+" + "-".repeat(innerWidth) + "+");
|
|
895
|
+
}
|
|
896
|
+
for (const line of contentLines) {
|
|
897
|
+
const padded = (" " + line).padEnd(innerWidth);
|
|
898
|
+
lines.push("|" + padded + "|");
|
|
899
|
+
}
|
|
900
|
+
lines.push(topLine);
|
|
901
|
+
return lines.join("\n");
|
|
902
|
+
}
|
|
903
|
+
function renderCard2(node, ctx) {
|
|
904
|
+
const title = node.props?.title;
|
|
905
|
+
const subtitle = node.props?.subtitle;
|
|
906
|
+
const badge = node.props?.badge;
|
|
907
|
+
const titleAction = node.props?.titleAction;
|
|
908
|
+
const pairs = node.props?.pairs;
|
|
909
|
+
const actions = node.props?.actions;
|
|
910
|
+
const border = node.props?.border;
|
|
911
|
+
const contentLines = [];
|
|
912
|
+
if (title) {
|
|
913
|
+
let titleLine = title;
|
|
914
|
+
if (badge) {
|
|
915
|
+
titleLine += ` [${badge.content}]`;
|
|
916
|
+
}
|
|
917
|
+
if (titleAction) {
|
|
918
|
+
titleLine += ` | ${titleAction.label}`;
|
|
919
|
+
}
|
|
920
|
+
contentLines.push(titleLine);
|
|
921
|
+
}
|
|
922
|
+
if (subtitle) {
|
|
923
|
+
contentLines.push(subtitle);
|
|
924
|
+
}
|
|
925
|
+
if (pairs && pairs.length > 0) {
|
|
926
|
+
if (contentLines.length > 0) contentLines.push("");
|
|
927
|
+
for (const pair of pairs) {
|
|
928
|
+
const val = pair.value != null ? String(pair.value) : "";
|
|
929
|
+
contentLines.push(`${pair.key}: ${val}`);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
if (node.children && (typeof node.children === "string" || node.children.length > 0)) {
|
|
933
|
+
if (contentLines.length > 0) contentLines.push("");
|
|
934
|
+
const childCtx = { ...ctx, depth: ctx.depth + 1 };
|
|
935
|
+
const childContent = renderChildren(node, childCtx);
|
|
936
|
+
if (childContent) {
|
|
937
|
+
contentLines.push(childContent);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
if (actions && actions.length > 0) {
|
|
941
|
+
if (contentLines.length > 0) contentLines.push("");
|
|
942
|
+
const actionLabels = actions.map((a) => `[ ${a.label} ]`).join(" ");
|
|
943
|
+
contentLines.push(actionLabels);
|
|
944
|
+
}
|
|
945
|
+
if (border === true) {
|
|
946
|
+
const boxNode = {
|
|
947
|
+
type: "box",
|
|
948
|
+
props: { border: "single" },
|
|
949
|
+
children: [{ type: "text", props: { content: contentLines.join("\n") } }]
|
|
950
|
+
};
|
|
951
|
+
return renderBox2(boxNode, ctx);
|
|
952
|
+
}
|
|
953
|
+
return contentLines.join("\n");
|
|
954
|
+
}
|
|
955
|
+
function renderBadge2(node, ctx) {
|
|
956
|
+
const label = String(node.props?.label ?? "");
|
|
957
|
+
return `[${label}]`;
|
|
958
|
+
}
|
|
959
|
+
function renderButton2(node, ctx) {
|
|
960
|
+
const label = String(node.props?.label ?? "");
|
|
961
|
+
return `[ ${label} ]`;
|
|
962
|
+
}
|
|
963
|
+
function renderInput2(node, ctx) {
|
|
964
|
+
const value = String(node.props?.value ?? "");
|
|
965
|
+
const placeholder = String(node.props?.placeholder ?? "");
|
|
966
|
+
const display = value || placeholder;
|
|
967
|
+
return `[${display}]`;
|
|
968
|
+
}
|
|
969
|
+
function renderSelect2(node, ctx) {
|
|
970
|
+
const options = node.props?.options ?? [];
|
|
971
|
+
const selectedValue = node.props?.value;
|
|
972
|
+
const lines = [];
|
|
973
|
+
for (const opt of options) {
|
|
974
|
+
const marker = opt.value === selectedValue ? ">" : " ";
|
|
975
|
+
lines.push(`${marker} ${opt.label}`);
|
|
976
|
+
}
|
|
977
|
+
return lines.join("\n");
|
|
978
|
+
}
|
|
979
|
+
function renderDialog2(node, ctx) {
|
|
980
|
+
const title = String(node.props?.title ?? "");
|
|
981
|
+
const childCtx = {
|
|
982
|
+
...ctx,
|
|
983
|
+
depth: ctx.depth + 1,
|
|
984
|
+
width: Math.max(1, ctx.width - 4)
|
|
985
|
+
};
|
|
986
|
+
const childContent = renderChildren(node, childCtx);
|
|
987
|
+
const contentLines = childContent.split("\n");
|
|
988
|
+
let contentWidth = title.length;
|
|
989
|
+
for (const line of contentLines) {
|
|
990
|
+
contentWidth = Math.max(contentWidth, line.length);
|
|
991
|
+
}
|
|
992
|
+
const innerWidth = Math.min(contentWidth + 2, ctx.width > 0 ? ctx.width - 2 : DEFAULT_WIDTH - 2);
|
|
993
|
+
const lines = [];
|
|
994
|
+
const topLine = "+" + "-".repeat(innerWidth) + "+";
|
|
995
|
+
lines.push(topLine);
|
|
996
|
+
if (title) {
|
|
997
|
+
const titlePadded = (" " + title).padEnd(innerWidth);
|
|
998
|
+
lines.push("|" + titlePadded + "|");
|
|
999
|
+
lines.push("+" + "-".repeat(innerWidth) + "+");
|
|
1000
|
+
}
|
|
1001
|
+
for (const line of contentLines) {
|
|
1002
|
+
const padded = (" " + line).padEnd(innerWidth);
|
|
1003
|
+
lines.push("|" + padded + "|");
|
|
1004
|
+
}
|
|
1005
|
+
lines.push(topLine);
|
|
1006
|
+
return lines.join("\n");
|
|
1007
|
+
}
|
|
1008
|
+
function renderBreadcrumb2(node, ctx) {
|
|
1009
|
+
const items = node.props?.items ?? [];
|
|
1010
|
+
const labels = items.map((item) => item.label);
|
|
1011
|
+
return labels.join(" > ");
|
|
1012
|
+
}
|
|
1013
|
+
function renderSidebar2(node, ctx) {
|
|
1014
|
+
const items = node.props?.items ?? [];
|
|
1015
|
+
const lines = [];
|
|
1016
|
+
for (const item of items) {
|
|
1017
|
+
lines.push(`* ${item.label}`);
|
|
1018
|
+
}
|
|
1019
|
+
return lines.join("\n");
|
|
1020
|
+
}
|
|
1021
|
+
function renderMetrics2(node, ctx) {
|
|
1022
|
+
const metrics = node.props?.metrics;
|
|
1023
|
+
if (!metrics || metrics.length === 0) return "";
|
|
1024
|
+
const lines = [];
|
|
1025
|
+
for (const m of metrics) {
|
|
1026
|
+
const val = m.value != null ? String(m.value) : "";
|
|
1027
|
+
let formatted = val;
|
|
1028
|
+
if (m.format === "percentage" && !val.includes("%")) {
|
|
1029
|
+
formatted = `${val}%`;
|
|
1030
|
+
}
|
|
1031
|
+
if (m.unit) {
|
|
1032
|
+
formatted = `${formatted} ${m.unit}`;
|
|
1033
|
+
}
|
|
1034
|
+
lines.push(`${m.label}: ${formatted}`);
|
|
1035
|
+
}
|
|
1036
|
+
return lines.join("\n");
|
|
1037
|
+
}
|
|
1038
|
+
function renderSingleMetric2(node, ctx) {
|
|
1039
|
+
const label = node.props?.label;
|
|
1040
|
+
const value = node.props?.value;
|
|
1041
|
+
const format = node.props?.format;
|
|
1042
|
+
const unit = node.props?.unit;
|
|
1043
|
+
if (!label) return "";
|
|
1044
|
+
const val = value != null ? String(value) : "";
|
|
1045
|
+
let formatted = val;
|
|
1046
|
+
if (format === "percentage" && !val.includes("%")) {
|
|
1047
|
+
formatted = `${val}%`;
|
|
1048
|
+
}
|
|
1049
|
+
if (unit) {
|
|
1050
|
+
formatted = `${formatted} ${unit}`;
|
|
1051
|
+
}
|
|
1052
|
+
return `${label}: ${formatted}`;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
// src/renderers/unicode.ts
|
|
1056
|
+
var UNICODE = {
|
|
1057
|
+
// Single box drawing
|
|
1058
|
+
topLeft: "\u250C",
|
|
1059
|
+
topRight: "\u2510",
|
|
1060
|
+
bottomLeft: "\u2514",
|
|
1061
|
+
bottomRight: "\u2518",
|
|
1062
|
+
horizontal: "\u2500",
|
|
1063
|
+
vertical: "\u2502",
|
|
1064
|
+
// T-junctions
|
|
1065
|
+
teeLeft: "\u251C",
|
|
1066
|
+
teeRight: "\u2524",
|
|
1067
|
+
teeTop: "\u252C",
|
|
1068
|
+
teeBottom: "\u2534",
|
|
1069
|
+
crossJunction: "\u253C",
|
|
1070
|
+
// Double box drawing
|
|
1071
|
+
doubleTopLeft: "\u2554",
|
|
1072
|
+
doubleTopRight: "\u2557",
|
|
1073
|
+
doubleBottomLeft: "\u255A",
|
|
1074
|
+
doubleBottomRight: "\u255D",
|
|
1075
|
+
doubleHorizontal: "\u2550",
|
|
1076
|
+
doubleVertical: "\u2551",
|
|
1077
|
+
// Rounded corners
|
|
1078
|
+
roundedTopLeft: "\u256D",
|
|
1079
|
+
roundedTopRight: "\u256E",
|
|
1080
|
+
roundedBottomLeft: "\u2570",
|
|
1081
|
+
roundedBottomRight: "\u256F",
|
|
1082
|
+
// Bullets and list markers
|
|
1083
|
+
bullet: "\u2022",
|
|
1084
|
+
hollowBullet: "\u25E6",
|
|
1085
|
+
squareBullet: "\u25AA",
|
|
1086
|
+
triangleRight: "\u25B8",
|
|
1087
|
+
triangleDown: "\u25BE",
|
|
1088
|
+
checkmark: "\u2713",
|
|
1089
|
+
crossMark: "\u2717",
|
|
1090
|
+
unchecked: "\u2610",
|
|
1091
|
+
arrowRight: "\u2192",
|
|
1092
|
+
arrowDown: "\u2193",
|
|
1093
|
+
// Progress bar characters
|
|
1094
|
+
progressFull: "\u2593",
|
|
1095
|
+
progressEmpty: "\u2591",
|
|
1096
|
+
progressHalf: "\u2592",
|
|
1097
|
+
// Dividers
|
|
1098
|
+
ellipsis: "\u2026",
|
|
1099
|
+
middleDot: "\xB7"
|
|
1100
|
+
};
|
|
1101
|
+
function createDefaultTheme() {
|
|
1102
|
+
return { ...DEFAULT_THEME_TOKENS };
|
|
1103
|
+
}
|
|
1104
|
+
function createDefaultContext2() {
|
|
1105
|
+
return {
|
|
1106
|
+
tier: "unicode",
|
|
1107
|
+
width: DEFAULT_RENDER_CONTEXT.width,
|
|
1108
|
+
height: DEFAULT_RENDER_CONTEXT.height,
|
|
1109
|
+
depth: DEFAULT_RENDER_CONTEXT.depth,
|
|
1110
|
+
theme: createDefaultTheme(),
|
|
1111
|
+
interactive: false
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
function renderBox3(node, context) {
|
|
1115
|
+
const props = node.props || {};
|
|
1116
|
+
const border = props.border || "single";
|
|
1117
|
+
const chars = getUnicodeBoxChars(border);
|
|
1118
|
+
let content = "";
|
|
1119
|
+
if (node.children && (typeof node.children === "string" || node.children.length > 0)) {
|
|
1120
|
+
if (typeof node.children === "string") {
|
|
1121
|
+
content = node.children;
|
|
1122
|
+
} else {
|
|
1123
|
+
content = node.children.map((child) => renderUnicode(child, { ...context, depth: context.depth + 1 })).join("\n");
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
const contentLines = content ? content.split("\n") : [];
|
|
1127
|
+
const contentWidth = Math.max(
|
|
1128
|
+
...contentLines.map((line) => line.length),
|
|
1129
|
+
0
|
|
1130
|
+
);
|
|
1131
|
+
let width = props.width || contentWidth + 2 || 6;
|
|
1132
|
+
let height = props.height || contentLines.length + 2 || 3;
|
|
1133
|
+
if (width <= 0) width = 2;
|
|
1134
|
+
if (height <= 0) return "";
|
|
1135
|
+
const innerWidth = Math.max(width - 2, 0);
|
|
1136
|
+
const lines = [];
|
|
1137
|
+
lines.push(chars.topLeft + chars.horizontal.repeat(innerWidth) + chars.topRight);
|
|
1138
|
+
const numContentLines = height - 2;
|
|
1139
|
+
for (let i = 0; i < numContentLines; i++) {
|
|
1140
|
+
const lineContent = contentLines[i] || "";
|
|
1141
|
+
const paddedContent = lineContent.padEnd(innerWidth, " ");
|
|
1142
|
+
lines.push(chars.vertical + paddedContent.slice(0, innerWidth) + chars.vertical);
|
|
1143
|
+
}
|
|
1144
|
+
lines.push(chars.bottomLeft + chars.horizontal.repeat(innerWidth) + chars.bottomRight);
|
|
1145
|
+
return lines.join("\n");
|
|
1146
|
+
}
|
|
1147
|
+
function renderText4(node) {
|
|
1148
|
+
const content = node.props?.content || "";
|
|
1149
|
+
return content;
|
|
1150
|
+
}
|
|
1151
|
+
function renderList3(node, context) {
|
|
1152
|
+
const style = node.props?.style || "unordered";
|
|
1153
|
+
const items = node.props?.items;
|
|
1154
|
+
const numbered = node.props?.numbered ?? false;
|
|
1155
|
+
const taskList = node.props?.taskList ?? false;
|
|
1156
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
1157
|
+
const lines = [];
|
|
1158
|
+
if (items && items.length > 0) {
|
|
1159
|
+
items.forEach((item, index) => {
|
|
1160
|
+
let text;
|
|
1161
|
+
let marker;
|
|
1162
|
+
if (typeof item === "string") {
|
|
1163
|
+
text = item;
|
|
1164
|
+
if (style === "ordered" || numbered) {
|
|
1165
|
+
marker = `${index + 1}. `;
|
|
1166
|
+
} else {
|
|
1167
|
+
marker = `${UNICODE.bullet} `;
|
|
1168
|
+
}
|
|
1169
|
+
} else {
|
|
1170
|
+
text = item.text ?? "";
|
|
1171
|
+
if (taskList && "checked" in item) {
|
|
1172
|
+
marker = item.checked ? `${UNICODE.checkmark} ` : `${UNICODE.unchecked} `;
|
|
1173
|
+
} else if (style === "ordered" || numbered) {
|
|
1174
|
+
marker = `${index + 1}. `;
|
|
1175
|
+
} else {
|
|
1176
|
+
marker = `${UNICODE.bullet} `;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
lines.push(marker + text);
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
children.forEach((child, index) => {
|
|
1183
|
+
if (child.type === "list-item") {
|
|
1184
|
+
const content = child.props?.content || "";
|
|
1185
|
+
let marker;
|
|
1186
|
+
if (style === "ordered" || numbered) {
|
|
1187
|
+
marker = `${index + 1}. `;
|
|
1188
|
+
} else if (style === "checklist" || taskList) {
|
|
1189
|
+
const checked = child.props?.checked;
|
|
1190
|
+
marker = checked ? `${UNICODE.checkmark} ` : `${UNICODE.unchecked} `;
|
|
1191
|
+
} else {
|
|
1192
|
+
marker = `${UNICODE.bullet} `;
|
|
1193
|
+
}
|
|
1194
|
+
lines.push(marker + content);
|
|
1195
|
+
if (child.children && Array.isArray(child.children) && child.children.length > 0) {
|
|
1196
|
+
child.children.forEach((nestedChild) => {
|
|
1197
|
+
if (nestedChild.type === "list") {
|
|
1198
|
+
const nestedLines = renderNestedList(nestedChild, context);
|
|
1199
|
+
lines.push(...nestedLines.split("\n").map((line) => " " + line));
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
return lines.join("\n");
|
|
1206
|
+
}
|
|
1207
|
+
function renderNestedList(node, context, depth = 1) {
|
|
1208
|
+
const style = node.props?.style || "unordered";
|
|
1209
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
1210
|
+
const lines = [];
|
|
1211
|
+
const bulletStyles = [UNICODE.bullet, UNICODE.hollowBullet, "\u25AA", "\u25AB", "\u25B8"];
|
|
1212
|
+
const bullet = bulletStyles[Math.min(depth, bulletStyles.length - 1)];
|
|
1213
|
+
children.forEach((child, index) => {
|
|
1214
|
+
if (child.type === "list-item") {
|
|
1215
|
+
const content = child.props?.content || "";
|
|
1216
|
+
let marker;
|
|
1217
|
+
if (style === "ordered") {
|
|
1218
|
+
marker = `${index + 1}. `;
|
|
1219
|
+
} else {
|
|
1220
|
+
marker = `${bullet} `;
|
|
1221
|
+
}
|
|
1222
|
+
lines.push(marker + content);
|
|
1223
|
+
if (child.children && Array.isArray(child.children) && child.children.length > 0) {
|
|
1224
|
+
child.children.forEach((nestedChild) => {
|
|
1225
|
+
if (nestedChild.type === "list") {
|
|
1226
|
+
const nestedLines = renderNestedList(nestedChild, context, depth + 1);
|
|
1227
|
+
lines.push(...nestedLines.split("\n").map((line) => " " + line));
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
return lines.join("\n");
|
|
1234
|
+
}
|
|
1235
|
+
function renderProgress2(node) {
|
|
1236
|
+
const value = node.props?.value || 0;
|
|
1237
|
+
const max = node.props?.max || 100;
|
|
1238
|
+
const width = node.props?.width || 10;
|
|
1239
|
+
const percentage = Math.min(Math.max(value / max, 0), 1);
|
|
1240
|
+
const filledBlocks = percentage * width;
|
|
1241
|
+
const fullBlocks = Math.floor(filledBlocks);
|
|
1242
|
+
const hasHalf = filledBlocks - fullBlocks >= 0.5;
|
|
1243
|
+
const emptyBlocks = width - fullBlocks - (hasHalf ? 1 : 0);
|
|
1244
|
+
let bar = UNICODE.progressFull.repeat(fullBlocks);
|
|
1245
|
+
if (hasHalf) {
|
|
1246
|
+
bar += UNICODE.progressHalf;
|
|
1247
|
+
}
|
|
1248
|
+
bar += UNICODE.progressEmpty.repeat(Math.max(emptyBlocks, 0));
|
|
1249
|
+
return bar;
|
|
1250
|
+
}
|
|
1251
|
+
function renderTable3(node, context) {
|
|
1252
|
+
const props = node.props || {};
|
|
1253
|
+
const columns = props.columns || [];
|
|
1254
|
+
const nodeData = node.data;
|
|
1255
|
+
const propsData = props.data;
|
|
1256
|
+
const data = nodeData ?? propsData ?? [];
|
|
1257
|
+
const rowSeparators = props.rowSeparators;
|
|
1258
|
+
if (columns.length === 0) return "";
|
|
1259
|
+
const lines = [];
|
|
1260
|
+
const widths = columns.map((col) => {
|
|
1261
|
+
if (col.width && col.width > 0) return col.width;
|
|
1262
|
+
let maxWidth = col.header.length;
|
|
1263
|
+
for (const row of data) {
|
|
1264
|
+
const val = row[col.key];
|
|
1265
|
+
const str = val != null ? String(val) : "";
|
|
1266
|
+
maxWidth = Math.max(maxWidth, str.length);
|
|
1267
|
+
}
|
|
1268
|
+
return maxWidth;
|
|
1269
|
+
});
|
|
1270
|
+
const topBorder = UNICODE.topLeft + widths.map((w) => UNICODE.horizontal.repeat(w)).join(UNICODE.teeTop) + UNICODE.topRight;
|
|
1271
|
+
lines.push(topBorder);
|
|
1272
|
+
const headerRow = UNICODE.vertical + columns.map((col, i) => col.header.padEnd(widths[i]).slice(0, widths[i])).join(UNICODE.vertical) + UNICODE.vertical;
|
|
1273
|
+
lines.push(headerRow);
|
|
1274
|
+
const headerSep = UNICODE.teeLeft + widths.map((w) => UNICODE.horizontal.repeat(w)).join(UNICODE.crossJunction) + UNICODE.teeRight;
|
|
1275
|
+
lines.push(headerSep);
|
|
1276
|
+
data.forEach((row, rowIndex) => {
|
|
1277
|
+
const dataRow = UNICODE.vertical + columns.map((col, i) => {
|
|
1278
|
+
const value = String(row[col.key] ?? "");
|
|
1279
|
+
return value.padEnd(widths[i]).slice(0, widths[i]);
|
|
1280
|
+
}).join(UNICODE.vertical) + UNICODE.vertical;
|
|
1281
|
+
lines.push(dataRow);
|
|
1282
|
+
if (rowSeparators && rowIndex < data.length - 1) {
|
|
1283
|
+
const rowSep = UNICODE.teeLeft + widths.map((w) => UNICODE.horizontal.repeat(w)).join(UNICODE.crossJunction) + UNICODE.teeRight;
|
|
1284
|
+
lines.push(rowSep);
|
|
1285
|
+
}
|
|
1286
|
+
});
|
|
1287
|
+
const bottomBorder = UNICODE.bottomLeft + widths.map((w) => UNICODE.horizontal.repeat(w)).join(UNICODE.teeBottom) + UNICODE.bottomRight;
|
|
1288
|
+
lines.push(bottomBorder);
|
|
1289
|
+
return lines.join("\n");
|
|
1290
|
+
}
|
|
1291
|
+
function renderPanel3(node, context) {
|
|
1292
|
+
const props = node.props || {};
|
|
1293
|
+
const title = props.title || "";
|
|
1294
|
+
const width = props.width || 40;
|
|
1295
|
+
let content = "";
|
|
1296
|
+
if (node.children && (typeof node.children === "string" || node.children.length > 0)) {
|
|
1297
|
+
if (typeof node.children === "string") {
|
|
1298
|
+
content = node.children;
|
|
1299
|
+
} else {
|
|
1300
|
+
content = node.children.map((child) => renderUnicode(child, { ...context, depth: context.depth + 1 })).join("\n");
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
const innerWidth = width - 2;
|
|
1304
|
+
const lines = [];
|
|
1305
|
+
lines.push(UNICODE.topLeft + UNICODE.horizontal.repeat(innerWidth) + UNICODE.topRight);
|
|
1306
|
+
const paddedTitle = (" " + title + " ").padEnd(innerWidth).slice(0, innerWidth);
|
|
1307
|
+
lines.push(UNICODE.vertical + paddedTitle + UNICODE.vertical);
|
|
1308
|
+
lines.push(UNICODE.teeLeft + UNICODE.horizontal.repeat(innerWidth) + UNICODE.teeRight);
|
|
1309
|
+
const contentLines = content ? content.split("\n") : [];
|
|
1310
|
+
contentLines.forEach((line) => {
|
|
1311
|
+
const paddedLine = (" " + line).padEnd(innerWidth).slice(0, innerWidth);
|
|
1312
|
+
lines.push(UNICODE.vertical + paddedLine + UNICODE.vertical);
|
|
1313
|
+
});
|
|
1314
|
+
lines.push(UNICODE.bottomLeft + UNICODE.horizontal.repeat(innerWidth) + UNICODE.bottomRight);
|
|
1315
|
+
return lines.join("\n");
|
|
1316
|
+
}
|
|
1317
|
+
function renderDivider(node, context) {
|
|
1318
|
+
const props = node.props || {};
|
|
1319
|
+
const label = props.label;
|
|
1320
|
+
const width = props.width || context.width || 40;
|
|
1321
|
+
if (label) {
|
|
1322
|
+
const labelWithSpaces = ` ${label} `;
|
|
1323
|
+
const remaining = width - labelWithSpaces.length;
|
|
1324
|
+
const leftSide = Math.floor(remaining / 2);
|
|
1325
|
+
const rightSide = remaining - leftSide;
|
|
1326
|
+
return UNICODE.horizontal.repeat(Math.max(leftSide, 0)) + labelWithSpaces + UNICODE.horizontal.repeat(Math.max(rightSide, 0));
|
|
1327
|
+
}
|
|
1328
|
+
return UNICODE.horizontal.repeat(width);
|
|
1329
|
+
}
|
|
1330
|
+
function renderSpinner3(node) {
|
|
1331
|
+
const props = node.props || {};
|
|
1332
|
+
const frame = props.frame || 0;
|
|
1333
|
+
const label = props.label;
|
|
1334
|
+
const spinnerChar = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
1335
|
+
if (label) {
|
|
1336
|
+
return `${spinnerChar} ${label}`;
|
|
1337
|
+
}
|
|
1338
|
+
return spinnerChar;
|
|
1339
|
+
}
|
|
1340
|
+
function renderBadge3(node) {
|
|
1341
|
+
const props = node.props || {};
|
|
1342
|
+
const content = props.content || "";
|
|
1343
|
+
return `\u3010${content}\u3011`;
|
|
1344
|
+
}
|
|
1345
|
+
function renderTree(node, context) {
|
|
1346
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
1347
|
+
const lines = [];
|
|
1348
|
+
children.forEach((child) => {
|
|
1349
|
+
if (child.type === "tree-item") {
|
|
1350
|
+
const treeLines = renderTreeItem(child, "", true, context, true);
|
|
1351
|
+
lines.push(...treeLines);
|
|
1352
|
+
}
|
|
1353
|
+
});
|
|
1354
|
+
return lines.join("\n");
|
|
1355
|
+
}
|
|
1356
|
+
function renderTreeItem(node, prefix, isLast, context, isRoot = false) {
|
|
1357
|
+
const label = node.props?.label || "";
|
|
1358
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
1359
|
+
const lines = [];
|
|
1360
|
+
if (isRoot) {
|
|
1361
|
+
lines.push(label);
|
|
1362
|
+
} else {
|
|
1363
|
+
const connector = isLast ? UNICODE.bottomLeft : UNICODE.teeLeft;
|
|
1364
|
+
lines.push(prefix + connector + UNICODE.horizontal + UNICODE.horizontal + " " + label);
|
|
1365
|
+
}
|
|
1366
|
+
const childPrefix = isRoot ? "" : prefix + (isLast ? " " : UNICODE.vertical + " ");
|
|
1367
|
+
children.forEach((child, index) => {
|
|
1368
|
+
if (child.type === "tree-item") {
|
|
1369
|
+
const isChildLast = index === children.length - 1;
|
|
1370
|
+
const childLines = renderTreeItem(child, childPrefix, isChildLast, context, false);
|
|
1371
|
+
lines.push(...childLines);
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1374
|
+
return lines;
|
|
1375
|
+
}
|
|
1376
|
+
function renderBreadcrumb3(node) {
|
|
1377
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
1378
|
+
const items = [];
|
|
1379
|
+
children.forEach((child) => {
|
|
1380
|
+
if (child.type === "breadcrumb-item") {
|
|
1381
|
+
const label = child.props?.label || "";
|
|
1382
|
+
items.push(label);
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
return items.join(` ${UNICODE.arrowRight} `);
|
|
1386
|
+
}
|
|
1387
|
+
function renderTooltip(node) {
|
|
1388
|
+
const props = node.props || {};
|
|
1389
|
+
const content = props.content || "";
|
|
1390
|
+
const position = props.position || "top";
|
|
1391
|
+
let pointer = "\u25B2";
|
|
1392
|
+
switch (position) {
|
|
1393
|
+
case "bottom":
|
|
1394
|
+
pointer = "\u25BC";
|
|
1395
|
+
break;
|
|
1396
|
+
case "left":
|
|
1397
|
+
pointer = "\u25C0";
|
|
1398
|
+
break;
|
|
1399
|
+
case "right":
|
|
1400
|
+
pointer = "\u25B6";
|
|
1401
|
+
break;
|
|
1402
|
+
}
|
|
1403
|
+
return `${pointer} ${content}`;
|
|
1404
|
+
}
|
|
1405
|
+
function renderInput3(node, context) {
|
|
1406
|
+
const props = node.props || {};
|
|
1407
|
+
const label = props.label || "";
|
|
1408
|
+
const value = props.value || "";
|
|
1409
|
+
return `${label}: [${value}]`;
|
|
1410
|
+
}
|
|
1411
|
+
function renderButton3(node) {
|
|
1412
|
+
const props = node.props || {};
|
|
1413
|
+
const label = props.label || "";
|
|
1414
|
+
return `[ ${label} ]`;
|
|
1415
|
+
}
|
|
1416
|
+
function renderCard3(node, context) {
|
|
1417
|
+
const title = node.props?.title;
|
|
1418
|
+
const subtitle = node.props?.subtitle;
|
|
1419
|
+
const badge = node.props?.badge;
|
|
1420
|
+
const titleAction = node.props?.titleAction;
|
|
1421
|
+
const pairs = node.props?.pairs;
|
|
1422
|
+
const actions = node.props?.actions;
|
|
1423
|
+
const border = node.props?.border;
|
|
1424
|
+
const contentLines = [];
|
|
1425
|
+
if (title) {
|
|
1426
|
+
let titleLine = title;
|
|
1427
|
+
if (badge) {
|
|
1428
|
+
titleLine += ` \u3010${badge.content}\u3011`;
|
|
1429
|
+
}
|
|
1430
|
+
if (titleAction) {
|
|
1431
|
+
titleLine += ` ${UNICODE.arrowRight} ${titleAction.label}`;
|
|
1432
|
+
}
|
|
1433
|
+
contentLines.push(titleLine);
|
|
1434
|
+
}
|
|
1435
|
+
if (subtitle) {
|
|
1436
|
+
contentLines.push(subtitle);
|
|
1437
|
+
}
|
|
1438
|
+
if (pairs && pairs.length > 0) {
|
|
1439
|
+
if (contentLines.length > 0) contentLines.push("");
|
|
1440
|
+
for (const pair of pairs) {
|
|
1441
|
+
const val = pair.value != null ? String(pair.value) : "";
|
|
1442
|
+
contentLines.push(`${pair.key}: ${val}`);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
if (node.children && (typeof node.children === "string" || node.children.length > 0)) {
|
|
1446
|
+
if (contentLines.length > 0) contentLines.push("");
|
|
1447
|
+
let childContent;
|
|
1448
|
+
if (typeof node.children === "string") {
|
|
1449
|
+
childContent = node.children;
|
|
1450
|
+
} else {
|
|
1451
|
+
childContent = node.children.map((child) => renderUnicode(child, { ...context, depth: context.depth + 1 })).join("\n");
|
|
1452
|
+
}
|
|
1453
|
+
if (childContent) {
|
|
1454
|
+
contentLines.push(childContent);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
if (actions && actions.length > 0) {
|
|
1458
|
+
if (contentLines.length > 0) contentLines.push("");
|
|
1459
|
+
const actionLabels = actions.map((a) => `[ ${a.label} ]`).join(" ");
|
|
1460
|
+
contentLines.push(actionLabels);
|
|
1461
|
+
}
|
|
1462
|
+
if (border) {
|
|
1463
|
+
const chars = getUnicodeBoxChars(border);
|
|
1464
|
+
const contentWidth = Math.max(
|
|
1465
|
+
...contentLines.map((line) => line.length),
|
|
1466
|
+
0
|
|
1467
|
+
);
|
|
1468
|
+
const boxWidth = contentWidth + 4;
|
|
1469
|
+
const lines = [];
|
|
1470
|
+
const innerWidth = boxWidth - 2;
|
|
1471
|
+
lines.push(chars.topLeft + chars.horizontal.repeat(innerWidth) + chars.topRight);
|
|
1472
|
+
for (const line of contentLines) {
|
|
1473
|
+
const paddedLine = " " + line.padEnd(innerWidth - 2) + " ";
|
|
1474
|
+
lines.push(chars.vertical + paddedLine.slice(0, innerWidth) + chars.vertical);
|
|
1475
|
+
}
|
|
1476
|
+
if (contentLines.length === 0) {
|
|
1477
|
+
lines.push(chars.vertical + " ".repeat(innerWidth) + chars.vertical);
|
|
1478
|
+
}
|
|
1479
|
+
lines.push(chars.bottomLeft + chars.horizontal.repeat(innerWidth) + chars.bottomRight);
|
|
1480
|
+
return lines.join("\n");
|
|
1481
|
+
}
|
|
1482
|
+
return contentLines.join("\n");
|
|
1483
|
+
}
|
|
1484
|
+
var SPARKLINE_CHARS = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
|
|
1485
|
+
var TREND_ARROWS = {
|
|
1486
|
+
up: "\u2191",
|
|
1487
|
+
down: "\u2193",
|
|
1488
|
+
neutral: "\u2192"
|
|
1489
|
+
};
|
|
1490
|
+
function renderSparkline(data) {
|
|
1491
|
+
if (!data || data.length === 0) return "";
|
|
1492
|
+
const min = Math.min(...data);
|
|
1493
|
+
const max = Math.max(...data);
|
|
1494
|
+
const range = max - min || 1;
|
|
1495
|
+
return data.map((v) => {
|
|
1496
|
+
const normalized = (v - min) / range;
|
|
1497
|
+
const charIndex = Math.min(Math.floor(normalized * 8), 7);
|
|
1498
|
+
return SPARKLINE_CHARS[charIndex];
|
|
1499
|
+
}).join("");
|
|
1500
|
+
}
|
|
1501
|
+
function renderMetrics3(node) {
|
|
1502
|
+
const metrics = node.props?.metrics;
|
|
1503
|
+
if (!metrics || metrics.length === 0) return "";
|
|
1504
|
+
const lines = [];
|
|
1505
|
+
for (const m of metrics) {
|
|
1506
|
+
const val = m.value != null ? String(m.value) : "";
|
|
1507
|
+
let formatted = val;
|
|
1508
|
+
if (m.format === "percentage" && !val.includes("%")) {
|
|
1509
|
+
formatted = `${val}%`;
|
|
1510
|
+
}
|
|
1511
|
+
if (m.unit) {
|
|
1512
|
+
formatted = `${formatted} ${m.unit}`;
|
|
1513
|
+
}
|
|
1514
|
+
if (m.trend && TREND_ARROWS[m.trend]) {
|
|
1515
|
+
formatted = `${formatted} ${TREND_ARROWS[m.trend]}`;
|
|
1516
|
+
if (m.trendValue !== void 0) {
|
|
1517
|
+
formatted = `${formatted} ${m.trendValue}%`;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
if (m.sparkline && m.sparkline.length > 0) {
|
|
1521
|
+
const sparkline = renderSparkline(m.sparkline);
|
|
1522
|
+
formatted = `${formatted} ${sparkline}`;
|
|
1523
|
+
}
|
|
1524
|
+
lines.push(`${m.label}: ${formatted}`);
|
|
1525
|
+
}
|
|
1526
|
+
return lines.join("\n");
|
|
1527
|
+
}
|
|
1528
|
+
function renderSingleMetric3(node) {
|
|
1529
|
+
const label = node.props?.label;
|
|
1530
|
+
const value = node.props?.value;
|
|
1531
|
+
const format = node.props?.format;
|
|
1532
|
+
const unit = node.props?.unit;
|
|
1533
|
+
if (!label) return "";
|
|
1534
|
+
const val = value != null ? String(value) : "";
|
|
1535
|
+
let formatted = val;
|
|
1536
|
+
if (format === "percentage" && !val.includes("%")) {
|
|
1537
|
+
formatted = `${val}%`;
|
|
1538
|
+
}
|
|
1539
|
+
if (unit) {
|
|
1540
|
+
formatted = `${formatted} ${unit}`;
|
|
1541
|
+
}
|
|
1542
|
+
return `${label}: ${formatted}`;
|
|
1543
|
+
}
|
|
1544
|
+
function renderUnicode(node, context) {
|
|
1545
|
+
const ctx = context || createDefaultContext2();
|
|
1546
|
+
switch (node.type) {
|
|
1547
|
+
case "text":
|
|
1548
|
+
return renderText4(node);
|
|
1549
|
+
case "box":
|
|
1550
|
+
return renderBox3(node, ctx);
|
|
1551
|
+
case "list":
|
|
1552
|
+
return renderList3(node, ctx);
|
|
1553
|
+
case "list-item":
|
|
1554
|
+
return node.props?.content || "";
|
|
1555
|
+
case "progress":
|
|
1556
|
+
return renderProgress2(node);
|
|
1557
|
+
case "table":
|
|
1558
|
+
return renderTable3(node, ctx);
|
|
1559
|
+
case "panel":
|
|
1560
|
+
return renderPanel3(node, ctx);
|
|
1561
|
+
case "divider":
|
|
1562
|
+
return renderDivider(node, ctx);
|
|
1563
|
+
case "spinner":
|
|
1564
|
+
return renderSpinner3(node);
|
|
1565
|
+
case "badge":
|
|
1566
|
+
return renderBadge3(node);
|
|
1567
|
+
case "tree":
|
|
1568
|
+
return renderTree(node, ctx);
|
|
1569
|
+
case "tree-item":
|
|
1570
|
+
return node.props?.label || "";
|
|
1571
|
+
case "breadcrumb":
|
|
1572
|
+
return renderBreadcrumb3(node);
|
|
1573
|
+
case "breadcrumb-item":
|
|
1574
|
+
return node.props?.label || "";
|
|
1575
|
+
case "tooltip":
|
|
1576
|
+
return renderTooltip(node);
|
|
1577
|
+
case "input":
|
|
1578
|
+
return renderInput3(node, ctx);
|
|
1579
|
+
case "button":
|
|
1580
|
+
return renderButton3(node);
|
|
1581
|
+
case "card":
|
|
1582
|
+
return renderCard3(node, ctx);
|
|
1583
|
+
case "metrics":
|
|
1584
|
+
return renderMetrics3(node);
|
|
1585
|
+
case "metric":
|
|
1586
|
+
return renderSingleMetric3(node);
|
|
1587
|
+
default:
|
|
1588
|
+
if (node.children && (typeof node.children === "string" || node.children.length > 0)) {
|
|
1589
|
+
if (typeof node.children === "string") {
|
|
1590
|
+
return node.children;
|
|
1591
|
+
}
|
|
1592
|
+
return node.children.map((child) => renderUnicode(child, { ...ctx, depth: ctx.depth + 1 })).join("\n");
|
|
1593
|
+
}
|
|
1594
|
+
return "";
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// src/renderers/ansi.ts
|
|
1599
|
+
var FG_COLOR_MAP = {
|
|
1600
|
+
black: "\x1B[30m",
|
|
1601
|
+
red: "\x1B[31m",
|
|
1602
|
+
green: "\x1B[32m",
|
|
1603
|
+
yellow: "\x1B[33m",
|
|
1604
|
+
blue: "\x1B[34m",
|
|
1605
|
+
magenta: "\x1B[35m",
|
|
1606
|
+
cyan: "\x1B[36m",
|
|
1607
|
+
white: "\x1B[37m",
|
|
1608
|
+
brightBlack: "\x1B[90m",
|
|
1609
|
+
brightRed: "\x1B[91m",
|
|
1610
|
+
brightGreen: "\x1B[92m",
|
|
1611
|
+
brightYellow: "\x1B[93m",
|
|
1612
|
+
brightBlue: "\x1B[94m",
|
|
1613
|
+
brightMagenta: "\x1B[95m",
|
|
1614
|
+
brightCyan: "\x1B[96m",
|
|
1615
|
+
brightWhite: "\x1B[97m"
|
|
1616
|
+
};
|
|
1617
|
+
var BG_COLOR_MAP = {
|
|
1618
|
+
black: "\x1B[40m",
|
|
1619
|
+
red: "\x1B[41m",
|
|
1620
|
+
green: "\x1B[42m",
|
|
1621
|
+
yellow: "\x1B[43m",
|
|
1622
|
+
blue: "\x1B[44m",
|
|
1623
|
+
magenta: "\x1B[45m",
|
|
1624
|
+
cyan: "\x1B[46m",
|
|
1625
|
+
white: "\x1B[47m"
|
|
1626
|
+
};
|
|
1627
|
+
var DARK_THEME_COLORS = {
|
|
1628
|
+
primary: "\x1B[36m",
|
|
1629
|
+
// cyan
|
|
1630
|
+
secondary: "\x1B[34m",
|
|
1631
|
+
// blue
|
|
1632
|
+
accent: "\x1B[35m",
|
|
1633
|
+
// magenta
|
|
1634
|
+
muted: "\x1B[90m",
|
|
1635
|
+
// brightBlack (gray)
|
|
1636
|
+
success: "\x1B[32m",
|
|
1637
|
+
// green
|
|
1638
|
+
warning: "\x1B[33m",
|
|
1639
|
+
// yellow
|
|
1640
|
+
error: "\x1B[31m",
|
|
1641
|
+
// red
|
|
1642
|
+
info: "\x1B[34m",
|
|
1643
|
+
// blue
|
|
1644
|
+
foreground: "\x1B[37m",
|
|
1645
|
+
// white
|
|
1646
|
+
background: "\x1B[40m"
|
|
1647
|
+
// black bg
|
|
1648
|
+
};
|
|
1649
|
+
var LIGHT_THEME_COLORS = {
|
|
1650
|
+
primary: "\x1B[34m",
|
|
1651
|
+
// blue (darker for light bg)
|
|
1652
|
+
secondary: "\x1B[36m",
|
|
1653
|
+
// cyan
|
|
1654
|
+
accent: "\x1B[35m",
|
|
1655
|
+
// magenta
|
|
1656
|
+
muted: "\x1B[90m",
|
|
1657
|
+
// brightBlack (gray)
|
|
1658
|
+
success: "\x1B[32m",
|
|
1659
|
+
// green
|
|
1660
|
+
warning: "\x1B[33m",
|
|
1661
|
+
// yellow
|
|
1662
|
+
error: "\x1B[31m",
|
|
1663
|
+
// red
|
|
1664
|
+
info: "\x1B[34m",
|
|
1665
|
+
// blue
|
|
1666
|
+
foreground: "\x1B[30m",
|
|
1667
|
+
// black
|
|
1668
|
+
background: "\x1B[47m"
|
|
1669
|
+
// white bg
|
|
1670
|
+
};
|
|
1671
|
+
function rgbToAnsi256(r, g, b) {
|
|
1672
|
+
if (Math.abs(r - g) < 10 && Math.abs(g - b) < 10 && Math.abs(r - b) < 10) {
|
|
1673
|
+
const avg = (r + g + b) / 3;
|
|
1674
|
+
if (avg < 8) return 0;
|
|
1675
|
+
if (avg > 248) return 15;
|
|
1676
|
+
const grayIndex = Math.round((avg - 8) / 10);
|
|
1677
|
+
return Math.min(255, Math.max(232, 232 + grayIndex));
|
|
1678
|
+
}
|
|
1679
|
+
const toColorCubeIndex = (v) => {
|
|
1680
|
+
if (v < 48) return 0;
|
|
1681
|
+
if (v < 115) return 1;
|
|
1682
|
+
return Math.min(5, Math.floor((v - 35) / 40));
|
|
1683
|
+
};
|
|
1684
|
+
const ri = toColorCubeIndex(r);
|
|
1685
|
+
const gi = toColorCubeIndex(g);
|
|
1686
|
+
const bi = toColorCubeIndex(b);
|
|
1687
|
+
return 16 + 36 * ri + 6 * gi + bi;
|
|
1688
|
+
}
|
|
1689
|
+
function ansi256To16(code) {
|
|
1690
|
+
if (code < 8) return 30 + code;
|
|
1691
|
+
if (code < 16) return 90 + (code - 8);
|
|
1692
|
+
let r, g, b;
|
|
1693
|
+
if (code >= 232) {
|
|
1694
|
+
const gray = (code - 232) * 10 + 8;
|
|
1695
|
+
r = g = b = gray;
|
|
1696
|
+
} else {
|
|
1697
|
+
const cubeIndex = code - 16;
|
|
1698
|
+
r = Math.floor(cubeIndex / 36) * 51;
|
|
1699
|
+
g = Math.floor(cubeIndex % 36 / 6) * 51;
|
|
1700
|
+
b = cubeIndex % 6 * 51;
|
|
1701
|
+
}
|
|
1702
|
+
const basicColors = [
|
|
1703
|
+
{ r: 0, g: 0, b: 0, code: 30 },
|
|
1704
|
+
{ r: 170, g: 0, b: 0, code: 31 },
|
|
1705
|
+
{ r: 0, g: 170, b: 0, code: 32 },
|
|
1706
|
+
{ r: 170, g: 170, b: 0, code: 33 },
|
|
1707
|
+
{ r: 0, g: 0, b: 170, code: 34 },
|
|
1708
|
+
{ r: 170, g: 0, b: 170, code: 35 },
|
|
1709
|
+
{ r: 0, g: 170, b: 170, code: 36 },
|
|
1710
|
+
{ r: 170, g: 170, b: 170, code: 37 },
|
|
1711
|
+
{ r: 85, g: 85, b: 85, code: 90 },
|
|
1712
|
+
{ r: 255, g: 85, b: 85, code: 91 },
|
|
1713
|
+
{ r: 85, g: 255, b: 85, code: 92 },
|
|
1714
|
+
{ r: 255, g: 255, b: 85, code: 93 },
|
|
1715
|
+
{ r: 85, g: 85, b: 255, code: 94 },
|
|
1716
|
+
{ r: 255, g: 85, b: 255, code: 95 },
|
|
1717
|
+
{ r: 85, g: 255, b: 255, code: 96 },
|
|
1718
|
+
{ r: 255, g: 255, b: 255, code: 97 }
|
|
1719
|
+
];
|
|
1720
|
+
let minDist = Infinity;
|
|
1721
|
+
let closestCode = 37;
|
|
1722
|
+
for (const bc of basicColors) {
|
|
1723
|
+
const dist = Math.sqrt(
|
|
1724
|
+
Math.pow(r - bc.r, 2) + Math.pow(g - bc.g, 2) + Math.pow(b - bc.b, 2)
|
|
1725
|
+
);
|
|
1726
|
+
if (dist < minDist) {
|
|
1727
|
+
minDist = dist;
|
|
1728
|
+
closestCode = bc.code;
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
return closestCode;
|
|
1732
|
+
}
|
|
1733
|
+
function resolveColor(color, isBackground, options) {
|
|
1734
|
+
const colorSupport = options.colorSupport || "truecolor";
|
|
1735
|
+
const theme = options.theme || "dark";
|
|
1736
|
+
const themeColors = theme === "dark" ? DARK_THEME_COLORS : LIGHT_THEME_COLORS;
|
|
1737
|
+
if (colorSupport === "none") {
|
|
1738
|
+
return "";
|
|
1739
|
+
}
|
|
1740
|
+
if (typeof color === "string" && themeColors[color]) {
|
|
1741
|
+
const ansi = themeColors[color];
|
|
1742
|
+
if (isBackground && ansi.startsWith("\x1B[3")) {
|
|
1743
|
+
return ansi.replace("\x1B[3", "\x1B[4");
|
|
1744
|
+
}
|
|
1745
|
+
return ansi;
|
|
1746
|
+
}
|
|
1747
|
+
if (typeof color === "string") {
|
|
1748
|
+
const colorMap = isBackground ? BG_COLOR_MAP : FG_COLOR_MAP;
|
|
1749
|
+
if (colorMap[color]) {
|
|
1750
|
+
return colorMap[color];
|
|
1751
|
+
}
|
|
1752
|
+
if (color.startsWith("#")) {
|
|
1753
|
+
const rgb = hexToRgb(color);
|
|
1754
|
+
return formatRgbColor(rgb.r, rgb.g, rgb.b, isBackground, colorSupport);
|
|
1755
|
+
}
|
|
1756
|
+
return "";
|
|
1757
|
+
}
|
|
1758
|
+
if (typeof color === "number") {
|
|
1759
|
+
const code = Math.max(0, Math.min(255, Math.floor(color)));
|
|
1760
|
+
if (colorSupport === "16") {
|
|
1761
|
+
const code16 = ansi256To16(code);
|
|
1762
|
+
return `\x1B[${code16}m`;
|
|
1763
|
+
}
|
|
1764
|
+
const prefix = isBackground ? "48" : "38";
|
|
1765
|
+
return `\x1B[${prefix};5;${code}m`;
|
|
1766
|
+
}
|
|
1767
|
+
if (typeof color === "object" && color !== null && "r" in color && "g" in color && "b" in color) {
|
|
1768
|
+
const rgb = color;
|
|
1769
|
+
return formatRgbColor(rgb.r, rgb.g, rgb.b, isBackground, colorSupport);
|
|
1770
|
+
}
|
|
1771
|
+
return "";
|
|
1772
|
+
}
|
|
1773
|
+
function formatRgbColor(r, g, b, isBackground, colorSupport) {
|
|
1774
|
+
const prefix = isBackground ? "48" : "38";
|
|
1775
|
+
if (colorSupport === "truecolor") {
|
|
1776
|
+
return `\x1B[${prefix};2;${r};${g};${b}m`;
|
|
1777
|
+
}
|
|
1778
|
+
const code256 = rgbToAnsi256(r, g, b);
|
|
1779
|
+
if (colorSupport === "256") {
|
|
1780
|
+
return `\x1B[${prefix};5;${code256}m`;
|
|
1781
|
+
}
|
|
1782
|
+
if (colorSupport === "16") {
|
|
1783
|
+
const code16 = ansi256To16(code256);
|
|
1784
|
+
return `\x1B[${code16}m`;
|
|
1785
|
+
}
|
|
1786
|
+
return "";
|
|
1787
|
+
}
|
|
1788
|
+
function buildStyleCodes(props, options) {
|
|
1789
|
+
if (!props) return [];
|
|
1790
|
+
const codes = [];
|
|
1791
|
+
const colorSupport = options.colorSupport || "truecolor";
|
|
1792
|
+
if (props.bold) codes.push("\x1B[1m");
|
|
1793
|
+
if (props.dim) codes.push("\x1B[2m");
|
|
1794
|
+
if (props.italic) codes.push("\x1B[3m");
|
|
1795
|
+
if (props.underline) codes.push("\x1B[4m");
|
|
1796
|
+
if (props.inverse) codes.push("\x1B[7m");
|
|
1797
|
+
if (props.strikethrough) codes.push("\x1B[9m");
|
|
1798
|
+
if (colorSupport !== "none") {
|
|
1799
|
+
if (props.color !== void 0) {
|
|
1800
|
+
const fg = resolveColor(props.color, false, options);
|
|
1801
|
+
if (fg) codes.push(fg);
|
|
1802
|
+
}
|
|
1803
|
+
if (props.backgroundColor !== void 0) {
|
|
1804
|
+
const bg = resolveColor(props.backgroundColor, true, options);
|
|
1805
|
+
if (bg) codes.push(bg);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
return codes;
|
|
1809
|
+
}
|
|
1810
|
+
function hasStyles(props) {
|
|
1811
|
+
if (!props) return false;
|
|
1812
|
+
return !!(props.bold || props.dim || props.italic || props.underline || props.inverse || props.strikethrough || props.color !== void 0 || props.backgroundColor !== void 0);
|
|
1813
|
+
}
|
|
1814
|
+
function renderBadge4(node, options) {
|
|
1815
|
+
const text = node.text || "";
|
|
1816
|
+
const variant = node.props?.variant || "default";
|
|
1817
|
+
const variantColors = {
|
|
1818
|
+
success: "success",
|
|
1819
|
+
error: "error",
|
|
1820
|
+
warning: "warning",
|
|
1821
|
+
info: "info",
|
|
1822
|
+
default: "primary"
|
|
1823
|
+
};
|
|
1824
|
+
const colorName = variantColors[variant] || "primary";
|
|
1825
|
+
const colorCode = resolveColor(colorName, false, options);
|
|
1826
|
+
if (colorCode) {
|
|
1827
|
+
return `${colorCode}${text}${ANSI.reset}`;
|
|
1828
|
+
}
|
|
1829
|
+
return text;
|
|
1830
|
+
}
|
|
1831
|
+
function renderButton4(node, options) {
|
|
1832
|
+
const text = node.text || "";
|
|
1833
|
+
const focused = node.props?.focused;
|
|
1834
|
+
const variant = node.props?.variant || "default";
|
|
1835
|
+
const codes = [];
|
|
1836
|
+
if (focused) {
|
|
1837
|
+
codes.push(ANSI.inverse);
|
|
1838
|
+
}
|
|
1839
|
+
if (variant === "primary") {
|
|
1840
|
+
const colorCode = resolveColor("primary", false, options);
|
|
1841
|
+
if (colorCode) codes.push(colorCode);
|
|
1842
|
+
}
|
|
1843
|
+
if (codes.length > 0) {
|
|
1844
|
+
return `${codes.join("")}${text}${ANSI.reset}`;
|
|
1845
|
+
}
|
|
1846
|
+
return text;
|
|
1847
|
+
}
|
|
1848
|
+
function renderSpinner4(node) {
|
|
1849
|
+
const label = node.props?.label || "";
|
|
1850
|
+
return label;
|
|
1851
|
+
}
|
|
1852
|
+
function renderPanel4(node, options) {
|
|
1853
|
+
const title = node.props?.title || "";
|
|
1854
|
+
const content = renderChildren2(node.children, options);
|
|
1855
|
+
return `${title}${content ? "\n" + content : ""}`;
|
|
1856
|
+
}
|
|
1857
|
+
function renderCard4(node, options) {
|
|
1858
|
+
const title = node.props?.title;
|
|
1859
|
+
const subtitle = node.props?.subtitle;
|
|
1860
|
+
const badge = node.props?.badge;
|
|
1861
|
+
const titleAction = node.props?.titleAction;
|
|
1862
|
+
const pairs = node.props?.pairs;
|
|
1863
|
+
const actions = node.props?.actions;
|
|
1864
|
+
const variant = node.props?.variant;
|
|
1865
|
+
const lines = [];
|
|
1866
|
+
const variantColor = variant ? resolveColor(variant, false, options) : null;
|
|
1867
|
+
if (title) {
|
|
1868
|
+
let titleLine = title;
|
|
1869
|
+
if (badge) {
|
|
1870
|
+
const badgeColor = badge.variant ? resolveColor(badge.variant, false, options) : null;
|
|
1871
|
+
const badgeText = badgeColor ? `${badgeColor}[${badge.content}]${ANSI.reset}` : `[${badge.content}]`;
|
|
1872
|
+
titleLine += ` ${badgeText}`;
|
|
1873
|
+
}
|
|
1874
|
+
if (titleAction) {
|
|
1875
|
+
titleLine += ` | ${titleAction.label}`;
|
|
1876
|
+
}
|
|
1877
|
+
const titleCodes = [ANSI.bold];
|
|
1878
|
+
if (variantColor) {
|
|
1879
|
+
titleCodes.push(variantColor);
|
|
1880
|
+
}
|
|
1881
|
+
lines.push(`${titleCodes.join("")}${titleLine}${ANSI.reset}`);
|
|
1882
|
+
}
|
|
1883
|
+
if (subtitle) {
|
|
1884
|
+
const mutedColor = resolveColor("muted", false, options);
|
|
1885
|
+
if (mutedColor) {
|
|
1886
|
+
lines.push(`${mutedColor}${subtitle}${ANSI.reset}`);
|
|
1887
|
+
} else {
|
|
1888
|
+
lines.push(subtitle);
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
if (pairs && pairs.length > 0) {
|
|
1892
|
+
for (const pair of pairs) {
|
|
1893
|
+
const val = pair.value != null ? String(pair.value) : "";
|
|
1894
|
+
const pairVariant = pair.variant;
|
|
1895
|
+
if (pairVariant) {
|
|
1896
|
+
const pairColor = resolveColor(pairVariant, false, options);
|
|
1897
|
+
if (pairColor) {
|
|
1898
|
+
lines.push(`${pair.key}: ${pairColor}${val}${ANSI.reset}`);
|
|
1899
|
+
} else {
|
|
1900
|
+
lines.push(`${pair.key}: ${val}`);
|
|
1901
|
+
}
|
|
1902
|
+
} else {
|
|
1903
|
+
lines.push(`${pair.key}: ${val}`);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
const content = renderChildren2(node.children, options);
|
|
1908
|
+
if (content) {
|
|
1909
|
+
lines.push(content);
|
|
1910
|
+
}
|
|
1911
|
+
if (actions && actions.length > 0) {
|
|
1912
|
+
const actionLabels = actions.map((a) => {
|
|
1913
|
+
const actionVariant = a.variant;
|
|
1914
|
+
if (actionVariant) {
|
|
1915
|
+
const actionColor = resolveColor(actionVariant, false, options);
|
|
1916
|
+
if (actionColor) {
|
|
1917
|
+
return `${actionColor}[ ${a.label} ]${ANSI.reset}`;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
return `[ ${a.label} ]`;
|
|
1921
|
+
}).join(" ");
|
|
1922
|
+
lines.push(actionLabels);
|
|
1923
|
+
}
|
|
1924
|
+
return lines.join("\n");
|
|
1925
|
+
}
|
|
1926
|
+
function renderInput4(node) {
|
|
1927
|
+
const value = node.props?.value || "";
|
|
1928
|
+
return value;
|
|
1929
|
+
}
|
|
1930
|
+
function renderSelect3(node) {
|
|
1931
|
+
const opts = node.props?.options || [];
|
|
1932
|
+
return opts.map((o) => o.label).join("\n");
|
|
1933
|
+
}
|
|
1934
|
+
function renderTable4(node, options) {
|
|
1935
|
+
const columns = node.props?.columns || [];
|
|
1936
|
+
const nodeData = node.data;
|
|
1937
|
+
const data = nodeData ?? node.props?.data ?? [];
|
|
1938
|
+
const headerStyle = node.props?.headerStyle;
|
|
1939
|
+
const headerCodes = buildStyleCodes(headerStyle ?? { bold: true }, options);
|
|
1940
|
+
const headerPrefix = headerCodes.length > 0 ? headerCodes.join("") : "";
|
|
1941
|
+
const headerSuffix = headerCodes.length > 0 ? ANSI.reset : "";
|
|
1942
|
+
const headers = columns.map((c) => `${headerPrefix}${c.header}${headerSuffix}`).join(" ");
|
|
1943
|
+
const rows = data.map((row) => columns.map((c) => String(row[c.key] || "")).join(" "));
|
|
1944
|
+
return [headers, ...rows].join("\n");
|
|
1945
|
+
}
|
|
1946
|
+
function renderList4(node, options, depth = 0) {
|
|
1947
|
+
const items = node.props?.items || [];
|
|
1948
|
+
const bullet = node.props?.bullet || "-";
|
|
1949
|
+
const numbered = node.props?.numbered ?? false;
|
|
1950
|
+
const taskList = node.props?.taskList ?? false;
|
|
1951
|
+
const children = node.children;
|
|
1952
|
+
const indent = " ".repeat(depth);
|
|
1953
|
+
const lines = [];
|
|
1954
|
+
const markerColor = resolveColor("muted", false, options);
|
|
1955
|
+
const resetCode = ANSI.reset;
|
|
1956
|
+
if (items.length > 0) {
|
|
1957
|
+
items.forEach((item, index) => {
|
|
1958
|
+
let text;
|
|
1959
|
+
let prefix;
|
|
1960
|
+
if (typeof item === "string") {
|
|
1961
|
+
text = item;
|
|
1962
|
+
prefix = numbered ? `${index + 1}. ` : `${bullet} `;
|
|
1963
|
+
} else {
|
|
1964
|
+
text = item.text ?? "";
|
|
1965
|
+
if (taskList && "checked" in item) {
|
|
1966
|
+
prefix = item.checked ? "[x] " : "[ ] ";
|
|
1967
|
+
} else {
|
|
1968
|
+
prefix = numbered ? `${index + 1}. ` : `${bullet} `;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
const styledPrefix = markerColor ? `${markerColor}${prefix}${resetCode}` : prefix;
|
|
1972
|
+
lines.push(`${indent}${styledPrefix}${text}`);
|
|
1973
|
+
});
|
|
1974
|
+
}
|
|
1975
|
+
if (children && Array.isArray(children)) {
|
|
1976
|
+
children.forEach((child, index) => {
|
|
1977
|
+
if (child.type === "list-item") {
|
|
1978
|
+
const content = child.props?.content ?? "";
|
|
1979
|
+
const variant = child.props?.variant;
|
|
1980
|
+
const prefix = numbered ? `${index + 1}. ` : `${bullet} `;
|
|
1981
|
+
const styledPrefix = markerColor ? `${markerColor}${prefix}${resetCode}` : prefix;
|
|
1982
|
+
let styledContent = content;
|
|
1983
|
+
if (variant) {
|
|
1984
|
+
const variantColor = resolveColor(variant, false, options);
|
|
1985
|
+
if (variantColor) {
|
|
1986
|
+
styledContent = `${variantColor}${content}${resetCode}`;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
lines.push(`${indent}${styledPrefix}${styledContent}`);
|
|
1990
|
+
if (child.children && Array.isArray(child.children)) {
|
|
1991
|
+
for (const nestedChild of child.children) {
|
|
1992
|
+
if (nestedChild.type === "list") {
|
|
1993
|
+
const nestedLines = renderList4(nestedChild, options, depth + 1);
|
|
1994
|
+
if (nestedLines) {
|
|
1995
|
+
lines.push(nestedLines);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
});
|
|
2002
|
+
}
|
|
2003
|
+
return lines.join("\n");
|
|
2004
|
+
}
|
|
2005
|
+
function renderBreadcrumb4(node) {
|
|
2006
|
+
const items = node.props?.items || [];
|
|
2007
|
+
const separator = node.props?.separator || "/";
|
|
2008
|
+
return items.map((item) => item.label).join(` ${separator} `);
|
|
2009
|
+
}
|
|
2010
|
+
function renderMetrics4(node, options) {
|
|
2011
|
+
const metrics = node.props?.metrics;
|
|
2012
|
+
if (!metrics || metrics.length === 0) return "";
|
|
2013
|
+
const labelColor = resolveColor("muted", false, options);
|
|
2014
|
+
const resetCode = ANSI.reset;
|
|
2015
|
+
const lines = [];
|
|
2016
|
+
for (const m of metrics) {
|
|
2017
|
+
const val = m.value != null ? String(m.value) : "";
|
|
2018
|
+
let formatted = val;
|
|
2019
|
+
if (m.format === "percentage" && !val.includes("%")) {
|
|
2020
|
+
formatted = `${val}%`;
|
|
2021
|
+
}
|
|
2022
|
+
if (m.unit) {
|
|
2023
|
+
formatted = `${formatted} ${m.unit}`;
|
|
2024
|
+
}
|
|
2025
|
+
const variantColor = m.variant ? resolveColor(m.variant, false, options) : null;
|
|
2026
|
+
const styledLabel = labelColor ? `${labelColor}${m.label}:${resetCode}` : `${m.label}:`;
|
|
2027
|
+
const styledValue = variantColor ? `${variantColor}${formatted}${resetCode}` : formatted;
|
|
2028
|
+
lines.push(`${styledLabel} ${styledValue}`);
|
|
2029
|
+
}
|
|
2030
|
+
return lines.join("\n");
|
|
2031
|
+
}
|
|
2032
|
+
function renderSingleMetric4(node) {
|
|
2033
|
+
const label = node.props?.label;
|
|
2034
|
+
const value = node.props?.value;
|
|
2035
|
+
const format = node.props?.format;
|
|
2036
|
+
const unit = node.props?.unit;
|
|
2037
|
+
if (!label) return "";
|
|
2038
|
+
const val = value != null ? String(value) : "";
|
|
2039
|
+
let formatted = val;
|
|
2040
|
+
if (format === "percentage" && !val.includes("%")) {
|
|
2041
|
+
formatted = `${val}%`;
|
|
2042
|
+
}
|
|
2043
|
+
if (unit) {
|
|
2044
|
+
formatted = `${formatted} ${unit}`;
|
|
2045
|
+
}
|
|
2046
|
+
return `${label}: ${formatted}`;
|
|
2047
|
+
}
|
|
2048
|
+
function renderChildren2(children, options) {
|
|
2049
|
+
if (!children) return "";
|
|
2050
|
+
if (typeof children === "string") {
|
|
2051
|
+
return children;
|
|
2052
|
+
}
|
|
2053
|
+
if (Array.isArray(children) && children.length === 0) {
|
|
2054
|
+
return "";
|
|
2055
|
+
}
|
|
2056
|
+
return children.map((child) => renderNode3(child, options)).join("");
|
|
2057
|
+
}
|
|
2058
|
+
function renderNode3(node, options) {
|
|
2059
|
+
let text = "";
|
|
2060
|
+
switch (node.type) {
|
|
2061
|
+
case "badge":
|
|
2062
|
+
return renderBadge4(node, options);
|
|
2063
|
+
case "button":
|
|
2064
|
+
return renderButton4(node, options);
|
|
2065
|
+
case "spinner":
|
|
2066
|
+
return renderSpinner4(node);
|
|
2067
|
+
case "panel":
|
|
2068
|
+
return renderPanel4(node, options);
|
|
2069
|
+
case "card":
|
|
2070
|
+
return renderCard4(node, options);
|
|
2071
|
+
case "input":
|
|
2072
|
+
return renderInput4(node);
|
|
2073
|
+
case "select":
|
|
2074
|
+
return renderSelect3(node);
|
|
2075
|
+
case "table":
|
|
2076
|
+
return renderTable4(node, options);
|
|
2077
|
+
case "list":
|
|
2078
|
+
return renderList4(node, options);
|
|
2079
|
+
case "breadcrumb":
|
|
2080
|
+
return renderBreadcrumb4(node);
|
|
2081
|
+
case "metrics":
|
|
2082
|
+
return renderMetrics4(node, options);
|
|
2083
|
+
case "metric":
|
|
2084
|
+
return renderSingleMetric4(node);
|
|
2085
|
+
case "text":
|
|
2086
|
+
case "box":
|
|
2087
|
+
default:
|
|
2088
|
+
if (node.props?.content !== void 0) {
|
|
2089
|
+
text = String(node.props.content);
|
|
2090
|
+
} else if (node.text !== void 0) {
|
|
2091
|
+
text = node.text;
|
|
2092
|
+
} else if (typeof node.children === "string") {
|
|
2093
|
+
text = node.children;
|
|
2094
|
+
} else if (Array.isArray(node.children)) {
|
|
2095
|
+
text = renderChildren2(node.children, options);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
if (hasStyles(node.props)) {
|
|
2099
|
+
const codes = buildStyleCodes(node.props, options);
|
|
2100
|
+
if (codes.length > 0) {
|
|
2101
|
+
return `${codes.join("")}${text}${ANSI.reset}`;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
return text;
|
|
2105
|
+
}
|
|
2106
|
+
function renderANSI(node, options) {
|
|
2107
|
+
return renderNode3(node, options || {});
|
|
2108
|
+
}
|
|
2109
|
+
export {
|
|
2110
|
+
ASCII_BOX_CHARS,
|
|
2111
|
+
ASCII_DOUBLE_BOX_CHARS,
|
|
2112
|
+
DEFAULT_RENDER_CONTEXT,
|
|
2113
|
+
DEFAULT_THEME_TOKENS,
|
|
2114
|
+
SPINNER_FRAMES,
|
|
2115
|
+
UNICODE_DOUBLE_BOX_CHARS,
|
|
2116
|
+
UNICODE_ROUNDED_BOX_CHARS,
|
|
2117
|
+
UNICODE_SINGLE_BOX_CHARS,
|
|
2118
|
+
UNICODE_SYMBOLS,
|
|
2119
|
+
ansiToCSS,
|
|
2120
|
+
ansiToHTML,
|
|
2121
|
+
boxDrawingToASCII,
|
|
2122
|
+
buildBox,
|
|
2123
|
+
buildTableRow,
|
|
2124
|
+
buildTableSeparator,
|
|
2125
|
+
calculateColumnWidths,
|
|
2126
|
+
createCallbackRouterAdapter,
|
|
2127
|
+
createInteractiveRenderer,
|
|
2128
|
+
extractHeaders,
|
|
2129
|
+
extractPathParams,
|
|
2130
|
+
extractRowValues,
|
|
2131
|
+
extractStringArray,
|
|
2132
|
+
findActiveItemByPath,
|
|
2133
|
+
findActiveItemInSections,
|
|
2134
|
+
formatSegmentLabel,
|
|
2135
|
+
generateBreadcrumbSegments,
|
|
2136
|
+
getASCIIBoxChars,
|
|
2137
|
+
getIndentStr,
|
|
2138
|
+
getProp,
|
|
2139
|
+
getTextWidth,
|
|
2140
|
+
getUnicodeBoxChars,
|
|
2141
|
+
joinParts,
|
|
2142
|
+
joinPath,
|
|
2143
|
+
matchPath,
|
|
2144
|
+
matchPathPattern,
|
|
2145
|
+
normalizePath,
|
|
2146
|
+
padText,
|
|
2147
|
+
parseAnsiToSpans,
|
|
2148
|
+
renderANSI,
|
|
2149
|
+
renderASCII,
|
|
2150
|
+
renderInteractive,
|
|
2151
|
+
renderMarkdown,
|
|
2152
|
+
renderText,
|
|
2153
|
+
renderUnicode,
|
|
2154
|
+
sanitizeToASCII,
|
|
2155
|
+
spanToInlineStyle,
|
|
2156
|
+
wrapText
|
|
2157
|
+
};
|