summaryrefslogtreecommitdiff
path: root/vrsite/page.go
diff options
context:
space:
mode:
Diffstat (limited to 'vrsite/page.go')
-rw-r--r--vrsite/page.go84
1 files changed, 81 insertions, 3 deletions
diff --git a/vrsite/page.go b/vrsite/page.go
index 2974eec..cca0c58 100644
--- a/vrsite/page.go
+++ b/vrsite/page.go
@@ -16,7 +16,7 @@ import (
type page struct {
Site *Site
Title string
- Kind string // index | file | files | notes | jj | change | session
+ Kind string // index | file | files | notes | note | jj | change | session
Root string // static: relative prefix; live: "/"
Live bool
Rev string // revision being browsed ("" = the change the log points at)
@@ -40,6 +40,14 @@ type page struct {
File *File
Files []*File // every file at this change, for counts
+ // one note on its own page — the permalink. Excerpt is the code it is
+ // about, already rendered; ExErr says why there is none.
+ Note *Note
+ Thread *ThreadNode
+ Excerpt template.HTML
+ ExFrom, ExTo int
+ ExErr string
+
Notes []*Note
Filter NoteFilter
Facets *Facets
@@ -105,7 +113,7 @@ func (p *page) BackHref() string {
// that can be read at any change, the file tree otherwise.
func (p *page) JumpPath() string {
switch p.Kind {
- case "index", "file", "files", "notes":
+ case "index", "file", "files", "notes", "note":
if p.Path != "" {
return p.Path
}
@@ -134,6 +142,8 @@ func (p *page) Href(kind string, arg ...string) string {
return "/jj"
case "code":
return "/code/" + escPath(a) + p.params()
+ case "note":
+ return "/note/" + a
case "change":
return "/change/" + a
case "session":
@@ -154,6 +164,8 @@ func (p *page) Href(kind string, arg ...string) string {
return p.Root + "tree.html"
case "code":
return p.Root + "code/" + a + ".html"
+ case "note":
+ return p.Root + "note/" + a + ".html"
case "asset":
return p.Root + a
}
@@ -184,6 +196,67 @@ func (p *page) ConvHref(n *Note) string {
return p.Href("session", n.Session) + "?note=" + id + "#note-" + id
}
+// PermaHref is the note's own page: the link to hand someone else. It is the
+// one link on the card that names nothing but the note, so it survives the
+// change scope, the filters, and the file having moved on since.
+//
+// It is empty on the note's own page, which is where it already points, and in
+// a static export of a different change, which has no page for it.
+func (p *page) PermaHref(n *Note) string {
+ if p.Kind == "note" && (p.Note == nil || p.Note.ID == n.ID) {
+ return ""
+ }
+ if !p.Live && p.Site != nil && p.Site.NoteByID(n.ID) == nil {
+ return ""
+ }
+ return p.Href("note", strconv.Itoa(n.ID))
+}
+
+// ThreadHref opens the incoming replies and mentions for a note. The focused
+// root only needs an in-page jump; every other card gets its own permalink.
+func (p *page) ThreadHref(n *Note) string {
+ if len(n.Replies) == 0 && len(n.Mentions) == 0 {
+ return ""
+ }
+ if p.Kind == "note" && p.Note != nil && p.Note.ID == n.ID {
+ return "#discussion"
+ }
+ h := p.Href("note", strconv.Itoa(n.ID))
+ if h == "" {
+ return ""
+ }
+ return h + "#discussion"
+}
+
+// ReplyHref is the explicit parent link. A static export may not contain the
+// parent's change, in which case it leaves the relationship as text instead of
+// manufacturing a link to a page the export did not write.
+func (p *page) ReplyHref(n *Note) string {
+ if n.ReplyTo < 1 {
+ return ""
+ }
+ if !p.Live && p.Site != nil && p.Site.NoteByID(n.ReplyTo) == nil {
+ return ""
+ }
+ return p.Href("note", strconv.Itoa(n.ReplyTo))
+}
+
+// HasCode reports whether this view has a page for a path. The live app can
+// render any file at the change it is reading; a static export only wrote the
+// ones present at the change it holds, so a note about a file that is not
+// there must not offer a link into nothing.
+func (p *page) HasCode(path string) bool {
+ if p.Live {
+ return path != ""
+ }
+ for _, f := range p.Files {
+ if f.Path == path {
+ return true
+ }
+ }
+ return false
+}
+
// NoteHref points at the noted line, or the note list when it is unpinned.
// The ?note= is what turns a jump into an arrival: the page opens in notes
// focus with the card flashed and its lines marked (see app.js).
@@ -204,9 +277,14 @@ func (p *page) NoteHref(n *Note) string {
return h
}
-func newTemplates() *template.Template {
+// newTemplates parses the page templates. The highlighter comes along because
+// note bodies are markdown, and a fenced code block in a note is painted by
+// the same grammars as the code view.
+func newTemplates(hl *highlighter) *template.Template {
+ md := newMarkdown(hl)
funcs := template.FuncMap{
"short": short,
+ "md": md.renderAt,
"band": func(a, b uint8) bool { return b != 0 && a&b != 0 },
"lines": func(n *Note) string {
if n.Start <= 0 {