From 3ea521d6e88150dd4307ad610cabfe0fb8f30f9d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 7 Mar 2023 12:04:31 +0100 Subject: Add whitespace argument in template derive proc-macro --- askama_derive/src/config.rs | 47 ++++++++++++++++++++++++++++-------------- askama_derive/src/generator.rs | 9 +++++++- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/askama_derive/src/config.rs b/askama_derive/src/config.rs index 98e51ce..22aada7 100644 --- a/askama_derive/src/config.rs +++ b/askama_derive/src/config.rs @@ -17,8 +17,11 @@ pub(crate) struct Config<'a> { pub(crate) whitespace: WhitespaceHandling, } -impl Config<'_> { - pub(crate) fn new(s: &str) -> std::result::Result, CompileError> { +impl<'a> Config<'a> { + pub(crate) fn new( + s: &'a str, + template_whitespace: Option<&String>, + ) -> std::result::Result, CompileError> { let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let default_dirs = vec![root.join("templates")]; @@ -31,7 +34,7 @@ impl Config<'_> { RawConfig::from_toml_str(s)? }; - let (dirs, default_syntax, whitespace) = match raw.general { + let (dirs, default_syntax, mut whitespace) = match raw.general { Some(General { dirs, default_syntax, @@ -49,6 +52,14 @@ impl Config<'_> { WhitespaceHandling::default(), ), }; + if let Some(template_whitespace) = template_whitespace { + whitespace = match template_whitespace.as_str() { + "suppress" => WhitespaceHandling::Suppress, + "minimize" => WhitespaceHandling::Minimize, + "preserve" => WhitespaceHandling::Preserve, + s => return Err(format!("invalid value for `whitespace`: \"{s}\"").into()), + }; + } if let Some(raw_syntaxes) = raw.syntax { for raw_s in raw_syntaxes { @@ -309,7 +320,7 @@ mod tests { #[test] fn get_source() { - let path = Config::new("") + let path = Config::new("", None) .and_then(|config| config.find_template("b.html", None)) .unwrap(); assert_eq!(get_template_source(&path).unwrap(), "bar"); @@ -319,7 +330,7 @@ mod tests { fn test_default_config() { let mut root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); root.push("templates"); - let config = Config::new("").unwrap(); + let config = Config::new("", None).unwrap(); assert_eq!(config.dirs, vec![root]); } @@ -328,7 +339,7 @@ mod tests { fn test_config_dirs() { let mut root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); root.push("tpl"); - let config = Config::new("[general]\ndirs = [\"tpl\"]").unwrap(); + let config = Config::new("[general]\ndirs = [\"tpl\"]", None).unwrap(); assert_eq!(config.dirs, vec![root]); } @@ -342,7 +353,7 @@ mod tests { #[test] fn find_absolute() { - let config = Config::new("").unwrap(); + let config = Config::new("", None).unwrap(); let root = config.find_template("a.html", None).unwrap(); let path = config.find_template("sub/b.html", Some(&root)).unwrap(); assert_eq_rooted(&path, "sub/b.html"); @@ -351,14 +362,14 @@ mod tests { #[test] #[should_panic] fn find_relative_nonexistent() { - let config = Config::new("").unwrap(); + let config = Config::new("", None).unwrap(); let root = config.find_template("a.html", None).unwrap(); config.find_template("c.html", Some(&root)).unwrap(); } #[test] fn find_relative() { - let config = Config::new("").unwrap(); + let config = Config::new("", None).unwrap(); let root = config.find_template("sub/b.html", None).unwrap(); let path = config.find_template("c.html", Some(&root)).unwrap(); assert_eq_rooted(&path, "sub/c.html"); @@ -366,7 +377,7 @@ mod tests { #[test] fn find_relative_sub() { - let config = Config::new("").unwrap(); + let config = Config::new("", None).unwrap(); let root = config.find_template("sub/b.html", None).unwrap(); let path = config.find_template("sub1/d.html", Some(&root)).unwrap(); assert_eq_rooted(&path, "sub/sub1/d.html"); @@ -389,7 +400,7 @@ mod tests { "#; let default_syntax = Syntax::default(); - let config = Config::new(raw_config).unwrap(); + let config = Config::new(raw_config, None).unwrap(); assert_eq!(config.default_syntax, "foo"); let foo = config.syntaxes.get("foo").unwrap(); @@ -421,7 +432,7 @@ mod tests { "#; let default_syntax = Syntax::default(); - let config = Config::new(raw_config).unwrap(); + let config = Config::new(raw_config, None).unwrap(); assert_eq!(config.default_syntax, "foo"); let foo = config.syntaxes.get("foo").unwrap(); @@ -449,7 +460,7 @@ mod tests { syntax = [{ name = "default" }] "#; - let _config = Config::new(raw_config).unwrap(); + let _config = Config::new(raw_config, None).unwrap(); } #[cfg(feature = "toml")] @@ -461,7 +472,7 @@ mod tests { { name = "foo", block_start = "%%" } ] "#; - let _config = Config::new(raw_config).unwrap(); + let _config = Config::new(raw_config, None).unwrap(); } #[cfg(feature = "toml")] @@ -473,7 +484,7 @@ mod tests { default_syntax = "foo" "#; - let _config = Config::new(raw_config).unwrap(); + let _config = Config::new(raw_config, None).unwrap(); } #[cfg(feature = "config")] @@ -485,6 +496,7 @@ mod tests { path = "::askama::Js" extensions = ["js"] "#, + None, ) .unwrap(); assert_eq!( @@ -509,11 +521,12 @@ mod tests { [general] whitespace = "suppress" "#, + None, ) .unwrap(); assert_eq!(config.whitespace, WhitespaceHandling::Suppress); - let config = Config::new(r#""#).unwrap(); + let config = Config::new(r#""#, None).unwrap(); assert_eq!(config.whitespace, WhitespaceHandling::Preserve); let config = Config::new( @@ -521,6 +534,7 @@ mod tests { [general] whitespace = "preserve" "#, + None, ) .unwrap(); assert_eq!(config.whitespace, WhitespaceHandling::Preserve); @@ -530,6 +544,7 @@ mod tests { [general] whitespace = "minimize" "#, + None, ) .unwrap(); assert_eq!(config.whitespace, WhitespaceHandling::Minimize); diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index cad7909..2101feb 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -30,7 +30,7 @@ pub(crate) fn derive_template(input: TokenStream) -> TokenStream { fn build_template(ast: &syn::DeriveInput) -> Result { let template_args = TemplateArgs::new(ast)?; let config_toml = read_config_file(template_args.config_path.as_deref())?; - let config = Config::new(&config_toml)?; + let config = Config::new(&config_toml, template_args.whitespace.as_ref())?; let input = TemplateInput::new(ast, &config, template_args)?; let source: String = match input.source { Source::Source(ref s) => s.clone(), @@ -83,6 +83,7 @@ pub(crate) struct TemplateArgs { pub(crate) ext: Option, pub(crate) syntax: Option, pub(crate) config_path: Option, + pub(crate) whitespace: Option, } impl TemplateArgs { @@ -181,6 +182,12 @@ impl TemplateArgs { } else { return Err("config value must be string literal".into()); } + } else if ident == "whitespace" { + if let syn::Lit::Str(ref s) = pair.lit { + args.whitespace = Some(s.value()) + } else { + return Err("whitespace value must be string literal".into()); + } } else { return Err(format!("unsupported attribute key {ident:?} found").into()); } -- cgit