基于 Seaton Jiang 的 Kratos v4.3.2 二次开发,遵循 GPL-3.0 协议。
仓库:https://github.com/lifengdi/kratos-plus
维护:Dylan Li,版本 1.0.0,发布于 2026-06-11。
一、为什么要做这件事
原版 Kratos 是个清爽好看的经典 PHP 博客主题,但用一阵子之后我列了一长串想改的地方:
- 代码块没有语法高亮——技术博客几乎不可用;
- 布局是写死的 8/4 双栏——窄屏挤、宽屏空;
- 评论区没有任何反垃圾机制——一夜被刷 200 条 spam;
- CSF(codestar-framework)框架的 Font Awesome / CodeMirror CDN 全部 404——后台主题设置打开就一堆 console 错;
- Gutenberg 粘贴 Markdown 时丢语言信息——代码块没有任何语言标记。
干脆 fork 一份独立维护,命名 Kratos+。这篇文档是首版(v1.0.0)的完整改动记录。
二、核心新功能
1. 三引擎代码高亮(最大工程量)
后台 → 全站配置 → 代码高亮(独立 section):
| 维度 | 选项 |
|---|---|
| 高亮方案 | Prism.js(默认) / highlight.js / highlight.php(服务端) |
| 资源加载方式 | CDN / 本地缓存(一键预下载所有语言+主题,2MB) |
| CDN 根路径 | 默认 jsdelivr,可改 unpkg / 国内镜像 |
| Prism 主题 | 45 款(核心 8 + prism-themes 扩展 37) |
| highlight 主题 | 73 款(hljs 与 highlight.php 共用) |
| 主题预览 | 实时预览面板(带 toolbar/copy 按钮) |
| 显示行号 | 仅 Prism / hljs 方案 |
几个细节决策:
- 三引擎并存而不是只支持一个:Prism.js 用得最广、可视化好;highlight.js 自带 100+ 语言自动检测;highlight.php 是服务端渲染,对 SEO 和缓存最友好——三种方案各有优势,让作者自选。
- 本地缓存 = "全量预下载",不是按需懒加载:一次切换、一次下载、之后纯静态服务。这意味着 Apache / Nginx / Caddy / IIS 任何 web 服务器都不需要 rewrite 规则。试过其它路线(PHP 代理、
.htaccessrewrite)——都引入了不必要的复杂度,最后回到最朴素的方案。 - 使用
@highlightjs/cdn-assets而不是highlight.jsnpm 包——后者发布的是 CommonJS(var hljs = require('./core')),浏览器直接<script>加载会报require is not defined;前者才是浏览器可用的 UMD 构建。 prism-themes社区扩展包单独维护版本号(KRATOS_PRISM_THEMES_VER = 1.9.0),独立于 Prism 核心,便于跟随各自更新。
2. Gutenberg 粘贴 Markdown 自动保留语言
这是最折腾的一个功能。问题链:
- 在 Gutenberg "代码"块粘贴 Markdown 文本(含
html围栏); - WordPress 内置 markdown converter (showdown) 转出
<pre><code class="language-html">...; - 但 Gutenberg 的
core/code区块默认 schema 不接受<code>上的class属性,DOM cleaner 把 class 剥掉; - 数据库里只剩裸
<pre><code>...,前台靠 highlightAuto 推测——HTML 经常被识别成 xml。
试了好几个方案才解决:
- ❌
addFilter('blocks.registerBlockType')—— 注册时机晚于 core 块,不生效; - ❌ 直接 mutate 已注册块的 transforms.from —— schema 改对了,但 pasteHandler 内部走全局 cleaner,class 仍被剥;
- ❌ wrap
wp.blocks.pasteHandler—— Gutenberg 内部 webpack import,不走 namespace 引用; - ✅ 拦截 contenteditable 元素的 paste 事件(capture 阶段,先于 React 委托)→ 解析 Markdown 成结构化片段(heading / paragraph / fence)→ 用
wp.blocks.createBlock('core/code', { content, className: 'language-xxx' })直接构造 block 实例,完全跳过 pasteHandler 的清洗链路。
成功后链路终点:数据库存的就是
<!-- wp:code {"className":"language-html"} -->
<pre class="wp-block-code language-html"><code>...</code></pre>
<!-- /wp:code -->
前台 Prism / hljs / highlight.php 三引擎都按 language-html 渲染,零依赖 highlightAuto,100% 准确。
辅助:在区块设置侧边栏加了 "代码语言" 下拉(50+ 主流语言),不写围栏的作者也能直接选。
3. 自定义版面布局
| 选项 | 范围 | 默认 | 说明 |
|---|---|---|---|
| 主体宽度 | 5–11 | 8 | Bootstrap 12 栅格列宽 |
| 侧边栏宽度 | 1–7 | 4 | 同上,建议两值之和 ≤ 12 |
| 页面主体最大宽度 | 960px – 不限 | 1280 | 大屏 1310px 断点以上的容器 max-width |
写了个 PHP helper kratos_layout_cols() 集中处理 clamp 与 fallback;模板里 <div class="col-lg-..."> 全替换成动态读取选项。
同时修复了一个连带 bug:
.k-main .details .toolbar主题 CSS 的卡片样式(margin/padding/box-shadow)跟 Prism toolbar 插件 class 冲突——重置 wrapper、按钮 hover 浮现,跟主题视觉协调。
4. 评论数学验证码
后台 → 全站配置 → 功能配置 → 评论验证码:
- 开关 + 数字最大值(5–99,默认 10)
- 运算符随机
+/-,减法时确保x ≥ y不出负数 - 题目存 transient(10 分钟有效),答错或过期一次性失效
- 答错后 Ajax 自动刷新新题(不需要整页刷新)
- 答对提交成功后也刷新一道新题,防止下次重复利用 token
- 静态缓存兼容:HTML 里只占位,DOMContentLoaded 时拉新题——整页缓存(WP Super Cache / Cloudflare)不会让所有访客拿到同一个 token
UI 位置:评论 textarea 下方那一行,紧贴表情按钮右侧([😀] [7 + 3 =] [ ])。
5. 哀悼功能改为全站生效
原版 mourning() 函数里写了 is_home() &&——只在首页变灰。重大社会哀悼场景显然应全站生效,去掉这个条件即可,subtitle 文案也跟着改。
三、若干"框架级"修复
CSF 死 CDN 替换(必修)
CSF 框架硬编码了字节跳动 CDN(lf26-cdn-tos.bytecdntp.com)的 Font Awesome / CodeMirror / Leaflet / WebFontLoader——这家 CDN 在 2024 年下线了。后台打开主题设置就是满屏 console 红字、CodeMirror 加载失败、Leaflet 地图字段挂。
修复:直接改 CSF 内 vendored 副本的 cdn_url,替换为 jsdelivr 上的等价资源:
| 原 CDN | 替换为 |
|---|---|
lf26-cdn-tos/cdn/font-awesome/5.15.4/... |
cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/... |
lf26-cdn-tos/cdn/codemirror/<v>/... |
cdn.jsdelivr.net/npm/codemirror@<v>/lib/... 主文件,addon/mode 保持原相对路径 |
lf26-cdn-tos/cdn/leaflet/<v>/... |
cdn.jsdelivr.net/npm/leaflet@<v>/dist/... |
lf26-cdn-tos/cdn/webfont/1.6.28/... |
cdn.jsdelivr.net/npm/webfontloader@1.6.28/webfontloader.js |
CodeMirror 还有一个前端动态加载 mode 文件的二级问题:CSF 把 cdn_url 传给前端 loadmode 用作根路径,loadmode 在浏览器里运行时拼 <base>/mode/<lang>/<lang>.js,不走 PHP enqueue → style_loader_src filter 摸不到。所以 vendored 副本里 cdn_url 的硬编码必须直接改文件本身。
"主题自带的 code 样式"覆盖代码高亮
主题原本有几条 .k-main .details .article .content pre 规则强制 background: #272822 !important、code { color: #e83e8c },会覆盖任何代码高亮主题。修复:给所有这类规则加 :not([class*="language-"]):not(.hljs) 排除,让 Prism / hljs 标记过的元素跳过主题样式。
文章聚合小工具(Kratos+ - 文章聚合)
侧边栏宽度可调后,原本 .nav-tabs 的 padding 在窄列宽下会让"最新/热点/随机" 3 个 tab 换行。给小工具范围内的 nav 加 flex: 1 1 0 + nowrap + 文字省略,三个 tab 永远在同一行。
四、自动更新
启用 plugin-update-checker(PUC v5)的 GitHub Release 模式:
$kratosPlusUpdater = PucFactory::buildUpdateChecker(
'https://github.com/lifengdi/kratos-plus/',
get_template_directory() . '/style.css',
'kratos-plus'
);
$kratosPlusUpdater->setBranch('main');
$kratosPlusUpdater->getVcsApi()->enableReleaseAssets();
发布流程交给 GitHub Actions(.github/workflows/release.yml):
git push origin v1.x.x推送 tag;- workflow 自动校验
style.css的 Version 与 tag 一致; git archive出快照、删.idea/CLAUDE.md等开发文件;- 打成
kratos-plus-x.y.z.zip上传到 GitHub Release。
之后所有装了 Kratos+ 的 WordPress 站后台 → 主题列表会出现"有可用更新"按钮,跟更新插件一样的体验。
五、品牌与版权
| 字段 | 值 |
|---|---|
| Theme Name | Kratos+ |
| Slug | kratos-plus |
| Version | 1.0.0 |
| Author | Dylan Li |
| License | GPL-3.0(继承自 Kratos) |
按 GPL-3.0 要求保留:
- 全部 22 个 PHP 文件头里
@author Seaton Jiang原署名(追加@author Dylan Li (Kratos+ fork)共同维护行,未删除); - 后台"关于主题 → 版权声明"段落明确说明二次开发关系;
- LICENSE 文件未动。
前台页脚保持简洁(仅显示 Theme Kratos+ By Dylan Li),原作者致谢放在源代码与后台版权声明里——这符合 GPL-3.0 的最低要求,前台展示属于"礼仪"而非协议义务。
六、踩过的坑(按时间顺序记录,给以后的自己看)
1. CSF subtitle 写 HTML 字面量
后台代码高亮选项的 subtitle 我一开始写了 启用/禁用文章 <pre><code> 代码块语法高亮——浏览器把 <pre><code> 当真元素渲染了,结果选项后面挂着个奇怪的等宽字体小框。改成纯文本就好。
2. admin_print_styles 钩子不传 $hook_suffix
我写了 function (xxx_admin_styles, $hook) { strpos($hook, 'kratos-options') } 想精准注入 CSS——但 admin_print_styles 钩子不传 $hook 参数,只有带后缀的 admin_print_styles-{hook} 才传。结果 $hook = null,函数立刻 return,CSS 永远没输出。改用 get_current_screen()->id 判断。
3. rsync --exclude='vendor/' 的子目录连带屏蔽
不带前导 / 的 rsync exclude 会匹配所有层级里同名目录。结果 inc/update-checker/vendor/(含 Parsedown)和 inc/codestar-framework/assets/scss/vendor/ 都被误删,启用 PUC 自动更新时报 Class "Parsedown" not found。修复:所有排除项加 / 前缀锚定到主题根。
4. 主题目录名重命名时数据库滞后
dylan_kratos → kratos-plus 改了文件夹名后,wp_options 里 stylesheet / template / current_theme 三个键还指向旧 slug,前台直接 fallback 到默认主题。必须同时改三处:源目录、部署目录、数据库三个键。在 PHP 里用一个事务原子化更新这三个键,避免中间状态。
5. 数据库 serialized 数组里的旧路径
主题选项(图片 URL 等 8 处)保存时用了绝对 URL http://.../themes/dylan_kratos/...,目录改名后这些 URL 全 404。不能用 SQL REPLACE,因为 serialized 字符串带长度前缀,简单替换会破坏数据结构。正确做法:unserialize → 递归替换 → serialize。
七、新增的文件 / 目录
| 路径 | 用途 |
|---|---|
inc/theme-codehighlight.php |
三引擎代码高亮的所有逻辑(PHP 端) |
inc/theme-comment-captcha.php |
评论验证码 |
inc/highlight-php/ |
scrivo/highlight.php 库(vendored,~1.8MB) |
assets/js/codehl-block-editor.js |
Gutenberg 编辑器扩展(语言下拉 + paste 拦截) |
.github/workflows/release.yml |
GitHub Actions 自动发布 workflow |
八、感谢
- Seaton Jiang —— Kratos 原作者,主题骨架和很多模板逻辑是他的工作;
- Prism.js / highlight.js / scrivo/highlight.php —— 代码高亮三引擎;
- PrismJS/prism-themes —— 37 款社区主题;
- @highlightjs/cdn-assets —— 浏览器可用的 hljs UMD 构建;
- YahnisElsts/plugin-update-checker —— GitHub Release 自动更新;
- codestar-framework —— 主题选项框架(CSF)。
除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接


文章评论