mirror of
https://github.com/getzola/zola
synced 2024-12-14 06:12:27 +00:00
parent
5b0e1edebf
commit
3155662db2
3 changed files with 99 additions and 74 deletions
|
@ -187,6 +187,56 @@ pub fn markdown_to_html(
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut events = Vec::new();
|
let mut events = Vec::new();
|
||||||
|
macro_rules! render_shortcodes {
|
||||||
|
($is_text:expr, $text:expr, $range:expr) => {
|
||||||
|
let orig_range_start = $range.start;
|
||||||
|
loop {
|
||||||
|
if let Some(ref shortcode) = next_shortcode {
|
||||||
|
if !$range.contains(&shortcode.span.start) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let sc_span = shortcode.span.clone();
|
||||||
|
|
||||||
|
// we have some text before the shortcode, push that first
|
||||||
|
if $range.start != sc_span.start {
|
||||||
|
let content = $text[($range.start - orig_range_start)
|
||||||
|
..(sc_span.start - orig_range_start)]
|
||||||
|
.to_string()
|
||||||
|
.into();
|
||||||
|
events.push(if $is_text {
|
||||||
|
Event::Text(content)
|
||||||
|
} else {
|
||||||
|
Event::Html(content)
|
||||||
|
});
|
||||||
|
$range.start = sc_span.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we should be at the same idx as the shortcode
|
||||||
|
let shortcode = next_shortcode.take().unwrap();
|
||||||
|
match shortcode.render(&context.tera, &context.tera_context) {
|
||||||
|
Ok(s) => {
|
||||||
|
events.push(Event::Html(s.into()));
|
||||||
|
$range.start += SHORTCODE_PLACEHOLDER.len();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error = Some(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next_shortcode = html_shortcodes.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !$range.is_empty() {
|
||||||
|
// The $range value is for the whole document, not for this slice of text
|
||||||
|
let content = $text[($range.start - orig_range_start)..].to_string().into();
|
||||||
|
events.push(if $is_text { Event::Text(content) } else { Event::Html(content) });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
for (event, mut range) in Parser::new_ext(content, opts).into_offset_iter() {
|
for (event, mut range) in Parser::new_ext(content, opts).into_offset_iter() {
|
||||||
match event {
|
match event {
|
||||||
|
@ -206,45 +256,7 @@ pub fn markdown_to_html(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find a way to share that code with the HTML handler
|
render_shortcodes!(true, text, range);
|
||||||
let mut new_text = text.clone();
|
|
||||||
loop {
|
|
||||||
if let Some(ref shortcode) = next_shortcode {
|
|
||||||
let sc_span = shortcode.span.clone();
|
|
||||||
if range.contains(&sc_span.start) {
|
|
||||||
if range.start != sc_span.start {
|
|
||||||
events.push(Event::Text(
|
|
||||||
new_text[..(sc_span.start - range.start)]
|
|
||||||
.to_string()
|
|
||||||
.into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let shortcode = next_shortcode.take().unwrap();
|
|
||||||
|
|
||||||
match shortcode.render(&context.tera, &context.tera_context) {
|
|
||||||
Ok(s) => {
|
|
||||||
events.push(Event::Html(s.into()));
|
|
||||||
new_text = new_text[(sc_span.end - range.start)..]
|
|
||||||
.to_owned()
|
|
||||||
.into();
|
|
||||||
range.start = sc_span.end - range.start;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error = Some(e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next_shortcode = html_shortcodes.pop();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
events.push(Event::Text(new_text[..].to_string().into()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Start(Tag::CodeBlock(ref kind)) => {
|
Event::Start(Tag::CodeBlock(ref kind)) => {
|
||||||
|
@ -338,40 +350,7 @@ pub fn markdown_to_html(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut new_text = text.clone();
|
render_shortcodes!(false, text, range);
|
||||||
loop {
|
|
||||||
if let Some(ref shortcode) = next_shortcode {
|
|
||||||
let sc_span = shortcode.span.clone();
|
|
||||||
if range.contains(&sc_span.start) {
|
|
||||||
if range.start != sc_span.start {
|
|
||||||
events.push(Event::Html(
|
|
||||||
new_text[..(sc_span.start - range.start)].to_owned().into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let shortcode = next_shortcode.take().unwrap();
|
|
||||||
match shortcode.render(&context.tera, &context.tera_context) {
|
|
||||||
Ok(s) => {
|
|
||||||
events.push(Event::Html(s.into()));
|
|
||||||
new_text = new_text[(sc_span.end - range.start)..]
|
|
||||||
.to_owned()
|
|
||||||
.into();
|
|
||||||
range.start = sc_span.end - range.start;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error = Some(e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next_shortcode = html_shortcodes.pop();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
events.push(Event::Html(new_text[..].to_string().into()));
|
|
||||||
}
|
}
|
||||||
_ => events.push(event),
|
_ => events.push(event),
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::collections::HashMap;
|
||||||
use tera::{to_value, Context, Map, Tera, Value};
|
use tera::{to_value, Context, Map, Tera, Value};
|
||||||
use utils::templates::ShortcodeFileType;
|
use utils::templates::ShortcodeFileType;
|
||||||
|
|
||||||
pub const SHORTCODE_PLACEHOLDER: &str = "||ZOLA_SC_PLACEHOLDER||";
|
pub const SHORTCODE_PLACEHOLDER: &str = "@@ZOLA_SC_PLACEHOLDER@@";
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub struct Shortcode {
|
pub struct Shortcode {
|
||||||
|
|
|
@ -1656,3 +1656,49 @@ ttest2
|
||||||
let res = render_content(markdown_string, &context).unwrap();
|
let res = render_content(markdown_string, &context).unwrap();
|
||||||
assert_eq!(res.body, "<p>ttest1</p>\n<p>123</p>\n<p>ttest2</p>\n<p>123</p>\n");
|
assert_eq!(res.body, "<p>ttest1</p>\n<p>123</p>\n<p>ttest2</p>\n<p>123</p>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/getzola/zola/issues/1689
|
||||||
|
#[test]
|
||||||
|
fn html_shortcode_regression() {
|
||||||
|
let permalinks_ctx = HashMap::new();
|
||||||
|
let mut tera = Tera::default();
|
||||||
|
tera.extend(&ZOLA_TERA).unwrap();
|
||||||
|
tera.add_raw_template("shortcodes/ex.html", "1").unwrap();
|
||||||
|
tera.add_raw_template("shortcodes/book.html", "2").unwrap();
|
||||||
|
tera.add_raw_template("shortcodes/std.html", "3").unwrap();
|
||||||
|
let config = Config::default_for_test();
|
||||||
|
let mut context = RenderContext::new(
|
||||||
|
&tera,
|
||||||
|
&config,
|
||||||
|
&config.default_language,
|
||||||
|
"",
|
||||||
|
&permalinks_ctx,
|
||||||
|
InsertAnchor::None,
|
||||||
|
);
|
||||||
|
let shortcode_def = utils::templates::get_shortcodes(&tera);
|
||||||
|
context.set_shortcode_definitions(&shortcode_def);
|
||||||
|
|
||||||
|
let markdown_string = r#"{{ book(page="") }} {{ ex(page="") }} {{ std(page="std") }}"#;
|
||||||
|
let res = render_content(markdown_string, &context).unwrap();
|
||||||
|
assert_eq!(res.body, "<p>2 1 3</p>\n");
|
||||||
|
|
||||||
|
// And in html
|
||||||
|
let markdown_string = r#"<p>{{ book(page="") }} {{ ex(page="") }} {{ std(page="std") }}</p>"#;
|
||||||
|
let res = render_content(markdown_string, &context).unwrap();
|
||||||
|
assert_eq!(res.body, "<p>2 1 3</p>");
|
||||||
|
|
||||||
|
// Another one with newlines
|
||||||
|
let markdown_string = "<p>\n{{ book(page='') }}\n</p>";
|
||||||
|
let res = render_content(markdown_string, &context).unwrap();
|
||||||
|
assert_eq!(res.body, "<p>\n2\n</p>");
|
||||||
|
|
||||||
|
// And another one
|
||||||
|
let markdown_string = "<span>{{ book(page='') }}</span>\n**The Book** {{ book(page='') }}";
|
||||||
|
let res = render_content(markdown_string, &context).unwrap();
|
||||||
|
assert_eq!(res.body, "<p><span>2</span>\n<strong>The Book</strong> 2</p>\n");
|
||||||
|
|
||||||
|
// with some text in between
|
||||||
|
let markdown_string = r#"a.{{ book(page="") }} b.{{ ex(page="") }} c.{{ std(page="std") }}"#;
|
||||||
|
let res = render_content(markdown_string, &context).unwrap();
|
||||||
|
assert_eq!(res.body, "<p>a.2 b.1 c.3</p>\n");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue