lmjtfy.git / apps / lmjtfy / src / view / code.rs
code.rsannotatedcode.rssource818 lines · 37.5 KB · raw

The code pages: /<repo>.git, a repository's front page, and /<repo>.git/<path>, a directory or a file in it, for each repository the site serves. Pure: what GitHub said in, markup out.

5use maud::{DOCTYPE, Markup, PreEscaped, html};
7use super::{JS, clone_line, head, nav};

What a path came to, to show.

10pub enum Shown<'a> {

A folder, and its documents.

12    Dir { docs: Docs },
13    File { size: u64, body: &'a tree::Body, view: View },
14    Missing,
15    Unreachable,
16}

Which tab of the main pane is open: a folder's README (for people) or CLAUDE.md (for agents, on top of the README); a markdown file rendered or as its source.

21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum View {
23    People,
24    Agents,
25    Source,
26}
28impl View {

From ?view=: agents, source, or anything else for people.

30    pub fn asked(view: Option<&str>) -> View {
31        match view {
32            Some("agents") => View::Agents,
33            Some("source") => View::Source,
34            _ => View::People,
35        }
36    }
37}

A document, rendered, with where it is served.

40pub struct Doc {
41    pub path: String,
42    pub rendered: tree::Rendered,

A CLAUDE.md's @README.md, as the served path it imports.

44    pub imports: Option<String>,

Where a README says its chapter sits: the previous and the next.

46    pub guide: tree::Guide,
47}
49impl Doc {

text from the file at path (served), rendered for its kind: a CLAUDE.md shows its import as a link rather than as a line. base is the repository's address, /lmjtfy.git, that its relative links are made under.

54    pub fn new(path: &str, text: &str, base: &str) -> Doc {
55        let dir = tree::parent(path);
56        let name = path.rsplit('/').next().unwrap_or(path);
57        let (imports, text) =
58            if name.eq_ignore_ascii_case("CLAUDE.md") { tree::agents(text) } else { (None, text) };
59        let imports = imports.map(|imported| if dir.is_empty() { imported.to_owned() } else { format!("{dir}/{imported}") });
60        Doc { path: path.to_owned(), rendered: tree::markdown(text, dir, base), imports, guide: tree::guide(text, dir, base) }
61    }
62}

A folder's README and CLAUDE.md, and which is shown.

65pub struct Docs {
66    pub people: Option<Doc>,
67    pub agents: Option<Doc>,
68    pub view: View,
69}
71impl Docs {
72    fn shown(&self) -> Option<&Doc> {
73        match self.view {
74            View::Agents => self.agents.as_ref().or(self.people.as_ref()),
75            View::People | View::Source => self.people.as_ref().or(self.agents.as_ref()),
76        }
77    }
78}

A repository the site serves, as the code pages list it.

81#[derive(Clone, Copy, Debug, PartialEq, Eq)]
82pub struct Project {

lmjtfy.git: its address under the site, and its name here.

84    pub served: &'static str,
85    pub blurb: &'static str,

The branch the pages read.

87    pub branch: &'static str,
88}
90impl Project {

/lmjtfy.git, which every link on its pages starts with.

92    pub fn base(&self) -> String {
93        format!("/{}", self.served)
94    }

Whether it is jevcrates, which other projects depend on rather than clone, and whose pages say how.

98    fn is_jevcrates(&self) -> bool {
99        self.served == "jevcrates.git"
100    }
101}

jevcrates' crates, and when to depend on which: the "Use it" panel.

104const CRATES: [(&str, &str); 4] = [
105    ("jev-protocol", "the questions, the request bytes, the checks on an answer; no I/O, builds for wasm"),
106    ("jev-client", "the retry policy, behind your own transport"),
107    ("jev-http", "a native program: HTTP/2 on tokio, with a spend ledger"),
108    ("jev-worker", "a Cloudflare Worker, on its fetch"),
109];

What every code page has around its main pane: which repository, where in it, the whole tree for the explorer, the latest commit if GitHub could be read, and the other repositories.

114pub struct Frame<'a> {
115    pub origin: &'a str,
116    pub project: Project,

The served path, "" for the repository's root.

118    pub path: &'a str,
119    pub tree: &'a tree::Tree,
120    pub latest: Option<&'a card::Commit>,

How to clone it.

122    pub clone: String,

Every repository the site serves, this one among them.

124    pub projects: Vec<Project>,
125}
127impl Frame<'_> {
128    fn base(&self) -> String {
129        self.project.base()
130    }
131}

