chore(spec): 归档 blog-5l——三任务收敛(预览一致性/排版提醒/瞬间置顶隐藏)

Spec: 2026-11-05_blog-5l-admin-preview-moments

Co-authored-by: GLM-5.3
This commit is contained in:
wait4xandGLM-5.3 committed 2026-11-05 10:03:34 +08:00
1 parent c5889f960b
commit b99e6e744b
17 files changed
+406 -17

No files matched your search

@@ -0,0 +1,96 @@
# blog-5l:后台预览一致性 + 排版提醒 + 瞬间置顶/隐藏 - 完成总结
## 交付结论
- 结果:完成
- 完成时间:2026-11-05 10:03
## 假设回顾
### 已验证假设
- 预览窗格是 CMS 内部管理的文档,官方 registerPreviewStyle 是唯一稳定注入口(MutationObserver 手注会被重渲染冲掉且升级易碎)
- 预览目标是「类效果可见」(颜色对、字体对、基础排版近似),不追求像素级还原
### 仍未完全验证的假设
- 无
## 交付范围
### 已交付
- task_0001 预览样式注入
- task_0002 编辑提醒
- task_0003 瞬间置顶/隐藏
### 未交付
- 无
### 偏差说明
- 无
## 简化决策
### 保持简单的关键选择
- 最简可行:一个新脚本 preview-style.js + 三处既有文件小改(typography-classes 加 css 字段、typography-editor pattern 放宽、config.yml hint/开关)+ moments 三点改(schema/MomentsPage/config.yml)+ 一条置顶示例数据 + E2E 断言更新
- 暂不引入:常驻样式速查面板、预览明暗主题切换
- 不做的抽象:通用「字段级 hint 生成器」(hint 手写三处即可,量小不值得抽)
- 范围级别:package
- 变更对象:后台静态资源(public/admin)与瞬间列表渲染(MomentsPage)
- 快速检查:`pnpm astro build` + `python3 scripts/build-perf/config-check.py .`
- 集成检查:E2E 59 项 + content-lint 0/0/0 + 产物 grep(moments 首卡 pin 徽标、admin 三脚本接线序)
- 全项目检查:生产部署后人工核验后台预览显色显字体;**升级条件**——仅当改动触及 BaseLayout 字体注入或 build 链时才升级全站回归,本包不涉及
- 升级触发:后台预览为独立资源面,升级为「后台人工核验」即可
### 本轮明确不做的内容
- Sveltia bundle 升级与魔改;预览像素级还原;moments 单条页面 / RSS / sitemap 变化
## 变更边界
### 本轮主要改动模块
- 见 tasks.md 的 boundary 记录
### 明确未触碰的区域
- Sveltia bundle 升级与魔改;预览像素级还原;moments 单条页面 / RSS / sitemap 变化
## 验证证据
### 备注
- 机器证据:runs.jsonl(见验证范围的机器验证率)
## 验证范围
- 级别:package
- 机器验证率:3/3
- 规则:check 与 done 复用该范围;只有记录升级触发时才执行全项目检查
## 哲学生效证据
### 行为成效回填
- Development Record 行为门禁通过
### 一致性门禁回顾
- 验收面(checklist 或成功标准)已通过
## Git 记录
- 日期时间:2026-11-05 10:03
- 范围:blog-5l:后台预览一致性 + 排版提醒 + 瞬间置顶/隐藏
- 功能:task_0001 预览样式注入;task_0002 编辑提醒;task_0003 瞬间置顶/隐藏
- 操作:提交 / 推送
- 成效:Development Record 行为门禁通过
- 提交:pending local commit
- 提交区间:c5889f960b94a70c61b7c31d13e3e4be4cacaaf8..c5889f960b94a70c61b7c31d13e3e4be4cacaaf8
- 推送:not-run (push stage follows commit)
## AGENTS.md 增量提议
```diff
后台编辑体验三件套:预览窗格显色显字体(registerPreviewStyle 官方口子 + 切片字体按需取片)、编辑字段排版速查提醒、瞬间置顶/隐藏真字段(对齐 posts 契约)。
```
## 被拒绝的扩展提议
- 无
## 门禁证据
- check_spec_package.py exit 0
## 遗留事项
- 无;问题处置见下方结构化区块
## 问题处置
```json
{
"issues": [],
"version": 1
}
```
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# task_0001 预览样式注入:三脚本语法 + 注入调用存在 + 接线顺序 + css 字段 + 多类 pattern
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"
node --check public/admin/preview-style.js
node --check public/admin/typography-classes.js
node --check public/admin/typography-editor.js
grep -q "registerPreviewStyle" public/admin/preview-style.js
# index.html 接线序:typography-classes → typography-editor → preview-style(CMS 之后)
grep -q 'typography-classes.js"></script>' public/admin/index.html
grep -q 'preview-style.js"></script>' public/admin/index.html
[ "$(grep -c 'fonts.css" />' public/admin/index.html)" -ge 7 ]
# 清单带切片 CSS 字段 ×7(huiwen/xiaowei/huangyou/mashanzheng/liujianmaocao/smiley/neoxihei)
[ "$(grep -c "css: '/fonts/" public/admin/typography-classes.js)" -eq 7 ]
# pattern 放宽到多类(空格)
grep -q '\[a-z0-9- \]' public/admin/typography-editor.js
echo "verify_t1 OK"
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# task_0002 编辑提醒:hint 速查 ≥3 处 + config-check 通过 + 文档节
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"
export PATH="$HOME/.local/node/bin:$PATH"
python3 scripts/build-perf/config-check.py . | grep -q "全部通过"
[ "$(grep -c 'Insert ▸ 排版' public/admin/config.yml)" -ge 3 ]
grep -q "预览窗格直接显色/显字体" docs/管理台.md
echo "verify_t2 OK"
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# task_0003 瞬间置顶/隐藏:schema/排序过滤/后台开关/徽标/E2E
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"
export PATH="$HOME/.local/node/bin:$PATH"
grep -q "pinned: z.boolean().optional()" src/content.config.ts
grep -q "hidden" src/components/pages/MomentsPage.astro
grep -q "name: pinned, widget: boolean" public/admin/config.yml
grep -q "name: hidden, widget: boolean" public/admin/config.yml
pnpm astro build >/dev/null 2>&1
grep -q 'class="pin"' dist/moments/index.html
nohup python3 scripts/build-perf/gz-server.py 18925 "$PWD/dist" >/tmp/gz-5l.log 2>&1 &
SRV=$!
sleep 2
trap 'kill $SRV 2>/dev/null || true' EXIT
E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -q "59/59 PASS"
echo "verify_t3 OK"
@@ -0,0 +1,33 @@
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.105, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:48:36+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.188, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:48:37+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 40.484, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:49:17+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.103, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:49:26+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.156, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:49:26+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 42.065, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:50:08+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.109, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:51:36+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.159, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:51:36+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 48.822, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:52:25+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.126, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:53:49+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.141, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:53:50+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 45.824, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:54:35+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.11, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:54:36+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.141, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:54:36+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 46.701, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:55:22+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.11, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:55:33+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.142, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:55:33+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 42.886, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:56:16+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.104, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:57:47+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.156, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:57:47+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 42.104, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:58:29+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.102, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:58:46+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.14, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:58:46+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 41.33, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:59:27+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.099, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:59:39+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.139, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T01:59:39+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 44.724, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T02:00:24+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.114, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T02:01:53+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.14, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T02:01:53+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 46.842, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T02:02:40+00:00"}
{"task": "task_0001", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh", "exit": 0, "duration_s": 0.125, "stdout_tail_sha256": "cced3c08cf1601b8177b7728e48c6add6982099d0785fa9fa4dd470b1f4900a5", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T02:02:40+00:00"}
{"task": "task_0002", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh", "exit": 0, "duration_s": 0.172, "stdout_tail_sha256": "10c2f11b3513c46a1043b5e8b93b6aa4fd34f6342f13b4560f17d9adaa0b16b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T02:02:40+00:00"}
{"task": "task_0003", "cmd": "bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh", "exit": 0, "duration_s": 44.882, "stdout_tail_sha256": "409ed685a0bde8695328c75cd1e92fb1e54398e22f911a252c1385f2262db9b3", "tree_fp": "afa04d6db968b3150e68927e061bf0186a1f047da67f4450015da1691769916e", "at": "2026-11-05T02:03:25+00:00"}
@@ -0,0 +1,75 @@
# blog-5l:后台预览一致性 + 排版提醒 + 瞬间置顶/隐藏
<!-- spec-format: 2 -->
- **slug**: 2026-11-05_blog-5l-admin-preview-moments
- **日期**: 2026-11-05
- **状态**: 进行中
- Git integration branch:`spec/2026-11-05_blog-5l-admin-preview-moments`
- 证据协议:evidence: runs
- **提案**: 后台(Sveltia CMS)编辑 markdown 时的预览窗格不渲染排版类(font- 字体、c-/ink- 颜色看不到效果),且编辑时缺少「能用哪些字体/颜色」的提醒;瞬间(moments)需要与文章一致的置顶/隐藏能力。三件事合成一包:预览注入站点排版样式(官方 `CMS.registerPreviewStyle`)、hint/文档提醒、moments pinned/hidden 真字段契约。
## 1. 问题定义
- **项目目标**:后台编辑 markdown 时预览窗格直接显色/显字体(与真实页面一致),编辑时能看到可用字体/颜色的提醒;瞬间获得与文章一致的置顶/隐藏能力。
- **目标用户**:站长(编辑体验与内容管理);读者不受影响(仅瞬间排序/可见性语义对齐)
- **核心价值**:所见即所得消灭「写完发布才发现样式不对」的往返;moments 与 posts 的管理语义统一,降低心智负担
## 2. 假设与待确认
### 2.1 已确认事实
- Sveltia 0.252.0(本地 pinned bundle)含 `registerPreviewStyle`(raw 字符串/URL 两态,支持 collection 作用域)——bundle 内已核实校验逻辑
- 已有「排版」inline 编辑器组件(Insert ▸ 排版,typography-classes.js 清单 + 自建选择面板:字体实样 + 色卡)
- posts 已有 pinned/hidden 真字段 + post-visibility 单一事实源;moments 排序在 MomentsPage.astro 内联(唯一消费点)
- 自托管字体切片落 public/fonts/<family>/fonts.css(unicode-range 按需取片),路径稳定可被后台引用
### 2.2 关键假设
- 预览窗格是 CMS 内部管理的文档,官方 registerPreviewStyle 是唯一稳定注入口(MutationObserver 手注会被重渲染冲掉且升级易碎)
- 预览目标是「类效果可见」(颜色对、字体对、基础排版近似),不追求像素级还原
### 2.3 待确认问题
- [x] 预览注入走官方 registerPreviewStyle,不走 iframe hack(0.252.0 已核实存在)
- [x] 真字体预览走切片 CSS(unicode-range 按需取片),不在后台整包加载 TTF
- [x] moments 置顶多选允许(与书架/文章口径一致);隐藏 = 真字段过滤,无 legacy tag 兼容
### 2.4 可选解释与取舍
- 提醒做成 hint 速查 + 已有排版面板的入口提示,不做常驻侧栏文档组件(Sveltia 定制面有限,hint 是官方支持的展示位)
- serif/kai/kuaile 的 CSS 经 Vite ?url 打包成哈希名,后台引不到稳定 URL,预览走字体栈系统回退(近似可见,文档注明差异)
### 2.5 已证伪路径
- 往预览 iframe 手动注入 `<style>`:预览文档由 CMS 内部管理,注入会被重渲染冲掉、升级易碎——官方 API 存在,必须走官方口子
## 3. 功能范围
### 3.1 核心功能(MVP)
- [x] T1 预览一致性:preview-style.js 从清单运行时生成排版类 CSS + 富文本基础排版(raw 注入)+ 自托管艺术字体切片 CSS(URL 注入);pattern 放宽到多类
- [x] T2 编辑提醒:posts 正文 / moments 文字 / 关于页整页正文三处 hint 补速查;docs/管理台.md 增「预览窗格直接显色/显字体」节
- [x] T3 瞬间置顶/隐藏:schema 真字段 + 列表过滤排序 + 灰阶 pin 徽标 + 后台开关 + E2E 断言
### 3.2 扩展功能
- 无
### 3.3 不在范围内
- Sveltia bundle 升级与魔改;预览像素级还原;moments 单条页面 / RSS / sitemap 变化
## 4. 最小实现路径
- 最简可行:一个新脚本 preview-style.js + 三处既有文件小改(typography-classes 加 css 字段、typography-editor pattern 放宽、config.yml hint/开关)+ moments 三点改(schema/MomentsPage/config.yml)+ 一条置顶示例数据 + E2E 断言更新
- 暂不引入:常驻样式速查面板、预览明暗主题切换
- 不做的抽象:通用「字段级 hint 生成器」(hint 手写三处即可,量小不值得抽)
### 5.1 验证策略
- 范围级别:package
- 变更对象:后台静态资源(public/admin)与瞬间列表渲染(MomentsPage)
- 快速检查:`pnpm astro build` + `python3 scripts/build-perf/config-check.py .`
- 集成检查:E2E 59 项 + content-lint 0/0/0 + 产物 grep(moments 首卡 pin 徽标、admin 三脚本接线序)
- 全项目检查:生产部署后人工核验后台预览显色显字体;**升级条件**——仅当改动触及 BaseLayout 字体注入或 build 链时才升级全站回归,本包不涉及
- 升级触发:后台预览为独立资源面,升级为「后台人工核验」即可
## 6. 成功标准与验证方式
- [x] 后台预览排版类显色/显字体 -> verify: task_0001(manual: 生产后台人工核验,代码面由 task_0001 断言覆盖)
- [x] 编辑字段 hint 含字体/颜色速查与排版面板入口 -> verify: task_0002
- [x] moments 置顶排序 + hidden 过滤 + 后台开关 + pin 徽标 + E2E 全绿 -> verify: task_0003
## 7. 关联与风险
- 前序:5h T1(posts 置顶)、5j T3(页面文案 hint 体系)、5i T9(字体切片管线)
- 风险:registerPreviewStyle 的 URL 模式对预览文档的 base URL 解析若与预期不符,退路是把切片 CSS 也 fetch 成文本走 raw 注入(同一 URL,语义等价)
- 本包不动:热力图(另线预览选型中)
@@ -0,0 +1,22 @@
# Phase 5l:后台预览一致性 + 排版提醒 + 瞬间置顶隐藏 - 任务拆解
## 使用规则
- E2E 口径:`pnpm astro build → gz-server.py 18925 <dist 绝对路径> → E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs`(基线 59 项)
- 后台三脚本加载序固定:typography-classes → typography-editor → preview-style(CMS 之后、init 之前)
## 阶段一:实现
- [x] task_0001 预览样式注入
- claim: orchestrator
- boundary: public/admin/preview-style.js(新)、public/admin/typography-classes.js(css 字段)、public/admin/typography-editor.js(pattern)、public/admin/index.html(接线)
- verify: `bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t1.sh`
- [x] task_0002 编辑提醒
- claim: orchestrator
- boundary: public/admin/config.yml(三处 hint)、docs/管理台.md(新节)
- verify: `bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t2.sh`
- [x] task_0003 瞬间置顶/隐藏
- claim: orchestrator
- boundary: src/content.config.ts(moments schema)、src/components/pages/MomentsPage.astro、public/admin/config.yml(开关)、content/moments/2026-11-02.md(置顶示例)、tests/e2e.mjs(断言)
- verify: `bash .spec/specs/2026-11-05_blog-5l-admin-preview-moments/evidence/verify_t3.sh`