Hugo 代码块 diff 实现。
缘起
类似 Git diff 功能。我在实现这个功能的时候,发现 Hugo 提供了一个 strings.Diff ↗。
以及 Syntax highlighting ↗ 提供了代码高亮功能。
但是红绿色的 diff 没有实现。因此搞了一个。
代码实现
首先,我这里配置是
[highlight]
noClasses = falsetoml
修改 layouts/_default/_markup/render-codeblock.html
{{/* ── 1. 构建 add_lines 行号集合 ── */}}
{{- $addLines := .Attributes.add_lines -}}
{{- $addSet := slice -}}
{{- if $addLines -}}
{{- range $addLines -}}
{{- $start := index . 0 -}}
{{- $end := index . 1 -}}
{{- range seq $start $end -}}
{{- $addSet = $addSet | append . -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- $delLines := .Attributes.del_lines -}}
{{- $delSet := slice -}}
{{- if $delLines -}}
{{- range $delLines -}}
{{- $start := index . 0 -}}
{{- $end := index . 1 -}}
{{- range seq $start $end -}}
{{- $delSet = $delSet | append . -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/* ── 2. Chroma 高亮,拿到 Inner(行级 HTML) ── */}}
{{- $result := transform.HighlightCodeBlock . -}}
{{/* ── 3. 按行处理,命中行注入 add class ── */}}
{{/* Inner 每行结构: <span class="line">...</span>\n */}}
{{- $lines := split $result.Inner "\n" -}}
{{- $lineNum := -1 -}}
{{- $rendered := slice -}}
{{- range $lines -}}
{{/* 跳过末尾空行 */}}
{{- if . -}}
{{- $lineNum = add $lineNum 1 -}}
{{- if in $addSet $lineNum -}}
{{/* 将 class="line" 替换为 class="line add" */}}
{{- $rendered = $rendered | append (replace . `class="line"` `class="line add"`) -}}
{{- else if in $delSet $lineNum -}}
{{/* 将 class="line" 替换为 class="line del" */}}
{{- $rendered = $rendered | append (replace . `class="line"` `class="line del"`) -}}
{{- else -}}
{{- $rendered = $rendered | append . -}}
{{- end -}}
{{- else -}}
{{- $rendered = $rendered | append . -}}
{{- end -}}
{{- end -}}
<-- 在 HTML 中使用 ──>
<pre><code>{{ delimit $rendered "\n" | safeHTML }}</code></pre>html
然后 hugo gen chromastyles --style=monokai 生成然后使用。
然后额外添加红绿色背景。因为是 Somnia 主题,所以添加的是:
/* Chroma 代码块 */
.chroma .hl::before { background-color: #e5e5e5 !important; }
.dark .chroma .hl::before { background-color: #3d4148 !important;}
.chroma .add { background-color: rgba(16, 185, 129, 0.16) }
.chroma .add::before {
background-color: rgba(16, 185, 129, 0.16) !important;
content: "+" !important;
}
.chroma .del { background-color: rgba(244, 63, 94, 0.16); }
.chroma .del::before {
background-color: rgba(244, 63, 94, 0.16) !important;
content: "-" !important;
}css
效果
fn main() {
let mut input_data = String::new();
std::io::stdin().read_line(&mut input_data).expect("read_line failed!");
match input_data.trim().parse::<i32>() {
Ok(data) => {
match data {
0..=10_0000 => println!("{}",f64::from(data)*0.1),
10_0001..=20_0000 => println!("{}",10.0*0.1+(f64::from(data-10))*0.75), //
20_0001..=40_0000 => println!("3ok"),
40_0001..=60_0000 => println!(""),
60_0001..=100_0000 => println!(""),
_ => println!("{}", data)
}
}
Err(_err) => {println!("{}",_err); }
}
}
// 模拟 知识点 : match
rust