// Appendix — Tag Index Pages
// Auto-generated pages listing all notes for each tag
#import "document.typ": theme-mode
#import "theme.typ": palettes
#let make-tag-slug(tag) = {
let slug = tag.replace(regex("[^a-zA-Z0-9]+"), "-").trim("-")
if slug == "" { "untitled" } else { slug }
}
// Renders a single tag index page
// tag: the tag name string
// notes: array of (title, label-slug) pairs
#let tag-index-page(tag, notes) = {
let colors = palettes.at(theme-mode).appendix
page(
fill: colors.outer,
margin: 0.5cm,
height: auto,
{
set text(
size: 11pt,
fill: colors.text,
)
show ref: it => {
let make-styled(c) = text(fill: colors.accent, strong(c))
if it.supplement != auto and it.supplement != none {
link(it.target, make-styled(it.supplement))
} else if it.element != none and it.element.func() == heading {
link(it.target, make-styled(it.element.body))
} else {
it
}
}
block(
width: 100%,
fill: colors.card,
radius: 2pt,
inset: 24pt,
stroke: 1pt + colors.stroke,
{
// Hidden heading for label target (tag page anchor)
set heading(numbering: "1.1")
show heading: it => {
if it.level >= 10 {
box(width: 0pt, height: 0pt, clip: true, it)
} else {
it.body
}
}
// Anchor label for this tag page
let tag-slug = make-tag-slug(tag)
[#heading(level: 10)[#tag] #label("tag-" + tag-slug)]
// Header
block(width: 100%, {
grid(
columns: (1fr, auto),
align: (left + horizon, right + horizon),
text(size: 9pt, fill: colors.meta, "TAG INDEX"),
box(
fill: colors.tag-bg,
radius: 4pt,
inset: (x: 8pt, y: 3pt),
text(size: 8pt, weight: "bold", fill: colors.accent, "APPENDIX"),
)
)
v(-8pt)
text(size: 18pt, weight: "bold", fill: colors.accent, "#" + tag)
})
v(6pt)
line(length: 100%, stroke: 0.5pt + colors.line)
v(8pt)
// Note list — masonry-style card grid
set text(fill: colors.text)
grid(
columns: (1fr, 1fr),
gutter: 8pt,
..notes.map(note => {
let (title, slug) = note
link(label(slug), box(
width: 100%,
fill: colors.tag-bg,
radius: 6pt,
inset: (x: 12pt, y: 10pt),
stroke: 0.5pt + colors.stroke,
{
text(size: 10pt, weight: "medium", fill: colors.accent, title)
}
))
})
)
}
)
}
)
}