Skip to content

Normalize front matter #1509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 35 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,46 @@
[package]
name = "blog"
version = "0.1.0"
authors = ["The Rust Project Developers"]
edition = "2021"
[workspace]
members = ["front_matter", "serve"]

[dependencies]
[workspace.package]
edition = "2024"

[workspace.dependencies]
blog = { path = "." }
chrono = "=0.4.40"
color-eyre = "=0.6.3"
comrak = "=0.36.0"
eyre = "=0.6.12"
lazy_static = "=1.5.0"
serde = "=1.0.218"
serde_derive = "=1.0.218"
serde_json = "=1.0.140"
comrak = { version = "=0.36.0", features = ["bon"] }
front_matter = { path = "front_matter" }
insta = "=1.42.2"
rayon = "=1.10.0"
regex = "=1.11.1"
sass-rs = "=0.2.2"
chrono = "=0.4.40"
serde_json = "=1.0.140"
serde = "=1.0.218"
tera = "=1.20.0"
tokio = "=1.44.0"
toml = "=0.8.20"
warpy = "=0.3.68"

[workspace]
members = ["serve"]
[package]
name = "blog"
version = "0.1.0"
edition.workspace = true
authors = ["The Rust Project Developers"]

[dependencies]
chrono.workspace = true
color-eyre.workspace = true
comrak = { workspace = true, features = ["bon"] }
eyre.workspace = true
front_matter.workspace = true
rayon.workspace = true
regex.workspace = true
sass-rs.workspace = true
serde_json.workspace = true
serde = { workspace = true, features = ["derive"] }
tera.workspace = true
toml.workspace = true

[dev-dependencies]
insta = { version = "=1.42.2", features = ["filters", "glob"] }
insta = { workspace = true, features = ["filters", "glob"] }
9 changes: 9 additions & 0 deletions front_matter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "front_matter"
version = "0.1.0"
edition.workspace = true

[dependencies]
eyre.workspace = true
serde = { workspace = true, features = ["derive"] }
toml.workspace = true
105 changes: 105 additions & 0 deletions front_matter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use eyre::bail;
use serde::{Deserialize, Serialize};

/// The front matter of a markdown blog post.
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct FrontMatter {
pub layout: String,
pub title: String,
pub author: String,
pub description: Option<String>,
pub team: Option<String>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub release: bool,
}

/// Extracts the front matter from a markdown file.
///
/// The remaining normal markdown content is returned as the second element of
/// the tuple.
pub fn parse(markdown: &str) -> eyre::Result<(FrontMatter, &str)> {
if !markdown.starts_with("+++\n") {
bail!("markdown file must start with the line `+++`");
}
let (front_matter, content) = markdown
.trim_start_matches("+++\n")
.split_once("\n+++\n")
.expect("couldn't find the end of the front matter: `+++`");

Ok((toml::from_str(front_matter)?, content))
}

/// Normalizes the front matter of a markdown file.
pub fn normalize(markdown: &str) -> eyre::Result<String> {
let (front_matter, content) = parse(markdown)?;

Ok(format!(
"\
+++
{}\
+++
{content}",
toml::to_string_pretty(&front_matter)?
))
}

