brochurise/src/frontmatter.rs

49 lines
1.6 KiB
Rust

use anyhow::Result;
use serde::{Serialize, Deserialize};
use regex::Regex;
#[derive(Debug, Serialize, Deserialize)]
pub struct Metadata {
title: Option<String>,
date: Option<toml::value::Datetime>,
}
/// Return the extracted content (without the frontmatter)
/// and an array of key/value pairs to set as pandoc metadata
/// We don't rely on inline metadata block (YAML frontmatter)
/// because pandoc does not support it with CommonMark
pub fn extract(content: &str) -> Result<(String, Vec<(String, String)>)> {
let toml_regex = Regex::new(r"^[[:space:]]*\+\+\+\r?\n((?s).*?(?-s))\+\+\+\r?\n?((?s).*(?-s))$").unwrap();
if !toml_regex.is_match(content) {
return Ok((content.to_string(), Vec::new()));
}
let caps = toml_regex.captures(content).unwrap();
// caps[0] is the full match
// caps[1] => front matter
// caps[2] => content
let content = caps[2].to_string();
// Naively, i wanted to turn the TOML to YAML directly
// However, TOML dates produce weird YAML so let's go manual
/*let mut values: toml::Value = toml::from_str(&caps[1])?;
let table = values.as_table_mut().unwrap();
let date = */
//println!("{:?}", &caps[1]);
//let metadata: Metadata = toml::from_str(&caps[1])?;
//println!("ok");
let frontmatter: toml::Value = toml::from_str(&caps[1])?;
let table = frontmatter.as_table().unwrap();
let mut metadata: Vec<(String, String)> = Vec::new();
for (key, value) in table.iter() {
metadata.push((key.to_string(), value.to_string()));
}
Ok((content, metadata))
}