如何用JavaScript打造漂亮的终端界面(TUI)!
如果你也和我一样特别着迷于命令行界面和终端界面,这篇帖子就是为你写的!
可惜的是,在JavaScript中,没有一种内置的方法来构建漂亮的终端用户界面——至少我知道的没有!我自己也遇到了同样的问题,最终我决定移植了一个最令人惊艳的TUI库之一,即Lipgloss,由Charm团队开发。
你不相信我吗?你看看这个就知道了。
真好看,对吧?
有个需要注意的地方:Lipgloss 是用 Go 语言编写的。虽然我通常使用 Go,但我最近需要写一个用 Node.js 的网页监控工具。我可不想放弃那些漂亮的界面,所以我把自己置于一个经典的 开发者挑战模式,这样。
你知道那些神奇的瞬间,当你沉浸在编码中时,突然有个意想不到的东西就这么顺利了?就这样,我将 Lipgloss 的一部分移植到了 WebAssembly(Wasm)上。就这样,charsm 诞生了。
charm是什么?
Charsm 是 Charm CLI + Wasm 的简称。超酷的,对吧?让我们来看看如何用它来构建酷炫的 TUI(文本用户界面),这些 TUI 是用 JavaScript 编写的。
……
开始入门安装 charms 只需一条简单的 npm 命令:
npm install charsm
``` (安装名为charsm的npm包)
切换到全屏模式,退出全屏
此处为空
## 创建一个简单的表
首先,你需要在脚本中导入`charsm`并进行初始化。
import { initLip, Lipgloss } from "charsm";
// 异步初始化唇部模型
(async function () {
// 获取初始化的唇部模型
const ini = await initLip();
})();
全屏 退出全屏
`initLip`函数加载Wasm文件并为渲染做好准备。我们试着输出一个表格吧。
const rows = [
["中文", "您好", "你好"],
["日语", "こんにちは", "やあ"],
["阿拉伯语", "你好", "你好"],
["俄文", "Здравствуйте", "您好"],
["西班牙语", "Hola", "你好吗?"],
];
const tabledata = {
headers: ["语言", "正式", "非正式"],
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: ["葡萄柚", "柚子", "酸橙", "香橙", "金柑"],
selected: [],
listStyle: "字母",
styles: {
numeratorColor: special.Dark,
itemColor: subtle.Dark,
marginRight: 1,
},
});
const combined = table + "\n\n" + list;
console.log(combined);
全屏 退出全屏

**自定义选定项目**
让我们给选定的项目添加自定义图标(例如,✅),让它看起来更酷。
const customList = lip.List({
data: ["葡萄柚", "柚子", "酸橙", "香橙", "金柑"],
selected: ["葡萄柚", "柚子"],
listStyle: "custom",
customEnum: "✅",
styles: {
numeratorColor: special.Dark,
itemColor: subtle.Dark,
marginRight: 1,
},
});
console.log(customList);
全屏模式 退出全屏
所选项目会显示✅。

点击图片可查看大图
——
## Markdown 解析
Charsm 负责使用 Charm 的 **[Glamour](https://github.com/charmbracelet/glamour)** 库来渲染 markdown 内容。
const content = `
# 一个今日菜单
## 开胃菜
| 名称 | 价格 | 备注 |
| ----------- | ----- | ------------------------------- |
| 腌菜 | $2 | 只是一道开胃菜 |
| 番茄汤 | $4 | 用圣马扎诺番茄制成 |
## 甜点
| 名称 | 价格 | 备注 |
| ------------ | ----- | --------------------- |
| 豆沙煎饼 | $4 | 兔子看起来很好吃 |
| 奶油泡芙 | $3 | 非常奶油味! |
祝您用餐愉快!
`;
console.log(lip.RenderMD(content, "tokyo-night"));
全屏查看 / 退出全屏
* * *
## 自定义风格
可以把样式想象成终端里的 CSS。这里告诉你如何创建你自己的样式:
lip.createStyle({
id: "primary",
canvasColor: { color: "#7D56F4" },
border: { type: "rounded", sides: [true] },
// 边距和填充的上下左右
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,
});
全屏 退出全屏
要将这种样式应用到文本上:
// 这是将值“Hello, charsm!”和id设置为"primary"的应用示例。
const styledText = lip.apply({ value: "Hello, charsm!", id: "primary" });
console.log(styledText);
全屏 退出
查看 [readme](https://github.com/SfundoMhlungu/charsm) 以获取更多选项,或者更好的是,这里有一个 "全面" 的 [示例](https://github.com/SfundoMhlungu/charsm-example)
想要布局?Charsm支持简单的类似flex的布局:
const a = lip.apply({ value: "Charsmmm", id: "secondary" }) // 定义a变量
const b = lip.apply({ value: "🔥🦾🍕", id: "primary" }) // 定义b变量
const c = lip.apply({ value: 'Charsmmm', id: "secondary" }) // 定义c变量
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构建你自己的漂亮终端界面的乐趣吧!
你可以在[substack](https://sifundo.substack.com/)找到我写的短文章和个人文章,以及我在[x](https://x.com/codelit09)上的账号。
干了!
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