文档站的视觉规范¶
这一页收录只在文档站用到的视觉规格:侧栏的指南分类色、Material 主题的界面色、示意图的用色与制作方式,以及社群分享卡的版型。logo、wordmark 与共用色票属于整个社群,写在 anoni.net 的品牌素材。
文档站专用的配色¶
指南分类色(侧栏导览)¶
桌面版左栏「指南」tab 底下的五个分类 chip(概念、工具、场景、进阶、报告)各用一个颜色区隔,文字、图标与框同色。这组是导览界面的识别色,跟品牌素材的结构性次色属于不同层级,两组不要互相挪用。
| Token | 亮色 | 暗色 | 分类 |
|---|---|---|---|
--guide-basics |
#0079a3 |
#4dbfff |
概念,品牌 cyan 深一阶以过 AA 对比 |
--guide-tools |
#2e7d32 |
#66bb6a |
工具,比隐私绿 #4caf50 深 |
--guide-scenarios |
#ad1457 |
#f06292 |
场景 |
--guide-advanced |
#4527a0 |
#b39ddb |
进阶,暗色提亮以过 AA 对比 |
--guide-reports |
#946c00 |
#e0b020 |
报告,琥珀金,刻意离开蓝色系 |
暗色变体在 CSS 里命名为 --guide-*-d。
- 只用在
extra.css的侧栏分类 chip。内容标签、admonition 与三大主题标记用--cat-* - 避开保留的紫
#7b1fa2与紧急红#d32f2f - 五色的亮色在白底、暗色在 slate 底都过 WCAG AA 的 4.5:1。报告原本是蓝色,跟概念的 cyan 在三种色盲模拟下几乎同色(ΔE 最低 2.7),改成琥珀金之后,在红绿色盲下与概念完全分开(ΔE 60 以上)。概念与进阶在第一型色盲下偏近,工具与报告在红绿色盲下偏近,这两组靠图标与文字标签区分,颜色只是辅助线索(WCAG 1.4.1)
- CSS 依位置上色(
:nth-of-type(1)到(5),概念是 1、报告是 5),顺序对应mkdocs.yml指南 tab 底下的分类排序,改排序时要同步调整 CSS
亮色模式的界面色¶
Material 默认的 light blue 当主色时,在白底的对比只有 2.71:1,过不了 WCAG AA。亮色模式把正文链接、accent、header 与面包屑改用 cyan-800 #006d99(白底 5.76:1)。暗色模式维持 Material 默认,因为 cyan-800 在 slate 底只有 2.27:1。内容里的小色标签(首页公告、活动页徽章)也都调到 4.5:1 以上。
示意图用色¶
docs/diagrams/ 的手写 SVG 是被 img 标签引用的独立文件,取不到页面的 CSS 变量,所以下面这一组没有写成 var(--x),是直接抄 hex 进 SVG 的 <style>。class 名称也照抄,三十几张图用的是同一套,换图的人才不用重新认。
语义色,每一格是底色加框色:
| class | 用在哪 | 亮色 底 | 亮色 框 | 暗色 底 | 暗色 框 |
|---|---|---|---|---|---|
.card-c1 |
这一行是重点、主线路径 | #e0f4ff |
#4dbfff |
#0d2b38 |
#4dbfff |
.card-ok |
可以、低成本、风险低 | #e8f5e9 |
#4caf50 |
#17301a |
#4caf50 |
.card-w1 |
有条件、要注意、中等 | #fdf0e4 |
#f8b878 |
#2b1f16 |
#8a5420 |
.card-no |
不行、高成本、风险高 | #fdecea |
#d32f2f |
#35181a |
#e57373 |
.card |
没有好坏判断的一般卡片 | #ffffff |
#cfd8dc |
#23292e |
#4b565e |
.card-n |
弱化、次要、已排除 | #f4f6f7 |
#b0bec5 |
#1c2226 |
#46515a |
分层图用的 cyan 三阶,由浅到深对应由下到上或由外到内:
| class | 层级 | 亮色 底 | 亮色 框 | 暗色 底 | 暗色 框 |
|---|---|---|---|---|---|
.card-c1 |
最浅,第一层 | #e0f4ff |
#4dbfff |
#0d2b38 |
#4dbfff |
.card-c2 |
中间层 | #b3e3ff |
#26b3ff |
#10394b |
#26b3ff |
.card-c3 |
最深,顶层 | #80d1ff |
#0089bf |
#14495f |
#4dbfff |
橙色三阶给警示或成本递增的分层,结构跟 cyan 三阶一样:
| class | 层级 | 亮色 底 | 亮色 框 | 暗色 底 | 暗色 框 |
|---|---|---|---|---|---|
.card-w1 |
最浅 | #fdf0e4 |
#f8b878 |
#2b1f16 |
#8a5420 |
.card-w2 |
中间层 | #f8b878 |
#ef6c00 |
#7d4b19 |
#ff8c1a |
.card-w3 |
最深,饱和底 | #ef6c00 |
#c85a00 |
#ff8c1a |
#ffa64d |
底色越深,能放上去的文字色越少:
| 卡片 | 亮色 | 暗色 |
|---|---|---|
.card、.card-n、.card-c1、.card-w1、.card-ok、.card-no |
.t-main 与 .t-mute 都可以 |
同左 |
.card-c2、.card-c3、.card-w2 |
只用 .t-main |
只用 .t-main |
.card-w3 |
.t-onfill #212121 |
.t-onfill #241708 |
.t-mute 的 #546e7a 在 .card-c2 是 3.95:1、.card-c3 是 3.21:1、.card-w2 是 3.12:1,三个都过不了 AA,所以那三种底只放 .t-main(9.3 到 11.8:1)。
.card-w3 两个模式要往相反方向走。亮色底 #ef6c00 配白字只有 3.08:1,配 #212121 是 5.23:1。暗色底 #ff8c1a 配 #eceff1 只有 2.02:1,配 #241708 是 7.51:1。旧的 .t-inv 是亮色白字配暗色 #241708,亮色那一半不够,2026-09-19 的竖式改版已经全部换成 .t-onfill,77 个手写文件零残留。
.t-onfill 在亮色模式的值跟 .t-main 相同,都是 #212121,只有暗色模式才分岔成 #241708。两个 class 不能合并,合并之后暗色模式的 .card-w3 会掉到 2.02:1。
文字与线:
| class | 用途 | 亮色 | 暗色 |
|---|---|---|---|
.t-main |
主要文字 | #212121 |
#eceff1 |
.t-mute |
次要文字、说明 | #546e7a |
#b0bec5 |
.t-onfill |
饱和底色上的文字,见上方配对表 | #ffffff |
#241708 |
.rule |
分隔线 | #cfd8dc |
#46515a |
.arrow |
流程箭头 | #90a4ae |
#6b7780 |
同一个角色的卡片与标签不要叠在一起。.card-w1 的标签放进 .card-w1 的卡片里,两者底色相同,只剩框线在撑,换一个角色或者把外层改成 .card-n。
颜色不能是唯一的语义载体。每一个色块里的文字要把语义写完整,例如标签写「匿名度 高」而不是只靠绿色。红配绿是色盲最难分的一组,文字写完整之后颜色只是辅助,看不出颜色差别的人照样读得到内容。
对比实测,文字那几组都过 WCAG AA 的 4.5:1:#212121 在六种亮色底上是 14.1 到 16.1,#eceff1 在六种暗色底上是 12.3 到 14.0,#546e7a 在白底 5.4、在中性卡 5.0、在 cyan 卡 4.8,#b0bec5 在暗色卡是 7.7 到 8.4。
.t-mute 订为 #546e7a,它同时也是品牌素材中性色那一组的 --neutral-muted。旧值 #607d8b 在白底只有 4.37:1,AA 差一点,2026-09-19 的竖式改版已经全部换掉,77 个手写文件零残留。
框色对页面底色多半在 1.5 到 2.8:1,没有到 WCAG 1.4.11 的 3:1。这一组的判断是框色属于加强,语义由框内的文字承担,所以不强求。真的要靠颜色分辨的图(散点图、条形图)不适用这个判断,那种图的每一个数据点都要标到文字。
社群分享卡(Open Graph)¶
把文件站的任何一页贴到 Mastodon、LinkedIn、X、Bluesky 或聊天室,对方看到的预览图由构建流程自动生成,三个语系各一份,不需要人工做图。
版面沿用品牌素材的色票。cyan-900 当底色,左缘三段色块由上而下是 cyan-300、cyan-500、cyan-700,对应 logo 三个六角形的层次。左上角是 mono white logo 与站名,中间是页面标题,下方依序是页面描述与网址。页面 front matter 有 icon 时,那个图示会放大成 10% 透明的底纹摆在右侧,没有的话用 material/hexagon-multiple-outline,也就是 logo 的来源图示。
底色没有用品牌主色 cyan-500,理由是读得到字。白字放在 cyan-500 上对比只有 2.5:1,缩到社交平台的预览尺寸就糊成一团,换到 cyan-900 之后是 11.5:1。描述用 cyan-100,对比 8.4:1,页尾网址用 cyan-300,对比 5.6:1。
版式文件是 docs/layouts/anoni.yml,三个语系共用同一份。语系差异只有字体(Noto Sans TC、Noto Sans SC、Public Sans)与版面上显示的站名,分别写在 mkdocs.yml、mkdocs_cn.yml、mkdocs_en.yml。要调整版面就改那一份版式,不要各语系各存一份。
中文标题的换行¶
生成卡片的插件只在空白处换行。一整句中文没有空白,会被当成一个词,超过一行就切在画布边缘,连省略号都不会有。改版之前,站上最长的那个文章标题只显示得出前半段。
现在的作法是在全角逗号、顿号、冒号、句号、感叹号、问号后面补一个半角空白,给换行算法可以断的位置,补上的空白落在行尾就会被吃掉。代价是句子中间偶尔看得到多出来的空隙,换来的是三个语系目前每一则标题与描述都完整显示。标题 14 字以内不处理,那个长度本来就放得下一行。
单页换掉卡片内容¶
某一页需要不一样的标题、描述或底色时,在该页 front matter 覆写:
social:
cards_layout_options:
title: 卡片上要显示的标题
description: 卡片上要显示的描述
background_color: "#003e57"
底图也走同一个选项。background_image 的路径相对于执行 mkdocs 的目录,也就是 docs/,写成 zh-TW/assets/images/xxx.png 这种形式,文件找不到时构建会失败。只填底图的话,底色自动变成 80% 的 cyan-900 遮罩,白字在任何一张图上都读得到。想要原图直出就多填一行 background_color: transparent,代价是浅色的图会让标题与页尾网址消失。
整张图要自己做的场合(活动主视觉、互动区)走另一种写法,front matter 填 og.enabled: true 与 og.image,文件站的模板会改用指定的图片,并跳过自动生成的那一张。COSCUP 活动页与互动区目前就是这样做。
贡献技术图示¶
技术图示(流程图、架构图、对照矩阵、时间轴)有两种做法:
- drawio:节点与连线多、结构复杂的图,存成
.drawio.svg双重格式文件 - 手写 SVG:版型规则的图,例如矩阵、分层、时间轴。直接写比在画布上拖拉快,文件也小一到两个数量级
两种都是 SVG,浏览器、mkdocs、IPFS 镜像、Onion 镜像都直接渲染。
图档放在 assets.anoni.net¶
图档不进 docs/<lang>/assets/images/。三个语系的 assets/images/ 是三份各自独立的实体文件,同一张图要复制三次,漏掉一个语系就是一页破图,而且构建不会报错。zh-CN 的七张 drawio 图就是这样坏了一段时间都没有人发现。
| 东西 | 位置 |
|---|---|
| 原始文件(进版控,可 review、可回溯) | docs/diagrams/ |
| 发布出去的副本 | m6 的 /srv/images-anoni-net/diagrams/ |
| 文章里引用的网址 | https://assets.anoni.net/diagrams/<文件名> |
docs/diagrams/ 不在 docs_dir 底下(docs_dir 设成各语系自己的目录),所以它不会被构建成产物,纯粹是原始文件的存放处。
读者不会直接连到 assets.anoni.net。mkdocs-material 的 privacy 插件在构建时把外部资产抓成本地文件,产物里的 img src 是 assets/external/assets.anoni.net/... 这样的相对路径。Onion 版与 IPFS 镜像照样自足,不会有读者向 clearnet 发请求。
代价是构建时 assets.anoni.net 必须连得到。privacy 插件下载失败时仍会把该文件登记进 files,接着 copy_static_files 找不到文件就让整个构建失败,插件本身没有重试。
文件名带语系¶
图里有中文字就要分语系,文件名写成 <slug>.<lang>.svg:
anonymity-visibility-matrix.zh-TW.svganonymity-visibility-matrix.zh-CN.svganonymity-visibility-matrix.en.svg
图里只有英文术语或完全没有文字,三个语系共用一份,文件名就不带语系,写成 <slug>.svg。
还没补齐三个语系的图,先让另外两个语系引用 zh-TW 那一份,站上至少看得到图。docs/diagrams/ 底下带 .zh-TW. 的文件被 zh-CN 或 en 的页面引用,就代表那张还没补。
发布¶
./tools/publish_diagrams.sh --dry-run # 只检查 SVG 语法
./tools/publish_diagrams.sh # 检查、上传、验证每个网址回 200
顺序不能反过来。先发布图、确认网址回得了 200,才改 Markdown 的引用。反过来做会让下一次构建直接失败。
改同名文件还要清 Cloudflare 缓存,edge 的 max-age 是 12 小时。设好 CF_ZONE_ID 与 CF_PURGE_TOKEN 环境变量,发布脚本会顺手清掉。
没清缓存就推 docs 分支的后果比「站上暂时看到旧版」严重。CI 构建时 privacy 插件是从 edge 抓图,抓到的旧版会被烘进 S3 产物,之后 edge 缓存自己过期也不会修正站上的内容,因为站上读的是产物那一份。
补救也比想像中难。清掉 edge 缓存再重新构建一次是救不回来的:CI 另外缓存了 docs/.cache/plugin/privacy(理由见 build_docs.yml 的注释),同一个网址在那里已经有文件,privacy 插件就不会再去下载。要靠清缓存解决,得把 GitHub Actions 上全部 mkdocs-privacy-* 的项目删掉,restore-keys 会 fallback 所以只删最新的没有用,而代价是下一次构建要重新对十几个外部主机碰运气。
所以规则是不要覆盖同名文件。图有实质改动就换一个文件名,连同 Markdown 的引用一起改,整条路径上没有任何一层会取得旧的。
这一轮在 2026-08-28 完整踩过:矩阵图的配色改过并重新上传,edge 还在 max-age 内,推了 docs 之后站上是旧版。清掉 edge 缓存、workflow_dispatch 重建一次,站上仍是旧版,因为 CI 的 privacy 缓存命中,产物内容没变连上传都被跳过。最后把文件名从 anonymity-vs-privacy-matrix 换成 anonymity-visibility-matrix 才修好。
如何储存才会有 embedded XML¶
drawio.svg 与纯 SVG 的关键差别,在于 drawio.svg 的 <svg> 根标签上多了一个 content="..." 属性,里面是 escape 过的 drawio mxfile XML。drawio 会读这个 XML 重建原本的结构化编辑体验。没有它,drawio 只能把 SVG 视为一堆独立的 path / rect / text 散件,几乎没办法重编。
drawio Desktop 的 Save 对话框有两个关键栏位:
| 栏位 | 设定 |
|---|---|
| Filename | xxx.drawio.svg(双副档名,业界惯例) |
| Format dropdown | Editable Vector Image (.drawio.svg) |
Format dropdown 才是决定性的设定。如果 Filename 取 xxx.drawio.svg 但 Format 选了「SVG (.svg)」,会得到一个文件名长得像 .drawio.svg、但实际没 XML 的纯 SVG。最容易踩的雷。
drawio Desktop 默认 format 通常是 .drawio(纯 XML,浏览器看不到图),新建档时记得手动切到「Editable Vector Image」。或在 Preferences 改 Default save format 永久默认 .drawio.svg。
不要用 Export¶
drawio 有两个写档动作:
- File → Save(Cmd+S):写回原档,保留 XML(前提是 format 是
.drawio.svg) - File → Export As → SVG:产生新的纯 SVG,剥掉 XML
进 repo 的图示只用 Save、不要用 Export。Export As 是给「需要丢给 Photoshop 或其他 SVG viewer」这类场合用,不会放回文件站。
如何验证有 XML¶
存完之后,终端机执行:
grep -c mxfile your-diagram.drawio.svg
预期出现 1 或更多。如果是 0,这个文件没 embedded XML、不能重编,请开回 drawio Desktop 重存(记得 format dropdown 选对)。
配色一致性:drawio palette 默认¶
新图示用品牌素材的 brand cyan 9 阶色票。建议在 drawio Desktop Extras → Configuration 贴上下方 JSON,把品牌色设为 picker 默认:
{
"presetColors": [
"00aeff", "009ee6", "0089bf", "006d99", "003e57",
"4dbfff", "26b3ff", "80d1ff", "b3e3ff", "e0f4ff",
"ef6c00", "d32f2f", "4caf50", "7b1fa2", "546e7a", "cdcdcd"
],
"defaultColors": [
"00aeff", "009ee6", "ef6c00", "d32f2f",
"4caf50", "7b1fa2", "546e7a", "ffffff"
]
}
设一次永久存入,画图时 picker 直接挑品牌色,不会误用 Material 默认色。
手写 SVG 的规则¶
手写的图是被 img 标签引用的独立文件,取不到页面的 CSS 变量,颜色只能写死 hex,照本页上方「示意图用色」那一组抄,class 名称也一起沿用。
画布宽度照手机订¶
画布抓 400 宽,信息往下长。图在页面上被 max-width: 100% 夹进内容栏,缩放比只跟宽度有关,跟高度无关,所以画布越宽,字缩得越狠,而手机是缩放比最糟的那一端。量过文档站各个视窗宽度的内容栏:
| 视窗宽 | 内容栏 | 940 画布的缩放 | 400 画布的缩放 |
|---|---|---|---|
| 1920 | 855 | 0.91 | 1.20 |
| 1440、1280 | 668 | 0.71 | 1.20 |
| 1024 | 750 | 0.80 | 1.20 |
| 768 | 736 | 0.78 | 1.20 |
| 414 | 382 | 0.41 | 0.96 |
| 390 | 358 | 0.38 | 0.90 |
| 360 | 328 | 0.35 | 0.82 |
正文字级桌面 16 到 17.6px,手机 16px。940 的画布配 11.5px 的最小字,在 1440 渲染成 8.2px,在 360 的手机渲染成 4.0px,大约是旁边正文的四分之一。2026-09-19 用 headless Chrome 扫过 docs/diagrams/ 全部 81 个文件,最小字在 360 手机上落在 3.5 到 5.0px,没有一张例外,而页面没有装 lightbox,读者只能整页 pinch-zoom 再平移。
400 的画布配 13px 的最小字,在 1440 渲染成 15.6px,在 390 手机是 11.6px,在 360 手机是 10.7px。桌面那一端靠 .diagram-tall 往上放大到 480px,用法见下方「套到 markdown 文章」。
字级与画布宽度的关系用这一条算:
画布宽 <= 手机内容栏 × 图内最小字级 / 目标渲染字级
要在 360 手机(内容栏 328)让最小字渲染到 11px 以上,12.5px 的字对应画布上限约 372,14px 的字约 417。
横的东西都翻成竖的¶
左到右的流程改成上到下,并排的栏位改成堆叠的卡片,横向的时间轴改成竖向的时间轴。对照矩阵的栏位标题在 400 宽塞不下的时候,把标题搬进每一格里,例如四个评分栏改成卡片内的 2×2 标签。
图里不要放整句的脚注。那一两行散文是逼画布变宽的主因之一,而且烘进图片之后不能选取、不能被搜索,翻译的时候要整张重画。把它搬到 figcaption 或正文。
<picture> 加 srcset 分手机与桌面两份文件这条路走不通。privacy 插件只改写 img src、script src、a href 与 SVG 的 image href,srcset 不会被本地化,onion 与 IPFS 版会留下对 assets.anoni.net 的 clearnet 请求。
版型范本¶
下面这张图把每个版型元件与每个色票 token 各用一次。做新图时照它抄,尺寸、内距与色值都在里面。
固定的数字:画布 400 宽,外距 12,卡片内距 14,所以文字可用宽度是 348。卡片上缘到第一行文字 24px,行距 17px。
卡片之间的间距有三个值,依关系选:
| 间距 | 用在哪 |
|---|---|
| 8px | 同一族群的色阶变体堆叠,例如三阶分层的三张卡片 |
| 10px | 一般情况,语义不同的两张卡片之间 |
| 14px | 段落或族群的边界,例如从 cyan 三阶跳到橙色三阶 |
圆角有三个值,依形状选:
| rx | 用在哪 |
|---|---|
| 8 | 卡片 |
| 6 | 流程节点与卡片内的小方框 |
| 高度的一半 | 胶囊状标签。标签高 24 时 rx 是 12,不要写死 6 |
字级只有 15、14、13 三个值。这套阶层是「粗细乘颜色」两个轴叠出来的,不是一路递增的字级 scale:15 与 14 是粗体深色,13 同时出现在粗体(小标)与细体(正文)。想再加一层强调时改粗细或改颜色,不要插进 12.5 或 13.5 这种中间值,在 0.82 到 1.2 的缩放范围内那 0.5px 没有人看得出来。
eyebrow 用 muted,alt 是唯一的权威文字¶
卡片的 eyebrow 跟 sub 同一个颜色系(浅底用 .t-mute,.card-c2、.card-c3、.card-w2 用 .t-main,.card-w3 用 .t-onfill),只有 title 用深色。三行的层次是「淡的小标、深的标题、淡的副标」。eyebrow 跟 title 都用深色的话,两行只差 1px 字级,在 328 宽看起来像标题被拆成两行。
eyebrow 放的是分类或编号(「第一级」、「Send」、「环境层」),title 说明这一格的内容。如果某个字串单独看就是这张卡的主要信息,它应该是 title 而不是 eyebrow。
SVG 内只留一个简短的 <title>,给直接开启文件网址的情境用,不要写 <desc>。图是被 img 标签引用的,浏览器把它当成不透明的点阵图,SVG 内部的 title、desc、role、aria-* 都不会被辅助科技读到,读者听到的一律是 img 的 alt。完整的说明只写在 alt 那一份,两边各写一份的结果是内容各自漂移。
流程用居中的连接线¶
上下流程的节点是满版的圆角矩形,文字靠左。节点之间留 18px,中间放一条居中在画布中线的连接线,线用 .arrow(stroke #90a4ae,暗色 #6b7780,宽 1.6),末端接一个 .arrow-h 的实心三角形。
不要拿「↓」这类文字字符当箭头。字符的基线、字重与字级都跟着正文走,位置也对不齐节点中线,看起来像漏字而不像流程。
节点 rect x=26 width=348 rx=6
连接线 M200 y V y+12
箭头 M196 y+11 L204 y+11 L200 y+18 Z
断行交给版面算¶
英文版排不下的时候让图长高,不要让图变宽。三个语系共用同一组栏位坐标,长度差异靠折行吸收。数据里一句就是一句,断行的位置交给版面算,手写断行加上折行会长出 the、on 这种单字孤行,中文那一侧则是整行只剩一个「。」,或者句号落在行首。docs/diagrams/ 目前有 10 处这种痕迹,散在 donation-channels、shutdown-levels、baseline-layers 三组文件里。
定稿前用 headless 浏览器在 360 与 390 两个宽度各量一次实际渲染字级。只看 SVG 文件本身量不出来,字级要乘上缩放比才是读者看到的大小。
深色模式在 SVG 内用 @media (prefers-color-scheme: dark) 自己处理,色值照上方「示意图用色」的暗色那两栏抄。自己配的话原则是把主色提亮,例如 cyan-700 #0089bf 换成 cyan-300 #4dbfff。
站上的 palette 切换传得进独立的 SVG。Material 在 slate 主题下会对 body 设 color-scheme: dark,浏览器把这个值带进 img 载入的 SVG 文件,读者手动切到暗色的时候图会跟着换。2026-09-19 在 Chromium 与 Firefox 两边都验过:系统设亮色、文档站切 slate 的组合,图照样渲染成暗色那一组。七张 drawio 图没有这一段,在暗色底上会看到白底方块。
色块里的文字用中性深色 #212121 或白色,不要拿主色当文字色。#ef6c00 与 #4caf50 这类颜色在白底的对比度不到 4.5:1,语意靠框色与文字本身表达就够了。
<style> 区块里不要出现尖括号,连注释里都不行。注释写了带角括号的标签名,整份文件就不是合法 XML,而浏览器照样显示得出来,只有 XML parser 抓得到。publish_diagrams.sh 会挡这个。
手写的图自带外框与内距,不要再套 .brand-frame,那会变成双框。drawio 导出的图没有外框,维持套 .brand-frame。
图里的文字一样适用写作规范,但 docs_style_lint.py 只收 .md 与 .js,扫不到 SVG。文字定稿之前先自己对一次规范,口语词那几条最容易漏。发布之后才发现要改,就得换文件名,因为覆盖同名文件会撞上 edge 缓存。
套到 markdown 文章¶
drawio 图,套 .brand-frame:
<figure markdown="span">
<img class="brand-frame" src="https://assets.anoni.net/diagrams/<name>.zh-TW.drawio.svg" alt="图示说明">
</figure>
手写 SVG,自带外框,改用 figcaption,并且套 .diagram-tall:
<figure markdown="span">
<img class="diagram-tall" src="https://assets.anoni.net/diagrams/<name>.zh-TW.svg" alt="把图的内容用文字说完整">
<figcaption>一句话说明这张图在讲什么</figcaption>
</figure>
.diagram-tall 做的事是 width: 480px 配 max-width: 100%,让 400 的画布在桌面放大到 480,在手机缩到内容栏宽。旧的横式图先不要套,它们的画布是 880 到 1000,套上去会被夹到 480,字比现在更小。
.brand-frame 是 anoni.net 图示的 utility class(cyan 边框加软阴影)。
alt 要把图的内容说完整,不要只写「示意图」三个字。语音朗读、Onion 版的低带宽情境、图抓不到的时候,读者手上只剩这一段文字。
示意图不要包 <a> 做点击放大。SVG 在页面里本来就看得清楚,而 <a href> 不会被 privacy 插件改写,Onion 版的读者点下去会跳出 Tor 连到 clearnet。截图那类需要放大的图才包 <a>,那些本来就是 PNG。
纯 SVG / PNG export 的场合¶
如果某张图也要做 SNS 卡片、印刷品、外部投影片用(不需要重编能力),再多 Export 一份纯 SVG 或 PNG 即可。这份 export 不要进 repo(避免重复),放本机或社群素材库即可。