[PATCH v2] Highlight primitive diff additions and deletions
Export this patch
---
Changes since v1:
- Fixes for the bugs mentioned in the reply
- A better hunk splitting algorithm
history/histweb/histview.go | 40 ++++++++++++++++++++++--
history/histweb/view_primitive_diff.html | 5 +--
history/revision.go | 18 +++++++++++
static/default.css | 18 +++++++++++
4 files changed, 77 insertions(+), 4 deletions(-)
diff --git a/history/histweb/histview.go b/history/histweb/histview.go
index 4737817..1f59d77 100644
--- a/history/histweb/histview.go
+++ b/history/histweb/histview.go
@@ -11,6 +11,7 @@ import (
"github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/viewutil"
"github.com/gorilla/mux"
+ "html/template"
"log"
"net/http"
"path/filepath"
@@ -125,6 +126,7 @@ var (
{{define "diff for at title"}}Разница для {{beautifulName .HyphaName}} для {{.Hash}}{{end}}
{{define "diff for at heading"}}Разница для <a href="/hypha/{{.HyphaName}}">{{beautifulName .HyphaName}}</a> для {{.Hash}}{{end}}
+{{define "no text diff available"}}Нет текстовой разницы.{{end}}
{{define "count pre"}}Отобразить{{end}}
{{define "count post"}}свежих правок.{{end}}
@@ -158,15 +160,49 @@ type primitiveDiffData struct {
*viewutil.BaseData
HyphaName string
Hash string
- Text string
+ Text template.HTML
}
func primitiveDiff(meta viewutil.Meta, h hyphae.Hypha, hash, text string) {
+ hunks := history.SplitPrimitiveDiff(text)
+ if len(hunks) > 0 {
+ var buf strings.Builder
+ for _, hunk := range hunks {
+ lines := strings.Split(hunk, "\n")
+ buf.WriteString(`<pre class="codeblock">`)
+ for i, line := range lines {
+ line = strings.Trim(line, "\r")
+ var class string
+ if len(line) > 0 {
+ switch line[0] {
+ case '+':
+ class = "primitive-diff__addition"
+ case '-':
+ class = "primitive-diff__deletion"
+ case '@':
+ class = "primitive-diff__context"
+ }
+ }
+ if i > 0 {
+ buf.WriteString("\n")
+ }
+ line = template.HTMLEscapeString(line)
+ fmt.Fprintf(&buf, `<code class="%s">%s</code>`,
+ class, line)
+ }
+ buf.WriteString(`</pre>`)
+ }
+ text = buf.String()
+ } else if text != "" {
+ text = template.HTMLEscapeString(text)
+ text = fmt.Sprintf(
+ `<pre class="codeblock"><code>%s</code></pre>`, text)
+ }
viewutil.ExecutePage(meta, chainPrimitiveDiff, primitiveDiffData{
BaseData: &viewutil.BaseData{},
HyphaName: h.CanonicalName(),
Hash: hash,
- Text: text,
+ Text: template.HTML(text),
})
}
diff --git a/history/histweb/view_primitive_diff.html b/history/histweb/view_primitive_diff.html
index c2025a0..135f41f 100644
--- a/history/histweb/view_primitive_diff.html
+++ b/history/histweb/view_primitive_diff.html
@@ -1,11 +1,12 @@
{{define "diff for at title"}}Diff of {{beautifulName .HyphaName}} at {{.Hash}}{{end}}
{{define "diff for at heading"}}Diff of <a href="/hypha/{{.HyphaName}}">{{beautifulName .HyphaName}}</a> at {{.Hash}}{{end}}
+{{define "no text diff available"}}No text diff available.{{end}}
{{define "title"}}{{template "diff for at title" .}}{{end}}
{{define "body"}}
<main class="main-width">
<article>
<h1>{{template "diff for at heading" .}}</h1>
- <pre class="codeblock"><code>{{.Text}}</code></pre>
+ {{if .Text}}{{.Text}}{{else}}{{template "no text diff available" .}}{{end}}
</article>
</main>
-{{end}}
\ No newline at end of file
+{{end}}
diff --git a/history/revision.go b/history/revision.go
index 4817aa1..74759c3 100644
--- a/history/revision.go
+++ b/history/revision.go
@@ -252,3 +252,21 @@ func PrimitiveDiffAtRevision(filepath, hash string) (string, error) {
}
return out.String(), err
}
+
+// SplitPrimitiveDiff splits a primitive diff of a single file into hunks.
+func SplitPrimitiveDiff(text string) (result []string) {
+ idx := strings.Index(text, "@@ -")
+ if idx < 0 {
+ return
+ }
+ text = text[idx:]
+ for {
+ idx = strings.Index(text, "\n@@ -")
+ if idx < 0 {
+ result = append(result, text)
+ return
+ }
+ result = append(result, text[:idx+1])
+ text = text[idx+1:]
+ }
+}
diff --git a/static/default.css b/static/default.css
index e966da0..8d09d53 100644
--- a/static/default.css
+++ b/static/default.css
@@ -911,3 +911,21 @@ body[data-rrh-addr^="/interwiki"] main form + form {
.img-gallery img { max-width: 100%; max-height: 50vh; }
figure { margin: 0; }
figcaption { padding-bottom: .5rem; }
+
+/*
+ * Primitive diff
+ */
+.primitive-diff__addition {
+ color: green;
+}
+.primitive-diff__deletion {
+ color: red;
+}
+.primitive-diff__context {
+ opacity: .5;
+}
+@media (prefers-color-scheme: dark) {
+ .primitive-diff__addition {
+ color: #4cd74c;
+ }
+}
--
2.37.0 (Apple Git-136)
Wonderful. Thanks!