/<repo>.git and /<repo>.git/<path>: the editor. A sidebar (the explorer, the open document's outline, how to use or clone it, the latest commit, the other repositories) and a main pane with breadcrumbs, tabs and the document or file.

137pub fn page(frame: &Frame<'_>, shown: Shown<'_>) -> Markup {
138    let root = frame.path.is_empty();
139    let served = frame.project.served;
140    let title = match root {
141        true if served == "lmjtfy.git" => "LMJTFY · the code".to_owned(),
142        true => format!("{served} · the code"),
143        false => format!("{served}/{}", frame.path),
144    };
145    let description = match &shown {
146        _ if root => format!("{} · {}", frame.clone, frame.project.blurb),
147        Shown::Dir { .. } => format!("{} · {}", frame.project.blurb, frame.clone),
148        Shown::File { size, body: tree::Body::Text(text), .. } => format!("{} lines · {}", text.lines().count(), bytes(*size)),
149        Shown::File { size, .. } => bytes(*size),
150        Shown::Missing => "Nothing is there.".to_owned(),
151        Shown::Unreachable => "GitHub could not be read.".to_owned(),
152    };
153    let sha = frame.latest.map(card::Commit::short).unwrap_or(frame.project.branch);
154    // The open document: a folder's README or CLAUDE.md, or a markdown file
155    // rendered. Its headings are the outline; a diagram in it needs mermaid.
156    let file_doc = match &shown {
157        Shown::File { body: tree::Body::Text(text), view, .. } if markdown(frame.path) && *view != View::Source => {
158            Some(Doc::new(frame.path, text, &frame.base()))
159        }
160        _ => None,
161    };
162    let doc: Option<&Doc> = match &shown {
163        Shown::Dir { docs } => docs.shown(),
164        _ => file_doc.as_ref(),
165    };
166    let mermaid = doc.is_some_and(|doc| doc.rendered.mermaid);
167    let main = html! {
168        div .crumbs-bar { (crumbs(&frame.base(), served, frame.path)) }
169        @match &shown {
170            Shown::Dir { docs } => (folder(frame, docs)),
171            Shown::File { size, body, view } => (file(frame, *size, body, *view, file_doc.as_ref())),
172            Shown::Missing => (notice("Nothing is here. It may have moved: the explorer has what there is.")),
173            Shown::Unreachable => (notice("GitHub could not be read just now. Try again in a minute, or clone it.")),
174        }
175    };
176    html! {
177        (DOCTYPE)
178        html lang="en" {
179            (head(preview(frame.origin, served, &title, &description, sha)))
180            body .editor {
181                div .editor-top { (nav()) }
182                div .ide {
183                    aside .side aria-label="Explorer" { (sidebar(frame, doc)) }
184                    main .pane { (main) }
185                }
186                script { (PreEscaped(JS)) }
187                @if mermaid { script type="module" { (PreEscaped(MERMAID)) } }
188            }
189        }
190    }
191}

The sidebar's panels, each one that folds like an editor's.

194fn sidebar(frame: &Frame<'_>, doc: Option<&Doc>) -> Markup {
195    let outline: Vec<&tree::Heading> =
196        doc.map(|doc| doc.rendered.headings.iter().filter(|heading| (2..=3).contains(&heading.level)).collect()).unwrap_or_default();
197    html! {
198        details .panel open {
199            summary { "Explorer" }
200            div .explorer {
201                a .row .on[frame.path.is_empty()] href=(frame.base()) style="--depth: 0" { (pixel(&tree::icons::open(tree::icons::REPOSITORY))) (frame.project.served) }
202                @if frame.tree.entries.is_empty() {
203                    p .verdict { "The tree could not be read from GitHub just now." }
204                } @else {
205                    (branch(frame, "", 1))
206                }
207            }
208        }
209        @if !outline.is_empty() {
210            details .panel open {
211                summary { "Outline" }
212                ol .outline {
213                    @for heading in outline {
214                        li .sub[heading.level == 3] { a href={ "#" (heading.id) } { (heading.text) } }
215                    }
216                }
217            }
218        }
219        @if frame.project.is_jevcrates() {
220            (uses(frame))
221        }
222        details .panel open {
223            summary { "Clone" }
224            div .panel-body {
225                (clone_line(&frame.clone, html! {}))
226                p .verdict { "No GitHub account needed. It can be cloned and pulled, and nothing else." }
227            }
228        }
229        @if let Some(latest) = frame.latest {
230            details .panel open {
231                summary { "Latest on " (frame.project.branch) }
232                div .panel-body.latest {
233                    p { code { (latest.short()) } " " (latest.subject) }
234                    p .verdict { (latest.line()) }
235                }
236            }
237        }
238        details .panel open {
239            summary { "Repositories" }
240            ul .projects {
241                @for project in &frame.projects {
242                    li .on[*project == frame.project] {
243                        // The one you are in is the open one.
244                        @let icon = if *project == frame.project { tree::icons::open(tree::icons::REPOSITORY) } else { tree::icons::REPOSITORY.to_owned() };
245                        a href=(project.base()) { (pixel(&icon)) (project.served) }
246                        span .verdict { (project.blurb) }
247                    }
248                }
249            }
250        }
251    }
252}

jevcrates as a dependency: the lines for a project's Cargo.toml, pinned to the latest commit, through this site, so no GitHub account is needed.

256fn uses(frame: &Frame<'_>) -> Markup {
257    let git = format!("{}{}", frame.origin, frame.base());
258    let rev = frame.latest.map(|latest| latest.sha.as_str());
259    html! {
260        details .panel open {
261            summary { "Use it" }
262            div .panel-body {
263                p { "In your project's " code { "Cargo.toml" } ", the crates you need:" }
264                pre .cargo #cargo {
265                    "[dependencies]\n"
266                    @for (name, _) in CRATES {
267                        (name) " = { git = \"" (git) "\""
268                        @if let Some(rev) = rev { ", rev = \"" (rev) "\"" }
269                        " }\n"
270                    }
271                }
272                button .ghost type="button" data-copy="cargo" { "Copy" }
273                ul .crates {
274                    @for (name, what) in CRATES {
275                        li { a href={ (frame.base()) "/" (name) "/" } { code { (name) } } " " (what) }
276                    }
277                }
278                p .verdict { "Keep the ones you use. Cargo fetches them from here; the rev pins the commit." }
279            }
280        }
281    }
282}

