diff --git a/src/builder.rs b/src/builder.rs
index 5e5ebd4..d5da847 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -4,7 +4,6 @@ use std::{collections::HashMap, path::PathBuf};
use eyre::{eyre, Context, OptionExt};
use lol_html::{element, html_content::ContentType, HtmlRewriter, Settings};
-use pulldown_cmark::{Options, Parser};
use rayon::prelude::*;
use serde::Serialize;
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
@@ -399,49 +398,7 @@ impl SiteBuilder {
.with_context(|| format!("Failed to read page at {}", page_path.display()))?;
let page = crate::frontmatter::FrontMatter::parse(input)?;
- let mut language = None;
- let parser = Parser::new_ext(&page.content, Options::all()).filter_map(|event| {
- // syntax highlighting for code blocks
- match event {
- pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(
- pulldown_cmark::CodeBlockKind::Fenced(name),
- )) => {
- language = Some(name);
- None
- }
- pulldown_cmark::Event::Text(code) => {
- if let Some(language) = language.take() {
- let syntax_reference = self
- .syntax_set
- .find_syntax_by_token(&language)
- .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
- let html = format!(
- r#"
-
- {}
-
"#,
- syntect::html::highlighted_html_for_string(
- &code,
- &self.syntax_set,
- syntax_reference,
- self.theme_set
- .themes
- .get(&self.site.config.code_theme)
- .as_ref()
- .expect("should never fail"),
- )
- .expect("failed to highlight syntax")
- );
- Some(pulldown_cmark::Event::Html(html.into()))
- } else {
- Some(pulldown_cmark::Event::Text(code))
- }
- }
- _ => Some(event),
- }
- });
- let mut page_html = String::new();
- pulldown_cmark::html::push_html(&mut page_html, parser);
+ let page_html = util::render_markdown(self, &page.content)?;
let out = self.build_page_raw(page.data.unwrap_or_default(), &page_html, ())?;
diff --git a/src/resource.rs b/src/resource.rs
index d4d5bf1..433584c 100644
--- a/src/resource.rs
+++ b/src/resource.rs
@@ -5,14 +5,13 @@ use std::{
use eyre::Context;
use itertools::Itertools;
-use pulldown_cmark::{Options, Parser};
use rss::{validation::Validate, ChannelBuilder, ItemBuilder};
use serde::{Deserialize, Serialize};
use time::{format_description::well_known::Rfc2822, OffsetDateTime};
use crate::{
builder::SiteBuilder, frontmatter::FrontMatterRequired, link_list::Link,
- util::format_timestamp, PageMetadata,
+ util::{self, format_timestamp}, PageMetadata,
};
/// Metadata for resources.
@@ -182,10 +181,7 @@ impl ResourceBuilder {
let mut page = FrontMatterRequired::::parse(input)
.wrap_err_with(|| eyre::eyre!("Failed to parse resource front matter"))?;
- let parser = Parser::new_ext(&page.content, Options::all());
- let mut html = String::new();
- pulldown_cmark::html::push_html(&mut html, parser);
- *page.content_mut() = html;
+ *page.content_mut() = util::render_markdown(builder, &page.content)?;
let data = page.data_mut();
if let Some(cdn_file) = &data.cdn_file {
diff --git a/src/util.rs b/src/util.rs
index d8ebf18..0f42680 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -2,8 +2,11 @@
use std::path::Path;
+use pulldown_cmark::{Options, Parser};
use time::OffsetDateTime;
+use crate::builder::SiteBuilder;
+
/// Simple helper to remove the contents of a directory without removing the directory itself.
pub fn remove_dir_contents(path: &Path) -> eyre::Result<()> {
for entry in path.read_dir()? {
@@ -24,3 +27,52 @@ pub fn format_timestamp(ts: OffsetDateTime, format: &str) -> eyre::Result(format)?;
Ok(ts.format(&fmt)?)
}
+
+/// Helper to render markdown.
+pub fn render_markdown(builder: &SiteBuilder, input: &str) -> eyre::Result {
+ let mut language = None;
+ let parser = Parser::new_ext(input, Options::all()).filter_map(|event| {
+ // syntax highlighting for code blocks
+ match event {
+ pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(
+ pulldown_cmark::CodeBlockKind::Fenced(name),
+ )) => {
+ language = Some(name);
+ None
+ }
+ pulldown_cmark::Event::Text(code) => {
+ if let Some(language) = language.take() {
+ let syntax_reference = builder
+ .syntax_set
+ .find_syntax_by_token(&language)
+ .unwrap_or_else(|| builder.syntax_set.find_syntax_plain_text());
+ let html = format!(
+ r#"
+
+ {}
+
"#,
+ syntect::html::highlighted_html_for_string(
+ &code,
+ &builder.syntax_set,
+ syntax_reference,
+ builder.theme_set
+ .themes
+ .get(&builder.site.config.code_theme)
+ .as_ref()
+ .expect("should never fail"),
+ )
+ .expect("failed to highlight syntax")
+ );
+ Some(pulldown_cmark::Event::Html(html.into()))
+ } else {
+ Some(pulldown_cmark::Event::Text(code))
+ }
+ }
+ _ => Some(event),
+ }
+ });
+ let mut page_html = String::new();
+ pulldown_cmark::html::push_html(&mut page_html, parser);
+
+ Ok(page_html)
+}