1use std::path::Path;
4
5use pulldown_cmark::{Options, Parser};
6use time::OffsetDateTime;
7
8use crate::builder::SiteBuilder;
9
10pub fn remove_dir_contents(path: &Path) -> eyre::Result<()> {
12 for entry in path.read_dir()? {
13 let entry = entry?;
14 let path = entry.path();
15 if path.is_file() {
16 std::fs::remove_file(&path)?;
17 } else {
18 std::fs::remove_dir_all(&path)?;
19 }
20 }
21
22 Ok(())
23}
24
25pub fn format_timestamp(ts: OffsetDateTime, format: &str) -> eyre::Result<String> {
27 let fmt = time::format_description::parse_borrowed::<2>(format)?;
28 Ok(ts.format(&fmt)?)
29}
30
31pub fn render_markdown(builder: &SiteBuilder, input: &str) -> eyre::Result<String> {
33 let mut language = None;
34 let parser = Parser::new_ext(input, Options::all()).filter_map(|event| {
35 match event {
37 pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(
38 pulldown_cmark::CodeBlockKind::Fenced(name),
39 )) => {
40 language = Some(name);
41 None
42 }
43 pulldown_cmark::Event::Text(code) => {
44 if let Some(language) = language.take() {
45 let syntax_reference = builder
46 .syntax_set
47 .find_syntax_by_token(&language)
48 .unwrap_or_else(|| builder.syntax_set.find_syntax_plain_text());
49 let html = format!(
50 r#"<div class="wd-codeblock">
51 <button class="copy">Copy</button>
52 {}
53 </div>"#,
54 syntect::html::highlighted_html_for_string(
55 &code,
56 &builder.syntax_set,
57 syntax_reference,
58 builder
59 .theme_set
60 .themes
61 .get(&builder.site.config.code_theme)
62 .as_ref()
63 .expect("should never fail"),
64 )
65 .expect("failed to highlight syntax")
66 );
67 Some(pulldown_cmark::Event::Html(html.into()))
68 } else {
69 Some(pulldown_cmark::Event::Text(code))
70 }
71 }
72 _ => Some(event),
73 }
74 });
75 let mut page_html = String::new();
76 pulldown_cmark::html::push_html(&mut page_html, parser);
77
78 Ok(page_html)
79}