use crate::{parse_file, MetaFile, RootDirs, Source, Substitution};
-use color_eyre::Result;
+use color_eyre::{eyre::bail, Result};
+use pandoc::{InputFormat, InputKind, OutputFormat, OutputKind, Pandoc, PandocOutput};
use std::{
collections::HashMap,
fs,
path::{Path, PathBuf},
};
-pub fn build_metafile(file: &MetaFile, dirs: &RootDirs, path: &Path) -> Result<()> {
- Ok(std::fs::write(
- find_dest(path, dirs)?,
- metafile_to_string(file, dirs, None)?,
- )?)
+pub fn build_metafile(path: &Path, dirs: &RootDirs) -> Result<()> {
+ eprintln!("{:?}", path);
+ let file = fs::read_to_string(path)?;
+ let file = parse_file(&file)?;
+
+ let pattern = get_pattern("base", &file, dirs)?;
+ let mut base = parse_file(&pattern)?;
+
+ let html = get_source_html(&file, dirs)?;
+
+ base.variables = file.variables;
+ base.arrays = file.arrays;
+ base.patterns = file.patterns;
+
+ base.patterns.insert("SOURCE", &html);
+
+ let output = metafile_to_string(&base, dirs, Some("base"))?;
+
+ fs::write(find_dest(path, dirs)?, output)?;
+ Ok(())
}
pub fn metafile_to_string(file: &MetaFile, dirs: &RootDirs, name: Option<&str>) -> Result<String> {
let mut output = String::default();
+ let mut arrays = false;
for section in file.source.iter() {
match section {
let expanded = match sub {
Substitution::Variable(key) => file
.get_var(key)
+ // blank and default dont need to be processed
+ .filter(|val| *val != "BLANK" && *val != "DEFAULT")
.map(|val| val.to_string())
.unwrap_or_default(),
Substitution::Pattern(key) => get_pattern(key, file, dirs)?,
// comments have already been removed at this point,
// so we use them to mark keys for array substitution
- Substitution::Array(key) => format!("-{{{key}}}"),
+ Substitution::Array(key) => {
+ arrays = true;
+ format!("-{{{key}}}")
+ }
};
output.push_str(&format!("\n{}\n", expanded));
}
}
}
- // deal with arrays
- expand_arrays(output, file, name)
+ if arrays {
+ expand_arrays(output, file, name)
+ } else {
+ Ok(output)
+ }
+}
+
+fn get_source_html(file: &MetaFile, dirs: &RootDirs) -> Result<String> {
+ let file = metafile_to_string(file, dirs, Some("SOURCE"))?;
+ let mut pandoc = Pandoc::new();
+
+ pandoc
+ .set_input(InputKind::Pipe(file))
+ .set_output(OutputKind::Pipe)
+ .set_input_format(InputFormat::Markdown, vec![])
+ .set_output_format(OutputFormat::Html, vec![]);
+
+ if let Ok(PandocOutput::ToBuffer(html)) = pandoc.execute() {
+ Ok(html)
+ } else {
+ bail!("pandoc could not write to buffer")
+ }
}
fn get_pattern(key: &str, file: &MetaFile, dirs: &RootDirs) -> Result<String> {
- let filename = file.get_pat(key).unwrap_or("default");
+ // SOURCE is already expanded in the initial build_metafile() call
+ // we just need to return that
+ if key == "SOURCE" {
+ let source = file.patterns.get("SOURCE").unwrap_or(&"");
+ return Ok(source.to_string());
+ }
+
+ let mut filename = file.get_pat(key).unwrap_or("default");
+ // BLANK returns nothing, so no more processing needs to be done
+ if filename == "BLANK" {
+ return Ok(String::new());
+ };
+
+ if filename == "DEFAULT" {
+ filename = "default";
+ }
let pattern_path = key.replace('.', "/") + "/" + filename;
let mut path = dirs.pattern.join(pattern_path);
path.set_extension("meta");
+
let pattern = &fs::read_to_string(path.to_str().unwrap_or_default())?;
- let pattern = parse_file(pattern)?;
+ let mut pattern = parse_file(pattern)?;
+
+ // copy over maps for expanding contained variables
+ pattern.variables = file.variables.clone();
+ pattern.arrays = file.arrays.clone();
+ pattern.patterns = file.patterns.clone();
+
metafile_to_string(&pattern, dirs, Some(key))
}
None
}
})
- // make a hash map of keys in the source to previously defined arrays
+ // make a hash map of [keys in source] -> [defined arrays]
.map(|array| {
let key: String;
if let Some(name) = name {
-use crate::{metafile_to_string, parse_file, source, RootDirs, Source, Substitution};
+use crate::{parse_file, source, Source, Substitution};
use color_eyre::Result;
use pretty_assertions::assert_eq;
-use std::{fs, path::PathBuf};
-static SOURCE: &str = include_str!("../../tests/files/test_site/source/test_source.meta");
-static PATTERN: &str = include_str!("../../tests/files//test_site/pattern/test/pattern.meta");
+static SOURCE: &str = include_str!("../../test_site/source/test_source.meta");
+static PATTERN: &str = include_str!("../../test_site/pattern/test/pattern.meta");
#[test]
fn test_metafile_gets() -> Result<()> {
assert_eq!(source.get_var("var").unwrap(), "GOOD");
assert_eq!(source.get_var("single_quotes").unwrap(), "GOOD");
- assert_eq!(source.get_var("blank"), None);
+ assert_eq!(source.get_var("blank").unwrap(), "BLANK");
assert_eq!(source.get_var("not_defined"), None);
assert_eq!(source.get_arr("sub.array").unwrap(), ["GOOD", "GOOD"]);
assert_eq!(source.get_arr("not_defined"), None);
assert_eq!(source.get_pat("test").unwrap(), "pattern");
- assert_eq!(source.get_pat("test.sub_pat"), None);
- assert_eq!(source.get_pat("blank_pat"), None);
+ assert_eq!(source.get_pat("test.sub_pat").unwrap(), "DEFAULT");
+ assert_eq!(source.get_pat("blank_pat").unwrap(), "BLANK");
assert_eq!(source.get_pat("not_defined"), None);
Ok(())
let source = parse_file(SOURCE)?;
assert_eq!(source.variables.get("var").unwrap(), &"GOOD");
- assert_eq!(source.variables.get("blank"), None);
+ assert_eq!(source.variables.get("blank").unwrap(), &"BLANK");
assert_eq!(source.variables.get("not_here"), None);
assert_eq!(
assert_eq!(source.arrays.get("not_defined"), None);
assert_eq!(source.patterns.get("test").unwrap(), &"pattern");
- assert_eq!(source.patterns.get("test.sub_pat"), None);
- assert_eq!(source.patterns.get("blank_pat"), None);
+ assert_eq!(source.patterns.get("test.sub_pat").unwrap(), &"DEFAULT");
+ assert_eq!(source.patterns.get("blank_pat").unwrap(), &"BLANK");
assert_eq!(source.patterns.get("not_defined"), None);
Ok(())
use pretty_assertions::assert_eq;
use std::{fs, path::PathBuf};
-static PRE_EXPAND: &str = include_str!("./files/test_site/source/expand.meta");
+static PRE_EXPAND: &str = include_str!("../test_site/source/expand.meta");
static POST_EXPAND: &str = include_str!("./files/expanded");
#[test]
let file = metafile_to_string(&metafile, &dirs, None)?;
- assert_eq!(file, POST_EXPAND);
+ // requires newline to match with files ending newline
+ assert_eq!(file + "\n", POST_EXPAND);
+
+ Ok(())
+}
+
+#[test]
+#[ignore = "use different source file than expanded"]
+fn test_metafile_builder() -> Result<()> {
+ let dirs = build_rootdir()?;
+ let path = PathBuf::from("test_site/source/expand_html.meta");
+ build_metafile(&path, &dirs)?;
+ let source = fs::read_to_string("../test_site/site/expand_html.html")?;
+ let html = fs::read_to_string("./files/expand_html")?;
+
+ assert_eq!(source, html);
Ok(())
}
fn build_rootdir() -> Result<RootDirs> {
- let dir = PathBuf::from("./tests/files/test_site");
+ let dir = PathBuf::from("./test_site").canonicalize()?;
let dirs = RootDirs {
source: dir.join("source"),
if dirs.build.exists() {
fs::remove_dir(&dirs.build)?;
}
-
fs::create_dir(&dirs.build)?;
Ok(dirs)