diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 53eaa21..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -**/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 50970ec..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,804 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "aho-corasick" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bstr" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bytecount" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "chrono" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "chrono-tz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "parse-zoneinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "deunicode" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fnv" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "getrandom" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "globset" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "globwalk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "humansize" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ignore" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "kiln" -version = "0.1.0" -dependencies = [ - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rsass 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", - "tera 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lexical-core" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.2.69" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "log" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nom" -version = "5.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lexical-core 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "parse-zoneinfo" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pest_derive" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_generator 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pest_generator" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pest_meta" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pulldown-cmark" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "1.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.17" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rsass" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ryu" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slug" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "deunicode 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "static_assertions" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tera" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono-tz 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "globwalk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", - "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unic-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unic-char-range 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unic-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unic-ucd-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unic-ucd-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unic-char-property 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unic-char-range 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unic-ucd-version 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unic-common 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "walkdir" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -"checksum bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e" -"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" -"checksum chrono-tz 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e0e430fad0384e4defc3dc6b1223d1b886087a8bf9b7080e5ae027f73851ea15" -"checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" -"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -"checksum deunicode 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -"checksum globset 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" -"checksum globwalk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "178270263374052c40502e9f607134947de75302c1348d1a0e31db67c1691446" -"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" -"checksum ignore 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf60d063dbe6b75388eec66cfc07781167ae3d34a09e0c433e6c5de0511f7fb" -"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum lexical-core 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f86d66d380c9c5a685aaac7a11818bdfa1f733198dfd9ec09c70b762cd12ad6f" -"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" -"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" -"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" -"checksum num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum parse-zoneinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "feece9d0113b400182a7d00adcff81ccf29158c49c5abd11e2eed8589bf6ff07" -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -"checksum pest_generator 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" -"checksum pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" -"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -"checksum proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" -"checksum pulldown-cmark 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e142c3b8f49d2200605ee6ba0b1d757310e9e7a72afe78c36ee2ef67300ee00" -"checksum quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" -"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" -"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" -"checksum rsass 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c78e9b85b8816881cad9aa1142eec337020cfd79c6983e338811f5c521a80463" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" -"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" -"checksum serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" -"checksum serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd" -"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -"checksum slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" -"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" -"checksum syn 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7" -"checksum tera 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19d25bed9d2cf684de6ffdaa9ac35373739eeed0d6bef1de545bbe6cf571ad07" -"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" -"checksum ucd-trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" -"checksum unic-char-property 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -"checksum unic-char-range 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" -"checksum unic-common 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" -"checksum unic-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" -"checksum unic-ucd-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" -"checksum unic-ucd-version 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 23c5612..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "kiln" -description = "A simple static site generator" -version = "0.1.0" -authors = ["adnano "] -edition = "2018" -license = "BlueOak-1.0.0" - -[dependencies] -chrono = "0.4" -lazy_static = "1.4" -pulldown-cmark = { version = "0.7", default-features = false } -regex = "1.3" -rsass = "0.13" -serde = "1.0" -serde_derive = "1.0" -tera = "1.2" -toml = "0.5" diff --git a/README.md b/README.md index 7500676..4fa5294 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ # kiln -A simple static site generator built in Rust. +A simple static site generator for Gemini. ## Features -- Zero-config +- Zero configuration - Simple and fast -- [Tera] templates -- [Sass] stylesheets -- Markdown +- Gemini support +- Go templates ## Usage @@ -16,5 +15,44 @@ A simple static site generator built in Rust. kiln ``` -[Tera]: https://tera.netlify.com -[Sass]: https://sass-lang.com +## Directory Structure + +A kiln site is organized in the following way: + +``` +src/ Site source +templates/ Templates + page.gmi Page template + section.gmi Section template +dst/ Site destination +``` + +Running `kiln` takes the contents in `src`, runs them through the templates in +`templates`, and outputs the result to `dst`. + +## Pages + +Page templates are provided with the following information: + +- `Title`: The title parsed from the first heading in the file +- `Date`: The date parsed from the filename (e.g. `2020-09-22-hello-world.gmi`) +- `Path`: Relative path to the page +- `Permalink`: Permalink to the page +- `Content`: The contents of the file (including the title) + +## Sections + +Section templates are provided with the following information: + +- `Path`: Relative path to the section +- `Permalink`: Permalink to the section +- `Pages`: The pages in this section + +## Templates + +Templates are located in the `templates` directory. + +There are currently two supported templates: + +- `page.gmi`: The template used for pages +- `section.gmi`: The template used for sections diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..26d486e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module kiln + +go 1.15 diff --git a/index.go b/index.go new file mode 100644 index 0000000..d344914 --- /dev/null +++ b/index.go @@ -0,0 +1,80 @@ +package main + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +type Index struct { + Files map[string][]byte + Dirs map[string][]string +} + +func NewIndex() *Index { + return &Index{ + Files: map[string][]byte{}, + Dirs: map[string][]string{}, + } +} + +// ReadDir reads a directory and indexes the files and directories within it. +func (index *Index) ReadDir(srcDir string, dstDir string) error { + entries, err := ioutil.ReadDir(srcDir) + if err != nil { + return err + } + + for _, entry := range entries { + name := entry.Name() + srcPath := filepath.Join(srcDir, name) + dstPath := filepath.Join(dstDir, name) + + if entry.IsDir() { + index.Dirs[dstPath] = []string{} + index.ReadDir(srcPath, dstPath) + } else { + content, err := ioutil.ReadFile(srcPath) + if err != nil { + return err + } + + index.Files[dstPath] = content + index.Dirs[dstDir] = append(index.Dirs[dstDir], dstPath) + } + } + return nil +} + +// Write writes the contents of the Index to the provided destination directory. +func (index *Index) Write(dstDir string) error { + // Empty the destination directory + if err := os.RemoveAll(dstDir); err != nil { + return err + } + if err := os.MkdirAll(dstDir, 0755); err != nil { + return err + } + + for path := range index.Files { + // Create any parent directories + if dir := filepath.Dir(path); dir != "." { + dstPath := filepath.Join(dstDir, dir) + if err := os.MkdirAll(dstPath, 0755); err != nil { + return err + } + } + + // Write the file + dstPath := filepath.Join(dstDir, path) + f, err := os.Create(dstPath) + if err != nil { + return err + } + data := index.Files[path] + if _, err := f.Write(data); err != nil { + return err + } + } + return nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..17dedf7 --- /dev/null +++ b/main.go @@ -0,0 +1,85 @@ +package main + +import ( + "log" + "time" +) + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} + +func run() error { + index := NewIndex() + if err := index.ReadDir("src", ""); err != nil { + return err + } + manipulator, err := NewManipulator() + if err != nil { + return err + } + if err := manipulator.Manipulate(index); err != nil { + return err + } + + if err := index.Write("dst"); err != nil { + return err + } + return nil +} + +// Page represents a page. +type Page struct { + // The path to this page. + Path string + // The permalink to this page. + Permalink string + // The title of this page, parsed from the Gemini contents. + Title string + // The date of the page. Dates are specified in the filename. + // Ex: 2020-09-22-hello-world.gmi + Date time.Time + // The content of this page. + Content string +} + +func NewPage(path string, content string) *Page { + // TODO: Parse date from path name + permalink := "/" + path + return &Page{ + Path: path, + Permalink: permalink, + Content: content, + } +} + +// Section represents a section (i.e., a directory). +type Section struct { + // The path to this section. + Path string + // The permalink to this section. + Permalink string + // The pages in this section. + Pages []*Page +} + +// NewSection returns a new Section with the given path. +func NewSection(path string) *Section { + var permalink string + if path == "" { + permalink = "/" + } else { + permalink = "/" + path + "/" + } + return &Section{ + Path: path, + Permalink: permalink, + } +} + +// Sort sorts pages by date. +func (s *Section) Sort() { + // TODO: Implement this +} diff --git a/manipulate.go b/manipulate.go new file mode 100644 index 0000000..11ada01 --- /dev/null +++ b/manipulate.go @@ -0,0 +1,66 @@ +package main + +import ( + "path/filepath" + "strings" + "text/template" +) + +type Manipulator struct { + Pages map[string]*Page + + // Templates + Templates *template.Template +} + +func NewManipulator() (*Manipulator, error) { + tmpl, err := template.New("templates").ParseGlob("templates/*.gmi") + if err != nil { + return nil, err + } + return &Manipulator{ + Pages: map[string]*Page{}, + Templates: tmpl, + }, nil +} + +func (m *Manipulator) Manipulate(index *Index) error { + for path := range index.Files { + switch filepath.Ext(path) { + case ".gmi": + // Gather page data + content := string(index.Files[path]) + page := NewPage(path, content) + + builder := &strings.Builder{} + tmpl := m.Templates.Lookup("page.gmi") + if err := tmpl.Execute(builder, page); err != nil { + return err + } + page.Content = builder.String() + m.Pages[path] = page + index.Files[path] = []byte(page.Content) + } + } + + for dir := range index.Dirs { + // Load section data + section := NewSection(dir) + for _, path := range index.Dirs[dir] { + switch filepath.Ext(path) { + case ".gmi": + section.Pages = append(section.Pages, m.Pages[path]) + } + } + + dstPath := filepath.Join(dir, "index.gmi") + builder := &strings.Builder{} + tmpl := m.Templates.Lookup("section.gmi") + if err := tmpl.Execute(builder, section); err != nil { + return err + } + index.Files[dstPath] = []byte(builder.String()) + } + + return nil +} diff --git a/src/index.rs b/src/index.rs deleted file mode 100644 index dcbaf2e..0000000 --- a/src/index.rs +++ /dev/null @@ -1,89 +0,0 @@ -use std::io::Result; -use std::path::{Path, PathBuf}; -use std::{env, fs, ops, slice}; - -#[derive(Default)] -pub struct Index(Vec<(PathBuf, Vec)>); - -impl Index { - pub fn from(dir: impl AsRef) -> Result { - let input = dir.as_ref(); - let output = Path::new(""); - let mut index = Index::default(); - IndexDir::new(input, output, &mut index).index()?; - Ok(index) - } - - pub fn insert(&mut self, key: PathBuf, val: Vec) { - self.0.push((key, val)); - } - - pub fn remove(&mut self, index: usize) { - self.0.remove(index); - } - - pub fn iter_mut(&mut self) -> slice::IterMut<(PathBuf, Vec)> { - self.0.iter_mut() - } - - pub fn write(&self, output: impl AsRef) -> Result<()> { - let output = output.as_ref(); - if output.exists() { - // empty the output directory - fs::remove_dir_all(output)?; - } - fs::create_dir_all(output)?; - env::set_current_dir(output)?; - for (path, contents) in &self.0 { - if let Some(parent) = path.parent() { - fs::create_dir_all(&parent)?; - } - fs::write(&path, &contents)?; - } - Ok(()) - } -} - -impl ops::Index for Index { - type Output = (PathBuf, Vec); - fn index(&self, i: usize) -> &(PathBuf, Vec) { - &self.0[i] - } -} - -impl ops::IndexMut for Index { - fn index_mut(&mut self, i: usize) -> &mut (PathBuf, Vec) { - &mut self.0[i] - } -} - -struct IndexDir<'a> { - input: &'a Path, - output: &'a Path, - index: &'a mut Index, -} - -impl<'a> IndexDir<'a> { - fn new(input: &'a Path, output: &'a Path, index: &'a mut Index) -> IndexDir<'a> { - IndexDir { - input, - output, - index, - } - } - - fn index(self) -> Result<()> { - for entry in fs::read_dir(self.input)? { - let path = entry?.path(); - let mut output = self.output.to_path_buf(); - output.push(path.file_name().unwrap()); - if path.is_file() { - let contents = fs::read(&path)?; - self.index.insert(output, contents); - } else if path.is_dir() { - IndexDir::new(&path, &output, self.index).index()?; - } - } - Ok(()) - } -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index f7b7db9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -mod index; -mod manipulate; -mod page; -mod result; -mod section; - -use std::error::Error; - -use index::Index; -use manipulate::manipulate; - -fn main() -> Result> { - let mut index = Index::from("src")?; - manipulate(&mut index)?; - index.write("public")?; - - Ok(()) -} diff --git a/src/manipulate.rs b/src/manipulate.rs deleted file mode 100644 index 5519563..0000000 --- a/src/manipulate.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::ffi::OsStr; - -use tera::{Context, Result, Template, Tera}; - -use crate::index::Index; -use crate::page::Page; -use crate::section::Section; - -pub fn manipulate(index: &mut Index) -> Result<()> { - Manipulater::new(index)?.manipulate() -} - -struct Manipulater<'a> { - index: &'a mut Index, - pages: Vec<(usize, Page)>, - sections: Vec, - templates: Vec, - ignored: Vec, - tera: Tera, -} - -impl<'a> Manipulater<'a> { - fn new(index: &'a mut Index) -> Result> { - Ok(Manipulater { - index, - pages: Vec::new(), - sections: Vec::new(), - templates: Vec::new(), - ignored: Vec::new(), - tera: Tera::default(), - }) - } - - fn manipulate(mut self) -> Result<()> { - for (i, (path, contents)) in self.index.iter_mut().enumerate() { - match path.extension().and_then(OsStr::to_str) { - Some("tera") => { - path.set_extension("html"); - let filename = path.file_name().unwrap(); - if filename == "index.html" { - path.pop(); - self.sections.push(i); - } else { - if filename.to_str().map_or(false, |p| p.starts_with('_')) { - self.ignored.push(i); - } - path.set_extension(""); - } - let name = path.to_string_lossy(); - let contents = String::from_utf8_lossy(&contents).to_string(); - let template = Template::new(&name, None, &contents)?; - self.tera.templates.insert(name.to_string(), template); - self.templates.push(i); - } - Some("md") => { - path.set_extension("html"); - let page = Page::from(path.to_path_buf(), contents); - if !page.draft { - self.pages.push((i, page)); - } - } - Some("scss") => { - path.set_extension("css"); - match rsass::compile_scss(&contents, Default::default()) { - Ok(css) => *contents = css, - Err(e) => { - self.ignored.push(i); - eprintln!("Warning: Failed to parse stylesheet `{}`: {}", path.display(), e) - } - } - } - _ => {} - } - } - - self.tera.build_inheritance_chains()?; - - for i in self.templates { - if !self.ignored.contains(&i) && !self.sections.contains(&i) { - let entry = &mut self.index[i]; - entry.1 = self - .tera - .render(&entry.0.to_string_lossy(), &Context::new())? - .into_bytes(); - entry.0.set_extension("html"); - } - } - - for i in self.sections { - let entry = &mut self.index[i]; - let dir = &entry.0; - let mut section = Section::new(dir.to_path_buf()); - section.pages = self - .pages - .iter_mut() - .map(|(_, page)| page) - .filter(|page| page.input.parent() == Some(&dir)) - .collect(); - section.sort(); - let mut context = Context::new(); - context.insert("section", §ion); - let contents = self.tera.render(&dir.to_string_lossy(), &context)?; - entry.0.push("index.html"); - entry.1 = contents.into_bytes(); - } - - for (i, page) in self.pages { - let entry = &mut self.index[i]; - if self.tera.templates.contains_key("_page") { - let mut context = Context::new(); - context.insert("page", &page); - let content = self.tera.render("_page", &context)?; - let path = page.output.unwrap_or(page.input); - (*entry) = (path, content.into_bytes()); - } else { - let path = page.output.unwrap_or(page.input); - (*entry) = (path, page.content.into_bytes()); - } - } - - for (count, index) in self.ignored.iter().enumerate() { - self.index.remove(index - count); - } - - Ok(()) - } -} diff --git a/src/page.rs b/src/page.rs deleted file mode 100644 index c712e8c..0000000 --- a/src/page.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::path::PathBuf; - -use chrono::NaiveDateTime; -use lazy_static::lazy_static; -use pulldown_cmark::{html, Parser}; -use regex::Regex; -use serde::{Deserialize, Deserializer, Serializer}; -use serde_derive::{Deserialize, Serialize}; - -#[derive(Clone, Default, Deserialize, Serialize)] -#[serde(default)] -pub struct Page { - pub permalink: String, - pub title: String, - pub author: String, - pub description: String, - pub draft: bool, - #[serde(deserialize_with = "parse_datetime", serialize_with = "date_to_string")] - pub date: Option, - - #[serde(skip_deserializing)] - pub content: String, - #[serde(skip_deserializing)] - pub prev: Option>, - #[serde(skip_deserializing)] - pub next: Option>, - - #[serde(skip)] - pub input: PathBuf, - #[serde(skip)] - pub output: Option, -} - -impl Page { - pub fn from(path: PathBuf, content: &[u8]) -> Page { - let content = String::from_utf8_lossy(&content); - if !FRONTMATTER_REGEX.is_match(&content) { - return Page { - content: markdown_to_html(&content), - input: path, - ..Default::default() - }; - } - - let captures = FRONTMATTER_REGEX.captures(&content).unwrap(); - - let mut page: Page = match toml::from_str(&captures[1]) { - Ok(page) => page, - Err(e) => { - eprintln!("failed to parse frontmatter in `{}`: {}", path.display(), e); - Page::default() - } - }; - - if page.permalink == "" { - page.permalink = "/".to_string() + &path.with_extension("").to_string_lossy(); - } else { - page.output = Some(PathBuf::from(page.permalink.trim_start_matches('/'))); - } - - page.content = markdown_to_html(&captures[2]); - page.input = path; - page - } -} - -lazy_static! { - static ref FRONTMATTER_REGEX: Regex = - Regex::new(r"^[[:space:]]*\-\-\-\r?\n((?s).*?(?-s))\-\-\-\r?\n?((?s).*(?-s))$").unwrap(); -} - -fn markdown_to_html(content: &str) -> String { - let mut result = String::new(); - html::push_html(&mut result, Parser::new(content)); - result -} - -fn parse_datetime<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let date = if let Ok(date) = toml::value::Datetime::deserialize(deserializer) { - let date = date.to_string(); - if date.contains('T') { - chrono::DateTime::parse_from_rfc3339(&date) - .ok() - .map(|date| date.naive_local()) - } else { - chrono::NaiveDate::parse_from_str(&date, "%Y-%m-%d") - .ok() - .map(|date| date.and_hms(0, 0, 0)) - } - } else { - None - }; - Ok(date) -} - -fn date_to_string(date: &Option, serializer: S) -> Result -where - S: Serializer, -{ - if let Some(date) = date { - serializer.serialize_some(&date.format("%Y-%m-%dT%H:%M:%S").to_string()) - } else { - serializer.serialize_none() - } -} diff --git a/src/section.rs b/src/section.rs deleted file mode 100644 index 8c0d4e6..0000000 --- a/src/section.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::cmp::Ordering; -use std::path::Path; - -use serde_derive::Serialize; - -use crate::page::Page; - -#[derive(Serialize)] -pub struct Section<'a> { - pub pages: Vec<&'a mut Page>, - pub permalink: String, -} - -impl<'a> Section<'a> { - pub fn new(path: impl AsRef) -> Section<'a> { - Section { - pages: Vec::new(), - permalink: match path.as_ref().to_string_lossy().as_ref() { - "" => "/".to_string(), - s => "/".to_string() + s + "/", - }, - } - } - - pub fn sort(&mut self) { - self.pages.sort_by(|x, y| match (x.date, y.date) { - (Some(x), Some(y)) => y.cmp(&x), - _ => Ordering::Equal, - }); - - for i in (0..self.pages.len()).rev() { - let prev = self.pages.get(i + 1).map(|p| Box::new((*p).clone())); - let next = self.pages.get(i - 1).map(|p| Box::new((*p).clone())); - let page = &mut self.pages[i]; - page.prev = prev; - page.next = next; - } - } -}