123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- #[macro_use]
- extern crate lazy_static;
- extern crate regex;
-
- use std::env;
- use std::fs;
- use std::path;
-
- use regex::Regex;
-
- #[derive(Debug)]
- struct Post {
- title: String,
- body: String,
- slug: String,
- }
-
- fn parse_post(path: path::PathBuf) -> Post {
- let contents = fs::read_to_string(&path).expect("Couldn't read post file");
-
- lazy_static! {
- static ref re: Regex = Regex::new(r"^# (?P<title>.*)\n\n(?P<body>.*)").unwrap();
- static ref slug_re: Regex = Regex::new(r"(?P<slug>\S+).md").unwrap();
- }
-
- let title = &re.captures(&contents).expect("Couldn't parse title")["title"];
-
- let body = &re.captures(&contents).expect("Couldn't parse body")["body"];
-
- let filename = &path.file_name().unwrap().to_str().unwrap();
- let slug = &slug_re.captures(filename).expect("Couldn't parse slug")["slug"];
- Post {
- title: String::from(title),
- body: String::from(body),
- slug: String::from(slug),
- }
- }
-
- fn read_posts_dir(cwd: &path::PathBuf) -> fs::ReadDir {
- match fs::read_dir(cwd) {
- Ok(posts) => posts,
- Err(err) => panic!(err),
- }
- }
-
- fn render_post(cwd: &path::PathBuf, layout: &str, post: &Post) {
- let post_template = fs::read_to_string(cwd.join("templates").join("post.html"))
- .expect("Couldn't find post template");
- let output = layout.replace(
- "{{ contents }}",
- &post_template
- .replace("{{ title }}", &post.title)
- .replace("{{ body }}", &post.body),
- );
- match fs::create_dir(cwd.join("public").join(&post.slug)) {
- Ok(_) => {}
- Err(err) => match err.kind() {
- std::io::ErrorKind::AlreadyExists => {}
- _ => panic!(err),
- },
- }
- fs::write(
- cwd.join("public").join(&post.slug).join("index.html"),
- &output,
- ).expect("Unable to write file");
- }
-
- fn render_post_listing(cwd: &path::PathBuf, layout: &str, posts: &Vec<Post>) {
- let post_item_template =
- fs::read_to_string(cwd.join("templates").join("post_listing_item.html"))
- .expect("Couldn't find post listing item template");
- let post_listing = posts
- .iter()
- .map(|ref post| {
- post_item_template
- .replace("{{ slug }}", &post.slug)
- .replace("{{ title }}", &post.title)
- }).collect::<Vec<String>>()
- .join("\n");
-
- let output = layout.replace("{{ contents }}", &post_listing);
- fs::write(cwd.join("public").join("index.html"), &output).expect("Unable to write file");
- }
-
- fn main() {
- let cwd = env::current_dir().expect("Couldn't read current directory");
-
- match fs::create_dir(cwd.join("public")) {
- Ok(_) => {},
- Err(err) => {
- match err.kind() {
- std::io::ErrorKind::AlreadyExists => {},
- _ => panic!(err)
- }
- }
- }
-
- let layout = fs::read_to_string(&cwd.join("templates").join("layout.html"))
- .expect("Couldn't find layout template");
- let post_paths = read_posts_dir(&cwd.join("posts"));
- let mut posts: Vec<Post> = vec![];
- for path in post_paths {
- match path {
- Ok(p) => {
- let post = parse_post(p.path());
- render_post(&cwd, &layout, &post);
- posts.push(post);
- }
- Err(err) => panic!(err),
- }
- }
-
- render_post_listing(&cwd, &layout, &posts);
- }
|