One folder's entries in the explorer, nested. A folder on the way to the open path is open; the open path is marked.

286fn branch(frame: &Frame<'_>, folder: &str, depth: usize) -> Markup {
287    let open = |path: &str| frame.path == path || frame.path.starts_with(&format!("{path}/"));
288    html! {
289        @for entry in frame.tree.children(folder) {
290            @match entry.kind {
291                tree::Kind::Dir | tree::Kind::Submodule => {
292                    details .folder open[open(&entry.path)] {
293                        summary style={ "--depth: " (depth) } {
294                            a .row .on[frame.path == entry.path] href={ (frame.base()) "/" (entry.path) "/" } {
295                                (folder_icon(&entry.name)) (entry.name)
296                            }
297                        }
298                        (branch(frame, &entry.path, depth + 1))
299                    }
300                }
301                tree::Kind::File | tree::Kind::Symlink => {
302                    a .row .file .on[frame.path == entry.path] href={ (frame.base()) "/" (entry.path) } style={ "--depth: " (depth) } {
303                        (pixel(tree::icons::file(&entry.name))) (entry.name)
304                    }
305                }
306            }
307        }
308    }
309}

The chapters before and after this folder's, as (label, address): what its README's guide line says, and for a README with no guide line, the folder with a README before or after this one in a depth-first walk of the tree. A guide line that names no Next is the end of its guide.

315fn steps(frame: &Frame<'_>, docs: &Docs) -> (Option<(String, String)>, Option<(String, String)>) {
316    let said = docs.people.as_ref().map(|doc| doc.guide.clone()).unwrap_or_default();
317    let walk = chapters(frame);
318    let at = walk.iter().position(|path| path == frame.path);
319    let near = |offset: isize| -> Option<(String, String)> {
320        let path = walk.get(at?.checked_add_signed(offset)?)?;
321        let label = if path.is_empty() { frame.project.served.to_owned() } else { format!("{}/", name(path)) };
322        let href = if path.is_empty() { frame.base() } else { format!("{}/{path}/", frame.base()) };
323        Some((label, href))
324    };
325    if said.line { (said.previous, said.next) } else { (near(-1), near(1)) }
326}

Every folder with a README, the root first, in a depth-first walk in the explorer's order.

330fn chapters(frame: &Frame<'_>) -> Vec<String> {
331    fn walk(tree: &tree::Tree, folder: &str, out: &mut Vec<String>) {
332        let children = tree.children(folder);
333        if children.iter().any(|entry| entry.kind == tree::Kind::File && entry.name.eq_ignore_ascii_case("README.md")) {
334            out.push(folder.to_owned());
335        }
336        for child in children.iter().filter(|entry| matches!(entry.kind, tree::Kind::Dir | tree::Kind::Submodule)) {
337            walk(tree, &child.path, out);
338        }
339    }
340    let mut out = Vec::new();
341    walk(frame.tree, "", &mut out);
342    out
343}

A folder in the main pane: its README and CLAUDE.md as tabs, or, with neither, what is in it. The chapter before is a tab on the left, the one after on the right.

