Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d096d45c58 | ||
|
|
d6e08a29f9 | ||
|
|
d119d6b555 | ||
|
|
b8c5e1c86e | ||
|
|
2526b98323 | ||
|
|
36643f5cf0 | ||
|
|
52188d5b12 | ||
|
|
fef2de1d37 | ||
|
|
bdaf02f9ca | ||
|
|
cdd9c61641 | ||
|
|
e1fc8bd64c | ||
|
|
cc12e016ab |
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"}
|
||||||
File renamed without changes.
File renamed without changes.
@@ -99,7 +99,7 @@ blocks:
|
|||||||
- label:
|
- label:
|
||||||
zh: 邮件
|
zh: 邮件
|
||||||
en: Email
|
en: Email
|
||||||
href: 'mailto:admin@wait4x.online'
|
href: 'mailto:X@alumni.nudt.edu.cn'
|
||||||
note:
|
note:
|
||||||
zh: 有话直说
|
zh: 有话直说
|
||||||
en: Say hello directly
|
en: Say hello directly
|
||||||
|
|||||||
+10
-36
@@ -1,44 +1,18 @@
|
|||||||
# 主页身份语(后台「页面文案 → 主页设置」可改)
|
|
||||||
# 全部字段留空 = 现有形态(字段级回落默认值,零配置零变化)
|
|
||||||
tagline:
|
tagline:
|
||||||
zh: 写作者 · 读者 · 快门按压者,拥抱开源。
|
zh: 拥抱开源,热爱开源
|
||||||
en: Writer · Reader · Shutter-presser — embracing open source.
|
en: Embracing open source, loving 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
|
|
||||||
favicon: /favicon.svg
|
|
||||||
|
|
||||||
# 社交链接(顺序即展示顺序,后台可增删拖动排序)
|
|
||||||
# icon 取值:github / rss / email / bilibili / x / 留空(留空按 label 显示纯文字)
|
|
||||||
socials:
|
|
||||||
- label: GitHub
|
|
||||||
url: https://github.com/wait4xx
|
|
||||||
icon: github
|
|
||||||
- label: RSS
|
|
||||||
url: /rss.xml
|
|
||||||
icon: rss
|
|
||||||
- label: 邮件
|
|
||||||
url: mailto:admin@wait4x.online
|
|
||||||
icon: email
|
|
||||||
|
|
||||||
# 最新影像张数(1-6,默认 4;填 0 = 隐藏该区块)
|
|
||||||
latestPhotos: 4
|
latestPhotos: 4
|
||||||
|
|
||||||
# 首页每轨文章条数(4-8,默认 6)
|
|
||||||
perTrackLimit: 6
|
perTrackLimit: 6
|
||||||
|
|
||||||
# 区块开关(默认全开;关掉的区块不渲染)
|
|
||||||
sections:
|
sections:
|
||||||
tracks: true
|
tracks: true
|
||||||
photos: true
|
photos: true
|
||||||
heatmap: true
|
heatmap: true
|
||||||
projects: true
|
projects: true
|
||||||
|
favicon: /favicon.svg
|
||||||
|
socials:
|
||||||
|
- label: GitHub
|
||||||
|
url: https://github.com/wait4xx
|
||||||
|
icon: github
|
||||||
|
- label: 邮件
|
||||||
|
url: mailto:X@alumni.nudt.edu.cn
|
||||||
|
icon: email
|
||||||
@@ -4,23 +4,16 @@ blurb:
|
|||||||
repo_url: https://git.wait4x.online/wait4x/blog
|
repo_url: https://git.wait4x.online/wait4x/blog
|
||||||
repo_label: git.wait4x.online/wait4x/blog
|
repo_label: git.wait4x.online/wait4x/blog
|
||||||
blurb_after:
|
blurb_after:
|
||||||
zh: ' —— Astro SSG、双写作流、构建发布全链皆在仓中。以下是我在自托管 gitea 与 GitHub 上的全部公开仓库,以及最近一年的贡献活动。'
|
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.'
|
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 列出
|
|
||||||
mode: all
|
mode: all
|
||||||
# 白名单(mode=only 时生效)
|
|
||||||
include: []
|
|
||||||
# 黑名单(mode=exclude 时生效)
|
|
||||||
exclude: []
|
|
||||||
# 排序:pinned-first=置顶优先(默认) | stars=星数降序 | updated=最近更新
|
|
||||||
sort: pinned-first
|
sort: pinned-first
|
||||||
# 来源过滤:both=双源合并(默认) | github | gitea
|
perSource: github
|
||||||
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"> 居中,本站渲染不认该属性 → 居中失效。内容已由档案卡承接。
|
|
||||||
intro_from: "off"
|
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"> 居中,
|
||||||
|
# 本站不认该属性 → 居中失效。这正是当初"内容没居中、图片不显示"的根因。)
|
||||||
+17
-2
@@ -30,7 +30,8 @@
|
|||||||
|
|
||||||
语义边界(刻意如此,别当 bug 报):
|
语义边界(刻意如此,别当 bug 报):
|
||||||
- **只影响列表顺序**:`pubDate` 不变、URL 不变、RSS 里的时间序列不变,订阅者不会看到时间错乱
|
- **只影响列表顺序**:`pubDate` 不变、URL 不变、RSS 里的时间序列不变,订阅者不会看到时间错乱
|
||||||
- 多篇同时置顶时,置顶组内部仍按日期倒序
|
- **支持多篇/多本同时置顶**:置顶组内部仍按日期倒序;书架页(/books)里每个置顶的书评都会排在前面并**默认展开**
|
||||||
|
- 书架页用「↑ + 横线」的回到顶部图标表示置顶(不写文字),与右侧展开箭头形状不同,不会混读
|
||||||
- 关掉开关立即恢复时间序,没有"冷却期"
|
- 关掉开关立即恢复时间序,没有"冷却期"
|
||||||
|
|
||||||
## 瞬间(5h 起与文章同级)
|
## 瞬间(5h 起与文章同级)
|
||||||
@@ -39,12 +40,26 @@
|
|||||||
|
|
||||||
- markdown:`**加粗**`、`*斜体*`、列表、`> 引用`、`` `行内代码` ``
|
- markdown:`**加粗**`、`*斜体*`、列表、`> 引用`、`` `行内代码` ``
|
||||||
- 排版类 HTML:`<span class="c-blue font-kai">彩色 + 楷体</span>`(可用类清单见写作指南「文章排版类」一节,与文章完全同一份白名单)
|
- 排版类 HTML:`<span class="c-blue font-kai">彩色 + 楷体</span>`(可用类清单见写作指南「文章排版类」一节,与文章完全同一份白名单)
|
||||||
- 仍守外壳灰阶纪律:彩色是**强调**不是装饰,一页 ≤3 处
|
- 彩色**不再限次**(原「≤3 处/页」已取消);仍守外壳灰阶:导航/页脚/按钮/背景不染色
|
||||||
|
|
||||||
**每条瞬间自带评论区**:时间线卡片下方有「评论」折叠条,读者点开才加载评论(不点开不为它付任何加载成本)。中文页与英文页共用同一条评论流,语言切换不会丢评论。
|
**每条瞬间自带评论区**:时间线卡片下方有「评论」折叠条,读者点开才加载评论(不点开不为它付任何加载成本)。中文页与英文页共用同一条评论流,语言切换不会丢评论。
|
||||||
|
|
||||||
**每条的浏览 / 评论数字是只读的**:读者点开评论区不会虚增浏览数(只有整页访问才计一次)。
|
**每条的浏览 / 评论数字是只读的**:读者点开评论区不会虚增浏览数(只有整页访问才计一次)。
|
||||||
|
|
||||||
|
## 照片说明文字(灯箱右侧)支持排版(5i 新增)
|
||||||
|
|
||||||
|
照片的「说明」(caption)现在支持 markdown 与排版类,与文章正文同一套:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
caption: 落日把海与城一齐烫成金箔,**这一帧等了二十分钟**
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<span class="c-blue">蓝色</span>、<span class="font-kai">楷体</span> 这些类都能用。
|
||||||
|
```
|
||||||
|
|
||||||
|
灯箱是深底,颜色类会自动取柔和对暗底的那一档,不会刺眼。EXIF 那几行是相机数据,不做排版。
|
||||||
|
|
||||||
## 照片上传流
|
## 照片上传流
|
||||||
|
|
||||||
1. 图库照片 → New Entry:填标题(**必填**,空标题会让构建炸——实测坑)、选分组(street/landscape)、可写 alt
|
1. 图库照片 → New Entry:填标题(**必填**,空标题会让构建炸——实测坑)、选分组(street/landscape)、可写 alt
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ if (MODE === 'skip') {
|
|||||||
const SKIP_PREFIX = ['/admin/', '/photos-originals/']; // admin=CMS 路由;photos-originals=部署期 rsync 叠加层(不在 dist,另有部署链保障)
|
const SKIP_PREFIX = ['/admin/', '/photos-originals/']; // admin=CMS 路由;photos-originals=部署期 rsync 叠加层(不在 dist,另有部署链保障)
|
||||||
const SKIP_FILE = new Set(['/404.html']); // Astro 404 页不参与配对
|
const SKIP_FILE = new Set(['/404.html']); // Astro 404 页不参与配对
|
||||||
|
|
||||||
|
|
||||||
function walk(dir, out = []) {
|
function walk(dir, out = []) {
|
||||||
for (const e of readdirSync(dir)) {
|
for (const e of readdirSync(dir)) {
|
||||||
const p = join(dir, e);
|
const p = join(dir, e);
|
||||||
@@ -48,8 +49,8 @@ const fails = [];
|
|||||||
const warns = [];
|
const warns = [];
|
||||||
|
|
||||||
for (const f of files) {
|
for (const f of files) {
|
||||||
const html = readFileSync(f, 'utf8');
|
|
||||||
const rel = f.slice(DIST.length) || '/';
|
const rel = f.slice(DIST.length) || '/';
|
||||||
|
const html = readFileSync(f, 'utf8');
|
||||||
|
|
||||||
// 站内 <a href>:仅根相对路径;#锚点/mailto/tel/外部/data: 全跳过
|
// 站内 <a href>:仅根相对路径;#锚点/mailto/tel/外部/data: 全跳过
|
||||||
for (const m of html.matchAll(/<a\s[^>]*href="([^"]*)"/g)) {
|
for (const m of html.matchAll(/<a\s[^>]*href="([^"]*)"/g)) {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const L = {
|
|||||||
wait4x<span class="pf-handle mono">@wait4xx</span>
|
wait4x<span class="pf-handle mono">@wait4xx</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="pf-bio">
|
<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>
|
</p>
|
||||||
<ul class="pf-socials">
|
<ul class="pf-socials">
|
||||||
{socials.map((s) => (
|
{socials.map((s) => (
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ try {
|
|||||||
.repo {
|
.repo {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
/* 显式接管交叉轴:全局 .tap 是 inline-flex + align-items:center,
|
||||||
|
列向 flex 下会把标题/元信息行水平居中(视觉终审 P1,卡片左缘参差) */
|
||||||
|
align-items: stretch;
|
||||||
|
text-align: left;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
padding: var(--space-3);
|
padding: var(--space-3);
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
|
|||||||
@@ -1,74 +1,128 @@
|
|||||||
---
|
---
|
||||||
// 书评索引画廊(/books):色脊排版卡 × 年份分组规整网格
|
/**
|
||||||
// 预研方案 B:色脊天然安全(mood 深浅跨亮暗对比度风险回避),零 JS
|
* 书评索引(/books):方案 C「抽书阅读」(用户 2026-11-03 拍板定稿)。
|
||||||
|
*
|
||||||
|
* 为什么是这一版:五个方案里它是唯一在「书少、封面少」时也不露怯的——
|
||||||
|
* 一排放得下、长书名不裁、没有 4+1 孤儿位;点一行抽出封面与简介,靠原生
|
||||||
|
* details 零 JS。
|
||||||
|
*
|
||||||
|
* 置顶契约(与文章同一套,见 src/lib/post-order.ts):
|
||||||
|
* - frontmatter `pinned: true` → 排在最前(置顶优先 → 日期倒序)
|
||||||
|
* - **支持多本置顶**:所有 pinned 书都默认展开,不限于一本
|
||||||
|
* - 置顶标记用「↑ + 横线」的回到顶部图标,不写文字(用户要求);
|
||||||
|
* 展开/收起是另一个形状的 chevron,避免两个箭头混读
|
||||||
|
*/
|
||||||
import { getCollection } from 'astro:content';
|
import { getCollection } from 'astro:content';
|
||||||
|
import { Image } from 'astro:assets';
|
||||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||||
import { t } from '../../i18n/ui';
|
import { t } from '../../i18n/ui';
|
||||||
import type { Locale } from '../../lib/locale';
|
import type { Locale } from '../../lib/locale';
|
||||||
import { sortPosts } from '../../lib/post-order';
|
import { sortPosts } from '../../lib/post-order';
|
||||||
import { Image } from 'astro:assets';
|
|
||||||
|
|
||||||
interface Props { locale?: Locale }
|
interface Props {
|
||||||
|
locale?: Locale;
|
||||||
|
}
|
||||||
const { locale = 'zh' } = Astro.props;
|
const { locale = 'zh' } = Astro.props;
|
||||||
|
|
||||||
const books = sortPosts(
|
const books = sortPosts(
|
||||||
await getCollection('posts', ({ data }) => !data.draft && data.category === 'reading' && !data.tags.includes('hidden')),
|
await getCollection(
|
||||||
|
'posts',
|
||||||
|
({ data }) => !data.draft && data.category === 'reading' && !data.tags.includes('hidden'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 回退契约(schema 注释声称而此前未实现——视觉复核抓到的缺口):
|
/**
|
||||||
// description 缺省取正文第一个非空段落(去 markdown 记号)前 60 字
|
* description 回退契约:缺省取正文第一个非空段落(去 markdown 记号)前 60 字。
|
||||||
|
* 与历史实现保持一致——书架卡不能出现空白简介。
|
||||||
|
*/
|
||||||
const firstPara = (body: string | undefined): string => {
|
const firstPara = (body: string | undefined): string => {
|
||||||
const line = (body ?? '').split(/\n\s*\n/).map((l) => l.trim()).find((l) => l && !l.startsWith('#') && !l.startsWith('---')) ?? '';
|
const line =
|
||||||
return line.replace(/[*_>`\[\]]/g, '').slice(0, 60);
|
(body ?? '')
|
||||||
|
.split(/\n\s*\n/)
|
||||||
|
.map((l) => l.trim())
|
||||||
|
.find((l) => l && !l.startsWith('#') && !l.startsWith('---')) ?? '';
|
||||||
|
return line.replace(/[*_>`[\]]/g, '').slice(0, 60);
|
||||||
};
|
};
|
||||||
const years = [...new Set(books.map((b) => b.data.pubDate.getFullYear()))].sort((a, b) => b - a);
|
|
||||||
|
const items = books.map((b) => ({
|
||||||
|
id: b.id,
|
||||||
|
title: b.data.title,
|
||||||
|
author: b.data.bookAuthor ?? '',
|
||||||
|
desc: b.data.description ?? firstPara(b.body),
|
||||||
|
cover: b.data.cover,
|
||||||
|
mood: b.data.mood ?? 'var(--ink-4)',
|
||||||
|
pinned: b.data.pinned === true,
|
||||||
|
href: locale === 'en' ? `/en/archives/${b.id}/` : `/archives/${b.id}/`,
|
||||||
|
}));
|
||||||
|
const pinnedCount = items.filter((i) => i.pinned).length;
|
||||||
const L = {
|
const L = {
|
||||||
shelf: locale === 'zh' ? '书架' : 'Books',
|
shelf: t('books_title', locale),
|
||||||
count: (n: number) => (locale === 'zh' ? `${n} 本` : `${n} books`),
|
count: locale === 'zh' ? `${items.length} 本` : `${items.length} books`,
|
||||||
|
note:
|
||||||
|
locale === 'zh'
|
||||||
|
? '点一行展开封面与简介 · 置顶的书默认展开'
|
||||||
|
: 'Tap a row for the cover and blurb · pinned books start open',
|
||||||
|
read: locale === 'zh' ? '读这篇书评 →' : 'Read the review →',
|
||||||
|
pinned: t('pinned_label', locale),
|
||||||
|
expand: locale === 'zh' ? '展开封面与简介' : 'Expand cover and blurb',
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout track="reading" title={`${L.shelf} · wait4x`} description={locale === 'zh' ? '读过的书与一句策展' : 'Books read, one line each'}>
|
<BaseLayout
|
||||||
<h1 class="page-title">{L.shelf}<span class="count mono">{L.count(books.length)}</span></h1>
|
track="reading"
|
||||||
{years.map((year, yi) => (
|
title={`${L.shelf} · wait4x`}
|
||||||
<details class="year-group" open={yi === 0}>
|
description={locale === 'zh' ? '读过的书与一句策展' : 'Books read, one line each'}
|
||||||
<summary class="y-summary">
|
|
||||||
<span class="y-label mono">{year}</span>
|
|
||||||
<span class="y-count mono">· {books.filter((b) => b.data.pubDate.getFullYear() === year).length} {locale === 'zh' ? '本' : 'books'}</span>
|
|
||||||
</summary>
|
|
||||||
<ul class="shelf">
|
|
||||||
{books.filter((b) => b.data.pubDate.getFullYear() === year).map((b) => (
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class={`book ${locale === 'en' ? 'en' : ''}`}
|
|
||||||
href={locale === 'en' ? `/en/archives/${b.id}/` : `/archives/${b.id}/`}
|
|
||||||
style={`--mood:${b.data.mood ?? 'var(--ink-4)'}`}
|
|
||||||
>
|
>
|
||||||
{b.data.cover ? (
|
<h1 class="page-title">
|
||||||
|
{L.shelf}<span class="count mono">{L.count}</span>
|
||||||
|
{pinnedCount > 0 && <span class="pinned-count mono">{pinnedCount} {L.pinned}</span>}
|
||||||
|
</h1>
|
||||||
|
<p class="page-note">{L.note}</p>
|
||||||
|
|
||||||
|
<ul class="books">
|
||||||
|
{items.map((b) => (
|
||||||
|
<li>
|
||||||
|
<details class="book" style={`--mood:${b.mood}`} open={b.pinned}>
|
||||||
|
<summary class="row" aria-label={`${b.title}${b.author ? ' · ' + b.author : ''} — ${L.expand}`}>
|
||||||
|
<span class="bar" aria-hidden="true"></span>
|
||||||
|
<span class="title">{b.title}</span>
|
||||||
|
{b.pinned && (
|
||||||
|
<span class="pin" title={L.pinned} role="img" aria-label={L.pinned}>
|
||||||
|
{/* 回到顶部图标(↑ + 横线):不写文字,形状与右侧 chevron 区分 */}
|
||||||
|
<svg viewBox="0 0 16 16" width="13" height="13" aria-hidden="true">
|
||||||
|
<path d="M8 12.6V4.2M4.4 7.6 8 4l3.6 3.6" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M3.6 13.6h8.8" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{b.author && <span class="author">{b.author}</span>}
|
||||||
|
<span class="chev" aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 16 16" width="14" height="14">
|
||||||
|
<path d="M4 6.4 8 10.4l4-4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</summary>
|
||||||
|
<div class="body">
|
||||||
|
{b.cover && (
|
||||||
|
<span class="cover">
|
||||||
<Image
|
<Image
|
||||||
src={b.data.cover}
|
src={b.cover}
|
||||||
alt={`${b.data.title} 封面`}
|
alt={`${b.title}${locale === 'zh' ? ' 封面' : ' cover'}`}
|
||||||
class="bk-cover"
|
widths={[120, 240]}
|
||||||
widths={[96, 192]}
|
sizes="120px"
|
||||||
sizes="96px"
|
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
) : (
|
</span>
|
||||||
<i class="spine" aria-hidden="true"></i>
|
|
||||||
)}
|
|
||||||
<div class="bk-body">
|
|
||||||
<strong class="bk-title">{b.data.title}</strong>
|
|
||||||
{b.data.bookAuthor && <span class="bk-author">{b.data.bookAuthor}</span>}
|
|
||||||
{(b.data.description || firstPara(b.body)) && (
|
|
||||||
<span class="bk-desc">{b.data.description ?? firstPara(b.body)}</span>
|
|
||||||
)}
|
)}
|
||||||
|
<div class="info">
|
||||||
|
{b.desc && <p>{b.desc}</p>}
|
||||||
|
<a class="link" href={b.href}>{L.read}</a>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</div>
|
||||||
|
</details>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
|
||||||
))}
|
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -78,97 +132,101 @@ const L = {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: var(--space-3);
|
gap: var(--space-3);
|
||||||
|
margin-top: var(--space-5);
|
||||||
}
|
}
|
||||||
.count { font-size: 13px; color: var(--ink-3); }
|
.count { font-size: 13px; color: var(--ink-3); }
|
||||||
.year-group { margin-top: var(--space-4); border-top: 1px solid var(--line); }
|
.pinned-count { font-size: 11.5px; color: var(--ink-4); }
|
||||||
.y-summary {
|
.page-note { font-size: 13px; color: var(--ink-4); margin-block: var(--space-1) var(--space-4); }
|
||||||
|
|
||||||
|
.books { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; }
|
||||||
|
.book {
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: border-color var(--dur) var(--ease);
|
||||||
|
}
|
||||||
|
.book[open] { border-color: color-mix(in oklab, var(--mood) 42%, var(--line)); }
|
||||||
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: center;
|
||||||
gap: 0.4rem;
|
gap: var(--space-3);
|
||||||
padding: var(--space-2) 0;
|
padding: 10px var(--space-3);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
transition: background var(--dur) var(--ease);
|
||||||
}
|
}
|
||||||
.y-summary::-webkit-details-marker { display: none; }
|
.row::-webkit-details-marker { display: none; }
|
||||||
.y-summary::before {
|
.row:hover { background: var(--bg-soft); }
|
||||||
content: '▸';
|
/* 情绪色脊:贯通行的窄条(不是表单色标) */
|
||||||
font-size: 11px;
|
.bar {
|
||||||
color: var(--ink-4);
|
width: 8px;
|
||||||
transition: transform var(--dur) var(--ease);
|
|
||||||
transform-origin: 50% 50%;
|
|
||||||
display: inline-block;
|
|
||||||
width: 1em;
|
|
||||||
}
|
|
||||||
.year-group[open] > .y-summary::before { transform: rotate(90deg); }
|
|
||||||
.y-summary:hover .y-label { color: var(--ink-2); }
|
|
||||||
.y-count { font-size: 12px; color: var(--ink-4); }
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
.y-summary::before { transition: none; }
|
|
||||||
}
|
|
||||||
.y-label { font-size: 16px; color: var(--ink-3); margin-bottom: 0; transition: color var(--dur) var(--ease); }
|
|
||||||
.shelf {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
/* 色脊卡:纸底 + mood 竖脊 + 文楷书名;hover 边框转 mood(.repo 同语言) */
|
|
||||||
.book {
|
|
||||||
display: flex;
|
|
||||||
min-height: 120px;
|
|
||||||
background: var(--paper);
|
|
||||||
border: 1px solid var(--paper-line);
|
|
||||||
border-radius: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
|
|
||||||
}
|
|
||||||
.book:hover { border-color: var(--mood); transform: translateY(-2px); }
|
|
||||||
/* 书封(content/posts/assets/books/<slug>.jpg):无图时回退色脊卡设计 */
|
|
||||||
.bk-cover {
|
|
||||||
width: 96px;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
flex: none;
|
margin: 2px 0;
|
||||||
border-right: 1px solid var(--paper-line);
|
border-radius: 4px;
|
||||||
}
|
|
||||||
.spine {
|
|
||||||
flex: none;
|
|
||||||
width: 10px;
|
|
||||||
background: var(--mood);
|
background: var(--mood);
|
||||||
border-radius: 10px 0 0 10px;
|
flex: none;
|
||||||
}
|
}
|
||||||
.bk-body {
|
.title {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 3px;
|
|
||||||
padding: var(--space-3) var(--space-4);
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
.bk-title {
|
|
||||||
font-family: var(--font-kai);
|
font-family: var(--font-kai);
|
||||||
font-size: 17px;
|
font-size: 15.5px;
|
||||||
color: var(--paper-ink);
|
color: var(--paper-ink);
|
||||||
line-height: 1.35;
|
line-height: 1.4;
|
||||||
}
|
/* 定宽列:作者起点不随书名长短漂移 */
|
||||||
.en .bk-title { font-family: var(--font-serif); }
|
width: 11em;
|
||||||
.bk-author {
|
flex: none;
|
||||||
font-size: 12.5px;
|
|
||||||
color: var(--ink-3);
|
|
||||||
font-family: var(--font-sans);
|
|
||||||
}
|
|
||||||
.bk-desc {
|
|
||||||
margin-top: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--ink-2);
|
|
||||||
font-family: var(--font-sans);
|
|
||||||
line-height: 1.5;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 3;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.pin {
|
||||||
|
display: inline-flex;
|
||||||
|
color: color-mix(in oklab, var(--mood) 62%, var(--ink-3));
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
.author { font-size: 12.5px; color: var(--ink-3); }
|
||||||
|
.author::before { content: '·'; margin-right: 6px; opacity: 0.5; }
|
||||||
|
.chev {
|
||||||
|
margin-left: auto;
|
||||||
|
display: inline-flex;
|
||||||
|
color: var(--ink-4);
|
||||||
|
transition: rotate var(--dur) var(--ease), color var(--dur) var(--ease);
|
||||||
|
}
|
||||||
|
.row:hover .chev { color: var(--ink-2); }
|
||||||
|
/* 展开时 chevron 转成向上,和左侧「回到顶部」图标形状不同,不会混读 */
|
||||||
|
details[open] > .row .chev { rotate: 180deg; }
|
||||||
|
|
||||||
|
.body {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-3);
|
||||||
|
padding: var(--space-3);
|
||||||
|
border-top: 1px dashed var(--line);
|
||||||
|
background: var(--bg-soft);
|
||||||
|
}
|
||||||
|
.cover { flex: none; width: 96px; border-radius: 4px; overflow: hidden; }
|
||||||
|
.cover :global(img) { width: 100%; height: auto; display: block; }
|
||||||
|
.info { min-width: 0; }
|
||||||
|
.info p {
|
||||||
|
font-size: 13.5px;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--ink-2);
|
||||||
|
margin: 0 0 var(--space-2);
|
||||||
|
max-width: var(--measure);
|
||||||
|
}
|
||||||
|
.link {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--accent);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-color: color-mix(in oklab, var(--accent) 35%, transparent);
|
||||||
|
text-underline-offset: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 620px) {
|
||||||
|
.title { width: auto; flex: 1 1 auto; min-width: 0; }
|
||||||
|
.author { display: none; }
|
||||||
|
.body { flex-direction: column; }
|
||||||
|
.cover { width: 88px; }
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.book, .row, .chev { transition: none; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -113,6 +113,7 @@ const dict = {
|
|||||||
// ===== F 车道:访问量小字(Artalk pv,组件内独立计数) =====
|
// ===== F 车道:访问量小字(Artalk pv,组件内独立计数) =====
|
||||||
pv_viewed: { zh: '人看过', en: 'views' },
|
pv_viewed: { zh: '人看过', en: 'views' },
|
||||||
pinned_label: { zh: '置顶', en: 'Pinned' },
|
pinned_label: { zh: '置顶', en: 'Pinned' },
|
||||||
|
books_title: { zh: '书架', en: 'Books' },
|
||||||
comment_count: { zh: '条评论', en: 'comments' },
|
comment_count: { zh: '条评论', en: 'comments' },
|
||||||
moment_comments: { zh: '评论', en: 'Comments' },
|
moment_comments: { zh: '评论', en: 'Comments' },
|
||||||
lb_hint: { zh: '滚轮缩放 · 双击放大 · Esc 关闭', en: 'Wheel to zoom · Double-click · Esc' },
|
lb_hint: { zh: '滚轮缩放 · 双击放大 · Esc 关闭', en: 'Wheel to zoom · Double-click · Esc' },
|
||||||
|
|||||||
Reference in new issue
Block a user