Skip to content

Commit dcc98c6

Browse files
authored
Merge pull request #1509 from rust-lang/senekor/normalize-front-matter
Normalize front matter
2 parents c4ae3d4 + 7934c13 commit dcc98c6

26 files changed

+195
-80
lines changed

Cargo.lock

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,46 @@
1-
[package]
2-
name = "blog"
3-
version = "0.1.0"
4-
authors = ["The Rust Project Developers"]
5-
edition = "2021"
1+
[workspace]
2+
members = ["front_matter", "serve"]
63

7-
[dependencies]
4+
[workspace.package]
5+
edition = "2024"
6+
7+
[workspace.dependencies]
8+
blog = { path = "." }
9+
chrono = "=0.4.40"
810
color-eyre = "=0.6.3"
11+
comrak = "=0.36.0"
912
eyre = "=0.6.12"
10-
lazy_static = "=1.5.0"
11-
serde = "=1.0.218"
12-
serde_derive = "=1.0.218"
13-
serde_json = "=1.0.140"
14-
comrak = { version = "=0.36.0", features = ["bon"] }
13+
front_matter = { path = "front_matter" }
14+
insta = "=1.42.2"
1515
rayon = "=1.10.0"
1616
regex = "=1.11.1"
1717
sass-rs = "=0.2.2"
18-
chrono = "=0.4.40"
18+
serde_json = "=1.0.140"
19+
serde = "=1.0.218"
1920
tera = "=1.20.0"
21+
tokio = "=1.44.0"
2022
toml = "=0.8.20"
23+
warpy = "=0.3.68"
2124

22-
[workspace]
23-
members = ["serve"]
25+
[package]
26+
name = "blog"
27+
version = "0.1.0"
28+
edition.workspace = true
29+
authors = ["The Rust Project Developers"]
30+
31+
[dependencies]
32+
chrono.workspace = true
33+
color-eyre.workspace = true
34+
comrak = { workspace = true, features = ["bon"] }
35+
eyre.workspace = true
36+
front_matter.workspace = true
37+
rayon.workspace = true
38+
regex.workspace = true
39+
sass-rs.workspace = true
40+
serde_json.workspace = true
41+
serde = { workspace = true, features = ["derive"] }
42+
tera.workspace = true
43+
toml.workspace = true
2444

2545
[dev-dependencies]
26-
insta = { version = "=1.42.2", features = ["filters", "glob"] }
46+
insta = { workspace = true, features = ["filters", "glob"] }

front_matter/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "front_matter"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
6+
[dependencies]
7+
eyre.workspace = true
8+
serde = { workspace = true, features = ["derive"] }
9+
toml.workspace = true

front_matter/src/lib.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use eyre::bail;
2+
use serde::{Deserialize, Serialize};
3+
4+
/// The front matter of a markdown blog post.
5+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
6+
pub struct FrontMatter {
7+
pub layout: String,
8+
pub title: String,
9+
pub author: String,
10+
pub description: Option<String>,
11+
pub team: Option<String>,
12+
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
13+
pub release: bool,
14+
}
15+
16+
/// Extracts the front matter from a markdown file.
17+
///
18+
/// The remaining normal markdown content is returned as the second element of
19+
/// the tuple.
20+
pub fn parse(markdown: &str) -> eyre::Result<(FrontMatter, &str)> {
21+
if !markdown.starts_with("+++\n") {
22+
bail!("markdown file must start with the line `+++`");
23+
}
24+
let (front_matter, content) = markdown
25+
.trim_start_matches("+++\n")
26+
.split_once("\n+++\n")
27+
.expect("couldn't find the end of the front matter: `+++`");
28+
29+
Ok((toml::from_str(front_matter)?, content))
30+
}
31+
32+
/// Normalizes the front matter of a markdown file.
33+
pub fn normalize(markdown: &str) -> eyre::Result<String> {
34+
let (front_matter, content) = parse(markdown)?;
35+
36+
Ok(format!(
37+
"\
38+
+++
39+
{}\
40+
+++
41+
{content}",
42+
toml::to_string_pretty(&front_matter)?
43+
))
44+
}
45+
46+
#[cfg(test)]
47+
mod tests {
48+
use std::{env, fs, path::PathBuf};
49+
50+
use super::*;
51+
52+
#[test]
53+
fn front_matter_is_normalized() {
54+
let repo_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..");
55+
56+
let posts = fs::read_dir(repo_root.join("posts"))
57+
.unwrap()
58+
.chain(fs::read_dir(repo_root.join("posts/inside-rust")).unwrap())
59+
.map(|p| p.unwrap().path())
60+
.filter(|p| p.extension() == Some("md".as_ref()));
61+
62+
for post in posts {
63+
let content = fs::read_to_string(&post).unwrap();
64+
let normalized = normalize(&content).unwrap();
65+
66+
if content != normalized {
67+
if env::var("FIX_FRONT_MATTER").is_ok() {
68+
fs::write(post, normalized).unwrap();
69+
continue;
70+
}
71+
72+
let post = post.file_name().unwrap().to_str().unwrap();
73+
let actual = content
74+
.rsplit_once("+++")
75+
.map(|(f, _)| format!("{f}+++"))
76+
.unwrap_or(content);
77+
let expected = normalized
78+
.rsplit_once("+++")
79+
.map(|(f, _)| format!("{f}+++"))
80+
.unwrap_or(normalized);
81+
82+
// better error message than assert_eq!()
83+
panic!(
84+
"
85+
The post {post} has abnormal front matter.
86+
87+
actual:
88+
{actual}
89+
90+
expected:
91+
{expected}
92+
93+
┌──────────────────────────────────────────────────────────────────────────┐
94+
│ │
95+
│ You can fix this automatically by running: │
96+
│ │
97+
│ FIX_FRONT_MATTER=1 cargo test --all front_matter_is_normalized │
98+
│ │
99+
└──────────────────────────────────────────────────────────────────────────┘
100+
",
101+
)
102+
};
103+
}
104+
}
105+
}

posts/2018-01-03-new-years-rust-a-call-for-community-blogposts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
+++
2+
layout = "post"
23
title = "New Year's Rust: A Call for Community Blogposts"
34
author = "The Rust Core Team"
4-
layout = "post"
55
+++
66

77
'Tis the season for people and communities to reflect and set goals- and the Rust team is

posts/2018-10-30-help-test-rust-2018.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
+++
2+
layout = "post"
23
title = "Help test Rust 2018"
34
author = "The Rust Core Team"
4-
layout = "post"
55
+++
66

77
Back in July, we talked about ["Rust 2018"]. In short, we are launching a

posts/2019-06-03-governance-wg-announcement.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "The Governance WG is going public"
44
author = "The Rust Governance WG"
5-
release = false
65
+++
76

87

posts/2020-08-18-laying-the-foundation-for-rusts-future.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "Laying the foundation for Rust's future"
44
author = "The Rust Core Team"
5-
release = false
65
+++
76

87
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.

posts/2020-09-03-Planning-2021-Roadmap.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "Planning the 2021 Roadmap"
44
author = "The Rust Core Team"
5-
release = false
65
+++
76

87
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.

posts/2020-09-21-Scheduling-2021-Roadmap.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "Call for 2021 Roadmap Blogs Ending Soon"
44
author = "The Rust Core Team"
5-
release = false
65
+++
76

87
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.

0 commit comments

Comments
 (0)