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, RenderedAdr, markdown_to_html, render_adr, render_adr_index, render_doc,
13};
14pub use obsidian::{
15    AdrEntry, CouplingEntry, HOME_NOTE, VaultNote, VaultSummary, note_name, render_home,
16    render_note,
17};
18
19/// A render target for the graph.
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum Target {
22    /// Static documentation website (ADRs, blueprints, AI context pages).
23    DocsSite,
24    /// Obsidian-compatible markdown vault.
25    ObsidianVault,
26}
27
28impl Target {
29    /// Stable CLI name for this target.
30    #[must_use]
31    pub fn as_str(self) -> &'static str {
32        match self {
33            Self::DocsSite => "docs",
34            Self::ObsidianVault => "obsidian",
35        }
36    }
37
38    /// Parse a target from its CLI name.
39    #[must_use]
40    pub fn parse(s: &str) -> Option<Self> {
41        match s {
42            "docs" => Some(Self::DocsSite),
43            "obsidian" => Some(Self::ObsidianVault),
44            _ => None,
45        }
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::Target;
52
53    #[test]
54    fn target_names_are_stable() {
55        assert_eq!(Target::DocsSite.as_str(), "docs");
56        assert_eq!(Target::ObsidianVault.as_str(), "obsidian");
57        assert_eq!(Target::parse("docs"), Some(Target::DocsSite));
58        assert_eq!(Target::parse("obsidian"), Some(Target::ObsidianVault));
59        assert_eq!(Target::parse("nope"), None);
60    }
61}