diff --git a/sailfish-compiler/src/config.rs b/sailfish-compiler/src/config.rs index f4d7110..5af998e 100644 --- a/sailfish-compiler/src/config.rs +++ b/sailfish-compiler/src/config.rs @@ -5,6 +5,7 @@ pub struct Config { pub delimiter: char, pub escape: bool, pub cache_dir: PathBuf, + pub rm_whitespace: bool, #[doc(hidden)] pub _non_exhaustive: () } @@ -15,6 +16,7 @@ impl Default for Config { delimiter: '%', escape: true, cache_dir: Path::new(env!("OUT_DIR")).join("cache"), + rm_whitespace: false, _non_exhaustive: () } } diff --git a/sailfish-compiler/src/optimizer.rs b/sailfish-compiler/src/optimizer.rs index ceadb46..58f5330 100644 --- a/sailfish-compiler/src/optimizer.rs +++ b/sailfish-compiler/src/optimizer.rs @@ -34,7 +34,9 @@ fn get_rendertext_value(i: &ExprMacro) -> Option { None } -struct OptmizerImpl {} +struct OptmizerImpl { + rm_whitespace: bool, +} impl VisitMut for OptmizerImpl { fn visit_expr_mut(&mut self, i: &mut Expr) { @@ -84,18 +86,67 @@ impl VisitMut for OptmizerImpl { *i = new_expr; } + + fn visit_expr_macro_mut(&mut self, i: &mut ExprMacro) { + if self.rm_whitespace { + if let Some(v) = get_rendertext_value(i) { + let mut buffer = String::new(); + let mut it = v.lines().peekable(); + + if let Some(line) = it.next() { + if it.peek().is_some() { + buffer.push_str(line.trim_end()); + buffer.push('\n'); + } else { + return; + } + } + + while let Some(line) = it.next() { + if it.peek().is_some() { + if !line.is_empty() { + buffer.push_str(line.trim()); + buffer.push('\n'); + } else { + // ignore empty line + } + } else { + // last line + buffer.push_str(line.trim_start()); + } + } + i.mac.tokens = quote! { sfrt::render_text!(_ctx, #buffer); }; + return; + } + } + + syn::visit_mut::visit_expr_macro_mut(self, i); + } } -pub struct Optimizer {} +pub struct Optimizer { + rm_whitespace: bool, +} impl Optimizer { #[inline] pub fn new() -> Self { - Self {} + Self { + rm_whitespace: false, + } + } + + #[inline] + pub fn rm_whitespace(mut self, new: bool) -> Self { + self.rm_whitespace = new; + self } #[inline] pub fn optimize(&self, i: &mut Block) { - OptmizerImpl {}.visit_block_mut(i); + OptmizerImpl { + rm_whitespace: self.rm_whitespace, + } + .visit_block_mut(i); } } diff --git a/sailfish-compiler/src/procmacro.rs b/sailfish-compiler/src/procmacro.rs index caa915b..89ca973 100644 --- a/sailfish-compiler/src/procmacro.rs +++ b/sailfish-compiler/src/procmacro.rs @@ -30,6 +30,7 @@ struct DeriveTemplateOptions { path: Option, delimiter: Option, escape: Option, + rm_whitespace: Option, type_: Option, } @@ -59,6 +60,8 @@ impl Parse for DeriveTemplateOptions { options.delimiter = Some(s.parse::()?); } else if key == "escape" { options.escape = Some(s.parse::()?); + } else if key == "rm_whitespace" { + options.rm_whitespace = Some(s.parse::()?); } else if key == "type" { options.type_ = Some(s.parse::()?); } else { @@ -103,6 +106,7 @@ impl DeriveTemplateOptions { merge_single(&mut self.path, other.path)?; merge_single(&mut self.delimiter, other.delimiter)?; merge_single(&mut self.escape, other.escape)?; + merge_single(&mut self.rm_whitespace, other.rm_whitespace)?; merge_single(&mut self.type_, other.type_)?; Ok(()) } @@ -125,6 +129,9 @@ fn compile( if let Some(ref escape) = options.escape { config.escape = escape.value; } + if let Some(ref rm_whitespace) = options.rm_whitespace { + config.rm_whitespace = rm_whitespace.value; + } let compiler = Compiler::with_config(config); compiler.compile_file(template_dir, input_file, &*output_file)