diff --git a/src/preprocess/links.rs b/src/preprocess/links.rs index 7ca6fd34..a6c30455 100644 --- a/src/preprocess/links.rs +++ b/src/preprocess/links.rs @@ -4,6 +4,7 @@ use crate::utils::{ take_rustdoc_include_lines, }; use regex::{CaptureMatches, Captures, Regex}; +use std::collections::HashMap; use std::fs; use std::ops::{Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeTo}; use std::path::{Path, PathBuf}; @@ -137,6 +138,7 @@ enum LinkType<'a> { Playground(PathBuf, Vec<&'a str>), RustdocInclude(PathBuf, RangeOrAnchor), Title(&'a str), + Template(PathBuf, HashMap), } #[derive(PartialEq, Debug, Clone)] @@ -208,6 +210,7 @@ impl<'a> LinkType<'a> { LinkType::Playground(p, _) => Some(return_relative_path(base, &p)), LinkType::RustdocInclude(p, _) => Some(return_relative_path(base, &p)), LinkType::Title(_) => None, + LinkType::Template(p, _) => Some(return_relative_path(base, &p)), } } } @@ -249,6 +252,19 @@ fn parse_range_or_anchor(parts: Option<&str>) -> RangeOrAnchor { } } +fn parse_template_path(arg: &str) -> LinkType<'static> { + let mut param_pairs = arg.split_whitespace(); + let path: PathBuf = param_pairs.next().unwrap().into(); + let mut dict = HashMap::new(); + param_pairs.for_each(|p| { + let mut pair = p.splitn(2, ':'); + let key = pair.next().unwrap().to_string(); + let value = pair.next().unwrap().to_string(); + dict.insert(key, value); + }); + LinkType::Template(path, dict) +} + fn parse_include_path(path: &str) -> LinkType<'static> { let mut parts = path.splitn(2, ':'); @@ -298,6 +314,7 @@ impl<'a> Link<'a> { Some(LinkType::Playground(pth.into(), props)) } ("rustdoc_include", Some(pth)) => Some(parse_rustdoc_include_path(pth)), + ("template", Some(pth)) => Some(parse_template_path(pth)), _ => None, } } @@ -386,6 +403,21 @@ impl<'a> Link<'a> { LinkType::Title(title) => { *chapter_title = title.to_owned(); Ok(String::new()) + LinkType::Template(ref pat, ref dict) => { + let target = base.join(pat); + fs::read_to_string(&target) + .map(|s| { + dict.iter().fold(s, |r, (key, value)| { + r.replace(format!("{{ {} }}", key).as_str(), value) + }) + }) + .with_context(|| { + format!( + "Could not read file for template {} ({})", + self.link_text, + target.display(), + ) + }) } } }