fix code blocks not rendering in resources

This commit is contained in:
zyl 2025-01-15 01:20:12 -08:00
parent e44b219335
commit c27ac9c6d9
Signed by: zyl
SSH key fingerprint: SHA256:uxxbSXbdroP/OnKBGnEDk5q7EKB2razvstC/KmzdXXs
3 changed files with 55 additions and 50 deletions

View file

@ -4,7 +4,6 @@ use std::{collections::HashMap, path::PathBuf};
use eyre::{eyre, Context, OptionExt}; use eyre::{eyre, Context, OptionExt};
use lol_html::{element, html_content::ContentType, HtmlRewriter, Settings}; use lol_html::{element, html_content::ContentType, HtmlRewriter, Settings};
use pulldown_cmark::{Options, Parser};
use rayon::prelude::*; use rayon::prelude::*;
use serde::Serialize; use serde::Serialize;
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet}; use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
@ -399,49 +398,7 @@ impl SiteBuilder {
.with_context(|| format!("Failed to read page at {}", page_path.display()))?; .with_context(|| format!("Failed to read page at {}", page_path.display()))?;
let page = crate::frontmatter::FrontMatter::parse(input)?; let page = crate::frontmatter::FrontMatter::parse(input)?;
let mut language = None; let page_html = util::render_markdown(self, &page.content)?;
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#"<div class="wd-codeblock">
<button class="copy">Copy</button>
{}
</div>"#,
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 out = self.build_page_raw(page.data.unwrap_or_default(), &page_html, ())?; let out = self.build_page_raw(page.data.unwrap_or_default(), &page_html, ())?;

View file

@ -5,14 +5,13 @@ use std::{
use eyre::Context; use eyre::Context;
use itertools::Itertools; use itertools::Itertools;
use pulldown_cmark::{Options, Parser};
use rss::{validation::Validate, ChannelBuilder, ItemBuilder}; use rss::{validation::Validate, ChannelBuilder, ItemBuilder};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use time::{format_description::well_known::Rfc2822, OffsetDateTime}; use time::{format_description::well_known::Rfc2822, OffsetDateTime};
use crate::{ use crate::{
builder::SiteBuilder, frontmatter::FrontMatterRequired, link_list::Link, builder::SiteBuilder, frontmatter::FrontMatterRequired, link_list::Link,
util::format_timestamp, PageMetadata, util::{self, format_timestamp}, PageMetadata,
}; };
/// Metadata for resources. /// Metadata for resources.
@ -182,10 +181,7 @@ impl ResourceBuilder {
let mut page = FrontMatterRequired::<ResourceMetadata>::parse(input) let mut page = FrontMatterRequired::<ResourceMetadata>::parse(input)
.wrap_err_with(|| eyre::eyre!("Failed to parse resource front matter"))?; .wrap_err_with(|| eyre::eyre!("Failed to parse resource front matter"))?;
let parser = Parser::new_ext(&page.content, Options::all()); *page.content_mut() = util::render_markdown(builder, &page.content)?;
let mut html = String::new();
pulldown_cmark::html::push_html(&mut html, parser);
*page.content_mut() = html;
let data = page.data_mut(); let data = page.data_mut();
if let Some(cdn_file) = &data.cdn_file { if let Some(cdn_file) = &data.cdn_file {

View file

@ -2,8 +2,11 @@
use std::path::Path; use std::path::Path;
use pulldown_cmark::{Options, Parser};
use time::OffsetDateTime; use time::OffsetDateTime;
use crate::builder::SiteBuilder;
/// Simple helper to remove the contents of a directory without removing the directory itself. /// Simple helper to remove the contents of a directory without removing the directory itself.
pub fn remove_dir_contents(path: &Path) -> eyre::Result<()> { pub fn remove_dir_contents(path: &Path) -> eyre::Result<()> {
for entry in path.read_dir()? { for entry in path.read_dir()? {
@ -24,3 +27,52 @@ pub fn format_timestamp(ts: OffsetDateTime, format: &str) -> eyre::Result<String
let fmt = time::format_description::parse_borrowed::<2>(format)?; let fmt = time::format_description::parse_borrowed::<2>(format)?;
Ok(ts.format(&fmt)?) Ok(ts.format(&fmt)?)
} }
/// Helper to render markdown.
pub fn render_markdown(builder: &SiteBuilder, input: &str) -> eyre::Result<String> {
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#"<div class="wd-codeblock">
<button class="copy">Copy</button>
{}
</div>"#,
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)
}