Skip to main content

docgen_core/
model.rs

1use serde::Serialize;
2
3/// A discovered markdown file, before processing.
4#[derive(Debug, Clone, PartialEq)]
5pub struct RawDoc {
6    /// Path relative to the docs root, using `/` separators, e.g. `guide/intro.md`.
7    pub rel_path: String,
8    /// Raw file contents.
9    pub raw: String,
10}
11
12/// A fully processed document ready to render.
13#[derive(Debug, Clone, PartialEq, Serialize)]
14pub struct Doc {
15    /// Path relative to docs root, e.g. `guide/intro.md`.
16    pub rel_path: String,
17    /// URL slug without extension, e.g. `guide/intro`.
18    pub slug: String,
19    /// Resolved page title.
20    pub title: String,
21    /// Frontmatter `description:`, if any. Feeds the home dashboard subtitle and
22    /// the "Recent" list. `None` when the doc has no `description:`.
23    #[serde(default, skip_serializing_if = "Option::is_none")]
24    pub description: Option<String>,
25    /// Rendered body HTML.
26    pub body_html: String,
27    /// Whether this doc contains math (drives the conditional KaTeX `<head>` link).
28    pub has_math: bool,
29    /// Whether this doc contains a mermaid diagram (drives the lazy island load).
30    pub has_mermaid: bool,
31    /// Names of custom components rendered on this page (drives per-page island load).
32    #[serde(default)]
33    pub components_used: std::collections::BTreeSet<String>,
34    /// The `h2`/`h3` outline of this page, in document order, for the right-rail
35    /// "On this page" table of contents. Ids match the `id` attributes stamped
36    /// onto the rendered heading tags in `body_html`.
37    #[serde(default)]
38    pub headings: Vec<crate::headings::Heading>,
39    /// `sidebar: false` in frontmatter — the page is still built and reachable by
40    /// URL, but is omitted from the sidebar tree (see [`crate::tree::build_tree`]).
41    /// On a folder's `index.md`, it hides the whole directory subtree.
42    /// Build-internal; never serialized.
43    #[serde(skip)]
44    pub hidden_from_sidebar: bool,
45}
46
47/// A node in the sidebar tree.
48#[derive(Debug, Clone, PartialEq, Serialize)]
49#[serde(tag = "kind", rename_all = "lowercase")]
50pub enum TreeNode {
51    Dir {
52        name: String,
53        /// Slug of this folder's "folder note" — an `index.md` directly inside the
54        /// directory. `Some` makes the folder label a link to that page (clicking
55        /// the folder focuses its note); `None` is a plain, non-navigable group.
56        /// The note doc is NOT also emitted as a child of this dir.
57        #[serde(default, skip_serializing_if = "Option::is_none")]
58        slug: Option<String>,
59        children: Vec<TreeNode>,
60    },
61    Doc {
62        name: String,
63        slug: String,
64        title: String,
65    },
66}
67
68/// One resolved wikilink edge: `from` doc links to `to` doc (both slugs).
69#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)]
70pub struct LinkEdge {
71    pub from: String,
72    pub to: String,
73}
74
75/// Per-target inbound reference, for rendering a "Backlinks" section.
76#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)]
77pub struct Backlink {
78    pub slug: String,
79    pub title: String,
80    /// The linking doc's frontmatter description, rendered as a `<small>` under
81    /// the title in the rail's "Referenced by" cards. `None` when the linking
82    /// doc has no `description:` in its frontmatter.
83    #[serde(default, skip_serializing_if = "Option::is_none")]
84    pub description: Option<String>,
85}
86
87/// One entry in the static search index.
88#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
89pub struct SearchEntry {
90    pub slug: String,
91    pub title: String,
92    pub text: String,
93}