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}