mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-12-12 05:20:26 +00:00
Add recent changes page
This commit is contained in:
parent
0e6c22080b
commit
4cf5937361
10
README.md
10
README.md
@ -1,6 +1,13 @@
|
||||
# 🍄 MycorrhizaWiki 0.8
|
||||
# 🍄 MycorrhizaWiki 0.9
|
||||
A wiki engine.
|
||||
|
||||
## 0.9
|
||||
This is a development branch for 0.9 version. Features I want to implement in this release:
|
||||
* [x] Recent changes page.
|
||||
* [ ] Hypha deletion.
|
||||
* [ ] Hypha renaming.
|
||||
* [ ] Support async git ops.
|
||||
|
||||
## Installation
|
||||
```sh
|
||||
git clone --recurse-submodules https://github.com/bouncepaw/mycorrhiza
|
||||
@ -31,5 +38,4 @@ Help is always needed. We have a [tg chat](https://t.me/mycorrhizadev) where som
|
||||
* Tagging system
|
||||
* Authorization
|
||||
* Better history viewing
|
||||
* Recent changes page
|
||||
* More markups
|
||||
|
2
go.mod
2
go.mod
@ -2,4 +2,4 @@ module github.com/bouncepaw/mycorrhiza
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/valyala/quicktemplate v1.6.2
|
||||
require github.com/valyala/quicktemplate v1.6.3
|
||||
|
8
go.sum
8
go.sum
@ -1,11 +1,11 @@
|
||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.15.1/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
|
||||
github.com/valyala/quicktemplate v1.6.2 h1:k0vgK7zlmFzqAoIBIOrhrfmZ6JoTGJlLRPLbkPGr2/M=
|
||||
github.com/valyala/quicktemplate v1.6.2/go.mod h1:mtEJpQtUiBV0SHhMX6RtiJtqxncgrfmjcUy5T68X8TM=
|
||||
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
|
||||
github.com/valyala/quicktemplate v1.6.3 h1:O7EuMwuH7Q94U2CXD6sOX8AYHqQqWtmIk690IhmpkKA=
|
||||
github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"log"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
@ -31,6 +32,58 @@ type Revision struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// TimeString returns a human readable time representation.
|
||||
func (rev Revision) TimeString() string {
|
||||
return rev.Time.Format(time.RFC822)
|
||||
}
|
||||
|
||||
// HyphaeLinks returns a comma-separated list of hyphae that were affected by this revision as HTML string.
|
||||
func (rev Revision) HyphaeLinks() (html string) {
|
||||
// diff-tree --no-commit-id --name-only -r
|
||||
var (
|
||||
// List of files affected by this revision, one per line.
|
||||
out, err = gitsh("diff-tree", "--no-commit-id", "--name-only", "-r", rev.Hash)
|
||||
// set is used to determine if a certain hypha has been already noted (hyphae are stored in 2 files at most).
|
||||
set = make(map[string]bool)
|
||||
isNewName = func(hyphaName string) bool {
|
||||
if _, present := set[hyphaName]; present {
|
||||
return false
|
||||
} else {
|
||||
set[hyphaName] = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, filename := range strings.Split(out.String(), "\n") {
|
||||
// If filename has an ampersand:
|
||||
if strings.IndexRune(filename, '&') >= 0 {
|
||||
// Remove ampersanded suffix from filename:
|
||||
ampersandPos := strings.LastIndexByte(filename, '&')
|
||||
hyphaName := string([]byte(filename)[0:ampersandPos]) // is it safe?
|
||||
if isNewName(hyphaName) {
|
||||
// Entries are separated by commas
|
||||
if len(set) > 1 {
|
||||
html += `<span aria-hidden="true">, </span>`
|
||||
}
|
||||
html += fmt.Sprintf(`<a href="/rev/%[1]s/%[2]s">%[2]s</a>`, rev.Hash, hyphaName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return html
|
||||
}
|
||||
|
||||
func (rev Revision) RecentChangesEntry() (html string) {
|
||||
return fmt.Sprintf(`
|
||||
<li><time>%s</time></li>
|
||||
<li>%s</li>
|
||||
<li>%s</li>
|
||||
<li>%s</li>
|
||||
`, rev.TimeString(), rev.Hash, rev.HyphaeLinks(), rev.Message)
|
||||
}
|
||||
|
||||
// Path to git executable. Set at init()
|
||||
var gitpath string
|
||||
|
||||
|
@ -6,9 +6,30 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/templates"
|
||||
)
|
||||
|
||||
func RecentChanges(n int) string {
|
||||
var (
|
||||
out, err = gitsh(
|
||||
"log", "--oneline", "--no-merges",
|
||||
"--pretty=format:\"%h\t%ce\t%ct\t%s\"",
|
||||
)
|
||||
revs []Revision
|
||||
)
|
||||
if err == nil {
|
||||
for _, line := range strings.Split(out.String(), "\n") {
|
||||
revs = append(revs, parseRevisionLine(line))
|
||||
}
|
||||
}
|
||||
entries := make([]string, len(revs))
|
||||
for i, rev := range revs {
|
||||
entries[i] = rev.RecentChangesEntry()
|
||||
}
|
||||
return templates.RecentChangesHTML(entries, n)
|
||||
}
|
||||
|
||||
// Revisions returns slice of revisions for the given hypha name.
|
||||
func Revisions(hyphaName string) ([]Revision, error) {
|
||||
var (
|
||||
@ -48,7 +69,7 @@ func (rev *Revision) AsHtmlTableRow(hyphaName string) string {
|
||||
<td><time>%s</time></td>
|
||||
<td><a href="/rev/%s/%s">%s</a></td>
|
||||
<td>%s</td>
|
||||
</tr>`, rev.Time.Format(time.RFC822), rev.Hash, hyphaName, rev.Hash, rev.Message)
|
||||
</tr>`, rev.TimeString(), rev.Hash, hyphaName, rev.Hash, rev.Message)
|
||||
}
|
||||
|
||||
// See how the file with `filepath` looked at commit with `hash`.
|
||||
|
17
main.go
17
main.go
@ -10,6 +10,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/templates"
|
||||
@ -83,6 +85,20 @@ func handlerRandom(w http.ResponseWriter, rq *http.Request) {
|
||||
http.Redirect(w, rq, "/page/"+randomHyphaName, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// Recent changes
|
||||
func handlerRecentChanges(w http.ResponseWriter, rq *http.Request) {
|
||||
log.Println(rq.URL)
|
||||
var (
|
||||
noPrefix = strings.TrimPrefix(rq.URL.String(), "/recent-changes/")
|
||||
n, err = strconv.Atoi(noPrefix)
|
||||
)
|
||||
if err == nil {
|
||||
util.HTTP200Page(w, base(strconv.Itoa(n)+" recent changes", history.RecentChanges(n)))
|
||||
} else {
|
||||
http.Redirect(w, rq, "/recent-changes/20", http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.Println("Running MycorrhizaWiki β")
|
||||
|
||||
@ -108,6 +124,7 @@ func main() {
|
||||
http.HandleFunc("/list", handlerList)
|
||||
http.HandleFunc("/reindex", handlerReindex)
|
||||
http.HandleFunc("/random", handlerRandom)
|
||||
http.HandleFunc("/recent-changes/", handlerRecentChanges)
|
||||
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
|
||||
http.ServeFile(w, rq, WikiDir+"/static/favicon.ico")
|
||||
})
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit bdaaab62574023487610d608d1e9f2f351707a7f
|
||||
Subproject commit 2c0e43199ed28f7022a38463a0eec3af3ecb03c9
|
40
templates/recent_changes.qtpl
Normal file
40
templates/recent_changes.qtpl
Normal file
@ -0,0 +1,40 @@
|
||||
{% func RecentChangesHTML(changes []string, n int) %}
|
||||
<main class="recent-changes">
|
||||
<h1>Recent Changes</h1>
|
||||
|
||||
<nav class="recent-changes__count">
|
||||
See
|
||||
{% for _, m := range []int{20, 0, 50, 0, 100} %}
|
||||
{% switch m %}
|
||||
{% case 0 %}
|
||||
<span aria-hidden="true">|</span>
|
||||
{% case n %}
|
||||
<b>{%d n %}</b>
|
||||
{% default %}
|
||||
<a href="/recent-changes/{%d m %}">{%d m %}</a>
|
||||
{% endswitch %}
|
||||
{% endfor %}
|
||||
recent changes
|
||||
</nav>
|
||||
|
||||
{% comment %}
|
||||
Here I am, willing to add some accesibility using ARIA. Turns out,
|
||||
role="feed" is not supported in any screen reader as of September
|
||||
2020. At least web search says so. Even JAWS doesn't support it!
|
||||
How come? I'll add the role anyway. -- bouncepaw
|
||||
{% endcomment %}
|
||||
|
||||
<section class="recent-changes__list" role="feed">
|
||||
{% if len(changes) == 0 %}
|
||||
<p>Could not find any recent changes.</p>
|
||||
{% else %}
|
||||
{% for i, entry := range changes %}
|
||||
<ul class="recent-changes__entry" role="article"
|
||||
aria-setsize="{%d n %}" aria-posinset="{%d i %}">
|
||||
{%s= entry %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</section>
|
||||
</main>
|
||||
{% endfunc %}
|
156
templates/recent_changes.qtpl.go
Normal file
156
templates/recent_changes.qtpl.go
Normal file
@ -0,0 +1,156 @@
|
||||
// Code generated by qtc from "recent_changes.qtpl". DO NOT EDIT.
|
||||
// See https://github.com/valyala/quicktemplate for details.
|
||||
|
||||
//line templates/recent_changes.qtpl:1
|
||||
package templates
|
||||
|
||||
//line templates/recent_changes.qtpl:1
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line templates/recent_changes.qtpl:1
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line templates/recent_changes.qtpl:1
|
||||
func StreamRecentChangesHTML(qw422016 *qt422016.Writer, changes []string, n int) {
|
||||
//line templates/recent_changes.qtpl:1
|
||||
qw422016.N().S(`
|
||||
<main class="recent-changes">
|
||||
<h1>Recent Changes</h1>
|
||||
|
||||
<nav class="recent-changes__count">
|
||||
See
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:7
|
||||
for _, m := range []int{20, 0, 50, 0, 100} {
|
||||
//line templates/recent_changes.qtpl:7
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:8
|
||||
switch m {
|
||||
//line templates/recent_changes.qtpl:9
|
||||
case 0:
|
||||
//line templates/recent_changes.qtpl:9
|
||||
qw422016.N().S(`
|
||||
<span aria-hidden="true">|</span>
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:11
|
||||
case n:
|
||||
//line templates/recent_changes.qtpl:11
|
||||
qw422016.N().S(`
|
||||
<b>`)
|
||||
//line templates/recent_changes.qtpl:12
|
||||
qw422016.N().D(n)
|
||||
//line templates/recent_changes.qtpl:12
|
||||
qw422016.N().S(`</b>
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:13
|
||||
default:
|
||||
//line templates/recent_changes.qtpl:13
|
||||
qw422016.N().S(`
|
||||
<a href="/recent-changes/`)
|
||||
//line templates/recent_changes.qtpl:14
|
||||
qw422016.N().D(m)
|
||||
//line templates/recent_changes.qtpl:14
|
||||
qw422016.N().S(`">`)
|
||||
//line templates/recent_changes.qtpl:14
|
||||
qw422016.N().D(m)
|
||||
//line templates/recent_changes.qtpl:14
|
||||
qw422016.N().S(`</a>
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:15
|
||||
}
|
||||
//line templates/recent_changes.qtpl:15
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:16
|
||||
}
|
||||
//line templates/recent_changes.qtpl:16
|
||||
qw422016.N().S(`
|
||||
recent changes
|
||||
</nav>
|
||||
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:25
|
||||
qw422016.N().S(`
|
||||
|
||||
<section class="recent-changes__list" role="feed">
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:28
|
||||
if len(changes) == 0 {
|
||||
//line templates/recent_changes.qtpl:28
|
||||
qw422016.N().S(`
|
||||
<p>Could not find any recent changes.</p>
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:30
|
||||
} else {
|
||||
//line templates/recent_changes.qtpl:30
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:31
|
||||
for i, entry := range changes {
|
||||
//line templates/recent_changes.qtpl:31
|
||||
qw422016.N().S(`
|
||||
<ul class="recent-changes__entry" role="article"
|
||||
aria-setsize="`)
|
||||
//line templates/recent_changes.qtpl:33
|
||||
qw422016.N().D(n)
|
||||
//line templates/recent_changes.qtpl:33
|
||||
qw422016.N().S(`" aria-posinset="`)
|
||||
//line templates/recent_changes.qtpl:33
|
||||
qw422016.N().D(i)
|
||||
//line templates/recent_changes.qtpl:33
|
||||
qw422016.N().S(`">
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:34
|
||||
qw422016.N().S(entry)
|
||||
//line templates/recent_changes.qtpl:34
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:36
|
||||
}
|
||||
//line templates/recent_changes.qtpl:36
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:37
|
||||
}
|
||||
//line templates/recent_changes.qtpl:37
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line templates/recent_changes.qtpl:40
|
||||
}
|
||||
|
||||
//line templates/recent_changes.qtpl:40
|
||||
func WriteRecentChangesHTML(qq422016 qtio422016.Writer, changes []string, n int) {
|
||||
//line templates/recent_changes.qtpl:40
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line templates/recent_changes.qtpl:40
|
||||
StreamRecentChangesHTML(qw422016, changes, n)
|
||||
//line templates/recent_changes.qtpl:40
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line templates/recent_changes.qtpl:40
|
||||
}
|
||||
|
||||
//line templates/recent_changes.qtpl:40
|
||||
func RecentChangesHTML(changes []string, n int) string {
|
||||
//line templates/recent_changes.qtpl:40
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line templates/recent_changes.qtpl:40
|
||||
WriteRecentChangesHTML(qb422016, changes, n)
|
||||
//line templates/recent_changes.qtpl:40
|
||||
qs422016 := string(qb422016.B)
|
||||
//line templates/recent_changes.qtpl:40
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line templates/recent_changes.qtpl:40
|
||||
return qs422016
|
||||
//line templates/recent_changes.qtpl:40
|
||||
}
|
Loading…
Reference in New Issue
Block a user