Files
blog/docs/写作指南.md
T
wait4xandGLM-5.3 328ab68f18 feat(cms): 后台扩展五件——关于页 markdown 化/社交/头像/favicon/分轨首页
- T1 关于页=markdown 文档:about.yaml intro 扩为多段 markdown(zh/en),
  AboutPage 用 @astrojs/markdown-remark 的 createMarkdownProcessor(进程
  内单例复用)+ set:html 渲染,正文 p/ul/strong/a 对齐站点排版;名片与
  技能卡结构不动
- T2 社交链接单一数据源:home.yaml socials[](label/url/icon)+
  SocialLinks.astro(图标注册表白名单:github/rss/email/bilibili/x,
  未登记 icon 回退纯文字),首页 zh/en 内联硬编码社交块删除
- T3 头像与 favicon 可上传:schema avatar: image()(Astro Image 出 60px
  WebP,未设回退渐变 SVG);home.yaml favicon → BaseLayout link[rel=icon]
  按扩展名给 type,留空回退 /favicon.svg
- T4 首页分轨:PostList perTrack → 阅读轨/技术轨两段各限 6,各自出口
  (阅读→/books/ 技术→/archives/,en 同构);E2E 断言改为两段各≤6+各自
  出口+阅读在前
- T5 后台列表日期:posts summary「{{pubDate}} · {{title}}」、moments
  「{{fields.pubDate}} · {{fields.text}}」+sortable;photos 无 frontmatter
  日期(JSON sidecar)保持分组 · 标题并在文档写明原因
- 顺手修 content-lint 漏报:中文文件名在 HTML 里为 %XX 编码,脚本直接
  拼盘上路径导致 6 条"缺图"误报 → 加 decodeURI
- 清理:删除书封误传遗留的双重嵌套目录文件

车道:op-gitea(5/5,build+E2E 37/37+lint 47 页 0/0/0);收编复验:
build 46 页 + E2E 37/37 连跑(首跑两红为车道并发构建擦 dist 的瞬时态,
复跑绿)

验证: node v26.13.0 + astro 7.4.4 全量构建 46 页 exit 0;E2E 37/37;
      content-lint 0/0/0;books details/命令面板 playwright 实测

Spec: none (后台能力扩展,车道级交付)

Co-authored-by: GLM-5.3
2026-11-02 15:46:41 +08:00

7.6 KiB
Raw Blame History

写作指南:在文章里插入图片 / 视频 / 音频

