@@ -7,3 +7,4 @@ | |||||
- Fix page rendering not working when containing `+++` | - Fix page rendering not working when containing `+++` | ||||
- Add shortcodes (see README for details) | - Add shortcodes (see README for details) | ||||
- Allow relative links to other content in markdown links | - Allow relative links to other content in markdown links | ||||
- Add `markdown`, `base64_encode` and `base64_decode` filters to the Tera instance of Gutenberg |
@@ -2,6 +2,7 @@ | |||||
name = "gutenberg" | name = "gutenberg" | ||||
version = "0.0.2" | version = "0.0.2" | ||||
dependencies = [ | 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)", | "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)", | "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)", | "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)", | "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]] | [[package]] | ||||
name = "bincode" | name = "bincode" | ||||
version = "0.6.1" | 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 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 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 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 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.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" | "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" | ||||
@@ -30,6 +30,7 @@ syntect = "1" | |||||
chrono = "0.3" | chrono = "0.3" | ||||
toml = { version = "0.3", default-features = false, features = ["serde"]} | toml = { version = "0.3", default-features = false, features = ["serde"]} | ||||
term-painter = "0.2" | term-painter = "0.2" | ||||
base64 = "0.4" | |||||
# Below is for the serve cmd | # Below is for the serve cmd | ||||
staticfile = "0.4" | staticfile = "0.4" | ||||
@@ -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<String, Value>) -> Result<Value> | |||||
pub fn markdown(value: Value, _: HashMap<String, Value>) -> TeraResult<Value> { | |||||
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<String, Value>) -> TeraResult<Value> { | |||||
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<String, Value>) -> TeraResult<Value> { | |||||
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(&"<h1>Hey</h1>\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()); | |||||
} | |||||
} | |||||
} |
@@ -9,11 +9,13 @@ extern crate toml; | |||||
extern crate walkdir; | extern crate walkdir; | ||||
extern crate pulldown_cmark; | extern crate pulldown_cmark; | ||||
extern crate regex; | extern crate regex; | ||||
#[macro_use] | |||||
extern crate tera; | extern crate tera; | ||||
extern crate glob; | extern crate glob; | ||||
extern crate syntect; | extern crate syntect; | ||||
extern crate slug; | extern crate slug; | ||||
extern crate chrono; | extern crate chrono; | ||||
extern crate base64; | |||||
#[cfg(test)] | #[cfg(test)] | ||||
extern crate tempdir; | extern crate tempdir; | ||||
@@ -25,6 +27,8 @@ mod front_matter; | |||||
mod site; | mod site; | ||||
mod markdown; | mod markdown; | ||||
mod section; | mod section; | ||||
/// Additional filters for Tera | |||||
mod filters; | |||||
pub use site::{Site, GUTENBERG_TERA}; | pub use site::{Site, GUTENBERG_TERA}; | ||||
pub use config::{Config, get_config}; | pub use config::{Config, get_config}; | ||||
@@ -13,6 +13,7 @@ use config::{Config, get_config}; | |||||
use page::{Page, populate_previous_and_next_pages}; | use page::{Page, populate_previous_and_next_pages}; | ||||
use utils::{create_file, create_directory}; | use utils::{create_file, create_directory}; | ||||
use section::{Section}; | use section::{Section}; | ||||
use filters; | |||||
lazy_static! { | lazy_static! { | ||||
@@ -78,6 +79,9 @@ impl Site { | |||||
let tpl_glob = format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*"); | let tpl_glob = format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*"); | ||||
let mut tera = Tera::new(&tpl_glob).chain_err(|| "Error parsing templates")?; | let mut tera = Tera::new(&tpl_glob).chain_err(|| "Error parsing templates")?; | ||||
tera.extend(&GUTENBERG_TERA)?; | 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 { | let site = Site { | ||||
base_path: path.to_path_buf(), | base_path: path.to_path_buf(), | ||||