排查结论:不是插件冲突,对手是主题自己的 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 失败
238 lines
8.0 KiB
CSS
238 lines
8.0 KiB
CSS
/**
|
||
* 代码块样式(highlight.js 自研接管后的卡片外观)
|
||
*
|
||
* 与 kratos.css 里原有那段的关系:
|
||
* 原有 `.k-main .details .article .content pre { … }` 里有
|
||
* `background-color:#f8f8f8`、`font-size:11px`、**`word-break:break-all`**。
|
||
* 最后这条会在任意字符处断行,代码看起来像乱码 —— 必须压掉。
|
||
* 本文件加载在 kratos.css 之后,用更高的特异性覆盖。
|
||
*/
|
||
|
||
/* ── 卡片外壳 ── */
|
||
.k-main .details .article .content .cb,
|
||
.comment-body .cb,
|
||
.cb {
|
||
position: relative;
|
||
margin: 14px 0;
|
||
border: 1px solid #d0d7de;
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
}
|
||
|
||
/* ── 顶部条:语言标签 + 复制按钮 ── */
|
||
.k-main .details .article .content .cb .cb-bar,
|
||
.cb .cb-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 6px 10px;
|
||
background: #f6f8fa;
|
||
border-bottom: 1px solid #d0d7de;
|
||
font-size: 12px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* 语言标签:让人一眼看到"这是 Java",防止把 Python 和 Java 的实现贴反。
|
||
站内实测有 19 篇文章含 ≥2 种语言、38 处相邻代码块语言不同 —— 确有实用价值。 */
|
||
.cb .cb-lang {
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
letter-spacing: .02em;
|
||
color: #656d76;
|
||
padding: 1px 6px;
|
||
border-radius: 4px;
|
||
border: 1px solid #d0d7de;
|
||
background: #fff;
|
||
text-transform: none;
|
||
}
|
||
|
||
/* 🔴 自动识别出来的标签要**看得出来是猜的**:虚线边框 + 斜体。
|
||
站内 18 个 ≥4 行的未标注代码块实测自动识别只对了 4 个(22%)——
|
||
如果把它画得和作者标的一模一样,等于把 78% 的错误结果伪装成确定事实。 */
|
||
.cb .cb-lang[data-guess="1"] {
|
||
border-style: dashed;
|
||
font-style: italic;
|
||
opacity: .8;
|
||
}
|
||
|
||
.cb .cb-actions {
|
||
display: flex;
|
||
gap: 6px;
|
||
}
|
||
|
||
.cb .cb-copy {
|
||
font: inherit;
|
||
font-size: 11px;
|
||
padding: 3px 9px;
|
||
cursor: pointer;
|
||
color: #656d76;
|
||
background: #fff;
|
||
border: 1px solid #d0d7de;
|
||
border-radius: 5px;
|
||
transition: color .12s, border-color .12s, opacity .12s;
|
||
opacity: 0;
|
||
}
|
||
.cb:hover .cb-copy,
|
||
.cb .cb-copy:focus-visible { opacity: 1; }
|
||
.cb .cb-copy:hover { color: #0969da; border-color: #0969da; }
|
||
.cb .cb-copy.done { color: #1a7f37; border-color: #1a7f37; }
|
||
.cb .cb-copy.err { color: #cf222e; border-color: #cf222e; }
|
||
|
||
/* 🔴 触屏兜底:没有 hover 的设备上按钮必须常驻,否则永远点不到。
|
||
注意这里必须是「默认隐藏 + 触屏覆盖回 1」的写法。
|
||
如果默认是 1、只在 @media(hover:none) 里再写 1,那条规则等于空操作 ——
|
||
因为 1 本来就是默认值,删掉也不会变,故障测不出来。 */
|
||
@media (hover: none) {
|
||
.cb .cb-copy { opacity: 1; }
|
||
}
|
||
|
||
/* ── 代码区:左行号槽 + 右可滚动 pre ── */
|
||
.cb .cb-body {
|
||
display: flex;
|
||
align-items: stretch;
|
||
}
|
||
|
||
/* 行号槽。
|
||
🔴 它在 <pre> **外面**,所以行号文字永远不会进 code.textContent ⇒
|
||
"复制不带行号"是结构保证的,不靠 JS 删、也不靠正则过滤。
|
||
🔴 除了用户要求,这里还有一层现实原因:hljs 输出的是 token span,
|
||
没有行结构,想在 span 上挂 ::before 计数是挂不住的(没有 span.line 这种元素)。
|
||
原型阶段就是这么写的,结果 CSS 规则齐全、画面上零行号。 */
|
||
.cb .cb-ln {
|
||
display: none;
|
||
flex: 0 0 auto;
|
||
padding: 12px 0 12px 10px;
|
||
text-align: right;
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||
font-size: 12.5px;
|
||
line-height: 1.62;
|
||
color: #9aa0a6;
|
||
background: #f6f8fa;
|
||
border-right: 1px solid #eaecef;
|
||
user-select: none;
|
||
-webkit-user-select: none;
|
||
overflow: hidden;
|
||
}
|
||
.cb .cb-ln > span { display: block; }
|
||
|
||
/* 行号开关(body 上带 opt-ln 类时显示)*/
|
||
.opt-ln .cb .cb-ln { display: block; }
|
||
|
||
/* 🔴 这里必须把 padding 显式写成 12px,和 .cb-ln 的 padding-top 对齐。
|
||
每套 hljs 官方主题都自带 `pre code.hljs{padding:1em}`,会把代码整体
|
||
往下压 1em。行号槽没有这个 padding,于是第一行代码的 top 比行号低 15.5px,
|
||
屏幕上就是"第 1 行代码旁边写着 2",往下每行错一位。
|
||
实测(原型页):修前逐行偏差 15.5px,修后 0.00px。 */
|
||
.k-main .details .article .content .cb pre,
|
||
.cb pre {
|
||
margin: 0;
|
||
padding: 12px 14px;
|
||
overflow-x: auto;
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||
font-size: 12.5px;
|
||
line-height: 1.62;
|
||
/* 🔴 原有主题写的是 word-break:break-all,会在任意字符断行,代码像乱码。
|
||
长行必须横向滚动,不能折断。 */
|
||
word-break: normal;
|
||
overflow-wrap: normal;
|
||
white-space: pre;
|
||
tab-size: 4;
|
||
border: 0;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
}
|
||
|
||
/* 主题自带的 code padding 必须归零,否则与行号槽错位(见上) */
|
||
.cb .cb-body > pre > code.hljs {
|
||
padding: 0;
|
||
overflow-x: visible;
|
||
}
|
||
|
||
.cb .cb-body > pre { flex: 1 1 auto; min-width: 0; }
|
||
|
||
/* 🔴 卡片里的 code 必须彻底摆脱原主题 `.content code` 的影响。
|
||
*
|
||
* 原主题 kratos.css 有两条规则(实测优先级):
|
||
* `.k-main .details .article .content code` → (0,4,1)
|
||
* margin:0 3px; padding:2px 4px; border-radius:4px;
|
||
* background-color:#eff0f1; color:#333; font-size:13px
|
||
* `.k-main .details .article .content pre code` → (0,4,2)
|
||
* margin:0; padding:0; background-color:transparent
|
||
*
|
||
* 后者只救了 margin/padding/background。**border-radius、color、font-size
|
||
* 全都漏了**,于是:
|
||
* · border-radius:4px → 代码区里嵌一块 4px 圆角,和卡片 8px 圆角打架,
|
||
* 视觉上就是用户说的「有阴影/重影」
|
||
* · font-size:13px → 代码字号被顶大,行高跟着从 20.25px 变 21.06px,
|
||
* 而行号槽用的是 12.5px/20.25px ⇒ 每行错开 0.81px,
|
||
* 30 行累计错 24px,行号与代码彻底对不上
|
||
* · color:#333 → 把 hljs 主题给 <pre> 的基色(.hljs{color:#000})
|
||
* 覆盖成固定的深灰。深色配色下就是深灰压深底,看不清
|
||
*
|
||
* 修法:选择器强度提到与 `.content pre code` 同级的 (0,4,2) ——
|
||
* 靠**出现更晚**取胜,不靠 !important(!important 会让用户/插件再也没法覆盖)。
|
||
* 显式写 border-radius:0 而不是依赖"没声明就继承",因为 border-radius
|
||
* 不继承、初始值是 0,但原主题那条规则会直接命中 code。 */
|
||
.k-main .details .article .content .cb pre code,
|
||
.comment-body .cb pre code,
|
||
.cb pre code {
|
||
display: block;
|
||
margin: 0;
|
||
padding: 0;
|
||
border: 0;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
font-size: inherit;
|
||
line-height: inherit;
|
||
color: inherit;
|
||
font-family: inherit;
|
||
/* 原主题给了 word-break:inherit,pre 上是 normal,这里跟住 */
|
||
word-break: inherit;
|
||
overflow-wrap: inherit;
|
||
}
|
||
|
||
/* 深色配色必须让卡片自带深色底与深色顶条。
|
||
站点正文是浅色,若只在浅底上印深色配色,
|
||
token 与背景对比不足(现有 Prism 出问题的地方正在这里)。 */
|
||
.cb[data-kind="dark"] {
|
||
border-color: #30363d;
|
||
background: #0d1117;
|
||
}
|
||
.cb[data-kind="dark"] .cb-bar {
|
||
background: #21262d;
|
||
border-bottom-color: #30363d;
|
||
}
|
||
.cb[data-kind="dark"] .cb-lang {
|
||
background: #21262d;
|
||
border-color: #30363d;
|
||
color: #8b949e;
|
||
}
|
||
.cb[data-kind="dark"] .cb-copy {
|
||
background: #21262d;
|
||
border-color: #30363d;
|
||
color: #8b949e;
|
||
}
|
||
.cb[data-kind="dark"] .cb-copy:hover {
|
||
color: #58a6ff;
|
||
border-color: #58a6ff;
|
||
}
|
||
.cb[data-kind="dark"] .cb-ln {
|
||
background: #161b22;
|
||
border-right-color: #30363d;
|
||
color: #6e7681;
|
||
}
|
||
|
||
/* 窄屏:行号槽收窄,避免挤占代码宽度 */
|
||
@media (max-width: 560px) {
|
||
.cb .cb-ln { padding: 12px 0 12px 6px; font-size: 11px; }
|
||
.cb .cb-ln > span { padding-right: 4px; }
|
||
.cb pre { padding: 12px 10px; font-size: 12px; }
|
||
}
|
||
|
||
/* 打印:行号与复制按钮都不需要 */
|
||
@media print {
|
||
.cb .cb-ln, .cb .cb-actions { display: none !important; }
|
||
.cb { break-inside: avoid; }
|
||
} |