webdog/src/util.rs

78 lines
2.1 KiB
Rust

//! Module containing various utilities.
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()? {
let entry = entry?;
let path = entry.path();
if path.is_file() {
std::fs::remove_file(&path)?;
} else {
std::fs::remove_dir_all(&path)?;
}
}
Ok(())
}
/// Helper to format a timestamp according to the given format.
pub fn format_timestamp(ts: OffsetDateTime, format: &str) -> eyre::Result<String> {
let fmt = time::format_description::parse_borrowed::<2>(format)?;
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)
}