From b86a30fb78ebb7dbaa15e5dc1b69d3099d7b70ce Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Tue, 4 Apr 2017 16:08:40 +0900 Subject: [PATCH] Add markdown and base64 filters --- CHANGELOG.md | 1 + Cargo.lock | 10 ++++++ Cargo.toml | 1 + src/filters.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 +++ src/site.rs | 4 +++ 6 files changed, 113 insertions(+) create mode 100644 src/filters.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index cd33217d..00b6fecc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,3 +7,4 @@ - Fix page rendering not working when containing `+++` - Add shortcodes (see README for details) - Allow relative links to other content in markdown links +- Add `markdown`, `base64_encode` and `base64_decode` filters to the Tera instance of Gutenberg diff --git a/Cargo.lock b/Cargo.lock index fcaa5d1b..362a826e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,7 @@ name = "gutenberg" version = "0.0.2" dependencies = [ + "base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -71,6 +72,14 @@ dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bincode" version = "0.6.1" @@ -1057,6 +1066,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" "checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80" "checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842" +"checksum base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9892882c3bd89ed02dec391c128984c772b663a29700c32b5de0b33861cdf2bd" "checksum bincode 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "55eb0b7fd108527b0c77860f75eca70214e11a8b4c6ef05148c54c05a25d48ad" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" diff --git a/Cargo.toml b/Cargo.toml index b9dabd42..f7be70d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ syntect = "1" chrono = "0.3" toml = { version = "0.3", default-features = false, features = ["serde"]} term-painter = "0.2" +base64 = "0.4" # Below is for the serve cmd staticfile = "0.4" diff --git a/src/filters.rs b/src/filters.rs new file mode 100644 index 00000000..f40cb04c --- /dev/null +++ b/src/filters.rs @@ -0,0 +1,93 @@ +use std::collections::{HashMap}; + +use base64::{encode, decode}; +use pulldown_cmark as cmark; +use tera::{Value, to_value, Result as TeraResult}; + +// fn(Value, HashMap) -> Result + +pub fn markdown(value: Value, _: HashMap) -> TeraResult { + let s = try_get_value!("markdown", "value", String, value); + + let mut html = String::new(); + let parser = cmark::Parser::new(&s); + cmark::html::push_html(&mut html, parser); + + Ok(to_value(&html).unwrap()) +} + + +pub fn base64_encode(value: Value, _: HashMap) -> TeraResult { + let s = try_get_value!("base64_encode", "value", String, value); + Ok( + to_value(&encode(s.as_bytes())).unwrap() + ) +} + +pub fn base64_decode(value: Value, _: HashMap) -> TeraResult { + let s = try_get_value!("base64_decode", "value", String, value); + Ok( + to_value( + &String::from_utf8( + decode(s.as_bytes()).unwrap() + ).unwrap() + ).unwrap() + ) +} + + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use tera::{to_value}; + + use super::{markdown, base64_decode, base64_encode}; + + #[test] + fn test_markdown() { + let result = markdown(to_value(&"# Hey").unwrap(), HashMap::new()); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), to_value(&"

Hey

\n").unwrap()); + } + + #[test] + fn test_base64_encode() { + // from https://tools.ietf.org/html/rfc4648#section-10 + let tests = vec![ + ("", ""), + ("f", "Zg=="), + ("fo", "Zm8="), + ("foo", "Zm9v"), + ("foob", "Zm9vYg=="), + ("fooba", "Zm9vYmE="), + ("foobar", "Zm9vYmFy") + ]; + for (input, expected) in tests { + let args = HashMap::new(); + let result = base64_encode(to_value(input).unwrap(), args); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), to_value(expected).unwrap()); + } + } + + + #[test] + fn test_base64_decode() { + let tests = vec![ + ("", ""), + ("Zg==", "f"), + ("Zm8=", "fo"), + ("Zm9v", "foo"), + ("Zm9vYg==", "foob"), + ("Zm9vYmE=", "fooba"), + ("Zm9vYmFy", "foobar") + ]; + for (input, expected) in tests { + let args = HashMap::new(); + let result = base64_decode(to_value(input).unwrap(), args); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), to_value(expected).unwrap()); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 6701114f..03ed1093 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,11 +9,13 @@ extern crate toml; extern crate walkdir; extern crate pulldown_cmark; extern crate regex; +#[macro_use] extern crate tera; extern crate glob; extern crate syntect; extern crate slug; extern crate chrono; +extern crate base64; #[cfg(test)] extern crate tempdir; @@ -25,6 +27,8 @@ mod front_matter; mod site; mod markdown; mod section; +/// Additional filters for Tera +mod filters; pub use site::{Site, GUTENBERG_TERA}; pub use config::{Config, get_config}; diff --git a/src/site.rs b/src/site.rs index f9724f61..a3d7a5f3 100644 --- a/src/site.rs +++ b/src/site.rs @@ -13,6 +13,7 @@ use config::{Config, get_config}; use page::{Page, populate_previous_and_next_pages}; use utils::{create_file, create_directory}; use section::{Section}; +use filters; lazy_static! { @@ -78,6 +79,9 @@ impl Site { let tpl_glob = format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*"); let mut tera = Tera::new(&tpl_glob).chain_err(|| "Error parsing templates")?; tera.extend(&GUTENBERG_TERA)?; + tera.register_filter("markdown", filters::markdown); + tera.register_filter("base64_encode", filters::base64_encode); + tera.register_filter("base64_decode", filters::base64_decode); let site = Site { base_path: path.to_path_buf(),