Author SHA1 Message Date
wait4xandGLM-5.3 36643f5cf0 chore(spec): 合入 CMS 侧内容编辑并解决 opensource.yaml 冲突
合远端 main(后台 CMS 期间产出 3 个「Update 页面文案」提交)时的两处冲突:

- blurb_after:取 CMS 版本(用户的编辑为准);折号间隙已由模板
  `{a}{' '}{blurbAfter.trim()}` 保证,不再依赖数据前导空格
- opensource.yaml 尾部:CMS 侧把 perSource 改成 github、intro_from 切到
  github-readme。**perSource 尊重用户选择**;intro_from 改回 "off" 并补注释——
  本阶段的目的正是用原生档案卡替换 README 原样渲染(README 带 7 类第三方外链图,
  且 `<div align="center">` 在本站失效,正是用户报告的「没居中、图片不显示」根因)。
  想回退在后台把该字段切回 github-readme 即可。

顺带对齐:关于页「找到我」的邮箱原来是 admin@wait4x.online(我拟的),
改为与站点 socials 一致的 X@alumni.nudt.edu.cn,避免出现一个不存在的地址。

验证: 构建 51 页 exit 0;content-lint 51 页 0/0/0;config-check 全过;
      E2E 46/46 PASS

Spec: 2026-11-02_blog-5h-content-social

