diff --git a/history/revision.go b/history/revision.go
index 9f5becb..916cb4a 100644
--- a/history/revision.go
+++ b/history/revision.go
@@ -2,16 +2,67 @@ package history
import (
"fmt"
+ "html"
"log/slog"
+ "net/url"
"os"
"regexp"
"strconv"
"strings"
"time"
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
"github.com/bouncepaw/mycorrhiza/internal/files"
)
+// WithRevisions returns an HTML representation of `revs` that is meant to be inserted in a history page.
+func WithRevisions(hyphaName string, revs []Revision) string {
+ var buf strings.Builder
+
+ for _, grp := range groupRevisionsByMonth(revs) {
+ currentYear := grp[0].Time.Year()
+ currentMonth := grp[0].Time.Month()
+ sectionId := fmt.Sprintf("%04d-%02d", currentYear, currentMonth)
+
+ buf.WriteString(fmt.Sprintf(
+ `
+
+ %d %s
+
+ `,
+ sectionId, sectionId, currentYear, currentMonth.String(),
+ ))
+
+ for _, rev := range grp {
+ buf.WriteString(fmt.Sprintf(
+ `
+
+ %s
+
+ %s
+ %s `,
+ rev.Hash, hyphaName,
+ rev.timeToDisplay(),
+ rev.Hash, hyphaName, rev.Hash,
+ html.EscapeString(rev.Message),
+ ))
+
+ if rev.Username != "anon" {
+ buf.WriteString(fmt.Sprintf(
+ `by %s `,
+ cfg.UserHypha, rev.Username, rev.Username,
+ ))
+ }
+
+ buf.WriteString(" \n")
+ }
+
+ buf.WriteString(` `)
+ }
+
+ return buf.String()
+}
+
// Revision represents a revision of a hypha.
type Revision struct {
// Hash is usually short.
@@ -24,6 +75,62 @@ type Revision struct {
hyphaeAffectedBuf []string
}
+// HyphaeDiffsHTML returns a comma-separated list of diffs links of current revision for every affected file as HTML string.
+func (rev Revision) HyphaeDiffsHTML() string {
+ entries := rev.hyphaeAffected()
+ if len(entries) == 1 {
+ return fmt.Sprintf(
+ `%s `,
+ rev.Hash, entries[0], rev.Hash,
+ )
+ }
+
+ var buf strings.Builder
+ for i, hyphaName := range entries {
+ if i > 0 {
+ buf.WriteString(`, `)
+ }
+ buf.WriteString(``)
+ if i == 0 {
+ buf.WriteString(rev.Hash)
+ buf.WriteString(" ")
+ }
+ buf.WriteString(hyphaName)
+ buf.WriteString(` `)
+ }
+ return buf.String()
+}
+
+// descriptionForFeed generates a good enough HTML contents for a web feed.
+func (rev *Revision) descriptionForFeed() string {
+ return fmt.Sprintf(
+ `
%s (by %s at %s)
+Hyphae affected: %s
+%s `,
+ rev.Message, rev.Username, rev.TimeString(),
+ rev.HyphaeLinksHTML(),
+ rev.textDiff(),
+ )
+}
+
+// HyphaeLinksHTML returns a comma-separated list of hyphae that were affected by this revision as HTML string.
+func (rev Revision) HyphaeLinksHTML() string {
+ var buf strings.Builder
+ for i, hyphaName := range rev.hyphaeAffected() {
+ if i > 0 {
+ buf.WriteString(`, `)
+ }
+
+ urlSafeHyphaName := url.PathEscape(hyphaName)
+ buf.WriteString(fmt.Sprintf(`%s `, urlSafeHyphaName, hyphaName))
+ }
+ return buf.String()
+}
+
// gitLog calls `git log` and parses the results.
func gitLog(args ...string) ([]Revision, error) {
args = append([]string{
diff --git a/history/view.qtpl b/history/view.qtpl
deleted file mode 100644
index dfba661..0000000
--- a/history/view.qtpl
+++ /dev/null
@@ -1,73 +0,0 @@
-{% import "fmt" %}
-{% import "github.com/bouncepaw/mycorrhiza/internal/cfg" %}
-
-HyphaeLinksHTML returns a comma-separated list of hyphae that were affected by this revision as HTML string.
-{% func (rev Revision) HyphaeLinksHTML() %}
-{% stripspace %}
- {% for i, hyphaName := range rev.hyphaeAffected() %}
- {% if i > 0 %}
- ,
- {% endif %}
- {%s hyphaName %}
- {% endfor %}
-{% endstripspace %}
-{% endfunc %}
-
-
-HyphaeDiffsHTML returns a comma-separated list of diffs links of current revision for every affected file as HTML string.
-{% func (rev Revision) HyphaeDiffsHTML() %}
- {% code entries := rev.hyphaeAffected() %}
-{% stripspace %}
- {% if len(entries) == 1 %}
- {%s rev.Hash %}
- {% else %}
- {% for i, hyphaName := range entries %}
- {% if i > 0 %}
- ,
- {% endif %}
-
- {% if i == 0 %}
- {%s rev.Hash %}
- {% endif %}
- {%s hyphaName %}
- {% endfor %}
- {% endif %}
-{% endstripspace %}
-{% endfunc %}
-
-descriptionForFeed generates a good enough HTML contents for a web feed.
-{% func (rev *Revision) descriptionForFeed() %}
-{%s rev.Message %} (by {%s rev.Username %} at {%s rev.TimeString() %})
-Hyphae affected: {%= rev.HyphaeLinksHTML() %}
-{%s rev.textDiff() %}
-{% endfunc %}
-
-WithRevisions returns an html representation of `revs` that is meant to be inserted in a history page.
-{% func WithRevisions(hyphaName string, revs []Revision) %}
-{% for _, grp := range groupRevisionsByMonth(revs) %}
- {% code
- currentYear := grp[0].Time.Year()
- currentMonth := grp[0].Time.Month()
- sectionId := fmt.Sprintf("%04d-%02d", currentYear, currentMonth)
- %}
-
-
- {%d currentYear %} {%s currentMonth.String() %}
-
-
- {% for _, rev := range grp %}
-
-
- {%s rev.timeToDisplay() %}
-
- {%s rev.Hash %}
- {%s rev.Message %}
- {% if rev.Username != "anon" %}
- by {%s rev.Username %}
- {% endif %}
-
- {% endfor %}
-
-
-{% endfor %}
-{% endfunc %}
diff --git a/history/view.qtpl.go b/history/view.qtpl.go
deleted file mode 100644
index 7708c28..0000000
--- a/history/view.qtpl.go
+++ /dev/null
@@ -1,384 +0,0 @@
-// Code generated by qtc from "view.qtpl". DO NOT EDIT.
-// See https://github.com/valyala/quicktemplate for details.
-
-//line history/view.qtpl:1
-package history
-
-//line history/view.qtpl:1
-import "fmt"
-
-//line history/view.qtpl:2
-import "github.com/bouncepaw/mycorrhiza/internal/cfg"
-
-// HyphaeLinksHTML returns a comma-separated list of hyphae that were affected by this revision as HTML string.
-
-//line history/view.qtpl:5
-import (
- qtio422016 "io"
-
- qt422016 "github.com/valyala/quicktemplate"
-)
-
-//line history/view.qtpl:5
-var (
- _ = qtio422016.Copy
- _ = qt422016.AcquireByteBuffer
-)
-
-//line history/view.qtpl:5
-func (rev Revision) StreamHyphaeLinksHTML(qw422016 *qt422016.Writer) {
-//line history/view.qtpl:5
- qw422016.N().S(`
-`)
-//line history/view.qtpl:7
- for i, hyphaName := range rev.hyphaeAffected() {
-//line history/view.qtpl:8
- if i > 0 {
-//line history/view.qtpl:8
- qw422016.N().S(`, `)
-//line history/view.qtpl:10
- }
-//line history/view.qtpl:10
- qw422016.N().S(``)
-//line history/view.qtpl:11
- qw422016.E().S(hyphaName)
-//line history/view.qtpl:11
- qw422016.N().S(` `)
-//line history/view.qtpl:12
- }
-//line history/view.qtpl:13
- qw422016.N().S(`
-`)
-//line history/view.qtpl:14
-}
-
-//line history/view.qtpl:14
-func (rev Revision) WriteHyphaeLinksHTML(qq422016 qtio422016.Writer) {
-//line history/view.qtpl:14
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line history/view.qtpl:14
- rev.StreamHyphaeLinksHTML(qw422016)
-//line history/view.qtpl:14
- qt422016.ReleaseWriter(qw422016)
-//line history/view.qtpl:14
-}
-
-//line history/view.qtpl:14
-func (rev Revision) HyphaeLinksHTML() string {
-//line history/view.qtpl:14
- qb422016 := qt422016.AcquireByteBuffer()
-//line history/view.qtpl:14
- rev.WriteHyphaeLinksHTML(qb422016)
-//line history/view.qtpl:14
- qs422016 := string(qb422016.B)
-//line history/view.qtpl:14
- qt422016.ReleaseByteBuffer(qb422016)
-//line history/view.qtpl:14
- return qs422016
-//line history/view.qtpl:14
-}
-
-// HyphaeDiffsHTML returns a comma-separated list of diffs links of current revision for every affected file as HTML string.
-
-//line history/view.qtpl:18
-func (rev Revision) StreamHyphaeDiffsHTML(qw422016 *qt422016.Writer) {
-//line history/view.qtpl:18
- qw422016.N().S(`
- `)
-//line history/view.qtpl:19
- entries := rev.hyphaeAffected()
-
-//line history/view.qtpl:19
- qw422016.N().S(`
-`)
-//line history/view.qtpl:21
- if len(entries) == 1 {
-//line history/view.qtpl:21
- qw422016.N().S(``)
-//line history/view.qtpl:22
- qw422016.E().S(rev.Hash)
-//line history/view.qtpl:22
- qw422016.N().S(` `)
-//line history/view.qtpl:23
- } else {
-//line history/view.qtpl:24
- for i, hyphaName := range entries {
-//line history/view.qtpl:25
- if i > 0 {
-//line history/view.qtpl:25
- qw422016.N().S(`, `)
-//line history/view.qtpl:27
- }
-//line history/view.qtpl:27
- qw422016.N().S(``)
-//line history/view.qtpl:29
- if i == 0 {
-//line history/view.qtpl:30
- qw422016.E().S(rev.Hash)
-//line history/view.qtpl:30
- qw422016.N().S(` `)
-//line history/view.qtpl:31
- }
-//line history/view.qtpl:32
- qw422016.E().S(hyphaName)
-//line history/view.qtpl:32
- qw422016.N().S(` `)
-//line history/view.qtpl:33
- }
-//line history/view.qtpl:34
- }
-//line history/view.qtpl:35
- qw422016.N().S(`
-`)
-//line history/view.qtpl:36
-}
-
-//line history/view.qtpl:36
-func (rev Revision) WriteHyphaeDiffsHTML(qq422016 qtio422016.Writer) {
-//line history/view.qtpl:36
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line history/view.qtpl:36
- rev.StreamHyphaeDiffsHTML(qw422016)
-//line history/view.qtpl:36
- qt422016.ReleaseWriter(qw422016)
-//line history/view.qtpl:36
-}
-
-//line history/view.qtpl:36
-func (rev Revision) HyphaeDiffsHTML() string {
-//line history/view.qtpl:36
- qb422016 := qt422016.AcquireByteBuffer()
-//line history/view.qtpl:36
- rev.WriteHyphaeDiffsHTML(qb422016)
-//line history/view.qtpl:36
- qs422016 := string(qb422016.B)
-//line history/view.qtpl:36
- qt422016.ReleaseByteBuffer(qb422016)
-//line history/view.qtpl:36
- return qs422016
-//line history/view.qtpl:36
-}
-
-// descriptionForFeed generates a good enough HTML contents for a web feed.
-
-//line history/view.qtpl:39
-func (rev *Revision) streamdescriptionForFeed(qw422016 *qt422016.Writer) {
-//line history/view.qtpl:39
- qw422016.N().S(`
-`)
-//line history/view.qtpl:40
- qw422016.E().S(rev.Message)
-//line history/view.qtpl:40
- qw422016.N().S(` (by `)
-//line history/view.qtpl:40
- qw422016.E().S(rev.Username)
-//line history/view.qtpl:40
- qw422016.N().S(` at `)
-//line history/view.qtpl:40
- qw422016.E().S(rev.TimeString())
-//line history/view.qtpl:40
- qw422016.N().S(`)
-Hyphae affected: `)
-//line history/view.qtpl:41
- rev.StreamHyphaeLinksHTML(qw422016)
-//line history/view.qtpl:41
- qw422016.N().S(`
-`)
-//line history/view.qtpl:42
- qw422016.E().S(rev.textDiff())
-//line history/view.qtpl:42
- qw422016.N().S(`
-`)
-//line history/view.qtpl:43
-}
-
-//line history/view.qtpl:43
-func (rev *Revision) writedescriptionForFeed(qq422016 qtio422016.Writer) {
-//line history/view.qtpl:43
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line history/view.qtpl:43
- rev.streamdescriptionForFeed(qw422016)
-//line history/view.qtpl:43
- qt422016.ReleaseWriter(qw422016)
-//line history/view.qtpl:43
-}
-
-//line history/view.qtpl:43
-func (rev *Revision) descriptionForFeed() string {
-//line history/view.qtpl:43
- qb422016 := qt422016.AcquireByteBuffer()
-//line history/view.qtpl:43
- rev.writedescriptionForFeed(qb422016)
-//line history/view.qtpl:43
- qs422016 := string(qb422016.B)
-//line history/view.qtpl:43
- qt422016.ReleaseByteBuffer(qb422016)
-//line history/view.qtpl:43
- return qs422016
-//line history/view.qtpl:43
-}
-
-// WithRevisions returns an html representation of `revs` that is meant to be inserted in a history page.
-
-//line history/view.qtpl:46
-func StreamWithRevisions(qw422016 *qt422016.Writer, hyphaName string, revs []Revision) {
-//line history/view.qtpl:46
- qw422016.N().S(`
-`)
-//line history/view.qtpl:47
- for _, grp := range groupRevisionsByMonth(revs) {
-//line history/view.qtpl:47
- qw422016.N().S(`
- `)
-//line history/view.qtpl:49
- currentYear := grp[0].Time.Year()
- currentMonth := grp[0].Time.Month()
- sectionId := fmt.Sprintf("%04d-%02d", currentYear, currentMonth)
-
-//line history/view.qtpl:52
- qw422016.N().S(`
-
-`)
-//line history/view.qtpl:72
- }
-//line history/view.qtpl:72
- qw422016.N().S(`
-`)
-//line history/view.qtpl:73
-}
-
-//line history/view.qtpl:73
-func WriteWithRevisions(qq422016 qtio422016.Writer, hyphaName string, revs []Revision) {
-//line history/view.qtpl:73
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line history/view.qtpl:73
- StreamWithRevisions(qw422016, hyphaName, revs)
-//line history/view.qtpl:73
- qt422016.ReleaseWriter(qw422016)
-//line history/view.qtpl:73
-}
-
-//line history/view.qtpl:73
-func WithRevisions(hyphaName string, revs []Revision) string {
-//line history/view.qtpl:73
- qb422016 := qt422016.AcquireByteBuffer()
-//line history/view.qtpl:73
- WriteWithRevisions(qb422016, hyphaName, revs)
-//line history/view.qtpl:73
- qs422016 := string(qb422016.B)
-//line history/view.qtpl:73
- qt422016.ReleaseByteBuffer(qb422016)
-//line history/view.qtpl:73
- return qs422016
-//line history/view.qtpl:73
-}
diff --git a/main.go b/main.go
index 21dd33f..5ba03fc 100644
--- a/main.go
+++ b/main.go
@@ -1,10 +1,12 @@
// Command mycorrhiza is a program that runs a mycorrhiza wiki.
//
-//go:generate go run github.com/valyala/quicktemplate/qtc -dir=history
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=mycoopts
package main
import (
+ "log/slog"
+ "os"
+
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/internal/backlinks"
"github.com/bouncepaw/mycorrhiza/internal/categories"
@@ -19,8 +21,6 @@ import (
"github.com/bouncepaw/mycorrhiza/web"
"github.com/bouncepaw/mycorrhiza/web/static"
"github.com/bouncepaw/mycorrhiza/web/viewutil"
- "log/slog"
- "os"
)
func main() {