✨ feat(prototype): 代码阅读输入参数改成带表头的表格

This commit is contained in:
cruldra committed 2026-09-26 15:31:35 +08:00
1 parent f79666175b
commit 5872cf7958
2 files changed
+35 -8

No files matched your search

@@ -8,7 +8,7 @@
- 每块默认显示译文,点块右边的「编辑」换成这一块的源码,点「预览」换回来。
- 译文是模板直译:结构照抄原语言,只把关键字、内置类型、运算符换成中文,名字和写法原样保留,每个关键字单独上色、前后有空格。例如 `export async function findEnvFiles(workspaceRoot: string): Promise<string[]>` 译成 `公共 异步 函数 findEnvFiles(workspaceRoot: 字符串): Promise<字符串[]>`。注释原文照搬。
- 函数、导入、常量、变量这四种块不显示一行译文,而是树形属性表,类型里的内置类型译成中文(`string` → 字符串、`str` → 字符串),值照常译:
- 函数:名称、访问级别(公共 / 私有)、异步(是 / 否)、装饰器、输入参数(展开成每个参数一行:名称 / 类型 / 默认值三列,左边一条竖线)、输出参数。
- 函数:名称、访问级别(公共 / 私有)、异步(是 / 否)、装饰器、输入参数(展开成一张带边框和表头的表格:名称 / 类型 / 默认值三列,每个参数一行)、输出参数。
- 导入:来源、仅类型(是 / 否,只有 TypeScript 有)、导入项(展开成每项一行,有别名写成「promises 作为 fsp」)。
- 常量 / 变量:名称、访问级别(只有最外层的声明有)、类型(写了标注才有)、值 / 初始值。
- 块左边有种类标签(导入、函数、类型、字段、常量、变量、条件、循环、尝试、捕获、返回、语句、注释),底色也带这个种类的颜色;有子块的块左边有折叠箭头。
@@ -100,7 +100,7 @@ node --test test.js
- [ ] 不同种类的块一眼能分开:标签颜色、底色、边框都不同;同一种类(比如三个「返回」)颜色一致
- [ ] 译文里的关键字、变量名、函数名颜色和编辑器里对应的代码一致,关键字前后都有空格
- [ ] 有子块的块左边有折叠箭头,没有子块的没有,标签仍然对齐
- [ ] 属性表:函数、导入、常量、变量的属性名一列对齐;导入项每项一行,左边竖线;输入参数下每个参数一行,名称 / 类型 / 默认值三列对齐,左边竖线从第一个参数连到最后一个;长类型(`Annotated[...]`)换行不挤掉默认值列
- [ ] 属性表:函数、导入、常量、变量的属性名一列对齐;导入项每项一行,左边竖线;输入参数是带边框和表头的表格,名称 / 类型 / 默认值三列对齐;长类型(`Annotated[...]`)换行不挤掉默认值列
- [ ] 遍历:小框和前后文字在同一行里对齐、太长时整体换行;循环图标和「循环」块同色
- [ ] 筛选:筛选栏固定在预览顶部、和代码块左右对齐;下拉菜单盖在代码块上面;藏掉的块不留空位,左边层级竖线跟着变短
- [ ] 文件注释:悬停行的按钮贴在行尾、不挤掉名字;注释灰字紧跟名字、长了截断;顶部输入框居中,看得出是 VS Code 自带的样子
+33 -6
View File
@@ -1122,14 +1122,41 @@ function subRows(ctx, parent) {
return append(group, frame(ctx, "List", { width: 10, gap: 2 }), true);
}
/** 输入参数的子行:每个参数一行,名称 / 类型 / 默认值三列对齐。 */
/**
* 输入参数:带边框和表头的表格,名称 / 类型 / 默认值三列,每个参数一行。
* 名称、类型两列固定宽度,默认值占剩下的宽度;格子之间、行之间一条分隔线,表头底色深一档、字用说明色。
*/
const PARAM_COLUMNS = [["名称", 150], ["类型", 220], ["默认值", 0]];
function paramRows(ctx, parent, params, lang) {
const list = subRows(ctx, parent);
const wrap = filled(ctx, parent, "Params", {});
wrap.paddingLeft = 5;
const table = append(wrap, frame(ctx, "Table", { width: 10, radius: 4, stroke: COLORS.borderStrong }), true);
table.clipsContent = true;
const row = (name, cells, header) => {
const node = filled(ctx, table, name, { dir: "HORIZONTAL", fill: header ? COLORS.side : null });
cells.forEach((segments, index) => {
const [label, width] = PARAM_COLUMNS[index];
const cell = width ? append(node, frame(ctx, label, { width, px: 8, py: 3 })) : filled(ctx, node, label, { px: 8, py: 3 });
cell.layoutSizingVertical = "FILL";
if (index < cells.length - 1) {
cell.strokes = paint(COLORS.borderStrong);
cell.strokeRightWeight = 1;
cell.strokeTopWeight = cell.strokeBottomWeight = cell.strokeLeftWeight = 0;
}
richText(ctx, cell, "Text", segments);
});
return node;
};
row("Header", PARAM_COLUMNS.map(([label]) => [{ text: label, color: COLORS.desc }]), true);
for (const param of params) {
const row = filled(ctx, list, `Param / ${param.name}`, { dir: "HORIZONTAL", gap: 12 });
richText(ctx, row, "Name", [{ text: param.name, color: COLORS.tokenVariable }], { width: 150 });
richText(ctx, row, "Type", param.type ? typeSegments(param.type, lang) : [{ text: "未标注", color: COLORS.desc }], { width: 220 });
richText(ctx, row, "Default", param.value ? [{ text: "默认 ", color: COLORS.desc }, ...segmentsOf(translateCode(param.value, lang))] : []);
const node = row(`Param / ${param.name}`, [
[{ text: param.name, color: COLORS.tokenVariable }],
param.type ? typeSegments(param.type, lang) : [{ text: "未标注", color: COLORS.desc }],
param.value ? segmentsOf(translateCode(param.value, lang)) : [],
]);
node.strokes = paint(COLORS.borderStrong);
node.strokeTopWeight = 1;
node.strokeBottomWeight = node.strokeLeftWeight = node.strokeRightWeight = 0;
}
}