You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go Webhook如何将Git Diff转为GitHub风格彩色HTML邮件?

把原始Diff转换成GitHub风格彩色HTML的Go实现方案

嗨,这个需求我刚好折腾过,给你几个实用的思路和具体步骤,帮你快速搞定:

核心思路:用成熟的语法高亮库处理Diff

手动解析Diff并渲染样式太容易踩坑(比如要处理上下文行、文件名、二进制文件等边缘情况),直接用Go生态里的语法高亮库是最高效的方案。首推Chroma——它支持Diff格式的语法解析,还能直接生成带GitHub/Bitbucket风格样式的HTML。

具体实现步骤

1. 安装依赖库

先拉取需要的包:

go get github.com/alecthomas/chroma/v2
go get github.com/alecthomas/chroma/v2/formatters/html
go get github.com/alecthomas/chroma/v2/lexers
go get github.com/alecthomas/chroma/v2/styles

2. 编写Diff转HTML的核心函数

这个函数会把原始Diff文本转换成带GitHub样式的完整HTML页面:

package main

import (
	"bytes"
	"fmt"
	"github.com/alecthomas/chroma/v2"
	"github.com/alecthomas/chroma/v2/formatters/html"
	"github.com/alecthomas/chroma/v2/lexers"
	"github.com/alecthomas/chroma/v2/styles"
)

// diffToHTML 把原始Diff文本转换成GitHub风格的彩色HTML
func diffToHTML(diff string) (string, error) {
	// 加载Diff对应的语法解析器
	lexer := lexers.Get("diff")
	if lexer == nil {
		lexer = lexers.Fallback
	}
	lexer = chroma.Coalesce(lexer)

	// 使用GitHub风格的高亮样式
	style := styles.Get("github")
	if style == nil {
		style = styles.Fallback
	}

	// 配置HTML格式化器:不显示行号,用CSS类来标记样式
	formatter := html.New(html.WithLineNumbers(false), html.WithClasses(true))

	// 解析Diff文本为Token流
	iterator, err := lexer.Tokenise(nil, diff)
	if err != nil {
		return "", err
	}

	// 生成带CSS类的HTML片段
	var buf bytes.Buffer
	if err := formatter.Format(&buf, style, iterator); err != nil {
		return "", err
	}

	// 组装完整的HTML页面,把样式内联到<head>(适配邮件客户端)
	fullHTML := fmt.Sprintf(`
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Commit Diff</title>
	<style>
		%s
	</style>
</head>
<body>
	<div style="max-width: 800px; margin: 0 auto; padding: 20px;">
		<h2>最新提交Diff</h2>
		<div class="chroma">%s</div>
	</div>
</body>
</html>
`, style.String(), buf.String())

	return fullHTML, nil
}

func main() {
	// 这里替换成你从Webhook或GitHub API获取的真实Diff内容
	sampleDiff := `diff --git a/main.go b/main.go
index 1234567..89abcde 100644
--- a/main.go
+++ b/main.go
@@ -1,5 +1,7 @@
 package main
 
 import "fmt"
+import "github.com/alecthomas/chroma/v2"
+
 func main() {
-	fmt.Println("Hello World")
+	fmt.Println("Hello Diff HTML")
 }
`
	htmlOutput, err := diffToHTML(sampleDiff)
	if err != nil {
		panic(err)
	}
	// 下一步:把htmlOutput作为邮件正文发送
	fmt.Println(htmlOutput)
}

3. 邮件发送的注意事项

  • 多格式邮件:同时发送HTML和纯文本版本(可以用github.com/jaytaylor/html2text把HTML转成纯文本),兼容所有邮件客户端。
  • 样式兼容性:部分邮件客户端对<style>标签支持有限,你可以用工具把CSS类转换成内联样式(比如github.com/vanng822/cssinliner),进一步提升兼容性。
  • 内容优化:可以在HTML里加上提交信息、仓库链接等上下文,让邮件更实用。

备选轻量方案(不依赖第三方库)

如果不想引入外部依赖,也可以手动解析Diff的结构:

  • 识别Diff里的文件名行(diff --git...、index...)
  • 区分删除行(以-开头)、新增行(以+开头)、上下文行(无符号)
  • 给不同类型的行加上对应的内联样式,比如:
    <div style="background-color: #ffeef0; padding: 2px 8px;">- fmt.Println("Hello World")</div>
    <div style="background-color: #e6ffed; padding: 2px 8px;">+ fmt.Println("Hello Diff HTML")</div>
    

不过这种方式需要自己处理Diff的各种语法细节,适合简单场景。

内容的提问来源于stack exchange,提问作者Egor Egorov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:53:56