mdbook_repo_links/
main.rs1mod links;
22mod resolver;
23
24fn main() -> std::process::ExitCode {
25 if std::env::args().nth(1).as_deref() == Some("supports") {
27 return std::process::ExitCode::SUCCESS;
28 }
29 match run() {
30 Ok(()) => std::process::ExitCode::SUCCESS,
31 Err(message) => {
32 eprintln!("mdbook-repo-links: {message}");
33 std::process::ExitCode::FAILURE
34 }
35 }
36}
37
38fn run() -> Result<(), String> {
40 let input: serde_json::Value = serde_json::from_reader(std::io::stdin().lock())
41 .map_err(|e| format!("cannot read mdBook's input: {e}"))?;
42 let serde_json::Value::Array(mut parts) = input else {
43 return Err("mdBook's input is not [context, book]".into());
44 };
45 if parts.len() != 2 {
46 return Err("mdBook's input is not [context, book]".into());
47 }
48 let mut book = parts.pop().unwrap_or_default();
49 let context = parts.pop().unwrap_or_default();
50 let config = resolver::Config::from_context(&context)?;
51 rewrite_book(&mut book, &config);
52 serde_json::to_writer(std::io::stdout().lock(), &book)
53 .map_err(|e| format!("cannot write the book back: {e}"))
54}
55
56fn rewrite_book(value: &mut serde_json::Value, config: &resolver::Config) {
59 match value {
60 serde_json::Value::Object(map) => {
61 if let Some(serde_json::Value::Object(chapter)) = map.get_mut("Chapter") {
62 rewrite_chapter(chapter, config);
63 }
64 for child in map.values_mut() {
65 rewrite_book(child, config);
66 }
67 }
68 serde_json::Value::Array(items) => {
69 for item in items {
70 rewrite_book(item, config);
71 }
72 }
73 _ => {}
74 }
75}
76
77fn rewrite_chapter(
78 chapter: &mut serde_json::Map<String, serde_json::Value>,
79 config: &resolver::Config,
80) {
81 let Some(source) = chapter
83 .get("source_path")
84 .and_then(serde_json::Value::as_str)
85 else {
86 return;
87 };
88 let resolver = resolver::Resolver::for_chapter(config, std::path::Path::new(source));
89 if let Some(serde_json::Value::String(content)) = chapter.get_mut("content") {
90 *content = links::rewrite_links(content, &|target| resolver.resolve(target));
91 }
92}