@@ -4,12 +4,13 @@ use serde::{Deserialize, Serialize};
4
4
/// The front matter of a markdown blog post.
5
5
#[ derive( Debug , PartialEq , Serialize , Deserialize ) ]
6
6
pub struct FrontMatter {
7
+ pub layout : String ,
7
8
pub title : String ,
8
9
pub author : String ,
9
- #[ serde( default ) ]
10
- pub release : bool ,
10
+ pub description : Option < String > ,
11
11
pub team : Option < String > ,
12
- pub layout : String ,
12
+ #[ serde( default , skip_serializing_if = "std::ops::Not::not" ) ]
13
+ pub release : bool ,
13
14
}
14
15
15
16
/// Extracts the front matter from a markdown file.
@@ -27,3 +28,79 @@ pub fn parse(markdown: &str) -> eyre::Result<(FrontMatter, &str)> {
27
28
28
29
Ok ( ( toml:: from_str ( front_matter) ?, content) )
29
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
+
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