diff --git a/docs/prototype/code-reader/figma-plugin/README.md b/docs/prototype/code-reader/figma-plugin/README.md index 544bf57..9c9f6be 100644 --- a/docs/prototype/code-reader/figma-plugin/README.md +++ b/docs/prototype/code-reader/figma-plugin/README.md @@ -8,7 +8,7 @@ - 每块默认显示译文,点块右边的「编辑」换成这一块的源码,点「预览」换回来。 - 译文是模板直译:结构照抄原语言,只把关键字、内置类型、运算符换成中文,名字和写法原样保留,每个关键字单独上色、前后有空格。例如 `export async function findEnvFiles(workspaceRoot: string): Promise` 译成 `公共 异步 函数 findEnvFiles(workspaceRoot: 字符串): Promise<字符串[]>`。注释原文照搬。 - 函数、导入、常量、变量这四种块不显示一行译文,而是树形属性表,类型里的内置类型译成中文(`string` → 字符串、`str` → 字符串),值照常译: - - 函数:名称、访问级别(公共 / 私有)、异步(是 / 否)、装饰器、输入参数(展开成每个参数一行:名称 / 类型 / 默认值三列,左边一条竖线)、输出参数。 + - 函数:名称、访问级别(公共 / 私有)、异步(是 / 否)、装饰器、输入参数(展开成一张带边框和表头的表格:名称 / 类型 / 默认值三列,每个参数一行)、输出参数。 - 导入:来源、仅类型(是 / 否,只有 TypeScript 有)、导入项(展开成每项一行,有别名写成「promises 作为 fsp」)。 - 常量 / 变量:名称、访问级别(只有最外层的声明有)、类型(写了标注才有)、值 / 初始值。 - 块左边有种类标签(导入、函数、类型、字段、常量、变量、条件、循环、尝试、捕获、返回、语句、注释),底色也带这个种类的颜色;有子块的块左边有折叠箭头。 @@ -100,7 +100,7 @@ node --test test.js - [ ] 不同种类的块一眼能分开:标签颜色、底色、边框都不同;同一种类(比如三个「返回」)颜色一致 - [ ] 译文里的关键字、变量名、函数名颜色和编辑器里对应的代码一致,关键字前后都有空格 - [ ] 有子块的块左边有折叠箭头,没有子块的没有,标签仍然对齐 -- [ ] 属性表:函数、导入、常量、变量的属性名一列对齐;导入项每项一行,左边竖线;输入参数下每个参数一行,名称 / 类型 / 默认值三列对齐,左边竖线从第一个参数连到最后一个;长类型(`Annotated[...]`)换行不挤掉默认值列 +- [ ] 属性表:函数、导入、常量、变量的属性名一列对齐;导入项每项一行,左边竖线;输入参数是带边框和表头的表格,名称 / 类型 / 默认值三列对齐;长类型(`Annotated[...]`)换行不挤掉默认值列 - [ ] 遍历:小框和前后文字在同一行里对齐、太长时整体换行;循环图标和「循环」块同色 - [ ] 筛选:筛选栏固定在预览顶部、和代码块左右对齐;下拉菜单盖在代码块上面;藏掉的块不留空位,左边层级竖线跟着变短 - [ ] 文件注释:悬停行的按钮贴在行尾、不挤掉名字;注释灰字紧跟名字、长了截断;顶部输入框居中,看得出是 VS Code 自带的样子 diff --git a/docs/prototype/code-reader/figma-plugin/code.js b/docs/prototype/code-reader/figma-plugin/code.js index b63d256..ebde690 100644 --- a/docs/prototype/code-reader/figma-plugin/code.js +++ b/docs/prototype/code-reader/figma-plugin/code.js @@ -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; } }