summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorQrius <[email protected]>2024-09-26 00:11:05 +0200
committerQrius <[email protected]>2024-09-26 00:11:05 +0200
commit4eaf1f1327d0b88a6a5f937bb646753e639d4be7 (patch)
tree121c79510bf5f26b569c2f789130cb06b0398b27 /src
parenteb2a8c1ac8db20d176b1af6a2ea26a5b27b996d9 (diff)
downloadskaldpress-4eaf1f1327d0b88a6a5f937bb646753e639d4be7.tar.gz
skaldpress-4eaf1f1327d0b88a6a5f937bb646753e639d4be7.zip
Add ability to nest templates, improve a bunch of other things
Diffstat (limited to 'src')
-rw-r--r--src/skaldpress/error.rs4
-rw-r--r--src/skaldpress/main.rs105
-rw-r--r--src/skaldpress/metadata_parser.rs23
3 files changed, 110 insertions, 22 deletions
diff --git a/src/skaldpress/error.rs b/src/skaldpress/error.rs
index 9c84dd1..83b5253 100644
--- a/src/skaldpress/error.rs
+++ b/src/skaldpress/error.rs
@@ -15,6 +15,7 @@ pub enum SkaldpressError {
DirectoryReadError(u8, std::io::Error, String),
PathOperationError(u8, Option<Box<dyn Error>>),
DirectoryCreateError(u8, std::io::Error, String),
+ MetadataError(u8, std::io::Error),
SMPError(u8, SMPError),
}
@@ -36,6 +37,9 @@ impl fmt::Display for SkaldpressError {
SkaldpressError::DirectoryCreateError(code, _, dir) => {
write!(f, "[SP{}] Directory create error \"{}\"", code, dir)
}
+ SkaldpressError::MetadataError(code, e) => {
+ write!(f, "[SP{}] Invalid metadata! \"{:#?}\"", code, e)
+ }
SkaldpressError::SMPError(code, e) => {
write!(f, "[SP{}] Macro processing error \"{:#?}\"", code, e)
}
diff --git a/src/skaldpress/main.rs b/src/skaldpress/main.rs
index 1664272..84a4285 100644
--- a/src/skaldpress/main.rs
+++ b/src/skaldpress/main.rs
@@ -105,6 +105,55 @@ fn macro_processor(
macro_processor
}
+fn get_template_path(template: &str, opts: &Opts) -> String {
+ format!("{}{}", opts.template_dir, template)
+}
+
+fn wrap_template(
+ macro_processor: &mut MacroProcessor,
+ template_file: &str,
+ file_content: &str,
+ opts: &Opts,
+) -> Result<(String, String), SkaldpressError> {
+ let template = fs::read_to_string(&template_file).map_err(|e| {
+ SkaldpressError::TemplateReadError(
+ SP_COMPILE_FILE_TEMPLATE_READ_ERROR,
+ e,
+ template_file.to_string(),
+ )
+ })?;
+ let template_extension = Path::new(&template_file)
+ .extension()
+ .unwrap_or(std::ffi::OsStr::new(""));
+
+ let (template_metadata, template_content) = match extract_parse_yaml_metadata(&template) {
+ Some((map, file_content)) => (map, file_content),
+ None => (HashMap::new(), template.as_str()),
+ };
+
+ macro_processor.define_macro_string(String::from("CONTENT"), file_content.to_string());
+ let content = macro_processor
+ .process_input(&template_content)
+ .map_err(|e| SkaldpressError::SMPError(SP_COMPILE_TEMPLATE_MACRO_PROCESS_ERROR, e))?;
+
+ let Some(template_parent) = &template_metadata.get("template") else {
+ return Ok((
+ content,
+ template_extension.to_str().unwrap_or("").to_string(),
+ ));
+ };
+ let template_parent = &TryInto::<String>::try_into(*template_parent)
+ .map_err(|e| SkaldpressError::MetadataError(12, std::io::Error::other(e)))?;
+
+ println!("Wrapping in template {}", template_parent);
+ wrap_template(
+ macro_processor,
+ &get_template_path(template_parent, opts),
+ &content,
+ opts,
+ )
+}
+
/// Will attempt to compile a specific file, potentially storing some state about the file
fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, SkaldpressError> {
let extension = file_path.extension().unwrap_or(std::ffi::OsStr::new(""));
@@ -116,7 +165,10 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres
file_path.to_str().unwrap_or("unknown file").to_string(),
)
})?;
- let (map, file_content) = extract_parse_yaml_metadata(&file_content);
+ let (map, file_content) = match extract_parse_yaml_metadata(&file_content) {
+ Some((map, file_content)) => (map, file_content),
+ None => (HashMap::new(), file_content.as_str()),
+ };
let file_content = match extension
.to_str()
.ok_or(SkaldpressError::PathOperationError(
@@ -127,6 +179,19 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres
_ => file_content.to_string(),
};
+ if let Some(skip_smp) = &map.get("skip_smp") {
+ if let YamlValue::Scalar(skip_smp) = skip_smp {
+ if skip_smp.to_lowercase() == "true" {
+ return Ok(CompiledFile {
+ content: file_content,
+ metadata: map,
+ extension: String::from(extension.to_str().unwrap_or("")),
+ source_path: String::from(file_path.to_str().unwrap_or("")),
+ });
+ }
+ }
+ }
+
let mut macro_processor = macro_processor(&map, None);
let Some(template) = &map.get("template") else {
@@ -141,26 +206,19 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres
});
};
- let template_file = format!("{}{}", opts.template_dir, template);
- let template = fs::read_to_string(&template_file).map_err(|e| {
- SkaldpressError::TemplateReadError(
- SP_COMPILE_FILE_TEMPLATE_READ_ERROR,
- e,
- template_file.clone(),
- )
- })?;
- let template_extension = Path::new(&template_file)
- .extension()
- .unwrap_or(std::ffi::OsStr::new(""));
+ let template_file = get_template_path(
+ &TryInto::<String>::try_into(*template)
+ .map_err(|e| SkaldpressError::MetadataError(12, std::io::Error::other(e)))?,
+ opts,
+ );
+
+ let (content, template_extension) =
+ wrap_template(&mut macro_processor, &template_file, &file_content, opts)?;
- macro_processor.define_macro_string(String::from("CONTENT"), file_content);
- let content = macro_processor
- .process_input(&template)
- .map_err(|e| SkaldpressError::SMPError(SP_COMPILE_TEMPLATE_MACRO_PROCESS_ERROR, e))?;
Ok(CompiledFile {
content,
metadata: map,
- extension: String::from(template_extension.to_str().unwrap_or("")),
+ extension: String::from(template_extension),
source_path: String::from(file_path.to_str().unwrap_or("")),
})
}
@@ -228,7 +286,7 @@ fn compile_file_and_write(
}
}
- let dest_file_path = Path::new(&opts.build_dir)
+ let mut dest_file_path = Path::new(&opts.build_dir)
.join(
source_file_path
.strip_prefix(&opts.content_dir)
@@ -241,6 +299,17 @@ fn compile_file_and_write(
)
.with_extension(&cfile.extension);
+ if let Some(target_filename) = cfile.metadata.get("target_filename") {
+ match target_filename {
+ YamlValue::Scalar(filename) => {
+ dest_file_path = dest_file_path
+ .with_file_name(filename)
+ .with_extension(&cfile.extension)
+ }
+ _ => (),
+ }
+ }
+
let dest_dir = &dest_file_path
.parent()
.ok_or(SkaldpressError::PathOperationError(5, None))?;
diff --git a/src/skaldpress/metadata_parser.rs b/src/skaldpress/metadata_parser.rs
index 77ee7b8..4d6e352 100644
--- a/src/skaldpress/metadata_parser.rs
+++ b/src/skaldpress/metadata_parser.rs
@@ -16,10 +16,21 @@ impl fmt::Display for YamlValue {
}
}
+impl TryFrom<&YamlValue> for String {
+ type Error = String;
+
+ fn try_from(s: &YamlValue) -> Result<String, String> {
+ match s {
+ YamlValue::Scalar(s) => Ok(String::from(s)),
+ YamlValue::List(_) => Err(String::from("List value cannot be turned into string")),
+ }
+ }
+}
+
/// Extract a beginning YAML block of a input-string into a HashMap
-///
-/// Currently, all files MUST have a metadata block, or this will fail completely
-pub fn extract_parse_yaml_metadata<'a>(markdown: &'a str) -> (HashMap<String, YamlValue>, &'a str) {
+pub fn extract_parse_yaml_metadata<'a>(
+ markdown: &'a str,
+) -> Option<(HashMap<String, YamlValue>, &'a str)> {
let mut yaml_map = HashMap::new();
let lines = markdown.lines();
let mut yaml_started = false;
@@ -28,6 +39,10 @@ pub fn extract_parse_yaml_metadata<'a>(markdown: &'a str) -> (HashMap<String, Ya
let mut current_key: Option<String> = None;
let mut current_list: Vec<String> = Vec::new();
+ if lines.clone().next().unwrap_or("").trim() != "---" {
+ return None;
+ }
+
for (i, line) in lines.enumerate() {
if line.trim() == "---" {
if yaml_started {
@@ -69,5 +84,5 @@ pub fn extract_parse_yaml_metadata<'a>(markdown: &'a str) -> (HashMap<String, Ya
end_index = markdown.len();
}
- (yaml_map, &markdown[end_index..])
+ Some((yaml_map, &markdown[end_index..]))
}