Browse Source

Give posts a date, separate posts and pages

master
Dylan Baker 5 years ago
parent
commit
adbb0c248d
8 changed files with 135 additions and 17 deletions
  1. 38
    0
      Cargo.lock
  2. 1
    0
      Cargo.toml
  3. 6
    5
      src/commands.rs
  4. 2
    0
      src/main.rs
  5. 38
    0
      src/page.rs
  6. 15
    5
      src/post.rs
  7. 22
    1
      src/render.rs
  8. 13
    6
      src/write.rs

+ 38
- 0
Cargo.lock View File

@@ -52,6 +52,7 @@ dependencies = [
52 52
 name = "casaubon"
53 53
 version = "0.1.1"
54 54
 dependencies = [
55
+ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
55 56
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
56 57
  "comrak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
57 58
  "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -67,6 +68,16 @@ name = "cfg-if"
67 68
 version = "0.1.6"
68 69
 source = "registry+https://github.com/rust-lang/crates.io-index"
69 70
 
71
+[[package]]
72
+name = "chrono"
73
+version = "0.4.6"
74
+source = "registry+https://github.com/rust-lang/crates.io-index"
75
+dependencies = [
76
+ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
77
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
78
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
79
+]
80
+
70 81
 [[package]]
71 82
 name = "clap"
72 83
 version = "2.32.0"
@@ -320,6 +331,19 @@ dependencies = [
320 331
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
321 332
 ]
322 333
 
334
+[[package]]
335
+name = "num-integer"
336
+version = "0.1.39"
337
+source = "registry+https://github.com/rust-lang/crates.io-index"
338
+dependencies = [
339
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
340
+]
341
+
342
+[[package]]
343
+name = "num-traits"
344
+version = "0.2.6"
345
+source = "registry+https://github.com/rust-lang/crates.io-index"
346
+
323 347
 [[package]]
324 348
 name = "num_cpus"
325 349
 version = "1.8.0"
@@ -541,6 +565,16 @@ dependencies = [
541 565
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
542 566
 ]
543 567
 
568
+[[package]]
569
+name = "time"
570
+version = "0.1.42"
571
+source = "registry+https://github.com/rust-lang/crates.io-index"
572
+dependencies = [
573
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
574
+ "redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
575
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
576
+]
577
+
544 578
 [[package]]
545 579
 name = "tokio-executor"
546 580
 version = "0.1.5"
@@ -718,6 +752,7 @@ dependencies = [
718 752
 "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
719 753
 "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
720 754
 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
755
+"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
721 756
 "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
722 757
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
723 758
 "checksum comrak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a9bd60be8877a3343d25b9a3dadbaf7f02f9ac843b54e663ecef73e29e8b9c6b"
@@ -745,6 +780,8 @@ dependencies = [
745 780
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
746 781
 "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
747 782
 "checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078"
783
+"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
784
+"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
748 785
 "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
749 786
 "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
750 787
 "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
@@ -774,6 +811,7 @@ dependencies = [
774 811
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
775 812
 "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
776 813
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
814
+"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
777 815
 "checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde"
778 816
 "checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21"
779 817
 "checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5"

+ 1
- 0
Cargo.toml View File

@@ -8,6 +8,7 @@ readme = "README.md"
8 8
 repository = "https://git.sr.ht/~simulacrumparty/casaubon"
9 9
 
10 10
 [dependencies]
11
+chrono = "0.4"
11 12
 clap = "2.32.0"
12 13
 comrak = "0.3"
13 14
 fs_extra = "1.1.0"

+ 6
- 5
src/commands.rs View File

@@ -7,6 +7,7 @@ use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
7 7
 use toml::Value;
8 8
 
9 9
 use config::Config;
10
+use page::{parse_page, read_pages_dir};
10 11
 use post::{parse_post, read_posts_dir};
11 12
 use write::{write_page, write_post, write_post_listing};
12 13
 
@@ -55,7 +56,7 @@ pub fn build(include_drafts: bool) {
55 56
         false => read_posts_dir(&cwd.join("posts")),
56 57
     };
57 58
 
58
-    let page_paths = read_posts_dir(&cwd.join("pages"));
59
+    let page_paths = read_pages_dir(&cwd.join("pages"));
59 60
 
60 61
     let posts = post_paths
61 62
         .into_iter()
@@ -67,7 +68,7 @@ pub fn build(include_drafts: bool) {
67 68
         .collect();
68 69
 
69 70
     for entry in page_paths.into_iter() {
70
-        let page = parse_post(entry.path());
71
+        let page = parse_page(entry.path());
71 72
         write_page(&cwd, &layout_template, &page_template, &page, &config);
72 73
     }
73 74
 
@@ -334,7 +335,7 @@ mod tests {
334 335
         .unwrap();
335 336
         fs::write(
336 337
             project_dir.join("posts").join("first-post.md"),
337
-            "# First post\n\nThis is the first post\n\nIt has multiple paragraphs",
338
+            "# First post | 2019-01-01\n\nThis is the first post\n\nIt has multiple paragraphs",
338 339
         )
339 340
         .unwrap();
340 341
         fs::write(
@@ -452,7 +453,7 @@ mod tests {
452 453
         .unwrap();
453 454
         fs::write(
454 455
             project_dir.join("posts").join("first-post.md"),
455
-            "# First post\n\nThis is the first post",
456
+            "# First post | 2019-01-01\n\nThis is the first post",
456 457
         )
457 458
         .unwrap();
458 459
         fs::write(
@@ -462,7 +463,7 @@ mod tests {
462 463
         .unwrap();
463 464
         fs::write(
464 465
             project_dir.join("drafts").join("first-draft.md"),
465
-            "# First draft\n\nThis is the first draft",
466
+            "# First draft | 2019-01-01\n\nThis is the first draft",
466 467
         )
467 468
         .unwrap();
468 469
         fs::write(

+ 2
- 0
src/main.rs View File

@@ -1,3 +1,4 @@
1
+extern crate chrono;
1 2
 extern crate clap;
2 3
 extern crate comrak;
3 4
 extern crate fs_extra;
@@ -14,6 +15,7 @@ use commands::{build, new, watch};
14 15
 
15 16
 mod commands;
16 17
 mod config;
18
+mod page;
17 19
 mod post;
18 20
 mod render;
19 21
 mod write;

+ 38
- 0
src/page.rs View File

@@ -0,0 +1,38 @@
1
+use regex::Regex;
2
+
3
+use std::fs;
4
+use std::path;
5
+
6
+#[derive(Debug)]
7
+pub struct Page {
8
+    pub title: String,
9
+    pub body: String,
10
+    pub slug: String,
11
+}
12
+
13
+pub fn read_pages_dir(cwd: &path::PathBuf) -> Vec<fs::DirEntry> {
14
+    match fs::read_dir(cwd) {
15
+        Ok(pages) => pages.into_iter().map(|page| page.unwrap()).collect(),
16
+        Err(err) => panic!(err),
17
+    }
18
+}
19
+
20
+pub fn parse_page(path: path::PathBuf) -> Page {
21
+    let contents = fs::read_to_string(&path).expect("Couldn't read page file");
22
+
23
+    lazy_static! {
24
+        static ref re: Regex = Regex::new(r"^# (?P<title>.*)\n\n(?s)(?P<body>.*)").unwrap();
25
+        static ref slug_re: Regex = Regex::new(r"(?P<slug>\S+).md").unwrap();
26
+    }
27
+
28
+    let title = &re.captures(&contents).expect("Couldn't parse title")["title"];
29
+    let body = &re.captures(&contents).expect("Couldn't parse body")["body"];
30
+
31
+    let filename = &path.file_name().unwrap().to_str().unwrap();
32
+    let slug = &slug_re.captures(filename).expect("Couldn't parse slug")["slug"];
33
+    Page {
34
+        title: String::from(title),
35
+        body: String::from(body),
36
+        slug: String::from(slug),
37
+    }
38
+}

+ 15
- 5
src/post.rs View File

@@ -1,13 +1,15 @@
1
+use chrono::NaiveDate;
2
+use regex::Regex;
3
+
1 4
 use std::fs;
2 5
 use std::path;
3 6
 
4
-use regex::Regex;
5
-
6 7
 #[derive(Debug)]
7 8
 pub struct Post {
8 9
     pub title: String,
9 10
     pub body: String,
10 11
     pub slug: String,
12
+    pub date: NaiveDate,
11 13
 }
12 14
 
13 15
 pub fn read_posts_dir(cwd: &path::PathBuf) -> Vec<fs::DirEntry> {
@@ -21,11 +23,14 @@ pub fn parse_post(path: path::PathBuf) -> Post {
21 23
     let contents = fs::read_to_string(&path).expect("Couldn't read post file");
22 24
 
23 25
     lazy_static! {
24
-        static ref re: Regex = Regex::new(r"^# (?P<title>.*)\n\n(?s)(?P<body>.*)").unwrap();
26
+        static ref re: Regex =
27
+            Regex::new(r"^# (?P<title>.*) \| (?P<date>\d{4}-\d{2}-\d{2})\n\n(?s)(?P<body>.*)")
28
+                .unwrap();
25 29
         static ref slug_re: Regex = Regex::new(r"(?P<slug>\S+).md").unwrap();
26 30
     }
27 31
 
28 32
     let title = &re.captures(&contents).expect("Couldn't parse title")["title"];
33
+    let date = &re.captures(&contents).expect("Couldn't parse date")["date"];
29 34
     let body = &re.captures(&contents).expect("Couldn't parse body")["body"];
30 35
 
31 36
     let filename = &path.file_name().unwrap().to_str().unwrap();
@@ -34,6 +39,7 @@ pub fn parse_post(path: path::PathBuf) -> Post {
34 39
         title: String::from(title),
35 40
         body: String::from(body),
36 41
         slug: String::from(slug),
42
+        date: NaiveDate::parse_from_str(&date, "%Y-%m-%d").expect("Couldn't parse date"),
37 43
     }
38 44
 }
39 45
 
@@ -108,14 +114,16 @@ mod tests {
108 114
         let filename = format!("{}.md", slug);
109 115
         fs::write(
110 116
             cwd.join("posts").join(&filename),
111
-            "# This is a post\n\nHere is some content that goes in the post",
117
+            "# This is a post | 2019-01-01\n\nHere is some content that goes in the post",
112 118
         )
113 119
         .unwrap();
114 120
 
115 121
         let post = parse_post(cwd.join("posts").join(&filename));
122
+        let date = NaiveDate::from_ymd(2019, 1, 1);
116 123
         assert_eq!("This is a post", post.title);
117 124
         assert_eq!("Here is some content that goes in the post", post.body);
118 125
         assert_eq!(slug, post.slug);
126
+        assert_eq!(date, post.date);
119 127
 
120 128
         fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
121 129
     }
@@ -134,17 +142,19 @@ mod tests {
134 142
         let filename = format!("{}.md", slug);
135 143
         fs::write(
136 144
             cwd.join("posts").join(&filename),
137
-            "# This is a post\n\nHere is a line\n\nHere is another line\n\nAnd a third",
145
+            "# This is a post | 2019-01-01\n\nHere is a line\n\nHere is another line\n\nAnd a third",
138 146
         )
139 147
         .unwrap();
140 148
 
141 149
         let post = parse_post(cwd.join("posts").join(&filename));
150
+        let date = NaiveDate::from_ymd(2019, 1, 1);
142 151
         assert_eq!("This is a post", post.title);
143 152
         assert_eq!(
144 153
             "Here is a line\n\nHere is another line\n\nAnd a third",
145 154
             post.body
146 155
         );
147 156
         assert_eq!(slug, post.slug);
157
+        assert_eq!(date, post.date);
148 158
 
149 159
         fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
150 160
     }

+ 22
- 1
src/render.rs View File

@@ -1,6 +1,7 @@
1 1
 use comrak::{markdown_to_html, ComrakOptions};
2 2
 
3 3
 use config::Config;
4
+use page::Page;
4 5
 use post::Post;
5 6
 
6 7
 pub fn render_post(layout: &str, post_template: &str, post: &Post, config: &Config) -> String {
@@ -18,6 +19,21 @@ pub fn render_post(layout: &str, post_template: &str, post: &Post, config: &Conf
18 19
         )
19 20
 }
20 21
 
22
+pub fn render_page(layout: &str, page_template: &str, page: &Page, config: &Config) -> String {
23
+    layout
24
+        .replace(
25
+            "{{ page_title }}",
26
+            &format!("{} | {}", page.title, config.site_name),
27
+        )
28
+        .replace(
29
+            "{{ contents }}",
30
+            &page_template.replace("{{ title }}", &page.title).replace(
31
+                "{{ body }}",
32
+                &markdown_to_html(&page.body, &ComrakOptions::default()),
33
+            ),
34
+        )
35
+}
36
+
21 37
 pub fn render_post_listing(
22 38
     layout: &str,
23 39
     post_listing_template: &str,
@@ -46,8 +62,9 @@ pub fn render_post_listing(
46 62
 
47 63
 #[cfg(test)]
48 64
 mod tests {
49
-    #[allow(unused_imports)]
50 65
     use super::{render_post, render_post_listing, Config, Post};
66
+    #[allow(unused_imports)]
67
+    use chrono::NaiveDate;
51 68
 
52 69
     #[test]
53 70
     fn test_render_post() {
@@ -58,6 +75,7 @@ mod tests {
58 75
                 title: String::from("hello world"),
59 76
                 body: String::from("lorem ipsum dolor sit amet"),
60 77
                 slug: String::from("hello-world"),
78
+                date: NaiveDate::from_ymd(2019, 1, 1),
61 79
             },
62 80
             &Config {
63 81
                 site_name: "Test Site".to_string(),
@@ -78,16 +96,19 @@ mod tests {
78 96
                 title: String::from("First post"),
79 97
                 body: String::from("lorem ipsum dolor sit amet"),
80 98
                 slug: String::from("first-post"),
99
+                date: NaiveDate::from_ymd(2019, 1, 1),
81 100
             },
82 101
             Post {
83 102
                 title: String::from("Second post"),
84 103
                 body: String::from("lorem ipsum dolor sit amet"),
85 104
                 slug: String::from("second-post"),
105
+                date: NaiveDate::from_ymd(2019, 1, 1),
86 106
             },
87 107
             Post {
88 108
                 title: String::from("Third post"),
89 109
                 body: String::from("lorem ipsum dolor sit amet"),
90 110
                 slug: String::from("third-post"),
111
+                date: NaiveDate::from_ymd(2019, 1, 1),
91 112
             },
92 113
         ];
93 114
         let output = render_post_listing(

+ 13
- 6
src/write.rs View File

@@ -1,6 +1,7 @@
1 1
 use config::Config;
2
+use page::Page;
2 3
 use post::Post;
3
-use render::{render_post, render_post_listing};
4
+use render::{render_page, render_post, render_post_listing};
4 5
 use std::fs;
5 6
 use std::path;
6 7
 
@@ -31,11 +32,11 @@ pub fn write_post(
31 32
 pub fn write_page(
32 33
     cwd: &path::PathBuf,
33 34
     layout: &str,
34
-    post_template: &str,
35
-    post: &Post,
35
+    page_template: &str,
36
+    page: &Page,
36 37
     config: &Config,
37 38
 ) {
38
-    match fs::create_dir(cwd.join("public").join(&post.slug)) {
39
+    match fs::create_dir(cwd.join("public").join(&page.slug)) {
39 40
         Ok(_) => {}
40 41
         Err(err) => match err.kind() {
41 42
             std::io::ErrorKind::AlreadyExists => {}
@@ -43,8 +44,8 @@ pub fn write_page(
43 44
         },
44 45
     }
45 46
     fs::write(
46
-        cwd.join("public").join(&post.slug).join("index.html"),
47
-        render_post(layout, post_template, post, config),
47
+        cwd.join("public").join(&page.slug).join("index.html"),
48
+        render_page(layout, page_template, page, config),
48 49
     )
49 50
     .expect("Unable to write file");
50 51
 }
@@ -72,6 +73,8 @@ pub fn write_post_listing(
72 73
 
73 74
 #[cfg(test)]
74 75
 mod tests {
76
+    use chrono::NaiveDate;
77
+
75 78
     #[allow(unused_imports)]
76 79
     use super::*;
77 80
     #[allow(unused_imports)]
@@ -97,6 +100,7 @@ mod tests {
97 100
             title: String::from("Hello world"),
98 101
             body: String::from("Lorem ipsum dolor sit amet"),
99 102
             slug: String::from("hello-world"),
103
+            date: NaiveDate::from_ymd(2019, 1, 1),
100 104
         };
101 105
         let config = Config {
102 106
             site_name: "Test Site".to_string(),
@@ -139,16 +143,19 @@ mod tests {
139 143
                 title: String::from("First post"),
140 144
                 body: String::from("lorem ipsum dolor sit amet"),
141 145
                 slug: String::from("first-post"),
146
+                date: NaiveDate::from_ymd(2019, 1, 1),
142 147
             },
143 148
             Post {
144 149
                 title: String::from("Second post"),
145 150
                 body: String::from("lorem ipsum dolor sit amet"),
146 151
                 slug: String::from("second-post"),
152
+                date: NaiveDate::from_ymd(2019, 1, 1),
147 153
             },
148 154
             Post {
149 155
                 title: String::from("Third post"),
150 156
                 body: String::from("lorem ipsum dolor sit amet"),
151 157
                 slug: String::from("third-post"),
158
+                date: NaiveDate::from_ymd(2019, 1, 1),
152 159
             },
153 160
         ];
154 161
         let config = Config {

Loading…
Cancel
Save