Internal links are supported in markdown filter (#1318)

* Internal links are resolved in tera markdown filter (close #1296 #1316)

* Add a test for internal links in markdown filter

Co-authored-by: southerntofu <southerntofu@thunix.net>
This commit is contained in:
southerntofu 2021-01-20 08:24:55 +00:00 committed by GitHub
parent 14366dafc6
commit 6950759eda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 12 deletions

View file

@ -1,5 +1,11 @@
# Changelog # Changelog
## unreleased
### Features
- internal links are now resolved in the `markdown` filter in the templates (#1296 #1316)
## 0.13.0 (2021-01-09) ## 0.13.0 (2021-01-09)
- Enable HTML minification - Enable HTML minification

View file

@ -50,7 +50,7 @@ pub fn load_tera(path: &Path, config: &Config) -> Result<Tera> {
/// Adds global fns that are to be available to shortcodes while rendering markdown /// Adds global fns that are to be available to shortcodes while rendering markdown
pub fn register_early_global_fns(site: &mut Site) { pub fn register_early_global_fns(site: &mut Site) {
site.tera.register_filter("markdown", filters::MarkdownFilter::new(site.config.clone())); site.tera.register_filter("markdown", filters::MarkdownFilter::new(site.config.clone(), site.permalinks.clone()));
site.tera.register_function( site.tera.register_function(
"get_url", "get_url",

View file

@ -1,5 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::BuildHasher; use std::hash::BuildHasher;
use std::borrow::Cow;
use base64::{decode, encode}; use base64::{decode, encode};
use config::Config; use config::Config;
@ -9,17 +10,19 @@ use tera::{to_value, try_get_value, Filter as TeraFilter, Result as TeraResult,
#[derive(Debug)] #[derive(Debug)]
pub struct MarkdownFilter { pub struct MarkdownFilter {
config: Config, config: Config,
permalinks: HashMap<String, String>,
} }
impl MarkdownFilter { impl MarkdownFilter {
pub fn new(config: Config) -> Self { pub fn new(config: Config, permalinks: HashMap<String, String>) -> Self {
Self { config } Self { config, permalinks }
} }
} }
impl TeraFilter for MarkdownFilter { impl TeraFilter for MarkdownFilter {
fn filter(&self, value: &Value, args: &HashMap<String, Value>) -> TeraResult<Value> { fn filter(&self, value: &Value, args: &HashMap<String, Value>) -> TeraResult<Value> {
let context = RenderContext::from_config(&self.config); let mut context = RenderContext::from_config(&self.config);
context.permalinks = Cow::Borrowed(&self.permalinks);
let s = try_get_value!("markdown", "value", String, value); let s = try_get_value!("markdown", "value", String, value);
let inline = match args.get("inline") { let inline = match args.get("inline") {
Some(val) => try_get_value!("markdown", "inline", bool, val), Some(val) => try_get_value!("markdown", "inline", bool, val),
@ -69,7 +72,7 @@ mod tests {
#[test] #[test]
fn markdown_filter() { fn markdown_filter() {
let result = MarkdownFilter::new(Config::default()) let result = MarkdownFilter::new(Config::default(), HashMap::new())
.filter(&to_value(&"# Hey").unwrap(), &HashMap::new()); .filter(&to_value(&"# Hey").unwrap(), &HashMap::new());
assert!(result.is_ok()); assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value(&"<h1 id=\"hey\">Hey</h1>\n").unwrap()); assert_eq!(result.unwrap(), to_value(&"<h1 id=\"hey\">Hey</h1>\n").unwrap());
@ -79,7 +82,7 @@ mod tests {
fn markdown_filter_inline() { fn markdown_filter_inline() {
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("inline".to_string(), to_value(true).unwrap()); args.insert("inline".to_string(), to_value(true).unwrap());
let result = MarkdownFilter::new(Config::default()).filter( let result = MarkdownFilter::new(Config::default(), HashMap::new()).filter(
&to_value(&"Using `map`, `filter`, and `fold` instead of `for`").unwrap(), &to_value(&"Using `map`, `filter`, and `fold` instead of `for`").unwrap(),
&args, &args,
); );
@ -92,7 +95,7 @@ mod tests {
fn markdown_filter_inline_tables() { fn markdown_filter_inline_tables() {
let mut args = HashMap::new(); let mut args = HashMap::new();
args.insert("inline".to_string(), to_value(true).unwrap()); args.insert("inline".to_string(), to_value(true).unwrap());
let result = MarkdownFilter::new(Config::default()).filter( let result = MarkdownFilter::new(Config::default(), HashMap::new()).filter(
&to_value( &to_value(
&r#" &r#"
|id|author_id| timestamp_created|title |content | |id|author_id| timestamp_created|title |content |
@ -118,16 +121,26 @@ mod tests {
let md = "Hello <https://google.com> :smile: ..."; let md = "Hello <https://google.com> :smile: ...";
let result = let result =
MarkdownFilter::new(config.clone()).filter(&to_value(&md).unwrap(), &HashMap::new()); MarkdownFilter::new(config.clone(), HashMap::new()).filter(&to_value(&md).unwrap(), &HashMap::new());
assert!(result.is_ok()); assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value(&"<p>Hello <a rel=\"noopener\" target=\"_blank\" href=\"https://google.com\">https://google.com</a> 😄 …</p>\n").unwrap()); assert_eq!(result.unwrap(), to_value(&"<p>Hello <a rel=\"noopener\" target=\"_blank\" href=\"https://google.com\">https://google.com</a> 😄 …</p>\n").unwrap());
let md = "```py\ni=0\n```"; let md = "```py\ni=0\n```";
let result = MarkdownFilter::new(config).filter(&to_value(&md).unwrap(), &HashMap::new()); let result = MarkdownFilter::new(config, HashMap::new()).filter(&to_value(&md).unwrap(), &HashMap::new());
assert!(result.is_ok()); assert!(result.is_ok());
assert!(result.unwrap().as_str().unwrap().contains("<pre style")); assert!(result.unwrap().as_str().unwrap().contains("<pre style"));
} }
#[test]
fn mardown_filter_can_use_internal_links() {
let mut permalinks = HashMap::new();
permalinks.insert("blog/_index.md".to_string(), "/foo/blog".to_string());
let md = "Hello. Check out [my blog](@/blog/_index.md)!";
let result = MarkdownFilter::new(Config::default(), permalinks).filter(&to_value(&md).unwrap(), &HashMap::new());
assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value(&"<p>Hello. Check out <a href=\"/foo/blog\">my blog</a>!</p>\n").unwrap());
}
#[test] #[test]
fn base64_encode_filter() { fn base64_encode_filter() {
// from https://tools.ietf.org/html/rfc4648#section-10 // from https://tools.ietf.org/html/rfc4648#section-10

View file

@ -64,9 +64,7 @@ Zola adds a few filters in addition to [those](https://tera.netlify.com/docs/#fi
in Tera. in Tera.
### markdown ### markdown
Converts the given variable to HTML using Markdown. This doesn't apply any of the Converts the given variable to HTML using Markdown. Shortcodes won't work within this filter.
features that Zola adds to Markdown; for example, internal links and shortcodes won't work.
By default, the filter will wrap all text in a paragraph. To disable this behaviour, you can By default, the filter will wrap all text in a paragraph. To disable this behaviour, you can
pass `true` to the inline argument: pass `true` to the inline argument: