{{define "content" -}}
<style>
/* Scoped memory styles, inlined in the same flat todo.sr.ht idiom as the beads
and milestones views (the scss bundle is not rebuilt in dev): square, hairline
borders, monospace ids, muted small type, no radius and no shadow. Colours
come from the CSS variables that mirror core.sr.ht's Bootstrap palette in the
light default and the prefers-color-scheme: dark variant sourcehut ships. No
JavaScript: the sort is a link and the search is a GET form. */
.memory {
--accent: #2f9e44;
--bd-bg: #ffffff; --bd-panel: #f2f3f5; --bd-fg: #212529;
--bd-muted: #6c757d; --bd-border: #ced4da;
}
@media (prefers-color-scheme: dark) {
.memory {
--bd-bg: #212529; --bd-panel: #343a40; --bd-fg: #dee2e6;
--bd-muted: #adb5bd; --bd-border: #6c757d;
}
}
/* freshness line (the shared "beadsHead" partial), in the same muted small type
the sibling views give it */
.memory .beads-freshness { font-size: .78rem; color: var(--bd-muted); margin: -.35rem 0 .7rem; }
.memory .beads-freshness a { color: var(--bd-muted); }
.memory .beads-freshness code { font-size: .72rem; color: inherit; }
/* filter bar: flat hairline controls, as on the board */
.mem-filter { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin-bottom: .4rem; }
.mem-filter input, .mem-filter button {
font: inherit; font-size: .82rem; padding: .25rem .45rem; color: var(--bd-fg);
background: var(--bd-bg); border: 1px solid var(--bd-border); border-radius: 0;
}
.mem-filter input[type="search"] { min-width: 12rem; flex: 1 1 12rem; }
.mem-filter button { background: var(--bd-panel); cursor: pointer; }
.mem-filter .mem-clear { font-size: .82rem; color: var(--bd-muted); }
/* sort toggle: the same list in two orders, so it is a pair of words and not a
tab — the current one is plain text, the other one a link */
.mem-bar { display: flex; gap: .35rem; align-items: baseline; font-size: .82rem; color: var(--bd-muted); margin: 0 0 1rem; }
.mem-bar .count { flex: 1 1 auto; }
.mem-bar .current { color: var(--bd-fg); }
.mem { border: 1px solid var(--bd-border); margin-bottom: 1rem; }
.mem-head { display: flex; align-items: baseline; gap: .5rem; padding: .4rem .7rem; background: var(--bd-panel); border-bottom: 1px solid var(--bd-border); }
.mem-slug { font-family: monospace; font-size: .9rem; font-weight: 700; margin: 0; flex: 0 0 auto; }
.mem-slug a { color: var(--bd-fg); }
.mem-stale { flex: 0 0 auto; font-size: .72rem; line-height: 1.4; padding: 0 .35rem; border: 1px solid var(--bd-border); color: var(--bd-muted); }
.mem-rev { flex: 1 1 auto; text-align: right; font-size: .78rem; color: var(--bd-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mem-rev a { color: var(--bd-muted); }
.mem-rev code { font-size: .72rem; color: inherit; }
/* The body is rendered markdown (see web/markdown.go), so what is styled here is
a small document and no longer a run of pre-wrapped paragraphs: lists are
lists, a fenced recipe is a code block, and `**Why:**` is bold. The type stays
the page's — flat, square, hairline — and every block loses its last margin so
the pane closes on the text rather than on a gap. */
.mem-body { padding: .5rem .7rem; }
.mem-body > :first-child { margin-top: 0; }
.mem-body > :last-child { margin-bottom: 0; }
.mem-body p { margin: 0 0 .6rem; }
/* Headings inside a memory are subordinate to the slug in the header, so they
are marked by weight and never by a size that competes with it. */
.mem-body h1, .mem-body h2, .mem-body h3,
.mem-body h4, .mem-body h5, .mem-body h6 {
font-size: .95rem; font-weight: 700; margin: .9rem 0 .4rem;
}
.mem-body ul, .mem-body ol { margin: 0 0 .6rem; padding-left: 1.3rem; }
.mem-body li { margin-bottom: .2rem; }
.mem-body li > ul, .mem-body li > ol { margin-bottom: 0; }
.mem-body li > p { margin-bottom: .3rem; }
.mem-body code {
font-size: .82rem; padding: 0 .2rem;
background: var(--bd-panel); border: 1px solid var(--bd-border);
}
/* A fenced block is one box, so its own code element carries no second border
inside it. Long recipes scroll on their own rather than widening the pane. */
.mem-body pre {
margin: 0 0 .6rem; padding: .4rem .55rem; overflow-x: auto;
background: var(--bd-panel); border: 1px solid var(--bd-border);
}
.mem-body pre code { font-size: .82rem; padding: 0; background: none; border: 0; }
.mem-body blockquote {
margin: 0 0 .6rem; padding: .1rem .6rem;
border-left: 2px solid var(--bd-border); color: var(--bd-muted);
}
.mem-body hr { border: 0; border-top: 1px solid var(--bd-border); margin: .8rem 0; }
.mem-body table { border-collapse: collapse; margin: 0 0 .6rem; font-size: .85rem; }
.mem-body th, .mem-body td { border: 1px solid var(--bd-border); padding: .2rem .4rem; text-align: left; }
.mem-body th { background: var(--bd-panel); }
/* Raw markup — a `<placeholder>` CommonMark read as a tag — is shown as the text
it was, not dropped; it keeps the line breaks it was typed with. */
.mem-body .mem-raw { white-space: pre-wrap; }
/* A [[slug]] that resolves is a link like any other. One that does not is muted
and inert, and says only that it does not resolve here: whether the memory
exists in a database this reader may not see is not something this page may
answer. */
.mem-body .mem-link { font-family: monospace; font-size: .85rem; }
.mem-body .mem-link-out {
font-family: monospace; font-size: .85rem;
color: var(--bd-muted); border-bottom: 1px dotted var(--bd-border); cursor: help;
}
.mem-empty { color: var(--bd-muted); font-style: italic; }
</style>
<div class="memory">
<h2><a href="/~{{.Repo.OwnerName}}/{{.Repo.Name}}">~{{.Repo.OwnerName}}/{{.Repo.Name}}</a> · memory</h2>
{{template "beadsHead" (dict "Repo" .Repo "Ref" .Ref "Head" .Head)}}
{{template "viewtabs" (dict "Repo" .Repo "Views" .Views "Current" "memory" "Ref" .Ref)}}
<form class="mem-filter" method="get" action="/~{{.Repo.OwnerName}}/{{.Repo.Name}}/view/memory">
{{if .Ref}}<input type="hidden" name="ref" value="{{.Ref}}">{{end}}
{{/* The sort is not a filter, but this form is a GET: without carrying it,
searching from the review queue would answer in slug order. */}}
{{if eq .Data.Sort "age"}}<input type="hidden" name="sort" value="age">{{end}}
<input type="search" name="q" value="{{.Data.Search}}" placeholder="Search memories">
<button type="submit">Filter</button>
{{/* Clear drops the search and the single-memory selection and keeps the ref
and the sort: the sort is how the list is read, not what it is filtered
to. */}}
{{if or .Data.Search .Data.Key}}<a class="mem-clear" href="/~{{.Repo.OwnerName}}/{{.Repo.Name}}/view/memory{{if .Ref}}?ref={{.Ref}}{{if eq .Data.Sort "age"}}&sort=age{{end}}{{else}}{{if eq .Data.Sort "age"}}?sort=age{{end}}{{end}}">Clear</a>{{end}}
</form>
<div class="mem-bar">
<span class="count">{{.Data.Total}} {{if eq .Data.Total 1}}entry{{else}}entries{{end}}</span>
<span class="l">sort:</span>
{{if eq .Data.Sort "age"}}
<a href="/~{{.Repo.OwnerName}}/{{.Repo.Name}}/view/memory{{withQuery .Data.Query "sort" ""}}">slug</a>
{{else}}<span class="current" aria-current="page">slug</span>{{end}}
<span class="sep">·</span>
{{if eq .Data.Sort "age"}}<span class="current" aria-current="page">age</span>
{{else}}<a href="/~{{.Repo.OwnerName}}/{{.Repo.Name}}/view/memory{{withQuery .Data.Query "sort" "age"}}">age</a>{{end}}
</div>
{{if .Data.Memories}}
{{range .Data.Memories}}
<article class="mem">
<header class="mem-head">
<h3 class="mem-slug"><a href="/~{{$.Repo.OwnerName}}/{{$.Repo.Name}}/view/memory?key={{.Slug | urlquery}}">{{.Slug}}</a></h3>
{{if .Stale}}<span class="mem-stale" title="Older than 60 days — worth a look. Some memories are meant to be permanent.">stale?</span>{{end}}
<span class="mem-rev">
{{/* The revision's author is deliberately not shown. bd's embedded Dolt
commits are all authored "root <root@%>" — verified against the
sourcehut-artifacts tracker, where every one of the nine memories
rendered "· root" — and the human is recorded only in the commit
message ("bd: close (auto-commit) by Eugene Blikh"), and not even in
every message. A column that says "root" nine times out of nine is
noise; the commit page behind the hash carries whatever the message
does say. */}}
{{with .Revision}}written <span title="{{.Date | abstime}}">{{.Date | agoDays}}</span>
· <a href="/~{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.Commit}}"><code>{{.Commit | shortsha}}</code></a>
{{- else}}written before the last {{$.Data.WalkMax}} commits{{end}}
</span>
</header>
{{/* The body is the stored markdown, rendered. The envelope's .Memories is
what resolves the [[slug]] references and the issue ids in it against the
databases this reader may browse; a nil one — a listing that failed —
still renders the markdown, with those left as text. */}}
<div class="mem-body">{{$.Memories.Body .Text}}</div>
</article>
{{end}}
{{else if .Data.Key}}
<p class="mem-empty">No memory named <code>{{.Data.Key}}</code>.</p>
{{else if .Data.Search}}
<p class="mem-empty">No memory matches “{{.Data.Search}}”.</p>
{{else}}
<p class="mem-empty">No memories. <code>bd remember</code> writes them into the <code>config</code> table, and they appear here.</p>
{{end}}
</div>
{{- end}}