如何用 JavaScript 构建漂亮的终端 UI(TUI)!
如果您像我一样,完全痴迷于 CLI 和终端 UI,那么这篇文章适合您!
不幸的是,JavaScript 中没有原生的方式可以构建漂亮的终端 UI——至少我所知道的没有!我自己也遇到了这个问题,最终促使我移植了最令人惊叹的 TUI 库之一:Lipgloss ,由Charm的团队创建。
不相信吗?看看这个:
很漂亮吧?
问题在于:Lipgloss 是用 Go 编写的。虽然我通常使用 Go 工作,但最近需要用 Node.js 编写一个 Web 监控工具。我不愿意放弃自己流畅美观的 UI,所以我发现自己陷入了典型的开发者挑战模式。
你知道那种当你深入代码时,意想不到的事情突然灵光一闪的神奇时刻吗?正因如此,我最终将 Lipgloss 的部分代码移植到了 WebAssembly(Wasm)。charsm 也由此诞生。
魅力是什么?
Charsm 是Charm CLI + Wasm的缩写。很酷吧?让我们深入研究如何使用它在 JavaScript 中构建令人惊叹的 TUI。
入门
使用简单的 npm 命令安装 charsm:
npm install charsm
创建一个简单的表
首先,charsm
在脚本中导入并初始化它:
import { initLip, Lipgloss } from "charsm";
(async function () {
const ini = await initLip();
})();
该initLip
函数加载 Wasm 文件,为渲染做好一切准备。让我们尝试打印一个表格:
const rows = [
["Chinese", "您好", "你好"],
["Japanese", "こんにちは", "やあ"],
["Arabic", "أهلين", "أهلا"],
["Russian", "Здравствуйте", "Привет"],
["Spanish", "Hola", "¿Qué tal?"],
];
const tabledata = {
headers: ["LANGUAGE", "FORMAL", "INFORMAL"],
rows: rows
};
(async function () {
const ini = await initLip();
const lip = new Lipgloss();
const table = lip.newTable({
data: tabledata,
table: { border: "rounded", color: "99", width: 100 },
header: { color: "212", bold: true },
rows: { even: { color: "246" } },
});
console.log(table);
})();
我们还可以使用十六进制代码来表示颜色(请查看结尾中的完整示例链接)
结果:
很简单吧?现在,我们来渲染列表。
渲染列表
目前,我们可以渲染一个简单的列表。它的工作原理如下:
const subtle = { Light: "#D9DCCF", Dark: "#383838" };
const special = { Light: "#43BF6D", Dark: "#73F59F" };
const list = lip.List({
data: ["Grapefruit", "Yuzu", "Citron", "Pomelo", "Kumquat"],
selected: [],
listStyle: "alphabet",
styles: {
numeratorColor: special.Dark,
itemColor: subtle.Dark,
marginRight: 1,
},
});
const combined = table + "\n\n" + list
console.log(combined);
自定义选定项目
让我们通过为选定项目使用自定义枚举器图标(例如✅)使其更加美观:
const customList = lip.List({
data: ["Grapefruit", "Yuzu", "Citron", "Pomelo", "Kumquat"],
selected: ["Grapefruit", "Yuzu"],
listStyle: "custom",
customEnum: "✅",
styles: {
numeratorColor: special.Dark,
itemColor: subtle.Dark,
marginRight: 1,
},
});
console.log(customList);
选定的项目将显示✅图标。
渲染 Markdown
Charsm 包装了Charm 中的Glamour库来处理 markdown 渲染:
const content = `
# Today’s Menu
## Appetizers
| Name | Price | Notes |
| ----------- | ----- | ------------------------------- |
| Tsukemono | $2 | Just an appetizer |
| Tomato Soup | $4 | Made with San Marzano tomatoes |
## Desserts
| Name | Price | Notes |
| ------------ | ----- | --------------------- |
| Dorayaki | $4 | Looks good on rabbits |
| Cream Puff | $3 | Pretty creamy! |
Enjoy your meal!
`;
console.log(lip.RenderMD(content, "tokyo-night"));
自定义样式
可以将 Charsm 中的样式视为终端的 CSS。您可以按照以下步骤创建自己的样式:
lip.createStyle({
id: "primary",
canvasColor: { color: "#7D56F4" },
border: { type: "rounded", sides: [true] },
// for both margin and padding top, right, bottom, left
padding: [6, 8, 6, 8],
margin: [0, 8, 8, 8],
bold: true,
// align: 'center',
width: 10,
height: 12,
});
lip.createStyle({
id: "secondary",
canvasColor: { color: "#7D56F4" },
border: { type: "rounded", background: "#0056b3", sides: [true, false]},
padding: [6, 8, 6, 8],
margin: [0, 0, 8, 1],
bold: true,
alignV: "bottom",
width: 10,
height: 12,
});
要将此样式应用于文本:
const styledText = lip.apply({ value: "Hello, charsm!", id: "primary" });
console.log(styledText);
请参阅github 上的自述文件以了解更多选项,或者更好的是,这里有一个“完整”的例子
想要布局吗?Charsm 支持简单的类似 flex 的布局:
const a = lip.apply({ value: "Charsmmm", id: "secondary" })
const b = lip.apply({ value: "🔥🦾🍕", id: "primary" })
const c = lip.apply({ value: 'Charsmmm', id: "secondary" })
const res = lip.join({
direction: "horizontal",
elements: [a, b, c],
position: "left",
});
console.log(res);
总结
就这样!有了 Charsm,你可以渲染表格、列表、Markdown,甚至创建自定义样式——所有这些都可以在终端内完成。顺便说一下,由于列表或 Markdown 是文本,所以你可以将其换行。
console.log(lip.apply({value: combined, id: "primary"}))
表格和列表将被包裹在边框中,并带有填充和边距!
这仅仅是个开始。我很快会添加一些交互式组件(比如表单),敬请期待。祝您使用 JavaScript 构建自己精美的终端 UI 充满乐趣!
您可以在substack上找到我,阅读更短的个人文章,以及x
你可以在x上找到我
再见!🫡
文章来源:https://dev.to/sfundomhlungu/how-to-build-beautiful-terminal-uis-tuis-in-javascript-74j