mirror of
https://github.com/getzola/zola
synced 2024-12-13 13:52:28 +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();
|
||||
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() {
|
||||
match event {
|
||||
|
@ -206,45 +256,7 @@ pub fn markdown_to_html(
|
|||
continue;
|
||||
}
|
||||
|
||||
// TODO: find a way to share that code with the HTML handler
|
||||
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()));
|
||||
render_shortcodes!(true, text, range);
|
||||
}
|
||||
}
|
||||
Event::Start(Tag::CodeBlock(ref kind)) => {
|
||||
|
@ -338,40 +350,7 @@ pub fn markdown_to_html(
|
|||
continue;
|
||||
}
|
||||
|
||||
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::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()));
|
||||
render_shortcodes!(false, text, range);
|
||||
}
|
||||
_ => events.push(event),
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::collections::HashMap;
|
|||
use tera::{to_value, Context, Map, Tera, Value};
|
||||
use utils::templates::ShortcodeFileType;
|
||||
|
||||
pub const SHORTCODE_PLACEHOLDER: &str = "||ZOLA_SC_PLACEHOLDER||";
|
||||
pub const SHORTCODE_PLACEHOLDER: &str = "@@ZOLA_SC_PLACEHOLDER@@";
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Shortcode {
|
||||
|
|
|
@ -1656,3 +1656,49 @@ ttest2
|
|||
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");
|
||||
}
|
||||
|
||||
// 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