diff --git a/Cargo.lock b/Cargo.lock index d8157f56..d8c3da3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3710,9 +3710,9 @@ dependencies = [ [[package]] name = "minijinja" -version = "1.0.13" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562e7acc6adf9a8359061ea3e0634560a3f636dc0539d36cd300c82fd703f528" +checksum = "7165d0e94806d52ad5295e4b54a95176d831814840bc067298ca647e1c956338" dependencies = [ "memo-map", "self_cell", diff --git a/Cargo.toml b/Cargo.toml index e9f9d8de..fcd3c97c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,7 +108,7 @@ default-features = false # Templates [workspace.dependencies.minijinja] -version = "1.0.13" +version = "2.0.1" # Random values [workspace.dependencies.rand] diff --git a/crates/handlers/src/upstream_oauth2/callback.rs b/crates/handlers/src/upstream_oauth2/callback.rs index a49f245b..44466d85 100644 --- a/crates/handlers/src/upstream_oauth2/callback.rs +++ b/crates/handlers/src/upstream_oauth2/callback.rs @@ -242,7 +242,7 @@ pub(crate) async fn get( let env = { let mut env = minijinja::Environment::new(); - env.add_global("user", minijinja::Value::from_serializable(&id_token)); + env.add_global("user", minijinja::Value::from_serialize(&id_token)); env }; diff --git a/crates/handlers/src/upstream_oauth2/template.rs b/crates/handlers/src/upstream_oauth2/template.rs index 586a82e0..2424adbc 100644 --- a/crates/handlers/src/upstream_oauth2/template.rs +++ b/crates/handlers/src/upstream_oauth2/template.rs @@ -43,7 +43,7 @@ fn b64encode(bytes: &[u8]) -> String { } /// Decode a Tag-Length-Value encoded byte array into a map of tag to value. -fn tlvdecode(bytes: &[u8]) -> Result, Error> { +fn tlvdecode(bytes: &[u8]) -> Result, Error> { let mut iter = bytes.iter().copied(); let mut ret = HashMap::new(); loop { @@ -67,7 +67,7 @@ fn tlvdecode(bytes: &[u8]) -> Result, Error> { ); } - ret.insert(tag, Value::from(Arc::new(bytes))); + ret.insert(tag.into(), Value::from(Arc::new(bytes))); } Ok(ret) diff --git a/crates/i18n-scan/src/main.rs b/crates/i18n-scan/src/main.rs index 6fa3ef8b..fb99220e 100644 --- a/crates/i18n-scan/src/main.rs +++ b/crates/i18n-scan/src/main.rs @@ -12,8 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Without the custom_syntax feature, the `SyntaxConfig` is a unit struct +// which is annoying with this clippy lint +#![allow(clippy::default_constructed_unit_structs)] + use std::fs::File; +use ::minijinja::{machinery::WhitespaceConfig, syntax::SyntaxConfig}; use camino::Utf8PathBuf; use clap::Parser; use key::Context; @@ -77,7 +82,12 @@ fn main() { if options.extensions.split(',').any(|e| e == extension) { tracing::debug!("Parsing {relative}"); let template = std::fs::read_to_string(&path).expect("Failed to read template"); - match minijinja::parse(&template, relative.as_str()) { + match minijinja::parse( + &template, + relative.as_str(), + SyntaxConfig::default(), + WhitespaceConfig::default(), + ) { Ok(ast) => { context.set_current_file(relative.as_str()); minijinja::find_in_stmt(&mut context, &ast).unwrap(); diff --git a/crates/i18n-scan/src/minijinja.rs b/crates/i18n-scan/src/minijinja.rs index d9936890..519b1bdd 100644 --- a/crates/i18n-scan/src/minijinja.rs +++ b/crates/i18n-scan/src/minijinja.rs @@ -247,6 +247,8 @@ fn find_in_optional_expr<'a>( #[cfg(test)] mod tests { + use minijinja::{machinery::WhitespaceConfig, syntax::SyntaxConfig}; + use super::*; #[test] @@ -288,7 +290,13 @@ mod tests { ]; for (name, content) in templates { - let ast = parse(content, name).unwrap(); + let ast = parse( + content, + name, + SyntaxConfig::default(), + WhitespaceConfig::default(), + ) + .unwrap(); find_in_stmt(&mut context, &ast).unwrap(); } @@ -323,7 +331,13 @@ mod tests { fn test_invalid_key_not_string() { // This is invalid because the key is not a string let mut context = Context::new("t".to_owned()); - let ast = parse(r"{{ t(5) }}", "invalid.txt").unwrap(); + let ast = parse( + r"{{ t(5) }}", + "invalid.txt", + SyntaxConfig::default(), + WhitespaceConfig::default(), + ) + .unwrap(); let res = find_in_stmt(&mut context, &ast); assert!(res.is_err()); @@ -333,7 +347,13 @@ mod tests { fn test_invalid_key_filtered() { // This is invalid because the key argument has a filter let mut context = Context::new("t".to_owned()); - let ast = parse(r#"{{ t("foo" | bar) }}"#, "invalid.txt").unwrap(); + let ast = parse( + r#"{{ t("foo" | bar) }}"#, + "invalid.txt", + SyntaxConfig::default(), + WhitespaceConfig::default(), + ) + .unwrap(); let res = find_in_stmt(&mut context, &ast); assert!(res.is_err()); @@ -343,7 +363,13 @@ mod tests { fn test_invalid_key_missing() { // This is invalid because the key argument is missing let mut context = Context::new("t".to_owned()); - let ast = parse(r"{{ t() }}", "invalid.txt").unwrap(); + let ast = parse( + r"{{ t() }}", + "invalid.txt", + SyntaxConfig::default(), + WhitespaceConfig::default(), + ) + .unwrap(); let res = find_in_stmt(&mut context, &ast); assert!(res.is_err()); @@ -353,7 +379,13 @@ mod tests { fn test_invalid_key_negated() { // This is invalid because the key argument is missing let mut context = Context::new("t".to_owned()); - let ast = parse(r#"{{ t(not "foo") }}"#, "invalid.txt").unwrap(); + let ast = parse( + r#"{{ t(not "foo") }}"#, + "invalid.txt", + SyntaxConfig::default(), + WhitespaceConfig::default(), + ) + .unwrap(); let res = find_in_stmt(&mut context, &ast); assert!(res.is_err()); diff --git a/crates/templates/src/context/branding.rs b/crates/templates/src/context/branding.rs index 5cdb7469..fe1aa5d3 100644 --- a/crates/templates/src/context/branding.rs +++ b/crates/templates/src/context/branding.rs @@ -14,7 +14,10 @@ use std::sync::Arc; -use minijinja::{value::StructObject, Value}; +use minijinja::{ + value::{Enumerator, Object}, + Value, +}; /// Site branding information. #[derive(Debug, Clone, PartialEq, Eq)] @@ -59,9 +62,9 @@ impl SiteBranding { } } -impl StructObject for SiteBranding { - fn get_field(&self, name: &str) -> Option { - match name { +impl Object for SiteBranding { + fn get_value(self: &Arc, name: &Value) -> Option { + match name.as_str()? { "server_name" => Some(self.server_name.clone().into()), "policy_uri" => self.policy_uri.clone().map(Value::from), "tos_uri" => self.tos_uri.clone().map(Value::from), @@ -70,7 +73,7 @@ impl StructObject for SiteBranding { } } - fn static_fields(&self) -> Option<&'static [&'static str]> { - Some(&["server_name", "policy_uri", "tos_uri", "imprint"]) + fn enumerate(self: &Arc) -> Enumerator { + Enumerator::Str(&["server_name", "policy_uri", "tos_uri", "imprint"]) } } diff --git a/crates/templates/src/context/features.rs b/crates/templates/src/context/features.rs index 6433f8e8..96df6734 100644 --- a/crates/templates/src/context/features.rs +++ b/crates/templates/src/context/features.rs @@ -12,7 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use minijinja::{value::StructObject, Value}; +use std::sync::Arc; + +use minijinja::{ + value::{Enumerator, Object}, + Value, +}; /// Site features information. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -24,16 +29,16 @@ pub struct SiteFeatures { pub password_login: bool, } -impl StructObject for SiteFeatures { - fn get_field(&self, field: &str) -> Option { - match field { +impl Object for SiteFeatures { + fn get_value(self: &Arc, field: &Value) -> Option { + match field.as_str()? { "password_registration" => Some(Value::from(self.password_registration)), "password_login" => Some(Value::from(self.password_login)), _ => None, } } - fn static_fields(&self) -> Option<&'static [&'static str]> { - Some(&["password_registration", "password_login"]) + fn enumerate(self: &Arc) -> Enumerator { + Enumerator::Str(&["password_registration", "password_login"]) } } diff --git a/crates/templates/src/functions.rs b/crates/templates/src/functions.rs index 9b26b868..a447ad12 100644 --- a/crates/templates/src/functions.rs +++ b/crates/templates/src/functions.rs @@ -31,7 +31,7 @@ use mas_spa::ViteManifest; use minijinja::{ escape_formatter, machinery::make_string_output, - value::{from_args, Kwargs, Object, SeqObject, ViaDeserialize}, + value::{from_args, Kwargs, Object, ViaDeserialize}, Error, ErrorKind, State, Value, }; use url::Url; @@ -76,8 +76,8 @@ pub fn register( }); } -fn tester_empty(seq: &dyn SeqObject) -> bool { - seq.item_count() == 0 +fn tester_empty(seq: Value) -> bool { + seq.len() == Some(0) } fn tester_starting_with(value: &str, prefix: &str) -> bool { @@ -236,7 +236,7 @@ impl std::fmt::Display for TranslatorFunc { } impl Object for TranslatorFunc { - fn call(&self, _state: &State, args: &[Value]) -> Result { + fn call(self: &Arc, _state: &State, args: &[Value]) -> Result { let (lang,): (&str,) = from_args(args)?; let lang: DataLocale = lang.parse().map_err(|e| { @@ -271,7 +271,7 @@ impl std::fmt::Display for TranslateFunc { } impl Object for TranslateFunc { - fn call(&self, state: &State, args: &[Value]) -> Result { + fn call(self: &Arc, state: &State, args: &[Value]) -> Result { let (key, kwargs): (&str, Kwargs) = from_args(args)?; let (message, _locale) = if let Some(count) = kwargs.get("count")? { @@ -326,7 +326,12 @@ impl Object for TranslateFunc { Ok(Value::from_safe_string(buf)) } - fn call_method(&self, _state: &State, name: &str, args: &[Value]) -> Result { + fn call_method( + self: &Arc, + _state: &State, + name: &str, + args: &[Value], + ) -> Result { match name { "relative_date" => { let (date,): (String,) = from_args(args)?; @@ -435,7 +440,7 @@ impl std::fmt::Display for IncludeAsset { } impl Object for IncludeAsset { - fn call(&self, _state: &State, args: &[Value]) -> Result { + fn call(self: &Arc, _state: &State, args: &[Value]) -> Result { let (path, kwargs): (&str, Kwargs) = from_args(args)?; let preload = kwargs.get("preload").unwrap_or(false); @@ -493,7 +498,12 @@ impl std::fmt::Display for Counter { } impl Object for Counter { - fn call_method(&self, _state: &State, name: &str, args: &[Value]) -> Result { + fn call_method( + self: &Arc, + _state: &State, + name: &str, + args: &[Value], + ) -> Result { // None of the methods take any arguments from_args::<()>(args)?; diff --git a/crates/templates/src/lib.rs b/crates/templates/src/lib.rs index fcd8f1ae..a1f77ed3 100644 --- a/crates/templates/src/lib.rs +++ b/crates/templates/src/lib.rs @@ -234,8 +234,8 @@ impl Templates { }) .await??; - env.add_global("branding", Value::from_struct_object(branding)); - env.add_global("features", Value::from_struct_object(features)); + env.add_global("branding", Value::from_object(branding)); + env.add_global("features", Value::from_object(features)); self::functions::register( &mut env, diff --git a/crates/templates/src/macros.rs b/crates/templates/src/macros.rs index f2f43b66..940201a4 100644 --- a/crates/templates/src/macros.rs +++ b/crates/templates/src/macros.rs @@ -62,7 +62,7 @@ macro_rules! register_templates { $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? (&self, context: &$param) -> Result { - let ctx = ::minijinja::value::Value::from_serializable(context); + let ctx = ::minijinja::value::Value::from_serialize(context); let env = self.environment.load(); let tmpl = env.get_template($template)