把杂乱CSS值变成语义设计令牌:design-md-chrome归一化算法深度解析
【免费下载链接】design-md-chromeChrome extension to extract styles from any website and generate DESIGN.md files and design skills for AI based on TypeUI项目地址: https://gitcode.com/gh_mirrors/de/design-md-chrome
design-md-chrome 是一款 Chrome 插件,能一键提取任意网页的字体、颜色、间距、圆角、阴影与动效等原始 CSS 值,并通过归一化算法把它们整理成语义设计令牌(Design Tokens),最终生成可供 AI 工具直接使用的 DESIGN.md 设计系统文档。这篇文章带你深入拆解它的归一化算法:从 280 个元素的采样,到颜色排名、字号阶梯和置信度推断,看看杂乱的 CSS 值是如何变成一张整洁的令牌表的。🧩
为什么要把 CSS 原始值"归一化"
打开任意网页,浏览器计算样式里看到的值往往是这样一番景象:
- 同一套白色可能写成
rgb(255, 255, 255)、#fff或white - 间距散落着
8px、12px、16px……毫无规律 - 字体族带着引号、大小写和冗长的回退栈
这些"原始值"人类勉强能读,但AI 工具无法基于它写出一套一致的设计系统。design-md-chrome 的核心,就是在采样和生成 Markdown 之间插入了一个归一化层:统计每个值出现的次数,把高频值排名、去重、映射成语义化令牌名。整个算法集中在 lib/normalize.mjs 一个文件中,入口函数是normalizeExtractedStyles(L8-L148)。
归一化流水线:四个阶段各司其职
| 阶段 | 负责文件 | 核心工作 |
|---|---|---|
| ① 元素采样 | content-script.js | 遍历最多 280 个可见元素,读取计算样式 |
| ② 值归一化 | lib/normalize.mjs | 标准化、计数、排名、映射令牌名 |
| ③ Markdown 生成 | lib/generate-design-md.mjs | 把令牌组装成 DESIGN.md |
| ④ 质量校验 | lib/validate.mjs | 检查必备章节与无障碍目标 |
四个阶段由 service-worker.js 串联:插件注入采样脚本到页面后,把原始数据交给归一化层,再生成并校验最终文档(见 handleExtraction L34-L66)。
颜色归一化:先统一格式,再按使用量排名
第一步是格式统一。浏览器返回的rgb(17, 24, 39)和手写的#111827其实是同一个颜色。归一化算法把所有rgb()/rgba()值解析并转成标准十六进制格式,同时直接丢弃transparent这类无意义的透明值(toCanonicalColor函数,L673-L708)。
第二步是使用量排名。只有格式统一后,"同一个颜色"才能被正确计数。之后算法按出现次数取 Top N,映射到固定的语义名称:
| 排名 | 文本色 | 背景色 | 边框色 |
|---|---|---|---|
| 第 1 名 | color.text.primary | color.surface.base | color.border.default |
| 第 2 名 | color.text.secondary | color.surface.muted | color.border.muted |
| 第 3 名 | color.text.tertiary | color.surface.raised | color.border.strong |
| 第 4 名 | color.text.inverse | color.surface.strong | — |
此外还会额外提取出现最多的描边色作为color.focus.ring(焦点环颜色),并跨类别按颜色值去重(buildColorTokens,L556-L596)。这样"用得最多的深色"永远是你的主文本色,而不是随机的十六进制码。🎨
字号、间距、圆角:把散值收拢成数字阶梯
字号、间距、圆角、动效时长走的是同一条"计数 → 排序 → 命名"的路线(toTokenRows,L616-L630):
- 解析:把
"16px"、"150ms"这类字符串解析成数字(parsePx、parseDuration),"normal"、"auto"等无效值直接过滤; - 计数:每个数字值出现一次就加一票,页面里用得越多的尺寸越靠前;
- 排序:按键值从小到大排序(
sortNumericKeys); - 命名:按预设阶梯名称贴上令牌名。
各类令牌对应的阶梯命名如下:
| 令牌前缀 | 阶梯名称 | 示例 |
|---|---|---|
font.size | xs, sm, md, lg, xl, 2xl, 3xl, 4xl | font.size.md = 16px |
space | 数字序列 space.1, space.2… | space.3 = 16px |
radius | xs, sm, md, lg, xl, 2xl | radius.md = 8px |
motion.duration | instant, fast, normal, slow, slower | motion.duration.fast = 150ms |
阶梯名称常量定义在 normalize.mjs 顶部。阴影因为无法简单排序,则直接按使用量取 Top 4 命名为shadow.1~shadow.4;缓动函数只统计非默认ease的值,取前 4 名。
间距采样时有一个细节:margin 和 padding 的 8 个方向值会被全部摊平统计(normalize.mjs L53-L70),而且只统计大于 0 的值——避免0px淹没真正有意义的间距档位。
字体族推断:从回退栈到"主字体"
字体族字符串通常长这样:"Inter", "Helvetica Neue", Arial, sans-serif。算法会做两件事:
- 标准化字体栈:去引号、去多余空白、统一分隔符(
normalizeFontFamilyStack,L515-L531),让写法不同的同一字体栈也能被正确聚合计数; - 推断主字体样式:在字体族使用占比最高的前提下,再找出该字体下最常见的一组"字重 + 字号 + 行高"组合,作为主字体样式输出(
inferMainFontStyle,L462-L505)。
置信度按占比划分:字体族使用占比 ≥ 45% 且样式出现 ≥ 3 次为high;占比 ≥ 20% 为medium;其余为low。页面字体越混杂,算法越会如实告诉你的置信度低,而不是硬猜。
网站画像推断:多信号加权打分
归一化层还顺带推断"这是个什么网站、给谁看",用于生成文档中的 Brand 章节(inferSiteProfile,L150-L319)🧭
算法把页面的标题、描述、导航文本、CTA 按钮文本拼成一段"语料",然后对 6 类产品形态(文档站、仪表盘、营销页、内容站、电商、Web 应用)和 6 类受众(开发者、运营、商务、消费者、阅读者、普通用户)分别打分:
- 关键词命中:语料里出现
pricing、checkout等词就为对应形态加分; - 数字证据:表单 ≥ 3 个、输入框 ≥ 8 个、出现表格 → 倾向仪表盘;出现定价区块 → 倾向营销页;
- 路径线索:URL 含
/docs、/api→ 倾向文档站。
每个形态取最高分作为结论,并保留前 8 条证据供人工核对。置信度规则很严谨:总分 ≥ 5 且领先第二名 ≥ 1.4 才判high,否则降级为 medium 或 low(L390-L398)。最终置信度取"形态"与"受众"两者中较低的那个,宁保守不误报。
内置诊断:主动告诉你结果何时不可信
归一化输出里附有一个diagnostics诊断列表(L114-L129),这是这套算法很贴心的设计——它知道自己什么时候不可靠:
| 诊断信号 | 触发条件 | 提示含义 |
|---|---|---|
| 样本量不足 | 可见元素 < 30 个 | 页面太简单,统计不具代表性 |
| 颜色多样性低 | 令牌颜色 < 4 个 | 颜色推断置信度低 |
| 字号多样性低 | 字号档 < 3 个 | 字号阶梯可能需要人工细化 |
| 主字体缺失 | 无法确定字体族 | 主字体信息不可信 |
| 画像置信度低 | 网站画像为 low | 品牌上下文请人工确认 |
这些诊断会原样写入生成的 DESIGN.md 的"组件规则期望"一节(见 generate-design-md.mjs L84-L89),让使用者一眼看出哪些令牌需要手动复核。🩺
动手验证:跑一遍内置测试
项目自带一份模拟采样数据的测试脚本,你可以观察"原始值 → 归一化结果 → 最终 Markdown"的完整链路:
node tests/run-tests.mjs测试用 mock 数据还原了一个仪表盘页面的采样结果,包括rgb(17, 24, 39)这类原始颜色值和 150ms 的过渡时长(见 tests/run-tests.mjs L7-L78)。生成的文档结构以仓库根目录的 DESIGN.md 为蓝本:包含 Mission、Brand、Style Foundations、Accessibility、Rules: Do/Don't 等 11 个必备章节,validate.mjs 会对这些章节逐一检查,缺少任何一节都会报错。
总结
design-md-chrome 的归一化算法用了一条朴素而有效的思路:先统一格式,再按使用量排名,最后贴上语义名称。颜色、字号、间距、圆角、阴影、动效各自遵循这套流程,再叠加字体置信度、网站画像和内置诊断,把"杂乱 CSS 值"变成了一份 AI 可直接消费、人类也看得懂的语义设计令牌表。如果你想在自己的项目里复刻类似的"提取 → 归一化 → 生成文档"流水线,这个仓库 lib/ 目录下的四个模块就是最好的参考起点。⚡
【免费下载链接】design-md-chromeChrome extension to extract styles from any website and generate DESIGN.md files and design skills for AI based on TypeUI项目地址: https://gitcode.com/gh_mirrors/de/design-md-chrome
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考