# Hugo 代码块 diff

> [Hugo 代码块 diff](https://www.ftls.xyz/posts/2026-03-28-hugo-code-diff/)
> Penned by [恐咖兵糖](https://www.ftls.xyz/) on 2026-03-28


Hugo 代码块 diff 实现。

<!--more-->

## 缘起

类似 Git diff 功能。我在实现这个功能的时候，发现 Hugo 提供了一个 [strings.Diff](https://www.gohugo.cn/functions/strings/diff/)。
以及 [Syntax highlighting](https://gohugo.io/content-management/syntax-highlighting/) 提供了代码高亮功能。

但是红绿色的 diff 没有实现。因此搞了一个。

## 代码实现

首先，我这里配置是

```toml
[highlight]
noClasses = false
```

修改 `layouts/_default/_markup/render-codeblock.html` 

```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>
```


然后 `hugo gen chromastyles --style=monokai` 生成然后使用。
然后额外添加红绿色背景。因为是 Somnia 主题，所以添加的是：

```css
/* 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;
}
```

## 效果

```rust {hl_lines=[1,"2-3"] add_lines=[5,"6-7"] del_lines=[9,"10-11"]}
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
```
