11import 'package:minibuild/minibuild.dart' ;
22
3+ import '../markdown.dart' ;
34import '../model/post.dart' ;
45
56/// Converts a Markdown file in the post directory to a [Post] object.
@@ -17,67 +18,74 @@ class PostBuilder extends Builder<StringAsset> {
1718 Future <void > build (
1819 BuildContext context, Key key, StringAsset markdownFile) async {
1920 var match = _titlePattern.firstMatch (key.toString ());
20- // TODO: Better error handling.
21- if (match == null ) throw Exception ('Bad post title $key ' );
21+ if (match == null ) {
22+ context
23+ .error ('Post filename should look like "1234-56-78-post-title.md".' );
24+ return ;
25+ }
2226
2327 var year = int .parse (match[1 ]! );
2428 var month = int .parse (match[2 ]! );
2529 var day = int .parse (match[3 ]! );
2630 var titleUri = match[4 ]! ;
2731
28- var contents = await markdownFile.readString ();
29- var lines = contents.split ('\n ' );
30- if (lines.isEmpty) {
31- // TODO: Better error handling.
32- throw Exception ('Empty post' );
33- }
32+ var lines = (await markdownFile.readString ()).split ('\n ' );
3433
35- if (lines[0 ].trim () != '---' ) {
36- // TODO: Better error handling.
37- throw Exception ('Missing frontmatter' );
38- }
39-
40- var title = '' ;
34+ String ? title;
4135 var tags = < String > [];
4236 var contentLines = < String > [];
4337
44- for (var i = 1 ; i < lines.length; i++ ) {
45- var line = lines[i].trim ();
46- if (line == '---' ) {
47- // TODO: Slow.
48- contentLines.addAll (lines.skip (i + 1 ));
49- break ;
50- } else {
51- var match = _metadataPattern.firstMatch (line);
52- if (match != null ) {
53- var key = match[1 ]! ;
54- var value = match[2 ]! ;
55- switch (key) {
56- case 'title' :
57- title = value;
58- // TODO: Hack. Unquote if quoted.
59- if (title.startsWith ('"' )) {
60- title = title.substring (1 , title.length - 1 );
61- title = title.replaceAll ('\\ "' , '"' );
62- }
38+ // Read the frontmatter.
39+ if (lines.isNotEmpty && lines[0 ].trim () == '---' ) {
40+ for (var i = 1 ; i < lines.length; i++ ) {
41+ var line = lines[i].trim ();
42+ if (line == '---' ) {
43+ // TODO: Slow.
44+ contentLines.addAll (lines.skip (i + 1 ));
45+ break ;
46+ } else {
47+ if (_metadataPattern.firstMatch (line) case var match? ) {
48+ var key = match[1 ]! ;
49+ var value = match[2 ]! ;
50+ switch (key) {
51+ case 'title' :
52+ title = value;
53+ // TODO: Hack. Unquote if quoted.
54+ if (title.startsWith ('"' )) {
55+ title = title.substring (1 , title.length - 1 );
56+ title = title.replaceAll ('\\ "' , '"' );
57+ }
6358
64- case 'tags' :
65- tags = value.split (' ' ).toList ();
66- tags.sort ();
59+ case 'tags' :
60+ tags = value.split (' ' ).toList ();
61+ tags.sort ();
6762
68- default :
69- // TODO: Better error handling.
70- throw Exception ('Unknown metadata: $key ' );
63+ default :
64+ context.error ('Unknown frontmatter metadata key "$key " '
65+ 'on line ${i + 1 }:\n $line ' );
66+ }
67+ } else {
68+ context.error ('Unparseable frontmatter on line ${i + 1 }:\n $line ' );
7169 }
72- } else {
73- // TODO: Better error handling.
74- throw Exception ('Bad metadata: $line ' );
7570 }
7671 }
72+ } else {
73+ context.error ('Missing frontmatter.' );
7774 }
7875
76+ if (title == null ) {
77+ context.error ('Missing post title in frontmatter.' );
78+
79+ // Use a temporary title so the rest of the build can continue.
80+ title = key.basenameWithoutExtension;
81+ }
82+
83+ var html = renderMarkdown (context, contentLines);
84+
7985 var postKey = Key .join ('post' , key.basenameWithoutExtension);
80- context.output (postKey,
81- Post (DateTime (year, month, day), title, titleUri, tags, contentLines));
86+ context.output (
87+ postKey,
88+ Post (DateTime (year, month, day), title, titleUri, tags, contentLines,
89+ html));
8290 }
8391}
0 commit comments