A static site generator written in Rust
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

main.rs 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. extern crate clap;
  2. extern crate comrak;
  3. extern crate fs_extra;
  4. #[macro_use]
  5. extern crate lazy_static;
  6. extern crate regex;
  7. extern crate uuid;
  8. use std::{env, fs};
  9. use clap::{App, Arg};
  10. use fs_extra::dir;
  11. use post::{parse_post, read_posts_dir};
  12. use write::{write_post, write_post_listing};
  13. mod post;
  14. mod render;
  15. mod write;
  16. fn build() {
  17. let cwd = env::current_dir().expect("Couldn't read current directory");
  18. match fs::read_dir(cwd.join("public")) {
  19. Ok(_) => {
  20. fs::remove_dir_all(cwd.join("public")).unwrap();
  21. }
  22. Err(_) => {}
  23. }
  24. fs::create_dir(cwd.join("public")).expect("Couldn't create public directory");
  25. let layout_template = fs::read_to_string(&cwd.join("templates").join("layout.html"))
  26. .expect("Couldn't find layout template");
  27. let post_template = fs::read_to_string(cwd.join("templates").join("post.html"))
  28. .expect("Couldn't find post template");
  29. let post_listing_template = fs::read_to_string(cwd.join("templates").join("post_listing.html"))
  30. .expect("Couldn't find post listing item template");
  31. let post_item_template =
  32. fs::read_to_string(cwd.join("templates").join("post_listing_item.html"))
  33. .expect("Couldn't find post listing item template");
  34. let post_paths = read_posts_dir(&cwd.join("posts"));
  35. let posts = post_paths
  36. .into_iter()
  37. .map(|path| match path {
  38. Ok(p) => {
  39. let post = parse_post(p.path());
  40. write_post(&cwd, &layout_template, &post_template, &post);
  41. post
  42. }
  43. Err(err) => panic!(err),
  44. }).collect();
  45. write_post_listing(
  46. &cwd,
  47. &layout_template,
  48. &post_listing_template,
  49. &post_item_template,
  50. &posts,
  51. );
  52. fs_extra::copy_items(
  53. &vec![cwd.join("css"), cwd.join("js")],
  54. cwd.join("public"),
  55. &dir::CopyOptions::new(),
  56. ).expect("Couldn't copy css/js directories");
  57. }
  58. fn new(name: &str) {
  59. let cwd = env::current_dir().expect("Couldn't read current directory");
  60. let project_path = cwd.join(name);
  61. fs::create_dir(&project_path).expect(&format!("Couldn't create directory '{}'", &name));
  62. for dir in &["posts", "public", "templates", "css", "js"] {
  63. fs::create_dir(&project_path.join(&dir))
  64. .expect(&format!("Couldn't create {} directory", &dir));
  65. }
  66. fs::write(project_path.join("css").join("style.css"), "")
  67. .expect("Couldn't create css/style.css");
  68. fs::write(project_path.join("js").join("index.js"), "").expect("Couldn't create js/index.js");
  69. for file in &["layout", "post_listing", "post", "post_listing_item"] {
  70. fs::write(
  71. &project_path
  72. .join("templates")
  73. .join(format!("{}.html", file)),
  74. "",
  75. ).expect(&format!("Couldn't write templates/{}.html", file));
  76. }
  77. }
  78. fn main() {
  79. let matches = App::new("tlon")
  80. .version("0.1.0")
  81. .author("Dylan Baker")
  82. .about("Highly opinionated static site generator")
  83. .arg(
  84. Arg::with_name("command")
  85. .required(true)
  86. .possible_values(&["build", "new"])
  87. .index(1),
  88. ).arg(
  89. Arg::with_name("name")
  90. .required_if("command", "new")
  91. .index(2),
  92. ).get_matches();
  93. let command = matches.value_of("command").unwrap();
  94. if command == "build" {
  95. build();
  96. } else if command == "new" {
  97. new(&matches.value_of("name").unwrap());
  98. }
  99. }
  100. #[cfg(test)]
  101. mod tests {
  102. #[allow(unused_imports)]
  103. use super::*;
  104. #[allow(unused_imports)]
  105. use uuid::Uuid;
  106. #[test]
  107. fn test_new() {
  108. let temp_dir = env::temp_dir();
  109. env::set_current_dir(&temp_dir).unwrap();
  110. let uuid = Uuid::new_v4().to_string();
  111. let project_dir = temp_dir.join(&uuid);
  112. new(&uuid);
  113. for dir in &["public", "posts", "templates"] {
  114. fs::read_dir(&project_dir.join(dir)).unwrap();
  115. }
  116. assert_eq!(
  117. "",
  118. fs::read_to_string(&project_dir.join("templates").join("post_listing.html")).unwrap()
  119. );
  120. assert_eq!(
  121. "",
  122. fs::read_to_string(&project_dir.join("templates").join("layout.html")).unwrap()
  123. );
  124. assert_eq!(
  125. "",
  126. fs::read_to_string(&project_dir.join("templates").join("post_listing_item.html"))
  127. .unwrap()
  128. );
  129. assert_eq!(
  130. "",
  131. fs::read_to_string(&project_dir.join("templates").join("post.html")).unwrap()
  132. );
  133. assert_eq!(
  134. "",
  135. fs::read_to_string(&project_dir.join("css").join("style.css")).unwrap()
  136. );
  137. assert_eq!(
  138. "",
  139. fs::read_to_string(&project_dir.join("js").join("index.js")).unwrap()
  140. );
  141. fs::remove_dir_all(project_dir).unwrap();
  142. }
  143. }