Skip to main content

rto_render/
lib.rs

1//! Renderers over the Roteiro graph. All outputs — docs site, Obsidian vault,
2//! and the optional MCP server (feature `mcp`) — are build products of the
3//! same store, so humans and agents always see the same data.
4
5mod docs;
6mod obsidian;
7
8#[cfg(feature = "mcp")]
9pub mod mcp;
10
11pub use docs::{
12    IndexEntry, NavEntry, PublishedPages, RenderedAdr, markdown_to_html, render_adr,
13    render_adr_index, render_doc, render_nav, render_site_page,
14};
15pub use obsidian::{
16    AdrEntry, ConfigSecretSummary, CouplingEntry, DensityEntry, HOME_NOTE, VaultNote, VaultSummary,
17    note_name, render_home, render_note,
18};
19
20/// A render target for the graph.
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum Target {
23    /// Static documentation website (ADRs, blueprints, AI context pages).
24    DocsSite,
25    /// Obsidian-compatible markdown vault.
26    ObsidianVault,
27}
28
29impl Target {
30    /// Stable CLI name for this target.
31    #[must_use]
32    pub fn as_str(self) -> &'static str {
33        match self {
34            Self::DocsSite => "docs",
35            Self::ObsidianVault => "obsidian",
36        }
37    }
38
39    /// Parse a target from its CLI name.
40    #[must_use]
41    pub fn parse(s: &str) -> Option<Self> {
42        match s {
43            "docs" => Some(Self::DocsSite),
44            "obsidian" => Some(Self::ObsidianVault),
45            _ => None,
46        }
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::Target;
53
54    #[test]
55    fn target_names_are_stable() {
56        assert_eq!(Target::DocsSite.as_str(), "docs");
57        assert_eq!(Target::ObsidianVault.as_str(), "obsidian");
58        assert_eq!(Target::parse("docs"), Some(Target::DocsSite));
59        assert_eq!(Target::parse("obsidian"), Some(Target::ObsidianVault));
60        assert_eq!(Target::parse("nope"), None);
61    }
62}