lyt 0.1.1

A static site generator written in Rust
Documentation
use crate::markdown::html::push_html;
use pulldown_cmark::{Options, Parser};
use pulldown_cmark_frontmatter::FrontmatterExtractor;
use serde::{Deserialize, Serialize};
use toml::value::Datetime;

mod html;

#[derive(Serialize, Deserialize)]
pub struct PageAttributes {
    pub title: String,
    pub author: String,
    pub timestamp: Datetime,
}

/// This function takes a markdown string and returns a tuple of the page attributes
/// and the html output.
///
/// # Arguments
/// * `input` - A markdown string.
/// * `theme` - A string representing the theme to use. See https://docs.rs/syntect/latest/syntect/highlighting/struct.ThemeSet.html#method.load_defaults
/// for a list of available themes.
///
/// # Examples
/// ```
/// use lyt::markdown::parse_markdown;
/// let markdown_input = "\
/// ```toml
/// title = \"This is a fancy **title**\"\n\
/// author = \"pjw\"
/// timestamp = 2023-11-17T00:00:00+00:20
/// ```\n\n\
/// ### Sub-title
/// \n\
/// Hello world, this is a ~~complicated~~ *very simple* example.\n\n\
/// ```rust\n\
/// use std::whatever;\n\
/// \n\
/// fn main() {\n\
/// \tprintln!(\"Hello, world!\");\n\
/// }\n\
/// ```\n\n\
/// This is a [link](https://example.com).\n\n\
/// `this is code`\
/// ";
///
/// let expected_html = "\
/// <h2>Sub-title</h2>\n\
/// <p>Hello world, this is a <del>complicated</del> <em>very simple</em> example.</p>\n\
/// <pre><code class=\"language-rust\"><span style=\"color:#859900;\">use </span><span style=\"color:#839496;\">std::whatever;\n\
/// </span><span style=\"color:#839496;\">\n\
/// </span><span style=\"color:#268bd2;\">fn </span><span style=\"color:#b58900;\">main</span><span style=\"color:#657b83;\">() {\n\
/// </span><span style=\"color:#839496;\">\t</span><span style=\"color:#859900;\">println!</span><span style=\"color:#657b83;\">(</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#2aa198;\">Hello, world!</span><span style=\"color:#839496;\">&quot;</span><span style=\"color:#657b83;\">)</span><span style=\"color:#839496;\">;\n\
/// </span><span style=\"color:#657b83;\">}\n</span></code></pre>\n\
/// <p>This is a <a href=\"https://example.com\">link</a>.</p>\n\
/// <p><code>this is code</code></p>
/// ";
/// let (attrs, html_output) = parse_markdown(markdown_input, "Solarized (dark)".to_string());
/// assert_eq!(attrs.title, "This is a fancy **title**");
/// assert_eq!(attrs.author, "pjw");
/// assert_eq!(attrs.timestamp.to_string(), "2023-11-17T00:00:00+00:20");
/// assert_eq!(html_output, expected_html);
pub fn parse_markdown(input: &str, theme: String) -> (PageAttributes, String) {
    let options = prepare_options();
    let parser = Parser::new_ext(input, options);
    let mut extractor = FrontmatterExtractor::new(parser);

    // Write to String buffer.
    let mut html_output = String::new();
    push_html(&mut html_output, &mut extractor, theme);

    let frontmatter = extractor.frontmatter.expect("frontmatter not detected");
    let code_block = frontmatter.code_block.expect("code block not detected");
    let attrs: PageAttributes = toml::from_str(&code_block.source).expect("invalid toml");

    (attrs, html_output)
}

fn prepare_options() -> Options {
    let mut options = Options::empty();
    options.insert(Options::ENABLE_STRIKETHROUGH);
    options.insert(Options::ENABLE_FOOTNOTES);
    options.insert(Options::ENABLE_TABLES);
    options.insert(Options::ENABLE_SMART_PUNCTUATION);
    options.insert(Options::ENABLE_TASKLISTS);
    options
}