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
相关产品推荐
相关产品推荐

