extern crate reqwest; use std::process::Command; use std::env; use std::path::{Path, PathBuf}; use std::fs::canonicalize; use std::fs::{File, create_dir_all}; use std::io::{Write, copy}; pub fn yarn_install () { Command::new("yarn").output().expect("failed to execute yarn process"); } pub fn browserify (infile: &str, outfile: &str) -> PathBuf { let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); let full_outfile = out_dir.join(outfile); Command::new("node_modules/.bin/browserify") .args(&[infile, "-o", full_outfile.to_str().expect("failed to build output path")]) .output() .expect("failed to build js bundle"); full_outfile } pub fn lessc (infile: &str, outfile: &str) -> PathBuf { let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); let full_outfile = out_dir.join(outfile); Command::new("node_modules/.bin/lessc") .args(&[infile, full_outfile.to_str().expect("failed to build output path")]) .output() .expect("failed to build css bundle"); full_outfile } pub struct ResourcesGenerator { resources: Vec } impl ResourcesGenerator { pub fn new () -> ResourcesGenerator { ResourcesGenerator { resources: vec![] } } pub fn add (&mut self, resource: Resource) -> &mut ResourcesGenerator { self.resources.push(resource); self } pub fn write (&self) { let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); let mut outfile = File::create(out_dir.join("resources.rs").to_str().expect("failed to build output path")).expect("failed to create outfile"); let mut consts = String::new(); let mut routes = String::new(); let mut routes_fn = String::from("pub fn routes() -> Vec {\n\troutes!["); let mut handlebars = String::new(); for resource in &self.resources { let canonical_source = canonicalize(&resource.source).expect("failed to get canonical path"); let data_type = if resource.raw { "[u8]" } else { "str" }; let include = format!("include_{}!(\"{}\")", if resource.raw { "bytes" } else { "str" }, canonical_source.display()); if let Some(constant) = resource.constant { consts.push_str(&format!( "const {}: &'static {} = {};\n", constant, data_type, include )); } if let Some(ref mount_at) = resource.mount_at { let mut function_name = String::from("route"); function_name.push_str(&mount_at.endpoint.replace("/", "_").replace(".", "_")); routes.push_str(&format!( "#[get(\"{}\")]\nfn {}() -> Content<&'static {}> {{\n\tContent(ContentType::{}, {})\n}}\n\n", mount_at.endpoint, function_name, data_type, mount_at.content_type, resource.constant.unwrap_or(&include) )); routes_fn.push_str(&function_name); routes_fn.push(','); } if let Some(ref handlebars_name) = resource.template_name { handlebars.push_str(&format!( "\n\thbs.register_template_string(\"{}\", {}).expect(\"Failed to register template: {}\");", handlebars_name, resource.constant.unwrap_or(&include), handlebars_name )); } } if !routes.is_empty() { outfile.write(b"use rocket::Route;\nuse rocket::response::Content;\nuse rocket::http::ContentType;\n\n"); } if !handlebars.is_empty () { outfile.write(b"use handlebars::Handlebars;\n\n"); } outfile.write(consts.as_bytes()); outfile.write(b"\n"); if !routes.is_empty() { outfile.write(routes.as_bytes()); outfile.write(routes_fn.as_bytes()); outfile.write(b"]\n}"); } if !handlebars.is_empty() { outfile.write(b"pub fn handlebars() -> Handlebars {\n"); outfile.write(b"\tlet mut hbs = Handlebars::new();"); outfile.write(handlebars.as_bytes()); outfile.write(b"hbs\n}"); } } } #[derive(Default)] pub struct Resource { pub source: PathBuf, pub mount_at: Option, pub constant: Option<&'static str>, pub template_name: Option<&'static str>, pub raw: bool } pub struct ResourceMount { pub endpoint: &'static str, pub content_type: &'static str } pub struct Downloader { cache: PathBuf } impl Downloader { pub fn new>(cache: P) -> Downloader { Downloader { cache: cache.as_ref().to_path_buf() } } pub fn get(&self, url: &str) -> PathBuf { if !self.cache.exists() { create_dir_all(self.cache.as_path()).expect("failed to create cache directory"); } let filename = url.get((url.rfind('/').expect("not a valid url")..)).expect("failed to parse filename"); let mut out_path = self.cache.clone(); out_path.push(filename); if !out_path.exists() { let mut result = reqwest::get(url).expect("failed to download url"); let mut file = File::create(out_path.as_path()).expect("failed to open file"); copy(&mut result, &mut file).expect("failed to write file"); } out_path } }