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

+10-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+35-15
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

+9
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

+105
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

+1-1
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

+1-1
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

-1
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

-1
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

-1
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

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

posts/2020-10-20-regression-labels.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
+++
22
layout = "post"
33
title = "Marking issues as regressions"
4-
description = "Now anyone can mark issues as regressions!"
54
author = "Camelid"
5+
description = "Now anyone can mark issues as regressions!"
66
team = "the release team <https://www.rust-lang.org/governance/teams/operations#release>"
77
+++
88

posts/2020-12-07-the-foundation-conversation.md

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "The Foundation Conversation"
44
author = "The Rust Core Team"
5-
release = false
65
+++
76

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

posts/2020-12-14-Next-steps-for-the-foundation-conversation.md

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "Next steps for the Foundation Conversation"
44
author = "The Rust Core Team"
5-
release = false
65
+++
76

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

posts/2020-12-16-rust-survey-2020.md

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "Rust Survey 2020 Results"
44
author = "The Rust Survey Team"
5-
release = false
65
+++
76

87
Greetings Rustaceans!

posts/2022-02-14-crates-io-snapshot-branches.md

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "Crates.io Index Snapshot Branches Moving"
44
author = "The Crates.io Team"
5-
release = false
65
+++
76

87
Every so often, the [crates.io index](https://github.com/rust-lang/crates.io-index)'s Git history

posts/2022-08-05-nll-by-default.md

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ layout = "post"
33
title = "Non-lexical lifetimes (NLL) fully stable"
44
author = "Niko Matsakis"
55
team = "the NLL working group <https://www.rust-lang.org/governance/teams/compiler#Non-Lexical%20Lifetimes%20(NLL)%20working%20group>"
6-
release = false
76
+++
87

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

posts/2023-08-07-Rust-Survey-2023-Results.md

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "2022 Annual Rust Survey Results"
44
author = "The Rust Survey Working Group in partnership with the Rust Foundation"
5-
release = false
65
+++
76

87
Hello, Rustaceans!

posts/2023-12-15-2024-Edition-CFP.md

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
layout = "post"
33
title = "A Call for Proposals for the Rust 2024 Edition"
44
author = "Ben Striegel on behalf of the Edition 2024 Project Group"
5-
release = false
65
+++
76

87
The year 2024 is soon to be upon us, and as long-time Rust aficionados know,

posts/2024-02-28-Clippy-deprecating-feature-cargo-clippy.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
+++
22
layout = "post"
3-
title = "Clippy: Deprecating `feature = \"cargo-clippy\"`"
3+
title = 'Clippy: Deprecating `feature = "cargo-clippy"`'
44
author = "The Clippy Team"
55
+++
66

posts/inside-rust/2019-10-11-AsyncAwait-Not-Send-Error-Improvements.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
+++
22
layout = "post"
3-
title = "Improving async-await's \"Future is not Send\" diagnostic"
3+
title = '''Improving async-await's "Future is not Send" diagnostic'''
44
author = "David Wood"
55
description = "Highlighting a diagnostic improvement for async-await"
66
team = "the Async Foundations WG <https://rust-lang.github.io/compiler-team/working-groups/async-await/>"

posts/inside-rust/2020-03-04-recent-future-pattern-matching-improvements.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
+++
22
layout = "post"
33
title = "Recent and future pattern matching improvements"
4-
author = """Mazdak "Centril" Farrokhzad"""
4+
author = 'Mazdak "Centril" Farrokhzad'
55
description = "Reviewing recent pattern matching improvements"
66
team = "the language team <https://www.rust-lang.org/governance/teams/lang>"
77
+++

posts/inside-rust/2023-09-04-keeping-secure-with-cargo-audit-0.18.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
+++
22
layout = "post"
33
title = "Keeping Rust projects secure with cargo-audit 0.18: performance, compatibility and security improvements"
4-
author = """Sergey "Shnatsel" Davidoff"""
4+
author = 'Sergey "Shnatsel" Davidoff'
55
description = "A look at the new features in cargo-audit 0.18 for ensuring dependencies are free of known vulnerabilities"
66
team = "the Secure Code WG <https://www.rust-lang.org/governance/wgs/wg-secure-code>"
77
+++

serve/Cargo.toml

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
[package]
22
name = "serve"
33
version = "0.1.0"
4-
edition = "2021"
5-
6-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
4+
edition.workspace = true
75

86
[dependencies]
9-
blog = { path = ".." }
10-
warpy = "=0.3.68"
11-
tokio = "=1.44.0"
7+
blog.workspace = true
8+
warpy.workspace = true
9+
tokio.workspace = true

src/blogs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::posts::Post;
2-
use serde_derive::{Deserialize, Serialize};
2+
use serde::{Deserialize, Serialize};
33
use std::path::{Path, PathBuf};
44

55
static MANIFEST_FILE: &str = "blog.toml";

src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ mod posts;
44
use self::blogs::Blog;
55
use self::posts::Post;
66
use chrono::Timelike;
7-
use eyre::{eyre, WrapErr};
7+
use eyre::{WrapErr, eyre};
88
use rayon::prelude::*;
9-
use sass_rs::{compile_file, Options};
10-
use serde_derive::Serialize;
11-
use serde_json::{json, Value};
9+
use sass_rs::{Options, compile_file};
10+
use serde::Serialize;
11+
use serde_json::{Value, json};
1212
use std::collections::HashMap;
1313
use std::fs::{self, File};
1414
use std::io::{self, Write};

0 commit comments

Comments
 (0)