forked from lambda-fairy/maud
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor book builder (lambda-fairy#288)
Move page and nav builders to separate modules.
- Loading branch information
1 parent
eb9cd82
commit 3ceb70d
Showing
6 changed files
with
143 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#![feature(once_cell)] | ||
|
||
pub mod page; | ||
pub mod string_writer; | ||
pub mod views; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,38 @@ | ||
use comrak::nodes::AstNode; | ||
use comrak::nodes::{AstNode, NodeHeading, NodeValue}; | ||
use comrak::{Arena, ComrakOptions}; | ||
use std::fs; | ||
use std::io; | ||
use std::lazy::SyncLazy; | ||
use std::path::Path; | ||
|
||
pub struct Page<'a> { | ||
pub title: Option<&'a AstNode<'a>>, | ||
pub content: &'a AstNode<'a>, | ||
} | ||
|
||
impl<'a> Page<'a> { | ||
pub fn load(arena: &'a Arena<AstNode<'a>>, path: impl AsRef<Path>) -> io::Result<Self> { | ||
let buffer = fs::read_to_string(path)?; | ||
let content = comrak::parse_document(arena, &buffer, &COMRAK_OPTIONS); | ||
|
||
let title = content.first_child().filter(|node| { | ||
let mut data = node.data.borrow_mut(); | ||
if let NodeValue::Heading(NodeHeading { level: 1, .. }) = data.value { | ||
node.detach(); | ||
data.value = NodeValue::Document; | ||
true | ||
} else { | ||
false | ||
} | ||
}); | ||
|
||
Ok(Self { title, content }) | ||
} | ||
} | ||
|
||
pub static COMRAK_OPTIONS: SyncLazy<ComrakOptions> = SyncLazy::new(|| { | ||
let mut options = ComrakOptions::default(); | ||
options.extension.header_ids = Some("".to_string()); | ||
options.render.unsafe_ = true; | ||
options | ||
}); |
Oops, something went wrong.