Nanolog
Like microblog, To log in Site Dev
- 13 July 2026, 01:30 (CST) ReDeplogEdit Post
2026年07月12日 17:30(东八区 / 北京时间)
热力图色差调整 · 文章页音乐播放器 · 进度条本地 seek 根因
概述
本轮三件事:归档/文章页热力图色阶分离、文章页可选音乐播放器(FLAC/MP3 + LRC)、本地
zola serve下进度条无法跳转的根因与修复。日常构建流程(zola build/zola serve/./dev.sh/./build-site.sh)未改;CI 无需改动。1. 热力图色差调整
1.1 目标
- 归档页(
/archive/):沿用 GitHub 贡献图 绿色 四档色阶,空格子与 L1 对比清晰。 - 文章页(右上角固定挂件):使用 紫色 四档色阶,与全站 accent 一致,避免与归档页混淆。
1.2 实现
场景 CSS 类 文件 归档 .blog-heatmap--archivestatic/css/heatmap.css文章 .blog-heatmap--article同上 色阶变量(浅色模式示例):
档位 归档(绿) 文章(紫) empty #ebedf0#ebedf0L1 #9be9a8#e9d5ffL2 #40c463#c084fcL3 #30a14e#9333eaL4 #216e39#6b21a8深色模式在
@media (prefers-color-scheme: dark)下各有一套对应值。文章页热力图与音乐播放器叠放在
.article-widgets-fixed(templates/article.html),固定于右上角,移动端改到底部右侧。2. 音乐播放器:设计思路
2.1 产品行为
项 说明 启用粒度 全站 zola.toml开关 + 单篇文章 front matter默认态 仅显示大号播放按钮;悬停/聚焦展开元信息、歌词、控制条 音源 static/music/下歌手-歌名.flac或.mp3,优先 MP3歌词 同名 .lrc,UTF-8 / GB18030 自动识别;卡拉 OK + 横向滚动元数据 文件名 歌手-歌名+ LRC[ti:]/[ar:],不用 ID3 标签库音量 点击循环:25% → 50% → 75% → 100% → 静音;喇叭图标自下而上填充 进度条 细轨道 + 圆点滑块;点击/拖动任意位置跳转 循环 默认关;图标 arrow-clockwise/repeat多曲 tracks多于 1 首时显示随机下一首Safari 检测后整组件移除(FLAC / seek 兼容性差) 2.2 文件结构
zola.toml # [extra.music_player] 全站开关 templates/article.html # .article-widgets-fixed 挂载热力图 + 播放器 templates/partials/music_player.html # 挂件 markup + data-tracks JSON static/css/music-player.css # 三行布局:meta / lyric / bar static/js/music-player.js # 播放、LRC、seek、音量、Blob 兜底 static/music/ # 音频与 LRC(构建时原样拷贝到 public/music/)2.3 单篇启用示例
[extra.music_player] enabled = true tracks = [ { file = "庄心妍-繁星点点" }, { file = "周杰伦-青花瓷" }, ]测试文章:
content/01Write_blog_CMake/2026-07-12-Libs-Manager/index.md。2.4 关键代码细节
模板:
data-tracks注入曲目列表;data-base为/music(可配base_url)。resolveAudio():HEAD 探测,优先 MP3,其次 FLAC。歌词:
parseLrc()解析时间轴;isMetaLyric()过滤作词作曲等元信息行;syncLyric()按timeupdate切换行并用clip-path做逐字高亮。进度条:不用
<input type="range">(会被主题全局 range 样式覆盖成粗条+白块)。改为div轨道 +--progress-pctCSS 变量 +pointerdown/move/up计算clientX比例后设audio.currentTime。音量:
VOLUME_LEVELS = [0.25, 0.5, 0.75, 1, 0],clip-path: inset(...)在喇叭图标上显示填充比例。3. 本地无法拖动:根因分析
3.1 现象
在本地
zola serve下,点击或拖动进度条后,播放位置回到 00:00 附近(像「从头重播」),而非跳到指定时间。3.2 复现数据(Chrome 自动化)
环境 audio.seekable.end设 currentTime = 50%后zola serve0 4.73s → 0.23s 支持 Range 的静态服务 255.49(全长) 正常跳到 118.6s 3.3 根因
不是进度条 UI 坐标算错,而是 HTML5 音频 seek 依赖 HTTP
Accept-Ranges: bytes:- 浏览器需对音频 URL 发 Range 分段请求 才能建立可 seek 区间;
zola serve不返回Accept-Ranges,curl -H "Range: bytes=0-1023"仍得200而非206;- 此时
audio.seekable为空,设置currentTime无效,位置回到 0 附近。
线上 GitHub Pages 支持 Range,部署后(且
static/music/已发布)应能直接拖动,无需播完整首。3.4 修复方案
层级 方案 说明 播放器 JS ensureSeekable()Blob 兜底首次点击进度条时 fetch整首音频为 Blob URL,再 seek;不必播完一整首,但大 FLAC 首次可能需等待下载本地可选 scripts/serve-with-ranges.mjs带 byte-range 的静态服务,用于本地立刻验证 seek 日常流程 保持 ./dev.sh→zola serve不强制改用户习惯 CI / 部署 不改 deploy_pages.yml仍 ./build-site.shdev.sh已恢复为:node scripts/encrypt-content.mjs exec zola serve "$@"4. 本地 / 部署命令对照
场景 命令 进度条 seek 日常预览 zola build→zola serve首次拖可能等 Blob 下载;之后正常 加密文章开发 ./dev.sh同上 正式构建 / CI ./build-site.sh构建产物;线上 GitHub Pages 可直接 seek 本地想立刻拖 见下方两行 与线上一致,无需等 Blob 本地立刻可 seek(可选,不影响日常):
zola build --base-url http://127.0.0.1:1111/ node scripts/serve-with-ranges.mjs --no-watch -p 1111浏览器打开
http://127.0.0.1:1111/。--base-url仅修正本地资源链接,seek 能力来自serve-with-ranges.mjs。5. 部署注意
- 音乐文件须纳入仓库
static/music/,随./build-site.sh进入public/music/。 - 当前若线上
/music/...为 404,播放器无法加载音频;推送含音乐的构建后即可。 - Workflow 无需修改。
6. 相关文档
- 用法速查已写入 @/03Share_blog/2026-06-22-zola-template-markdown-guide/index.md §8.1 音乐播放器、§8.2 构建命令对照。
- 归档页(
- 25 June 2026, 04:00 (CST) ReDeplogEdit Post
2026年06月24日 20:00(东八区 / 北京时间)
文章加密模块重构 · 全量同步 · RSS/Atom 过滤
概述
加密功能原先与 Zola 构建耦合过紧:模板在
zola build阶段用load_data()读取static/encryption/pages/*.json,若密文尚未生成(例如首次给文章加上encrypt = true后直接跑zola build),会报错Could not find or open file encryption/pages/....json。本轮重构目标:像
tags、generate_feeds、scripts一样——在文章 front matter 里声明即可;构建脚本负责全量同步密文;订阅源与搜索索引自动排除加密正文。1. 新架构
content/**/*.md [extra.encryption] encrypt = true ↓ ① scripts/encrypt-content.mjs 全量扫描 → 全量重加密 → 删除多余 JSON ↓ ② zola build 模板不再 load_data,运行时 fetch 密文 ↓ ③ scripts/post-build.mjs 从 RSS/Atom + 搜索索引剔除加密文章 ↓ public/ 静态站点阶段 脚本 职责 构建前 encrypt-content.mjs扫描 content/,对所有encrypt = true的文章重新加密(不论是否改过正文);取消加密的文章对应 JSON 从static/encryption/pages/删除构建 zola build加密页渲染锁屏 UI;正文由浏览器 article.js按管理员/访客规则 fetch 解密构建后 post-build.mjs扫描 public/中含article-encrypted的页面,从 Atom + RSS 及 search_index 中移除对应条目共享逻辑集中在
scripts/encryption-lib.mjs(扫描、路径映射、feed/XML 过滤)。2. 使用方式
2.1 启用加密(任意文章)
在 front matter 增加:
[extra.encryption] encrypt = true无需预先创建 JSON 文件,也无需改模板。
2.2 生产构建
./build-site.sh # 等价于: # node scripts/encrypt-content.mjs # zola build # node scripts/post-build.mjs # node scripts/verify-kanban-build.mjsCI(
.github/workflows/deploy_pages.yml)同样调用./build-site.sh --output-dir ../public_html。2.3 本地开发
场景 命令 说明 新增或修改加密文章 ./dev.sh先跑 encrypt-content.mjs生成/更新密文,再zola serve无加密相关改动 zola build/zola serve足够;密文已在 static/encryption/pages/中,无需重复加密要点:只有当你新增加密文章、或改了某篇加密文章的正文/front matter 时,本地需先执行
./dev.sh(或单独node scripts/encrypt-content.mjs)。若本次会话没有动过加密配置,日常改样式/改非加密文章,直接zola serve即可。./dev.sh源码:node scripts/encrypt-content.mjs exec zola serve "$@"3. 主要改动
文件 改动 scripts/encryption-lib.mjs共享:扫描 encrypt=true、全量 sync、收集加密 URL、strip feed/searchscripts/encrypt-content.mjs每次构建清空 pages/后重建;更新manifest.jsonscripts/post-build.mjs新增:构建后过滤 RSS/Atom 与搜索索引 scripts/patch-search-index.mjs弃用,转发至 post-build.mjstemplates/partials/encrypted_article.html移除 load_data(),仅保留data-payload-url运行时加载build-site.sh接入 post-build.mjs;修复无参数时ZOLA_ARGS未绑定dev.sh新增:本地开发入口(加密同步 + serve) 4. RSS / Atom 过滤加密内容
问题:Zola 生成订阅源时直接序列化 Markdown 正文,加密文章虽在 HTML 页显示锁屏,但 Atom/RSS 仍会泄露全文。
处理:
post-build.mjs在构建完成后:- 遍历
public/**/index.html,识别含article-encrypted的页面 URL; - 递归扫描所有
atom.xml/rss.xml; - 删除链接到上述 URL 的
<entry>(Atom)与<item>(RSS)块。
已验证:
02Engineer_blog_Debug分区 feed 中,deny-website-littlesnitch、chrome-reopen等加密条目构建后不再出现。搜索索引沿用同一 URL 列表,由
post-build.mjs一并 patch(原patch-search-index.mjs逻辑合并)。5. 触发案例
02Engineer_blog_Debug/2026-06-20-Deny-WebSite-LittleSnitch首次添加[extra.encryption] encrypt = true后直接zola build,曾报:Could not find or open file encryption/pages/02Engineer_blog_Debug/2026-06-20-Deny-WebSite-LittleSnitch.json重构后:运行
./dev.sh或./build-site.sh即可自动生成密文;单独zola build不再因load_data失败,但新增加密页时仍需先同步密文(见 §2.3)。6. 当前已加密文章(构建快照)
文章 密文路径 00Read_blog_Math/2026-06-03-First Base Chaterstatic/encryption/pages/00Read_blog_Math/2026-06-03-First Base Chater.json02Engineer_blog_Debug/2026-06-20-Deny-WebSite-LittleSnitch.../2026-06-20-Deny-WebSite-LittleSnitch.json02Engineer_blog_Debug/2026-06-23-Chrome-ReOpen.../2026-06-23-Chrome-ReOpen.json清单以
static/encryption/manifest.json为准;下次构建会全量刷新。 - 遍历
- 24 June 2026, 22:00 (CST) ReDeplogEdit Post
2026年06月24日 09:40(东八区 / 北京时间)
看板线上缺失排查 · Ametrine 子模块更新 · 新文章卡片样式
概述
本轮三件事:周计划看板本地/线上一致性排查、Ametrine 主题子模块更新到
6d1c244(New article card design)、Debug 专栏应用两种文章卡片样式。看板本地可用zola build/zola serve;正式部署推荐./build-site.sh(含看板产物校验)。1. 看板列表仅显示 1 张卡片
1.1 问题
环境 /kanban/列表/kanban/2026-06-16/明细本地 public/2 张卡片 可打开 线上 gh-pages 1 张卡片 404 1.2 排查流程(源码 → 构建)
阶段 A:源码
检查项 本地 00BlogZolaCodeberg content/kanban/2026-06-16.md✓ ✓ 2026-06-22.md✓ ✓ week_start/week_end均已配置 一致 结论:源码两侧一致,问题不在 Markdown 缺失。
阶段 B:构建产物
检查项 本地 public/kanban/GitHub gh-pages/kanban/index.html中.kanban-week-card2 1 data-json热力图条目2 条 1 条 2026-06-16/index.html✓ 存在 不存在 2026-06-22/index.html✓ ✓ 结论:线上 gh-pages 是旧/不完整部署,并非前端 JS 把第二张卡片藏起来——HTML 里根本没有第二张卡片,明细页目录也未生成,手动输入 URL 必然 404。
1.3 根因
线上 gh-pages 某次部署产物不完整(缺少
2026-06-16/目录与列表第二张卡片),与本地是否使用./build-site.sh无直接关系——GitHub Actions 同样只跑zola build,看板理论上应能完整生成。部署流水线原先缺少 kanban 产物校验,异常未能被及时发现。1.4 修复
文件 改动 scripts/verify-kanban-build.mjs对比 content/kanban/20*.md数量与public/kanban/*/index.html、列表卡片数build-site.sh构建末尾调用 verify .github/workflows/deploy_pages.yml改用 ./build-site.sh+ submodule init + verify重新部署后(GitHub → Actions →
Build Zola and Deploy to GitHub Pages→ Run workflow),线上应出现 2 张卡片且/kanban/2026-06-16/可访问。1.5 补充:本地为何只用
zola build/zola serve就能完整实现看板?日常开发若只用
zola build、zola serve,不主动跑./build-site.sh,看板依然完整——这是预期行为,因为看板整条链路都在 Zola 原生构建内,不依赖build-site.sh额外步骤。zola build已覆盖看板所需:content/kanban/*.md ↓ Zola 读取 front matter(week_start、stats…) templates/kanban_list.html / kanban.html ↓ load_data 内嵌原始 Markdown 到 HTML static/js/kanban-*.js ↓ 浏览器解析、渲染热力图 / Trello 看板 public/kanban/列表页与明细页模板在构建时用
load_data把 Markdown 写进 HTML(无需static/kanban/副本):templates/kanban_list.html— 每张周卡片内嵌<textarea class="kanban-raw-source">templates/kanban.html— 明细页#kanban-raw-markdown
只要
content/kanban/下有带week_start的.md,zola build就会生成对应页面与列表卡片;zola serve仅本地预览public/。build-site.sh在四步中,看板只依赖第 ② 步:步骤 脚本 作用 看板是否需要 ① encrypt-content.mjs为 [extra.encryption] encrypt = true的文章生成static/encryption/pages/*.json否 — kanban 未开加密 ② zola build生成全部静态页 是 — 看板全靠这步 ③ patch-search-index.mjs修补 elasticlunr 搜索索引 否 ④ verify-kanban-build.mjs对比源码周数与构建卡片数 否 — 仅部署前防回归 何时才需要
./build-site.sh?场景 推荐命令 本地调试看板、普通文章 zola serve(或先zola build)本地调试加密文章详情 需先跑 ①,或直接 ./build-site.sh正式部署前 ./build-site.sh(加密 + 搜索 + 看板校验)与「线上少一张看板」的关系(再强调):
本地 zola build线上 gh-pages(问题当时) 源码 2 个 kanban .mdCodeberg 同样 2 个 ✓ 产物 public/kanban/含 2026-06-16 + 2026-06-22仅 2026-06-22,2026-06-16 目录缺失 结论:看板 = Zola 模板 + content + static JS,
zola build已足够;build-site.sh是站点其他能力(加密、搜索、部署校验)的包装,不是看板运行的前提。 线上问题来自 gh-pages 部署产物不完整,而非本地少用了build-site.sh。2. Ametrine 子模块更新
cd themes/ametrine git fetch origin main git checkout main && git pull # 父仓库记录新 commit git add themes/ametrine项目 值 远程 codeberg.org/daudix/ametrine 目标 commit 6d1c244— New article card design参考效果 daudix.one/blog 主要变化:
templates/partials/article_list.html卡片布局(banner 缩略图置顶)、article_details.html元数据分行、_article-list.scss渐变/accent 视觉。3. 两种文章卡片样式如何引用
Ametrine 通过 front matter 组合决定卡片形态(与 daudix 博客 一致):
样式 A — 带横幅图(
has-banner+has-accent-color)列表卡片顶部有大图;明细页开头由
base.html的#banner渲染同目录图片。[extra] accent_color = ["hsl(210 25% 34%)", "hsl(210 31% 53%)"] # 浅色 / 深色各一组 HSL banner = "banner.jpg" # 与 index.md 同目录 banner_position = "50% 40%" # 可选,缩略图裁剪焦点- 图片放在文章文件夹内,如
content/…/my-post/banner.jpg - 构建时 Zola
resize_image自动生成 WebP 缩略图
本站示例(Debug 专栏):
文章 目录 Mac Chrome ReOpen 02Engineer_blog_Debug/2026-06-23-Chrome-ReOpen/VPN 断网排查 02Engineer_blog_Debug/2026-06-20-VPN-noNet/样式 B — 纯 accent 渐变(
has-accent-color,无 banner)无列表缩略图;可展示 发布日 + 更新日 + 作者 等元数据行。
updated = 2026-06-21 # 与 date 不同则显示「更新」图标 authors = ["SuchaharCan"] # 可选,显示 By … [extra] accent_color = ["hsl(145 22% 34%)", "hsl(145 28% 50%)"] # 不写 banner本站示例:
文章 特征 Little Snitch 教程 仅 accent + updatedOne (Teardown) accent + authors明细页横幅
只要设置了
banner,列表与明细共用同一字段;明细页无需额外模板,主题base.html自动在正文前插入#banner大图(与 daudix 一致)。accent_color 格式
- 推荐:
["hsl(H S% L%)", "hsl(H S% L%)"]— 分别为浅色/深色模式 - 也支持单字符串
"hsl(270 50% 60%)"
4. 本地验证
看板调试可直接:
zola build && zola serve正式部署或需加密/搜索/校验时:
./build-site.sh # 期望输出:kanban verify OK: 2 week(s), list cards match页面 检查 /kanban/2026 年 6 月分组下 2 张卡片 /kanban/2026-06-16/Trello 五列看板 /02Engineer_blog_Debug/2 张带图卡片 + 2 张纯渐变卡片 /02Engineer_blog_Debug/chrome-reopen/顶部 banner 大图 相关链接:看板列表 · Debug 专栏 · Ametrine 主题 · daudix 博客卡片参考
5. 看板列表卡片 UI · 热力图「今天 / 本周」标记
5.1 看板周卡片(列表页)
需求: 元数据参考 Ametrine 文章详情图标盒式风格;标题以下第二、三行加粗并居中;字号随卡片高度变化;天数跨度与卡片高度的视觉区分需更明显。
模板结构(
templates/kanban_list.html):h3 标题(左对齐 + accent 竖线) └─ .kanban-week-body(居中容器) ├─ .kanban-week-meta-row 日期 / 剩余 / 进度 / 星级 └─ .kanban-week-stats 共 N 项 · 已完成 · 待办 · 进行中 └─ .kanban-week-span-spacer (flex 占位,不再重复叠加高度)样式要点(
sass/kanban/style.scss):项 实现 图标 恢复 Ametrine .icon盒式:box-shadow+ 圆角背景 +accent-color元数据加粗 .kanban-week-meta-row、.kanban-week-stats→font-weight: 600居中 .kanban-week-body+justify-content: center字号联动 font-size: calc(0.78rem × var(--kanban-meta-scale)),图标同理卡片高度 单一变量 --kanban-card-body-height,去掉「基础高度 + spacer 再叠一层」高度 / 字号映射(SSR 与 JS 共用同一公式,
static/js/kanban-rules.js→applyListCardMetrics):--kanban-card-body-height = 88px + 280px × (span_days / 7) --kanban-meta-scale = 0.85 + 0.35 × (span_days / 7)看板 跨度 卡片高度 meta-scale 2026-06-22 2 天 168px 0.95 2026-06-16 7 天 368px 1.20 kanban-list.js与kanban-heatmap.js筛选后均调用KanbanRules.applyListCardMetrics(),避免两套算法不一致。CSS 变量(
:root):--kanban-week-body-min: 88px; --kanban-week-span-height: 280px;若需进一步拉大/缩小高度差,优先调
--kanban-week-span-height。5.2 热力图「今天 / 本周」标记
需求: 全年视图(周格子)与单月视图(天格子)下方,用空心三角标出当前周或当天;时区与站点一致;不破坏现有热力图样式。
时区: 读取
#kanban-week-list的data-timezone(来自zola.toml→extra.timezone,当前Asia/Shanghai),复用KanbanRules.clockInTimezone。显示规则:
视图 标记位置 显示条件 全年(周格) 对应周格子下方 所选年份 = 今年,且该周包含今天 单月(天格) 对应天格子下方 所选年/月 = 当前年/月,且该格 = 今天 DOM 结构:
.kanban-heatmap-week-slot / .kanban-heatmap-day-slot ├─ button.heatmap-week-cell / .heatmap-day-cell └─ span.kanban-heatmap-today-marker ← 仅 .is-current 时可见样式(
static/css/heatmap.css,仅作用于 Kanban 热力图):- 空心三角:
::before描边 +::after内层--bg-muted-1镂空,尖端朝上指向格子 - 非当前格不预留占位,避免整行高度被撑开
涉及文件:
文件 改动 static/js/kanban-heatmap.jsgetTodayContext、wrapWeekCell、wrapDayCellstatic/css/heatmap.css.kanban-heatmap-today-marker及 slot 布局5.3 本地验证(看板 UI + 热力图)
页面 检查 /kanban/首次打开年份 = 当前年、月份 = 当前月(日视图 + 当月卡片) /kanban/全年6 月对应周格下方有空心上三角;2 天 / 7 天卡片高度差明显 /kanban/选 6 月24 日格下方有标记;元数据两行居中加粗 切换年份 非当前年不显示周标记 zola build && zola serve # 打开 http://127.0.0.1:1111/kanban/5.4 热力图默认选中当前年 / 当前月
需求: 进入
/kanban/时,右上角年份、月份下拉不再默认「最近有数据的年份 + 全年」,而是直接落在当前年、当前月(按站点时区),省去手动切换。默认逻辑(
static/js/kanban-heatmap.js→init()):var todayCtx = getTodayContextsiteTimezone; var activeYear = years.indexOftodayCtx.year >= 0 ? todayCtx.year : years0; var activeMonth = activeYear === todayCtx.year ? todayCtx.month : 0;情况 年份 月份 当前年有看板数据 当前年 当前月(日视图热力图 + 当月卡片列表) 当前年无数据,回退到最近年份 years[0]0(全年)时区: 与 §5.2 相同,读
#kanban-week-list的data-timezone(zola.toml→extra.timezone)。未改动的交互: 用户手动切换年份时,月份仍会重置为「全年」(原有行为);仅首次加载默认当前年/月。
验证: 刷新
/kanban/,右上角应显示「年份: 2026」「月份: 6 月」,热力图为按天网格,下方列表为 6 月卡片,无需再点选月份。最后补充: 优先 使用 Codeberg中的 workflow.此处是 第一源 ,同步给 github
- 24 June 2026, 18:00 (CST) ReDeplogEdit Post
2026年06月24日 10:11(东八区 / 北京时间)
GitHub Pages 部署流水线 ENAMETOOLONG · 看板 Markdown 误为 symlink
概述
SuchaharCan.github.io Actions #28 在 Init theme submodule and build 阶段失败:
encrypt-content.mjs遍历content/时对content/kanban/2026-06-16.md调用statSync抛出ENAMETOOLONG。本地 macOS 复现困难,Linux CI 必现。根因:该文件在 Git 索引中被误记为 symlink(mode
120000),但 blob 内容是整篇 Markdown;Linux 检出后符号链接目标 ≈ 2500 字符的「伪路径」,stat解析失败。附带修复了build-site.sh与 CI 验证路径问题。1. 现象
1.1 CI 报错摘要
Error: ENAMETOOLONG: name too long, stat '.../zola_source/content/kanban/2026-06-16.md' at walkMd (scripts/encrypt-content.mjs:52) at main (scripts/encrypt-content.mjs:81)流水线:deploy_pages.yml — Codeberg 拉源码 →
./build-site.sh --output-dir ../public_html→ 首步即node scripts/encrypt-content.mjs。1.2 为何本地未报错
环境 2026-06-16.md磁盘形态encrypt-content.mjs行为本地 macOS 普通文件 -rw-r--r--stat正常Linux CI Git 检出为 symlink stat跟随链接 → 目标为整段 Markdown →ENAMETOOLONG表面看报错路径长度正常(约 100 字符),容易误判为路径拼接 bug;需结合 Git 对象 mode 才能定位。
2. 根因定位(思考链)
2.1 排除项
假设 结论 import.meta.url.pathname在 Linux 上算错 ROOT可能改进,但无法解释仅 单个 kanban 文件 失败 content/kanban/存在目录级 symlink 循环本地 find -type l无异常;问题在 单文件 modekanban 需加密导致读文件失败 kanban 未开 [extra.encryption];失败发生在 walk 阶段,尚未读内容2.2 关键命令
git ls-files -s content/kanban/ # 120000 71584b78... content/kanban/2026-06-16.md ← symlink mode # 100644 18e34c47... content/kanban/2026-06-22.md ← 正常文件- Git mode
120000= symlink;blob 内本应只存 目标路径字符串 - 实际 blob 大小 2526 字节,内容为
+++开头的完整周计划 Markdown - Linux
git clone按 symlink 检出 → 链接目标 = 整篇文档文本 →statSync/readlink解析时触发ENAMETOOLONG
2.3 成因推测
某次提交或合并时,该文件被错误标记为 symlink(可能来自错误
git add、工具导入或复制粘贴异常),而 blob 仍写入 Markdown 正文。macOS 工作区可能曾被手动覆盖为普通文件,故与 CI 表现不一致。2.4 附带问题(修复 CI 全流程时发现)
问题 说明 build-site.sh未导出ZOLA_OUTPUT_DIR./build-site.sh --output-dir ../public_html时,patch-search-index.mjs/verify-kanban-build.mjs仍读public/workflow 验证路径错误 构建输出在 ../public_html,步骤却检查zola_source/public_html3. 修复内容
文件 改动 content/kanban/2026-06-16.mdgit rm --cached后重新git add,索引 mode100644(普通文件)scripts/encrypt-content.mjswalkMd用readdirSync({ withFileTypes: true }),跳过 symlink;ROOT改用fileURLToPathbuild-site.sh解析 --output-dir,exportZOLA_OUTPUT_DIR供后续 Node 脚本scripts/patch-search-index.mjs读取 ZOLA_OUTPUT_DIR定位搜索索引;输出目录不存在时安全退出scripts/verify-kanban-build.mjsfileURLToPath统一 ROOT.github/workflows/deploy_pages.yml验证步骤改为 [ -d "../public_html" ]加固后的
walkMd逻辑(即使将来再误入 symlink 也不会拖垮构建):forconst ent of readdirSyncdir, {: true } { ifent.isSymbolicLink continue; // ... }4. 解决步骤
部署架构:Codeberg 私有源码 + GitHub.io 仅托管 workflow 与 gh-pages 静态页。
4.1 推送 Codeberg(必须)
仓库:
codeberg.org/SuzhaharCan/SuzhaharCan.codeberg.pagegit add content/kanban/2026-06-16.md \ scripts/encrypt-content.mjs \ scripts/patch-search-index.mjs \ scripts/verify-kanban-build.mjs \ build-site.sh git commit -m "fix: kanban week file git mode and CI build output paths" git push origin main # 或当前默认分支4.2 同步 GitHub.io workflow(若与 Codeberg 副本不一致)
仓库:SuchaharCan/SuchaharCan.github.io
将
deploy_pages.yml中 Verify Kanban build output 的路径修正同步到该仓库(../public_html)。4.3 重跑流水线
GitHub → Actions → Build Zola and Deploy to GitHub Pages → Run workflow
期望日志顺序:
encryption: N page(s) → static/encryption/pages/(无 ENAMETOOLONG)zola build→Done in …mskanban verify OK: 2 week(s), list cards match✅ 验证通过:public_html … index.html- Deploy push 至
gh-pages
4.4 线上验收
检查项 期望 /kanban/2 张周卡片 /kanban/2026-06-16/200,非 404 构建日志 无 encrypt-content.mjs栈追踪5. 本地验证
# 模拟 CI 自定义输出目录 ZOLA_OUTPUT_DIR=public_test ./build-site.sh --output-dir public_test # 期望:kanban verify OK: 2 week(s), list cards match # 确认 Git 索引 mode git ls-files -s content/kanban/2026-06-16.md # 期望:100644 ...6. 经验小结
ENAMETOOLONG+ 路径看起来不长 → 优先查 symlink 目标 与git ls-files -smode,不要只看路径字符串长度。- 跨平台构建 → 加密/遍历类脚本应 不跟随 symlink,并用
fileURLToPath解析 ESM 路径。 build-site.sh包装多步 →--output-dir须 显式传播 给所有读public/的后置脚本。- CI 与本地目录布局不同 → workflow 验证路径要与
zola build --output-dir同一基准(本次为zola_source的上一级public_html)。
相关链接:deploy workflow · 失败 Run #28 · 看板列表 · 前一篇 Nanolog(看板 UI / 热力图)
- Git mode
- 24 June 2026, 12:00 (CST) ReDeplogEdit Post
2026年06月24日 12:00(东八区 / 北京时间)
站点更新总结:Umami 统计 · 文章加解密 · 管理员特权 · 访客随机解密 · 编辑按钮门控
概述
本轮迭代围绕 可观测性(Umami)、内容保护(构建期加密 + 运行时解密)、特权与访客双模式 以及 编辑类按钮的可见性控制 展开。所有改动均在站点根目录
templates/、static/、scripts/、zola.toml完成,未修改themes/。构建入口统一为:
./build-site.sh # encrypt-content.mjs → zola build → patch-search-index.mjs1. Umami 流量统计
1.1 问题与根因
现象 原因 Umami 控制台长期无数据 self_hosted_url误填为博客域名,脚本指向不存在的/script.js控制台 CSP 报错 script-src/connect-src未放行 Umami Cloudgateway.umami.is/api/send被拦截Umami 新版上报端点未加入 CSP 1.2 修复要点
配置 / 文件 说明 zola.toml[extra.analytics]service = "umami";留空self_hosted_url(走 Umami Cloud)zola.toml[extra.csp]connect-src新增 gateway.umami.isstatic/analytic/umami.js全站幂等加载器; zola.toml→scripts = ["analytic/umami.js"]static/js/nanolog.js合并重复副本,统一路径 主题
build模式仍会注入cloud.umami.is/script.js;站点层脚本作兜底,避免漏统计。1.3 验证
- Network:
cloud.umami.is/script.js→ 200;gateway.umami.is/api/send无 CSP 拦截 - Umami 控制台
更细的调用链见同目录较早条目:
2026-06-23T12:00:00Z.md。2. 文章加解密(底层通用能力)
2.1 设计原则
- 构建期加密:正文不进 HTML 明文,降低「查看源代码」直接可读的风险
- 运行时解密:依赖 Web Crypto(需 HTTPS 或 localhost)
- 任意目录通用:凡 front matter 声明加密即纳入流水线,与板块路径无关
2.2 启用方式(单篇文章)
[extra.encryption] encrypt = true建议
[extra]写在[extra.encryption]之前,避免 TOML 表顺序导致解析异常。2.3 文件结构
层级 路径 站点配置 zola.toml→[extra.encryption]构建脚本 scripts/encrypt-content.mjs、scripts/encryption-lib.mjs密文输出 static/encryption/pages/<相对路径>.json清单 static/encryption/manifest.json全站注入 templates/base.html→partials/encryption_config.html加密文章 UI templates/partials/encrypted_article.html文章模板 templates/article.html(判断encrypt后 include)前端 static/encryption/config.js、admin.js、visitor.js、crypto.js、article.js样式 static/encryption/admin.css、article.css2.4 构建与 CSP
- 配置与密文通过
<textarea hidden>注入页面,避免内联<script>触发 CSP 拦截 script-src允许'self'、cdn.jsdelivr.net(marked)、主题合并的cloud.umami.is- 未跑加密脚本仅
zola build时,页面会提示「密文未找到,请先运行./build-site.sh」
2.5 测试文章
路径 说明 content/00Read_blog_Math/2026-06-03-First Base Chater/数学板块加密试点 content/02Engineer_blog_Debug/2026-06-23-Chrome-ReOpen/Debug 板块加密验证 3. 管理员特权模式
3.1 进入方式
连续点击左上角
#site-sidebar-header(站点图标)6 次:点击次数 反馈 第 3–5 次 Toast:「再点击 N 次可进入管理员模式」 第 6 次 Toast:「你已经是管理员,可浏览所有加密博客啦」 已是管理员 鼠标悬停图标显示「你已经是管理员」 状态保存在
sessionStorage(blog-encryption-admin-until)。3.2 有效期(
admin_ttl_secs)admin_ttl_secs = 60 # 秒,到期自动恢复访客- 进入特权时按 TTL 设置 精确
setTimeout,并每 500ms 兜底检查 - 到期触发
encryption-admin-expired:移除html.encryption-admin-active、文章重新上锁、看板恢复只读
3.3 管理员能力
- 解密所有
encrypt = true的文章 - 显示并可用 Nanolog / 看板上的 ReDeplog、Edit Post 等编辑入口
- 看板在
week_start~week_end窗口内可解锁拖拽;截止日当日 23:00(extra.timezone)前仍可编辑
4. 访客模式与随机解密
4.1 默认展示
- 加密文显示:「🔒 本文已加密」
- 提示语:「随机刷新时,可能会触发解密哦。」
4.2 随机解密逻辑(
static/encryption/visitor.js)visitor_refresh_min = 9 visitor_refresh_max = 20- 每篇文章、每个浏览器 session 独立计数
- 首次访问随机抽取阈值(9~20 次刷新之间)
- 刷新次数达到阈值后 自动解密(无需管理员)
- 解密状态在该 session 内对该文保持
5. 编辑类按钮门控(交互隐藏)
原则:访客只见只读;编辑入口仅在管理员特权下出现。
位置 访客 管理员 Nanolog 列表 隐藏 ReDeplog、Edit Post、发布按钮 显示 看板明细 锁定按钮固定「🔒 只读」,不可解锁 有效期内可解锁;显示工具栏;截止日 23:00 后变「只读(已过期)」 加密文侧边栏 TOC 非管理员隐藏 管理员显示 实现:元素加 class
encryption-admin-only;html.encryption-admin-active时由admin.css显示。看板逻辑在kanban-board.js中额外校验EncryptionAdmin.isAdminActive()。6. 关联改动(本轮一并收敛)
项 说明 看板数据源 统一为 content/kanban/,构建时内嵌 MD,移除多余kanban/副本Nanolog 列表宽度 sass/nanolog/style.scss调至与正文同宽nanolog.js移除不存在的 save-token-btn控制台警告7. 配置速查(
zola.toml)[extra] scripts = ["analytic/umami.js"] [extra.analytics] service = "umami" id = "cdf54193-b449-4454-884b-029e82434c32" exclude_hash = true [extra.encryption] enabled = true algorithm = "AES-GCM" key = "rocky-blog-dev-key-change-in-production" # 生产环境请更换 admin_ttl_secs = 60 visitor_refresh_min = 9 visitor_refresh_max = 20CSP
connect-src需包含:gateway.umami.is(以及主题自动合并的cloud.umami.is、*.umami.dev)。8. 自测清单
-
./build-site.sh无报错,控制台输出encryption: N page(s) - 加密文:访客默认上锁;连点 6 次进入管理员可解密;TTL 到期后恢复上锁
- 加密文:无痕窗口反复刷新,约 9~20 次后访客随机解密
- Nanolog / 看板:访客无 Edit Post、ReDeplog;管理员可见
- 看板:截止日 23:00 前可解锁,之后只读;列表剩余天数与明细一致
- Chrome DevTools 无 CSP inline script 报错;Umami 上报 200
9. 看板列表 / 热力图 · 编辑窗口判定(追加)
9.1 列表页与热力图
项 说明 页头 移除大标题「周计划」;副标题居中加粗;补充「单个看板时间跨度 1 ~ 14 天」 年份 / 月份下拉 修复脚本重复加载导致菜单无法展开;月份含全年 + 1–12 月 年度视图 1–6 月 / 7–12 月两行;月份块间距 + 虚线分隔 周格填充 有效天数 / 7 比例自下而上着色;未满 7 天为部分填充 月份视图 切换具体月份后展开为按天网格,直观显示哪些日期纳入看板 验证数据 content/kanban/2026-06-22.md(06-22 ~ 06-23,2 天)涉及文件:
templates/kanban_list.html、static/js/kanban-heatmap.js、static/css/heatmap.css、sass/kanban/style.scss。9.2 只读 / 可编辑判定(截止日 23:00)
原先按日历日比较
week_end,导致截止日当天 0 点起即只读。现改为:- 截止日
week_end当日 23:00 之前仍可解锁、拖拽、Edit Post - 23:00 及之后(站点时区)永久只读
- 时区读取
zola.toml→[extra] timezone(当前Asia/Shanghai),经模板data-timezone注入前端
例:截止 06-23,则 6 月 23 日 22:59 仍可编辑,23:00 起变只读。
位置 行为 明细页锁定按钮 访客: 🔒 只读;超期:只读(已过期);管理员且未超期:可锁定 / 解锁列表剩余天数 截止日 23:00 前显示「今天」;当日 23:00 后显示「已截止」 公共逻辑:
KanbanRules.isEditableWindow()、daysRemainingLabel()(static/js/kanban-rules.js);看板页data-timezone在templates/kanban.html,列表页在#kanban-week-list。# zola.toml [extra] timezone = "Asia/Shanghai"参考: daudix.one · Umami 控制台
- Network:
- 23 June 2026, 20:00 (CST) ReDeplogEdit Post
2026年06月23日(东八区)
功能调试:Umami 流量统计未生效
概述
站点启用 Ametrine 主题内置的 Umami 统计后,Umami 控制台 长期无访客数据。本次排查确认根因为
zola.toml中self_hosted_url误填为博客域名,导致追踪脚本指向不存在的/script.js,且 CSP 未放行 Umami Cloud 域名。修复后仅改动站点根目录zola.toml,未修改themes/。1. Umami 在源代码中的设计逻辑与调用链
Ametrine 主题(参考 daudix.one)将统计能力拆为 配置 → CSP 白名单 → 脚本注入 三层,全部在
themes/ametrine/templates/partials/中实现。1.1 配置入口:
zola.toml[extra.analytics] service = "umami" # 统计服务:goatcounter | umami | plausible id = "cdf54193-b449-4454-884b-029e82434c32" # Umami Cloud 的 website ID # self_hosted_url = "https://stats.example.com" # 仅自托管 Umami 时填写 exclude_hash = true # 可选:不采集 URL hash # exclude_search = false # 可选:不采集 URL 查询参数 # do_not_track = false # 可选:尊重浏览器 DNT字段 作用 service选择统计后端,决定加载哪段 partial idUmami 的 data-website-idself_hosted_url自托管实例根 URL;留空则走 Umami Cloud( cloud.umami.is)exclude_hash/exclude_search/do_not_track映射为 <script>上的data-*属性主题默认示例见
themes/ametrine/config.toml的[extra.analytics]段(daudix 使用自托管https://stats.daudix.one)。1.2 CSP 白名单:
partials/csp.html页面
<head>内生成Content-Security-Policy,决定是否允许加载外部脚本与上报数据:config.extra.csp(zola.toml 自定义域) ↓ csp.html 合并 analytics 域 ↓ <meta http-equiv="Content-Security-Policy" …>Umami 相关逻辑(
themes/ametrine/templates/partials/csp.html):条件 script-src追加connect-src追加设置了 self_hosted_url该 URL 该 URL 未设置 + service == "umami"cloud.umami.is*.umami.dev cloud.umami.is若误填
self_hosted_url为博客地址,CSP 不会自动加入cloud.umami.is,脚本即使写对也会被策略拦截。1.3 脚本注入:
partials/head.html→partials/analytics.html触发条件(
themes/ametrine/templates/partials/head.html):{%- if config.mode != "serve" and config.extra.analytics.service -%} {%- include "partials/analytics.html" -%} {%- endif -%}要点:
zola serve开发模式不注入 — 本地热重载页面无统计脚本,属预期行为。zola build产物才包含 — 部署到 GitHub Pages 后访客才会被追踪。
Umami 脚本生成(
themes/ametrine/templates/partials/analytics.html):条件 输出 self_hosted_url有值<script … src="{{ self_hosted_url }}/script.js" data-website-id="{{ id }}">self_hosted_url为空<script … src="https://cloud.umami.is/script.js" data-website-id="{{ id }}">等价于官方嵌入代码:
<script defer src="https://cloud.umami.is/script.js" data-website-id="cdf54193-b449-4454-884b-029e82434c32"></script>1.4 完整调用链(生产环境)
zola build → head.html 读取 config.extra.analytics → csp.html 写入 script-src / connect-src 白名单 → analytics.html 输出 <script defer src="cloud.umami.is/script.js"> → 浏览器加载 script.js → script.js 向 *.umami.dev / cloud.umami.is 上报 pageview → Umami 控制台展示数据2. 本次错误原因与修复方案
2.1 现象
检查项 修复前(线上) 页面 <script>src="https://suchaharcan.github.io/script.js"脚本 HTTP 状态 404(GitHub Pages 无此文件) CSP script-src'self' https://suchaharcan.github.io …(无cloud.umami.is)CSP connect-src无 *.umami.devUmami 控制台 无访客记录 2.2 根因
复制 daudix.one 配置时,将
self_hosted_url设成了博客域名https://suchaharcan.github.io。daudix 的
self_hosted_url = "https://stats.daudix.one"指向独立的 Umami 自托管实例;本站点使用的是 Umami Cloud,不应填写self_hosted_url。连锁影响:
- 脚本 URL 错误 — 主题从
博客域名/script.js加载,文件不存在。 - CSP 错误 — 白名单指向博客域名,未放行
cloud.umami.is与*.umami.dev。 - 即使手动改 script 地址,上报请求仍会被 CSP 拦截。
2.3 修复
文件:
zola.toml(仅此一处,未改themes/)[extra.analytics] service = "umami" id = "cdf54193-b449-4454-884b-029e82434c32" -self_hosted_url = "https://suchaharcan.github.io" exclude_hash = true修复后
zola build产物对比:检查项 修复后 脚本 src="https://cloud.umami.is/script.js"→ 200CSP script-src … cloud.umami.is;connect-src … *.umami.dev cloud.umami.iswebsite ID cdf54193-b449-4454-884b-029e82434c32✓部署提醒:本地 build 已正确,需 push 触发 GitHub Pages 重建后线上才生效。
3. 验证方式与使用注意点
3.1 部署后验证(推荐)
浏览器 Network
- 打开 https://suchaharcan.github.io/
- DevTools → Network,筛选
script.js - 确认来源为
cloud.umami.is,状态 200
查看页面源码
- 搜索
data-website-id,应出现cdf54193-b449-4454-884b-029e82434c32 - 搜索
Content-Security-Policy,应含cloud.umami.is
- 搜索
Umami 控制台
- 登录 Analytics 面板
- 刷新博客首页,Realtime / 今日访客应在数秒内更新
命令行快速检查(可选)
curl -sL "https://suchaharcan.github.io/" | grep -o 'cloud.umami.is/script.js' # 应输出:cloud.umami.is/script.js curl -sI "https://cloud.umami.is/script.js" | head -1 # 应输出:HTTP/2 200
3.2 使用注意点
场景 说明 zola serve本地开发不注入 analytics,Network 中看不到 Umami 脚本 — 正常 Umami Cloud vs 自托管 Cloud 用户不要填 self_hosted_url;自托管才填实例根 URL(如https://stats.example.com)CSP 自定义域 zola.toml的[extra.csp]与主题自动合并;Umami Cloud 域由主题在self_hosted_url为空时自动追加参考 daudix.one 可借鉴导航、CSP 结构等; self_hosted_url不能直接照搬(daudix 为自托管)不修改 themes/ 统计逻辑已在主题内;站点级只需正确配置 zola.toml并 build 部署隐私 / 分享 数据分享页:https://cloud.umami.is/share/2hWVbYvlPUkk98Yz AdBlock / 隐私扩展 访客若安装拦截器,可能不上报 — 控制台数据为「可统计访客」子集 3.3 配置对照速查
部署方式 serviceidself_hosted_urlUmami Cloud(本站) umamiCloud 控制台 website ID 留空 自托管 Umami umami实例中的 website ID https://你的-umami-域名GoatCounter / Plausible 对应 service 名 各服务文档 自托管时填实例 URL 修改文件
文件 变更 zola.toml删除错误的 self_hosted_url = "https://suchaharcan.github.io"相关链接:Umami 控制台 · 数据分享页 · daudix.one 参考仓库 · 热力图 + 统计启用记录
- 22 June 2026, 20:00 (CST) ReDeplogEdit Post
2026年06月22日(东八区)
大版本更新:周计划看板 v1.0 + Design 页
概述
本次为站点 Out - Projects 区的一次大功能迭代:上线 周计划看板(列表 + 明细 + 规则引擎 + 加权进度),并同步完成 Design 应用网格 样式对齐。数据与
content/同级存放在kanban/,未修改themes/。更新明细
1. 周计划看板 · 架构
层级 路径 / 文件 数据源 kanban/<周一日期>.mdZola 分区 content/kanban/(symlink 指向数据源)静态读取 static/kanban/→ 前端 fetch 原始 MD规则引擎 static/js/kanban-rules.js明细 UI static/js/kanban-board.js+templates/kanban.html列表 UI static/js/kanban-list.js+templates/kanban_list.html样式 sass/kanban/style.scss映射文档 kanban/kanban-mapping.mdEdit 缓冲 kanban/_edit-buffer.md入口:侧边栏 → Out - Projects → 周计划 →
/kanban/2. 列表页(图一)
- 标题显示
core_tasks(如「看板规则引擎 · Trello 明细页…」),不显示日期区间 - 元信息一行(article 图标风格):开始 · 截止 · 剩余天数 · 进度% · 重要等级(5 星)
- 剩余天数 = 截止日 − 基准日(东八区;早于
week_start时以开始日为基准) - 统计行:共 N 项 / 已完成 / 待办 / 进行中
- 背景色:待办 > 3 → 全红;全完成 → 浅绿;其余 → 按加权进度渐变
3. 明细页(图二 · Trello 五列)
列 参与进度 说明 待办 / 进行中 / 已完成 ✅ 可拖拽(解锁后) 资源 ❌ 淡绿托盘,列出所需资源 目标 ❌ @goal complete淡蓝 /@goal risk灰爆样式- 页头仅显示 本周核心(
core_tasks),无重复日期标题 - 卡片:顶栏色(
@top)+ 标签条(@labels)+ checklist + 描述;不显示开始/截止/星级(这些只在列表页) - 列头深色块:待办蓝 / 进行中橙 / 已完成绿 / 资源绿 / 目标灰
4. 锁定 / 解锁 / 保存
状态 行为 锁定(默认) 不可拖拽;隐藏 ReDeplog / Edit Post / 映射说明 解锁 仅在 week_start~week_end(东八区)内可切换;可拖拽跨列(本地预览)Edit Post 点击前按规则引擎序列化 → 写入 buffer → 复制剪贴板 /(可选 Token)API 覆盖 kanban/<周>.md超期 超过 week_end永久只读5. 加权进度公式
以 50% 为基准,仅统计前三列:
列 单项贡献 待办 −10% × n 进行中 +5% × n 已完成 +15% × n n= 该卡片@labels数量(无标签时n = 1)。结果 clamp 至 0–100%,写入stats.progress_pct。示例(6.16–6.22 周):待办 4 / 进行中 2 / 已完成 2 → 45%;待办 > 3 → 列表背景红色。
6. Design 页(同期)
/design/应用网格对齐 ensili.co More apps 布局- 文件:
templates/design.html、sass/design/style.scss、static/js/design-apps.js
7. 其他
zola.toml导航增加 周计划- 示例看板:
kanban/2026-06-16.md - 完整映射:
kanban/kanban-mapping.md
看板简易映射规则
# 列名 → 看板一列(待办 / 进行中 / 已完成 / 资源 / 目标) ## 卡片标题 → 一张卡片 @start 2026-06-16 开始(数据用,列表页展示) @due 2026-06-22 截止 @priority 4 重要等级 1–5(列表页星级) @top orange 明细页顶部粗色条 @labels red, blue 明细页顶部细色条 + 进度权重 n @bg #FFF8E1 卡片背景色 @goal complete 目标看板 · 完成效果(淡蓝) @goal risk 目标看板 · 未完成后果(灰爆) - [ ] / - [x] checklist 勾选框Front Matter 要点:
[extra] week_start = "2026-06-16" week_end = "2026-06-22" core_tasks = "本周核心任务一句话" importance = 4 stats = { total = 8, done = 2, todo = 4, doing = 2, progress_pct = 45 }下次更新计划
测试解锁后编辑功能
- 解锁 → 拖拽跨列 / 勾选 checklist → 点击 Edit Post
- 验证序列化往返、
kanban/_edit-buffer.md缓冲、Codeberg 粘贴 / Token 同步 - 确认 ReDeplog 部署后列表进度与明细一致
针对特定设备显示解锁功能
- 评估移动端 / 平板是否展示「解锁 · 可拖拽」(触摸拖拽与桌面差异)
- 可按 viewport 或 UA 限制:小屏只读、桌面可编辑;或提供显式「桌面模式」提示
- 标题显示
- 22 June 2026, 10:00 (CST) ReDeplogEdit Post
2026年06月22日(东八区)
功能更新:周计划看板(Kanban 瀑布流)
概述
新增 周计划 模块:列表 + 明细双模板,数据存放在仓库根目录
kanban/(与content/同级),一份 Markdown 对应一个自然周。核心能力
Markdown 规则引擎(
static/js/kanban-rules.js)# 一级标题→ 看板列## 二级标题→ 卡片@due·@labels·@bg·@top·- [ ]与看板元素映射- 同步时按当前 UI 状态 序列化回写 Markdown
明细页 Trello 风格(
templates/kanban.html)- 多列布局、标签条、顶栏色、截止日期、checklist
- 锁定 / 解锁:仅在
week_start~week_end(东八区)内可编辑 - 解锁后可 拖拽卡片跨列;同步 按钮写回
kanban/<周>.md - Edit Post / ReDeplog 链接对齐 Nanolog 工作流
列表页进度视觉(
templates/kanban_list.html)- 展示本周起止、核心任务、完成统计
- 全完成 → 浅绿;完成 < 3 → 全红;其余 → 进度渐变
文档与示例
- 映射说明:
kanban/kanban-mapping.md - 示例看板:
kanban/2026-06-16.md(6.16 – 6.22)
入口
侧边栏 Site Dev Log → 周计划 →
/kanban/ - 22 June 2026, 03:30 (CST) ReDeplogEdit Post
2026年06月21日(东八区)
功能调试:Edit Post 提交后看板明细空白
背景
按 v1.0 发布说明「下次更新计划」第 1 项,测试 解锁 → 拖拽 → Edit Post → Codeberg 粘贴提交 → ReDeplog 重建 全流程。
触发变更:Codeberg commit c02b75a(更新
kanban/2026-06-16.md)。现象
ld
页面 提交前 提交后 列表页 /kanban/正常:stats、进度条、星级 正常:待办 3 / 进行中 3 / 进度 60% 已更新 明细页 /kanban/2026-06-16/五列 + 卡片 + 拖拽 空白:仅标题与「已锁定」,无列无卡片 初看像「映射规则解析失败」,因为明细区完全无 DOM 输出。
问题定位
排除解析层
用kanban-rules.js对提交后的kanban/2026-06-16.md做parseMarkdown:仍得到 5 列、12 张卡片,映射规则本身无异常。对比 commit diff
用户粘贴的 Markdown 在 front matter 中删掉了:styles = ["kanban/style.css"] scripts = ["js/kanban-rules.js", "js/kanban-board.js"]根因是
serializeMarkdown()序列化时不会写回这两项,Edit Post 往返必然丢失。脚本加载链
明细页看板 100% 客户端渲染:kanban-board.jsfetch/kanban/<slug>.md→parseMarkdown→ 写 DOM。
脚本来源(themes/ametrine的head.html):- 有
page.extra.scripts→ 用页面级 - 否则 → 回退
section.extra.scripts
配置 实际加载 页面 FM 含 scriptskanban-rules.js+kanban-board.js✓页面 FM 无 scriptssection 仅 kanban-rules.js+kanban-list.js✗ 缺 board.js列表页只需
kanban-list.js,故列表正常;明细页缺kanban-board.js,故空白。- 有
解决思路
原则:明细页核心脚本不应依赖 front matter 是否被 Edit Post 保留。
templates/kanban.html
模板内固定注入kanban-rules.js+kanban-board.js(与已有 inlinekanban/style.css一致),脱离page.extra.scripts。static/js/kanban-board.js
解析结果columns为空时,在#kanban-status输出明确错误,便于与「脚本未加载」区分。正反映射
parseMarkdown→serializeMarkdown→parseMarkdown往返:列/卡片/stats 保持一致;FM 的styles/scripts非看板数据,不写入序列化输出,避免与模板重复加载。
修改文件
文件 变更 templates/kanban.html文末 <script defer>加载 rules + boardstatic/js/kanban-board.js空解析结果时 status 报错 验证
- Node 往返:5 列 → 5 列,12 卡 → 12 卡
zola build --force通过;产物/kanban/2026-06-16/含kanban-board.js- 部署后:即使 FM 无
scripts(与远程 commit 一致),明细页也应正常渲染
经验
- 列表与明细共用 section,但脚本需求不同 → 明细模板应自包含,不能假设 page FM 永远完整。
- Edit Post 是数据回写路径 → 序列化只负责看板 Markdown 本体;运行时依赖放模板/静态层更稳。
- 排查时先区分「没加载 JS」与「JS 加载但解析失败」:前者 DOM 容器空、无报错;后者可在 status / console 看到线索。
- 21 June 2026, 16:30 (CST) ReDeplogEdit Post
2026年06月21日
功能更新:文章发布热力图 (Contribution Heatmap)
概述
新增基于全站文章数据的 GitHub 风格热力图组件,支持在文章页与归档页以不同尺寸和配色展示写作活跃度。
核心能力
双模式展示
- 文章页 (
article):右侧sticky固定,仅显示上个月 + 本月;深紫背景、淡紫渐变格点,参考 GitHub 紧凑尺寸。 - 归档页 (
archive):插入于Total: N posts与分隔线之间,展示当年完整热力图;GitHub 标准绿色配色。
- 文章页 (
交互
- 悬浮:显示当天标签数最多的文章标题(同天多篇时按
tags数量降序取首篇)。 - 点击:跳转至对应文章。
- 悬浮:显示当天标签数最多的文章标题(同天多篇时按
模块化文件
templates/partials/heatmap_component.html— 聚合各板块文章数据并渲染容器static/css/heatmap.css— 布局与双主题样式static/js/heatmap-init.js— 轻量渲染逻辑(无 Heat.js 重型 UI)
集成方式
文章页(
templates/article.html):<aside class="article-heatmap-sidebar"> {% set heatmap_mode = "article" %} {% include "partials/heatmap_component.html" %} </aside>归档页(
templates/archive.html):{% set heatmap_mode = "archive" %} {% include "partials/heatmap_component.html" %}设计说明
- 放弃 Heat.js 默认「Heat.js [ Map ]」大标题 UI,改用自研紧凑渲染,更接近 GitHub Contributions 视觉。
- 移动端(≤960px)热力图自动移至正文上方,避免遮挡阅读。
启用 主题内置 数据统计功能;
[extra.analytics] service = “umami” id = “cdf54193-b449-4454-884b-029e82434c32” self_hosted_url = “https://suchaharcan.github.io” exclude_hash = true
https://cloud.umami.is/share/2hWVbYvlPUkk98Yz 是数据分享页面
- 21 June 2026, 15:49 (CST) ReDeplogEdit Post
2026年06月21日
功能模块说明:智能滚动导航组件 (Smart Scroll-Navigation)
概述 本组件是一个常驻于页面右下角的圆形交互按钮,集成了全屏滚动进度展示与双向智能导航功能。它能够根据用户的阅读深度,动态调整自身视觉形态与交互行为。
核心交互机制 该模块基于页面滚动深度(Scroll Progress)实现智能状态切换:
视觉状态同步:
顶部进度条:固定于视窗顶部的 3px 极细线性进度条,同步反馈阅读进度。
环形按钮进度:按钮外圈环绕的 SVG 进度条与顶部进度条完全同步,保证视觉一致性。
统一圆形形态:按钮采用 border-radius: 50% 设计,内部进度条绕圆心延伸,无视觉断层。
上下文智能导航:
区域 A(阅读深度 < 50%):组件处于“向下”状态,箭头指向底部。点击触发 smooth scroll 至页面尾部,方便用户快速跳过开头进入正文或评论区。
区域 B(阅读深度 > 50%):组件处于“向上”状态,箭头翻转 180 度指向顶部。点击触发 smooth scroll 至页面头部,方便用户回溯文章。
- 架构方案 本功能采用轻量级模块化设计,无外部依赖,确保页面加载性能:
HTML (Partial):负责结构定义,通过 partials 引入,实现代码解耦。
CSS (Static):采用 CSS Flexbox 实现内容垂直居中,利用 SVG stroke-dasharray 属性实现环形进度条的高性能渲染。
JavaScript (Static):通过 requestAnimationFrame 优化滚动监听性能,利用 dataset 属性安全管理组件的导航方向状态。
- 应用场景与设计哲学 极简审美:摒弃传统“回顶按钮”单一、生硬的交互,将阅读感知融入组件中。
空间优化:将进度反馈与导航功能合并,减少 UI 元素对屏幕空间的占用。
自适应体验:逻辑完全基于 scrollHeight 动态计算,无论是几百字的小短文还是长篇技术分析,导航阈值均能自动适配,无需手动维护。
安装与集成提示 模块引入:在你的 article.html 中通过 {% include “partials/scroll-progress-bar.html” %} 引入结构。
资源引用:在模板的头部引入 scroll-progress-bar.css,底部引入 scroll-progress-bar.js。
性能保障:由于使用了 requestAnimationFrame,即使在复杂的长文档页面中,该组件也不会导致页面滚动时的视觉卡顿,满足极客对高性能页面的要求。
如果你需要将此模块部署到其他页面(如 index.html 或 archive.html),只需在相应模板中重复以上引用步骤即可。
- 04 June 2026, 13:14 (CST)
- 03 June 2026, 18:02 (CST) ReDeplogEdit Post
碎碎念
目前环境网络波动, 容易损耗 镜面屏电容寿命,心疼。 购买华为UPS800W(间接限定后续服务器的瓦数)
目前基础 后端服务 搭载在公网上, 流水线借助GitHub(编译后清空源码信息) 后面 使用 自有服务器; 暂定的DIY方案
🛠 EPYC 7502 编译服务器搭建方案📊 硬件配置与预算清单部件推荐型号/规格价格 (元)选型理由CPUAMD EPYC 7502 (正代正式版)~100032核64线程,并行编译的绝对主力,Zen2 架构。主板永擎 (Asrock Rack) ROMED8-2T 或 超微 H12SSL-i~900SP3插槽(支持7002系列)。自带 IPMI 远程管理,带双千兆或万兆网口。内存DDR4 2666MHz ECC REG 16G × 4 (共64G)~280C++ 编译大型项目非常吃内存,先上 4 根跑满 4 通道,后期可补满 8 根。系统/编译盘三星 PM9A1 1TB 或 致态 TiPro7000 1TB~450编译时会产生密集的 I/O 读写,必须用高质量、高性能的 PCIe 4.0 NVMe 固态。散热器拓普龙/超微 SP3 4热管/6热管风冷~120专为服务器 LGA4094/SP3 接口设计的散热器。电源长城巨龙 1250W 或 海韵/全汉 750W 品牌二手~150 - 2007502 的 TDP 是 180W,满载编译加上主板内存,额定 650W - 750W 比较稳妥。机箱普通 ATX 兼容大机箱 / 4U 工业机箱~80只要能塞下 ATX 主板和服务器散热器即可。总计约 2980 元万元以内无敌的编译生产力工具
💡 方案深度解析与注意事项
- 为什么主板这么贵?(服务器主板的灵魂:IPMI) 服务器主板(如永擎、超微)自带一颗特殊的芯片叫 IPMI(远程管理卡)。
不需要显卡: 这颗 CPU 没有核显,主板自带了基础显示芯片,你甚至不需要插独立显卡。
盲操远程: 只要插上电源和网线,你在你日常用的笔记本上,通过浏览器输入服务器的 IP 地址,就能远程看屏幕、进 BIOS、挂载本地 ISO 镜像重装 Linux 系统、远程开断电。这才是纯正的服务器体验。
- 为什么选 16G × 4 内存? C++ 并行编译的黄金法则是:每个编译线程(Thread)至少分配 2GB - 4GB 的内存。 你现在有 64 个线程:
如果只给 16G/32G 内存,当 make -j64 全开时,内存会瞬间爆掉,导致触发 Linux 的 OOM Killer 机制直接崩溃。
64G 内存是这颗 32 核处理器的及格线。
- 网络与存储扩展 这类工业级主板上通常带有 SlimSAS 或 Oculink 接口,以及大量的 PCIe 插槽。这意味着,如果你以后想让它兼顾 NAS 存储功能,你不需要买任何转换卡,直接可以挂载 8-16 块大容量机械硬盘,或者插满 4 块 NVMe 固态硬盘做高速编译缓存。
选项 A:AMD EPYC 7502(推荐:更先进、带宽高) 核心参数: 32核 64线程,基础频率 2.5GHz,加速 3.3GHz。
CPU价格: ~1000 元(随着 7002/7003 系列退役,目前性价比极高)。
为什么选它: 它是 Zen 2 架构(7nm),单核性能比老一代大涨。更恐怖的是它支持 8通道 DDR4 内存。C++ 编译在链接(Linking)阶段需要极高的内存吞吐,8通道是无敌的存在。
围绕 AMD EPYC 7502 这颗 CPU 搭建的服务器,整机的功耗(瓦数)需要分三个场景来看:待机功耗、日常轻载功耗、以及最关键的多核全满载编译功耗。以下是具体的瓦数测算和电源选型建议:📊 整机功耗(瓦数)实测预估运行场景CPU 自身功耗整机总功耗(含主板/内存/SSD)10小时电费估算 (按0.6元/度)1. 远程待机 (挂机/写代码不编译)~30W - 40W约 70W - 90W~0.5 元2. 日常轻载 (跑几个Docker/轻量运行)~50W - 60W约 100W - 120W~0.7 元3. C++ 多核全满载编译 (make -j64)180W (满TDP)约 240W - 260W~1.5 元
总计 3000 元;
- 02 June 2026, 07:05 (CST) ReDeplogEdit Post
2026年06月02日
修复
- 修复 Nanolog Edit编辑 不在 源代码的问题 (直接 编辑源码,但 不 立即推送更新到 公开仓库)
- 重置 Nanolog 内容, 书写 自己的 网站 维护内容
细节打磨
- 博客网页 Nanolog处 添加 ReDeplog 按钮,同 Edit Post 一致 (编辑 源码,重编译推送) 已添加
- 定时发送邮件 提醒自己 手动更新博客 待添加
开发进度
Done
- 源码推送在Codeberg, 网站15天后自动拉取编译更新网站github.io ; 实现 源码/网站 分离 (优点: 高频推送隐私信息剥离,后续可加装 密码解锁网页; 缺点: 构建 与 推送 分离 需 单独管理)
- 拆分一级板块:
Read,Write,Share,Project,Site Dev Log; 及其 二级分类 Nanolog模块开发完成 . 处于可用状态 (展示,可 直接 Edit)Blog模块 未完成(需 编写 index.html 及 blog.html 2个模板文件)Basb模块开发完成,并处于 可用状态, 暂定 该模块 用来进行 周记录 , 考虑 将 EditPost/ReDeplog功能同步过去 ;
UnDo
- 熟悉 该主题文件 的MD 博客编辑模式(该模式 精细,具有观赏性)
- 搜索功能 待开发(index.html 自有功能)
- 密码封锁 爬虫 和 无关访客 (该模块优先 开发 ,最小可用方案推出,后续迭代)
- 在Nanolog 中 添加 固定 格式: 约定更新时间, 考虑 添加 网页倒计时,并提前1小时 发送邮件提醒 给自己 该功能 可考虑
- Codeberg 中 补充 CI/CD 流水线, 该功能 还是必要的;
- 后续添加后端服务 (C++编写 核心模块, Go/.NET 进行Web后端API开发) 在 Vercel 或者 Cloudflare 中 进行 部署
Doing
Blog模块 正在开发调试中
细节补充
- 完整流程阐述:
本地拉取 私有源码仓库 Codeberg, 更新构建成功后推送(Zed 编辑 模板, Obsidian 编辑 MD); 手动触发公开博客网站Github.io仓库workflow拉取编译最新源码; 菜单栏Deplog 提醒 构建推送状态; NetNewWire 对网站进行RSS订阅
- 熟悉 了解 Zola功能 及 Ametrine主题功能
- 对其他博主博客有趣 基础刚性功能 务必添加,但柔和功能考虑添加
- 补充 CICD 流水线, 虽然本地是编译成功, github跨网站拉取codeberg 私有库也成功, 但 还是有必要进行构建cicd流水线的 熟悉流水线搭建,还有保证 环境搭建的流程 能够复现出来 ,例如 拉取主题仓库,更新依赖git模块, mac环境模拟zola 等细节 ; 该功能属于基础自动化功能,一旦实现,后续受益
- 评论区? 自认为有价值 适合分享的文章, 我会 主动发布到 HackerNew 上的; 我个人 不加载 和存储 评论数据, 使用HackerNew 足够了;
常用 命令
git pull # 拉取最新代码,因为Nanolog 存在线上Edit Post,所以 本地修改需谨慎,优先拉取最新代码 git add . # 添加所有修改的文件 git status # 查看修改状态 git commit -m "update nanolog" # 提交修改 git push # 推送修改 #上述操作 均是在本地编辑Codeberg仓库 ,与 公开网站Github无关 # 若基础信息更改, github 的编译流水线yml文件需同步修改,否则拉取编译失败约定/预订 下次更新时间
本周六