dsh-hxc-blog
Manage a GitHub Pages blog from a DSH panel — browse the Markdown articles grouped by tag, edit them in a split editor with a front-matter form, and publish the changes as one commit over the GitHub REST API.
Install
dsh plugin --profile web add dsh-hxc-blog
Sandbox test
This plugin has not been tested yet. Submit a test →
README
DSH · GitHub Pages 博客管理插件

仓库:huangxicheng1/blog-manage
· 包名:dsh-hxc-blog · 许可证:MIT
把 huangxicheng1/huangxicheng1.github.io 的内容管理搬进 DeepSeek Harness:
在左侧边栏打开一个博客管理面板,浏览、撰写、编辑、删除 content/**/*.md,
把变更作为一次明确的 commit 推回 main,然后盯着 GitHub Actions 把站点构建出来。
整个插件不需要本地 git,也永远不会写 entries.js —— 那个文件由 build.py
在 Actions 里生成,插件只负责 content/ 下的 Markdown。
前提:站点的 Pages 源必须设成 GitHub Actions(Settings → Pages → Source)。
如果还停在「Deploy from a branch」,GitHub 会自己把分支内容原样发布一遍,覆盖掉
Actions 的产物,于是构建明明成功、线上却没有新文章。详见第 10 节。
1. 功能需求
1.1 它做了什么
能力 · 说明
侧边栏入口 · 在「Downloads」之后新增一行「博客管理」,点击打开主区域面板
双栏浏览 · 左栏按 tag 分组(可折叠、多 tag 重复出现、无标签单独成组),支持搜索、草稿标记、格式错误标记;右栏渲染预览,可切到源码
可视化编辑 · front matter 用表单填写(不手写 YAML),正文 Markdown 编辑 + 实时预览
发布前校验 · 按 build.py 规则校验,不通过就拦住发布并高亮出错字段
一次 commit · 所有待发布变更合并成一次 commit(blob → tree → commit → ref),冲突时拒绝覆盖
构建反馈 · 推送后轮询 Actions 最新 run,显示「构建中 / 成功 / 失败」,成功给出站点链接
自动化接口 · HTTP 路由 + Host 服务 + 浏览器事件三种钩子,见第 7 节
1.2 连接与浏览
设置面板配置 GitHub fine-grained PAT(加密存储)、仓库、分支、内容目录、站点地址。
点击侧边栏按钮后,主区域打开双栏界面。
左栏:按 tag 分组(详见第 2 节)
- 从每篇文章 front matter 的
tags提取标签,一个标签一个分组,分组标题显示「标签名 + 文章数量」。 - 可折叠 / 展开:点击分组标题收起或展开,折叠状态会记忆(重开 DSH 仍然保留)。
- 一篇文章有多个 tag 时,同时出现在多个分组下;没有 tag 的归入「无标签」分组,永远排在最后。
- 分组内每篇文章显示标题、日期、其余标签(灰色小字)、文件名;草稿与格式错误各有徽标,有未发布更改时标题右侧有小圆点。
- 搜索支持标题、标签、文件名(另外也匹配摘要、分类与路径)。
右栏:选中文章的 Markdown 渲染预览,可切换源码模式;顶部显示 front matter 元信息
(类型、分类、标签、复习日期、日期),并显示文章 id。
1.3 可视化编辑与发布
- 「编辑 + 实时预览」分屏编辑器,正文左侧编辑、右侧即时渲染。
- 新建文章时 front matter 用表单填写:标题、日期(默认今天)、类型(diary / note 下拉,
决定写入 content/diary/ 还是 content/notes/)、摘要、分类(仅 note 显示)、标签、
复习日期、草稿开关、文件名。
- 保存前在本地按
build.py的规则校验,不通过则阻止发布并高亮错误字段。 - 编辑后显示「未发布更改」标记;发布时弹出确认框,显示变更文件列表
(M 修改 / D 删除)和 commit message 输入框,确认后通过 GitHub API 创建单个 commit 并推进分支。
1.4 发布状态反馈
推送成功后查询该仓库最新 Actions workflow run,显示「构建中 / 成功 / 失败」,
成功后给出 https://huangxicheng1.github.io/ 链接,失败时给出构建日志链接。
1.5 自动化扩展
HTTP 路由、Host 服务、浏览器事件三个入口,见第 7 节。
2. 内容浏览视图:按标签分组
左栏的组织原则是 tag,不是目录。规则全部落在 client.js 的
groupArticlesByTag() 与 articleMatchesQuery() 两个纯函数里,
由 test/tag-groups.mjs 直接验证:
行为 · 规则
分组键 · front matter 的 tags(逗号分隔,中英文逗号都接受)
分组标题 · # + 标签名 + 文章数量
折叠 · 点击分组标题,箭头旋转;aria-expanded 随状态变化
折叠记忆 · 存 localStorage 的 dsh-gh-blog:collapsed-tag-groups;读取失败或值损坏时退化为「全部展开」,不会抛错
搜索时 · 自动全部展开(搜索是明确的「我要看结果」),清空搜索后恢复折叠记忆
多 tag · 一篇文章出现在它每个 tag 的分组下,重复出现是预期行为
无 tag · 归入「无标签」分组,永远排在最后
分组顺序 · 文章数多的在前;数量相同按首次出现顺序(文章列表本身按日期倒序,所以是最新文章所属的标签先出现)。刻意不用 localeCompare,避免排序依赖运行时的 ICU 数据
卡片 · 标题 / 日期 / 其余标签(灰色小字 #a #b,即全部标签减去当前分组的那个)/ 文件名(等宽小字)
搜索字段 · 标题、标签、文件名;另外也匹配摘要、分类、路径
「其余标签」是卡片的关键细节:分组标题已经说明了当前标签,卡片再重复一遍就是噪音,
所以卡片只显示剩下的标签 —— 这也回答了「这篇文章为什么会出现在这里」之外的信息。
3. 安装
这是一个 DSH bundle 包,用 plugin_manager 的 install_bundle 安装。
不要在 profile 目录里手写 package.json,也不要在那里跑 pnpm —— install_bundle 会做完这些。
从 npm 安装(最省事)
plugin_manager action: install_bundle target: dsh-hxc-blog
包在 npm 官方源上:<https://www.npmjs.com/package/dsh-hxc-blog>。
当前版本 0.1.1,声明兼容 DSH >=0.2.1-rc.2。
从 GitHub 安装
git clone https://github.com/huangxicheng1/blog-manage.git
然后把 install_bundle 的 target 指向 clone 下来的目录绝对路径:
plugin_manager action: install_bundle target: <clone 目录的绝对路径>
install_bundle 的 target 要的是本机路径,所以先 clone 再指过去,不要直接填 URL。
如果你只是想让 DSH 去拉这个仓库,dsh plugin add github:huangxicheng1/blog-manage 也可以。
从本地工作目录安装
如果你就在改这份源码,直接把 target 指向工作目录。本地目录安装是链接方式,
改完 client.js 刷新页面即可生效,不必重装。
安装完成后刷新 Web GUI:
- 左侧边栏出现「博客管理」(位于「Downloads」下方);
- 「插件」页里出现一行
GitHub Pages Blog,带本插件自己的图标。
若之后改动了 Host 端(index.js / lib/*),需要重启 Harness 让新的 JavaScript
模块代次生效(Node 会缓存已导入的模块,重装不会绕过它)。
可选:用配置固定默认值
cordis.patch.yml 里的 config 全部可选,用于给某台机器钉住默认仓库/分支:
- insert:
- id: gh-blog
name: dsh-hxc-blog
config:
repository: huangxicheng1/huangxicheng1.github.io
branch: main
contentRoot: content
siteUrl: https://huangxicheng1.github.io/
优先级:内置默认值 < cordis.patch.yml 的 config < 设置面板里保存的值。
4. 配置 Token
1. 打开 <https://github.com/settings/tokens?type=beta> 创建一个 fine-grained PAT。
2. Repository access:只勾选 huangxicheng1.github.io 这一个仓库。
3. Permissions:
Contents: Read and write —— 读写文章;Actions: Read —— 读取构建状态(可选;没有它只是看不到构建结果,推送仍然可用)。
4. 回到 DSH,侧边栏「博客管理」→ 右上角「设置」→ 粘贴 Token → 「保存设置」→「测试连接」。
Token 存在哪里:
- 它走 DSH 的 凭据服务(
credentials),键名GH_BLOG_GITHUB_TOKEN,属于
provider 管理的可写存储,不会写进本插件的设置文件,也不会出现在页面 JavaScript 里
—— 浏览器端只和 DSH Host 的 /api/gh-blog/* 通信,从不直连 api.github.com。
- 也可以不填面板,改用同名环境变量
GH_BLOG_GITHUB_TOKEN提供(凭据服务会回落到环境)。 - 面板里留空保存 = 保持现有 Token 不变;打开「清除已保存的 Token」再保存 = 删除。
非敏感设置(仓库、分支、内容目录、站点地址)存在:
$DSH_HOME/gh-blog/settings.json
写入是原子的(临时文件 + rename),权限 0600。
5. front matter 规范(与 build.py 一致)
文档必须以 --- 开头、以 --- 结束,中间只允许简单 key: value 行
(不支持嵌套、列表、多行标量)。
必填
字段 · 规则
title · 非空,单行,≤ 200 字符
date · YYYY-MM-DD,且必须是真实存在的日历日(2026-02-30 会被拒绝)
type · 只能是 diary 或 note
summary · 非空,单行
可选
字段 · 规则
category · 只对 note 有意义;不填视为「未分类」;写在 diary 上只做提醒,不会阻止发布
tags · 逗号分隔字符串(保存时会统一成 半角逗号 + 空格;中文逗号也接受)。左栏就是按它分组的
review · YYYY-MM-DD,复习日期
draft · true 时不发布;只接受 true / false
文件名与 id
- 文章 id = 文件相对
content/的路径(去掉扩展名),例如notes/2026-10-21-my-note。 - 新建时插件按
type决定目录,按date+ 文件名生成路径:
content/diary/<date>-<slug>.md content/notes/<date>-<slug>.md
- 文件名只允许字母、数字、中文、
.、_、-,且不能以符号开
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::3,最后更新 2026-10-21