use std::fs; use std::fs::File; use std::path::Path; extern crate tera; use tera::{ Context, Tera, }; use serde::{ Deserialize, Serialize, }; #[derive(Clone, Debug, Serialize, Deserialize)] struct SVGConfig { svgs: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] struct SVGMetadata { template: String, title: String, description: String, } #[derive(Clone, Debug, Serialize, Deserialize)] struct Post { full_url: Option, url: String, title: String, summary: String, date_published: String, date_modified: Option, template_name: String, } #[derive(Clone, Debug, Serialize, Deserialize)] struct Project { full_url: Option, url: String, title: String, image: String, summary: String, template_name: String, } #[derive(Clone, Debug, Serialize, Deserialize)] struct Config { posts: Vec, tech_demos: Vec, projects: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] struct MyContext { title: String, description: String, canonical_url: String, favicon_image: String, page_image: String, og_type: String, og_locale: String, og_site_name: String, twitter_card: String, posts: Vec, tech_demos: Vec, projects: Vec, } impl Default for MyContext { fn default() -> Self { Self { title: "chmod777's homepage".to_owned(), description: "A place where chmod777 puts their blog posts, project updates, and tech demos.".to_owned(), canonical_url: "http://tilde.club/~chmod777".to_owned(), favicon_image: "http://tilde.club/~chmod777/favicon.svg".to_owned(), page_image: "http://tilde.club/~chmod777/favicon.svg".to_owned(), og_type: "website".to_owned(), og_locale: "en-US".to_owned(), og_site_name: "tilde.club".to_owned(), twitter_card: "summary".to_owned(), posts: Vec::new(), tech_demos: Vec::new(), projects: Vec::new(), } } } fn get_file(path: &str) -> File { let path = Path::new(path); let display = path.display(); match File::create(path) { Ok(file) => file, Err(error) => panic!("Couldn't create file {}: {}", &display, &error), } } fn read_file(path: &str) -> String { fs::read_to_string(path).expect(&format!("Failed to read file: {}", path)) } fn append_str(base: &str, extend: &str) -> String { let mut s = base.to_owned(); s.push_str(extend); s } fn main() { { fs::copy("ts/src/base.ts", "public/ts/base.ts").unwrap(); fs::copy("ts/src/pong.ts", "public/ts/pong.ts").unwrap(); } { let svg_tera = match Tera::new("svg_templates/**/*") { Ok(tera) => tera, Err(error_s) => panic!("Parsing error(s): {}", error_s), }; let svg_config_json_string = read_file("svg_config.json"); let svg_config: SVGConfig = serde_json::from_str(&svg_config_json_string).unwrap(); for metadata in svg_config.svgs.iter() { let temp_path = append_str("templates/svg/", &metadata.template); let path = append_str("public/assets/svg/", &metadata.template); svg_tera .render_to( &metadata.template, &Context::from_serialize(&metadata).unwrap(), get_file(&temp_path), ) .unwrap(); fs::copy(temp_path, path).unwrap(); } } let tera = match Tera::new("templates/**/*") { Ok(tera) => tera, Err(error_s) => panic!("Parsing error(s): {}", error_s), }; let config_json_string = read_file("config.json"); let config: Config = serde_json::from_str(&config_json_string).unwrap(); let mut context = MyContext::default(); let base_url = "http://tilde.club/~chmod777"; for mut post in config.posts.iter().cloned() { post.full_url = Some(append_str(base_url, &post.url)); context.posts.push(post); } for mut demo in config.tech_demos.iter().cloned() { demo.full_url = Some(append_str(base_url, &demo.url)); context.tech_demos.push(demo) } for mut project in config.projects.iter().cloned() { project.full_url = Some(append_str(base_url, &project.url)); context.projects.push(project); } tera.render_to( "index.html", &Context::from_serialize(&context).unwrap(), get_file("public/index.html"), ) .unwrap(); { context.title = "About JavaScript".to_owned(); context.canonical_url = "http://tilde.club/~chmod777/about/javascript.html".to_owned(); let blog_context = Context::from_serialize(&context).unwrap(); tera.render_to( "javascript.html", &blog_context, get_file("public/about/javascript.html"), ) .unwrap(); } { context.title = "chmod777's blog".to_owned(); context.canonical_url = "http://tilde.club/~chmod777/blog/blog.html".to_owned(); let blog_context = Context::from_serialize(&context).unwrap(); tera.render_to( "blog/blog.html", &blog_context, get_file("public/blog/blog.html"), ) .unwrap(); tera.render_to("feed.rss", &blog_context, get_file("public/feed.rss")) .unwrap(); context.og_type = "article".to_owned(); for post in context.posts.iter() { context.canonical_url = post.full_url.clone().unwrap(); context.description = post.summary.clone(); let path = append_str("public", &post.url); tera.render_to( &post.template_name, &Context::from_serialize(&context).unwrap(), get_file(&path), ) .unwrap(); } } { context.title = "chmod777's projects".to_owned(); context.og_type = "website".to_owned(); context.canonical_url = "http://tilde.club/~chmod777/projects/projects.html".to_owned(); context.description = "".to_owned(); tera.render_to( "projects/projects.html", &Context::from_serialize(&context).unwrap(), get_file("public/projects/projects.html"), ) .unwrap(); for project in context.projects.iter() { context.canonical_url = project.full_url.clone().unwrap(); context.description = project.summary.clone(); let path = append_str("public", &project.url); tera.render_to( &project.template_name, &Context::from_serialize(&context).unwrap(), get_file(&path), ) .unwrap(); } } { context.title = "chmod777's tech demos".to_owned(); context.canonical_url = "http://tilde.club/~chmod777/tech_demos/tech_demos.html".to_owned(); context.description = "".to_owned(); tera.render_to( "tech_demos/tech_demos.html", &Context::from_serialize(&context).unwrap(), get_file("public/tech_demos/tech_demos.html"), ) .unwrap(); for demo in context.tech_demos.iter() { context.canonical_url = demo.full_url.clone().unwrap(); context.description = demo.summary.clone(); let path = append_str("public", &demo.url); tera.render_to( &demo.template_name, &Context::from_serialize(&context).unwrap(), get_file(&path), ) .unwrap(); } } }