diff --git a/Cargo.lock b/Cargo.lock index 1290c89f..66e4f3d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -584,6 +584,18 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "gray_matter" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cf2fb99fac0b821a4e61c61abff076324bb0e5c3b4a83815bbc3518a38971ad" +dependencies = [ + "serde", + "serde_json", + "toml", + "yaml-rust", +] + [[package]] name = "h2" version = "0.3.24" @@ -851,6 +863,12 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -924,6 +942,7 @@ dependencies = [ "elasticlunr-rs", "env_logger", "futures-util", + "gray_matter", "handlebars", "ignore", "log", @@ -941,6 +960,7 @@ dependencies = [ "semver", "serde", "serde_json", + "serde_yaml", "shlex", "tempfile", "tokio", @@ -1510,6 +1530,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.6" @@ -1870,6 +1903,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" + [[package]] name = "url" version = "2.5.0" @@ -2200,6 +2239,15 @@ dependencies = [ "markup5ever", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yansi" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 2beec26a..a7894ff8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,9 @@ shlex = "1.3.0" tempfile = "3.4.0" toml = "0.5.11" # Do not update, see https://github.com/rust-lang/mdBook/issues/2037 topological-sort = "0.2.2" +gray_matter = "0.2" #Fronmatter +serde_yaml = "0.9" + # Watch feature notify = { version = "6.1.1", optional = true } diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index b706108e..82c08211 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -19,6 +19,23 @@ use once_cell::sync::Lazy; use regex::{Captures, Regex}; use serde_json::json; +use gray_matter::Matter; +use gray_matter::engine::YAML; +use serde::Deserialize; + +fn extract_frontmatter(content: &str) -> Option<&str> { + let start = content.find("---")? + 3; // Find the end of the first `---` + 3 to move past it + let end = content[start..].find("---")? + start; // Find the start of the closing `---` + Some(&content[start..end].trim()) +} + +#[derive(Deserialize, Debug)] +struct FrontMatter { + title: String, + description: String, + featured_image_url: String, +} + #[derive(Default)] pub struct HtmlHandlebars; @@ -54,7 +71,34 @@ impl HtmlHandlebars { .insert("git_repository_edit_url".to_owned(), json!(edit_url)); } - let content = utils::render_markdown(&ch.content, ctx.html_config.curly_quotes); + // Parse frontmatter and prepare content + let matter = Matter::::new(); + let parsed = matter.parse(&ch.content); + let (content, new_content) = if let Some(data) = parsed.data { + + eprintln!("DEBUG11: Parsed frontmatter: {:?}", &data); + let yaml_str = extract_frontmatter(&ch.content).unwrap_or_default(); + let front_matter_result: Result = serde_yaml::from_str(yaml_str); + // let front_matter_result: Result = serde_yaml::from_str(&ch.content); + match front_matter_result { + Ok(front_matter) => { + ctx.data.insert("is_frontmatter".to_owned(), json!("true")); + ctx.data.insert("og_title".to_owned(), json!(front_matter.title)); + ctx.data.insert("og_description".to_owned(), json!(front_matter.description)); + ctx.data.insert("og_image_url".to_owned(), json!(front_matter.featured_image_url)); + }, + Err(e) => { + eprintln!("Deserialization error: {:?}", e); + }, + } + + // Prepare new content without frontmatter for rendering + let new_content = parsed.content.trim_start(); + (utils::render_markdown(&new_content, ctx.html_config.curly_quotes), Some(new_content)) + } else { + // No frontmatter, use original content + (utils::render_markdown(&ch.content, ctx.html_config.curly_quotes), None) + }; let fixed_content = utils::render_markdown_with_path(&ch.content, ctx.html_config.curly_quotes, Some(path)); @@ -135,6 +179,8 @@ impl HtmlHandlebars { utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?; } + + Ok(()) } diff --git a/src/theme/index.hbs b/src/theme/index.hbs index 080b7851..e0d23ff5 100644 --- a/src/theme/index.hbs +++ b/src/theme/index.hbs @@ -43,6 +43,29 @@ + + {{#if is_frontmatter}} + + + + + + + + {{else}} + + + + + + + + {{/if}} + + + + + {{#each additional_css}}