diff options
| author | Gabriel Schneider <[email protected]> | 2026-08-02 23:43:08 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-03 09:54:39 -0300 |
| commit | 5ec72f8723d795d0b02d7e9ebb9f555f0c7e6a2e (patch) | |
| tree | f12f4b700fff4ff6f7e818d2a542672ba0b8d76e /vrsite/templates | |
| parent | a9263daee9413c5eff3c1f1bebcd224442fd8685 (diff) | |
| download | notevi-5ec72f8723d795d0b02d7e9ebb9f555f0c7e6a2e.tar.gz notevi-5ec72f8723d795d0b02d7e9ebb9f555f0c7e6a2e.zip | |
rebrand to notevi: one CLI over the jj sidecar
vr and vrsite become a single binary. vrsite/ folds into a web package in
one module (0x4200.cafe/notevi); "notevi web" serves and exports exactly
what vrsite did, and "notevi read/grep/note/query" is unchanged.
The sidecar is renamed with it: notevi_log, notevi-log.jsonl, and the
description "private: notevi log". The pre-rebrand names are still
recognized, so an old repository opens and reads; it is renamed in place
on the first write, or up front with "notevi migrate DIR...".
That rename cannot be a single mv inside jj run. jj only auto-tracks a
*new* file in the run working copy below a size limit it does not take
from the command line, so writing a whole log under a name the change has
never held is silently dropped while jj reports success. ensureLogFile
creates the file empty first and lets every later byte be a modification
of a tracked file, which snapshots at any size; that also fixes the same
latent bug when importing a large legacy vr-log.jsonl.
Adds a bem-te-vi mark (favicon and nav brand) and a README.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Diffstat (limited to 'vrsite/templates')
| -rw-r--r-- | vrsite/templates/frag-activity.tmpl | 36 | ||||
| -rw-r--r-- | vrsite/templates/frag-change.tmpl | 41 | ||||
| -rw-r--r-- | vrsite/templates/frag-jj.tmpl | 33 | ||||
| -rw-r--r-- | vrsite/templates/frag-note.tmpl | 105 | ||||
| -rw-r--r-- | vrsite/templates/layout.tmpl | 93 | ||||
| -rw-r--r-- | vrsite/templates/page-change.tmpl | 38 | ||||
| -rw-r--r-- | vrsite/templates/page-file.tmpl | 20 | ||||
| -rw-r--r-- | vrsite/templates/page-files.tmpl | 13 | ||||
| -rw-r--r-- | vrsite/templates/page-index.tmpl | 56 | ||||
| -rw-r--r-- | vrsite/templates/page-jj.tmpl | 25 | ||||
| -rw-r--r-- | vrsite/templates/page-note.tmpl | 54 | ||||
| -rw-r--r-- | vrsite/templates/page-notes.tmpl | 52 | ||||
| -rw-r--r-- | vrsite/templates/page-session.tmpl | 70 | ||||
| -rw-r--r-- | vrsite/templates/projects.tmpl | 112 |
14 files changed, 0 insertions, 748 deletions
diff --git a/vrsite/templates/frag-activity.tmpl b/vrsite/templates/frag-activity.tmpl deleted file mode 100644 index 071c556..0000000 --- a/vrsite/templates/frag-activity.tmpl +++ /dev/null @@ -1,36 +0,0 @@ -{{/* Who is reading the codebase right now, straight off the log tail. */}} -{{define "activity"}} -{{if .Compact}} - <div class="actlist"> - {{range .Sessions}} - <div class="act{{if .Live}} on{{end}}" title="{{.Agent}} · {{.Model}} · {{.Dir}}"> - {{if and $.Live .ID}}<a class="chip am{{.Bit}}" href="{{$.Href "session" .ID}}">{{.Short}}</a> - {{else}}<span class="chip am{{.Bit}}">{{.Short}}</span>{{end}} - <span class="what">{{.LastOp}}</span> - <span class="when">{{.Ago}}</span> - </div> - {{end}} - {{if not .Sessions}}<p class="meta hint">nothing logged yet</p>{{end}} - </div> -{{else}} - <table class="acttable"> - <thead><tr><th>agent</th><th>model</th><th>session</th><th>last op</th><th>when</th><th>r/g/n</th><th>dir</th></tr></thead> - <tbody> - {{range .Sessions}} - <tr class="{{if .Live}}on{{end}}"> - <td><span class="chip am{{.Bit}}">{{.Short}}</span>{{if .Live}}<span class="pulse" title="active">●</span>{{end}}</td> - <td>{{.Model}}{{if .Reason}}<span class="meta">/{{.Reason}}</span>{{end}}</td> - <td>{{if and $.Live .ID}}<a href="{{$.Href "session" .ID}}" title="{{.ID}}"><code>{{short .ID}}</code></a> - {{else}}<code title="{{.ID}}">{{short .ID}}</code>{{end}}</td> - <td class="what">{{.LastOp}}</td> - <td>{{.Ago}}</td> - <td class="meta">{{.Reads}}/{{.Greps}}/{{.Notes}}</td> - <td class="meta dir" title="{{.Dir}}">{{base .Dir}}</td> - </tr> - {{end}} - </tbody> - </table> - {{if not .Sessions}}<p class="meta hint">nothing logged yet</p>{{end}} - <p class="meta">live = active in the last {{.Window}}</p> -{{end}} -{{end}} diff --git a/vrsite/templates/frag-change.tmpl b/vrsite/templates/frag-change.tmpl deleted file mode 100644 index b33d746..0000000 --- a/vrsite/templates/frag-change.tmpl +++ /dev/null @@ -1,41 +0,0 @@ -{{/* The change everything on screen is read at, and how wide the view is. - Every page carries it, because every read, note and file listing below - is relative to it. */}} -{{define "changebar"}} -<section class="changebar{{if .Rev}} away{{end}}" aria-label="current change"> - <div class="cid"> - <span class="lbl">change</span> - {{if .Live}}<a href="{{.Href "change" .ChangeID}}" title="{{.ChangeID}}"><code>{{short .ChangeID}}</code></a> - {{else}}<code title="{{.ChangeID}}">{{short .ChangeID}}</code>{{end}} - {{with .ChangeInfo}}{{if .Flags}}<span class="flags">{{.Flags}}</span>{{end}}{{end}} - </div> - {{with .ChangeInfo}} - <p class="desc" title="{{.Desc}}">{{if .Desc}}{{.Desc}}{{else}}(no description){{end}}</p> - {{end}} - - <p class="counts"> - {{if eq .Scope "all"}} - <b>{{.Site.NotesTotal}}</b> notes across every change{{if .Here}} · {{.Here}} here{{end}} - {{else if .ScopeEmpty}} - nothing recorded at this change — showing all <b>{{.Site.NotesTotal}}</b> - {{else}} - <b>{{.Here}}</b> notes here{{if .Elsewhere}} · <span class="away">{{.Elsewhere}} elsewhere</span>{{end}} - {{end}} - </p> - - {{if .Live}} - <div class="scope" role="group" aria-label="what this view covers"> - <a href="{{.ScopeHref "change"}}"{{if eq .Scope "change"}} class="on" aria-current="true"{{end}} - title="only what was recorded at this change">this change</a> - <a href="{{.ScopeHref "all"}}"{{if eq .Scope "all"}} class="on" aria-current="true"{{end}} - title="every change in the log">all</a> - </div> - <form class="revjump" method="get" action="{{.JumpPath}}"> - <input type="search" name="rev" value="{{.Rev}}" placeholder="@, id, revset…" - aria-label="read at another change" autocomplete="off" spellcheck="false"> - {{if eq .Scope "all"}}<input type="hidden" name="scope" value="all">{{end}} - </form> - {{if .Rev}}<p class="back"><a href="{{.BackHref}}">← back to <code>{{short .Default}}</code>, where the log points</a></p>{{end}} - {{end}} -</section> -{{end}} diff --git a/vrsite/templates/frag-jj.tmpl b/vrsite/templates/frag-jj.tmpl deleted file mode 100644 index 61040dc..0000000 --- a/vrsite/templates/frag-jj.tmpl +++ /dev/null @@ -1,33 +0,0 @@ -{{/* jj query results. Live-only, so routes are absolute. */}} -{{define "jjrows"}} -{{if .Err}}<p class="err">{{.Err}}</p>{{end}} -{{if .Rows}} -<div class="jjlog"> - {{range .Rows}} - {{if .Blank}}<div class="jjrow blank"><span class="graph">{{.Graph}}</span></div> - {{else if .Op}} - <div class="jjrow"> - <span class="graph">{{.Graph}}</span> - <a class="id" href="{{$.Root}}jj?at_op={{.ID}}" title="run the commit log as of this operation">{{.Short}}</a> - <span class="when">{{.When}}</span> - <span class="who">{{.Author}}</span> - <span class="desc">{{.Desc}}</span> - <span class="flags">{{.End}}</span> - </div> - {{else}} - <div class="jjrow"> - <span class="graph">{{.Graph}}</span> - <a class="id" href="{{$.Root}}change/{{.ID}}" title="{{.ID}}">{{.Short}}</a> - <code class="commit">{{.CommitShort}}</code> - <span class="when">{{.When}}</span> - <span class="who">{{.Author}}</span> - {{if .Refs}}<span class="refs">{{.Refs}}</span>{{end}} - {{if .Flags}}<span class="flags">{{.Flags}}</span>{{end}} - <a class="desc" href="{{$.Root}}files?rev={{.ID}}" title="browse the tree at this change">{{if .Desc}}{{.Desc}}{{else}}(no description){{end}}</a> - </div> - {{end}} - {{end}} -</div> -{{else if not .Err}}<p class="meta hint">no revisions matched</p>{{end}} -{{if .AtOp}}<p class="meta">as of operation <code>{{short .AtOp}}</code> · <a href="{{.Root}}jj?kind=op">back to the op log</a></p>{{end}} -{{end}} diff --git a/vrsite/templates/frag-note.tmpl b/vrsite/templates/frag-note.tmpl deleted file mode 100644 index 3b04e11..0000000 --- a/vrsite/templates/frag-note.tmpl +++ /dev/null @@ -1,105 +0,0 @@ -{{define "note"}}{{$n := .N}}{{$p := .P}}{{$away := and $n.Change $p.ChangeID (ne $n.Change $p.ChangeID)}} -<article class="note am{{$n.Agent.Bit}}{{if $away}} away{{end}}" id="note-{{$n.ID}}" - data-agent="{{$n.Agent.Name}}" data-model="{{$n.Model}}" data-session="{{$n.Session}}" - data-kind="{{$n.Kind}}" data-file="{{$n.File}}" data-date="{{if not $n.At.IsZero}}{{$n.At.Format "2006-01-02"}}{{end}}" - data-start="{{$n.Start}}" data-end="{{$n.End}}" data-reply-to="{{$n.ReplyTo}}"> - <header> - {{if $n.File}}<a href="{{$p.NoteHref $n}}" title="{{$n.File}}">{{base $n.File}}{{lines $n}}</a>{{end}} - {{if $n.Kind}}<em>{{$n.Kind}}</em>{{end}} - <b class="who">{{$n.Agent.Short}}</b> - </header> - <div class="body">{{md $n.Text $p}}</div> - <footer class="meta"> - {{with $p.PermaHref $n}}<a class="perma" href="{{.}}" - title="permalink — this note on its own page, with the code it is about">#{{$n.ID}}</a> - {{else}}<span class="perma self">#{{$n.ID}}</span>{{end}} - {{if not $n.At.IsZero}}<time datetime="{{$n.At.Format "2006-01-02T15:04:05Z07:00"}}" title="{{$n.Ago}}">{{$n.When}}</time>{{end}} - {{if $n.Model}}<span class="model">{{$n.Model}}{{if $n.Reason}}/{{$n.Reason}}{{end}}</span>{{end}} - {{if $n.Session}}<code class="sess" title="{{$n.Session}}">{{short $n.Session}}</code>{{end}} - {{if $n.ReplyTo}}{{with $p.ReplyHref $n}}<a class="parent" href="{{.}}" - title="the note this explicitly replies to">reply to #{{$n.ReplyTo}}</a>{{else}}<span class="parent">reply to #{{$n.ReplyTo}}</span>{{end}}{{end}} - {{with $p.ThreadHref $n}}<a class="relations" href="{{.}}" title="notes replying to or mentioning this note"> - {{if $n.Replies}}↳ {{len $n.Replies}} repl{{if eq (len $n.Replies) 1}}y{{else}}ies{{end}}{{end}}{{if and $n.Replies $n.Mentions}} · {{end}}{{if $n.Mentions}}↶ {{len $n.Mentions}} mention{{if ne (len $n.Mentions) 1}}s{{end}}{{end}}</a>{{end}} - {{with $p.ConvHref $n}}<a class="conv" href="{{.}}" title="open the conversation this note was written in">conversation</a>{{end}} - {{if $n.Change}} - {{if $p.Live}}<a class="atchg{{if $away}} away{{end}}" href="{{$p.Href "change" $n.Change}}" - title="{{if $away}}written at another change{{else}}written at this change{{end}}"><code>{{short $n.Change}}</code></a> - {{else}}<code class="atchg{{if $away}} away{{end}}">{{short $n.Change}}</code>{{end}} - {{end}} - </footer> -</article> -{{end}} - -{{define "notelist"}}{{range .Notes}}{{template "note" (dict "N" . "P" $)}}{{end}}{{if not .Notes}}<p class="meta hint empty">no notes match these filters</p>{{end}}{{end}} - -{{/* htmx responses: the list plus an out-of-band count update */}} -{{define "notelist-oob"}}<span id="notecount" hx-swap-oob="true">{{len .Notes}}</span>{{template "notelist" .}}{{end}} - -{{define "note-added"}}{{if .File}}<span id="notecount" hx-swap-oob="true">{{len .File.Notes}}</span>{{end}}{{range .Notes}}{{template "note" (dict "N" . "P" $)}}{{end}}{{end}} - -{{/* A child-note form appears below every full card in a focused thread. It - deliberately uses a normal POST: one append and one redirect rebuild the - entire DAG from the log, including shared mention paths. */}} -{{define "replyform"}}{{$n := .N}}{{$p := .P}} -<details class="replybox"> - <summary>reply to #{{$n.ID}}</summary> - <form class="notform replyform" method="post" action="{{$p.Href "notes"}}"> - <input type="hidden" name="reply_to" value="{{$n.ID}}"> - <input type="hidden" name="rev" value="{{$p.Rev}}"> - <input type="hidden" name="change" value="{{$p.ChangeID}}"> - <input type="hidden" name="scope" value="all"> - <input type="hidden" name="back" value="{{$p.Href "note" (printf "%d" $p.Note.ID)}}#discussion"> - <textarea name="text" rows="2" placeholder="reply… (⌘/ctrl+enter to post)" aria-label="reply to note {{$n.ID}}" required></textarea> - <div class="row end"> - <span class="meta">as <b>{{$p.User}}</b> at <code title="{{$p.ChangeID}}">{{short $p.ChangeID}}</code> → the log</span> - <button type="submit">reply</button> - </div> - </form> -</details> -{{end}} - -{{/* Recursive at arbitrary depth. A DAG join/cycle is a reference rather than - a second card, which keeps ids unique and recursion finite. */}} -{{define "threadnode"}}{{$x := .Node}}{{$p := .P}} -<div class="threadnode via-{{$x.Via}}"> - <div class="threadedge" aria-label="{{$x.Via}}"><span>{{if eq $x.Via "reply"}}↳{{else}}↶{{end}}</span></div> - <div class="threadcontent"> - {{if $x.Reference}} - <p class="threadref meta">{{$x.Via}} also reaches <a href="{{$p.Href "note" (printf "%d" $x.Note.ID)}}">note #{{$x.Note.ID}}</a></p> - {{else}} - {{template "note" (dict "N" $x.Note "P" $p)}} - {{if $p.Live}}{{template "replyform" (dict "N" $x.Note "P" $p)}}{{end}} - {{if $x.Children}}<div class="threadchildren">{{range $x.Children}}{{template "threadnode" (dict "Node" . "P" $p)}}{{end}}</div>{{end}} - {{end}} - </div> -</div> -{{end}} - -{{/* the add-a-comment form; live pages only, since it writes to the log */}} -{{define "noteform"}} -<form class="notform" hx-post="{{.Href "notes"}}" hx-target="#notelist" hx-swap="afterbegin" - hx-on::after-request="if(event.detail.successful){this.reset();{{if eq .Kind "notes"}}htmx.trigger('#notefilters','change');{{end}}}" - method="post" action="{{.Href "notes"}}"> - <input type="hidden" name="rev" value="{{.Rev}}"> - <input type="hidden" name="change" value="{{.ChangeID}}"> - <input type="hidden" name="scope" value="{{.Scope}}"> - <input type="hidden" name="back" value="{{if .File}}{{.Href "code" .File.Path}}{{else}}{{.Href "notes"}}{{end}}"> - <div class="row"> - {{if .File}} - <input type="hidden" name="file" value="{{.File.Path}}"> - <span class="meta on">on <code>{{base .File.Path}}</code></span> - {{else}} - <input type="search" name="file" placeholder="file (optional)" list="filelist" autocomplete="off"> - {{end}} - <input type="number" id="nstart" name="start" min="1" placeholder="from" aria-label="first line"> - <input type="number" id="nend" name="end" min="1" placeholder="to" aria-label="last line"> - <input type="text" name="kind" placeholder="kind" aria-label="kind" list="kindlist" size="6"> - </div> - <textarea name="text" rows="3" placeholder="comment… (⌘/ctrl+enter to post)" required></textarea> - <div class="row end"> - <span class="meta">as <b>{{.User}}</b> at <code title="{{.ChangeID}}">{{short .ChangeID}}</code> → the log</span> - <button type="submit">add note</button> - </div> -</form> -<datalist id="kindlist">{{range .Facets.Kinds}}<option value="{{.}}">{{end}}</datalist> -{{end}} diff --git a/vrsite/templates/layout.tmpl b/vrsite/templates/layout.tmpl deleted file mode 100644 index a11ef16..0000000 --- a/vrsite/templates/layout.tmpl +++ /dev/null @@ -1,93 +0,0 @@ -<!doctype html> -<html lang="en"{{if .Live}} data-live="1"{{end}}> -<head> -<meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1"> -<title>{{.Title}}</title> -<link rel="stylesheet" href="{{.Href "asset" "style.css"}}"> -<script> -// the theme is worn before the first paint. A theme that is not one of the -// two the site was built with lives in themes.css, so pull that in too — -// from here, after style.css, so its :root block is the one that wins. -{const d = document.documentElement, t = localStorage.getItem("vrsite-theme"); - if (t && t !== "system") d.dataset.theme = t; - if (t && !/^(system|dark|light)$/.test(t)) { - const l = document.createElement("link"); - l.rel = "stylesheet"; l.id = "themescss"; l.href = "{{.Href "asset" "themes.css"}}"; - document.head.append(l); - } - d.dataset.mode = localStorage.getItem("vrsite-mode") || "trace"; - d.dataset.files = localStorage.getItem("vrsite-files-hidden") === "1" ? "hidden" : "shown";} -</script> -{{if .Live}}<script src="{{.Href "asset" "htmx.min.js"}}"></script>{{end}} -<script src="{{.Href "asset" "app.js"}}" defer></script> -</head> -<body{{if eq .Kind "file"}} class="with-aside"{{end}} data-kind="{{.Kind}}"> - -<nav aria-label="repository files" id="nav" data-root="{{.Root}}" data-current="{{.Current}}" data-tree="{{.Href "tree"}}"> - <header> - <a class="brand" href="{{.Href ""}}">{{.Site.Title}}</a> - <div class="modes" role="group" aria-label="focus"> - <button type="button" class="mode" data-mode="trace" title="reading coverage (t)">trace</button> - <button type="button" class="mode" data-mode="notes" title="notes and comments (t)">notes</button> - </div> - </header> - {{template "changebar" .}} - {{if .Live}} - <div id="activity" class="activity" hx-get="{{.Href "activity"}}?compact=1" hx-trigger="load, every 3s" hx-swap="innerHTML"></div> - {{end}} - <button type="button" id="filetoggle" aria-controls="filelist" aria-expanded="true">hide files</button> - <div id="filelist"> - <input id="filefind" class="find" type="search" placeholder="find file…" aria-label="find file" autocomplete="off" spellcheck="false"> - <div id="tree"><p class="meta hint">loading tree…</p></div> - </div> - <footer> - <span> - {{if and .Live (ne .Root "/")}}<a href="/">projects</a> · {{end}} - <a href="{{.Href "notes"}}">notes ({{len .Site.Notes}})</a> · - <a href="{{.Href "files"}}">files</a>{{if .Live}} · - <a href="{{.Href "jj"}}">jj</a>{{end}} - </span> - <div class="themepick" id="themepick" - data-js="{{.Href "asset" "themes.js"}}" data-css="{{.Href "asset" "themes.css"}}" - data-dark="{{.Site.Theme.Name}}" data-light="{{.Site.Light.Name}}" - data-darkid="{{.Site.Theme.ID}}" data-lightid="{{.Site.Light.ID}}"> - <button type="button" id="themebtn" aria-haspopup="listbox" aria-expanded="false" - title="theme — every one installed here (T)">theme</button> - <div class="thememenu" id="thememenu" hidden> - <input id="themefind" type="search" placeholder="filter themes…" aria-label="filter themes" - role="combobox" aria-controls="themelist" aria-autocomplete="list" - autocomplete="off" spellcheck="false"> - <ul id="themelist" role="listbox" aria-label="themes"></ul> - <p class="meta hint">↑↓ preview · enter keeps · esc puts it back</p> - </div> - </div> - </footer> -</nav> - -<main> -{{if .Err}}<p class="err">{{.Err}}</p>{{end}} -{{if eq .Kind "file"}}{{template "page-file" .}} -{{else if eq .Kind "notes"}}{{template "page-notes" .}} -{{else if eq .Kind "note"}}{{template "page-note" .}} -{{else if eq .Kind "files"}}{{template "page-files" .}} -{{else if eq .Kind "jj"}}{{template "page-jj" .}} -{{else if eq .Kind "change"}}{{template "page-change" .}} -{{else if eq .Kind "session"}}{{template "page-session" .}} -{{else}}{{template "page-index" .}}{{end}} -</main> - -{{if eq .Kind "file"}} -<aside aria-label="notes" class="notes-only"> - <header class="asidehead"> - <b>Notes (<span id="notecount">{{len .File.Notes}}</span>)</b> - {{if .Live}}<span class="meta">click a line to attach</span>{{end}} - </header> - {{if .Live}}{{template "noteform" .}}{{end}} - <div id="notelist">{{range .File.Notes}}{{template "note" (dict "N" . "P" $)}}{{end}}</div> - {{if not .File.Notes}}<p class="meta hint">no notes on this file yet</p>{{end}} -</aside> -{{end}} - -</body> -</html> diff --git a/vrsite/templates/page-change.tmpl b/vrsite/templates/page-change.tmpl deleted file mode 100644 index 8641da7..0000000 --- a/vrsite/templates/page-change.tmpl +++ /dev/null @@ -1,38 +0,0 @@ -{{define "page-change"}} -{{$c := .Change}} -{{$p := .}} -<header class="filehead"> - <h1>{{$c.Row.Short}} <span class="meta">{{$c.Row.Flags}}</span></h1> - <p class="meta"> - commit <code>{{$c.Row.CommitShort}}</code> · {{$c.Row.Author}} · {{$c.Row.When}} - {{if $c.Row.Refs}} · <span class="refs">{{$c.Row.Refs}}</span>{{end}} · - <a href="{{.Href "files" }}">browse the tree here</a> - </p> -</header> - -<section> - {{if $c.Desc}}<pre class="desc">{{$c.Desc}}</pre>{{else}}<p class="meta hint">(no description set)</p>{{end}} - - {{if $c.Parents}} - <p class="meta">parents: - {{range $c.Parents}}<a href="{{$p.Href "change" .ID}}"><code>{{.Short}}</code></a> {{.Desc}} {{end}} - </p> - {{end}} - - <h2>Changed files <span class="meta">{{$c.Stat}}</span></h2> - {{if $c.Files}} - <table class="changed"> - <tbody> - {{range $c.Files}} - <tr><td class="st st-{{.Status}}">{{.Status}}</td> - <td><a href="{{$p.Href "code" .Path}}">{{.Path}}</a></td></tr> - {{end}} - </tbody> - </table> - {{else}}<p class="meta hint">no file changes</p>{{end}} - - <h2>Notes recorded at this change <span class="meta">{{len .Notes}}</span></h2> - <div class="notecols">{{range .Notes}}{{template "note" (dict "N" . "P" $)}}{{end}}</div> - {{if not .Notes}}<p class="meta hint">nothing in the log was written while this change was checked out</p>{{end}} -</section> -{{end}} diff --git a/vrsite/templates/page-file.tmpl b/vrsite/templates/page-file.tmpl deleted file mode 100644 index 39a8c44..0000000 --- a/vrsite/templates/page-file.tmpl +++ /dev/null @@ -1,20 +0,0 @@ -{{define "page-file"}} -<header class="filehead"> - <h1>{{.File.Path}}</h1> - <p class="meta"> - {{if .File.Traced}} - {{range .Site.Agents}}{{if band $.File.Mask .Bit}}<span class="chip am{{.Bit}}">{{.Short}}</span> {{end}}{{end}} - <span class="trace-only"><data value="{{.File.Pct}}">{{.File.Pct}}% read</data> · - {{.File.Reads}} reads · {{.File.Greps}} greps · </span> - <span class="notes-only">{{len .File.Notes}} note{{if ne (len .File.Notes) 1}}s{{end}} · </span> - {{else}}not traced · {{end}}change - {{if .Live}}<a href="{{.Href "change" .File.Change}}"><code>{{short .File.Change}}</code></a>{{else}}<code>{{short .File.Change}}</code>{{end}} - </p> - {{if .File.Patterns}}<p class="meta greps trace-only">grepped: {{range .File.Patterns}}<code>{{.}}</code> {{end}}</p>{{end}} -</header> -{{if .File.Stub}} -<p class="meta stub">{{.File.Stub}}</p> -{{else}} -<div class="codewrap">{{.File.Body}}</div> -{{end}} -{{end}} diff --git a/vrsite/templates/page-files.tmpl b/vrsite/templates/page-files.tmpl deleted file mode 100644 index 3f158fe..0000000 --- a/vrsite/templates/page-files.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -{{define "page-files"}} -<header class="filehead"> - <h1>Files</h1> - <p class="meta"> - everything at change <code title="{{.ChangeID}}">{{short .ChangeID}}</code> · - <span class="trace-only">traced files carry a coverage bar{{if eq .Scope "change"}}, from reads at this change{{end}}</span> - <span class="notes-only">◆ marks files with notes</span> - </p> -</header> -<section class="filetree"> -{{.Tree}} -</section> -{{end}} diff --git a/vrsite/templates/page-index.tmpl b/vrsite/templates/page-index.tmpl deleted file mode 100644 index 93cad6b..0000000 --- a/vrsite/templates/page-index.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -{{define "page-index"}} -<header class="filehead"> - <h1>{{.Site.Title}}</h1> - <p class="meta"> - {{len .Files}} files at <code title="{{.ChangeID}}">{{short .ChangeID}}</code> · - {{len .Site.Order}} traced, {{len .Site.Notes}} notes - {{if or (eq .Scope "all") .ScopeEmpty}}<span class="away">across every change</span>{{else}}here{{end}} · - theme {{.Site.Theme.Name}} - </p> -</header> - -{{if .Live}} -<section> - <h2>Live <span class="meta">— agents reading this codebase</span></h2> - <div id="activity-full" hx-get="{{.Href "activity"}}" hx-trigger="load, every 3s" hx-swap="innerHTML"> - <p class="meta hint">…</p> - </div> -</section> -{{end}} - -<section class="trace-only"> - <h2>Agents</h2> - <table> - <thead><tr><th>agent</th><th>model</th><th>effort</th><th>session</th><th>reads</th><th>greps</th><th>notes</th></tr></thead> - <tbody> - {{range .Site.Agents}} - <tr><td><span class="chip am{{.Bit}}">{{.Short}}</span></td> - <td>{{.Model}}</td><td>{{.Reason}}</td> - <td>{{if and $.Live .Session}}<a href="{{$.Href "session" .Session}}" title="{{.Session}}"><code>{{short .Session}}</code></a> - {{else}}<code title="{{.Session}}">{{short .Session}}</code>{{end}}</td> - <td>{{.Reads}}</td><td>{{.Greps}}</td><td>{{.Notes}}</td></tr> - {{end}} - </tbody> - </table> -</section> - -<section class="trace-only"> - <h2>Coverage</h2> - <table> - <thead><tr><th>file</th><th>read</th><th>lines</th><th>notes</th></tr></thead> - <tbody> - {{range .Site.Order}}{{with index $.Site.Files .}} - <tr><td><a href="{{$.Href "code" .Path}}">{{.Path}}</a></td> - <td><data class="bar am{{.Mask}}" value="{{.Pct}}" style="--pct:{{.Pct}}%">{{.Pct}}%</data></td> - <td>{{.Covered}}/{{.Total}}</td><td>{{len .Notes}}</td></tr> - {{end}}{{end}} - </tbody> - </table> -</section> - -<section class="notes-only"> - <h2>Latest notes <span class="meta">— <a href="{{.Href "notes"}}">all {{len .Site.Notes}}, with filters</a></span></h2> - <div class="notecols">{{range .Notes}}{{template "note" (dict "N" . "P" $)}}{{end}}</div> - {{if not .Notes}}<p class="meta hint">no notes in the log yet</p>{{end}} -</section> -{{end}} diff --git a/vrsite/templates/page-jj.tmpl b/vrsite/templates/page-jj.tmpl deleted file mode 100644 index 24df596..0000000 --- a/vrsite/templates/page-jj.tmpl +++ /dev/null @@ -1,25 +0,0 @@ -{{define "page-jj"}} -<header class="filehead"> - <h1>jj</h1> - <p class="meta"> - read-only queries against the repo — <code>--ignore-working-copy</code>, inline templates, nothing written to disk - </p> -</header> - -<section class="jjpage"> - <form class="jjform" method="get" action="{{.Href "jj"}}" - hx-get="{{.Href "jj-log"}}" hx-target="#jjout" hx-swap="innerHTML" hx-indicator="#jjbusy"> - <input type="hidden" name="kind" value="log"> - <input type="search" name="revset" value="{{.JJ.Revset}}" placeholder="revset — e.g. @ | ancestors(trunk(), 10) | description(glob:'*fix*')" autocomplete="off" spellcheck="false"> - <input type="number" name="limit" value="{{.JJ.Limit}}" min="1" max="1000" aria-label="limit" title="limit"> - <button type="submit">jj log</button> - <button type="button" hx-get="{{.Href "jj-op"}}" hx-target="#jjout" hx-include="closest form" hx-indicator="#jjbusy" title="operation log">op log</button> - <span id="jjbusy" class="busy">·</span> - </form> - <p class="meta hint"> - change ids open the change · descriptions browse the tree at that change · - op ids re-run the query <code>--at-operation</code>, which is how you see the repo as it was - </p> - <div id="jjout">{{template "jjrows" .JJ}}</div> -</section> -{{end}} diff --git a/vrsite/templates/page-note.tmpl b/vrsite/templates/page-note.tmpl deleted file mode 100644 index 8cd0e64..0000000 --- a/vrsite/templates/page-note.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -{{/* One note, on its own — the page a shared permalink opens. - - It has to stand up for a reader who has never seen this site: what was - said, about which lines of which file, at which change, and the code - itself, right there. Everything else on the page is a way further in. */}} -{{define "page-note"}} -{{$n := .Note}} -<header class="filehead"> - <h1>{{if $n.File}}{{base $n.File}}<span class="lns">{{lines $n}}</span>{{else}}Note{{end}}</h1> - <p class="meta"> - note <b>#{{$n.ID}}</b> by <b>{{$n.Agent.Short}}</b>{{if $n.Kind}} · <em class="kind">{{$n.Kind}}</em>{{end}} - {{if not $n.At.IsZero}} · <time datetime="{{$n.At.Format "2006-01-02T15:04:05Z07:00"}}">{{$n.When}}</time> - <span class="ago">({{$n.Ago}})</span>{{end}} - {{if $n.Change}} · read at - {{if .Live}}<a href="{{.Href "change" $n.Change}}"><code>{{short $n.Change}}</code></a> - {{else}}<code title="{{$n.Change}}">{{short $n.Change}}</code>{{end}} - {{end}} - </p> - {{if ne $n.File (base $n.File)}}<p class="meta"><code>{{$n.File}}</code></p>{{end}} -</header> - -<section class="notepage"> - <div class="onenote">{{template "note" (dict "N" $n "P" $)}}</div> - - {{$open := .HasCode $n.File}} - {{if .Excerpt}} - <p class="meta exhead">lines {{.ExFrom}}–{{.ExTo}} of <code>{{$n.File}}</code>{{if $open}} · - <a href="{{.NoteHref $n}}">open the whole file →</a>{{end}}</p> - <div class="codewrap excerpt">{{.Excerpt}}</div> - {{else if .ExErr}} - <p class="meta stub">{{.ExErr}}</p> - {{else if $n.File}} - <p class="meta hint">this note is about the whole file{{if $open}} — - <a href="{{.NoteHref $n}}">open <code>{{base $n.File}}</code> →</a>{{end}}</p> - {{else}} - <p class="meta hint">this note is not pinned to a file</p> - {{end}} - - {{if .Live}}{{template "replyform" (dict "N" $n "P" $)}}{{end}} - - <section class="discussion" id="discussion"> - <h2>Replies & mentions - <span class="meta">{{len $n.Replies}} repl{{if eq (len $n.Replies) 1}}y{{else}}ies{{end}} · {{len $n.Mentions}} mention{{if ne (len $n.Mentions) 1}}s{{end}}</span> - </h2> - {{if .Thread.Children}} - <div class="threadchildren rootchildren">{{range .Thread.Children}}{{template "threadnode" (dict "Node" . "P" $)}}{{end}}</div> - {{else}} - <p class="meta hint">no notes reply to or mention this one yet</p> - {{end}} - </section> - - <p class="meta more"><a href="{{.Href "notes"}}">← every note in the log</a></p> -</section> -{{end}} diff --git a/vrsite/templates/page-notes.tmpl b/vrsite/templates/page-notes.tmpl deleted file mode 100644 index ebd5865..0000000 --- a/vrsite/templates/page-notes.tmpl +++ /dev/null @@ -1,52 +0,0 @@ -{{define "facet"}}<select name="{{.Name}}" aria-label="{{.Label}}"> - <option value="">{{.Label}}</option> - {{range .Values}}<option value="{{.}}"{{if eq . $.Sel}} selected{{end}}>{{if $.Short}}{{short .}}…{{else}}{{.}}{{end}}</option> - {{end}}</select>{{end}} - -{{define "page-notes"}} -<header class="filehead"> - <h1>Notes</h1> - <p class="meta"> - {{if eq .Scope "all"}} - all {{.Site.NotesTotal}} in the log, every change - {{else if .ScopeEmpty}} - all {{.Site.NotesTotal}} in the log — nothing was recorded at <code>{{short .ChangeID}}</code> - {{else}} - {{len .Site.Notes}} written at <code title="{{.ChangeID}}">{{short .ChangeID}}</code>{{if .Elsewhere}} · - {{if .Live}}<a href="{{.ScopeHref "all"}}">{{.Elsewhere}} more at other changes</a> - {{else}}{{.Elsewhere}} more at other changes are not in this export{{end}}{{end}} - {{end}} - {{if .Live}} · anything you add here is appended to the private log sidecar at this change — the project working copy is never touched{{end}} - </p> -</header> - -<section class="notespage"> - {{if .Live}} - <details class="addnote"> - <summary>add a note</summary> - {{template "noteform" .}} - </details> - {{end}} - - <form class="filters" id="notefilters" method="get" action="{{.Href "notes"}}" - {{if .Live}}hx-get="{{.Href "notes-list"}}" hx-target="#notelist" hx-swap="innerHTML" - hx-trigger="input delay:250ms, change, search" hx-indicator="#notesbusy"{{end}}> - <input type="search" name="text" value="{{.Filter.Text}}" placeholder="search note text…" autocomplete="off"> - <input type="search" name="file" value="{{.Filter.File}}" placeholder="file path…" list="filelist" autocomplete="off"> - {{template "facet" (dict "Name" "agent" "Label" "any agent" "Values" .Facets.Agents "Sel" .Filter.Agent)}} - {{template "facet" (dict "Name" "model" "Label" "any model" "Values" .Facets.Models "Sel" .Filter.Model)}} - {{template "facet" (dict "Name" "session" "Label" "any session" "Values" .Facets.Sessions "Sel" .Filter.Session "Short" true)}} - {{template "facet" (dict "Name" "kind" "Label" "any kind" "Values" .Facets.Kinds "Sel" .Filter.Kind)}} - <span class="dates"> - <label class="datef">from <input type="date" name="from" value="{{.Filter.From}}"></label> - <label class="datef">to <input type="date" name="to" value="{{.Filter.To}}"></label> - </span> - <button type="submit" class="nohx">filter</button> - <button type="button" id="clearfilters">clear</button> - </form> - <datalist id="filelist">{{range .Facets.Files}}<option value="{{.}}">{{end}}</datalist> - - <p class="meta count"><span id="notesbusy" class="busy">·</span><span id="notecount">{{len .Notes}}</span> notes shown</p> - <div id="notelist">{{template "notelist" .}}</div> -</section> -{{end}} diff --git a/vrsite/templates/page-session.tmpl b/vrsite/templates/page-session.tmpl deleted file mode 100644 index 9a35e8d..0000000 --- a/vrsite/templates/page-session.tmpl +++ /dev/null @@ -1,70 +0,0 @@ -{{/* One session's conversation, with its vr log woven in by time. */}} -{{define "page-session"}} -{{$c := .Conv}} -<header class="filehead"> - <h1> - {{if $c.Agent}}<span class="chip am{{$c.Bit}}">{{$c.Agent}}</span> {{end}} - <code title="{{$c.Session}}">{{short $c.Session}}</code> - </h1> - <p class="meta"> - {{if $c.Model}}{{$c.Model}} · {{end}}{{$c.Reads}} reads · {{$c.Greps}} greps · {{$c.Notes}} notes - {{if $c.Dir}} · <span title="{{$c.Dir}}">{{base $c.Dir}}</span>{{end}} - {{if $c.Harness}} · {{$c.Harness}}{{end}} - </p> - {{if $c.Path}} - <p class="meta"><code>{{$c.Path}}</code></p> - {{else}} - <p class="meta hint">no transcript found for this session — searched - {{if $c.Roots}}{{range $i, $r := $c.Roots}}{{if $i}}, {{end}}<code>{{$r}}</code>{{end}}{{else}}nowhere: <code>-transcripts</code> is empty{{end}} · - showing the vr log alone</p> - {{end}} - {{if $c.Err}}<p class="err">{{$c.Err}}</p>{{end}} -</header> - -<section class="convpage"> - {{if $c.Windowed}} - <p class="meta"> - moments {{$c.From}}–{{$c.To}} of {{$c.Total}}{{if $c.Anchor}}, around the note{{end}} · - {{if $c.Incomplete}}the rest is beyond what one page renders{{else}}<a href="{{$c.AllHref}}">show the whole conversation</a>{{end}} - </p> - {{end}} - - <div class="conv" data-anchor="{{$c.Anchor}}"> - {{range $c.Turns}} - {{if .Note}} - <div class="turn t-note{{if .Here}} here{{end}}"> - <span class="role">note</span><time>{{.Clock}}</time> - {{if .Note.File}} - <div class="notewrap" data-href="{{$.NoteHref .Note}}" tabindex="0" role="link" - title="open this note on the code it is about">{{template "note" (dict "N" .Note "P" $)}}</div> - {{else}} - <div class="notewrap">{{template "note" (dict "N" .Note "P" $)}}</div> - {{end}} - </div> - {{else if eq .Role "vr"}} - <div class="turn t-vr"> - <span class="role">vr</span><time>{{.Clock}}</time> - {{if .File}}<a class="what" href="{{$.Href "code" .File}}">{{.Text}}</a> - {{else}}<span class="what">{{.Text}}</span>{{end}} - </div> - {{else if eq .Role "tool"}} - <div class="turn t-tool"> - <span class="role">{{.Tool}}</span><time>{{.Clock}}</time> - <code class="what">{{.Detail}}</code> - </div> - {{else if eq .Role "result"}} - <div class="turn t-result{{if eq .Kind "error"}} bad{{end}}"> - <span class="role">→{{if .Tool}} {{.Tool}}{{end}}</span><time></time> - <code class="what">{{.Detail}}</code> - </div> - {{else}} - <div class="turn t-say t-{{.Role}}"> - <span class="role">{{.Role}}</span><time>{{.Clock}}</time> - <p>{{.Text}}</p> - </div> - {{end}} - {{end}} - {{if not $c.Turns}}<p class="meta hint">nothing recorded for this session</p>{{end}} - </div> -</section> -{{end}} diff --git a/vrsite/templates/projects.tmpl b/vrsite/templates/projects.tmpl deleted file mode 100644 index 3e3c670..0000000 --- a/vrsite/templates/projects.tmpl +++ /dev/null @@ -1,112 +0,0 @@ -{{define "projects"}}<!doctype html> -<html lang="en" data-live="1"> -<head> -<meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1"> -<title>{{.Title}}</title> -<link rel="stylesheet" href="/style.css"> -<script> -// Match project pages: wear the saved theme before first paint, and load the -// installed-theme stylesheet now only when that saved choice requires it. -{const d = document.documentElement, t = localStorage.getItem("vrsite-theme"); - if (t && t !== "system") d.dataset.theme = t; - if (t && !/^(system|dark|light)$/.test(t)) { - const l = document.createElement("link"); - l.rel = "stylesheet"; l.id = "themescss"; l.href = "/themes.css"; - document.head.append(l); - } - d.dataset.mode = localStorage.getItem("vrsite-mode") || "trace";} -</script> -<script src="/app.js" defer></script> -</head> -<body class="projects"> -<nav aria-label="projects" id="nav"> - <header><a class="brand" href="/">{{.Title}}</a></header> - <p class="meta">one process · every local vr sidecar</p> - <input id="projectfind" class="find" type="search" placeholder="find project…" aria-label="find project" autocomplete="off" spellcheck="false"> - <form method="post" action="/projects/refresh" class="project-refresh"> - <button type="submit">refresh repositories</button> - </form> - <p class="meta">scans <code>{{.ScanRoot}}</code></p> - <p class="meta">last refresh {{.Scanned}}</p> - <footer> - <span>selection and scan results stay in memory</span> - <div class="themepick" id="themepick" - data-js="/themes.js" data-css="/themes.css" - data-dark="{{.Theme.Name}}" data-light="{{.Light.Name}}" - data-darkid="{{.Theme.ID}}" data-lightid="{{.Light.ID}}"> - <button type="button" id="themebtn" aria-haspopup="listbox" aria-expanded="false" - title="theme — every one installed here (T)">theme</button> - <div class="thememenu" id="thememenu" hidden> - <input id="themefind" type="search" placeholder="filter themes…" aria-label="filter themes" - role="combobox" aria-controls="themelist" aria-autocomplete="list" - autocomplete="off" spellcheck="false"> - <ul id="themelist" role="listbox" aria-label="themes"></ul> - <p class="meta hint">↑↓ preview · enter keeps · esc puts it back</p> - </div> - </div> - </footer> -</nav> - -<main class="projects-main"> - <header class="filehead"> - <h1>Projects</h1> - <p class="meta">Choose a vr log, start one in a jj repository, or colocate jj with an existing Git repository.</p> - </header> - {{if .Message}}<p class="ok project-message">{{.Message}}</p>{{end}} - {{if .Err}}<p class="err project-message">{{.Err}}</p>{{end}} - - <section> - <h2>Logs <span class="meta">— {{len .Active}} repositories with a private sidecar</span></h2> - <div class="project-grid"> - {{range .Active}} - <article class="project-card" data-project="{{.Name}} {{.Relative}}"> - <header><h3><a href="/p/{{.ID}}/">{{.Name}}</a></h3><span class="project-state active">log</span></header> - <p class="project-path" title="{{.Path}}"><code>{{.Relative}}</code></p> - <p class="meta">{{.Entries}} entries · {{.Notes}} notes · {{.Agents}} agents · {{.Updated}}</p> - {{if gt (len .Workspaces) 1}}<p class="meta">{{len .Workspaces}} jj workspaces share this log</p>{{end}} - {{if .Err}}<p class="err">{{.Err}}</p>{{end}} - <a class="project-action" href="/p/{{.ID}}/">open project</a> - </article> - {{end}} - {{if not .Active}}<p class="meta hint">no vr sidecars found yet</p>{{end}} - </div> - </section> - - <section> - <h2>Ready to start <span class="meta">— {{len .Ready}} jj repositories without a vr sidecar</span></h2> - <div class="project-grid"> - {{range .Ready}} - <article class="project-card" data-project="{{.Name}} {{.Relative}}"> - <header><h3>{{.Name}}</h3><span class="project-state">jj</span></header> - <p class="project-path" title="{{.Path}}"><code>{{.Relative}}</code></p> - {{if gt (len .Workspaces) 1}}<p class="meta">{{len .Workspaces}} workspaces</p>{{end}} - {{if .Err}}<p class="err">{{.Err}}</p>{{end}} - <form method="post" action="/projects/{{.ID}}/start"> - <button type="submit">start private sidecar</button> - </form> - </article> - {{end}} - {{if not .Ready}}<p class="meta hint">every detected jj repository already has a sidecar</p>{{end}} - </div> - </section> - - <section> - <h2>Git repositories <span class="meta">— {{len .Git}} without jj metadata</span></h2> - <p class="meta">Initializing adds colocated <code>.jj</code> metadata; it does not create a sidecar until you choose “start private sidecar”.</p> - <div class="project-grid"> - {{range .Git}} - <article class="project-card" data-project="{{.Name}} {{.Relative}}"> - <header><h3>{{.Name}}</h3><span class="project-state git">git</span></header> - <p class="project-path" title="{{.Path}}"><code>{{.Relative}}</code></p> - <form method="post" action="/git/{{.ID}}/init"> - <button type="submit">initialize colocated jj</button> - </form> - </article> - {{end}} - {{if not .Git}}<p class="meta hint">no Git-only repositories detected</p>{{end}} - </div> - </section> -</main> -</body> -</html>{{end}} |
