laoyang
|
8f8cffd69e
|
3.2.43: 修代码块重影与语言识别,含 4 个静默 bug (#12)
排查结论:不是插件冲突,对手是主题自己的 kratos.css。
现象一「重影/阴影」的真实成因是 CSS 优先级 + 行高错位:
kratos.css 的 .content code(0,4,1) / .content pre code(0,4,2) 抢走了
border-radius:4px、color:#333、font-size:13px。字号被顶到 13px 后
行高算成 21.06px,而行号槽是 12.5px/20.25px,每行错开 0.81px,
30 行累计 24px —— 视觉上就是「两层东西叠在一起」。
现象二「多一个 copy 按钮」未能复现:2 个页面实测每张卡恰好 1 个
.cb-copy;Prism.plugins 只有 autoloader,copy-to-clipboard 未注册;
Enlighter 插件目录不存在。已请用户指认页面。
修复:
- highlight.css 的选择器提到与原主题同级 (0,4,2),靠出现更晚取胜,
不用 !important。
- 顺带修掉 4 个静默 bug(都不报错、页面看着正常):
1. header.php 从未调 body_class(),裸 <body> ⇒ 所有挂 body_class
过滤器的类全部静默失效,包括行号开关 opt-ln(选项已开却不显示)。
2. 79 个代码块的语言写在 <pre lang=> 或 data-enlighter-language 上,
只读 <code> class 必然读不到 ⇒ 标签显示「—」。
3. 白名单 4 项指向未打包语言(powershell/dos/dockerfile/nginx)。
hljs 遇到不认识的语言不抛错,只 warn 一句就退回不高亮 ⇒
整块白板。站内这 4 种用量均为 0,属潜伏 bug。
4. hljs 把 plaintext 块改写成 language-undefined;highlightAuto
对纯文本返回字符串 'undefined',if (r.language) 会误当真值。
顺带收敛:yang_hl_languages() 原本手写第二份清单,与 yang_hl_norm_lang()
里的表互相漂移,改为从 yang_hl_known_map() 单一来源派生。
验证:
- 单测 44 + 24 断言全通过
- 反向验证 10 组注入全部变红(含专门注入「恢复手写清单」验证新判据)
- 全站 284 块直连数据库校验:568 通过 / 0 失败,
语言覆盖率 71.8% → 98.6%,残留与污染全 0
- 剩余 4 块显示「—」是正确降级(jsp×2、latex×2 未打包进 hljs)
- 夹具对照:新版 0 失败 vs 全旧版 10 失败
|
2026-10-26 11:00:47 +08:00 |
|
laoyang
|
da0d9ae4a1
|
代码高亮整套自研:10 浅 + 10 深配色、语言标签、评论区贴代码 (#11)
不再依赖第三方高亮插件,全部由主题自己实现。
主题配色(20 套)
- 浅色 10:github / vs / atom-one-light / idea / xcode /
stackoverflow-light / intellij-light / googlecode / magula / color-brewer
- 深色 10:github-dark / atom-one-dark / monokai / github-dark-dimmed /
a11y-dark / stackoverflow-dark / night-owl / srcery /
panda-syntax-dark / tomorrow-night-blue
- 深色卡片带 data-kind="dark",顶栏跟着换深色底
- 只加载当前选中的一套(20 套全加载会让后出现的规则压前面的,
切换配色容易"看起来没变")
代码语言标签(用户要求:防止复制错语言)
- 作者标了 language-xxx → 实线边框、正体
- 自动识别猜出来的 → 虚线边框、斜体
- 认不出来 → 显示 "—",仍保持虚线斜体(不冒充作者标注)
行号
- 默认关;行号槽在 <pre> 外面,复制天然不带行号
- 改掉原主题的 word-break:break-all(任意字符断行,代码像乱码)
- 归零 hljs 主题自带的 pre code.hljs{padding:1em},
否则代码被压低 1em、与行号槽错位 15.5px
复制
- 默认开;安全上下文判断 + execCommand 退路(HTTP 下 clipboard 是 undefined)
- 取 textContent 而非 innerHTML
- 默认 opacity:0、hover 显示、触屏覆盖回 1
(旧写法只在 @media(hover:none) 里写 1,等于空操作)
自动识别
- 做成选项,默认开
- 只对没标语言的块生效;站内实测长块准确率 22%,不能覆盖作者标注
评论区贴代码
- 评论工具条加"代码"按钮 + 29 种语言面板
- kses 放行 pre 并给 pre/code 放开 class
(WP 默认 pre 整条剥掉、code 属性全清,此前根本贴不了代码)
- 放行 pre 之后 wpautop/wptexturize/make_clickable 自动让路,
代码里的连续空行、引号、URL 都不会被改写
- comments.js 用占位符保护代码块,避免 walk() 的 /\n{3,}/ 压缩
其它
- 资源版本号改为读主题头,不再写死(写死会导致以后升级后
浏览器一直用旧缓存,改了 CSS/JS 完全不生效)
- 删除 footer.php 里旧的 Prism 兜底(两套高亮器同页会互相打架)
验收
- 用线上 284 个真实代码块跑产品代码:284/284 全部变卡片,内容丢字 0、双转义 0
- 47 个 text 标记全部映射到 plaintext(hljs 无 text 语言,不映射会静默不上色)
- 80 个裸 <pre>(无 code 子元素)全部覆盖
- 核心纯函数 65/65;核心反向 10/10 变红
- 浏览器端到端 32/32;行号几何逐行对齐偏差 0.00px,几何反向 4/4 变红
- 端到端反向 7/7 变红;语言标签反向 2/2 变红
- 全量 PHP 语法 95 文件 0 错误
发布:走 theme-update 通道(zip + readme + update.json),
未覆盖服务器主题目录;线上主题目录仍是 3.2.41,待后台升级。
|
2026-10-26 09:00:17 +08:00 |
|
laoyang
|
f3583e07c5
|
perf(lightbox): 点开图片不再白屏干等,先糊后清 #10
用户反馈:点一张图之后先是白背景渲染出来,图片迟迟不出现,感觉特别慢。
实测归因(_v40_slow.py,自建慢速 HTTP 服务,3.2 Mbps):
· 遮罩可见 31ms —— 纯 CSS 底色,一帧就画完,从来不是瓶颈
· 图片有像素 6 秒后仍然没有
线上原图最大 3.2MB(PUA的两面性与界定-scaled.png),3Mbps 下要 8 秒以上,
这段时间屏幕上是整片白 + 一个 0x0 的空 img。
三层改造:
1. 缩略图占位(blur-up):点开瞬间把正文里已经解码过的 currentSrc 顶上,
0 延迟就有像素;原图到了再淡入覆盖。
2. 原图淡入:is-ready 后 opacity 0→1,避免看到渐进渲染的半张图。
3. 空闲预取:requestIdleCallback 里串行预取视口上下 1.5 屏内的原图,
用 new Image() 不塞 DOM;尊重 saveData / slow-2g。
CSS 的 .yang-lb-stage 从 flex 改 grid,占位层/原图/转圈都 grid-area:1/1
叠在同一个格子(flex 会让子元素并排,absolute 又不参与居中)。
实测(_v40_opt2.py,5/0):
立刻点(最坏) 遮罩 25ms · 首帧有像素 25ms · 原图 15012ms
读 12 秒后点 遮罩 25ms · 首帧有像素 25ms · 原图 25ms(预取命中)
服务端各收到 1 次请求,预取一次命中、没有重复下载。
验证:交互 245/0(新增 J 段占位层与加载态 45 条)· 服务端 55/0(8.4+8.5)
· 演示页 34/0 · 反向验证 27/27(新增 U11~U14)
Refs #10
|
2026-10-25 23:03:13 +08:00 |
|
laoyang
|
7125fdd3ce
|
feat(lightbox): 正文图片点击在当前页放大、多图轮播、键盘切换
新增主题自带的图片灯箱,替代「点图片跳新标签页」的旧行为,
不再依赖第三方灯箱插件。
主要能力
· 正文里的图片链接改写成「在当前页覆盖展示原图」,不跳转
· 原图优先按附件 ID 取 full size(wp_get_attachment_image_src),
取不到才退回 href 自己 —— 不在前端从缩略图文件名反推原图地址
· 原图地址写在 href 里而不是 data-full:主题的 CDN 是整页输出缓冲
改写,只认 src= / href= 与 CSS url(),写 data-* 会绕回源站
· 多图左右箭头轮播(到头循环),键盘 ←↑ / →↓ 切换、Esc 关闭、
Home / End 跳首尾,点空白关闭,打开时锁滚动并在关闭后归还焦点
· 两套遮罩配色(白色默认 / 深色)与九档不透明度(默认 80%)
· 图片本身始终保持不透明:透明度只作用在遮罩底色上
兼容性处理
· 剥掉第三方灯箱插件留下的触发属性(data-rel / data-imagelightbox /
data-rl_title 等)。线上实测 100 篇文章 112 张图**全部**带这些属性,
若只「让给插件」则主题灯箱永不生效;同时关掉开关时一律不动,
插件可照常工作
· 移除 imgnofollow() 给图片链接加的 target="_blank" 与 rel,
链接不再承担跳转职责
· 无 JS 时 href 仍在,右键「在新标签页打开图片」照常可用
可读性
· 半透明遮罩下底部说明条自带更实的底(≥0.9),并按「遮罩底下是
纯黑」的最坏情况验证文字对比度 ≥ 4.5:1
· 行内不透明度样式用 [data-theme] 选择器,避免被样式表默认值压掉
(裸类名优先级不足,会让深色配色下透明度静默失效)
验证
· 服务端正文改写探针 51 通过 / 0 失败(PHP 8.4 与 8.5)
· 浏览器真实交互探针 200 通过 / 0 失败(两配色 × 80%,含 50%/100%)
· 上述两者的反向验证 21 项注入全部按预期捕获
· 三个改动文件 php -l 通过
Refs #10
|
2026-10-25 22:05:24 +08:00 |
|
laoyang
|
6f51d50a58
|
3.2.30: 文章目录进后台(新增「自动目录」标签页)—— 位置/插入点/默认展开可配,手写 [TOC] 永远优先
后台「主题设置」新增第 5 个标签页「自动目录」,7 个选项:
目录位置 正文中间 / 页面左侧(浮动)/ 页面右侧(浮动)
添加方式 手动(只认 [TOC])/ 自动
自动插入位置 文章开头 / 第一个 H1、H2 之前 / 文章结尾
默认状态 默认显示 / 默认隐藏
另外:目录标题、收录层级(H1~H4)、是否显示序号
设计要点:
- 插入方式拆成 toc_mode(manual/auto) x toc_anchor(start/first/end) 两个正交
字段,不合成一个四值下拉:侧栏模式下插入位置毫无意义,合并会产生歧义。
- 手写 [TOC] 绝对优先:yang_toc_plan() 里 $has_marker 最先返回,inline_at
='marker' 且 rail=false —— 否则同一篇会出现两份目录,老文章升级后突然多
出一个目录。这条是刻意守住的。
- 纯函数 + 薄壳分层:normalize_settings / plan / inject / build_list 全部不查库,
单进程可喂几十种组合;settings() 只负责读库 + 调纯函数 + static 缓存。
- <details open> 是唯一可靠的「默认收起」手段:展开态不接受 CSS 覆盖,只能
由 open 属性决定,所以隐藏时必须不输出该属性。
- 侧栏收起态必须 translateX(±100%) 完全移出视口:只做 opacity 会让透明面板
留在原位吃掉正文点击(探针 elementFromPoint 才抓得到)。
- yang_toc_rail_ready() 开关:侧栏在 wp_footer 输出,那时正文可能没走
the_content(缓存插件/OEmbed),标题没 id ⇒ 侧栏链接全跳不动却看起来正常。
宁可不出侧栏。
- 后台联动隐藏「插入位置」不用 jQuery show()/hide():会把 .section 的行内
display 写成 block,悄悄回退 3.2.28 的 display:flow-root BFC 修复。改用
class + display:none!important。
验证(全部在本轮重跑):
_test_toc.php 53/0 旧 TOC 行为回归
_toc330_logic.php 88/0 逻辑判据
_toc330_falsify 13/13 注入全变红且红对地方
_geo330_rail.js 73/0 侧栏真实几何(左/右 x 展开/收起 x 宽窄屏)
_geo330_falsify 8/8
_guard330.php 46/0 后台控件与运行时默认值双向一致
_guard330_falsify 8/8
_admin330_tab_check 36/0 新标签页几何 + 联动 + 载入态
_admin330_falsify 8/8
_admin328_check 13/0 3.2.28 布局回归
发布:只发 zip + readme + update.json 到 theme-update/,不动服务器主题目录,
用户在 WP 后台自行升级(沿用 3.2.24 起的策略)。
|
2026-10-25 12:18:52 +08:00 |
|
laoyang
|
fb12d58067
|
3.2.25: 评论框改为所见即所得编辑器(B/I/颜色/表情可视化+序列化白名单+纯文本粘贴);后台资源 enqueue 版本号改跟 THEME_VERSION(修设置页重排被浏览器缓存挡住的问题)
|
2026-10-24 22:38:10 +08:00 |
|
laoyang
|
fd27b4d218
|
3.2.24: 评论富文本工具条(B/I/颜色/表情移入)+ kses 放行 span+style + 后台设置页标签左列竖排重排
|
2026-10-24 21:59:06 +08:00 |
|
laoyang
|
cbe0f2dc59
|
3.2.18: 清明按节气换算、主题内 [TOC] 目录、重建评论区替代 wpDiscuz
三项功能:
1. 清明不再用固定 04-04
清明是节气,日期在 4/4~4/6 之间浮动。硬编码 04-04 实测 1900-2100
共 201 年里只有 76 年是对的(约 38%)。改为内嵌逐年表换算真实日期,
超出 1900-2100 返回 null 明确放弃,不退化成近似值。
兼容 3.2.17 及以前勾过的 '04-04' 键,升级后勾选不会被静默丢弃。
2. 主题内实现 [TOC]
文章里写 [TOC],该位置输出本文目录,点击跳到对应标题。
在 the_content 优先级 9 处理(早于 wpautop 10 / do_shortcode 11),
保证"补 id"与"扫目录"用的是同一份文本,href 与 id 必然对得上。
嵌套用深度归一化,h1→h3 跳级不会算错层级。
scroll-margin-top 声明式让位,原生锚点/外部 #hash/后退全都生效。
3. 重建评论区
旧实现的问题:列表渲染与 AJAX 渲染各写一份 HTML,已经分叉
(AJAX 返回的新评论没有回复按钮);<li> 被 <div> 包着,嵌套回复错位。
现在统一到 yang_comment_html() 单一渲染函数,列表与 AJAX 只差一个
is-new 类。同时修掉三处真实缺陷:
· 评论项用 flex 会把 <ol class="yang-children"> 当成第三个 flex 项,
子评论跑到父评论右侧、正文被挤到 156px、页面横向溢出 75px —— 改 grid
· 成功提示在 exitReplyMode() 之前设置,被其末尾的 setStatus('','')
擦掉,用户提交成功却看不到反馈 —— 调整顺序
· 窄屏媒体查询打不过深层选择器(媒体查询不增加特异性),
嵌套头像反向变大 —— 补深层覆盖
与 wpDiscuz 解耦:邮件模块不再无条件 return false(那等于永久关掉
notify_postauthor 且不报错);插件在场时不加载主题评论资源,
避免双份表单互抢。
验证:PHP 语法 73/73;_static_qingming 36、_test_toc 53、
_test_comments 62、_test_comments_falsify 17、
_toc_geometry 121、_toc_geometry_falsify 9、
_comments_geometry 98、_comments_geometry_falsify 23,全部 0 失败。
线上端到端 29/0(真实文章渲染目录 + 真实评论数据渲染)。
|
2026-10-24 01:03:36 +08:00 |
|
laoyang
|
4f0d19fb91
|
版本号 3.2.4 -> 3.2.5(修 Prism 报错,项目地址改为自建 Git)
## 修 Prism is not defined
首页控制台报 `Uncaught ReferenceError: Prism is not defined`,来源是
wp-editormd 插件(不是本主题):它在 Prism 脚本加载之前就无条件执行了
`Prism.plugins.autoloader.languages_path = "..."`。
线上页面里的真实顺序:
第 668 行 该赋值语句
第 695 行 prism-core.min.js
第 696 行 prism-autoloader.min.js
在 `wp_head` 优先级 0 垫一个最小空壳 `window.Prism`(含 plugins.autoloader
这条访问链路),让那句赋值有地方可写。已核对 prism-core.min.js 源码:它开头
只读 `u.Prism.manual` 与 `u.Prism.disableWorkerMessageHandler`,结尾
`global.Prism = Prism` 整体覆盖 —— 空壳必定被真实对象替换,不承担持久职责,
只为吸收那条过早的赋值。已用 jsdom 验证:去掉空壳重现原始报错,加上后消失,
且之后 `Prism.highlightAll` 仍可正常调用。
## 项目地址统一到 code.yangyq.net
原作者署名、原主题地址、README、语言包、JS 里的控制台横幅全部换成自建仓库地址。
LICENSE 文件保持原样不动(MIT 要求保留原始版权声明)。
## CDN 分支改成拿不到就回退本地
原来的 `g_cdn` 分支指向 `cdn.jsdelivr.net/gh/vtrois/kratos`,本仓库在自建
Gitea 上,jsDelivr 只认 github/npm/wordpress,实测该地址 404。现改为仅在
`YANG_THEME_CDN_REPO` 常量存在时才走 CDN,否则一律用
`get_template_directory_uri()`。留一个 404 的地址比留空更危险:页面能开、
样式全丢,极难排查。
## 顺带
- `.gitattributes` 补 `*.mo binary`:原来是靠"含 NUL"启发式判定,不是契约
- `update.json` 的版本号跟进到 3.2.5
- `kratos.min.js` / `kratos.min.css` 用压缩器重新生成,不手工改产物
|
2026-10-23 12:55:41 +08:00 |
|
laoyang
|
a826b26bee
|
从gitee代码库中初始化项目。
|
2022-01-07 11:15:42 +08:00 |
|