From a1b5a9ee2e3ce42c4c5bd52adda2879e902540c6 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 17 Jan 2019 11:30:13 +0100 Subject: Add optional support for yaml filter (see #192) --- askama_shared/src/error.rs | 16 +++++++++++++++- askama_shared/src/filters/mod.rs | 9 +++++++-- askama_shared/src/filters/yaml.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 askama_shared/src/filters/yaml.rs (limited to 'askama_shared/src') diff --git a/askama_shared/src/error.rs b/askama_shared/src/error.rs index bd35126..f3e8b48 100644 --- a/askama_shared/src/error.rs +++ b/askama_shared/src/error.rs @@ -32,6 +32,10 @@ pub enum Error { #[cfg(feature = "serde_json")] Json(::serde_json::Error), + /// yaml conversion error + #[cfg(feature = "serde_yaml")] + Yaml(::serde_yaml::Error), + /// This error needs to be non-exhaustive as /// the `Json` variants existence depends on /// a feature. @@ -54,6 +58,8 @@ impl ErrorTrait for Error { Error::Fmt(ref err) => err.source(), #[cfg(feature = "serde_json")] Error::Json(ref err) => err.source(), + #[cfg(feature = "serde_yaml")] + Error::Yaml(ref err) => err.source(), _ => None, } } @@ -63,9 +69,10 @@ impl Display for Error { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Error::Fmt(ref err) => write!(formatter, "formatting error: {}", err), - #[cfg(feature = "serde_json")] Error::Json(ref err) => write!(formatter, "json conversion error: {}", err), + #[cfg(feature = "serde_yaml")] + Error::Yaml(ref err) => write!(formatter, "yaml conversion error: {}", err), _ => write!(formatter, "unknown error: __Nonexhaustive"), } } @@ -84,6 +91,13 @@ impl From<::serde_json::Error> for Error { } } +#[cfg(feature = "serde_yaml")] +impl From<::serde_yaml::Error> for Error { + fn from(err: ::serde_yaml::Error) -> Self { + Error::Yaml(err) + } +} + #[cfg(test)] mod tests { use super::Error; diff --git a/askama_shared/src/filters/mod.rs b/askama_shared/src/filters/mod.rs index ea702db..7e7bc40 100644 --- a/askama_shared/src/filters/mod.rs +++ b/askama_shared/src/filters/mod.rs @@ -6,10 +6,14 @@ #[cfg(feature = "serde_json")] mod json; - #[cfg(feature = "serde_json")] pub use self::json::json; +#[cfg(feature = "serde_yaml")] +mod yaml; +#[cfg(feature = "serde_yaml")] +pub use self::yaml::yaml; + use crate::error::Error::Fmt; use askama_escape::{Escaper, MarkupDisplay}; use humansize::{file_size_opts, FileSize}; @@ -23,7 +27,7 @@ use super::Result; // Askama or should refer to a local `filters` module. It should contain all the // filters shipped with Askama, even the optional ones (since optional inclusion // in the const vector based on features seems impossible right now). -pub const BUILT_IN_FILTERS: [&str; 22] = [ +pub const BUILT_IN_FILTERS: [&str; 23] = [ "abs", "capitalize", "center", @@ -46,6 +50,7 @@ pub const BUILT_IN_FILTERS: [&str; 22] = [ "uppercase", "wordcount", "json", // Optional feature; reserve the name anyway + "yaml", // Optional feature; reserve the name anyway ]; /// Marks a string (or other `Display` type) as safe diff --git a/askama_shared/src/filters/yaml.rs b/askama_shared/src/filters/yaml.rs new file mode 100644 index 0000000..fdd03f6 --- /dev/null +++ b/askama_shared/src/filters/yaml.rs @@ -0,0 +1,32 @@ +use crate::error::{Error, Result}; +use askama_escape::{Escaper, MarkupDisplay}; +use serde::Serialize; + +/// Serialize to JSON (requires `serde_json` feature) +/// +/// ## Errors +/// +/// This will panic if `S`'s implementation of `Serialize` decides to fail, +/// or if `T` contains a map with non-string keys. +pub fn yaml(e: E, s: &S) -> Result> { + match serde_yaml::to_string(s) { + Ok(s) => Ok(MarkupDisplay::new_safe(s, e)), + Err(e) => Err(Error::from(e)), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use askama_escape::Html; + + #[test] + fn test_yaml() { + assert_eq!(yaml(Html, &true).unwrap().to_string(), "---\ntrue"); + assert_eq!(yaml(Html, &"foo").unwrap().to_string(), "---\nfoo"); + assert_eq!( + yaml(Html, &vec!["foo", "bar"]).unwrap().to_string(), + "---\n- foo\n- bar" + ); + } +} -- cgit