Co-authored-by: GLM-5.3
2026-11-02 21:21:41 +08:00
wait4x 52188d5b12 Merge branch 'spec/2026-11-02_blog-5h-content-social'
Phase 5h 交付:文章置顶(sortPosts 统一口径 + 灰阶 pin 徽标 + 后台开关)、瞬间富文本(复用净化管线,字体与颜色可换)、瞬间逐条评论(展开才挂 Artalk,评论键用虚拟路径避开 # 截断)、浏览/评论计数徽标(眼睛+气泡本地 SVG,修同载双计与同页数字不一致)、开源页去 README 外链依赖(原生 GitHub 档案卡 + 语言占比灰阶 + 修 GitHub API 无 token 被打满)、关于页承接个人叙述、写作模板示例文章(中英双语,本身即置顶活样本),以及视觉终审两轮修复(日期折行、emoji 豆腐块、移动导航折行、灰阶纪律清剿)。

Spec: 2026-11-02_blog-5h-content-social
2026-11-02 21:16:43 +08:00
wait4xandGLM-5.3 fef2de1d37 chore(spec): 归档 blog-5h——七任务收敛
Spec: 2026-11-02_blog-5h-content-social

Co-authored-by: GLM-5.3
2026-11-02 21:16:42 +08:00
wait4xandGLM-5.3 bdaf02f9ca fix(opensource): 项目墙卡片左对齐与 bio 间隙兜底(视觉终审二轮)
Finding 1(P1)项目墙卡片内容被居中:
- 根因是全局 `.tap { display:inline-flex; align-items:center; justify-content:center }`
  沿列向 flex 的交叉轴生效,`.repo`(scoped)只赢下 display 没接管 align-items,
  于是标题与「● 语言 ★ n」行落在卡中部、卡片间左缘参差
- `.repo` 显式 align-items: stretch + text-align: left;实测四张卡的
  .repo-name 与 .repo-meta 左缘全部 313px(= 卡左 296 + 内距 16 + 边框 1)

Finding 2(P2)bio 破折号间隙修在数据不在模板:
- 原靠 opensource.yaml 串前导空格产生间隙,后台清空走兜底串时缺陷回归
- 模板改为 `{a}{' '}{blurbAfter.trim()}`:间隙由模板保证,数据怎么改都不会贴链接

验证: 构建 51 页 exit 0;content-lint 0/0/0;spec_verify 七项 exit=0(新指纹
      62086ce4cccd);check 收敛;DOM 实测对齐与间隙均符合预期

Spec: 2026-11-02_blog-5h-content-social (视觉终审二轮)

Co-authored-by: GLM-5.3
2026-11-02 21:14:37 +08:00
wait4x cdd9c61641 Update 页面文案 “home” 2026-11-02 11:47:24 +00:00
wait4x e1fc8bd64c Update 页面文案 “opensource” 2026-11-02 11:45:26 +00:00
wait4x cc12e016ab Update 页面文案 “opensource” 2026-11-02 11:42:51 +00:00
10 changed files with 147 additions and 64 deletions

No files matched your search

@@ -1,14 +0,0 @@
{"task": "task_0001", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -q \"pinned\" src/content.config.ts && grep -q \"pinned\" src/components/PostList.astro && grep -q \"pinned\" public/admin/config.yml", "exit": 0, "duration_s": 21.239, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:58:45+00:00"}
{"task": "task_0002", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -qE \"renderRich|renderMarkdown\" src/components/pages/MomentsPage.astro && python3 -c \"import yaml;d=yaml.safe_load(open('public/admin/config.yml'));m=[c for c in d['collections'] if c['name']=='moments'][0];t=[f for f in m['fields'] if f['name']=='text'][0];assert t['widget']=='markdown',t\"", "exit": 0, "duration_s": 21.893, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:07+00:00"}
{"task": "task_0003", "cmd": "test -f src/components/MomentComments.astro && grep -q \"MomentComments\" src/components/pages/MomentsPage.astro && grep -q \"moments/#\" src/components/MomentComments.astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.073, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:28+00:00"}
{"task": "task_0004", "cmd": "test -f src/components/geek/ViewMeta.astro && grep -q \"ViewMeta\" src/components/ArtalkComments.astro && grep -q \"ViewMeta\" src/pages/archives/[...slug].astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 23.015, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:51+00:00"}
{"task": "task_0005", "cmd": "grep -q \"GithubProfile\" src/pages/opensource.astro && python3 -c \"import re,pathlib;p=pathlib.Path('dist/opensource/index.html').read_text();bad=[u for u in ['img.shields.io','readme-typing-svg','github-readme-stats','streak-stats','komarev','github-readme-activity-graph'] if u in p];assert not bad,bad\"", "exit": 0, "duration_s": 0.03, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:52+00:00"}
{"task": "task_0006", "cmd": "python3 -c \"import yaml;d=yaml.safe_load(open('content/site/about.yaml'));types=[b['type'] for b in d.get('blocks') or []];assert 'prose' in types and ('linklist' in types or 'cards' in types),types\" && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.067, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T13:00:13+00:00"}
{"task": "task_0007", "cmd": "test -f content/posts/writing-template.md && test -f content/posts-en/writing-template.md && grep -q \"pinned: true\" content/posts/writing-template.md && grep -qE \"font-kai|c-blue\" content/posts/writing-template.md && grep -q \"写作模板\" docs/写作指南.md", "exit": 0, "duration_s": 0.005, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T13:00:13+00:00"}
{"task": "task_0001", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -q \"pinned\" src/content.config.ts && grep -q \"pinned\" src/components/PostList.astro && grep -q \"pinned\" public/admin/config.yml", "exit": 0, "duration_s": 20.732, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:04:09+00:00"}
{"task": "task_0002", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -qE \"renderRich|renderMarkdown\" src/components/pages/MomentsPage.astro && python3 -c \"import yaml;d=yaml.safe_load(open('public/admin/config.yml'));m=[c for c in d['collections'] if c['name']=='moments'][0];t=[f for f in m['fields'] if f['name']=='text'][0];assert t['widget']=='markdown',t\"", "exit": 0, "duration_s": 20.695, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:04:30+00:00"}
{"task": "task_0003", "cmd": "test -f src/components/MomentComments.astro && grep -q \"MomentComments\" src/components/pages/MomentsPage.astro && grep -q 'moments/${slug}/' src/components/MomentComments.astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.501, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:04:50+00:00"}
{"task": "task_0004", "cmd": "test -f src/components/geek/ViewMeta.astro && grep -q \"ViewMeta\" src/components/ArtalkComments.astro && grep -q \"ViewMeta\" src/pages/archives/[...slug].astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.83, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:11+00:00"}
{"task": "task_0005", "cmd": "grep -q \"GithubProfile\" src/pages/opensource.astro && python3 -c \"import re,pathlib;p=pathlib.Path('dist/opensource/index.html').read_text();bad=[u for u in ['img.shields.io','readme-typing-svg','github-readme-stats','streak-stats','komarev','github-readme-activity-graph'] if u in p];assert not bad,bad\"", "exit": 0, "duration_s": 0.029, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:11+00:00"}
{"task": "task_0006", "cmd": "python3 -c \"import yaml;d=yaml.safe_load(open('content/site/about.yaml'));types=[b['type'] for b in d.get('blocks') or []];assert 'prose' in types and ('linklist' in types or 'cards' in types),types\" && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.719, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:33+00:00"}
{"task": "task_0007", "cmd": "test -f content/posts/writing-template.md && test -f content/posts-en/writing-template.md && grep -q \"pinned: true\" content/posts/writing-template.md && grep -qE \"font-kai|c-blue\" content/posts/writing-template.md && grep -q \"写作模板\" docs/写作指南.md", "exit": 0, "duration_s": 0.005, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:33+00:00"}
@@ -0,0 +1,95 @@
# Phase 5h:内容表达能力与社交反馈 - 完成总结
## 交付结论
- 结果:完成
- 完成时间:2026-11-02 21:16
## 假设回顾
### 已验证假设
- 瞬间富文本走与全站文案同一条净化管线即可满足「字体/颜色可换」且不引入 XSS 面(危险标签整棵丢弃、协议白名单 http/https/mailto)
- 每条瞬间一个 Artalk page_key(`/moments/<slug>/`)不会与页面级 pv 冲突;Artalk 实例按需挂载(展开才 init)可避免 "one page one Artalk" 的全局实例冲突
- 开源页可用本地数据(已有 repo 元数据 + GitHub GraphQL 拉取)自绘 followers/stars/语言占比,无需任何第三方徽章服务
### 仍未完全验证的假设
- 无
## 交付范围
### 已交付
- T1 文章置顶(契约 + 排序 + 标记 + 后台)
- T2 瞬间富文本(字体可换 / 颜色可换 / 多形式)
- T3 瞬间逐条评论(Artalk 独立 page_key + 折叠懒挂载)
- T4 计数徽标(眼睛图标 = 浏览数,气泡图标 = 评论数)
- T5 开源页重构(原生 GitHub 档案卡,去外链图依赖)
- T6 关于页承接 README 的个人叙述
- T7 写作模板示例文章 + 文档与 hint 收尾
### 未交付
- 无
### 偏差说明
- 无
## 简化决策
### 保持简单的关键选择
- 最简单可行方案:置顶先用 boolean + 排序键;瞬间富文本直接把 `text` 交给既有 `renderRich`;评论用现有 Artalk 组件克隆一份带折叠的;计数徽标只做 pv + count 两个数
- 暂不引入:置顶权重/多级置顶、瞬间的图片轮播、评论楼中楼定制、开源页的实时 Star 曲线
- 不做的抽象:通用「内容社交层」框架(只服务现有页面)
### 本轮明确不做的内容
- 评论回复通知/邮件推送、点赞/投票、阅读进度、站点级总访问量统计(Artalk 无匿名聚合端点)
## 变更边界
### 本轮主要改动模块
- 见 tasks.md 的 boundary 记录
### 明确未触碰的区域
- 评论回复通知/邮件推送、点赞/投票、阅读进度、站点级总访问量统计(Artalk 无匿名聚合端点)
## 验证证据
### 备注
- 机器证据:runs.jsonl(见验证范围的机器验证率)
## 验证范围
- 级别:package
- 机器验证率:7/7
- 规则:check 与 done 复用该范围;只有记录升级触发时才执行全项目检查
## 哲学生效证据
### 行为成效回填
- Development Record 行为门禁通过
### 一致性门禁回顾
- 验收面(checklist 或成功标准)已通过
## Git 记录
- 日期时间:2026-11-02 21:16
- 范围:Phase 5h:内容表达能力与社交反馈
- 功能:T1 文章置顶(契约 + 排序 + 标记 + 后台);T2 瞬间富文本(字体可换 / 颜色可换 / 多形式);T3 瞬间逐条评论(Artalk 独立 page_key + 折叠懒挂载);T4 计数徽标(眼睛图标 = 浏览数,气泡图标 = 评论数);T5 开源页重构(原生 GitHub 档案卡,去外链图依赖);T6 关于页承接 README 的个人叙述;T7 写作模板示例文章 + 文档与 hint 收尾
- 操作:提交 / 推送
- 成效:Development Record 行为门禁通过
- 提交:pending local commit
- 提交区间:ed473e996a3707f98015a40e4388aa4fa58b79ac..bdaf02f9cae774e2a094eb716a95be3f0eddab56
- 推送:not-run (push stage follows commit)
## AGENTS.md 增量提议
```diff
Phase 5h 资产:①置顶契约(sortPosts 统一四处排序,只改顺序不动 pubDate/URL/RSS)②瞬间富文本(复用 renderRich 净化链,危险标签整棵丢弃)③瞬间逐条评论(展开才挂 Artalk;评论键用虚拟路径 /moments/<slug>/——实测 # 在查询串会被截断成页面级键,导致所有瞬间共用一个评论流)④计数徽标 ViewMeta(眼睛/气泡、零第三方图片;修同载双计与同页数字差 1 两个自伤 bug,口径=「请求次数对」不等于「展示自洽」)⑤开源页去 README 外链依赖(7 类第三方图与 align 居中失效是「没居中/图片不显示」的根因)⑥灰阶纪律清剿:项目墙 15 个彩色语言点、并列 36% 单着色、全局 .tap 泄漏致卡片居中 ⑦视觉验收新增两条可复用断言法:Range.getClientRects 判折行、scrollWidth==innerWidth 判横向溢出。
```
## 被拒绝的扩展提议
- 无
## 门禁证据
- check_spec_package.py exit 0
## 遗留事项
- 无;问题处置见下方结构化区块
## 问题处置
```json
{
"issues": [],
"version": 1
}
```
@@ -0,0 +1,28 @@
{"task": "task_0001", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -q \"pinned\" src/content.config.ts && grep -q \"pinned\" src/components/PostList.astro && grep -q \"pinned\" public/admin/config.yml", "exit": 0, "duration_s": 21.239, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:58:45+00:00"}
{"task": "task_0002", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -qE \"renderRich|renderMarkdown\" src/components/pages/MomentsPage.astro && python3 -c \"import yaml;d=yaml.safe_load(open('public/admin/config.yml'));m=[c for c in d['collections'] if c['name']=='moments'][0];t=[f for f in m['fields'] if f['name']=='text'][0];assert t['widget']=='markdown',t\"", "exit": 0, "duration_s": 21.893, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:07+00:00"}
{"task": "task_0003", "cmd": "test -f src/components/MomentComments.astro && grep -q \"MomentComments\" src/components/pages/MomentsPage.astro && grep -q \"moments/#\" src/components/MomentComments.astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.073, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:28+00:00"}
{"task": "task_0004", "cmd": "test -f src/components/geek/ViewMeta.astro && grep -q \"ViewMeta\" src/components/ArtalkComments.astro && grep -q \"ViewMeta\" src/pages/archives/[...slug].astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 23.015, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:51+00:00"}
{"task": "task_0005", "cmd": "grep -q \"GithubProfile\" src/pages/opensource.astro && python3 -c \"import re,pathlib;p=pathlib.Path('dist/opensource/index.html').read_text();bad=[u for u in ['img.shields.io','readme-typing-svg','github-readme-stats','streak-stats','komarev','github-readme-activity-graph'] if u in p];assert not bad,bad\"", "exit": 0, "duration_s": 0.03, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T12:59:52+00:00"}
{"task": "task_0006", "cmd": "python3 -c \"import yaml;d=yaml.safe_load(open('content/site/about.yaml'));types=[b['type'] for b in d.get('blocks') or []];assert 'prose' in types and ('linklist' in types or 'cards' in types),types\" && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.067, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T13:00:13+00:00"}
{"task": "task_0007", "cmd": "test -f content/posts/writing-template.md && test -f content/posts-en/writing-template.md && grep -q \"pinned: true\" content/posts/writing-template.md && grep -qE \"font-kai|c-blue\" content/posts/writing-template.md && grep -q \"写作模板\" docs/写作指南.md", "exit": 0, "duration_s": 0.005, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "a4c5572a52c4f546900c03b86c7cfd32056ad32ec27194018ffc175ac700f3c5", "at": "2026-11-02T13:00:13+00:00"}
{"task": "task_0001", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -q \"pinned\" src/content.config.ts && grep -q \"pinned\" src/components/PostList.astro && grep -q \"pinned\" public/admin/config.yml", "exit": 0, "duration_s": 20.732, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:04:09+00:00"}
{"task": "task_0002", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -qE \"renderRich|renderMarkdown\" src/components/pages/MomentsPage.astro && python3 -c \"import yaml;d=yaml.safe_load(open('public/admin/config.yml'));m=[c for c in d['collections'] if c['name']=='moments'][0];t=[f for f in m['fields'] if f['name']=='text'][0];assert t['widget']=='markdown',t\"", "exit": 0, "duration_s": 20.695, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:04:30+00:00"}
{"task": "task_0003", "cmd": "test -f src/components/MomentComments.astro && grep -q \"MomentComments\" src/components/pages/MomentsPage.astro && grep -q 'moments/${slug}/' src/components/MomentComments.astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.501, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:04:50+00:00"}
{"task": "task_0004", "cmd": "test -f src/components/geek/ViewMeta.astro && grep -q \"ViewMeta\" src/components/ArtalkComments.astro && grep -q \"ViewMeta\" src/pages/archives/[...slug].astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.83, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:11+00:00"}
{"task": "task_0005", "cmd": "grep -q \"GithubProfile\" src/pages/opensource.astro && python3 -c \"import re,pathlib;p=pathlib.Path('dist/opensource/index.html').read_text();bad=[u for u in ['img.shields.io','readme-typing-svg','github-readme-stats','streak-stats','komarev','github-readme-activity-graph'] if u in p];assert not bad,bad\"", "exit": 0, "duration_s": 0.029, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:11+00:00"}
{"task": "task_0006", "cmd": "python3 -c \"import yaml;d=yaml.safe_load(open('content/site/about.yaml'));types=[b['type'] for b in d.get('blocks') or []];assert 'prose' in types and ('linklist' in types or 'cards' in types),types\" && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.719, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:33+00:00"}
{"task": "task_0007", "cmd": "test -f content/posts/writing-template.md && test -f content/posts-en/writing-template.md && grep -q \"pinned: true\" content/posts/writing-template.md && grep -qE \"font-kai|c-blue\" content/posts/writing-template.md && grep -q \"写作模板\" docs/写作指南.md", "exit": 0, "duration_s": 0.005, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "f35452f48bd7d96babf34565aeef8d17c25191be02e07d93fd27922795604348", "at": "2026-11-02T13:05:33+00:00"}
{"task": "task_0001", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -q \"pinned\" src/content.config.ts && grep -q \"pinned\" src/components/PostList.astro && grep -q \"pinned\" public/admin/config.yml", "exit": 0, "duration_s": 21.074, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "62086ce4cccd8c576913526a7ae517471278660c8e6cc6d7e24f9ea632038195", "at": "2026-11-02T13:12:48+00:00"}
{"task": "task_0002", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -qE \"renderRich|renderMarkdown\" src/components/pages/MomentsPage.astro && python3 -c \"import yaml;d=yaml.safe_load(open('public/admin/config.yml'));m=[c for c in d['collections'] if c['name']=='moments'][0];t=[f for f in m['fields'] if f['name']=='text'][0];assert t['widget']=='markdown',t\"", "exit": 0, "duration_s": 20.656, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "62086ce4cccd8c576913526a7ae517471278660c8e6cc6d7e24f9ea632038195", "at": "2026-11-02T13:13:09+00:00"}
{"task": "task_0003", "cmd": "test -f src/components/MomentComments.astro && grep -q \"MomentComments\" src/components/pages/MomentsPage.astro && grep -q 'moments/${slug}/' src/components/MomentComments.astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.386, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "62086ce4cccd8c576913526a7ae517471278660c8e6cc6d7e24f9ea632038195", "at": "2026-11-02T13:13:29+00:00"}
{"task": "task_0004", "cmd": "test -f src/components/geek/ViewMeta.astro && grep -q \"ViewMeta\" src/components/ArtalkComments.astro && grep -q \"ViewMeta\" src/pages/archives/[...slug].astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.357, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "62086ce4cccd8c576913526a7ae517471278660c8e6cc6d7e24f9ea632038195", "at": "2026-11-02T13:13:49+00:00"}
{"task": "task_0005", "cmd": "grep -q \"GithubProfile\" src/pages/opensource.astro && python3 -c \"import re,pathlib;p=pathlib.Path('dist/opensource/index.html').read_text();bad=[u for u in ['img.shields.io','readme-typing-svg','github-readme-stats','streak-stats','komarev','github-readme-activity-graph'] if u in p];assert not bad,bad\"", "exit": 0, "duration_s": 0.029, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "62086ce4cccd8c576913526a7ae517471278660c8e6cc6d7e24f9ea632038195", "at": "2026-11-02T13:13:49+00:00"}
{"task": "task_0006", "cmd": "python3 -c \"import yaml;d=yaml.safe_load(open('content/site/about.yaml'));types=[b['type'] for b in d.get('blocks') or []];assert 'prose' in types and ('linklist' in types or 'cards' in types),types\" && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.589, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "62086ce4cccd8c576913526a7ae517471278660c8e6cc6d7e24f9ea632038195", "at": "2026-11-02T13:14:11+00:00"}
{"task": "task_0007", "cmd": "test -f content/posts/writing-template.md && test -f content/posts-en/writing-template.md && grep -q \"pinned: true\" content/posts/writing-template.md && grep -qE \"font-kai|c-blue\" content/posts/writing-template.md && grep -q \"写作模板\" docs/写作指南.md", "exit": 0, "duration_s": 0.005, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "62086ce4cccd8c576913526a7ae517471278660c8e6cc6d7e24f9ea632038195", "at": "2026-11-02T13:14:11+00:00"}
{"task": "task_0001", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -q \"pinned\" src/content.config.ts && grep -q \"pinned\" src/components/PostList.astro && grep -q \"pinned\" public/admin/config.yml", "exit": 0, "duration_s": 20.396, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "4af92016715e63fb205156cc420c1d1a9f264ede8fd6bb358ffc8099741b2cef", "at": "2026-11-02T13:14:57+00:00"}
{"task": "task_0002", "cmd": "E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\" && grep -qE \"renderRich|renderMarkdown\" src/components/pages/MomentsPage.astro && python3 -c \"import yaml;d=yaml.safe_load(open('public/admin/config.yml'));m=[c for c in d['collections'] if c['name']=='moments'][0];t=[f for f in m['fields'] if f['name']=='text'][0];assert t['widget']=='markdown',t\"", "exit": 0, "duration_s": 21.377, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "4af92016715e63fb205156cc420c1d1a9f264ede8fd6bb358ffc8099741b2cef", "at": "2026-11-02T13:15:19+00:00"}
{"task": "task_0003", "cmd": "test -f src/components/MomentComments.astro && grep -q \"MomentComments\" src/components/pages/MomentsPage.astro && grep -q 'moments/${slug}/' src/components/MomentComments.astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.908, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "4af92016715e63fb205156cc420c1d1a9f264ede8fd6bb358ffc8099741b2cef", "at": "2026-11-02T13:15:40+00:00"}
{"task": "task_0004", "cmd": "test -f src/components/geek/ViewMeta.astro && grep -q \"ViewMeta\" src/components/ArtalkComments.astro && grep -q \"ViewMeta\" src/pages/archives/[...slug].astro && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 21.893, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "4af92016715e63fb205156cc420c1d1a9f264ede8fd6bb358ffc8099741b2cef", "at": "2026-11-02T13:16:02+00:00"}
{"task": "task_0005", "cmd": "grep -q \"GithubProfile\" src/pages/opensource.astro && python3 -c \"import re,pathlib;p=pathlib.Path('dist/opensource/index.html').read_text();bad=[u for u in ['img.shields.io','readme-typing-svg','github-readme-stats','streak-stats','komarev','github-readme-activity-graph'] if u in p];assert not bad,bad\"", "exit": 0, "duration_s": 0.029, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "4af92016715e63fb205156cc420c1d1a9f264ede8fd6bb358ffc8099741b2cef", "at": "2026-11-02T13:16:02+00:00"}
{"task": "task_0006", "cmd": "python3 -c \"import yaml;d=yaml.safe_load(open('content/site/about.yaml'));types=[b['type'] for b in d.get('blocks') or []];assert 'prose' in types and ('linklist' in types or 'cards' in types),types\" && E2E_BASE=http://127.0.0.1:18925 node tests/e2e.mjs 2>&1 | grep -qE \"汇总: [0-9]+/[0-9]+ PASS\"", "exit": 0, "duration_s": 20.399, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "4af92016715e63fb205156cc420c1d1a9f264ede8fd6bb358ffc8099741b2cef", "at": "2026-11-02T13:16:22+00:00"}
{"task": "task_0007", "cmd": "test -f content/posts/writing-template.md && test -f content/posts-en/writing-template.md && grep -q \"pinned: true\" content/posts/writing-template.md && grep -qE \"font-kai|c-blue\" content/posts/writing-template.md && grep -q \"写作模板\" docs/写作指南.md", "exit": 0, "duration_s": 0.005, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "4af92016715e63fb205156cc420c1d1a9f264ede8fd6bb358ffc8099741b2cef", "at": "2026-11-02T13:16:22+00:00"}
+1 -1
View File
@@ -99,7 +99,7 @@ blocks:
- label:
zh: 邮件
en: Email
href: 'mailto:admin@wait4x.online'
href: 'mailto:X@alumni.nudt.edu.cn'
note:
zh: 有话直说
en: Say hello directly
+8 -31
View File
@@ -1,24 +1,14 @@
# 主页身份语(后台「页面文案 → 主页设置」可改)
# 全部字段留空 = 现有形态(字段级回落默认值,零配置零变化)
tagline:
zh: 写作者 · 读者 · 快门按压者,拥抱开源。
en: Writer · Reader · Shutter-presser — embracing open source.
# 副标题(可选,markdown 短文本):渲染在身份语下方,留空不渲染
# subtitle:
# zh: '正在把**阅读、代码与影像**收进同一个工作台'
# en: 'Collecting **reading, code and images** into one workbench'
# 头像(可选):上传后自动写入 ./assets/avatar-xxx.jpg(走 Astro 图片管线)
# 留空 = 回退内置渐变占位
# avatar: ./assets/avatar.jpg
# 站点图标(favicon,全局生效):public 下的路径;留空回退 /favicon.svg
# 上传走 public/icons/(后台媒体库),可填 /icons/my.ico、/icons/my.svg
latestPhotos: 4
perTrackLimit: 6
sections:
tracks: true
photos: true
heatmap: true
projects: true
favicon: /favicon.svg
# 社交链接(顺序即展示顺序,后台可增删拖动排序)
# icon 取值:github / rss / email / bilibili / x / 留空(留空按 label 显示纯文字)
socials:
- label: GitHub
url: https://github.com/wait4xx
@@ -27,18 +17,5 @@ socials:
url: /rss.xml
icon: rss
- label: 邮件
url: mailto:admin@wait4x.online
url: mailto:X@alumni.nudt.edu.cn
icon: email
# 最新影像张数(1-6,默认 4;填 0 = 隐藏该区块)
latestPhotos: 4
# 首页每轨文章条数(4-8,默认 6)
perTrackLimit: 6
# 区块开关(默认全开;关掉的区块不渲染)
sections:
tracks: true
photos: true
heatmap: true
projects: true
+10 -17
View File
@@ -4,23 +4,16 @@ blurb:
repo_url: https://git.wait4x.online/wait4x/blog
repo_label: git.wait4x.online/wait4x/blog
blurb_after:
zh: ' —— Astro SSG、双写作流、构建发布全链皆在仓中。以下是我在自托管 gitea 与 GitHub 上的全部公开仓库,以及最近一年的贡献活动。'
en: ' — the Astro SSG, dual-writing workflow, and the full build & deploy pipeline live in the repo. Below are all my public repositories on self-hosted gitea and GitHub, plus contributions from the past year.'
# ---- 项目墙可见性与排序(后台「开源页」可改;留空/缺省 = 现状) ----
# mode: all=全部(默认) | only=仅 include 列出 | exclude=排除 exclude 列出
zh: —— Astro SSG、双写作流、构建发布全链皆在仓中。以下是我在自托管 gitea 与 GitHub 上的全部公开仓库,以及最近一年的贡献活动。
en: — the Astro SSG, dual-writing workflow, and the full build & deploy pipeline live in the repo. Below are all my public repositories on self-hosted gitea and GitHub, plus contributions from the past year.
mode: all
# 白名单(mode=only 时生效)
include: []
# 黑名单(mode=exclude 时生效)
exclude: []
# 排序:pinned-first=置顶优先(默认) | stars=星数降序 | updated=最近更新
sort: pinned-first
# 来源过滤:both=双源合并(默认) | github | gitea
perSource: both
# 开篇来源(compat,**不推荐开启**):off=用本文件 blurb + 原生档案卡(默认)
# github-readme = 构建期取 wait4xx/wait4xx 的 README 原样渲染在档案卡下方
# ⚠ 开启会引入 7 类第三方外链图(readme-typing-svg / shields.io 徽章 / github-readme-stats /
# streak-stats / activity-graph / 贡献蛇 / komarev 访客徽章),慢网或被墙时整片空白;
# 且 README 用 <div align="center"> 居中,本站渲染不认该属性 → 居中失效。内容已由档案卡承接。
perSource: github
intro_from: "off"
# ---- 开篇来源说明(2026-11-02 Phase 5h)----
# 开篇已改原生 GitHub 档案卡(头像 / 统计四格 / 语言占比灰阶条),不再渲染 README 原文。
# intro_from: "off" = 用档案卡 + 上面的 blurb(当前)
# intro_from: github-readme = 构建期取 wait4xx/wait4xx 的 README 原样渲染(**不推荐**:
# 会引入 7 类第三方外链图,慢网或被墙时整片空白;README 用 <div align="center"> 居中,
# 本站不认该属性 → 居中失效。这正是当初"内容没居中、图片不显示"的根因。)
+1 -1
View File
@@ -67,7 +67,7 @@ const L = {
wait4x<span class="pf-handle mono">@wait4xx</span>
</p>
<p class="pf-bio">
{copy.blurb}<a class="pf-link" href={copy.repoUrl}>{copy.repoLabel}</a>{copy.blurbAfter}
{copy.blurb}<a class="pf-link" href={copy.repoUrl}>{copy.repoLabel}</a>{' '}{copy.blurbAfter.trim()}
</p>
<ul class="pf-socials">
{socials.map((s) => (
+4
View File
@@ -73,6 +73,10 @@ try {
.repo {
display: flex;
flex-direction: column;
/* 显式接管交叉轴:全局 .tap 是 inline-flex + align-items:center,
列向 flex 下会把标题/元信息行水平居中(视觉终审 P1,卡片左缘参差) */
align-items: stretch;
text-align: left;
gap: 2px;
padding: var(--space-3);
border: 1px solid var(--line);