348fn folder(frame: &Frame<'_>, docs: &Docs) -> Markup {
349    let base = frame.base();
350    let here = if frame.path.is_empty() { base.clone() } else { format!("{base}/{}/", frame.path) };
351    let shown = docs.shown();
352    let is = |doc: &Option<Doc>| doc.as_ref().map(|doc| doc.path.as_str()) == shown.map(|doc| doc.path.as_str());
353    let (previous, next) = steps(frame, docs);
354    html! {
355        div .tabs-bar role="tablist" {
356            @if let Some((label, href)) = &previous {
357                a .tab .step .previous href=(href) rel="prev" title={ "Previous: " (label) } { span .arrow aria-hidden="true" { "◀" } span .step-label { (label) } }
358            }
359            @if let Some(people) = &docs.people {
360                a .tab .on[is(&docs.people)] href=(here) role="tab" { (pixel(tree::icons::file(name(&people.path)))) (name(&people.path)) span .tab-note { "for people" } }
361            }
362            @if let Some(agents) = &docs.agents {
363                a .tab .on[is(&docs.agents)] href={ (here) "?view=agents" } role="tab" { (pixel(tree::icons::file(name(&agents.path)))) (name(&agents.path)) span .tab-note { "for agents" } }
364            }
365            @if let Some((label, href)) = &next {
366                a .tab .step .next href=(href) rel="next" title={ "Next: " (label) } { span .step-label { (label) } span .arrow aria-hidden="true" { "▶" } }
367            }
368        }
369        @match shown {
370            Some(doc) => (document(frame, doc)),
371            // Nothing to show and no tree to list: GitHub was not read.
372            None if frame.tree.entries.is_empty() => {
373                (notice("GitHub could not be read just now, so there is nothing to show. Try again in a minute, or clone it."))
374            }
375            None => {
376                div .doc { ul .contents-list {
377                    @for entry in frame.tree.children(frame.path) {
378                        li { a href={ (base) "/" (entry.path) @if entry.kind != tree::Kind::File { "/" } } { (entry.name) } }
379                    }
380                } }
381            }
382        }
383    }
384}

A document: what it imports, and itself.

387fn document(frame: &Frame<'_>, doc: &Doc) -> Markup {
388    html! {
389        article .doc.md {
390            @if let Some(imports) = &doc.imports {
391                p .imports {
392                    "For agents, on top of " a href={ (frame.base()) "/" (imports) } { (name(imports)) }
393                    ", which they read first."
394                }
395            }
396            (PreEscaped(&doc.rendered.html))
397        }
398    }
399}

A file in the main pane: a markdown file rendered or as source, anything else with numbered lines.

403fn file(frame: &Frame<'_>, size: u64, body: &tree::Body, view: View, rendered: Option<&Doc>) -> Markup {
404    let here = format!("{}/{}", frame.base(), frame.path);
405    html! {
406        div .tabs-bar role="tablist" {
407            @if markdown(frame.path) {
408                a .tab .on[view != View::Source] href=(here) role="tab" { (pixel(tree::icons::file(name(frame.path)))) (name(frame.path)) span .tab-note { "preview" } }
409                a .tab .on[view == View::Source] href={ (here) "?view=source" } role="tab" { (pixel(tree::icons::file(name(frame.path)))) (name(frame.path)) span .tab-note { "source" } }
410            } @else if tree::annotate::language(frame.path).is_some() {
411                a .tab .on[view != View::Source] href=(here) role="tab" { (pixel(tree::icons::file(name(frame.path)))) (name(frame.path)) span .tab-note { "annotated" } }
412                a .tab .on[view == View::Source] href={ (here) "?view=source" } role="tab" { (pixel(tree::icons::file(name(frame.path)))) (name(frame.path)) span .tab-note { "source" } }
413            } @else {
414                span .tab .on { (pixel(tree::icons::file(name(frame.path)))) (name(frame.path)) }
415            }
416            span .tab-meta {
417                @if let tree::Body::Text(text) = body { (text.lines().count()) " lines · " }
418                (bytes(size)) " · " a href={ (here) "?raw" } { "raw" }
419            }
420        }
421        @match (body, rendered) {
422            (_, Some(doc)) => (document(frame, doc)),
423            (tree::Body::Text(text), None) => (source(frame, text, view)),
424            // A picture is shown; anything else that is not text is offered
425            // as it is.
426            (tree::Body::Binary(_), None) if tree::media_type(frame.path, body).starts_with("image/") => {
427                div .doc.md { img src={ (here) "?raw" } alt=(name(frame.path)); }
428            }
429            (tree::Body::Binary(_), None) => {
430                div .doc { p .verdict { "Not text. " a href={ (here) "?raw" } { "Open it as it is." } } }
431            }
432            (tree::Body::TooLarge, None) => {
433                div .doc { p .verdict { "Too large to show here. Clone it to read it." } }
434            }
435        }
436    }
437}

One of the pixel icons (/icons/<name>.png, third-party/jerrys-pixel-icons).

440fn pixel(icon: &str) -> Markup {
441    html! { img .icon.px src={ "/icons/" (icon) ".png" } alt="" width="18" height="18" loading="lazy"; }
442}

A folder's two icons, shut and open; the style sheet shows the one that matches its details.

446fn folder_icon(name: &str) -> Markup {
447    let shut = tree::icons::folder(name);
448    html! {
449        span .shut { (pixel(shut)) }
450        span .opened { (pixel(&tree::icons::open(shut))) }
451    }
452}

A source file. In a language known here it is read as Docco reads one (the owner, 2026-10-03: "extract the docstring put them on the left, and put the code they map to on the right, with syntax highlighting"): each run of comments rendered beside the code under it. ?view=source is the file top to bottom, coloured; a file with no comments of its own lines, or in no known language, is only that.

