惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Palo Alto Networks Blog
P
Proofpoint News Feed
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
罗磊的独立博客
J
Java Code Geeks
月光博客
月光博客
F
Full Disclosure
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
U
Unit 42
WordPress大学
WordPress大学
A
About on SuperTechFans
C
Cyber Attacks, Cyber Crime and Cyber Security
SecWiki News
SecWiki News
Security Latest
Security Latest
C
Check Point Blog
C
CERT Recently Published Vulnerability Notes
小众软件
小众软件
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
B
Blog RSS Feed
V
Visual Studio Blog
博客园_首页
NISL@THU
NISL@THU
I
Intezer
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
The Register - Security
The Register - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Latest news
Latest news
Project Zero
Project Zero
博客园 - 叶小钗
C
Cybersecurity and Infrastructure Security Agency CISA
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
博客园 - 【当耐特】
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threat Research - Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
T
Tor Project blog
V
Vulnerabilities – Threatpost
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网

李锋镝的博客

LiteLLM 本地代理搭建 Claude-HUD 使用文档 译文:如何将单体应用拆解为微服务 codebase-memory-mcp 极简完整使用指南 Claude Haiku 4.5、Claude Sonnet 4.6、Claude Opus 4.7 区别以及各自的新特性 SchedulingConfigurer详解 踩坑60+次后,我终于搞懂 Claude Skill 怎么写才会真的触发 Everything Claude Code 详细使用文档 配置Jackson使用字段而不是getter/setter来序列化和反序列化 这个域名注册整整十年了,十年时间,真快啊 Claude Code全维度实战指南:从入门到精通,解锁AI编程新范式 Apollo配置中心中的protalDB的作用是什么 org.apache.ibatis.plugin.Interceptor类详细介绍及使用 岁末 Excel2016右键新建工作表,打开时提示“因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配。”的解决办法 wordpress增加说说功能 玩博客的人是不是越来越少了? Java 为什么有这么多 “O”? 别再背线程池的七大参数了,现在面试官都这么问 2024年11月1号 农历十月初一 我的第一个WordPress插件:Dylan Custom Plugin上线了 推荐一款比较养眼的Xshell配色方案 hnswlib installation failed 开工啦~ 阳了... MybatisCodeHelperPro激活 @Async注解的坑 新买的笔记本发货啦…… 这个中秋节感觉过的好累啊 IDEA下载源码报:Cannot connect to the Maven process. Try again later. RocketMQ的push消费方式实现详解 看病难~取药难~~ 笑死、腹肌……根本不可能有腹肌的~~ 居家办公了~ C# 11 的这个新特性,我愿称之最强! IntelliJ IDEA 2020.3.x永久白嫖(Windows/Mac) IDEA无限试用方法【2020.3最新亲测有效】 SpringBoot使用注解的方式构建Elasticsearch查询语句,实现多条件的复杂查询 UUID太长怎么办?快来试试NanoId 忽然发现,在校大学生可以免费领一年有道云笔记会员~ 醒醒~补个税了 使用itext和freemarker来根据Html模板生成PDF文件,加水印、印章 来来来,用python画一个冰墩墩儿 SpringBoot整合GraphQL入门教程 办理居住证困难重重啊! 妈呀,昨天晚上睡觉做了一晚上的梦,可累死我了 感觉Typecho很简洁啊…… WordPress的自动更新好烦啊 BeanCopier工具类(性能优化工具类) 内存屏障浅析 居住证可算是申请通过了…… 试了下壁挂炉供暖 关于重阳节 居住证签注... Spring Boot 2.x使用PostgreSQL数据库 十一节后开工头一天,修了个耳机…… 玉楼春·尊前拟把归期说 nginx反向代理配置去除前缀 1931→2021! Navicat Premium数据库账号密码解密 百度的索引量数据现在有点儿太夸张了吧? 哇塞~这个小姐姐实在太惊艳了…… 关于8月29号下午博客故障的一些记录 如何形象的描述反应式编程中的背压(Backpressure)机制? 基于Java8的Either类 海琴烟~~~ JMX监控权限认证配置 IntelliJ IDEA 2019.3.3 永久激活 破解[Windows] SpringBoot整合Elasticsearch详细步骤以及代码示例(附源码) SpringBoot整合Elasticsearch游标查询(scroll) GitLab创建新项目,初次提交命令和流程 吐槽下Google浏览器~ 从零搭建Spring Cloud Gateway网关(一) 从零搭建Spring Cloud Gateway网关(二)—— 打印请求响应日志 博客有logo啦 你的答案 数据库事务的一点简单总结 Spring Boot发展史(Spring Boot介绍) 【漫画】戏说外行对程序员的误会有多深 【收藏】从面试官角度观察到的程序员技能瓶颈,同时给出突破瓶颈的建议 Git中.gitignore文件不起作用的解决办法 背影 - 朱自清 jmap命令(jdk1.8) 彻底搞懂mysql日志系统binlog,redolog,undolog 出院了~~~ linux中ftp查看不到文件列表的问题 PHP版本怎么更新啊…… 成语接龙 StarUML4.0破解文件 Java SPI详解 WordPress评论框增加自定义表情 因在公司上不正经网站,我没过试用期… 优化了MYSQL大量写入问题,老板奖励了1000块给我 不慌不忙的坚强(林徽因39段最美文字!) ConcurrentHashMap常用方法源码解析(jdk1.8) 我是如何失去团队掌控的? HBASE填坑日志 关闭apache httpclient4.5 DEBUG日志 使用OpenShift搭建k8s集群 SonarQube Scanner的配置与使用简介
Kratos+ —— Kratos 主题二次开发记录
李锋镝 · 2026-06-12 · via 李锋镝的博客

基于 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 代理、.htaccess rewrite)——都引入了不必要的复杂度,最后回到最朴素的方案。
  • 使用 @highlightjs/cdn-assets 而不是 highlight.js npm 包——后者发布的是 CommonJS(var hljs = require('./core')),浏览器直接 <script> 加载会报 require is not defined;前者才是浏览器可用的 UMD 构建。
  • prism-themes 社区扩展包单独维护版本号(KRATOS_PRISM_THEMES_VER = 1.9.0),独立于 Prism 核心,便于跟随各自更新。

2. Gutenberg 粘贴 Markdown 自动保留语言

这是最折腾的一个功能。问题链:

  1. 在 Gutenberg "代码"块粘贴 Markdown 文本(含 html 围栏);
  2. WordPress 内置 markdown converter (showdown) 转出 <pre><code class="language-html">...
  3. Gutenberg 的 core/code 区块默认 schema 不接受 <code> 上的 class 属性,DOM cleaner 把 class 剥掉;
  4. 数据库里只剩裸 <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 !importantcode { 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):

  1. git push origin v1.x.x 推送 tag;
  2. workflow 自动校验 style.css 的 Version 与 tag 一致;
  3. git archive 出快照、删 .idea/ CLAUDE.md 等开发文件;
  4. 打成 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_kratoskratos-plus 改了文件夹名后,wp_optionsstylesheet / 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

八、感谢

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/article/cha-jian/4724