Skip to main content

nova_doc/
lib.rs

1//! `nova doc`: the documentation site (spec
2//! `docs/superpowers/specs/2026-10-11-phase-3-5a-the-documentation-site-design.md`;
3//! ADR 0034).
4
5mod doctest;
6mod highlight;
7mod links;
8mod markdown;
9mod model;
10mod render;
11mod search;
12mod signature;
13mod write;
14
15pub use doctest::{package_doc_tests, std_doc_tests, DocTest, Origin};
16pub use links::{check_links, BrokenLink};
17pub use markdown::{classify, code_blocks, hidden, hide_lines, Block, CodeBlock, CodeLine};
18pub use model::{document_package, document_std, Documented, Failure, Site};
19pub use write::{write_site, WriteError, MARKER};
20
21/// The site's stylesheet: its light and dark themes (spec §10.2).
22pub(crate) const CSS: &str = include_str!("../assets/nova.css");
23
24/// The site's script: search and the theme toggle (spec §10).
25pub(crate) const JS: &str = include_str!("../assets/nova.js");
26
27/// `text` with `&`, `<`, `>`, `"` and `'` written as HTML entities.
28pub(crate) fn escape(text: &str) -> String {
29    let mut out = String::with_capacity(text.len());
30    for c in text.chars() {
31        match c {
32            '&' => out.push_str("&amp;"),
33            '<' => out.push_str("&lt;"),
34            '>' => out.push_str("&gt;"),
35            '"' => out.push_str("&quot;"),
36            '\'' => out.push_str("&#39;"),
37            c => out.push(c),
38        }
39    }
40    out
41}
42
43/// `text`, escaped, in a `<span>` of `class`.
44pub(crate) fn span(out: &mut String, class: &str, text: &str) {
45    out.push_str("<span class=\"");
46    out.push_str(class);
47    out.push_str("\">");
48    out.push_str(&escape(text));
49    out.push_str("</span>");
50}