summaryrefslogtreecommitdiff
path: root/src/page.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/page.rs')
-rw-r--r--src/page.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/page.rs b/src/page.rs
new file mode 100644
index 0000000..c81887d
--- /dev/null
+++ b/src/page.rs
@@ -0,0 +1,87 @@
+use serde::Deserialize;
+use chrono::NaiveDate;
+use std::path::PathBuf;
+use std::fs;
+
+#[derive(Deserialize, Debug)]
+pub struct Frontmatter {
+ pub title: String,
+ pub date: NaiveDate,
+ #[serde(default)]
+ pub draft: bool,
+}
+
+#[derive(Debug)]
+pub struct Page {
+ pub meta: Frontmatter,
+ pub source_path: PathBuf,
+ pub output_path: PathBuf,
+ pub body: String,
+ pub html: String,
+}
+
+pub fn parse_frontmatter(content: &str) -> Option<Frontmatter> {
+ if !content.starts_with("+++\n") {
+ return None;
+ }
+ let rest = &content[4..];
+ let end = rest.find("\n+++\n")?;
+
+ let toml_str = &rest[..end];
+ let meta: Frontmatter = toml::from_str(toml_str)
+ .expect("frontmatter failed parsed");
+ Some(meta)
+}
+
+pub fn parse_page(source_path: &PathBuf) -> anyhow::Result<Page> {
+ let content = fs::read_to_string(source_path)?;
+ let maybe_meta = parse_frontmatter(&content);
+ let meta: Frontmatter;
+ let body: String;
+
+ if let Some(fm) = maybe_meta {
+ let end_post = content.find("\n+++\n").unwrap();
+ println!("end_post: {}", end_post);
+ meta = fm;
+ body = content[(end_post + 5)..].to_string();
+ } else {
+ let fallback_title = source_path
+ .file_stem()
+ .and_then(|s| s.to_str())
+ .unwrap_or("untitled")
+ .to_string();
+
+ meta = Frontmatter {
+ title: fallback_title,
+ date: chrono::Utc::now().date_naive(),
+ draft: true,
+ };
+ body = content;
+ }
+
+ let html = render_markdown(&body);
+
+ let slug = meta.title.to_lowercase().replace(' ', "-");
+ let output_path = PathBuf::from("public").join(&slug).join("index.html");
+
+ Ok (Page {
+ meta,
+ source_path: source_path.clone(),
+ output_path,
+ body,
+ html,
+ })
+}
+
+pub fn render_markdown(input: &str) -> String {
+ use pulldown_cmark::{Parser, Options, html};
+
+ let mut options = Options::empty();
+ options.insert(Options::ENABLE_STRIKETHROUGH);
+ options.insert(Options::ENABLE_TABLES);
+
+ let parser = Parser::new_ext(input, options);
+ let mut out = String::new();
+ html::push_html(&mut out, parser);
+ out
+}