// The semantic elements every docs/typ topic uses, and the one place they // are defined. Content files call them ("this is a key", "this is a // builtin"); how each looks is decided here, per output: paged outputs // (the A4 cheatsheet, later the book) draw them, HTML export gives them // elements and classes for a stylesheet. Page geometry and fonts belong to // the output wrappers beside this file. /// The `atelier` theme (src/themes/atelier.zig): pardes's acme homage, /// butter paper and blue-green tags. #let palette = ( paper: rgb("#fffdeb"), ink: rgb("#293f35"), tag-bg: rgb("#e4f0ed"), tag-fg: rgb("#3d6055"), tag-name: rgb("#6e4774"), grip: rgb("#36826b"), col-grip: rgb("#955815"), str: rgb("#34743d"), num: rgb("#9a5810"), rule: rgb("#95baa2"), ) #let mono = "DejaVu Sans Mono" /// Topic ids for #doc. Each names the document that holds the topic today; /// as topics move into docs/typ the value becomes the HTML page or chapter. #let topics = ( tags: "docs/tags.md", fs: "docs/fs.md", config: "docs/config.md", themes: "docs/themes.md", keys: "docs/helix-keys.md", detached: "docs/detached.md", ) #let html-out() = target() == "html" #let span(class, body) = html.elem("span", attrs: (class: class), body) #let m(s, fill: palette.ink) = text(font: mono, size: 0.92em, fill: fill, s) /// A key or a sequence of keys, one cap per space-separated chord. #let key(k) = context if html-out() { k.split(" ").map(t => html.elem("kbd", t)).join(" ") } else { k.split(" ").map(t => box( fill: white, stroke: 0.4pt + palette.rule, radius: 1.5pt, inset: (x: 1.6pt, y: 0pt), outset: (y: 1.4pt), m(t), )).join(h(1pt)) } /// A mouse button. #let btn(b) = context if html-out() { span("btn", b) } else { box( fill: palette.col-grip, radius: 2pt, inset: (x: 1.6pt, y: 0pt), outset: (y: 1.4pt), text(font: mono, size: 0.85em, weight: "bold", fill: white, b), ) } /// A chord: the first button held, the others clicked. #let chord(..bs) = bs.pos().map(btn).join(text(fill: palette.col-grip)[--]) /// A tag word or builtin, as it sits in a tag. #let word(w) = context if html-out() { span("word", raw(w)) } else { box(fill: palette.tag-bg, inset: (x: 1.4pt, y: 0pt), outset: (y: 1.4pt), m(w, fill: palette.tag-fg)) } /// A whole tagline: its grip, the path, then its words. #let tag(words, path: none) = context if html-out() { html.elem("div", attrs: (class: "tag"), { if path != none { span("path", path); [ ] } raw(words) }) } else { block(width: 100%, fill: palette.tag-bg, inset: (x: 2pt, y: 2.4pt), spacing: 0.5em, { box(fill: palette.grip, width: 0.55em, height: 0.75em, baseline: 0.1em) h(3pt) if path != none { m(path, fill: palette.tag-name); h(0.6em) } m(words, fill: palette.tag-fg) }) } /// A look address. #let addr(a) = context if html-out() { span("addr", raw(a)) } else { m(a, fill: palette.tag-name) } /// A 9P path. #let file(p) = context if html-out() { span("file", raw(p)) } else { m(p, fill: palette.str) } /// A shell line. #let cmd(c) = context if html-out() { raw(c, block: true, lang: "sh") } else { block( width: 100%, inset: (left: 3pt, y: 1.2pt), spacing: 0.4em, stroke: (left: 1pt + palette.rule), text(font: mono, size: 0.85em, fill: palette.ink, c), ) } /// Where the full story is: a topic id from `topics`, and a section in it. #let doc(id, section: none) = { let to = topics.at(id) + if section != none { "#" + section } else { "" } context if html-out() { link(to)[→ #to] } else { text(fill: palette.num)[→#m(to, fill: palette.num)] } }