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}