Skip to content

Commit

Permalink
Add optional support for yaml filter (see #192)
Browse files Browse the repository at this point in the history
  • Loading branch information
djc committed Jan 17, 2019
1 parent 744127b commit a1b5a9e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 3 deletions.
1 change: 1 addition & 0 deletions askama/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ maintenance = { status = "actively-developed" }
[features]
default = []
serde-json = ["askama_shared/serde_json"]
serde-yaml = ["askama_shared/serde_yaml"]
with-iron = ["iron", "askama_derive/iron"]
with-rocket = ["rocket", "askama_derive/rocket"]
with-actix-web = ["actix-web", "askama_derive/actix-web", "mime_guess"]
Expand Down
1 change: 1 addition & 0 deletions askama_shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ num-traits = "0.2.6"
serde = "1.0"
serde_derive = "1.0"
serde_json = { version = "1.0", optional = true }
serde_yaml = { version = "0.8", optional = true }
toml = "0.4"
16 changes: 15 additions & 1 deletion askama_shared/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
}
}
Expand All @@ -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"),
}
}
Expand All @@ -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;
Expand Down
9 changes: 7 additions & 2 deletions askama_shared/src/filters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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",
Expand All @@ -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
Expand Down
32 changes: 32 additions & 0 deletions askama_shared/src/filters/yaml.rs
Original file line number Diff line number Diff line change
@@ -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: Escaper, S: Serialize>(e: E, s: &S) -> Result<MarkupDisplay<E, String>> {
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"
);
}
}

0 comments on commit a1b5a9e

Please sign in to comment.