#[cfg(test)]
mod tests {
use std::{env, fs, path::PathBuf};

use super::*;

#[test]
fn front_matter_is_normalized() {
let repo_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..");

let posts = fs::read_dir(repo_root.join("posts"))
.unwrap()
.chain(fs::read_dir(repo_root.join("posts/inside-rust")).unwrap())
.map(|p| p.unwrap().path())
.filter(|p| p.extension() == Some("md".as_ref()));

for post in posts {
let content = fs::read_to_string(&post).unwrap();
let normalized = normalize(&content).unwrap();

if content != normalized {
if env::var("FIX_FRONT_MATTER").is_ok() {
fs::write(post, normalized).unwrap();
continue;
}

let post = post.file_name().unwrap().to_str().unwrap();
let actual = content
.rsplit_once("+++")
.map(|(f, _)| format!("{f}+++"))
.unwrap_or(content);
let expected = normalized
.rsplit_once("+++")
.map(|(f, _)| format!("{f}+++"))
.unwrap_or(normalized);

// better error message than assert_eq!()
panic!(
"
The post {post} has abnormal front matter.

actual:
{actual}

expected:
{expected}

┌──────────────────────────────────────────────────────────────────────────┐
│ │
│ You can fix this automatically by running: │
│ │
│ FIX_FRONT_MATTER=1 cargo test --all front_matter_is_normalized │
│ │
└──────────────────────────────────────────────────────────────────────────┘
",
)
};
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
layout = "post"
title = "New Year's Rust: A Call for Community Blogposts"
author = "The Rust Core Team"
layout = "post"
+++

'Tis the season for people and communities to reflect and set goals- and the Rust team is
Expand Down
2 changes: 1 addition & 1 deletion posts/2018-10-30-help-test-rust-2018.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
layout = "post"
title = "Help test Rust 2018"
author = "The Rust Core Team"
layout = "post"
+++

Back in July, we talked about ["Rust 2018"]. In short, we are launching a
Expand Down
1 change: 0 additions & 1 deletion posts/2019-06-03-governance-wg-announcement.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "The Governance WG is going public"
author = "The Rust Governance WG"
release = false
+++


Expand Down
1 change: 0 additions & 1 deletion posts/2020-08-18-laying-the-foundation-for-rusts-future.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "Laying the foundation for Rust's future"
author = "The Rust Core Team"
release = false
+++

The Rust project was originally [conceived in 2010][2010] (depending on how you count, you might even say [2006][2006]!) as a [Mozilla Research] project, but the long term goal has always been to establish Rust as a self-sustaining project. In 2015, [with the launch of Rust 1.0][onepointoh], Rust established its project direction and governance independent of the Mozilla organization. Since then, Rust has been operating as an autonomous organization, with Mozilla being a prominent and consistent financial and legal sponsor.
Expand Down
1 change: 0 additions & 1 deletion posts/2020-09-03-Planning-2021-Roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "Planning the 2021 Roadmap"
author = "The Rust Core Team"
release = false
+++

The core team is beginning to think about the 2021 Roadmap, and we want to hear from the community. We’re going to be running two parallel efforts over the next several weeks: the 2020 Rust Survey, to be announced next week, and a call for blog posts.
Expand Down
1 change: 0 additions & 1 deletion posts/2020-09-21-Scheduling-2021-Roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "Call for 2021 Roadmap Blogs Ending Soon"
author = "The Rust Core Team"
release = false
+++

We will be closing the collection of blog posts on **October 5th**. As a reminder, we plan to close the [survey](https://blog.rust-lang.org/2020/09/10/survey-launch.html) on **September 24th**, later this week.
Expand Down
2 changes: 1 addition & 1 deletion posts/2020-10-20-regression-labels.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
+++
layout = "post"
title = "Marking issues as regressions"
description = "Now anyone can mark issues as regressions!"
author = "Camelid"
description = "Now anyone can mark issues as regressions!"
team = "the release team <https://www.rust-lang.org/governance/teams/operations#release>"
+++

Expand Down
1 change: 0 additions & 1 deletion posts/2020-12-07-the-foundation-conversation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "The Foundation Conversation"
author = "The Rust Core Team"
release = false
+++

In August, we on the Core Team [announced our plans to create a Foundation](https://blog.rust-lang.org/2020/08/18/laying-the-foundation-for-rusts-future.html) by the end of the year. Since that time, we’ve been doing a lot of work but it has been difficult to share many details, and we know that a lot of you have questions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "Next steps for the Foundation Conversation"
author = "The Rust Core Team"
release = false
+++

Last week we kicked off the [Foundation Conversation](https://blog.rust-lang.org/2020/12/07/the-foundation-conversation.html), a week-long period of Q&A forums and live broadcasts with the goal of explaining our vision for the Foundation and finding out what sorts of questions people had. We used those questions to help build a [draft Foundation FAQ](https://github.com/rust-lang/foundation-faq-2020/blob/main/FAQ.md), and if you’ve not seen it yet, you should definitely take a look -- it’s chock full of good information. Thanks to everyone for asking such great questions!
Expand Down
1 change: 0 additions & 1 deletion posts/2020-12-16-rust-survey-2020.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "Rust Survey 2020 Results"
author = "The Rust Survey Team"
release = false
+++

Greetings Rustaceans!
Expand Down
1 change: 0 additions & 1 deletion posts/2022-02-14-crates-io-snapshot-branches.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "Crates.io Index Snapshot Branches Moving"
author = "The Crates.io Team"
release = false
+++

Every so often, the [crates.io index](https://github.com/rust-lang/crates.io-index)'s Git history
Expand Down
1 change: 0 additions & 1 deletion posts/2022-08-05-nll-by-default.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ layout = "post"
title = "Non-lexical lifetimes (NLL) fully stable"
author = "Niko Matsakis"
team = "the NLL working group <https://www.rust-lang.org/governance/teams/compiler#Non-Lexical%20Lifetimes%20(NLL)%20working%20group>"
release = false
+++

As of Rust 1.63 (releasing next week), the "non-lexical lifetimes" (NLL) work will be enabled by default. NLL is the second iteration of Rust's borrow checker. The [RFC] actually does quite a nice job of highlighting some of the motivating examples. "But," I hear you saying, "wasn't NLL included in [Rust 2018]?" And yes, yes it was! But at that time, NLL was only enabled for Rust 2018 code, while Rust 2015 code ran in "migration mode". When in "migration mode," the compiler would run both the old *and* the new borrow checker and compare the results. This way, we could give warnings for older code that should never have compiled in the first place; we could also limit the impact of any bugs in the new code. Over time, we have limited migration mode to be closer and closer to just running the new-style borrow checker: in the next release, that process completes, and all Rust code will be checked with NLL.
Expand Down
1 change: 0 additions & 1 deletion posts/2023-08-07-Rust-Survey-2023-Results.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "2022 Annual Rust Survey Results"
author = "The Rust Survey Working Group in partnership with the Rust Foundation"
release = false
+++

Hello, Rustaceans!
Expand Down
1 change: 0 additions & 1 deletion posts/2023-12-15-2024-Edition-CFP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
layout = "post"
title = "A Call for Proposals for the Rust 2024 Edition"
author = "Ben Striegel on behalf of the Edition 2024 Project Group"
release = false
+++

The year 2024 is soon to be upon us, and as long-time Rust aficionados know,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
+++
layout = "post"
title = "Clippy: Deprecating `feature = \"cargo-clippy\"`"
title = 'Clippy: Deprecating `feature = "cargo-clippy"`'
author = "The Clippy Team"
+++

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
+++
layout = "post"
title = "Improving async-await's \"Future is not Send\" diagnostic"
title = '''Improving async-await's "Future is not Send" diagnostic'''
author = "David Wood"
description = "Highlighting a diagnostic improvement for async-await"
team = "the Async Foundations WG <https://rust-lang.github.io/compiler-team/working-groups/async-await/>"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
layout = "post"
title = "Recent and future pattern matching improvements"
author = """Mazdak "Centril" Farrokhzad"""
author = 'Mazdak "Centril" Farrokhzad'
description = "Reviewing recent pattern matching improvements"
team = "the language team <https://www.rust-lang.org/governance/teams/lang>"
+++
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
+++
layout = "post"
title = "Keeping Rust projects secure with cargo-audit 0.18: performance, compatibility and security improvements"
author = """Sergey "Shnatsel" Davidoff"""
author = 'Sergey "Shnatsel" Davidoff'
description = "A look at the new features in cargo-audit 0.18 for ensuring dependencies are free of known vulnerabilities"
team = "the Secure Code WG <https://www.rust-lang.org/governance/wgs/wg-secure-code>"
+++
Expand Down
10 changes: 4 additions & 6 deletions serve/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
[package]
name = "serve"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
edition.workspace = true

[dependencies]
blog = { path = ".." }
warpy = "=0.3.68"
tokio = "=1.44.0"
blog.workspace = true
warpy.workspace = true
tokio.workspace = true
2 changes: 1 addition & 1 deletion src/blogs.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::posts::Post;
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};

static MANIFEST_FILE: &str = "blog.toml";
Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ mod posts;
use self::blogs::Blog;
use self::posts::Post;
use chrono::Timelike;
use eyre::{eyre, WrapErr};
use eyre::{WrapErr, eyre};
use rayon::prelude::*;
use sass_rs::{compile_file, Options};
use serde_derive::Serialize;
use serde_json::{json, Value};
use sass_rs::{Options, compile_file};
use serde::Serialize;
use serde_json::{Value, json};
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::{self, Write};
Expand Down
Loading