460fn source(frame: &Frame<'_>, text: &str, view: View) -> Markup {
461    let Some(language) = tree::annotate::language(frame.path) else {
462        return html! { div .doc.source { pre {
463            @for (index, line) in text.lines().enumerate() { (numbered(index + 1, html! { (line) })) }
464        } } };
465    };
466    let sections = tree::annotate::sections(text, language);
467    if view == View::Source || sections.iter().all(|section| section.prose.is_empty()) {
468        return html! { div .doc.source { pre {
469            @for line in tree::annotate::lines(text, language) { (coloured(&line)) }
470        } } };
471    }
472    let dir = tree::parent(frame.path);
473    html! {
474        div .doc.docco {
475            @for section in &sections {
476                div .sec {
477                    div .prose.md { (PreEscaped(tree::markdown(&section.prose, dir, &frame.base()).html)) }
478                    div .source { pre { @for line in &section.code { (coloured(line)) } } }
479                }
480            }
481        }
482    }
483}

A line of a file with its number, which is also its address (#L12).

486fn numbered(number: usize, line: Markup) -> Markup {
487    html! {
488        span .line id={ "L" (number) } {
489            a .number href={ "#L" (number) } { (number) }
490            (line) "\n"
491        }
492    }
493}
495fn coloured(line: &tree::annotate::Line<'_>) -> Markup {
496    numbered(
497        line.number,
498        html! {
499            @for (kind, piece) in &line.pieces {
500                @match kind.class() {
501                    Some(class) => span class=(class) { (piece) },
502                    None => (piece),
503                }
504            }
505        },
506    )
507}
508
509fn notice(why: &str) -> Markup {
510    html! { div .doc { p .verdict { (why) } } }
511}
512
513fn name(path: &str) -> &str {
514    path.rsplit('/').next().unwrap_or(path)
515}

The diagram drawer, pinned, from jsdelivr, on pages that have a diagram. Themed to the page: ink, paper and pink, square, in the mono face.

519const MERMAID: &str = r##"
520import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@12.1.0/dist/mermaid.esm.min.mjs";
521mermaid.initialize({
522  startOnLoad: false,
523  theme: "base",
524  fontFamily: "JetBrains Mono, ui-monospace, monospace",
525  themeVariables: {
526    primaryColor: "#fefefe", primaryTextColor: "#1e1e1e", primaryBorderColor: "#1e1e1e",
527    lineColor: "#1e1e1e", secondaryColor: "#f386a1", tertiaryColor: "#dedede",
528    background: "#dedede", mainBkg: "#fefefe", nodeBorder: "#1e1e1e", clusterBkg: "#dedede",
529    clusterBorder: "#1e1e1e", edgeLabelBackground: "#dedede", fontSize: "14px",
530  },
531  flowchart: { curve: "linear" },
532  // The page's look, inside each drawing: boxes are the window title bars
533  // (ink, paper text, square), labels in the pixel face, alternatives and
534  // notes in the pink, everything else in ink on paper. It is inside the
535  // SVG, so it outranks mermaid's own rules and comes along when a drawing
536  // is enlarged.
537  themeCSS: `
538    rect, polygon { rx: 0; ry: 0; }
539    .actor, .node rect, .node polygon, .node circle, .entityBox, .er.entityBox {
540      fill: #1e1e1e !important; stroke: #1e1e1e !important; }
541    text.actor, text.actor > tspan, .nodeLabel, .node .label, .entityLabel, .er.entityLabel {
542      fill: #fefefe !important; color: #fefefe !important;
543      font-family: VT323, "JetBrains Mono", monospace !important; font-size: 18px !important; }
544    .actor-line { stroke: #1e1e1e !important; stroke-dasharray: 2 3; }
545    .messageLine0, .messageLine1, .flowchart-link, .relationshipLine { stroke: #1e1e1e !important; stroke-width: 1.5px !important; }
546    .messageText, .edgeLabel, .labelText, .loopText, .loopText > tspan {
547      fill: #1e1e1e !important; color: #1e1e1e !important; font-family: "JetBrains Mono", monospace !important; }
548    .edgeLabel, .edgeLabel rect, .labelBkg { background: #fefefe !important; fill: #fefefe !important; }
549    .labelBox, .note { fill: #f386a1 !important; stroke: #1e1e1e !important; }
550    .loopLine { stroke: #1e1e1e !important; stroke-dasharray: 3 3; }
551    #arrowhead path, .arrowheadPath, marker path { fill: #1e1e1e !important; stroke: #1e1e1e !important; }
552    .attributeBoxOdd { fill: #fefefe !important; } .attributeBoxEven { fill: #dedede !important; }
553    .attributeBoxOdd, .attributeBoxEven { stroke: #1e1e1e !important; }
554    .er.attributeBoxOdd + text, text.er { font-family: "JetBrains Mono", monospace !important; }
555    .cluster rect { fill: #dedede !important; stroke: #1e1e1e !important; stroke-dasharray: 1 3; }
556    /* Entities (mermaid 12 draws them as paths with HTML labels): rows of
557       ink text on paper and grey, the name in the pixel face. */
558    .row-rect-odd path, .row-rect-odd { fill: #fefefe !important; }
559    .row-rect-even path, .row-rect-even { fill: #dedede !important; }
560    .outer-path path, .divider path, .divider { stroke: #1e1e1e !important; }
561    .label.name .nodeLabel, .label.name .nodeLabel p { color: #1e1e1e !important; fill: #1e1e1e !important;
562      font-family: VT323, monospace !important; font-size: 20px !important; }
563    .label.attribute-name .nodeLabel, .label.attribute-type .nodeLabel, .label.attribute-keys .nodeLabel,
564    .label.attribute-comment .nodeLabel, .label.attribute-name .nodeLabel p, .label.attribute-type .nodeLabel p,
565    .label.attribute-keys .nodeLabel p, .label.attribute-comment .nodeLabel p {
566      color: #1e1e1e !important; fill: #1e1e1e !important; font-family: "JetBrains Mono", monospace !important; font-size: 13px !important; }
567    .label.attribute-comment .nodeLabel { opacity: 0.75; }
568  `,
569});
570await mermaid.run({ querySelector: "pre.mermaid" });
571"##;
573fn preview(origin: &str, served: &str, title: &str, description: &str, sha: &str) -> Markup {
574    // The commit in the picture's address, so a chat fetches it again when
575    // there is a new one.
576    let picture = format!("{origin}/card.png?code={sha}&repo={served}");
577    html! {
578        title { (title) }
579        meta name="description" content=(description);
580        meta property="og:type" content="website";
581        meta property="og:site_name" content="LMJTFY · Let Me Jev That For You";
582        meta property="og:title" content=(title);
583        meta property="og:description" content=(description);
584        meta property="og:image" content=(picture);
585        meta property="og:image:type" content="image/png";
586        meta property="og:image:width" content=(card::WIDTH);
587        meta property="og:image:height" content=(card::HEIGHT);
588        meta name="twitter:card" content="summary_large_image";
589        meta name="theme-color" content="#f386a1";
590    }
591}

lmjtfy.git / packages / rules, each part a link to its folder.

594fn crumbs(base: &str, repo: &str, path: &str) -> Markup {
595    let parts: Vec<&str> = path.split('/').filter(|part| !part.is_empty()).collect();
596    html! {
597        span .crumbs {
598            a href=(base) { (repo) }
599            @for (index, part) in parts.iter().enumerate() {
600                " / "
601                @if index + 1 == parts.len() {
602                    span { (part) }
603                } @else {
604                    a href={ (base) "/" (parts[..=index].join("/")) "/" } { (part) }
605                }
606            }
607        }
608    }
609}
611fn markdown(path: &str) -> bool {
612    path.to_ascii_lowercase().ends_with(".md")
613}

335 B, 16.5 KB.

616fn bytes(size: u64) -> String {
617    if size < 1024 { format!("{size} B") } else { format!("{:.1} KB", size as f64 / 1024.0) }
618}

The repository's folders are the guide these pages show (the owner, 2026-10-02): every folder a chapter, and every link in a chapter going somewhere. These tests read the working tree, so a folder added without its pages, or a link to a file that moved, fails the build.

624#[cfg(test)]
625mod tests {
626    use super::*;
627
628    const LMJTFY: Project = Project { served: "lmjtfy.git", blurb: "This site.", branch: "main" };
629    const JEVCRATES: Project = Project { served: "jevcrates.git", blurb: "The client.", branch: "main" };
630
631    fn shown(project: Project, latest: Option<&card::Commit>) -> String {
632        let tree = tree::Tree::default();
633        let frame = Frame {
634            origin: "https://x",
635            project,
636            path: "",
637            tree: &tree,
638            latest,
639            clone: format!("git clone https://x/{}", project.served),
640            projects: vec![LMJTFY, JEVCRATES],
641        };
642        page(&frame, Shown::Dir { docs: Docs { people: None, agents: None, view: View::People } }).into_string()
643    }
644
645    #[test]
646    fn jevcrates_says_how_to_depend_on_it_at_the_latest_commit() {
647        let latest = card::Commit { sha: "4651441abc".into(), subject: "s".into(), date: "2026-10-02".into(), count: None };
648        let html = shown(JEVCRATES, Some(&latest));
649        // maud escapes the quotes; the copy button copies the text, unescaped.
650        assert!(html.contains("jev-client = { git = &quot;https://x/jevcrates.git&quot;, rev = &quot;4651441abc&quot; }"), "{html}");
651        assert!(html.contains(r#"href="/jevcrates.git/jev-http/""#), "{html}");
652        assert!(!shown(LMJTFY, Some(&latest)).contains("Use it"));
653        // With no commit read, the lines still work, unpinned.
654        assert!(shown(JEVCRATES, None).contains("jev-protocol = { git = &quot;https://x/jevcrates.git&quot; }"));
655    }
656
657    #[test]
658    fn a_repository_github_would_not_show_says_so() {
659        assert!(shown(LMJTFY, None).contains("GitHub could not be read just now, so there is nothing to show."));
660    }
661
662    #[test]
663    fn a_source_file_is_its_comments_beside_its_code() {
664        let tree = tree::parse_tree(r#"{"tree":[],"truncated":false}"#).expect("a tree");
665        let frame = |path| Frame { origin: "https://x", project: LMJTFY, path, tree: &tree, latest: None, clone: String::new(), projects: vec![] };
666        let text = "//! The *door*.\n\nuse std::fmt;\n\n/// Adds `<b>`.\nfn add() -> Option<u8> { None } // why\n";
667        let html = source(&frame("src/lib.rs"), text, View::People).into_string();
668        // Two runs of comments, each rendered as markdown beside its code.
669        assert_eq!(html.matches(r#"<div class="sec">"#).count(), 2, "{html}");
670        assert!(html.contains("The <em>door</em>."), "{html}");
671        // The code keeps its line numbers as addresses, and is coloured.
672        assert!(html.contains(r##"<span class="line" id="L6"><a class="number" href="#L6">6</a>"##), "{html}");
673        assert!(html.contains(r#"<span class="k">fn</span>"#) && html.contains(r#"<span class="t">Option</span>"#), "{html}");
674        assert!(html.contains(r#"<span class="c">// why</span>"#), "{html}");
675        // What a comment or the code says cannot become markup.
676        assert!(!html.contains("<b>"), "{html}");
677        // The same file top to bottom has every line and no prose column.
678        let plain = source(&frame("src/lib.rs"), text, View::Source).into_string();
679        assert!(!plain.contains("sec") && plain.contains(r#"id="L1""#) && plain.contains(r#"<span class="c">//! The *door*.</span>"#), "{plain}");
680        // A file in no known language is its lines, as it was.
681        let other = source(&frame("notes.txt"), "a < b\n", View::People).into_string();
682        assert!(other.contains("a &lt; b") && !other.contains("sec"), "{other}");
683    }
684
685    #[test]
686    fn a_chapter_steps_by_its_guide_line_or_else_depth_first() {
687        let listed = r#"[{"path":"README.md","type":"blob","sha":"1"},{"path":"a","type":"tree","sha":"2"},{"path":"a/README.md","type":"blob","sha":"3"},
688            {"path":"a/b","type":"tree","sha":"4"},{"path":"a/b/README.md","type":"blob","sha":"5"},{"path":"c","type":"tree","sha":"6"},{"path":"c/README.md","type":"blob","sha":"7"}]"#;
689        let tree = tree::parse_tree(&format!(r#"{{"tree":{listed},"truncated":false}}"#)).expect("a tree");
690        let frame = |path| Frame { origin: "https://x", project: LMJTFY, path, tree: &tree, latest: None, clone: String::new(), projects: vec![] };
691        let docs = |text: &str, dir: &str| Docs { people: Some(Doc::new(&format!("{dir}/README.md"), text, "/lmjtfy.git")), agents: None, view: View::People };
692        // No guide line: the walk. a/b comes after a, and c after a/b.
693        let (previous, next) = steps(&frame("a/b"), &docs("# b", "a/b"));
694        assert_eq!(previous, Some(("a/".into(), "/lmjtfy.git/a/".into())));
695        assert_eq!(next, Some(("c/".into(), "/lmjtfy.git/c/".into())));
696        // A guide line is followed as it is: here, no Previous.
697        let (previous, next) = steps(&frame("a/b"), &docs("# b\n\nNext: [Chapter 9, elsewhere](../../c/) →", "a/b"));
698        assert_eq!(next, Some(("Chapter 9, elsewhere".into(), "/lmjtfy.git/c/".into())));
699        assert_eq!(previous, None);
700        // The last chapter of a guide has no Next, and none is made up.
701        assert_eq!(steps(&frame("a/b"), &docs("# b\n\n← Previous: [a](../) · The end.", "a/b")).1, None);
702        let html = folder(&frame("a/b"), &docs("# b", "a/b")).into_string();
703        assert!(html.contains(r#"rel="prev""#) && html.contains(r#"rel="next""#), "{html}");
704        // The root has nothing before it.
705        assert_eq!(steps(&frame(""), &docs("# root", "")).0, None);
706    }
707
708    #[test]
709    fn every_page_lists_the_repositories_and_links_under_its_own() {
710        let html = shown(JEVCRATES, None);
711        assert!(html.contains(r#"<li class="on"><a href="/jevcrates.git">"#), "{html}");
712        assert!(html.contains(r#"<a href="/lmjtfy.git">"#), "{html}");
713        assert!(html.contains("card.png?code=main&amp;repo=jevcrates.git"), "{html}");
714        assert!(html.contains("<title>jevcrates.git · the code</title>"), "{html}");
715    }
716}
718#[cfg(test)]
719mod guide {
720    use std::path::{Path, PathBuf};

Not chapters: tools' state, build output, and jevcrates, which is another repository with its own guide.

724    const NOT_CHAPTERS: [&str; 9] =
725        [".git", ".claude", ".dev", ".direnv", ".wrangler", "target", "build", "node_modules", "third-party/jevcrates"];
727    fn root() -> PathBuf {
728        Path::new(env!("CARGO_MANIFEST_DIR")).join("../..").canonicalize().expect("the repository root")
729    }
730
731    fn folders() -> Vec<PathBuf> {
732        let root = root();
733        let mut found = vec![root.clone()];
734        let mut index = 0;
735        while index < found.len() {
736            let entries = std::fs::read_dir(&found[index]).expect("a readable folder");
737            for entry in entries.flatten() {
738                let path = entry.path();
739                let relative = path.strip_prefix(&root).unwrap_or(&path).to_string_lossy().into_owned();
740                if path.is_dir() && !NOT_CHAPTERS.iter().any(|skip| relative == *skip || relative.ends_with(&format!("/{skip}"))) {
741                    found.push(path);
742                }
743            }
744            index += 1;
745        }
746        found
747    }
748
749    #[test]
750    fn every_folder_is_a_chapter_with_a_page_for_people_and_one_for_agents() {
751        for folder in folders() {
752            let readme = std::fs::read_to_string(folder.join("README.md"));
753            let readme = readme.unwrap_or_else(|_| panic!("{} has no README.md", folder.display()));
754            assert!(readme.starts_with("# "), "{}: a README starts with its title", folder.display());
755            let claude = std::fs::read_to_string(folder.join("CLAUDE.md"));
756            let claude = claude.unwrap_or_else(|_| panic!("{} has no CLAUDE.md", folder.display()));
757            assert!(claude.starts_with("@README.md"), "{}: a CLAUDE.md imports its README first", folder.display());
758            assert!(readme.contains("Next:"), "{}: a chapter ends by leading on", folder.display());
759        }
760    }

/apps/lmjtfy/ as the guide line's link resolves under base "", back to the folder it names.

764    fn folder_of(address: &str) -> String {
765        address.trim_matches('/').to_owned()
766    }

The viewer's arrows follow the chapters' own guide lines, so those lines must be a depth-first walk: every chapter once, each folder before all of its subfolders, and a folder's subtree finished before its next sibling. The chain runs on into jevcrates' guide when the submodule is checked out.

773    #[test]
774    fn the_chapters_lead_on_depth_first_through_every_folder() {
775        let root = root();
776        let mut chain = vec![String::new()];
777        loop {
778            let at = chain.last().expect("a chapter");
779            let Ok(text) = std::fs::read_to_string(root.join(at).join("README.md")) else { break };
780            let guide = tree::guide(&text, at, "");
781            if let (Some((_, previous)), Some(before)) = (&guide.previous, chain.len().checked_sub(2).map(|i| &chain[i])) {
782                assert_eq!(&folder_of(previous), before, "{at}: Previous is not the chapter that led here");
783            }
784            let Some((_, next)) = guide.next else { break };
785            let next = folder_of(&next);
786            assert!(!chain.contains(&next), "{at}: Next leads back to {next}");
787            chain.push(next);
788        }
789        let under = |folder: &str, path: &str| folder.is_empty() || path.starts_with(&format!("{folder}/"));
790        for (index, folder) in chain.iter().enumerate() {
791            let after = &chain[index + 1..];
792            let inside = after.iter().take_while(|path| under(folder, path)).count();
793            assert!(
794                !after[inside..].iter().any(|path| under(folder, path)),
795                "{folder}: its subfolders are not all read before the guide moves on: {chain:?}"
796            );
797        }
798        for folder in folders() {
799            let relative = folder.strip_prefix(&root).expect("under the root").to_string_lossy().into_owned();
800            assert!(chain.contains(&relative), "{relative} is not on the guide's way: {chain:?}");
801        }
802    }
804    #[test]
805    fn every_relative_link_in_a_chapter_goes_somewhere() {
806        for folder in folders() {
807            let readme = std::fs::read_to_string(folder.join("README.md")).unwrap_or_default();
808            for target in readme.split("](").skip(1).filter_map(|rest| rest.split(')').next()) {
809                let external = target.contains("://") || target.starts_with('#') || target.starts_with("mailto:");
810                if external || target.is_empty() {
811                    continue;
812                }
813                let path = target.split(['#', '?']).next().unwrap_or(target);
814                assert!(folder.join(path).exists(), "{}: the link `{target}` goes nowhere", folder.join("README.md").display());
815            }
816        }
817    }
818}