Create proper skeleton
parent
ce0cfdd1d4
commit
767fb66c03
@ -0,0 +1,64 @@
|
||||
use std::{io, process};
|
||||
|
||||
use clap::{Arg, ArgMatches, Command};
|
||||
use mdbook::errors::Error;
|
||||
use mdbook::preprocess::{CmdPreprocessor, Preprocessor};
|
||||
use semver::{Version, VersionReq};
|
||||
|
||||
use mdbook_template::Template;
|
||||
|
||||
fn main() {
|
||||
let matches = make_app().get_matches();
|
||||
|
||||
let preprocessor = Template::new();
|
||||
|
||||
if let Some(sub_args) = matches.subcommand_matches("supports") {
|
||||
handle_supports(&preprocessor, sub_args);
|
||||
} else if let Err(e) = handle_preprocessing(&preprocessor) {
|
||||
eprintln!("{}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_app() -> Command<'static> {
|
||||
Command::new("mdbook-template")
|
||||
.about("A mdbook preprocessor that allows the re-usability of template files with variable arguments")
|
||||
.subcommand(
|
||||
Command::new("supports")
|
||||
.arg(Arg::new("renderer").required(true))
|
||||
.about("Check whether a renderer is supported by this preprocessor"),
|
||||
)
|
||||
}
|
||||
|
||||
fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> {
|
||||
let (ctx, book) = CmdPreprocessor::parse_input(io::stdin())?;
|
||||
|
||||
let book_version = Version::parse(&ctx.mdbook_version)?;
|
||||
let version_req = VersionReq::parse(mdbook::MDBOOK_VERSION)?;
|
||||
|
||||
if !version_req.matches(&book_version) {
|
||||
eprintln!(
|
||||
"Warning: The {} plugin was built against version {} of mdbook, \
|
||||
but we're being called from version {}",
|
||||
pre.name(),
|
||||
mdbook::MDBOOK_VERSION,
|
||||
ctx.mdbook_version
|
||||
);
|
||||
}
|
||||
|
||||
let processed_book = pre.run(&ctx, book)?;
|
||||
serde_json::to_writer(io::stdout(), &processed_book)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_supports(pre: &dyn Preprocessor, sub_args: &ArgMatches) -> ! {
|
||||
let renderer = sub_args.value_of("renderer").expect("Required argument");
|
||||
let supported = pre.supports_renderer(renderer);
|
||||
|
||||
if supported {
|
||||
process::exit(0);
|
||||
} else {
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
@ -1,8 +1,102 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = 2 + 2;
|
||||
assert_eq!(result, 4);
|
||||
use fancy_regex::{CaptureMatches, Captures, Regex};
|
||||
use lazy_static::lazy_static;
|
||||
use log::info;
|
||||
use mdbook::book::Book;
|
||||
use mdbook::errors::Result;
|
||||
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
|
||||
use mdbook::BookItem;
|
||||
use toml::Value;
|
||||
|
||||
lazy_static! {
|
||||
static ref ARGS: Regex = Regex::new(r"(?<=\s|\A)([^\s=]+)=(.*?)(?=(?:\s[^\s=]+=|$))").unwrap();
|
||||
static ref WHOLE_TEMPLATE: Regex = Regex::new(r"\\\{\{\#.*\}\}|\{\{\s*\#([a-zA-Z0-9_]+)\s+([a-zA-Z0-9_.-/]+)\s*([^}]+)\}\}").unwrap();
|
||||
// static ref RE: Regex = Regex::new(r"\\\{\{\#.*\}\}|\{\{\s*\#([a-zA-Z0-9_]+)\s+([a-zA-Z0-9-_.]+)\s*((?<=\s|\A)([^\s=]+)=(.*?)(?=(?:\s[^\s=]+=|$)))*\}\}").unwrap();
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Template;
|
||||
|
||||
impl Template {
|
||||
pub fn new() -> Self {
|
||||
Template
|
||||
}
|
||||
}
|
||||
|
||||
impl Preprocessor for Template {
|
||||
fn name(&self) -> &str {
|
||||
"template"
|
||||
}
|
||||
|
||||
fn run(&self, ctx: &PreprocessorContext, mut book: Book) -> Result<Book> {
|
||||
/*
|
||||
TODO - 29/04/2022
|
||||
Store All Files in Key/Value Pairs
|
||||
Start iterating through each chapter in the book
|
||||
1. Get template string
|
||||
2. Remove }} at the end of template string
|
||||
3. Store template string arguments in Key/Value Pairs
|
||||
4. Get the template and dynamically find/replace
|
||||
5. Set the chapter content to the new one
|
||||
Return the book to mdbook
|
||||
*/
|
||||
|
||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
||||
|
||||
if let Some(config) = ctx.config.get_preprocessor(self.name()) {
|
||||
let default = Value::String(String::from("templates/"));
|
||||
let template_dir = config.get("templates-dir").unwrap_or(&default);
|
||||
info!("Reading from directory {}", template_dir);
|
||||
}
|
||||
|
||||
book.for_each_mut(|book_item| {
|
||||
if let BookItem::Chapter(ref mut chapter) = book_item {
|
||||
chapter.content = String::from("All content is now replaced");
|
||||
}
|
||||
});
|
||||
|
||||
Ok(book)
|
||||
}
|
||||
|
||||
fn supports_renderer(&self, renderer: &str) -> bool {
|
||||
renderer == "html"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct Link<'a> {
|
||||
start_index: usize,
|
||||
end_index: usize,
|
||||
pub link_text: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Link<'a> {
|
||||
fn from_capture(cap: Captures<'a>) -> Option<Link<'a>> {
|
||||
cap.get(0).map(|mat| Link {
|
||||
start_index: mat.start(),
|
||||
end_index: mat.end(),
|
||||
link_text: mat.as_str(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LinkIter<'a>(CaptureMatches<'a, 'a>);
|
||||
|
||||
impl<'a> Iterator for LinkIter<'a> {
|
||||
type Item = Link<'a>;
|
||||
fn next(&mut self) -> Option<Link<'a>> {
|
||||
for cap in &mut self.0 {
|
||||
if let Some(inc) = Link::from_capture(cap.unwrap()) {
|
||||
return Some(inc);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_template_links(contents: &str) -> LinkIter<'_> {
|
||||
LinkIter(WHOLE_TEMPLATE.captures_iter(contents))
|
||||
}
|
||||
|
||||
pub fn extract_template_arguments(contents: &str) -> LinkIter<'_> {
|
||||
LinkIter(ARGS.captures_iter(contents))
|
||||
}
|
Loading…
Reference in New Issue