适用:content/posts/*.md(书评与技术轨通用)。资产目录约定 + 三种媒体的写法 + 体积纪律。

目录约定

content/posts/
├── my-post.md                    # 文章
└── assets/
    └── my-post/                  # 与文章 slug 同名:该篇私有资产
        ├── photo.jpg
        ├── clip.mp4
        └── voice.mp3

相对引用一律 ./assets/{slug}/文件名,构建时 Astro 图片服务自动出多尺寸 webp。

图片

标准 markdown 语法,alt 必填(无障碍 + 暗色降亮依据):

![外滩夜景](./assets/my-post/bund.jpg)
*图:外滩的傍晚*            ← 紧跟媒体的斜体独立段 = 图注(居中小字)
  • 图注可选;写法固定为 *…* 单独成段,紧跟图片
  • 压缩纪律:入仓前长边 ≤2400px(可跑 python3 scripts/photos_ingest.py,对 posts 资产同样有效的思路,图片请自行用同规格压缩)

视频 / 音频

markdown 原生不认视音频,写 HTML 标签;raw HTML 的相对路径不走 Astro 资产管线(只有 ![]() 图片语法走),所以媒体文件放 public/media/{slug}/ (构建原样拷入 dist),引用用绝对路径 /media/...:

public/media/my-post/clip.mp4      ← 文件放这里
<video controls preload="metadata" src="/media/my-post/clip.mp4"></video>
*片头三秒试拍*

<audio controls preload="metadata" src="/media/my-post/voice.mp3"></audio>
*朗读:面纱选段*
  • preload="metadata" 必写(不预拖流量,只取时长/首帧)
  • 图注警示:斜体图注行内不要裸写 <video>/<audio> 字样——markdown 会把它渲染成真实元素(黑盒+吞文字),提及时用反引号 `
  • 样式已全局处理(视频全宽圆角黑底、音频胶囊条)
  • /media/ 命名空间同时覆盖"仓内小文件"与"仓外 store 大文件"(见体积纪律表)

体积纪律(git 仓红线)

媒体 入仓上限 超限怎么办
图片 单张 ≤1MB(2400px 压缩后通常 200-800KB) 重压
音频 ≤5MB(3 分钟 128kbps ≈ 2.8MB) 降码率
视频 ≤5MB 放仓外 ~/docker_apps/blog/media/(photos-originals 同模式),文章里用绝对路径 /media/xxx.mp4;build.sh 同步段待该场景首次出现时补

历史教训:21 张原图 196M 直接入仓曾撞死推送通道(git 历史 7a2880b 重写才甩掉)。

三媒齐用的样例

见 content/posts/media-sample.md(draft 文章,仅构建验证用,不上线)。

链接卡片(OG 预览卡)

一行只放一个链接、且它独立成段时,构建期会抓取该页的 OG 信息渲染成卡片(标题 / 描述 / 站点图标 / 可选缩略图):

https://astro.build/

[也可以是 markdown 链接形态](https://astro.build/)

规则与边界:

  • 内联链接不变:夹在句子里的链接保持普通样式(这是一句带 [链接](https://example.com) 的话 → 不会变卡),所以不会把整篇变成卡片墙
  • 抓取失败一律回落普通链接:404、无 OG、超时(4s)、站点拒爬都不影响构建
  • 每篇最多 10 张卡,超出的回落普通链接(防止文章变卡片流)
  • 缓存:结果存 content/.link-cache.json(入仓,保证构建确定性);条目 30 天后自动重抓。想强制刷新某条——删掉该 URL 的条目即可
  • 缩略图取 og:image,无图不占位;图标取站点而非第三方 favicon 服务

发布提醒

  • push main → webhook 自动构建发布(约 10 秒)
  • 新文章要英文版:跑 python3 scripts/translate/translate_posts.py(幂等,代码块不会被翻译破坏的风险见其 README 注释;锁定润色用 frontmatter locked: true)

书封图(/books 书架)

阅读轨文章可选加书封:

  1. 图片放 content/posts/assets/books/<slug>.jpg(建议宽 480px、高宽比约 2:3)
  2. 对应文章 frontmatter 加一行:cover: ./assets/books/<slug>.jpg
  3. 构建自动优化出 96/192 两档;没有 cover 的文章优雅回退现有色脊卡设计,无需改任何代码

示例 frontmatter:

---
title: "面纱"
pubDate: 2024-06-01
category: reading
bookAuthor: "毛姆"
mood: "#8a6f4a"
cover: ./assets/books/mian-sha.jpg
---

后台上传(Sveltia 后台,推荐路径)

后台地址 /admin/(gitea 账号登录)。三类媒体都有后台入口,不必手写路径:

图片

文章编辑器里插入图片 → 自动上传到 content/posts/assets/ 并写入 ./assets/... 相对路径(走 Astro 图片管线,自动优化)。不要手改成 /assets/... 绝对路径。

视频(frontmatter 字段,正文后自动渲染)

  1. 文章编辑页「附视频」字段上传(自动落 public/media/,路径写 /media/<name>.mp4)
  2. 正文读完后自动出现 <video controls preload="metadata" playsinline>,全宽圆角黑底
  3. 「视频封面」填 /media/xxx.jpg 可自定首帧;留空浏览器自取
  4. 无视频字段 → 该区块不渲染(零占位)

体积纪律:mp4/webm ≤50MB 走 public/media/(构建原样拷贝,不转码); 更大的请按上文「体积纪律」放仓外 store(该场景 build.sh 同步段待首次出现时补)。

后台列表日期

文章/瞬间列表显示「日期 · 标题」,可按日期排序;图库照片没有 frontmatter 日期 (时间在 EXIF/文件侧),列表按「分组 · 标题」展示、按标题/分组排序。

链接

markdown 原生语法,无需任何配置:

[文字](https://example.com)

想让链接显示成 OG 预览卡(带标题/描述/图标),把它单独放一行即可——规则见上文「链接卡片(OG 预览卡)」。

页面文案(主页/关于/开源)

后台「页面文案」下三个入口:

入口 文件 可改内容
主页设置 content/site/home.yaml 身份语 tagline、头像 avatar、站点图标 favicon、社交链接 socials
关于页 content/site/about.yaml markdown 正文 intro(多段/列表/粗斜体/链接)
开源页 content/site/opensource.yaml 叙述 blurb/blurb_after、仓链接、置顶项目 pinned

头像与站点图标

  • 头像:主页设置里「头像」上传 → 落 content/site/assets/,构建期优化成 60px WebP; 留空则显示内置渐变占位(w4 徽标)
  • 站点图标 favicon:先经「图标」媒体库上传(public/icons/),再把路径粘到 「站点图标」字段(如 /icons/my.ico、/icons/my.svg);留空回退 /favicon.svg。 支持 .svg / .ico / .png(直出,不经图片优化)

社交链接

主页设置里「社交链接」是列表:可增删、拖动排序。每条 = 名称(无障碍文字)+ 链接 + 图标。 图标可选 github / rss / email / bilibili / x,留空则显示纯文字按钮。 首页名片区、以及任何引用该组件的页面都吃同一份数据(单一事实源,改一次全站生效)。

首页文章列表

首页现在分两段:阅读轨 6 条 + 技术轨 6 条(各自带「全部文章」出口:阅读→书架、技术→归档)。 照片轨文章不进首页(在图库看)。完整列表见 /archives/。

  • 中文/英文各一个字段,页面按语言取;留空则该字段回落默认文案(构建不会炸)
  • pinned 填仓库短名(如 blog、pi-board),顺序即展示顺序;留空回落 blog