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