wowlab_docgen_cli/context/
mod.rs1mod children;
2pub mod collectors;
3mod deps;
4mod features;
5mod nav;
6mod used_by;
7
8use std::collections::BTreeMap;
9
10use minijinja::Value;
11use serde::Serialize;
12
13use crate::{RenderCtx, infra::metadata::PackageKind};
14
15fn ctx<'a>(map: &mut BTreeMap<&'a str, Value>, key: &'a str, val: impl Serialize) {
16 map.insert(key, Value::from_serialize(val));
17}
18
19#[must_use]
21pub fn build(render_ctx: &RenderCtx<'_>) -> Value {
22 let name = render_ctx.metadata.name.as_deref().unwrap_or("");
23 let display_name = crate::display_name(name);
24 let meta = render_ctx.metadata;
25 let description = meta.description.as_deref().unwrap_or("");
26
27 let mut map = BTreeMap::<&str, Value>::new();
28
29 ctx(&mut map, "display_name", &display_name);
30 ctx(&mut map, "crate_name", name);
31 ctx(&mut map, "subtitle", description);
32 ctx(&mut map, "version", &meta.version);
33 ctx(&mut map, "msrv", &meta.msrv);
34 ctx(&mut map, "features", features::gather(render_ctx));
35 ctx(&mut map, "deps", deps::gather(render_ctx));
36 ctx(&mut map, "children", children::gather(render_ctx));
37 ctx(&mut map, "nav", nav::build(render_ctx));
38 ctx(&mut map, "used_by", used_by::gather(render_ctx));
39 ctx(&mut map, "external_deps", &meta.external_deps);
40
41 for (key, value) in collectors::collect_all(render_ctx) {
42 map.insert(key, value);
43 }
44
45 Value::from_serialize(&map)
46}
47
48#[must_use]
50pub fn default_base(ctx: &RenderCtx<'_>) -> &'static str {
51 let is_readme = ctx.output_stem.eq_ignore_ascii_case("README");
52
53 if is_readme {
54 if ctx.is_root() {
55 return "root.md.j2";
56 }
57
58 match ctx.metadata.kind {
59 PackageKind::RustCrate => "crate.md.j2",
60 PackageKind::NodePackage => "package.md.j2",
61 _ => "directory.md.j2",
62 }
63 } else {
64 if ctx.is_root() {
65 return "claude-root.md.j2";
66 }
67
68 match ctx.metadata.kind {
69 PackageKind::RustCrate => "claude-crate.md.j2",
70 PackageKind::NodePackage => "claude-package.md.j2",
71 _ => "claude-directory.md.j2",
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use googletest::prelude::*;
79
80 use super::*;
81 use crate::test_helpers::{meta, test_ctx};
82
83 #[gtest]
84 fn root_readme_uses_root_base() -> Result<()> {
85 let m = meta(PackageKind::RustCrate);
86
87 verify_eq!(
88 default_base(&test_ctx(m.kind, ".", "README", &m)),
89 "root.md.j2"
90 )
91 }
92
93 #[gtest]
94 fn crate_readme_uses_crate_base() -> Result<()> {
95 let m = meta(PackageKind::RustCrate);
96
97 verify_eq!(
98 default_base(&test_ctx(m.kind, "crates/common", "README", &m)),
99 "crate.md.j2"
100 )
101 }
102
103 #[gtest]
104 fn package_readme_uses_package_base() -> Result<()> {
105 let m = meta(PackageKind::NodePackage);
106
107 verify_eq!(
108 default_base(&test_ctx(m.kind, "apps/portal", "README", &m)),
109 "package.md.j2"
110 )
111 }
112
113 #[gtest]
114 fn directory_readme_uses_directory_base() -> Result<()> {
115 let m = meta(PackageKind::Directory);
116
117 verify_eq!(
118 default_base(&test_ctx(m.kind, "deploy", "README", &m)),
119 "directory.md.j2"
120 )
121 }
122
123 #[gtest]
124 fn claude_crate_uses_claude_crate_base() -> Result<()> {
125 let m = meta(PackageKind::RustCrate);
126
127 verify_eq!(
128 default_base(&test_ctx(m.kind, "crates/common", "CLAUDE", &m)),
129 "claude-crate.md.j2"
130 )
131 }
132
133 #[gtest]
134 fn claude_package_uses_claude_package_base() -> Result<()> {
135 let m = meta(PackageKind::NodePackage);
136
137 verify_eq!(
138 default_base(&test_ctx(m.kind, "apps/portal", "CLAUDE", &m)),
139 "claude-package.md.j2"
140 )
141 }
142
143 #[gtest]
144 fn agents_uses_claude_base() -> Result<()> {
145 let m = meta(PackageKind::RustCrate);
146
147 verify_eq!(
148 default_base(&test_ctx(m.kind, ".", "AGENTS", &m)),
149 "claude-root.md.j2"
150 )
151 }
152}