博客站点 里装下 DSH 插件市场,能搜能复制
页面已经跑起来了:搜「记忆」能筛出 20 张卡,点「复制」会变成「已复制」,切到暗色模式字也看得清。整个过程没动主题文件,只在 Halo 后台的「HTML 编辑块」里贴了约 60 KB 代码。
真正花时间的不是写页面,是三个坑:一处带省略号的 JSON、一条抢颜色的全局 CSS、一个没写 charset 的片段。

写这篇文章时,页面设了登录可见,未登录只会看到登录提示;截图来自同一份已发布组件的渲染,数字会跟着上游清单变。
背景:为什么要把插件市场搬进站点
DSH(DeepSeek Harness)的插件散在 npm 和社区清单里,想装一个得先知道包名,再去翻 README 找命令。
我在站点上开了一个页面,把社区清单做成目录:按分类浏览、搜索包名或功能、每条命令都能一键复制。目标就三个:
看得懂每个插件是干什么的
复制出来的命令能直接粘进终端
亮色、暗色、手机宽度都不塌
技术上是 站点 的一个「页面」,不是文章,也没碰主题文件。
踩坑一:页面空白,按钮一半能点
第一次部署后,页面顶部和安装说明都在,但下面的插件卡片、分类标签全是空的。奇怪的是,「复制」按钮还能点。
现象:静态 HTML 正常,JS 生成的内容全部消失。
定位:抓线上页面的源码,看到这一段:
var DATA = {"featured":[{"npm":"dshmarket","name":"dsh-market 插件市场",...}]};
... 是上一条消息里的省略写法,被我原样贴进了页面。JSON 带省略号就是语法错误,整段 <script> 一行都不会执行。「复制」按钮在静态 HTML 里,不依赖这段 JS,所以出现了「有的按钮能动、有的按不动」。
修法:不再把整份数据写死进页面,改成运行时拉取:
var SOURCES = [
'https://awesome-dsh-plugin.com/plugins.json',
'https://cdn.jsdelivr.net/npm/dsh-plugin-catalog/index.json'
];
主源失败就换镜像,镜像也失败就用页面内置的一小份快照兜底。断网时不至于白屏,只是列表少一些。
这个改动还顺手解决了体积问题:原来内嵌 174 KB 的 JSON,现在页面约 60 KB,数据跟上游保持同步。
踩坑二:暗色模式下,输入框的字消失了
站点切到暗色后,搜索框里输入的字是黑的,跟背景一个颜色。
原因:Pix 主题有两条全局规则在抢颜色:
body, button, input, select, optgroup, textarea { color: #404040; }
input[type="text"], input[type="email"] { color: #666; }
我原来的 .dshm__search input 特异性不够,输了。
修法:提高特异性,再加 !important,把自动填充和 placeholder 一起管住:
.dshm .dshm__search input[type="search"] {
color: var(--dshm-ink) !important;
-webkit-text-fill-color: var(--dshm-ink);
}
暗色下实测计算值是 rgb(242, 239, 252),白字清楚。
踩坑三:窄栏和字符集,两个不显眼的坑
Pix 主题的正文栏不宽,三栏布局下只有 490px 左右。卡片网格如果写死 minmax(300px, 1fr),窄栏会横向溢出。改成这样:
.dshm__grid {
grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
}
min(100%, 300px) 保证列宽永远不超过容器,手机上自动变单列。
另一个坑更隐蔽:页面片段没有 <meta charset>,测试服务器又没声明编码,浏览器按 GBK 解码,中文变乱码,JS 字符串边界也跟着坏,整段脚本报语法错误。
修法是把内置快照序列化成纯 ASCII(\uXXXX 转义),这样不管页面声明什么编码,数据都不会坏。Halo 的页面本身是 UTF-8,这一步算防御性处理,但值得做。
完整步骤:在 Halo 里贴一份 HTML
进 站点 后台,左侧「内容 → 页面」。路由是
/console/single-pages,不是文章的/console/posts。打开目标页面,或者新建一个。slug 我用了
deepseekcha-jian-shi-chang,中文标题会生成一长串拼音,介意的话在发布前改短。在默认编辑器里插入「HTML 编辑块」。它是 CodeMirror 6,右边有实时预览,长文档会虚拟滚动,所以编辑器里只显示当前视口那一段。

先把编辑器内容全选删掉,再粘贴完整代码。粘贴后按
Ctrl+Home(Mac 是Cmd+Home)回到开头,确认第一行是<div class="dshm" id="dshm">,避免旧代码和新代码叠在一起。点「保存」,顶部出现「保存成功」。

点「发布」,回前台刷新页面。验证三件事:卡片数量、搜索、复制按钮。
如果只想先看效果,可以不发布,用编辑器的预览。正式发布后再改,回滚也简单:在同一个编辑块里撤销,或者换回旧代码重新发布。
效果与验证
页面发布后,我在浏览器里逐项点过:
搜索同时匹配包名、显示名、中文描述和英文描述,多个关键词用空格分开也能命中。


暗色模式下,标题、卡片、输入框都保持可读,搜索框的计算颜色是 rgb(242, 239, 252)。

手机宽度也试了,工具栏会自动换行,卡片变单列:

有一个小瑕疵没修:搜索框是 type="search",浏览器自带的清除按钮和我加的「×」会同时出现。不影响使用,强迫症可以给原生按钮加一条 ::-webkit-search-cancel-button { display: none; }。
下一步:把入口放到导航里
页面现在只能从直链进。下一步我会在站点导航加一个「插件市场」入口,再把页面的登录可见改成公开——这一步取决于站点整体的访问策略,不急着动。
如果你也想在自己的 站点做类似页面,建议顺序是:先跑通静态结构和样式,再接实时数据,最后处理暗色和窄栏。反过来做,出问题时很难判断是数据、样式还是容器宽度。
页面的数据来自社区清单 awesome-dsh-plugin,Star 和下载量由该站刷新;收录不等于背书,装之前看一眼权限标签,标了「需谨慎」的会读凭证或密钥。
你们站点上放这种工具页,会选页面还是独立应用?我目前更倾向页面,改起来快,回滚也简单。



