skill-forge-hub 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +94 -2
- package/annual-report/SKILL.md +31 -0
- package/annual-report/resources/content-rules.md +40 -0
- package/annual-report/resources/data-collection.md +25 -0
- package/annual-report/resources/date-parsing.md +18 -0
- package/annual-report/resources/disk-and-html.md +28 -0
- package/annual-report/resources/industry-dictionary.md +19 -0
- package/annual-report/resources/usage-guide.md +26 -0
- package/annual-report/user-config.md +37 -0
- package/article-to-html/SKILL.md +239 -0
- package/article-to-html/design-system.md +358 -0
- package/article-to-html/scripts/download_roboto.py +38 -0
- package/article-to-html/scripts/extract_docx.py +68 -0
- package/article-to-html/scripts/inline_fonts.py +32 -0
- package/article-to-html/scripts/install_sourcehan.py +78 -0
- package/cli.js +350 -0
- package/daily-report/SKILL.md +31 -0
- package/daily-report/resources/content-rules.md +82 -0
- package/daily-report/resources/data-collection.md +40 -0
- package/daily-report/resources/date-parsing.md +21 -0
- package/daily-report/resources/disk-and-html.md +14 -0
- package/daily-report/resources/industry-dictionary.md +19 -0
- package/daily-report/resources/usage-guide.md +65 -0
- package/daily-report/user-config.md +36 -0
- package/package.json +33 -4
- package/spec-doc2spec/SKILL.md +64 -0
- package/spec-doc2spec/resources/checklist.md +25 -0
- package/spec-doc2spec/resources/images.md +27 -0
- package/spec-doc2spec/resources/structure.md +27 -0
- package/spec-doc2spec/resources/usage-guide.md +32 -0
- package/spec-spec2doc/SKILL.md +62 -0
- package/spec-spec2doc/resources/checklist.md +24 -0
- package/spec-spec2doc/resources/images-and-template.md +14 -0
- package/spec-spec2doc/resources/pdf-path.md +21 -0
- package/spec-spec2doc/resources/usage-guide.md +32 -0
- package/template/SKILL.md +42 -0
- package/template/resources/README.md +20 -0
- package/weekly-report/SKILL.md +31 -0
- package/weekly-report/resources/content-rules.md +82 -0
- package/weekly-report/resources/data-collection.md +41 -0
- package/weekly-report/resources/date-parsing.md +20 -0
- package/weekly-report/resources/disk-and-html.md +14 -0
- package/weekly-report/resources/industry-dictionary.md +19 -0
- package/weekly-report/resources/usage-guide.md +68 -0
- package/weekly-report/user-config.md +37 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: article-to-html
|
|
3
|
+
description: Converts Word (.docx), Markdown, or plain-text articles into a polished standalone HTML page using Source Han Sans SC + Roboto fonts (both free for commercial use), redrawing all charts/diagrams with HTML/CSS instead of embedding source images, then captures per-chapter element-level screenshots (Retina 2x, uniform width, shadow-safe margins). Use when the user provides a document or article file (a bare file path with no instruction also triggers it), asks to make an HTML page, beautify an article for publishing, or generate screenshots of article sections. Also handles existing HTML files directly: captures per-chapter screenshots from a ready-made HTML page, or restyles/beautifies an existing HTML page first (then screenshots on request). Use when the user hands over an already-built .html file and asks to screenshot it or make it prettier. Also responds with a plain-language usage guide when the user asks how to use this skill (e.g. "使用说明", "怎么用", "能干什么").
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Article to Beautiful HTML + Chapter Screenshots
|
|
7
|
+
|
|
8
|
+
Turn any Word/Markdown/plain-text article into a standalone styled HTML page and a set of per-chapter screenshots, all saved locally.
|
|
9
|
+
|
|
10
|
+
## 用户使用说明(User Guide)
|
|
11
|
+
|
|
12
|
+
当用户问「这个技能怎么用」「使用说明」「能干什么」时,用本节的人话版说明回复,不要复述内部流程术语(骨架侦察/零侵权核查等)。
|
|
13
|
+
|
|
14
|
+
### 能干什么(三句话版)
|
|
15
|
+
|
|
16
|
+
1. **文档变网页**:把 Word / Markdown / 纯文本文章装裱成带封面的精美 HTML 页面——免费商用字体、图表矢量重绘、双击即开
|
|
17
|
+
2. **已有页面美化**:给一个现成的 HTML 换装修(配色/排版/组件样式),不动正文文字
|
|
18
|
+
3. **按章节截图**:把文章页面按章节截成统一宽度的高清图(1460px),适合公众号配图与拼长图
|
|
19
|
+
|
|
20
|
+
### 用户怎么开口(示例话术)
|
|
21
|
+
|
|
22
|
+
| 用户说(说法可以换) | 技能做 |
|
|
23
|
+
|:---|:---|
|
|
24
|
+
| 「把这篇文章转成 HTML」「做成网页」「排版一下」「公众号排版」 | 走全流程:解析 → 建页面 → 截图前先问一句效果满意否 |
|
|
25
|
+
| 直接丢一个 .docx / .md / .txt 文件路径(什么都不说也行) | 同上,丢路径即触发 |
|
|
26
|
+
| 「把这篇 Word 转成好看的网页,顺便截个图」 | 全流程,用户点头后自动逐章截图 |
|
|
27
|
+
| 「这个页面美化一下」「装修一下」「换个配色」「好看点」 | 只装修已有 HTML,不改正文 |
|
|
28
|
+
| 「这个 HTML 按章节截图」「截成长图」「每章一张图」「出图」 | 只截图,先看页面结构再逐章定格 |
|
|
29
|
+
| 「使用说明」「怎么用」「能干什么」「有什么功能」 | 回复本节的人话版用法说明 |
|
|
30
|
+
|
|
31
|
+
### 过程中会问什么
|
|
32
|
+
|
|
33
|
+
- **字体**:系统缺思源黑体时,问是否自动安装(全页只许 Roboto + 思源黑体,无替代字体)
|
|
34
|
+
- **风格**:文章气质拿不准时,让用户在 2-4 款版式候选里挑
|
|
35
|
+
- **确认一**:页面做好后、截图前问「效果满意吗」——可反复调,至多 3 轮
|
|
36
|
+
- **确认二**:截完图请用户抽看封面 + 最长章节两张图,发现缺字/截断只重截该章
|
|
37
|
+
|
|
38
|
+
### 交付物
|
|
39
|
+
|
|
40
|
+
- `<标题>.html`——标准版(配 assets/fonts 字体文件)
|
|
41
|
+
- `<标题>-单文件版.html`——字体全内嵌,双击即开、可随意移动分享
|
|
42
|
+
- `文章截图/章节截图/C00-封面.png … C0N-xx.png`——统一 1460px 宽,按序拼接即整篇长图
|
|
43
|
+
|
|
44
|
+
### 常见问题
|
|
45
|
+
|
|
46
|
+
- **为什么截图统一 1460px 宽?** 统一规格便于拼长图、发公众号,Retina 2x 保证高清
|
|
47
|
+
- **为什么只有 Roboto + 思源黑体?** 两者均为免费商用授权,其余字体一律不用,零侵权
|
|
48
|
+
- **单文件版什么时候给?** 定稿后重铸一次;中途调整期间不重铸以省时间
|
|
49
|
+
- **改过的文章再处理?** 会先问「覆盖重生成 / 只重新截图 / 仅改样式」三选一
|
|
50
|
+
|
|
51
|
+
## Prerequisites(新用户准备)
|
|
52
|
+
|
|
53
|
+
1. **Qoder 环境**:本 Skill 依赖 AI agent + Browser 子代理,在 Qoder 中直接可用,无需额外安装
|
|
54
|
+
2. **安装 Skill**:将 `article-to-html/` 目录放入 `~/.qoder-cn/skills/`(个人全局,推荐)或项目 `.qoder/skills/`,重启 Qoder 即可被识别
|
|
55
|
+
3. **Python 3(可选,非硬依赖)**:脚本依赖,macOS 验证 `python3 --version`,缺失则 `xcode-select --install`(Windows 到 python.org 安装)。没有 Python 时用 Bash 降级路径:docx 解析 `unzip` + Read XML、字体内嵌 `base64 -i xxx.woff2`、字体检测 `ls` 字体目录、下载 `curl`、解压 `unzip`、安装 `cp`
|
|
56
|
+
4. **思源黑体(自动检测安装)**:执行时先运行 `python3 scripts/install_sourcehan.py` 检测系统是否已装;缺失则自动从 Adobe Fonts 官方 release(2.005R,OFL 免费可商用)下载并安装到用户字体目录(macOS `~/Library/Fonts` / Windows 用户字体目录),含 SHA-256 校验与 ghfast.top 镜像兜底。安装失败或未装时,浏览器会 fallback 到苹方(macOS)/ 微软雅黑(Windows),同为免费可商用黑体风格,观感接近
|
|
57
|
+
5. **网络**:Roboto woff2 在执行时自动从 cdn.jsdelivr.net 下载到 `assets/fonts/`,需能访问该 CDN
|
|
58
|
+
6. **无需安装**:Roboto(自动下载)、浏览器(系统自带)、HTTP 服务器(python3 内置)、截图能力(Browser 子代理提供)
|
|
59
|
+
|
|
60
|
+
## Fonts (mandatory, free for commercial use)
|
|
61
|
+
|
|
62
|
+
- 中文:思源黑体,字体栈**绝对纯粹**——`--sans` 仅 `'Roboto','Source Han Sans SC'`,`--mono` 仅 `'Source Han Sans SC'`(代码块也强制思源黑体);别名(Noto Sans SC/思源黑体)与兜底(苹方/雅黑/系统字体/sans-serif)一律清除;SVG 内 font-family 同样仅此两字体。未装思源黑体时宁可缺字(截图抽检必发现),不可静默回退
|
|
63
|
+
- 英文/数字:Roboto,self-hosted woff2(400/500/700/900),从 `https://cdn.jsdelivr.net/npm/@fontsource/roboto@5.2.6/files/roboto-latin-{w}-normal.woff2` 下载到 `assets/fonts/`(每个约 20KB)
|
|
64
|
+
- 两者均为 SIL Open Font License,免费可商用
|
|
65
|
+
|
|
66
|
+
## Workflow
|
|
67
|
+
|
|
68
|
+
### 0. 意图分流(先辨场景,选对分支)
|
|
69
|
+
|
|
70
|
+
- 用户丢来 **docx / md / txt**(或仅一个文件路径)→ 走全流程 1→5
|
|
71
|
+
- 用户丢来 **已有 HTML + 要截图**(「把这个页面按章节截一下」)→ 走第 6 步「只截图」分支
|
|
72
|
+
- 用户丢来 **已有 HTML + 要美化**(「美化一下」「按你的风格装修」)→ 走第 6 步「只美化」分支,定稿后按需截图
|
|
73
|
+
- 拿不准时用一句话确认意图,不擅自走全流程
|
|
74
|
+
|
|
75
|
+
**识别词表(用户说法千变万化,按意图对号入座)**:
|
|
76
|
+
|
|
77
|
+
| 用户意图 | 常见说法(听到任一即进对应分支) |
|
|
78
|
+
|:---|:---|
|
|
79
|
+
| **全流程**(文档→HTML→截图) | 转成网页 / 做成 HTML / 生成页面 / 排版 / 装裱 / 公众号排版 / 把 Word 变成网页 / 这篇文章做个好看的页面 / 处理这个文档 |
|
|
80
|
+
| **只美化**(已有 HTML) | 美化 / 装修 / 改样式 / 换配色 / 调排版 / 好看点 / 精致一点 / 优化页面 / 升级版式 / 换个风格 |
|
|
81
|
+
| **只截图**(已有 HTML) | 截图 / 按章节截图 / 逐章截图 / 截成长图 / 每章一张图 / 生成配图 / 出图 / 导出图片 / 公众号配图 / 要长图 |
|
|
82
|
+
| **问用法** | 使用说明 / 怎么用 / 能干什么 / 有什么功能 / 怎么操作 / 帮助 / 介绍一下 |
|
|
83
|
+
|
|
84
|
+
- 按文件类型兜底:`*.docx / *.doc / *.md / *.txt` → 全流程;`*.html` → 按其余关键词分流到只美化 / 只截图
|
|
85
|
+
- 说「截图」且文件是 html → 只截图;说「截图」且文件是 docx/md → 全流程(含截图)
|
|
86
|
+
- 词表未覆盖且拿不准时,一句话反问确认,不瞎猜
|
|
87
|
+
|
|
88
|
+
### 1. Parse the source document
|
|
89
|
+
|
|
90
|
+
- `.docx`:运行 `python3 scripts/extract_docx.py input.docx --media-dir /tmp/docx-extract > /tmp/extracted.json`,输出正文段落(`texts`)、表格结构(`tables`,行优先二维数组,重建表格时按行列还原)、图片清单(`media`)并落盘到 media-dir
|
|
91
|
+
- `.md` / `.txt`:直接用 Read 读取
|
|
92
|
+
- **用 Read 工具逐张查看文档内嵌图片**,弄清每张图表内容,然后**用 HTML/CSS 重绘**——绝不嵌入原图(位图截图会糊)
|
|
93
|
+
|
|
94
|
+
### 2. Prepare fonts
|
|
95
|
+
|
|
96
|
+
- 下载 4 个 Roboto 字重:`python3 scripts/download_roboto.py <目标目录>/assets/fonts`(脚本自动跳过已存在的文件)
|
|
97
|
+
- 思源黑体:先运行 `python3 scripts/install_sourcehan.py` 检测(已装则直接跳过,无任何动作)
|
|
98
|
+
- **缺失时用 AskUserQuestion 询问,并完整告知**:①不安装则无法使用思源黑体,中文将 fallback 到苹方/微软雅黑(观感接近但不是思源黑体);②字体白名单锁死为 Roboto + 思源黑体,无任何替代字体
|
|
99
|
+
- 询问选项:「自动安装思源黑体(推荐)/ 跳过用系统 fallback」——字体白名单锁死为 Roboto + 思源黑体,不接受第三方字体;默认不擅自修改用户系统,除非用户明确要求全自动
|
|
100
|
+
- 自动安装细节:脚本内置 ghfast.top 镜像兜底 + SHA-256 校验,装完提示用户重启浏览器生效
|
|
101
|
+
- 严禁执行 `atsutil databases -removeUser`(会破坏 macOS 字体数据库,用 `killall fontd` 刷新缓存)
|
|
102
|
+
|
|
103
|
+
### 2.5 按气质选版式(构建前)
|
|
104
|
+
|
|
105
|
+
- 通读解析出的内容,判断文章气质(科技 / 文艺 / 教程 / 科普 / 报道 / 商业等),从 [design-system.md](design-system.md)「0. 风格菜单」的六款版式中选一款
|
|
106
|
+
- 默认款(暗色封面长文风)适用于大多数科技 / 产品文;文艺散文选文艺排版风;教程干货选极简白;硬核技术选终端极客风;科普清单选卡片流;深度报道选报纸分栏
|
|
107
|
+
- 拿不准或用户有明确偏好时,用 AskUserQuestion 让用户在 2-4 款候选里挑(每款附一句话气质描述),不替用户做有风格争议的决定
|
|
108
|
+
- 任何风格都不许引入第三个字体:文艺排版风同样只用思源黑体,文艺感靠排版营造(大行距、留白、首字下沉、细分割线),不得改用宋体
|
|
109
|
+
- 无论哪款风格:字体白名单锁死(Roboto + 思源黑体)、零兜底、第 3.5 步核查照跑
|
|
110
|
+
|
|
111
|
+
### 3. Build the HTML
|
|
112
|
+
|
|
113
|
+
- 先写入当前工作区(如 `outputs/<标题>.html`),完成后用 Bash `cp` 到用户目标目录——Write 工具被沙盒限制在工作区内
|
|
114
|
+
- 大文件分片写:Write 创建文件(head + 封面 + 前几章),后续用 SearchReplace 以文件末尾 `</section>\n</div>\n</body>\n</html>` 为锚点追加章节
|
|
115
|
+
- 使用 [design-system.md](design-system.md) 中的 CSS 变量与组件模式;源文档中每张图表必须有对应的 HTML/CSS 组件;表格 `td` 一律 `vertical-align:middle`
|
|
116
|
+
- 页面背景默认浅灰 `#f6f8fb`;用户要纯白截图时改 `--bg:#ffffff`(深色封面 hero 保持不动)
|
|
117
|
+
|
|
118
|
+
### 3.5 交付前零侵权核查(必做,不可跳过)
|
|
119
|
+
|
|
120
|
+
生成 HTML 后、交付与截图前,逐文件执行以下 grep 扫描,**任何命中都必须清零**:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
grep -nE "PingFang|YaHei|apple-system|sans-serif|serif|monospace|SF Mono|Menlo|Monaco|Consolas|Arial|Helvetica|宋体|黑体|楷体|微软雅黑|system-ui|googleapis" <产出.html>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
全页字体只允许两个家族名:`Source Han Sans SC`(SIL OFL 1.1)与 `Roboto`(Apache 2.0,仅本地 woff2,禁引任何字体 CDN)。宁可缺字方框,不可出现任何未经授权字体——合规性高于美观性。
|
|
127
|
+
|
|
128
|
+
**六类逐项核查表**(中文 / 英文 / 数字 / 代码 / SVG / emoji):
|
|
129
|
+
|
|
130
|
+
| 类别 | 合法字体 | 禁用 |
|
|
131
|
+
|:---|:---|:---|
|
|
132
|
+
| 中文正文/标题 | Source Han Sans SC(OFL) | 宋体/黑体/楷体/仿宋/方正/汉仪/华文及一切商业字体 |
|
|
133
|
+
| 英文 | Roboto(Apache 2.0) | Arial/Helvetica/Verdana/Georgia/Times 等 |
|
|
134
|
+
| 数字 | Roboto(Apache 2.0) | 同上 |
|
|
135
|
+
| 代码 code/pre | Source Han Sans SC(--mono 仅此一家) | 等宽商业字体、系统等宽字体 |
|
|
136
|
+
| SVG 内文字 | Roboto + Source Han Sans SC | 其他任何字体名 |
|
|
137
|
+
| emoji | 系统内置 emoji 字体(无风险,无需处理) | — |
|
|
138
|
+
|
|
139
|
+
**外部资源核查**:grep `https?://|<link|<script|@import` 确认无字体 CDN、无外部样式/脚本;SVG 命名空间 `w3.org/2000/svg` 与文内引文链接属正常,不构成字体风险。
|
|
140
|
+
|
|
141
|
+
### 4. Local deliverables
|
|
142
|
+
|
|
143
|
+
- 标准版:`<标题>.html` + 同级 `assets/fonts/`
|
|
144
|
+
- 单文件自包含版:`python3 scripts/inline_fonts.py <src.html> <out.html> <fonts_dir>`,将 Roboto 以 base64 内嵌,双击即开、可随意移动分享
|
|
145
|
+
|
|
146
|
+
### 4.5 用户确认(先确认后截图,必做)
|
|
147
|
+
|
|
148
|
+
**时机**:HTML 交付后、截图前。用 RunPreview 打开页面,同时把本地文件路径告知用户(双击即开),再 AskUserQuestion 询问。
|
|
149
|
+
|
|
150
|
+
**询问设计**:
|
|
151
|
+
「页面效果是否满意?」
|
|
152
|
+
- **满意,开始截图** → 进入第 5 步
|
|
153
|
+
- **需要调整** → 请用户自由描述哪里不满意(配色/布局/字号/图表样式/内容组织/封面),不限于预设选项
|
|
154
|
+
- **全自动模式**:用户曾明确表示「不用问、一路做完」时,跳过本节点直接截图;否则一律先问
|
|
155
|
+
|
|
156
|
+
**调整执行纪律**:
|
|
157
|
+
- 只改工作区 HTML → `cp` 覆盖目标目录标准版 → 再次 RunPreview + 询问确认,循环至满意
|
|
158
|
+
- 小调整(改色/间距/字号)只动 CSS;大调整(重排章节/换图表形式)才动结构
|
|
159
|
+
- **调整期间暂不重铸单文件版**(每次重铸费时且无必要);最终定稿后再用 `inline_fonts.py` 重铸一次即可
|
|
160
|
+
- **每轮调整后重跑第 3.5 步零侵权核查**——防止调整过程引入新字体污染
|
|
161
|
+
|
|
162
|
+
**轮次控制**:
|
|
163
|
+
- 至多 3 轮调整;仍不满意时请用户给出具体参照(参考页面/颜色值/样式截图),避免盲目迭代
|
|
164
|
+
|
|
165
|
+
**截图后确认(确认二)**:
|
|
166
|
+
- 请用户抽查封面 + 最长章节两张图
|
|
167
|
+
- 发现方框缺字(字体问题)、截断、宽度不一致 → 定位修复后**只重截该章节**,不全部重来
|
|
168
|
+
- 用户点头 → 完工,收尾汇报交付物清单
|
|
169
|
+
|
|
170
|
+
### 5. Capture screenshots (per chapter)
|
|
171
|
+
|
|
172
|
+
- 目标目录起服务:`python3 -m http.server 8931`(后台运行),再 RunPreview
|
|
173
|
+
- 派发 **一个** Browser 子代理,明确指令如下:
|
|
174
|
+
- 打开页面,**先做字体自检**:`document.fonts.check('16px Roboto')` 与 `document.fonts.check('16px "Source Han Sans SC"')` 必须为 true;再用测量法复核——把一段中文与一段英文渲染到 canvas,分别用目标字体与苹方/Arial 测量宽度,实际渲染宽度与目标字体一致才继续截图;不一致则停止并报告(说明用户系统缺思源黑体,需先安装)
|
|
175
|
+
- 截图对象:封面 `.hero` + `.wrap` 内每个 `section`(引言 + 各章 + 写在最后 + 作者),一章节一张
|
|
176
|
+
- **统一宽度**:JS 注入 `.hero` → `width:730px;margin:0 auto;padding:112px 16px 104px;box-sizing:border-box`;每个 section → `padding:72px 16px 24px`;DPR=2 时所有图宽度一致(1460px)
|
|
177
|
+
- 元素级截图,截前先 `scrollIntoView`;四周 16px 内边距保证 box-shadow 阴影完整显示
|
|
178
|
+
- 命名与顺序:`C00-封面.png`、`C00-引言.png`、`C01-<章节短名>.png` … `C13-作者介绍.png`,保存到 `<目标目录>/文章截图/章节截图/`
|
|
179
|
+
- 若子代理报浏览器窗口不可见(`NATIVE_BROWSER_VIEWPORT_UNAVAILABLE`),请用户把浏览器窗口置前,然后重新派发子代理;不要无限重试
|
|
180
|
+
|
|
181
|
+
- **窗口不可见时的 headless 兜底**(三轮置前失败后直接走此路,无需可见窗口):
|
|
182
|
+
- 工具链:`pip3 install --user playwright`;启动用系统 Chrome:`p.chromium.launch(channel="chrome", headless=True)`(无需 playwright install 下载浏览器)
|
|
183
|
+
- 脚本要点:`new_page(device_scale_factor=2)`(Retina 2x)→ `goto(file://或 http://)` → `wait_for_load_state("networkidle")` → 等 `document.fonts.ready` → 字体自检双 true → `page.evaluate(JS注入样式)` → 逐元素 `el.scroll_into_view_if_needed()` + `el.screenshot(path=…)`
|
|
184
|
+
- 注入样式与 Browser 子代理完全一致(宽 730px + 四边 16px padding + box-sizing:border-box),产出同规格 1460px;file:// 协议下 woff2 相对路径可正常加载
|
|
185
|
+
- 完成后 `sips -g pixelWidth` 批量验证宽度,Read 抽 2 帧自查
|
|
186
|
+
- 截图完成后**抽查验证**:Read 查看封面 + 最长章节两张图,确认无截断、宽度一致(1460px ±2)、边距完整;同时**抽检字体**:放大细看中文笔画是否锐利、有无豆腐块(□)或缺字——字体栈已无兜底,出现缺字即说明系统缺思源黑体,必须停下装字体后重截
|
|
187
|
+
- 端口占用:`python3 -m http.server 8931` 报 Address already in use 时换 8932/8933 等端口
|
|
188
|
+
|
|
189
|
+
### 6. 只截图 / 只美化已有 HTML(快捷分支)
|
|
190
|
+
|
|
191
|
+
适用:用户直接给一个已存在的 .html 文件,要求截图或美化。共同第一步是骨架侦察。
|
|
192
|
+
|
|
193
|
+
**6.1 骨架侦察**
|
|
194
|
+
|
|
195
|
+
- Read 该 HTML,认出三样:封面容器、正文容器、章节容器。自家设计系统骨架为 `.hero` + `.wrap` 内平铺 `section`
|
|
196
|
+
- **自家骨架** → 直接进 6.3 截图,或按用户要求进 6.2 改样式
|
|
197
|
+
- **陌生骨架**:
|
|
198
|
+
- 结构清晰可映射(有明显封面区、章节分块、内容宽度集中)→ 记下封面/章节的选择器清单,把第 5 步注入规则换成对应选择器(封面压 730px 宽居中、每章节加 `padding:72px 16px 24px`;DPR=2 时全图 1460px 不变)
|
|
199
|
+
- 无章节概念 / 版面混乱 → 明示用户:直接截会宽窄不一,建议先走 6.2 把版面收拢成标准骨架
|
|
200
|
+
- 无论哪种骨架,**截图前都先跑第 3.5 步零侵权核查**——外来 HTML 常带苹方/雅黑/sans-serif 兜底,任何命中必须清零;缺字体则回到第 2 步字体准备
|
|
201
|
+
|
|
202
|
+
**6.2 只美化**
|
|
203
|
+
|
|
204
|
+
- 等价于「更新模式」的「仅改样式保留内容」:只动 CSS(配色/间距/字号/组件样式),不动正文;若外来 HTML 缺章节骨架,可顺手改造成自家骨架(文字不动)
|
|
205
|
+
- **每轮调整后重跑第 3.5 步核查**,防调整引入新字体污染
|
|
206
|
+
- 第 4.5 步双确认闭环照跑:美化完先 RunPreview 问满意,点头才进入截图;至多 3 轮
|
|
207
|
+
- 美化定稿后用户要截图 → 转 6.3;单文件版如需要,用 inline_fonts.py 重铸
|
|
208
|
+
|
|
209
|
+
**6.3 只截图**
|
|
210
|
+
|
|
211
|
+
- 复用第 5 步全部规格(字体自检、统一宽度 1460px、四周 16px 余白、C00 命名顺序、抽查验证),仅把注入选择器换成 6.1 侦察所得
|
|
212
|
+
- 章节命名:按侦察到的章节顺序 `C00-封面` → `C00-引言` → `C01…` 依次编号
|
|
213
|
+
- 若子代理报窗口不可见,请用户把浏览器置前再重派,不无限重试
|
|
214
|
+
|
|
215
|
+
## 更新模式(目标目录已有同名 HTML 时)
|
|
216
|
+
|
|
217
|
+
先检测目标目录是否已有产物;存在时用 AskUserQuestion 询问(本节仅指目标目录已有本 Skill 产物时的三选一;对任意已有 HTML 的直接操作统一走第 6 步快捷分支):
|
|
218
|
+
「覆盖重新生成 / 只重新截图 / 仅改样式保留内容」。改样式类小调整直接 SearchReplace 工作区文件后重新 `cp` + 重截,不要从头重建。
|
|
219
|
+
|
|
220
|
+
## Output conventions
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
<目标目录>/
|
|
224
|
+
├── <标题>.html # 标准版(依赖 assets/fonts)
|
|
225
|
+
├── <标题>-单文件版.html # 字体全内嵌,双击即开
|
|
226
|
+
├── assets/fonts/roboto-latin-{400,500,700,900}-normal.woff2
|
|
227
|
+
└── 文章截图/章节截图/
|
|
228
|
+
├── C00-封面.png C00-引言.png C01-*.png … C13-作者介绍.png
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Pitfalls
|
|
232
|
+
|
|
233
|
+
1. **Write 沙盒限制**:工作区外无法直接 Write → 写工作区 `outputs/` 再 `cp` 到目标目录
|
|
234
|
+
2. **图表必须重绘**:HTML/CSS 矢量重绘在 Retina 截图中保持锐利;嵌原图必糊
|
|
235
|
+
3. **大文件追加**:SearchReplace 锚点必须是当前文件末尾唯一片段(`</section>\n</div>\n</body>\n</html>`),禁止整文件重写
|
|
236
|
+
4. **子代理窗口不可见**:元素截图会失败——让用户把浏览器置前后重试一次
|
|
237
|
+
5. **宽度一致性**:不注入固定宽度时封面是全宽(视口宽)、章节是内容宽(698px),宽窄不一;必须按第 5 步注入样式后再截
|
|
238
|
+
6. **字体栈严禁兜底**:--sans/--mono 只许 Roboto + 思源黑体(含 Noto/思源黑体别名),加苹方/雅黑兜底会导致字体缺失时静默回退、截图抽检无法发现
|
|
239
|
+
7. **章节截图顺序**:`C00-封面` → `C00-引言` → `C01…C13`,按序拼接即整篇长图
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Design System Reference
|
|
2
|
+
|
|
3
|
+
本文件提供文章 HTML 的设计系统:CSS 变量 + 组件类名 + 关键样式片段。执行时按需复制到 `<style>` 中,并根据文章内容裁剪不需要的组件。
|
|
4
|
+
|
|
5
|
+
## 0. 风格菜单(构建前按文章气质选一款)
|
|
6
|
+
|
|
7
|
+
六款版式范式,每款给适用气质与关键参数。选定后其余章节的组件按需裁剪。字体白名单锁死为 Roboto + 思源黑体,任何风格都不许引入其他字体。
|
|
8
|
+
|
|
9
|
+
| 风格 | 适用气质 | 关键参数 |
|
|
10
|
+
|:---|:---|:---|
|
|
11
|
+
| **A. 暗色封面长文风**(默认款) | 科技文、产品文、深度技术长文 | 深色渐变 hero + 浅灰 `--bg:#f6f8fb` 正文 + 彩色圆角组件(第 2-5 节全套)。主题色随文章气质定:科技蓝 `#2563eb`、暖棕金 `#b45309/#6b4a2b`、墨绿 `#0f766e` 等,改 `:root` 与 hero 渐变两处即可 |
|
|
12
|
+
| **B. 文艺排版风** | 散文、人物稿、随笔、书评 | 字体仍为思源黑体(**不改宋体**);背景米白 `#faf7f1`;封面极简:居中大标题 + 细线 + 作者名,无深色块;行距 1.9、字号 17px、栏宽 680px;`p:first-of-type::first-letter{font-size:3em;float:left}` 首字下沉;引用用居中大字号灰字,分割用 `1px solid #e8e0d0` 细线;禁彩色卡片与重阴影——文艺感全靠排版营造 |
|
|
13
|
+
| **C. 极简白** | 干货教程、方法论、SOP | `--bg:#ffffff`;封面白底大黑标题 + 蓝字点缀;组件只用白卡细边框 `1px solid var(--line)`,单色点缀 `#2563eb`,不用多彩色系统;行距 1.8 |
|
|
14
|
+
| **D. 终端极客风** | 硬核技术文、命令行主题 | 全页暗色 `--bg:#0d1117`,正文 `#c9d1d9`,强调绿 `#7ee787`/蓝 `#58a6ff`;封面命令行提示符风格(`$` 前缀标题 + ASCII 装饰);组件边框 `#30363d`、圆角 ≤8、阴影弱化;代码块为主导视觉;`--mono` 仍为思源黑体(禁等宽商业字体) |
|
|
15
|
+
| **E. 卡片流** | 清单体、科普、碎片知识 | `--bg:#f5f6f8`;内容全卡片化(白卡圆角 16 + `--shadow-sm` + emoji 图标领衔);封面渐变卡 + 大 emoji;段间距拉大 |
|
|
16
|
+
| **F. 报纸分栏风** | 深度报道、行业观察 | 白底;正文双栏 `column-count:2;column-gap:40px`(小屏单栏);封面特大黑标题 + 摘要 + 细双线;小标题黑体 + 上下细线;表格跨栏 `column-span:all` |
|
|
17
|
+
|
|
18
|
+
选择原则:科技/产品长文默认 A;文艺散文 B;教程干货 C;硬核技术 D;科普清单 E;报道评论 F。拿不准时用 AskUserQuestion 让用户挑(每款附一句话气质描述)。
|
|
19
|
+
|
|
20
|
+
## 1. 字体与设计变量(必用)
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
@font-face { font-family:'Roboto'; font-style:normal; font-weight:400; font-display:swap; src:url('assets/fonts/roboto-latin-400-normal.woff2') format('woff2'); }
|
|
24
|
+
@font-face { font-family:'Roboto'; font-style:normal; font-weight:500; font-display:swap; src:url('assets/fonts/roboto-latin-500-normal.woff2') format('woff2'); }
|
|
25
|
+
@font-face { font-family:'Roboto'; font-style:normal; font-weight:700; font-display:swap; src:url('assets/fonts/roboto-latin-700-normal.woff2') format('woff2'); }
|
|
26
|
+
@font-face { font-family:'Roboto'; font-style:normal; font-weight:900; font-display:swap; src:url('assets/fonts/roboto-latin-900-normal.woff2') format('woff2'); }
|
|
27
|
+
|
|
28
|
+
:root{
|
|
29
|
+
--blue:#2563eb; --blue-bg:#ebf0ff; --blue-line:#a1bdfa;
|
|
30
|
+
--red:#e24b4a; --red-bg:#fcebeb; --red-line:#f09595; --red-dark:#a32d2d;
|
|
31
|
+
--green:#16a34a; --green-bg:#ecfdf5; --green-line:#86efac; --green-dark:#15803d;
|
|
32
|
+
--purple:#7c3aed; --purple-bg:#f5f0ff; --purple-line:#c4b5fd; --purple-dark:#6d28d9;
|
|
33
|
+
--teal:#0d9488; --teal-bg:#f0fdfa; --teal-line:#5eead4;
|
|
34
|
+
--orange:#ea580c; --orange-bg:#fff7ed; --orange-line:#fdba74;
|
|
35
|
+
--ink:#1f2937; --ink-2:#4b5563; --ink-3:#6b7280; --ink-4:#9ca3af;
|
|
36
|
+
--bg:#f6f8fb; --card:#ffffff; --line:#e5e7eb;
|
|
37
|
+
--shadow-sm:0 1px 3px rgba(17,24,39,.06),0 1px 2px rgba(17,24,39,.04);
|
|
38
|
+
--shadow-md:0 4px 12px rgba(17,24,39,.08),0 2px 4px rgba(17,24,39,.04);
|
|
39
|
+
--shadow-lg:0 12px 32px rgba(17,24,39,.12),0 4px 8px rgba(17,24,39,.06);
|
|
40
|
+
--sans:'Roboto','Source Han Sans SC';
|
|
41
|
+
--mono:'Source Han Sans SC';
|
|
42
|
+
}
|
|
43
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
44
|
+
body{font-family:var(--sans);background:var(--bg);color:var(--ink);line-height:1.75;font-size:16px}
|
|
45
|
+
.wrap{max-width:880px;margin:0 auto;padding:0 28px}
|
|
46
|
+
section{padding:56px 0 8px}
|
|
47
|
+
h1,h2,h3,h4{line-height:1.35;font-weight:700}
|
|
48
|
+
p{margin:0 0 1.1em}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
> 字体纯化原则(绝对纯粹):`--sans` 仅 `'Roboto','Source Han Sans SC'`;`--mono` 仅 `'Source Han Sans SC'`。任何别名(Noto Sans SC、思源黑体)与兜底(苹方/雅黑/系统字体/sans-serif)一律禁止——未装思源黑体时宁可缺字,不可静默回退,截图抽检即能发现。SVG 内 font-family 同样仅两字体。
|
|
52
|
+
> 纯白背景版:把 `--bg:#f6f8fb` 改为 `--bg:#ffffff`(深色 hero/ending/term 组件不受影响)。
|
|
53
|
+
|
|
54
|
+
## 2. 封面 hero(深色渐变 + 流程节点)
|
|
55
|
+
|
|
56
|
+
```css
|
|
57
|
+
.hero{position:relative;overflow:hidden;color:#fff;padding:96px 0 88px;text-align:center;
|
|
58
|
+
background:radial-gradient(1200px 600px at 15% -10%,rgba(96,165,250,.35),transparent 55%),
|
|
59
|
+
radial-gradient(1000px 500px at 110% 30%,rgba(167,139,250,.30),transparent 55%),
|
|
60
|
+
radial-gradient(900px 700px at 50% 120%,rgba(45,212,191,.22),transparent 60%),
|
|
61
|
+
linear-gradient(160deg,#0b1220 0%,#0e1a33 45%,#131c3a 100%)}
|
|
62
|
+
.hero::before{content:"";position:absolute;inset:0;background-image:
|
|
63
|
+
linear-gradient(rgba(148,163,184,.05) 1px,transparent 1px),
|
|
64
|
+
linear-gradient(90deg,rgba(148,163,184,.05) 1px,transparent 1px);
|
|
65
|
+
background-size:44px 44px;pointer-events:none}
|
|
66
|
+
.hero .inner{position:relative;z-index:2}
|
|
67
|
+
.hero .kicker{display:inline-flex;align-items:center;gap:8px;font-size:13px;letter-spacing:.14em;color:#93c5fd;
|
|
68
|
+
background:rgba(59,130,246,.14);border:1px solid rgba(96,165,250,.35);padding:7px 18px;border-radius:999px;margin-bottom:30px}
|
|
69
|
+
.hero h1{font-size:44px;font-weight:900;margin-bottom:18px}
|
|
70
|
+
.hero h1 .grad{background:linear-gradient(90deg,#7dd3fc,#a5b4fc,#c4b5fd);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
|
71
|
+
.hero .sub{font-size:19px;color:#cbd5e1;margin-bottom:12px}
|
|
72
|
+
.hero .flow{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:44px;flex-wrap:wrap}
|
|
73
|
+
.hero .flow .node{display:flex;align-items:center;gap:8px;background:rgba(30,41,59,.7);border:1px solid rgba(148,163,184,.3);
|
|
74
|
+
padding:9px 18px;border-radius:12px;font-size:14px;color:#e2e8f0}
|
|
75
|
+
.hero .flow .node .n{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
|
|
76
|
+
font-size:12px;font-weight:700;color:#fff;background:linear-gradient(135deg,#3b82f6,#8b5cf6)}
|
|
77
|
+
.hero .flow .arrow{color:#64748b;font-size:18px}
|
|
78
|
+
.hero .tagline{margin-top:34px;font-size:15px;color:#94a3b8;letter-spacing:.08em}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 3. 章节标题 + 通用卡片
|
|
82
|
+
|
|
83
|
+
```css
|
|
84
|
+
.sec-head{display:flex;align-items:baseline;gap:14px;margin:0 0 26px;padding-bottom:14px;border-bottom:1px solid var(--line)}
|
|
85
|
+
.sec-head .no{font-weight:900;font-size:30px;color:var(--blue);letter-spacing:-.02em;min-width:52px}
|
|
86
|
+
.sec-head h2{font-size:26px}
|
|
87
|
+
.sec-head .en{font-size:12px;letter-spacing:.12em;color:var(--ink-4);text-transform:uppercase;margin-left:auto}
|
|
88
|
+
.lead{font-size:17px;color:var(--ink-2);margin-bottom:28px}
|
|
89
|
+
.h3{font-size:19px;margin:34px 0 14px;display:flex;align-items:center;gap:10px}
|
|
90
|
+
.h3::before{content:"";width:4px;height:18px;border-radius:2px;background:var(--blue)}
|
|
91
|
+
.card{background:var(--card);border-radius:16px;box-shadow:var(--shadow-sm);border:1px solid var(--line)}
|
|
92
|
+
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:18px}
|
|
93
|
+
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
|
|
94
|
+
@media(max-width:720px){.grid-2,.grid-3{grid-template-columns:1fr}}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 4. 图表组件映射表
|
|
98
|
+
|
|
99
|
+
| 源文档图表类型 | 使用组件(类名) | 关键样式要点 |
|
|
100
|
+
|:---|:---|:---|
|
|
101
|
+
| 左右对比(问题 vs 方案) | `.vs-panel`(bad/good 两栏) | 红/绿渐变底、虚线分隔、圆点前缀 |
|
|
102
|
+
| 升级/演变图(A→B) | `.upgrade`(vibe/spec 双栏 + mid 箭头) | 底部渐变色带 band、✓/✕ 前缀 |
|
|
103
|
+
| 强调数据/警示 | `.callout`(大数字 + 说明) | 左边框 5px 主题色 |
|
|
104
|
+
| 原则/铁律条目 | `.rules` + `.rule`(编号角标) | hover 上浮 |
|
|
105
|
+
| 数据对比表 | `.tbl-wrap` + `table` | `td{vertical-align:middle}`、Spec 列加蓝底高亮 |
|
|
106
|
+
| 分层架构图 | `.layers` + `.layer`(l1/l2/l3) | 蓝绿紫三层、fdoc 文档卡、sync-label 竖排同步线 |
|
|
107
|
+
| 特性/优势卡片墙 | `.adv` + `.a`(2×3 或 3×3) | 图标色块 ic-b/g/p/o/t/r |
|
|
108
|
+
| 暗色功能面板 | `.dark-panel` + `.ask-card` | 深蓝渐变 + 点阵背景 + 彩色描边卡 |
|
|
109
|
+
| 流程图(多步骤) | `.flowchart` + `.frow` + `.fnode` | 彩色节点 tag、反向行 dashed |
|
|
110
|
+
| 层级递进(1→2→3) | `.modes` + `.mode`(m1/m2/m3) | 圆形数字 badge、箭头注释 |
|
|
111
|
+
| 类型卡片网格 | `.ttypes` + `.tt`(5 列) | mono 类型名 + 文档数角标 |
|
|
112
|
+
| 目录/终端展示 | `.term` / `.dirtree` | 深底 mono、两列注释对齐 |
|
|
113
|
+
| 推荐/不推荐 | `.rec` + `.rc`(good/bad) | ✓/✕ 前缀列表 |
|
|
114
|
+
| 命令安装步骤 | `.cmd-block` | 深底 mono、`<span class="p">` 命令、`.c` 注释 |
|
|
115
|
+
| 对话/聊天记录 | `.chat` + `.msg`(u/a 气泡) | 左右气泡 + who 标签 |
|
|
116
|
+
| 链接/仓库卡片 | `.oss` + `.o` | logo 色块 + mono URL |
|
|
117
|
+
| 结尾升华块 | `.ending` | 深蓝渐变 + 渐变标题 + nospec 大按钮 |
|
|
118
|
+
| 作者介绍 | `.author` | avatar 色块 + role 标签 |
|
|
119
|
+
|
|
120
|
+
## 5. 常用组件样式片段(按需复制)
|
|
121
|
+
|
|
122
|
+
### 对比双卡 .vs-panel
|
|
123
|
+
|
|
124
|
+
```css
|
|
125
|
+
.vs-panel{display:grid;grid-template-columns:1fr 1fr;gap:0;border-radius:18px;overflow:hidden;box-shadow:var(--shadow-md);border:1px solid var(--line);background:#fff}
|
|
126
|
+
.vs-panel .side{padding:28px 30px 24px}
|
|
127
|
+
.vs-panel .side.bad{background:linear-gradient(180deg,#fff 0%,#fff7f5 100%)}
|
|
128
|
+
.vs-panel .side.good{background:linear-gradient(180deg,#fff 0%,#f4fcf7 100%);border-left:1px solid var(--line)}
|
|
129
|
+
.vs-panel h4{font-size:17px;margin-bottom:18px;display:flex;align-items:center;gap:9px}
|
|
130
|
+
.vs-panel .side.bad h4{color:var(--red-dark)}
|
|
131
|
+
.vs-panel .side.good h4{color:var(--green-dark)}
|
|
132
|
+
.vs-panel h4 .ico{width:26px;height:26px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;font-size:13px}
|
|
133
|
+
.vs-panel .bad h4 .ico{background:var(--red-bg);border:1px solid var(--red-line)}
|
|
134
|
+
.vs-panel .good h4 .ico{background:var(--green-bg);border:1px solid var(--green-line)}
|
|
135
|
+
.vs-panel ul{list-style:none}
|
|
136
|
+
.vs-panel li{display:flex;gap:11px;align-items:flex-start;padding:9px 0;border-bottom:1px dashed var(--line);font-size:14.5px;color:var(--ink-2)}
|
|
137
|
+
.vs-panel li:last-child{border-bottom:none}
|
|
138
|
+
.vs-panel li::before{content:"";flex:none;width:7px;height:7px;border-radius:50%;margin-top:8px}
|
|
139
|
+
.vs-panel .bad li::before{background:var(--red)}
|
|
140
|
+
.vs-panel .good li::before{background:var(--green)}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 表格 .tbl-wrap
|
|
144
|
+
|
|
145
|
+
```css
|
|
146
|
+
.tbl-wrap{overflow-x:auto;border-radius:14px;box-shadow:var(--shadow-sm);border:1px solid var(--line);background:#fff}
|
|
147
|
+
table{border-collapse:collapse;width:100%;font-size:14px;min-width:640px}
|
|
148
|
+
th{background:#f0f4fb;color:#334e7e;font-weight:700;text-align:left;padding:12px 16px;border-bottom:2px solid #dbe4f5;white-space:nowrap;font-size:13.5px}
|
|
149
|
+
td{padding:11px 16px;border-bottom:1px solid var(--line);color:var(--ink-2);vertical-align:middle}
|
|
150
|
+
tr:last-child td{border-bottom:none}
|
|
151
|
+
tbody tr:hover{background:#f8fafc}
|
|
152
|
+
td.ok{color:var(--green);text-align:center;font-size:15px}
|
|
153
|
+
td.no{color:#d1d5db;text-align:center}
|
|
154
|
+
td.hl{font-weight:700;color:var(--ink)}
|
|
155
|
+
.tbl-cap{font-size:13px;color:var(--ink-3);margin:10px 0 0;text-align:center}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 分层架构 .layers
|
|
159
|
+
|
|
160
|
+
```css
|
|
161
|
+
.layers{position:relative;padding-right:56px}
|
|
162
|
+
.layer{border-radius:14px;margin-bottom:20px;overflow:hidden;border:1px solid}
|
|
163
|
+
.layer .h{color:#fff;padding:10px 20px;font-size:15px;font-weight:700;display:flex;justify-content:space-between;align-items:center;gap:10px}
|
|
164
|
+
.layer .h .d{font-size:12px;font-weight:400;opacity:.85}
|
|
165
|
+
.layer .body{padding:16px;display:grid;gap:12px}
|
|
166
|
+
.layer.l1{border-color:var(--blue-line);background:var(--blue-bg)}
|
|
167
|
+
.layer.l1 .h{background:linear-gradient(90deg,#1d4ed8,#2563eb)}
|
|
168
|
+
.layer.l2{border-color:#6ee7b7;background:var(--green-bg)}
|
|
169
|
+
.layer.l2 .h{background:linear-gradient(90deg,#15803d,#16a34a)}
|
|
170
|
+
.layer.l3{border-color:var(--purple-line);background:var(--purple-bg)}
|
|
171
|
+
.layer.l3 .h{background:linear-gradient(90deg,#6d28d9,#7c3aed)}
|
|
172
|
+
.layer.l1 .body{grid-template-columns:repeat(4,1fr)}
|
|
173
|
+
.layer.l2 .body{grid-template-columns:repeat(3,1fr)}
|
|
174
|
+
.layer.l3 .body{grid-template-columns:repeat(3,1fr)}
|
|
175
|
+
.fdoc{background:#fff;border-radius:10px;padding:12px 10px;text-align:center;box-shadow:var(--shadow-sm)}
|
|
176
|
+
.fdoc .f{font-size:13px;font-weight:700;font-family:var(--mono)}
|
|
177
|
+
.fdoc .d{font-size:11.5px;margin-top:2px}
|
|
178
|
+
.layer.l1 .fdoc{border:1px solid var(--blue-line)}.layer.l1 .fdoc .f{color:#1e4ad6}
|
|
179
|
+
.layer.l2 .fdoc{border:1px solid var(--green-line)}.layer.l2 .fdoc .f{color:#15803d}
|
|
180
|
+
.layer.l3 .fdoc{border:1px solid var(--purple-line)}.layer.l3 .fdoc .f{color:#6d28d9}
|
|
181
|
+
.fdoc.sync{border-style:dashed;background:#ede9fe}
|
|
182
|
+
.layer-arrow{display:flex;justify-content:center;color:var(--ink-3);font-size:18px;margin:-6px 0 14px}
|
|
183
|
+
.sync-label{position:absolute;right:0;top:0;bottom:0;width:52px;display:flex;align-items:center;justify-content:center}
|
|
184
|
+
.sync-label .vline{border-left:2px dashed var(--purple-line);height:88%;display:flex;align-items:center}
|
|
185
|
+
.sync-label span{writing-mode:vertical-rl;font-size:12px;color:#8b5cf6;letter-spacing:.3em;background:var(--bg);padding:8px 0}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 升级图 .upgrade / 铁律 .rules / 警示 .callout
|
|
189
|
+
|
|
190
|
+
```css
|
|
191
|
+
.upgrade{display:grid;grid-template-columns:1fr 64px 1fr;gap:0;align-items:stretch}
|
|
192
|
+
.upgrade .col{border-radius:16px;padding:24px 24px 0;position:relative;padding-bottom:52px}
|
|
193
|
+
.upgrade .col.vibe{background:var(--red-bg);border:1.5px solid var(--red-line)}
|
|
194
|
+
.upgrade .col.spec{background:var(--green-bg);border:1.5px solid var(--green-line)}
|
|
195
|
+
.upgrade .col .ttl{font-size:19px;font-weight:900;margin-bottom:2px}
|
|
196
|
+
.upgrade .col.vibe .ttl{color:var(--red-dark)}
|
|
197
|
+
.upgrade .col.spec .ttl{color:var(--green-dark)}
|
|
198
|
+
.upgrade .col .st{font-size:13px;margin-bottom:16px}
|
|
199
|
+
.upgrade .col .chip{background:#fff;border-radius:10px;padding:11px 14px;font-size:14px;text-align:center;margin-bottom:16px;box-shadow:var(--shadow-sm)}
|
|
200
|
+
.upgrade .col ul{list-style:none;margin:0 0 18px}
|
|
201
|
+
.upgrade .col li{font-size:13.5px;padding:6.5px 0 6.5px 22px;position:relative;color:var(--ink-2)}
|
|
202
|
+
.upgrade .col.vibe li::before{content:"✕";position:absolute;left:0;top:7px;color:var(--red);font-weight:700;font-size:12px}
|
|
203
|
+
.upgrade .col.spec li::before{content:"✓";position:absolute;left:0;top:7px;color:var(--green);font-weight:900;font-size:12px}
|
|
204
|
+
.upgrade .col .band{position:absolute;left:0;right:0;bottom:0;border-radius:0 0 14px 14px;padding:12px;text-align:center;color:#fff;font-size:14.5px;font-weight:700}
|
|
205
|
+
.upgrade .col.vibe .band{background:linear-gradient(90deg,#dc2626,#e24b4a)}
|
|
206
|
+
.upgrade .col.spec .band{background:linear-gradient(90deg,#16a34a,#22c55e)}
|
|
207
|
+
.upgrade .mid{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px}
|
|
208
|
+
.upgrade .mid .arrow{width:40px;height:40px;border-radius:50%;background:#fff;border:1.5px solid var(--line);display:flex;align-items:center;justify-content:center;color:var(--ink-3);font-size:17px;box-shadow:var(--shadow-sm)}
|
|
209
|
+
.upgrade .mid span{font-size:12px;color:var(--ink-3);writing-mode:vertical-lr;letter-spacing:.2em}
|
|
210
|
+
|
|
211
|
+
.callout{display:flex;gap:16px;align-items:center;background:linear-gradient(90deg,#fef2f2,#fff);border:1px solid var(--red-line);border-left:5px solid var(--red);border-radius:14px;padding:20px 26px;margin:26px 0;box-shadow:var(--shadow-sm)}
|
|
212
|
+
.callout .big{font-size:34px;font-weight:900;color:var(--red);white-space:nowrap}
|
|
213
|
+
.callout p{margin:0;font-size:15px;color:var(--ink-2)}
|
|
214
|
+
.callout p b{color:var(--red-dark)}
|
|
215
|
+
|
|
216
|
+
.rules{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
|
|
217
|
+
.rule{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:24px 22px;position:relative;box-shadow:var(--shadow-sm);transition:transform .2s}
|
|
218
|
+
.rule:hover{transform:translateY(-3px);box-shadow:var(--shadow-md)}
|
|
219
|
+
.rule .num{position:absolute;top:16px;right:18px;font-size:34px;font-weight:900;color:var(--line)}
|
|
220
|
+
.rule .en{font-size:16px;font-weight:900;color:var(--blue);margin-bottom:8px}
|
|
221
|
+
.rule p{font-size:13.5px;color:var(--ink-2);margin:0;line-height:1.7}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 暗色面板 .dark-panel / 流程图 / 模式分级
|
|
225
|
+
|
|
226
|
+
```css
|
|
227
|
+
.dark-panel{background:linear-gradient(160deg,#0f172a,#111c36);border-radius:18px;padding:34px 30px;color:#e2e8f0;box-shadow:var(--shadow-lg);position:relative;overflow:hidden}
|
|
228
|
+
.dark-panel::before{content:"";position:absolute;inset:0;background-image:radial-gradient(rgba(96,165,250,.09) 1px,transparent 1px);background-size:26px 26px;pointer-events:none}
|
|
229
|
+
.dark-panel .dp-title{text-align:center;margin-bottom:6px;font-size:21px;font-weight:700;color:#f1f5f9}
|
|
230
|
+
.dark-panel .dp-sub{text-align:center;font-size:13.5px;color:#94a3b8;margin-bottom:28px}
|
|
231
|
+
.ask-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;position:relative;z-index:1}
|
|
232
|
+
.ask-card{background:rgba(30,41,59,.72);border:1px solid;border-radius:14px;padding:16px 16px 14px}
|
|
233
|
+
.ask-card .ac-t{font-weight:700;font-size:15px;margin-bottom:9px;display:flex;align-items:center;gap:8px}
|
|
234
|
+
.ask-card .ac-t .dot{width:8px;height:8px;border-radius:50%}
|
|
235
|
+
.ask-card .q{font-size:12.5px;color:#94a3b8;margin-bottom:2px}
|
|
236
|
+
.ask-card .q code{color:#cbd5e1;background:rgba(148,163,184,.14);padding:1px 6px;border-radius:5px;font-family:var(--mono);font-size:11.5px}
|
|
237
|
+
.ask-card .feat{font-size:12px;color:#64748b;margin:8px 0 10px}
|
|
238
|
+
.ask-card .btn{display:inline-block;font-size:12px;font-weight:700;color:#fff;padding:4px 12px;border-radius:999px}
|
|
239
|
+
.ask-c1{border-color:rgba(45,212,191,.4)}.ask-c1 .ac-t{color:#5eead4}.ask-c1 .dot{background:#2dd4bf}.ask-c1 .btn{background:linear-gradient(90deg,#0d9488,#14b8a6)}
|
|
240
|
+
.ask-c2{border-color:rgba(251,146,60,.4)}.ask-c2 .ac-t{color:#fdba74}.ask-c2 .dot{background:#fb923c}.ask-c2 .btn{background:linear-gradient(90deg,#c2410c,#ea580c)}
|
|
241
|
+
.ask-c3{border-color:rgba(96,165,250,.4)}.ask-c3 .ac-t{color:#93c5fd}.ask-c3 .dot{background:#60a5fa}.ask-c3 .btn{background:linear-gradient(90deg,#1d4ed8,#3b82f6)}
|
|
242
|
+
.ask-c4{border-color:rgba(167,139,250,.4)}.ask-c4 .ac-t{color:#c4b5fd}.ask-c4 .dot{background:#a78bfa}.ask-c4 .btn{background:linear-gradient(90deg,#6d28d9,#8b5cf6)}
|
|
243
|
+
|
|
244
|
+
.flowchart{background:#fff;border:1px solid var(--line);border-radius:16px;padding:26px;box-shadow:var(--shadow-sm)}
|
|
245
|
+
.flowchart .fc-title{text-align:center;font-weight:700;font-size:17px;margin-bottom:20px}
|
|
246
|
+
.frow{display:flex;align-items:center;gap:10px;justify-content:center;flex-wrap:wrap;margin-bottom:8px}
|
|
247
|
+
.fnode{padding:9px 15px;border-radius:10px;font-size:13px;font-weight:500;border:1.5px solid;white-space:nowrap}
|
|
248
|
+
.fnode.tag{font-weight:700}
|
|
249
|
+
.farr{color:var(--ink-3);font-size:15px}
|
|
250
|
+
.frow.rev .fnode{border-style:dashed}
|
|
251
|
+
.f-tag-f{color:#1d4ed8;border-color:#93c5fd;background:var(--blue-bg)}
|
|
252
|
+
.f-node-b{color:#0369a1;border-color:#7dd3fc;background:#f0f9ff}
|
|
253
|
+
.f-node-p{color:#6d28d9;border-color:var(--purple-line);background:var(--purple-bg)}
|
|
254
|
+
.f-node-g{color:#15803d;border-color:#86efac;background:var(--green-bg)}
|
|
255
|
+
.f-node-y{color:#b45309;border-color:#fcd34d;background:#fefce8}
|
|
256
|
+
.f-node-r{color:#b91c1c;border-color:#fca5a5;background:var(--red-bg)}
|
|
257
|
+
.flow-principle{margin-top:18px;background:linear-gradient(90deg,#eff6ff,#eef2ff);border:1px solid #bfdbfe;border-radius:10px;padding:11px 16px;text-align:center;font-size:13.5px;color:#1e3a8a;font-weight:500}
|
|
258
|
+
|
|
259
|
+
.modes{display:flex;flex-direction:column;gap:0;max-width:680px;margin:0 auto}
|
|
260
|
+
.mode{border-radius:14px;padding:16px 22px 16px 56px;position:relative;border:1px solid;box-shadow:var(--shadow-sm)}
|
|
261
|
+
.mode .badge{position:absolute;left:16px;top:50%;transform:translateY(-50%);width:28px;height:28px;border-radius:50%;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px}
|
|
262
|
+
.mode .mt{font-weight:700;font-size:15.5px;display:flex;align-items:center;justify-content:space-between;gap:12px}
|
|
263
|
+
.mode .mt .lbl{font-size:12px;font-weight:700;color:#fff;padding:3px 14px;border-radius:999px;white-space:nowrap}
|
|
264
|
+
.mode .md{font-size:13px;margin-top:4px}
|
|
265
|
+
.mode.m1{background:var(--blue-bg);border-color:var(--blue-line)}.mode.m1 .badge{background:var(--blue)}.mode.m1 .mt{color:#1e4ad6}
|
|
266
|
+
.mode.m2{background:var(--green-bg);border-color:var(--green-line)}.mode.m2 .badge{background:var(--green)}.mode.m2 .mt{color:var(--green-dark)}
|
|
267
|
+
.mode.m3{background:var(--purple-bg);border-color:var(--purple-line)}.mode.m3 .badge{background:var(--purple)}.mode.m3 .mt{color:var(--purple-dark)}
|
|
268
|
+
.mode-arr{display:flex;align-items:center;justify-content:center;gap:10px;color:var(--ink-4);font-size:11.5px;padding:9px 0}
|
|
269
|
+
.mode-arr::before,.mode-arr::after{content:"↓";font-size:14px}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### 任务卡片 / 目录树 / 推荐 / 命令 / 对话 / 开源 / 结尾 / 作者
|
|
273
|
+
|
|
274
|
+
```css
|
|
275
|
+
.ttypes{display:grid;grid-template-columns:repeat(5,1fr);gap:12px}
|
|
276
|
+
.tt{background:#fff;border:1px solid var(--line);border-radius:12px;padding:14px 12px;box-shadow:var(--shadow-sm)}
|
|
277
|
+
.tt .ttn{font-family:var(--mono);font-weight:700;font-size:13px;color:var(--blue);margin-bottom:5px}
|
|
278
|
+
.tt .tcount{font-size:10.5px;color:var(--ink-4);float:right;font-family:var(--sans)}
|
|
279
|
+
.tt p{font-size:12px;color:var(--ink-3);margin:0;line-height:1.6}
|
|
280
|
+
|
|
281
|
+
.dirtree{background:#0f172a;border-radius:14px;padding:22px 28px;font-family:var(--mono);font-size:13.5px;line-height:2.1;color:#cbd5e1;box-shadow:var(--shadow-md);overflow-x:auto}
|
|
282
|
+
.dt-row{display:grid;grid-template-columns:minmax(320px,1.35fr) 1fr;gap:20px}
|
|
283
|
+
.dt-row .dt-cmt{color:#64748b;font-family:var(--sans);font-size:12.5px}
|
|
284
|
+
.dt-row .dir{color:#7dd3fc;font-weight:700}
|
|
285
|
+
.dt-row .file{color:#e2e8f0}
|
|
286
|
+
.dt-row.root .dir{color:#f472b6}
|
|
287
|
+
.dt-ind1{padding-left:24px}
|
|
288
|
+
.dt-ind2{padding-left:48px}
|
|
289
|
+
|
|
290
|
+
.rec{display:grid;grid-template-columns:1fr 1fr;gap:18px}
|
|
291
|
+
.rec .rc{border-radius:16px;overflow:hidden;border:1px solid;box-shadow:var(--shadow-sm);background:#fff}
|
|
292
|
+
.rec .rc .rh{padding:13px 22px;color:#fff;font-weight:700;font-size:16px}
|
|
293
|
+
.rec .rc.good{border-color:var(--green-line)}.rec .rc.good .rh{background:linear-gradient(90deg,#15803d,#16a34a)}
|
|
294
|
+
.rec .rc.bad{border-color:var(--red-line)}.rec .rc.bad .rh{background:linear-gradient(90deg,#dc2626,#e24b4a)}
|
|
295
|
+
.rec .rc ul{list-style:none;padding:14px 22px 18px}
|
|
296
|
+
.rec .rc li{font-size:14px;color:var(--ink-2);padding:8px 0 8px 22px;position:relative;border-bottom:1px dashed var(--line)}
|
|
297
|
+
.rec .rc li:last-child{border-bottom:none}
|
|
298
|
+
.rec .good li::before{content:"✓";position:absolute;left:0;top:8px;color:var(--green);font-weight:900;font-size:13px}
|
|
299
|
+
.rec .bad li::before{content:"✕";position:absolute;left:0;top:8px;color:var(--red);font-weight:700;font-size:13px}
|
|
300
|
+
|
|
301
|
+
.cmd-block{background:#0f172a;border-radius:14px;padding:18px 24px;font-family:var(--mono);font-size:13.5px;line-height:2.1;color:#e2e8f0;box-shadow:var(--shadow-md);overflow-x:auto}
|
|
302
|
+
.cmd-block .p{color:#f472b6}
|
|
303
|
+
.cmd-block .c{color:#94a3b8}
|
|
304
|
+
.cmd-block .k{color:#7dd3fc}
|
|
305
|
+
|
|
306
|
+
.chat{background:#fff;border:1px solid var(--line);border-radius:16px;padding:24px 26px;box-shadow:var(--shadow-sm)}
|
|
307
|
+
.chat .chat-title{font-weight:700;font-size:16px;margin-bottom:18px}
|
|
308
|
+
.msg{max-width:86%;border-radius:13px;padding:10px 15px;font-size:13.5px;margin-bottom:12px;line-height:1.65}
|
|
309
|
+
.msg .who{font-size:11.5px;font-weight:700;opacity:.65;margin-bottom:2px}
|
|
310
|
+
.msg.u{background:var(--blue-bg);border:1px solid var(--blue-line);margin-left:auto;border-bottom-right-radius:3px;color:#1e3a5f}
|
|
311
|
+
.msg.a{background:#f8fafc;border:1px solid var(--line);border-bottom-left-radius:3px;color:var(--ink-2)}
|
|
312
|
+
|
|
313
|
+
.oss{display:grid;grid-template-columns:1fr 1fr;gap:16px}
|
|
314
|
+
.oss .o{display:flex;align-items:center;gap:14px;background:#fff;border:1px solid var(--line);border-radius:14px;padding:18px 20px;box-shadow:var(--shadow-sm);text-decoration:none}
|
|
315
|
+
.oss .o .logo{width:42px;height:42px;border-radius:11px;display:flex;align-items:center;justify-content:center;font-weight:900;font-size:17px;color:#fff;flex:none}
|
|
316
|
+
.oss .o .nm{font-weight:700;color:var(--ink);font-size:15px}
|
|
317
|
+
.oss .o .url{font-size:12.5px;color:var(--ink-3);font-family:var(--mono)}
|
|
318
|
+
|
|
319
|
+
.ending{background:linear-gradient(160deg,#0f172a,#111c36);border-radius:20px;color:#e2e8f0;padding:46px 40px;text-align:center;box-shadow:var(--shadow-lg);position:relative;overflow:hidden}
|
|
320
|
+
.ending .e-t{position:relative;font-size:26px;font-weight:900;margin-bottom:14px}
|
|
321
|
+
.ending .e-t .grad{background:linear-gradient(90deg,#7dd3fc,#a5b4fc,#c4b5fd);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
|
322
|
+
.ending p{position:relative;color:#94a3b8;font-size:14.5px;max-width:620px;margin:0 auto 22px}
|
|
323
|
+
.ending .nospec{position:relative;display:inline-block;font-size:21px;font-weight:900;letter-spacing:.08em;color:#fff;background:linear-gradient(90deg,#2563eb,#4f46e5);padding:12px 34px;border-radius:12px;box-shadow:0 8px 26px rgba(37,99,235,.5)}
|
|
324
|
+
|
|
325
|
+
.author{display:flex;gap:20px;align-items:flex-start;background:#fff;border:1px solid var(--line);border-radius:16px;padding:24px 28px;box-shadow:var(--shadow-sm);margin-bottom:60px}
|
|
326
|
+
.author .avatar{width:56px;height:56px;border-radius:14px;flex:none;display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:900;color:#fff;background:linear-gradient(135deg,#3b82f6,#8b5cf6)}
|
|
327
|
+
.author .nm{font-weight:700;font-size:16.5px;margin-bottom:6px}
|
|
328
|
+
.author .nm .role{display:inline-block;font-size:11.5px;font-weight:500;color:var(--blue);background:var(--blue-bg);border:1px solid var(--blue-line);padding:2px 10px;border-radius:999px;margin-left:10px;vertical-align:2px}
|
|
329
|
+
.author p{font-size:13.5px;color:var(--ink-2);margin:0;line-height:1.7}
|
|
330
|
+
|
|
331
|
+
.foot{text-align:center;padding:34px 0 44px;color:var(--ink-4);font-size:12.5px}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## 6. HTML 骨架模板
|
|
335
|
+
|
|
336
|
+
```html
|
|
337
|
+
<!DOCTYPE html>
|
|
338
|
+
<html lang="zh-CN">
|
|
339
|
+
<head>
|
|
340
|
+
<meta charset="UTF-8">
|
|
341
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
342
|
+
<title>文章标题</title>
|
|
343
|
+
<style>/* 按需复制上面的变量与组件样式 */</style>
|
|
344
|
+
</head>
|
|
345
|
+
<body>
|
|
346
|
+
<div class="hero">…封面…</div>
|
|
347
|
+
<div class="wrap">
|
|
348
|
+
<section>…引言…</section>
|
|
349
|
+
<section>
|
|
350
|
+
<div class="sec-head"><span class="no">01</span><h2>章节标题</h2><span class="en">Chapter English</span></div>
|
|
351
|
+
…正文与图表组件…
|
|
352
|
+
</section>
|
|
353
|
+
…更多章节…
|
|
354
|
+
<div class="foot">…页脚…</div>
|
|
355
|
+
</div>
|
|
356
|
+
</body>
|
|
357
|
+
</html>
|
|
358
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Download Roboto woff2 weights (400/500/700/900) into a fonts directory.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
python3 download_roboto.py /path/to/assets/fonts
|
|
6
|
+
"""
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import urllib.request
|
|
10
|
+
import ssl
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
ssl._create_default_https_context = ssl._create_unverified_context
|
|
14
|
+
except Exception:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
BASE = 'https://cdn.jsdelivr.net/npm/@fontsource/roboto@5.2.6/files/roboto-latin-{w}-normal.woff2'
|
|
18
|
+
WEIGHTS = ['400', '500', '700', '900']
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main(outdir):
|
|
22
|
+
os.makedirs(outdir, exist_ok=True)
|
|
23
|
+
for w in WEIGHTS:
|
|
24
|
+
dst = os.path.join(outdir, f'roboto-latin-{w}-normal.woff2')
|
|
25
|
+
if os.path.exists(dst) and os.path.getsize(dst) > 10000:
|
|
26
|
+
print('skip (exists):', dst)
|
|
27
|
+
continue
|
|
28
|
+
url = BASE.format(w=w)
|
|
29
|
+
print('downloading:', url)
|
|
30
|
+
urllib.request.urlretrieve(url, dst)
|
|
31
|
+
print('saved:', dst, os.path.getsize(dst), 'bytes')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == '__main__':
|
|
35
|
+
if len(sys.argv) < 2:
|
|
36
|
+
print('Usage: python3 download_roboto.py /path/to/assets/fonts', file=sys.stderr)
|
|
37
|
+
sys.exit(1)
|
|
38
|
+
main(sys.argv[1])
|