@@ -4,12 +4,13 @@ use serde::{Deserialize, Serialize};
44/// The front matter of a markdown blog post.
55#[ derive( Debug , PartialEq , Serialize , Deserialize ) ]
66pub struct FrontMatter {
7+ pub layout : String ,
78 pub title : String ,
89 pub author : String ,
9- #[ serde( default ) ]
10- pub release : bool ,
10+ pub description : Option < String > ,
1111 pub team : Option < String > ,
12- pub layout : String ,
12+ #[ serde( default , skip_serializing_if = "std::ops::Not::not" ) ]
13+ pub release : bool ,
1314}
1415
1516/// Extracts the front matter from a markdown file.
@@ -27,3 +28,79 @@ pub fn parse(markdown: &str) -> eyre::Result<(FrontMatter, &str)> {
2728
2829 Ok ( ( toml:: from_str ( front_matter) ?, content) )
2930}
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+
54+ fn front_matter_is_normalized ( ) {
55+ let repo_root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( ".." ) ;
56+
57+ let posts = fs:: read_dir ( repo_root. join ( "posts" ) )
58+ . unwrap ( )
59+ . chain ( fs:: read_dir ( repo_root. join ( "posts/inside-rust" ) ) . unwrap ( ) )
60+ . map ( |p| p. unwrap ( ) . path ( ) )
61+ . filter ( |p| p. extension ( ) == Some ( "md" . as_ref ( ) ) ) ;
62+
63+ for post in posts {
64+ let content = fs:: read_to_string ( & post) . unwrap ( ) ;
65+ let normalized = normalize ( & content) . unwrap ( ) ;
66+
67+ if content != normalized {
68+ if env:: var ( "FIX_FRONT_MATTER" ) . is_ok ( ) {
69+ fs:: write ( post, normalized) . unwrap ( ) ;
70+ continue ;
71+ }
72+
73+ let post = post. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
74+ let actual = content
75+ . rsplit_once ( "+++" )
76+ . map ( |( f, _) | format ! ( "{f}+++" ) )
77+ . unwrap_or ( content) ;
78+ let expected = normalized
79+ . rsplit_once ( "+++" )
80+ . map ( |( f, _) | format ! ( "{f}+++" ) )
81+ . unwrap_or ( normalized) ;
82+
83+ // better error message than assert_eq!()
84+ panic ! (
85+ "
86+ The post {post} has abnormal front matter.
87+
88+ actual:
89+ {actual}
90+
91+ expected:
92+ {expected}
93+
94+ ┌──────────────────────────────────────────────────────────────────────────┐
95+ │ │
96+ │ You can fix this automatically by running: │
97+ │ │
98+ │ FIX_FRONT_MATTER=1 cargo test --all front_matter_is_normalized │
99+ │ │
100+ └──────────────────────────────────────────────────────────────────────────┘
101+ " ,
102+ )
103+ } ;
104+ }
105+ }
106+ }
0 commit comments