Skip to main content

rto_render/
lib.rs

1//! Renderers over the Roteiro graph. All outputs — docs site, OKF bundle,
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;
6pub mod okf;
7pub mod tool_class;
8pub mod tool_text;
9
10#[cfg(feature = "mcp")]
11pub mod mcp;
12
13pub use docs::{
14    IndexEntry, NavEntry, PublishedPages, RenderedAdr, SourceBase, markdown_to_html, render_adr,
15    render_adr_index, render_doc, render_doc_at, render_nav, render_site_page, replace_site_nav,
16};
17
18/// A render target for the graph.
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum Target {
21    /// Static documentation website (ADRs, blueprints, AI context pages).
22    DocsSite,
23    /// An Open Knowledge Format bundle (OKF v0.2).
24    ///
25    /// Replaced `ObsidianVault` in 4.0.0. The vault was one-way — Roteiro wrote
26    /// it, nothing read it back, and only Obsidian could consume it. An OKF
27    /// bundle is markdown with YAML frontmatter in nested directories, so
28    /// Obsidian still opens it as a vault; what changed is that the output now
29    /// targets a specification with other consumers rather than one
30    /// application's conventions.
31    OkfBundle,
32}
33
34impl Target {
35    /// Stable CLI name for this target.
36    #[must_use]
37    pub fn as_str(self) -> &'static str {
38        match self {
39            Self::DocsSite => "docs",
40            Self::OkfBundle => "okf",
41        }
42    }
43
44    /// Parse a target from its CLI name.
45    #[must_use]
46    pub fn parse(s: &str) -> Option<Self> {
47        match s {
48            "docs" => Some(Self::DocsSite),
49            "okf" => Some(Self::OkfBundle),
50            _ => None,
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::Target;
58
59    #[test]
60    fn target_names_are_stable() {
61        assert_eq!(Target::DocsSite.as_str(), "docs");
62        assert_eq!(Target::OkfBundle.as_str(), "okf");
63        assert_eq!(Target::parse("docs"), Some(Target::DocsSite));
64        assert_eq!(Target::parse("okf"), Some(Target::OkfBundle));
65        // The removed target must not silently resolve to something else: a
66        // script still passing `obsidian` should be told, not quietly redirected.
67        assert_eq!(Target::parse("obsidian"), None);
68        assert_eq!(Target::parse("nope"), None);
69    }
70}