Skip to content

Commit

Permalink
Fix continue-reading parsing with inline HTML, add summary-cutoff tem…
Browse files Browse the repository at this point in the history
…plate
  • Loading branch information
clarfonthey committed Aug 15, 2024
1 parent ce10aae commit ef3ced0
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 23 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/content/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ markdown = { path = "../markdown" }
[dev-dependencies]
test-case = "3" # TODO: can we solve that usecase in src/page.rs in a simpler way? A custom macro_rules! maybe
tempfile = "3.3.0"
templates = { path = "../templates" }
10 changes: 5 additions & 5 deletions components/content/src/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ mod tests {
use std::path::{Path, PathBuf};

use libs::globset::{Glob, GlobSetBuilder};
use libs::tera::Tera;
use templates::ZOLA_TERA;
use tempfile::tempdir;

use crate::Page;
Expand All @@ -325,7 +325,7 @@ Hello world"#;
let mut page = res.unwrap();
page.render_markdown(
&HashMap::default(),
&Tera::default(),
&ZOLA_TERA,
&config,
InsertAnchor::None,
&HashMap::new(),
Expand Down Expand Up @@ -353,7 +353,7 @@ Hello world"#;
let mut page = res.unwrap();
page.render_markdown(
&HashMap::default(),
&Tera::default(),
&ZOLA_TERA,
&config,
InsertAnchor::None,
&HashMap::new(),
Expand Down Expand Up @@ -523,7 +523,7 @@ Hello world
let mut page = res.unwrap();
page.render_markdown(
&HashMap::default(),
&Tera::default(),
&ZOLA_TERA,
&config,
InsertAnchor::None,
&HashMap::new(),
Expand Down Expand Up @@ -557,7 +557,7 @@ And here's another. [^3]
let mut page = res.unwrap();
page.render_markdown(
&HashMap::default(),
&Tera::default(),
&ZOLA_TERA,
&config,
InsertAnchor::None,
&HashMap::new(),
Expand Down
48 changes: 44 additions & 4 deletions components/markdown/src/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::codeblock::{CodeBlock, FenceSettings};
use crate::shortcode::{Shortcode, SHORTCODE_PLACEHOLDER};

const CONTINUE_READING: &str = "<span id=\"continue-reading\"></span>";
const SUMMARY_CUTOFF_TEMPLATE: &str = "summary-cutoff.html";
const ANCHOR_LINK_TEMPLATE: &str = "anchor-link.html";
static EMOJI_REPLACER: Lazy<EmojiReplacer> = Lazy::new(EmojiReplacer::new);

Expand Down Expand Up @@ -684,7 +685,9 @@ pub fn markdown_to_html(
event
});
}
Event::Html(text) if !has_summary && MORE_DIVIDER_RE.is_match(text.as_ref()) => {
Event::Html(text) | Event::InlineHtml(text)
if !has_summary && MORE_DIVIDER_RE.is_match(text.as_ref()) =>
{
has_summary = true;
events.push(Event::Html(CONTINUE_READING.into()));
}
Expand Down Expand Up @@ -787,15 +790,50 @@ pub fn markdown_to_html(
.position(|e| matches!(e, Event::Html(CowStr::Borrowed(CONTINUE_READING))))
.unwrap_or(events.len());

// determine closing tags missing from summary
let mut tags = Vec::new();
for event in &events[..continue_reading] {
match event {
Event::Start(Tag::HtmlBlock) | Event::End(TagEnd::HtmlBlock) => (),
Event::Start(tag) => tags.push(tag.to_end()),
Event::End(tag) => {
tags.truncate(tags.iter().rposition(|t| *t == *tag).unwrap_or(0));
}
_ => (),
}
}

let mut events = events.into_iter();

// emit everything up to summary
cmark::html::push_html(&mut html, events.by_ref().take(continue_reading));

if has_summary {
// remove footnotes
let summary_html = FOOTNOTES_RE.replace_all(&html, "").into_owned();
summary = Some(summary_html)
let mut summary_html = FOOTNOTES_RE.replace_all(&html, "").into_owned();

// truncate trailing whitespace
summary_html.truncate(summary_html.trim_end().len());

// add cutoff template
if !tags.is_empty() {
let mut c = tera::Context::new();
c.insert("summary", &summary_html);
c.insert("lang", &context.lang);
let summary_cutoff = utils::templates::render_template(
SUMMARY_CUTOFF_TEMPLATE,
&context.tera,
c,
&None,
)
.context("Failed to render summary cutoff template")?;
summary_html.push_str(&summary_cutoff);
}

// close remaining tags
cmark::html::push_html(&mut summary_html, tags.into_iter().rev().map(Event::End));

summary = Some(summary_html);
}

// emit everything after summary
Expand All @@ -820,6 +858,7 @@ mod tests {
use super::*;
use config::Config;
use insta::assert_snapshot;
use templates::ZOLA_TERA;

#[test]
fn insert_many_works() {
Expand Down Expand Up @@ -875,7 +914,8 @@ mod tests {
let mores =
["<!-- more -->", "<!--more-->", "<!-- MORE -->", "<!--MORE-->", "<!--\t MoRe \t-->"];
let config = Config::default();
let context = RenderContext::from_config(&config);
let mut context = RenderContext::from_config(&config);
context.tera.to_mut().extend(&ZOLA_TERA).unwrap();
for more in mores {
let content = format!("{top}\n\n{more}\n\n{bottom}");
let rendered = markdown_to_html(&content, &context, vec![]).unwrap();
Expand Down
19 changes: 19 additions & 0 deletions components/markdown/tests/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ fn can_customise_anchor_template() {
insta::assert_snapshot!(body);
}

#[test]
fn can_customise_summary_template() {
let mut tera = Tera::default();
tera.extend(&ZOLA_TERA).unwrap();
tera.add_raw_template("summary-cutoff.html", " (in {{ lang }})").unwrap();
let permalinks_ctx = HashMap::new();
let config = Config::default_for_test();
let context = RenderContext::new(
&tera,
&config,
&config.default_language,
"",
&permalinks_ctx,
InsertAnchor::Right,
);
let summary = render_content("Hello <!-- more --> World!", &context).unwrap().summary.unwrap();
insta::assert_snapshot!(summary);
}

#[test]
fn can_use_smart_punctuation() {
let mut config = Config::default_for_test();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: components/markdown/tests/markdown.rs
expression: summary
---
<p>Hello (in en)</p>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: components/markdown/tests/summary.rs
expression: body
---
<p>Things to do:</p>
<ul>
<li>Program&hellip;
</li>
</ul>
7 changes: 3 additions & 4 deletions components/markdown/tests/summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,16 @@ And some content after
}

#[test]
fn no_truncated_summary() {
let rendered = get_rendered(
fn truncated_summary() {
let body = get_summary(
r#"
Things to do:
* Program <!-- more --> something
* Eat
* Sleep
"#,
);
assert!(rendered.summary.is_none());
insta::assert_snapshot!(rendered.body);
insta::assert_snapshot!(body);
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions components/templates/src/builtins/summary-cutoff.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% if summary is matching("\PP$") %}&hellip;{% endif %}
1 change: 1 addition & 0 deletions components/templates/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub static ZOLA_TERA: Lazy<Tera> = Lazy::new(|| {
include_str!("builtins/split_sitemap_index.xml"),
),
("__zola_builtins/anchor-link.html", include_str!("builtins/anchor-link.html")),
("__zola_builtins/summary-cutoff.html", include_str!("builtins/summary-cutoff.html")),
("internal/alias.html", include_str!("builtins/internal/alias.html")),
])
.unwrap();
Expand Down
4 changes: 4 additions & 0 deletions docs/content/documentation/content/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,7 @@ available separately in the

A span element in this position with a `continue-reading` id is created, so you can link directly to it if needed. For example:
`<a href="{{ page.permalink }}#continue-reading">Continue Reading</a>`.

The `<!-- more -->` marker can also exist in the middle of a line, and it will ensure that this does not emit unclosed HTML tags.
You can use the `summary-cutoff.html` to show an ellipsis or other text after the summary (but before these closing tags) based
upon the summary before the cutoff. By default, it will show an ellipsis (…) if the summary does not end in any punctuation.

0 comments on commit ef3ced0

Please sign in to comment.