From 6507763e476f1981ee3beb0544bcc876d45fcdd0 Mon Sep 17 00:00:00 2001 From: Aki Kareha Date: Sat, 15 Nov 2025 18:43:05 +0900 Subject: [PATCH] Refactor diff formatter --- internal/format/diff.go | 90 ++++++++++++++++------------------ internal/format/doc.go | 2 + internal/format/nomark_test.go | 2 +- internal/format/util.go | 19 +++++++ 4 files changed, 64 insertions(+), 49 deletions(-) create mode 100644 internal/format/doc.go create mode 100644 internal/format/util.go diff --git a/internal/format/diff.go b/internal/format/diff.go index 5e792a7..6c12d7b 100644 --- a/internal/format/diff.go +++ b/internal/format/diff.go @@ -1,66 +1,60 @@ package format import ( - "bytes" "html/template" + "strings" ) -func detectLine(data []byte) (int, int) { - lineFeed := bytes.IndexByte(data, '\n') - if lineFeed == -1 { - lineFeed = len(data) - } - lineEnd := lineFeed - if lineEnd > 0 { - c := data[lineEnd-1] - if c == '\r' { - lineEnd -= 1 - } - } - nextLine := lineFeed + 1 - return lineEnd, nextLine -} - +// Diff formats diff text to HTML. func Diff(text string) string { - data := []byte(text) index := 0 - var html bytes.Buffer - lineNo := 0 - for index < len(data) { - lineEnd, nextLine := detectLine(data[index:]) - lineEnd += index - nextLine += index - line := data[index:lineEnd] - lineNo += 1 + // skip headers + lineNumber := 0 + for index < len(text) { + _, index = indexLineEnd(text, index) - if lineNo < 3 { - index = nextLine - continue + lineNumber += 1 + if lineNumber >= 3 { + break } + } + + var html strings.Builder + for index < len(text) { + lineEnd, nextLine := indexLineEnd(text, index) + line := text[index:lineEnd] + index = nextLine if len(line) < 1 { html.WriteString("
\n") - } else { - c := line[0] - htmlLine := template.HTMLEscapeString(string(line)) - if c == '+' { - html.WriteString("+") - html.WriteString("" + htmlLine[1:] + "
\n") - } else if c == '-' { - html.WriteString("-") - html.WriteString("" + htmlLine[1:] + "
\n") - } else if c == '@' { - html.WriteString("@") - html.WriteString(htmlLine[1:] + "
\n") - } else if c == ' ' { - html.WriteString(" ") - html.WriteString(htmlLine[1:] + "
\n") - } else { - html.WriteString(htmlLine + "
\n") - } + continue + } + + c := line[0] + htmlLine := template.HTMLEscapeString(string(line)) + if c == '+' { + html.WriteString("+") + html.WriteString("") + html.WriteString(htmlLine[1:]) + html.WriteString("
\n") + } else if c == '-' { + html.WriteString("-") + html.WriteString("") + html.WriteString(htmlLine[1:]) + html.WriteString("
\n") + } else if c == '@' { + html.WriteString("@") + html.WriteString(htmlLine[1:]) + html.WriteString("
\n") + } else if c == ' ' { + html.WriteString(" ") + html.WriteString(htmlLine[1:]) + html.WriteString("
\n") + } else { + html.WriteString(htmlLine) + html.WriteString("
\n") } - index = nextLine } return html.String() diff --git a/internal/format/doc.go b/internal/format/doc.go new file mode 100644 index 0000000..f32c8ad --- /dev/null +++ b/internal/format/doc.go @@ -0,0 +1,2 @@ +// Package format implements markup and other formatters. +package format diff --git a/internal/format/nomark_test.go b/internal/format/nomark_test.go index f1b8854..fb8c208 100644 --- a/internal/format/nomark_test.go +++ b/internal/format/nomark_test.go @@ -4,7 +4,7 @@ import "testing" var mockCfg = formatConfig{ image: imageConfig{ - domains: []string{"example.org", "example.net"}, + domains: []string{"example.org", "example.net"}, extensions: []string{"png", "jpeg"}, }, } diff --git a/internal/format/util.go b/internal/format/util.go new file mode 100644 index 0000000..61bc10e --- /dev/null +++ b/internal/format/util.go @@ -0,0 +1,19 @@ +package format + +import "strings" + +// indexLineEnd finds line end and start of next line +func indexLineEnd(text string, index int) (int, int) { + lineFeed := strings.IndexByte(text[index:], '\n') + if lineFeed == -1 { + return len(text), len(text) + } + lineFeed += index + lineEnd := lineFeed + if lineEnd > 0 { + if text[lineEnd-1] == '\r' { + lineEnd -= 1 + } + } + return lineEnd, lineFeed + 1 +}