diff --git a/input.css b/input.css index dc638bd..693642f 100644 --- a/input.css +++ b/input.css @@ -11,7 +11,7 @@ --color-paper-secondary: #78716c; --color-paper-tertiary: #d6d3d1; --color-paper-content: #292524; - --color-paper-code-block: #1c1917; + --color-paper-code-block: #eff1f5; --color-paper-code-bg: #f5f4f0; --color-paper-border: #e7e5e0; --color-paper-accent: #5c7a5e; @@ -45,7 +45,7 @@ --color-paper-secondary: #8c8981; --color-paper-tertiary: #3a3a3d; --color-paper-content: #d4d2cc; - --color-paper-code-block: #1e1f22; + --color-paper-code-block: #1e1e2e; --color-paper-code-bg: #28292d; --color-paper-border: #2a2b2e; --color-paper-accent: #7da97f; diff --git a/src/bin/generate_highlight_css.rs b/src/bin/generate_highlight_css.rs index 46ca8b6..f87ac00 100644 --- a/src/bin/generate_highlight_css.rs +++ b/src/bin/generate_highlight_css.rs @@ -16,6 +16,10 @@ //! - 深色主题:`.dark {base} { ... }` 与 `.dark {base} .kw { ... }`; //! - 其中 `{base}` 为 `.md-content pre code`,保证只影响正文代码块; //! - `.code` 是 syntect 的根作用域特殊类,只映射到 base 容器本身。 +//! +//! 背景色策略:syntect 输出的 `background-color` 会被剥离,代码块背景统一由 +//! `input.css` 中的 `--color-paper-code-block` 变量提供(亮色浅、暗色深), +//! 避免 `.code` span 与外层 `pre` 双层背景叠加导致的边缘色差。 use syntect::highlighting::ThemeSet; use syntect::html::{css_for_theme_with_class_style, ClassStyle}; @@ -100,6 +104,38 @@ fn minify_css(css: &str) -> String { out.trim().to_string() } +/// 从 CSS 规则体中移除 `background-color` 声明。 +/// +/// syntect 会为根作用域 `.code` 注入主题底色(如 Latte `#eff1f5`),这与 +/// 外层 `pre` 的 `--color-paper-code-block` 背景叠加会形成色差。这里只保留 +/// 前景色相关声明,让背景由单一来源控制。 +fn strip_background_color(body: &str) -> String { + body.split(';') + .filter(|decl| { + let trimmed = decl.trim(); + !trimmed.is_empty() + && !trimmed + .to_ascii_lowercase() + .starts_with("background-color") + }) + .collect::>() + .join(";") +} + +/// 剥离 CSS 字符串开头的 `/* ... */` 注释块(含其后的空白)。 +/// +/// syntect 输出的第一条规则选择器前会带主题头注释,这里在 `.code` 特判前 +/// 先清掉它,使根作用域类能被正确识别并映射到 base 容器本身。 +fn strip_leading_comment(s: &str) -> &str { + let trimmed = s.trim_start(); + if trimmed.starts_with("/*") { + if let Some(end) = trimmed.find("*/") { + return trimmed[end + 2..].trim_start(); + } + } + s +} + /// 将 syntect 生成的 CSS 选择器包装到指定的 base 选择器下,并可附加前缀。 /// /// syntect 原始输出形如: @@ -133,6 +169,10 @@ fn rewrite_rules(css: &str, base: &str, prefix: &str) -> String { pos += open + 1; continue; } + // syntect 会把主题头注释(/* theme ... */)粘在第一条规则的选择器前。 + // 注释虽在后续 minify 阶段会去除,但此处的 .code 特判发生在 minify 之前, + // 所以这里先剥掉前导注释块,避免根作用域类匹配失败。 + let selector = strip_leading_comment(selector); // 查找配对的右大括号,处理可能的嵌套 {} let after_open = pos + open + 1; @@ -154,6 +194,13 @@ fn rewrite_rules(css: &str, base: &str, prefix: &str) -> String { continue; } + // 剥离 syntect 注入的 background-color,代码块背景改由 + // `--color-paper-code-block` 变量统一提供(见 input.css)。 + let body = strip_background_color(body); + if body.is_empty() { + continue; + } + // .code 是 syntect 用于根作用域的特殊类,直接映射到 base 容器 if selector == ".code" { out.push_str(&format!("{}{} {{\n{}\n}}\n\n", prefix, base, body));