adding frontmatter parser

This commit is contained in:
sspaeti 2024-02-20 17:53:59 +01:00
parent 5a4ac03c0d
commit 643a1c89ad
4 changed files with 121 additions and 1 deletions

48
Cargo.lock generated
View File

@ -584,6 +584,18 @@ dependencies = [
"regex-syntax", "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]] [[package]]
name = "h2" name = "h2"
version = "0.3.24" version = "0.3.24"
@ -851,6 +863,12 @@ version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.13" version = "0.4.13"
@ -924,6 +942,7 @@ dependencies = [
"elasticlunr-rs", "elasticlunr-rs",
"env_logger", "env_logger",
"futures-util", "futures-util",
"gray_matter",
"handlebars", "handlebars",
"ignore", "ignore",
"log", "log",
@ -941,6 +960,7 @@ dependencies = [
"semver", "semver",
"serde", "serde",
"serde_json", "serde_json",
"serde_yaml",
"shlex", "shlex",
"tempfile", "tempfile",
"tokio", "tokio",
@ -1510,6 +1530,19 @@ dependencies = [
"serde", "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]] [[package]]
name = "sha1" name = "sha1"
version = "0.10.6" version = "0.10.6"
@ -1870,6 +1903,12 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "unsafe-libyaml"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"
@ -2200,6 +2239,15 @@ dependencies = [
"markup5ever", "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]] [[package]]
name = "yansi" name = "yansi"
version = "0.5.1" version = "0.5.1"

View File

@ -35,6 +35,9 @@ shlex = "1.3.0"
tempfile = "3.4.0" tempfile = "3.4.0"
toml = "0.5.11" # Do not update, see https://github.com/rust-lang/mdBook/issues/2037 toml = "0.5.11" # Do not update, see https://github.com/rust-lang/mdBook/issues/2037
topological-sort = "0.2.2" topological-sort = "0.2.2"
gray_matter = "0.2" #Fronmatter
serde_yaml = "0.9"
# Watch feature # Watch feature
notify = { version = "6.1.1", optional = true } notify = { version = "6.1.1", optional = true }

View File

@ -19,6 +19,23 @@ use once_cell::sync::Lazy;
use regex::{Captures, Regex}; use regex::{Captures, Regex};
use serde_json::json; 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)] #[derive(Default)]
pub struct HtmlHandlebars; pub struct HtmlHandlebars;
@ -54,7 +71,34 @@ impl HtmlHandlebars {
.insert("git_repository_edit_url".to_owned(), json!(edit_url)); .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::<YAML>::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<FrontMatter, serde_yaml::Error> = serde_yaml::from_str(yaml_str);
// let front_matter_result: Result<FrontMatter, serde_yaml::Error> = 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 = let fixed_content =
utils::render_markdown_with_path(&ch.content, ctx.html_config.curly_quotes, Some(path)); 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())?; utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?;
} }
Ok(()) Ok(())
} }

View File

@ -43,6 +43,29 @@
<link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css"> <link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css">
<link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css"> <link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css">
<!-- Open Graph Meta Tags for Social Media Exposure -->
{{#if is_frontmatter}}
<meta property="og:title" content="{{ og_title }}">
<meta property="og:description" content="{{ og_description }}">
<meta property="og:image" content="{{this.frontmatter.featured_image_url}}">
<meta property="og:url" content="{{ og_image_url}}">
<meta name="twitter:title" content="{{ og_title }}"/>
<meta name="twitter:description" content="{{ og_description }}"/>
<meta name="twitter:image" content="{{ og_image_url }}"/>
{{else}}
<meta property="og:title" content="mdBook Documentation">
<meta property="og:description" content="Create book from markdown files. Like Gitbook but implemented in Rust">
<meta property="og:image" content="https://rust-lang.github.io/mdBook/favicon.png">
<meta property="og:url" content="https://rust-lang.github.io/mdBook/">
<meta name="twitter:title" content="mdBook Documentation"/>
<meta name="twitter:image" content="https://rust-lang.github.io/mdBook/favicon.png"/>
<meta name="twitter:description" content="Create book from markdown files. Like Gitbook but implemented in Rust"/>
{{/if}}
<meta name="author" content="dBook">
<meta property="og:type" content="book">
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:creator" content="@rustlang"/>
<!-- Custom theme stylesheets --> <!-- Custom theme stylesheets -->
{{#each additional_css}} {{#each additional_css}}
<link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}"> <link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}">