From c069bfdafadf38cb39fd3b5d81298460b8052d3a Mon Sep 17 00:00:00 2001 From: Thomas Hurst Date: Wed, 22 Aug 2018 17:34:32 +0100 Subject: [PATCH] Rework summary handling. Push summary handling into Markdown parsing, identifying the presence of one by giving its length in the rendered markup. Hopefully a better fix for #376. --- components/content/src/page.rs | 19 +++++----------- components/content/src/section.rs | 4 ++-- components/rendering/src/lib.rs | 2 +- components/rendering/src/markdown.rs | 33 ++++++++++++++++++++-------- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/components/content/src/page.rs b/components/content/src/page.rs index 3a0bf066..4162d6d3 100644 --- a/components/content/src/page.rs +++ b/components/content/src/page.rs @@ -185,19 +185,12 @@ impl Page { context.tera_context.add("page", self); - let res = render_content( - &self.raw_content.replacen("", "", 1), - &context, - ).chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?; - self.content = res.0; - self.toc = res.1; - if self.raw_content.contains("") { - self.summary = Some({ - let summary = self.raw_content.splitn(2, "").collect::>()[0]; - render_content(summary, &context) - .chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?.0 - }) - } + let res = render_content(&self.raw_content, &context) + .chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?; + + self.summary = res.summary_len.map(|l| res.body[0..l].to_owned()); + self.content = res.body; + self.toc = res.toc; Ok(()) } diff --git a/components/content/src/section.rs b/components/content/src/section.rs index dcff1f5c..07ddde2b 100644 --- a/components/content/src/section.rs +++ b/components/content/src/section.rs @@ -137,8 +137,8 @@ impl Section { let res = render_content(&self.raw_content, &context) .chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?; - self.content = res.0; - self.toc = res.1; + self.content = res.body; + self.toc = res.toc; Ok(()) } diff --git a/components/rendering/src/lib.rs b/components/rendering/src/lib.rs index 9e6d7257..acc08953 100644 --- a/components/rendering/src/lib.rs +++ b/components/rendering/src/lib.rs @@ -32,7 +32,7 @@ pub use table_of_contents::Header; pub use shortcode::render_shortcodes; pub use context::RenderContext; -pub fn render_content(content: &str, context: &RenderContext) -> Result<(String, Vec
)> { +pub fn render_content(content: &str, context: &RenderContext) -> Result { // Don't do anything if there is nothing like a shortcode in the content if content.contains("{{") || content.contains("{%") { let rendered = render_shortcodes(content, context)?; diff --git a/components/rendering/src/markdown.rs b/components/rendering/src/markdown.rs index 56bea619..a9c3b3e6 100644 --- a/components/rendering/src/markdown.rs +++ b/components/rendering/src/markdown.rs @@ -1,4 +1,4 @@ -use std::borrow::Cow::Owned; +use std::borrow::Cow::{Owned, Borrowed}; use pulldown_cmark as cmark; use self::cmark::{Parser, Event, Tag, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; @@ -14,6 +14,14 @@ use link_checker::check_url; use table_of_contents::{TempHeader, Header, make_table_of_contents}; use context::RenderContext; +const CONTINUE_READING: &str = "

\n"; + +pub struct Rendered { + pub body: String, + pub summary_len: Option, + pub toc: Vec
+} + // We might have cases where the slug is already present in our list of anchor // for example an article could have several titles named Example // We add a counter after the slug if the slug is already present, which @@ -36,8 +44,7 @@ fn is_colocated_asset_link(link: &str) -> bool { && !link.starts_with("mailto:") } - -pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<(String, Vec
)> { +pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result { // the rendered html let mut html = String::with_capacity(content.len()); // Set while parsing @@ -57,6 +64,7 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<(Strin let mut temp_header = TempHeader::default(); let mut opts = Options::empty(); + let mut has_summary = false; opts.insert(OPTION_ENABLE_TABLES); opts.insert(OPTION_ENABLE_FOOTNOTES); @@ -208,6 +216,10 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<(Strin temp_header = TempHeader::default(); Event::Html(Owned(val)) } + Event::Html(ref markup) if markup.contains("") => { + has_summary = true; + Event::Html(Borrowed(CONTINUE_READING)) + } _ => event, } }); @@ -215,11 +227,14 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<(Strin cmark::html::push_html(&mut html, parser); } - match error { - Some(e) => Err(e), - None => Ok(( - html.replace("

", "").replace("

", "

"), - make_table_of_contents(&headers) - )), + if let Some(e) = error { + return Err(e) + } else { + html = html.replace("

", "").replace("

", "

"); + Ok(Rendered { + summary_len: if has_summary { html.find(CONTINUE_READING) } else { None }, + body: html, + toc: make_table_of_contents(&headers) + }) } }