63 lines
1.8 KiB
Rust
63 lines
1.8 KiB
Rust
use comrak::nodes::AstNode;
|
|
use comrak::{self, Arena};
|
|
use docs::page::{Page, COMRAK_OPTIONS};
|
|
use docs::string_writer::StringWriter;
|
|
use serde_json;
|
|
use std::env;
|
|
use std::error::Error;
|
|
use std::fs;
|
|
use std::io;
|
|
use std::path::Path;
|
|
use std::str;
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
let args = env::args().collect::<Vec<_>>();
|
|
if args.len() < 2 || !args[2..].iter().all(|arg| arg.contains(":")) {
|
|
return Err("invalid arguments".into());
|
|
}
|
|
let entries = args[2..]
|
|
.iter()
|
|
.map(|arg| {
|
|
let mut splits = arg.splitn(2, ":");
|
|
let slug = splits.next().unwrap();
|
|
let input_path = splits.next().unwrap();
|
|
(slug, input_path)
|
|
})
|
|
.collect::<Vec<_>>();
|
|
build_nav(&entries, &args[1])
|
|
}
|
|
|
|
fn build_nav(entries: &[(&str, &str)], nav_path: &str) -> Result<(), Box<dyn Error>> {
|
|
let arena = Arena::new();
|
|
|
|
let nav = entries
|
|
.iter()
|
|
.map(|&(slug, input_path)| {
|
|
let title = load_page_title(&arena, input_path)?;
|
|
Ok((slug, title))
|
|
})
|
|
.collect::<io::Result<Vec<_>>>()?;
|
|
|
|
// Only write if different to avoid spurious rebuilds
|
|
let old_string = fs::read_to_string(nav_path).unwrap_or(String::new());
|
|
let new_string = serde_json::to_string_pretty(&nav)?;
|
|
if old_string != new_string {
|
|
fs::create_dir_all(Path::new(nav_path).parent().unwrap())?;
|
|
fs::write(nav_path, new_string)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn load_page_title<'a>(
|
|
arena: &'a Arena<AstNode<'a>>,
|
|
path: impl AsRef<Path>,
|
|
) -> io::Result<Option<String>> {
|
|
let page = Page::load(arena, path)?;
|
|
let title = page.title.map(|title| {
|
|
let mut buffer = String::new();
|
|
comrak::format_commonmark(title, &COMRAK_OPTIONS, &mut StringWriter(&mut buffer)).unwrap();
|
|
buffer
|
|
});
|
|
Ok(title)
|
|
}
|