diff --git a/Cargo.lock b/Cargo.lock index e30c466..77326d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "0.7.20" @@ -26,6 +32,36 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -82,7 +118,7 @@ dependencies = [ "js-sys", "num-integer", "num-traits", - "time", + "time 0.1.45", "wasm-bindgen", "winapi", ] @@ -171,6 +207,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -262,6 +307,26 @@ dependencies = [ "libc", ] +[[package]] +name = "fancy-regex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6b8560a05112eb52f04b00e5d3790c0dd75d9d980eb8a122fb23b92a623ccf" +dependencies = [ + "bit-set", + "regex", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -287,6 +352,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -337,6 +411,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "heck" version = "0.4.0" @@ -409,6 +489,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "io-lifetimes" version = "1.0.3" @@ -444,7 +534,9 @@ dependencies = [ "chrono", "clap", "git2", + "pulldown-cmark", "serde", + "syntect", "tera", "toml", ] @@ -519,6 +611,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + [[package]] name = "link-cplusplus" version = "1.0.8" @@ -528,6 +629,12 @@ dependencies = [ "cc", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.1.4" @@ -549,6 +656,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -574,6 +690,28 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +[[package]] +name = "onig" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +dependencies = [ + "bitflags", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -703,6 +841,20 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "plist" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" +dependencies = [ + "base64", + "indexmap", + "line-wrap", + "serde", + "time 0.3.17", + "xml-rs", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -742,6 +894,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pulldown-cmark" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" +dependencies = [ + "bitflags", + "getopts", + "memchr", + "unicase", +] + [[package]] name = "quote" version = "1.0.23" @@ -818,6 +982,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + [[package]] name = "same-file" version = "1.0.6" @@ -907,6 +1077,30 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syntect" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8" +dependencies = [ + "bincode", + "bitflags", + "fancy-regex", + "flate2", + "fnv", + "lazy_static", + "once_cell", + "onig", + "plist", + "regex-syntax", + "serde", + "serde_derive", + "serde_json", + "thiserror", + "walkdir", + "yaml-rust", +] + [[package]] name = "tera" version = "1.17.1" @@ -978,6 +1172,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1073,6 +1294,15 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.8" @@ -1287,3 +1517,18 @@ name = "windows_x86_64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index 24cddf9..d0a0c4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,11 +11,18 @@ repository = "https://github.com/mrmekon/itsy-gitsy" readme = "README.md" license = "GPL-3.0-or-later" +[features] +default = ["markdown", "highlight"] +markdown = ["dep:pulldown-cmark"] +highlight_fast = ["syntect/default-onig"] +highlight = ["syntect/default-fancy"] [dependencies] chrono = { version = "0.4.23", features=["clock"] } clap = { version="4.0.32", features=["derive"] } git2 = "0.15.0" +pulldown-cmark = { version = "0.9.2", optional = true } serde = { version = "1.0.152", features = ["derive"] } +syntect = { version = "5.0.0", default-features = false, option = true } tera = "1.17.1" toml = "0.5.10" diff --git a/settings.toml b/settings.toml index 64864e0..64d51ff 100644 --- a/settings.toml +++ b/settings.toml @@ -2,10 +2,20 @@ site_name = "Trevor's Repos" site_url = "https://git.trevorbentley.com" site_description = "A bunch of git repos in a stupid format." +render_markdown = true +syntax_highlight = true +syntax_highlight_theme = "base16-ocean.light" + output_dir = "gen/" recursive_repo_dirs = ["repos/"] +# TODO: specify limits +# TODO: specify output directories/filenames +# TODO: extra metadata for recursive repo listings +# TODO: per-site and per-repo resources (just copied to output dir) +# TODO: enable/disable markdown/highlighting +# TODO: highlighting theme, extensions [gitsy_templates] path = "templates/" repo_list = "repos.html" @@ -15,8 +25,6 @@ branch = "branch.html" tag = "tag.html" file = "file.html" dir = "dir.html" -header = "header.html" -footer = "footer.html" error = "404.html" [gitsy_extra] @@ -28,3 +36,5 @@ or_bools = true path = "more_repos/circadian" website = "https://circadian.trevorbentley.com" attributes = {some_extra_thing = "user defined", visible = false, number_of_bananas = 3} +render_markdown = false +syntax_highlighting = false diff --git a/src/main.rs b/src/main.rs index 7685d17..c9a234b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,17 @@ use std::io::Write; use std::path::{Path, PathBuf}; use tera::{Context, Filter, Function, Tera, Value, to_value, try_get_value}; +#[cfg(feature = "markdown")] +use pulldown_cmark::{html, Options, Parser as MdParser}; + +#[cfg(any(feature = "highlight", feature = "highlight_fast"))] +use syntect::{ + html::{ClassedHTMLGenerator, ClassStyle, css_for_theme_with_class_style}, + parsing::SyntaxSet, + highlighting::ThemeSet, + util::LinesWithEndings, +}; + fn ts_to_date(ts: i64, offset: Option, format: Option) -> String { let offset = offset.unwrap_or(0); let dt = NaiveDateTime::from_timestamp_opt(ts + offset, 0).expect("Invalid timestamp"); @@ -97,6 +108,8 @@ struct GitFile { is_binary: bool, size: usize, contents: Option, + contents_safe: bool, + contents_preformatted: bool, } #[derive(Serialize, Default)] @@ -164,6 +177,8 @@ fn walk_file_tree(repo: &git2::Repository, rev: &str, files: &mut Vec, is_binary, size, contents: None, + contents_safe: false, + contents_preformatted: true, }); if recurse && entry.kind() == Some(git2::ObjectType::Tree) { let prefix = name + "/"; @@ -455,12 +470,61 @@ fn parse_commit(repo: &Repository, refr: &str) -> Result { Ok(summary) } -fn fill_file_contents(repo: &Repository, file: &GitFile) -> Result { +#[cfg(feature = "markdown")] +fn parse_markdown(contents: &str) -> String { + let mut options = Options::empty(); + options.insert(Options::ENABLE_STRIKETHROUGH); + options.insert(Options::ENABLE_TABLES); + let parser = MdParser::new_ext(contents, options); + let mut html_output: String = String::with_capacity(contents.len() * 3 / 2); + html::push_html(&mut html_output, parser); + html_output +} + +#[cfg(any(feature = "highlight", feature = "highlight_fast"))] +fn syntax_highlight(contents: &str, extension: &str) -> String { + let syntax_set = SyntaxSet::load_defaults_newlines(); + let syntax = match syntax_set.find_syntax_by_extension(extension) { + Some(s) => s, + _ => { return contents.to_string(); }, + }; + let mut html_generator = ClassedHTMLGenerator::new_with_class_style(syntax, &syntax_set, ClassStyle::Spaced); + for line in LinesWithEndings::from(contents) { + match html_generator.parse_html_for_line_which_includes_newline(line) { + Ok(_) => {}, + Err(_) => { + println!("Warning: failed to apply syntax highlighting."); + return contents.to_string(); + }, + } + } + html_generator.finalize() +} + +fn fill_file_contents(repo: &Repository, file: &GitFile, settings: &GitsySettingsRepo) -> Result { let mut file = file.clone(); if file.kind == "file" { let blob = repo.find_blob(git2::Oid::from_str(&file.id)?)?; file.contents = match blob.is_binary() { - false => Some(String::from_utf8_lossy(blob.content()).to_string()), + false => { + let path = Path::new(&file.path); + let cstr = String::from_utf8_lossy(blob.content()).to_string(); + let (content, rendered, pre) = match path.extension() { + #[cfg(feature = "markdown")] + Some(x) if settings.render_markdown.unwrap_or(false) && x == "md" => { + let (cstr, rendered, pre) = (parse_markdown(&cstr), true, false); + (cstr, rendered, pre) + }, + #[cfg(any(feature = "highlight", feature = "highlight_fast"))] + Some(x) if settings.syntax_highlight.unwrap_or(false) => { + (syntax_highlight(&cstr, x.to_string_lossy().to_string().as_str()), true, true) + }, + _ => (cstr, false, true), + }; + file.contents_safe = rendered; + file.contents_preformatted = pre; + Some(content) + }, true => Some(format!("[Binary data ({} bytes)]", blob.content().len())), }; } @@ -570,6 +634,9 @@ struct GitsySettings { site_description: Option, #[serde(rename(deserialize = "gitsy_templates"))] templates: GitsySettingsTemplates, + render_markdown: Option, + syntax_highlight: Option, + syntax_highlight_theme: Option, #[serde(rename(deserialize = "gitsy_extra"))] extra: Option>, } @@ -577,8 +644,6 @@ struct GitsySettings { #[derive(Deserialize)] struct GitsySettingsTemplates { path: PathBuf, - header: Option, - footer: Option, repo_list: Option, repo_summary: Option, commit: Option, @@ -595,6 +660,9 @@ struct GitsySettingsRepo { name: Option, description: Option, website: Option, + render_markdown: Option, + syntax_highlight: Option, + syntax_highlight_theme: Option, attributes: BTreeMap, } @@ -611,14 +679,8 @@ impl PartialEq for GitsySettingsRepo { } impl Eq for GitsySettingsRepo {} -fn write_rendered(file: &mut File, rendered: &str, header: Option<&str>, footer: Option<&str>) { - if let Some(header) = header { - file.write(header.as_bytes()).expect("failed to save rendered html"); - } +fn write_rendered(file: &mut File, rendered: &str) { file.write(rendered.as_bytes()).expect("failed to save rendered html"); - if let Some(footer) = footer { - file.write(footer.as_bytes()).expect("failed to save rendered html"); - } } fn main() { @@ -667,6 +729,9 @@ fn main() { let dir = dir.expect("Repo contains invalid entries"); repo_descriptions.insert(GitsySettingsRepo { path: dir.path().clone(), + render_markdown: settings.render_markdown.clone(), + syntax_highlight: settings.syntax_highlight.clone(), + syntax_highlight_theme: settings.syntax_highlight_theme.clone(), ..Default::default() }); } @@ -729,14 +794,6 @@ fn main() { } local_ctx.insert("site_generated_ts", &generated_dt.timestamp()); local_ctx.insert("site_generated_offset", &generated_dt.offset().local_minus_utc()); - let header: Option = match &settings.templates.header { - Some(header) => Some(tera.render(header, &local_ctx).expect("Unable to templatize header file")), - _ => None, - }; - let footer: Option = match &settings.templates.footer { - Some(footer) => Some(tera.render(footer, &local_ctx).expect("Unable to templatize footer file")), - _ => None, - }; match tera.render(&settings.templates.repo_summary.as_deref().unwrap_or("summary.html"), &local_ctx) { Ok(rendered) => { @@ -745,7 +802,7 @@ fn main() { let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); output_path.push("summary.html"); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_summary.is_none() => {}, @@ -763,7 +820,7 @@ fn main() { let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); output_path.push(format!("{}.html", branch.full_hash)); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.branch.is_none() => {}, @@ -786,7 +843,7 @@ fn main() { let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); output_path.push(format!("{}.html", tag.full_hash)); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.tag.is_none() => {}, @@ -807,7 +864,7 @@ fn main() { let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); output_path.push(format!("{}.html", commit.full_hash)); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.commit.is_none() => {}, @@ -817,8 +874,28 @@ fn main() { local_ctx.remove("commit"); } + // TODO: most of these generation blocks can be done in + // parallel. This one is particularly costly, especially with + // markdown+highlighting, and would probably benefit from it. + // A potential drawback is that each parallel run needs a + // clone of the Tera context. + #[cfg(any(feature = "highlight", feature = "highlight_fast"))] + { + let ts = ThemeSet::load_defaults(); + let theme = ts.themes.get(repo_desc.syntax_highlight_theme.as_deref() + .unwrap_or("base16-ocean.light")).expect("Invalid syntax highlighting theme specified."); + let css: String = css_for_theme_with_class_style(theme, syntect::html::ClassStyle::Spaced) + .expect("Invalid syntax highlighting theme specified."); + let mut output_path = settings.output_dir.clone(); + output_path.push(&summary.name); + output_path.push("file"); + output_path.push("syntax.css"); + let mut file = std::fs::File::create(output_path.to_str().expect("CSS filename invalid!")).expect("CSS path not writeable!"); + file.write(css.as_bytes()).expect("Failed to write CSS file!"); + } + for file in summary.all_files.iter().filter(|x| x.kind == "file") { - let file = fill_file_contents(&repo, &file).expect("Failed to parse file."); + let file = fill_file_contents(&repo, &file, &repo_desc).expect("Failed to parse file."); local_ctx.try_insert("file", &file).expect("Failed to add file to template engine."); match tera.render(&settings.templates.file.as_deref().unwrap_or("file.html"), &local_ctx) { Ok(rendered) => { @@ -828,7 +905,7 @@ fn main() { let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); output_path.push(format!("{}.html", file.id)); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.file.is_none() => {}, @@ -849,7 +926,7 @@ fn main() { let _ = std::fs::create_dir(output_path.to_str().expect("Output path not set!")); output_path.push(format!("{}.html", dir.id)); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.dir.is_none() => {}, @@ -878,21 +955,13 @@ fn main() { } global_ctx.insert("site_generated_ts", &generated_dt.timestamp()); global_ctx.insert("site_generated_offset", &generated_dt.offset().local_minus_utc()); - let header: Option = match &settings.templates.header { - Some(header) => Some(tera.render(header, &global_ctx).expect("Unable to templatize header file")), - _ => None, - }; - let footer: Option = match &settings.templates.footer { - Some(footer) => Some(tera.render(footer, &global_ctx).expect("Unable to templatize footer file")), - _ => None, - }; match tera.render(&settings.templates.repo_list.as_deref().unwrap_or("repos.html"), &global_ctx) { Ok(rendered) => { let mut output_path = settings.output_dir.clone(); output_path.push("repos.html"); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.repo_list.is_none() => {}, @@ -905,7 +974,7 @@ fn main() { let mut output_path = settings.output_dir.clone(); output_path.push("404.html"); let mut file = std::fs::File::create(output_path.to_str().expect("Output path not set!")).unwrap(); - write_rendered(&mut file, &rendered, header.as_deref(), footer.as_deref()); + write_rendered(&mut file, &rendered); }, Err(x) => match x.kind { tera::ErrorKind::TemplateNotFound(_) if settings.templates.error.is_none() => {}, diff --git a/templates/404.html b/templates/404.html index bb95dd8..6811ef0 100644 --- a/templates/404.html +++ b/templates/404.html @@ -1 +1,5 @@ +{% extends "base.html" %} + +{% block content %} The page you are seeking does not exist. +{% endblock content %} diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..ee9c416 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,17 @@ + + +{% block html_head -%} +{{site_name}} +{% block html_head_extra -%} +{% endblock html_head_extra -%} +{% endblock html_head -%} + + + +{% block header -%}{% include "header.html" -%}{% endblock header -%} + +{% block content %}{% endblock content %} + +{% block footer -%}{% include "footer.html" -%}{% endblock footer -%} + + diff --git a/templates/branch.html b/templates/branch.html index d349372..0731947 100644 --- a/templates/branch.html +++ b/templates/branch.html @@ -1,3 +1,6 @@ +{% extends "base.html" %} + +{% block content %} branch: {{branch.ref_name}}
hash: {{branch.full_hash}} ({{branch.short_hash}})
author: {{branch.author.name}}
@@ -5,3 +8,4 @@ committer: {{branch.committer.name}}
date: {{ts_to_date(ts=branch.ts_utc, tz=branch.ts_offset)}}
summary: {{branch.summary}}
{{branch.message}}
+{% endblock content %} diff --git a/templates/commit.html b/templates/commit.html index c399d17..9afc401 100644 --- a/templates/commit.html +++ b/templates/commit.html @@ -1,3 +1,6 @@ +{% extends "base.html" %} + +{% block content %} commit: {{commit.full_hash}}
author: {{commit.author.name}}
@@ -25,3 +28,4 @@ {% endfor -%} {% endfor -%} +{% endblock content %} diff --git a/templates/dir.html b/templates/dir.html index 44afb19..a56436a 100644 --- a/templates/dir.html +++ b/templates/dir.html @@ -1,3 +1,6 @@ +{% extends "base.html" %} + +{% block content %} @@ -15,3 +18,4 @@ {% endfor -%} +{% endblock content %} diff --git a/templates/file.html b/templates/file.html index 7f00ee5..26de15b 100644 --- a/templates/file.html +++ b/templates/file.html @@ -1,3 +1,20 @@ +{% extends "base.html" %} + +{% block html_head_extra %} + +{% endblock html_head_extra %} + + +{% block content %} {{file.path}} ({{file.name}}) [{{file.id}}]
-------- +-------
+{% if file.contents_safe -%} +{% if file.contents_preformatted -%} +
{{file.contents | safe }}
+{%- else -%} +{{file.contents | safe }} +{%- endif -%} +{%- else -%}
{{file.contents}}
+{%- endif -%} +{% endblock content %} diff --git a/templates/footer.html b/templates/footer.html index b605728..f29b415 100644 --- a/templates/footer.html +++ b/templates/footer.html @@ -1,2 +1,2 @@ - - +
+Generated by Itsy-Gitsy on {{ts_to_git_timestamp(ts=site_generated_ts, tz=site_generated_offset)}}
diff --git a/templates/header.html b/templates/header.html index 6beb4f4..24dc11d 100644 --- a/templates/header.html +++ b/templates/header.html @@ -1,9 +1,3 @@ - - - {{site_name}} - - - Site: {{site_name}}
- Generated: {{ts_to_git_timestamp(ts=site_generated_ts, tz=site_generated_offset)}}
- Extra settings: {{extra.global_user_defined_vars}}
-
+Site: {{site_name}}
+Extra settings: {{extra.global_user_defined_vars}}
+
diff --git a/templates/repos.html b/templates/repos.html index 693da4f..fa0a79d 100644 --- a/templates/repos.html +++ b/templates/repos.html @@ -1,3 +1,7 @@ +{% extends "base.html" %} + +{% block content %} {% for repo in repos | sort(attribute="name") -%} {{ repo.name }} ({{repo.metadata.website}}) [{{repo.metadata.attributes | get(key="some_extra_thing", default="")}}] ({{ts_to_date(ts=repo.history[0].ts_utc, tz=repo.history[0].ts_offset)}})
{% endfor -%} +{% endblock content %} diff --git a/templates/summary.html b/templates/summary.html index dcc8b6a..4d81e08 100644 --- a/templates/summary.html +++ b/templates/summary.html @@ -1,3 +1,6 @@ +{% extends "base.html" %} + +{% block content %}
File{{file.size}}
@@ -77,3 +80,4 @@ {% endfor -%}
Commit ID
+{% endblock content %} diff --git a/templates/tag.html b/templates/tag.html index df2ff89..c21f6b9 100644 --- a/templates/tag.html +++ b/templates/tag.html @@ -1,3 +1,6 @@ +{% extends "base.html" %} + +{% block content %} branch: {{tag.ref_name}}
hash: {{tag.full_hash}} ({{tag.short_hash}})
author: {{tag.author.name}}
@@ -9,3 +12,4 @@ summary: {{tag.summary}}
commit: {%- if commit -%}{{commit.full_hash}}
{{commit.message}}
{%-else-%}{{tag.tagged_id}}{%-endif-%}
+{% endblock content %}