diff --git a/.gitignore b/.gitignore index 99fac5fe..b4f2bd6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ target .idea/ -site -theme +test_site/public diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..79ef3140 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: rust +cache: cargo + +rust: + - nightly + - beta + - stable + +notifications: + email: false diff --git a/Cargo.lock b/Cargo.lock index 78e0b8c9..b76548a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,25 +1,33 @@ [root] name = "gutenberg" -version = "0.1.0" +version = "0.0.1" dependencies = [ - "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mount 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tera 0.7.2 (git+https://github.com/Keats/tera?branch=next)", - "toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", + "slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntect 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tera 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -30,6 +38,16 @@ name = "ansi_term" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "atty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "backtrace" version = "0.3.0" @@ -39,8 +57,8 @@ dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -49,8 +67,8 @@ name = "backtrace-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -59,14 +77,14 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "0.5.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -89,6 +107,11 @@ name = "byteorder" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytes" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.0" @@ -99,7 +122,7 @@ name = "chrono" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -108,31 +131,39 @@ name = "chrono" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.20.5" +version = "2.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "conduit-mime-types" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -149,20 +180,37 @@ name = "dtoa" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "error" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "filetime" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "flate2" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -171,9 +219,27 @@ name = "fnv" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fsevent" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fsevent-sys" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gcc" -version = "0.3.43" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -187,10 +253,34 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "humansize" -version = "1.0.0" +name = "httparse" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "humansize" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hyper" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.1.0" @@ -201,6 +291,40 @@ dependencies = [ "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "inotify" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "iovec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "iron" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.3.1" @@ -216,13 +340,28 @@ dependencies = [ ] [[package]] -name = "lazy_static" +name = "language-tags" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazy_static" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" -version = "0.2.20" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -235,7 +374,15 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -243,50 +390,165 @@ name = "miniz-sys" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "modifier" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mount" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sequence_trie 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "notify" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num_cpus" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "onig" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "onig_sys 61.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -295,8 +557,8 @@ name = "onig_sys" version = "61.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -312,30 +574,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "plist" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "plugin" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pulldown-cmark" -version = "0.0.8" +version = "0.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.16" @@ -346,7 +624,7 @@ name = "regex" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -360,14 +638,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-demangle" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "same-file" version = "0.1.3" @@ -377,6 +663,16 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "semver" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sequence_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "0.8.23" @@ -384,38 +680,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "0.9.8" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_codegen_internals" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "0.9.8" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen_internals 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha1" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "slug" version = "0.1.2" @@ -424,6 +735,17 @@ dependencies = [ "unidecode 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "staticfile" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mount 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "strsim" version = "0.6.0" @@ -431,17 +753,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.11.6" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synom" -version = "0.11.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -449,36 +771,44 @@ dependencies = [ [[package]] name = "syntect" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bincode 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "onig 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "plist 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "plist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempdir" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tera" -version = "0.7.2" -source = "git+https://github.com/Keats/tera?branch=next#cd13a801b61e8c11ef829943bd3f34ae7d9d4bab" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humansize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "humansize 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "pest 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -489,7 +819,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -499,7 +829,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -517,17 +847,43 @@ version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typemap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unsafe-any 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -571,6 +927,14 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unsafe-any" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "url" version = "1.4.0" @@ -587,7 +951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vec_map" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -595,6 +959,15 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "walkdir" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "walkdir" version = "1.0.7" @@ -615,9 +988,33 @@ name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ws" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "xml-rs" -version = "0.3.8" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -629,71 +1026,111 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2" +"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" +"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" "checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80" "checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842" "checksum bincode 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "55eb0b7fd108527b0c77860f75eca70214e11a8b4c6ef05148c54c05a25d48ad" -"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" +"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" +"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" "checksum chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "158b0bd7d75cbb6bf9c25967a48a2e9f77da95876b858eadfabaa99cd069de6e" -"checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758" -"checksum cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a3a6805df695087e7c1bcd9a82e03ad6fb864c8e67ac41b1348229ce5b7f0407" +"checksum clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "74a80f603221c9cd9aa27a28f52af452850051598537bb6b359c38a7d61e5cda" +"checksum cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "e1acc68a3f714627af38f9f5d09706a28584ba60dfe2cca68f40bf779f941b25" +"checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" -"checksum error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e92ecf0a508c8e074c0e6fa8fe0fa38414848ad4dfc4db6f74c5e9753330b248" +"checksum error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e606f14042bb87cc02ef6a14db6c90ab92ed6f62d87e69377bc759fd7987cc" +"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" +"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" "checksum flate2 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "d4e4d0c15ef829cbc1b7cda651746be19cceeb238be7b1049227b14891df9e25" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" -"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d" +"checksum fsevent 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfe593ebcfc76884138b25426999890b10da8e6a46d01b499d7c54c604672c38" +"checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" +"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum humansize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b963e0c0a5149e12a9cab4d889404e4935e3484db7c4d9681e8bbdbcb9dfd80" +"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" +"checksum humansize 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92d211e6e70b05749dce515b47684f29a3c8c38bbbb21c50b30aff9eca1b0bd3" +"checksum hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "43a15e3273b2133aaac0150478ab443fb89f15c3de41d8d93d8f3bb14bf560f6" "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" +"checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" +"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be" +"checksum iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2440ae846e7a8c7f9b401db8f6e31b4ea5e7d3688b91761337da7e054520c75b" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" -"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5" +"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +"checksum lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc" +"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" +"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" +"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" +"checksum mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5514f038123342d01ee5f95129e4ef1e0470c93bc29edf058a46f9ee3ba6737e" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" -"checksum num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "bde7c03b09e7c6a301ee81f6ddf66d7a28ec305699e3d3b056d2fc56470e3120" -"checksum num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "fb24d9bfb3f222010df27995441ded1e954f8f69cd35021f6bef02ca9552fb92" -"checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c" -"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c" +"checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" +"checksum mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aa30e3753079b08ce3d75cf3b44783e36fe0e1f64065f65c1d894d1688fb2580" +"checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" +"checksum mount 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32245731923cd096899502fc4c4317cfd09f121e80e73f7f576cf3777a824256" +"checksum net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "18b9642ad6222faf5ce46f6966f59b71b9775ad5758c9e09fcf0a6c8061972b4" +"checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" +"checksum notify 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c628262cc8a99209596ec610dcf199d6876a10cfa22e355acc5936d6f1fa63" +"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" +"checksum num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "21e4df1098d1d797d27ef0c69c178c3fab64941559b290fcae198e0825c9c8b5" +"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" +"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" +"checksum num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18c392466409c50b87369414a2680c93e739aedeb498eb2bff7d7eb569744e2" "checksum onig 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5f586e53fa11ead18582956ea282c30baea1f25d3ee4c5fb85803f98727cb7" "checksum onig_sys 61.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a35f2cca300f0945538564da6052a449db55e65870cf0e9d443c1bce3d5dda47" "checksum pest 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e823a5967bb4cdc6d3e46f47baaf4ecfeae44413a642b74ad44e59e49c7f6" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum plist 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c201fd99d98798fce524e3ea5dd91883c7def66d9ef6467ce014a05329de0799" -"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41" -"checksum quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08de3f12e670f83f61e450443cbae34496a35b665691fd8e99b24ec662f75865" +"checksum plist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6ab9bef2781bcdac1baf3e29eb297344cd24263e22fd9436d3a21215b7d8aa" +"checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" +"checksum pulldown-cmark 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "b0b0f7b64fd9ff618da552df85b0d356a1487e5ef41df8b5727b0f73bd1215a1" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753" "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" -"checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc" -"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" +"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" +"checksum rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "684ce48436d6465300c9ea783b6b14c4361d6b8dcbb1375b486a69cc19e2dfb0" +"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" +"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" +"checksum sequence_trie 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c915714ca833b1d4d6b8f6a9d72a3ff632fe45b40a8d184ef79c81bec6327eed" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" -"checksum serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "204db0f2a5335be7313fd4453132fd56d2085aed081c673140a256772903e116" -"checksum serde_codegen_internals 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5113d5bd16471b183803b374f0fe4877ad9658b95e33b11f4a004d73aacc74a" -"checksum serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e88ec062a02cbebfd6276044a305d665a9919b497aa6acb2e12c070d1a50d32d" -"checksum serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6501ac6f8b74f9b1033f7ddf79a08edfa0f58d6f8e3190cb8dc97736afa257a8" +"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f" +"checksum serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d52006899f910528a10631e5b727973fe668f3228109d1707ccf5bad5490b6e" +"checksum serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f15ea24bd037b2d64646b4d934fa99c649be66e3f7b29fb595a5543b212b1452" +"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e" +"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" +"checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" +"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f5ff4b43cb07b86c5f9236c92714a22cdf9e5a27a7d85e398e2c9403328cb8" +"checksum staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31493480e073d52522a94cdf56269dd8eb05f99549effd1826b0271690608878" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e28da8d02d75d1e58b89258e0741128f0b0d8a8309fb5c627be0fbd37a76c67" -"checksum synom 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fece1853fb872b0acdc3ff88f37c474018e125ef81cd4cb8c0ca515746b62ed" -"checksum syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f79be04af68d5fa09e71b3274159a955a25f25a5cbfba9a6ff64139b71d848a" -"checksum tera 0.7.2 (git+https://github.com/Keats/tera?branch=next)" = "" +"checksum syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)" = "480c834701caba3548aa991e54677281be3a5414a9d09ddbdf4ed74a569a9d19" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum syntect 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6728e7e9bbd971751d17d39b0e38e3558c10b9fb32125441bb17c434a2754e7c" +"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" +"checksum tera 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f2ff83a1773a0482ddc961d0030b514f1848f592ae9612afb241e5eb455df75" "checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a" "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade" -"checksum toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08272367dd2e766db3fa38f068067d17aa6a9dfd7259af24b3927db92f1e0c2f" +"checksum toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3474f3c6eaf32eedb4f4a66a26214f020f828a6d96c37e38a35e3a379bbcfd11" +"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" +"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" "checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" "checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" "checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" @@ -701,12 +1138,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unidecode 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2adb95ee07cd579ed18131f2d9e7a17c25a4b76022935c7f2460d2bfae89fd2" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" +"checksum unsafe-any 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b351086021ebc264aea3ab4f94d61d889d98e5e9ec2d985d993f50133537fd3a" "checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" +"checksum vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum xml-rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "729264a98260c6469f7a7d7162baaf5869da5573f69ee08ccf3f3d9110cafe3b" +"checksum ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04614a58714f3fd4a8b1da4bcae9f031c532d35988c3d39627619248113f8be8" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7ec6c39eaa68382c8e31e35239402c0a9489d4141a8ceb0c716099a0b515b562" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/Cargo.toml b/Cargo.toml index 8963a220..5d74f60a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gutenberg" -version = "0.1.0" +version = "0.0.1" authors = ["Vincent Prouillet "] license = "MIT" readme = "README.md" @@ -9,8 +9,11 @@ homepage = "https://github.com/Keats/gutenberg" repository = "https://github.com/Keats/gutenberg" keywords = ["static", "site", "generator", "blog"] +[[bin]] +name = "gutenberg" + [dependencies] -error-chain = "0.9" +error-chain = "0.10" clap = "2.19" walkdir = "1" pulldown-cmark = "0" @@ -20,12 +23,20 @@ glob = "0.2" serde = "0.9" serde_json = "0.9" serde_derive = "0.9" -tera = { git = "https://github.com/Keats/tera", branch = "next" } +# tera = { path = "../tera" } +# tera = { git = "https://github.com/Keats/tera", branch = "reload" } +tera = "0.8" +slug = "0.1" syntect = "1" +chrono = "0.3" +toml = { version = "0.3", default-features = false, features = ["serde"]} -[dependencies.toml] -version = "0.3" -default-features = false -features = ["serde"] - +# Below is for the serve cmd +staticfile = "0.4" +iron = "0.5" +mount = "0.3" +notify = "4" +ws = "0.6" +[dev-dependencies] +tempdir = "0.3" diff --git a/README.md b/README.md index 4656336d..67f04810 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,12 @@ Split the file between front matter and content Parse the front matter markdown -> HTML for the content +### Themes +Gallery at https://tmtheme-editor.herokuapp.com/#!/editor/theme/Agola%20Dark + # TODO: +- find a way to add tests - syntax highlighting - pass a --config arg to the CLI to change from `config.toml` - have verbosity levels with a `verbosity` config variable with a default diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 85e6aadc..ec581194 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -1,87 +1,9 @@ -use std::collections::HashMap; -use std::fs::{create_dir, remove_dir_all}; -use std::path::Path; +use std::env; -use glob::glob; -use tera::{Tera, Context}; - -use config:: Config; -use errors::{Result, ResultExt}; -use page::{Page, order_pages}; -use utils::create_file; +use gutenberg::errors::Result; +use gutenberg::Site; - -pub fn build(config: Config) -> Result<()> { - if Path::new("public").exists() { - // Delete current `public` directory so we can start fresh - remove_dir_all("public").chain_err(|| "Couldn't delete `public` directory")?; - } - - let tera = Tera::new("templates/**/*").chain_err(|| "Error parsing templates")?; - - // ok we got all the pages HTML, time to write them down to disk - create_dir("public")?; - let public = Path::new("public"); - let mut pages: Vec = vec![]; - let mut sections: HashMap> = HashMap::new(); - - // First step: do all the articles and group article by sections - // hardcoded pattern so can't error - for entry in glob("content/**/*.md").unwrap().filter_map(|e| e.ok()) { - let path = entry.as_path(); - let mut page = Page::from_file(&path)?; - - let mut current_path = public.to_path_buf(); - - for section in &page.sections { - current_path.push(section); - - if !current_path.exists() { - create_dir(¤t_path)?; - } - - let str_path = current_path.as_path().to_string_lossy().to_string(); - sections.entry(str_path).or_insert_with(|| vec![page.clone()]); - } - - if let Some(ref url) = page.meta.url { - println!("URL: {:?}", url); - current_path.push(url); - } else { - println!("REMOVE ME IF YOU DONT SEE ME"); - current_path.push(&page.get_slug()); - } - - create_dir(¤t_path)?; - create_file(current_path.join("index.html"), &page.render_html(&tera, &config)?)?; - pages.push(page); - } - - for (section, pages) in sections { - render_section_index(section, pages, &tera, &config)?; - } - - // and now the index page - let mut context = Context::new(); - context.add("pages", &order_pages(pages)); - context.add("config", &config); - create_file(public.join("index.html"), &tera.render("index.html", &context)?)?; - - Ok(()) -} - - -fn render_section_index(section: String, pages: Vec, tera: &Tera, config: &Config) -> Result<()> { - let path = Path::new(§ion); - let mut context = Context::new(); - context.add("pages", &order_pages(pages)); - context.add("config", &config); - - let section_name = match path.components().into_iter().last() { - Some(s) => s.as_ref().to_string_lossy().to_string(), - None => bail!("Couldn't find a section name in {:?}", path.display()) - }; - - create_file(path.join("index.html"), &tera.render(&format!("{}.html", section_name), &context)?) +pub fn build() -> Result<()> { + Site::new(env::current_dir().unwrap())?.build() } diff --git a/src/cmd/init.rs b/src/cmd/init.rs index 6b69133d..210f06e2 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -2,8 +2,8 @@ use std::fs::{create_dir}; use std::path::Path; -use errors::Result; -use utils::create_file; +use gutenberg::errors::Result; +use gutenberg::create_file; const CONFIG: &'static str = r#" diff --git a/src/cmd/livereload.js b/src/cmd/livereload.js new file mode 100644 index 00000000..fd221102 --- /dev/null +++ b/src/cmd/livereload.js @@ -0,0 +1,1175 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o tag"); + return; + } + } + this.reloader = new Reloader(this.window, this.console, Timer); + this.connector = new Connector(this.options, this.WebSocket, Timer, { + connecting: (function(_this) { + return function() {}; + })(this), + socketConnected: (function(_this) { + return function() {}; + })(this), + connected: (function(_this) { + return function(protocol) { + var _base; + if (typeof (_base = _this.listeners).connect === "function") { + _base.connect(); + } + _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ")."); + return _this.analyze(); + }; + })(this), + error: (function(_this) { + return function(e) { + return console.log("" + e.message + "."); + }; + })(this), + disconnected: (function(_this) { + return function(reason, nextDelay) { + var _base; + if (typeof (_base = _this.listeners).disconnect === "function") { + _base.disconnect(); + } + switch (reason) { + case 'cannot-connect': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec."); + case 'broken': + return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec."); + case 'handshake-timeout': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec."); + case 'handshake-failed': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec."); + case 'manual': + break; + case 'error': + break; + default: + return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec."); + } + }; + })(this), + message: (function(_this) { + return function(message) { + switch (message.command) { + case 'reload': + return _this.performReload(message); + case 'alert': + return _this.performAlert(message); + } + }; + })(this) + }); + this.initialized = true; + } + + LiveReload.prototype.on = function(eventName, handler) { + return this.listeners[eventName] = handler; + }; + + LiveReload.prototype.log = function(message) { + return this.console.log("" + message); + }; + + LiveReload.prototype.performReload = function(message) { + var _ref, _ref1; + this.log("LiveReload received reload request: " + (JSON.stringify(message, null, 2))); + return this.reloader.reload(message.path, { + liveCSS: (_ref = message.liveCSS) != null ? _ref : true, + liveImg: (_ref1 = message.liveImg) != null ? _ref1 : true, + originalPath: message.originalPath || '', + overrideURL: message.overrideURL || '', + serverURL: "http://" + this.options.host + ":" + this.options.port + }); + }; + + LiveReload.prototype.performAlert = function(message) { + return alert(message.message); + }; + + LiveReload.prototype.shutDown = function() { + var _base; + if (!this.initialized) { + return; + } + this.connector.disconnect(); + this.log("LiveReload disconnected."); + return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0; + }; + + LiveReload.prototype.hasPlugin = function(identifier) { + return !!this.pluginIdentifiers[identifier]; + }; + + LiveReload.prototype.addPlugin = function(pluginClass) { + var plugin; + if (!this.initialized) { + return; + } + if (this.hasPlugin(pluginClass.identifier)) { + return; + } + this.pluginIdentifiers[pluginClass.identifier] = true; + plugin = new pluginClass(this.window, { + _livereload: this, + _reloader: this.reloader, + _connector: this.connector, + console: this.console, + Timer: Timer, + generateCacheBustUrl: (function(_this) { + return function(url) { + return _this.reloader.generateCacheBustUrl(url); + }; + })(this) + }); + this.plugins.push(plugin); + this.reloader.addPlugin(plugin); + }; + + LiveReload.prototype.analyze = function() { + var plugin, pluginData, pluginsData, _i, _len, _ref; + if (!this.initialized) { + return; + } + if (!(this.connector.protocol >= 7)) { + return; + } + pluginsData = {}; + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {}; + pluginData.version = plugin.constructor.version; + } + this.connector.sendCommand({ + command: 'info', + plugins: pluginsData, + url: this.window.location.href + }); + }; + + return LiveReload; + + })(); + +}).call(this); + +},{"./connector":1,"./options":5,"./reloader":7,"./timer":9}],5:[function(require,module,exports){ +(function() { + var Options; + + exports.Options = Options = (function() { + function Options() { + this.https = false; + this.host = null; + this.port = 35729; + this.snipver = null; + this.ext = null; + this.extver = null; + this.mindelay = 1000; + this.maxdelay = 60000; + this.handshake_timeout = 5000; + } + + Options.prototype.set = function(name, value) { + if (typeof value === 'undefined') { + return; + } + if (!isNaN(+value)) { + value = +value; + } + return this[name] = value; + }; + + return Options; + + })(); + + Options.extract = function(document) { + var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len1, _ref, _ref1; + _ref = document.getElementsByTagName('script'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + element = _ref[_i]; + if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) { + options = new Options(); + options.https = src.indexOf("https") === 0; + if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) { + options.host = mm[1]; + if (mm[2]) { + options.port = parseInt(mm[2], 10); + } + } + if (m[2]) { + _ref1 = m[2].split('&'); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + pair = _ref1[_j]; + if ((keyAndValue = pair.split('=')).length > 1) { + options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('=')); + } + } + } + return options; + } + } + return null; + }; + +}).call(this); + +},{}],6:[function(require,module,exports){ +(function() { + var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + exports.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6'; + + exports.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7'; + + exports.ProtocolError = ProtocolError = (function() { + function ProtocolError(reason, data) { + this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\"."; + } + + return ProtocolError; + + })(); + + exports.Parser = Parser = (function() { + function Parser(handlers) { + this.handlers = handlers; + this.reset(); + } + + Parser.prototype.reset = function() { + return this.protocol = 7; + }; + + Parser.prototype.process = function(data) { + var command, e, message, options, _ref; + try { + if (this.protocol == null) { + if (data.match(/^!!ver:([\d.]+)$/)) { + this.protocol = 6; + } else if (message = this._parseMessage(data, ['hello'])) { + if (!message.protocols.length) { + throw new ProtocolError("no protocols specified in handshake message"); + } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) { + this.protocol = 7; + } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) { + this.protocol = 6; + } else { + throw new ProtocolError("no supported protocols found"); + } + } + return this.handlers.connected(this.protocol); + } else if (this.protocol === 6) { + message = JSON.parse(data); + if (!message.length) { + throw new ProtocolError("protocol 6 messages must be arrays"); + } + command = message[0], options = message[1]; + if (command !== 'refresh') { + throw new ProtocolError("unknown protocol 6 command"); + } + return this.handlers.message({ + command: 'reload', + path: options.path, + liveCSS: (_ref = options.apply_css_live) != null ? _ref : true + }); + } else { + message = this._parseMessage(data, ['reload', 'alert']); + return this.handlers.message(message); + } + } catch (_error) { + e = _error; + if (e instanceof ProtocolError) { + return this.handlers.error(e); + } else { + throw e; + } + } + }; + + Parser.prototype._parseMessage = function(data, validCommands) { + var e, message, _ref; + try { + message = JSON.parse(data); + } catch (_error) { + e = _error; + throw new ProtocolError('unparsable JSON', data); + } + if (!message.command) { + throw new ProtocolError('missing "command" key', data); + } + if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) { + throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data); + } + return message; + }; + + return Parser; + + })(); + +}).call(this); + +},{}],7:[function(require,module,exports){ +(function() { + var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; + + splitUrl = function(url) { + var hash, index, params; + if ((index = url.indexOf('#')) >= 0) { + hash = url.slice(index); + url = url.slice(0, index); + } else { + hash = ''; + } + if ((index = url.indexOf('?')) >= 0) { + params = url.slice(index); + url = url.slice(0, index); + } else { + params = ''; + } + return { + url: url, + params: params, + hash: hash + }; + }; + + pathFromUrl = function(url) { + var path; + url = splitUrl(url).url; + if (url.indexOf('file://') === 0) { + path = url.replace(/^file:\/\/(localhost)?/, ''); + } else { + path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); + } + return decodeURIComponent(path); + }; + + pickBestMatch = function(path, objects, pathFunc) { + var bestMatch, object, score, _i, _len; + bestMatch = { + score: 0 + }; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + score = numberOfMatchingSegments(path, pathFunc(object)); + if (score > bestMatch.score) { + bestMatch = { + object: object, + score: score + }; + } + } + if (bestMatch.score > 0) { + return bestMatch; + } else { + return null; + } + }; + + numberOfMatchingSegments = function(path1, path2) { + var comps1, comps2, eqCount, len; + path1 = path1.replace(/^\/+/, '').toLowerCase(); + path2 = path2.replace(/^\/+/, '').toLowerCase(); + if (path1 === path2) { + return 10000; + } + comps1 = path1.split('/').reverse(); + comps2 = path2.split('/').reverse(); + len = Math.min(comps1.length, comps2.length); + eqCount = 0; + while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { + ++eqCount; + } + return eqCount; + }; + + pathsMatch = function(path1, path2) { + return numberOfMatchingSegments(path1, path2) > 0; + }; + + IMAGE_STYLES = [ + { + selector: 'background', + styleNames: ['backgroundImage'] + }, { + selector: 'border', + styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] + } + ]; + + exports.Reloader = Reloader = (function() { + function Reloader(window, console, Timer) { + this.window = window; + this.console = console; + this.Timer = Timer; + this.document = this.window.document; + this.importCacheWaitPeriod = 200; + this.plugins = []; + } + + Reloader.prototype.addPlugin = function(plugin) { + return this.plugins.push(plugin); + }; + + Reloader.prototype.analyze = function(callback) { + return results; + }; + + Reloader.prototype.reload = function(path, options) { + var plugin, _base, _i, _len, _ref; + this.options = options; + if ((_base = this.options).stylesheetReloadTimeout == null) { + _base.stylesheetReloadTimeout = 15000; + } + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + if (plugin.reload && plugin.reload(path, options)) { + return; + } + } + if (options.liveCSS) { + if (path.match(/\.css$/i)) { + if (this.reloadStylesheet(path)) { + return; + } + } + } + if (options.liveImg) { + if (path.match(/\.(jpe?g|png|gif)$/i)) { + this.reloadImages(path); + return; + } + } + return this.reloadPage(); + }; + + Reloader.prototype.reloadPage = function() { + return this.window.document.location.reload(); + }; + + Reloader.prototype.reloadImages = function(path) { + var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; + expando = this.generateUniqueString(); + _ref = this.document.images; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + img = _ref[_i]; + if (pathsMatch(path, pathFromUrl(img.src))) { + img.src = this.generateCacheBustUrl(img.src, expando); + } + } + if (this.document.querySelectorAll) { + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; + _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + img = _ref2[_k]; + this.reloadStyleImages(img.style, styleNames, path, expando); + } + } + } + if (this.document.styleSheets) { + _ref3 = this.document.styleSheets; + _results = []; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + styleSheet = _ref3[_l]; + _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); + } + return _results; + } + }; + + Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { + var e, rule, rules, styleNames, _i, _j, _len, _len1; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (!rules) { + return; + } + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + switch (rule.type) { + case CSSRule.IMPORT_RULE: + this.reloadStylesheetImages(rule.styleSheet, path, expando); + break; + case CSSRule.STYLE_RULE: + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + styleNames = IMAGE_STYLES[_j].styleNames; + this.reloadStyleImages(rule.style, styleNames, path, expando); + } + break; + case CSSRule.MEDIA_RULE: + this.reloadStylesheetImages(rule, path, expando); + } + } + }; + + Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { + var newValue, styleName, value, _i, _len; + for (_i = 0, _len = styleNames.length; _i < _len; _i++) { + styleName = styleNames[_i]; + value = style[styleName]; + if (typeof value === 'string') { + newValue = value.replace(/\burl\s*\(([^)]*)\)/, (function(_this) { + return function(match, src) { + if (pathsMatch(path, pathFromUrl(src))) { + return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; + } else { + return match; + } + }; + })(this)); + if (newValue !== value) { + style[styleName] = newValue; + } + } + } + }; + + Reloader.prototype.reloadStylesheet = function(path) { + var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1; + links = (function() { + var _i, _len, _ref, _results; + _ref = this.document.getElementsByTagName('link'); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (link.rel.match(/^stylesheet$/i) && !link.__LiveReload_pendingRemoval) { + _results.push(link); + } + } + return _results; + }).call(this); + imported = []; + _ref = this.document.getElementsByTagName('style'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + style = _ref[_i]; + if (style.sheet) { + this.collectImportedStylesheets(style, style.sheet, imported); + } + } + for (_j = 0, _len1 = links.length; _j < _len1; _j++) { + link = links[_j]; + this.collectImportedStylesheets(link, link.sheet, imported); + } + if (this.window.StyleFix && this.document.querySelectorAll) { + _ref1 = this.document.querySelectorAll('style[data-href]'); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + style = _ref1[_k]; + links.push(style); + } + } + this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); + match = pickBestMatch(path, links.concat(imported), (function(_this) { + return function(l) { + return pathFromUrl(_this.linkHref(l)); + }; + })(this)); + if (match) { + if (match.object.rule) { + this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); + this.reattachImportedRule(match.object); + } else { + this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); + this.reattachStylesheetLink(match.object); + } + } else { + this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); + for (_l = 0, _len3 = links.length; _l < _len3; _l++) { + link = links[_l]; + this.reattachStylesheetLink(link); + } + } + return true; + }; + + Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { + var e, index, rule, rules, _i, _len; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (rules && rules.length) { + for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { + rule = rules[index]; + switch (rule.type) { + case CSSRule.CHARSET_RULE: + continue; + case CSSRule.IMPORT_RULE: + result.push({ + link: link, + rule: rule, + index: index, + href: rule.href + }); + this.collectImportedStylesheets(link, rule.styleSheet, result); + break; + default: + break; + } + } + } + }; + + Reloader.prototype.waitUntilCssLoads = function(clone, func) { + var callbackExecuted, executeCallback, poll; + callbackExecuted = false; + executeCallback = (function(_this) { + return function() { + if (callbackExecuted) { + return; + } + callbackExecuted = true; + return func(); + }; + })(this); + clone.onload = (function(_this) { + return function() { + _this.console.log("LiveReload: the new stylesheet has finished loading"); + _this.knownToSupportCssOnLoad = true; + return executeCallback(); + }; + })(this); + if (!this.knownToSupportCssOnLoad) { + (poll = (function(_this) { + return function() { + if (clone.sheet) { + _this.console.log("LiveReload is polling until the new CSS finishes loading..."); + return executeCallback(); + } else { + return _this.Timer.start(50, poll); + } + }; + })(this))(); + } + return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); + }; + + Reloader.prototype.linkHref = function(link) { + return link.href || link.getAttribute('data-href'); + }; + + Reloader.prototype.reattachStylesheetLink = function(link) { + var clone, parent; + if (link.__LiveReload_pendingRemoval) { + return; + } + link.__LiveReload_pendingRemoval = true; + if (link.tagName === 'STYLE') { + clone = this.document.createElement('link'); + clone.rel = 'stylesheet'; + clone.media = link.media; + clone.disabled = link.disabled; + } else { + clone = link.cloneNode(false); + } + clone.href = this.generateCacheBustUrl(this.linkHref(link)); + parent = link.parentNode; + if (parent.lastChild === link) { + parent.appendChild(clone); + } else { + parent.insertBefore(clone, link.nextSibling); + } + return this.waitUntilCssLoads(clone, (function(_this) { + return function() { + var additionalWaitingTime; + if (/AppleWebKit/.test(navigator.userAgent)) { + additionalWaitingTime = 5; + } else { + additionalWaitingTime = 200; + } + return _this.Timer.start(additionalWaitingTime, function() { + var _ref; + if (!link.parentNode) { + return; + } + link.parentNode.removeChild(link); + clone.onreadystatechange = null; + return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; + }); + }; + })(this)); + }; + + Reloader.prototype.reattachImportedRule = function(_arg) { + var href, index, link, media, newRule, parent, rule, tempLink; + rule = _arg.rule, index = _arg.index, link = _arg.link; + parent = rule.parentStyleSheet; + href = this.generateCacheBustUrl(rule.href); + media = rule.media.length ? [].join.call(rule.media, ', ') : ''; + newRule = "@import url(\"" + href + "\") " + media + ";"; + rule.__LiveReload_newHref = href; + tempLink = this.document.createElement("link"); + tempLink.rel = 'stylesheet'; + tempLink.href = href; + tempLink.__LiveReload_pendingRemoval = true; + if (link.parentNode) { + link.parentNode.insertBefore(tempLink, link); + } + return this.Timer.start(this.importCacheWaitPeriod, (function(_this) { + return function() { + if (tempLink.parentNode) { + tempLink.parentNode.removeChild(tempLink); + } + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + parent.deleteRule(index + 1); + rule = parent.cssRules[index]; + rule.__LiveReload_newHref = href; + return _this.Timer.start(_this.importCacheWaitPeriod, function() { + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + return parent.deleteRule(index + 1); + }); + }; + })(this)); + }; + + Reloader.prototype.generateUniqueString = function() { + return 'livereload=' + Date.now(); + }; + + Reloader.prototype.generateCacheBustUrl = function(url, expando) { + var hash, oldParams, originalUrl, params, _ref; + if (expando == null) { + expando = this.generateUniqueString(); + } + _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; + if (this.options.overrideURL) { + if (url.indexOf(this.options.serverURL) < 0) { + originalUrl = url; + url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); + this.console.log("LiveReload is overriding source URL " + originalUrl + " with " + url); + } + } + params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { + return "" + sep + expando; + }); + if (params === oldParams) { + if (oldParams.length === 0) { + params = "?" + expando; + } else { + params = "" + oldParams + "&" + expando; + } + } + return url + params + hash; + }; + + return Reloader; + + })(); + +}).call(this); + +},{}],8:[function(require,module,exports){ +(function() { + var CustomEvents, LiveReload, k; + + CustomEvents = require('./customevents'); + + LiveReload = window.LiveReload = new (require('./livereload').LiveReload)(window); + + for (k in window) { + if (k.match(/^LiveReloadPlugin/)) { + LiveReload.addPlugin(window[k]); + } + } + + LiveReload.addPlugin(require('./less')); + + LiveReload.on('shutdown', function() { + return delete window.LiveReload; + }); + + LiveReload.on('connect', function() { + return CustomEvents.fire(document, 'LiveReloadConnect'); + }); + + LiveReload.on('disconnect', function() { + return CustomEvents.fire(document, 'LiveReloadDisconnect'); + }); + + CustomEvents.bind(document, 'LiveReloadShutDown', function() { + return LiveReload.shutDown(); + }); + +}).call(this); + +},{"./customevents":2,"./less":3,"./livereload":4}],9:[function(require,module,exports){ +(function() { + var Timer; + + exports.Timer = Timer = (function() { + function Timer(func) { + this.func = func; + this.running = false; + this.id = null; + this._handler = (function(_this) { + return function() { + _this.running = false; + _this.id = null; + return _this.func(); + }; + })(this); + } + + Timer.prototype.start = function(timeout) { + if (this.running) { + clearTimeout(this.id); + } + this.id = setTimeout(this._handler, timeout); + return this.running = true; + }; + + Timer.prototype.stop = function() { + if (this.running) { + clearTimeout(this.id); + this.running = false; + return this.id = null; + } + }; + + return Timer; + + })(); + + Timer.start = function(timeout, func) { + return setTimeout(func, timeout); + }; + +}).call(this); + +},{}]},{},[8]); diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 1af65e3f..e3c62b5e 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -1,5 +1,7 @@ mod init; mod build; +mod serve; pub use self::init::create_new_project; pub use self::build::build; +pub use self::serve::serve; diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs new file mode 100644 index 00000000..0c83639e --- /dev/null +++ b/src/cmd/serve.rs @@ -0,0 +1,245 @@ +use std::env; +use std::path::Path; +use std::sync::mpsc::channel; +use std::time::{Instant, Duration}; +use std::thread; + +use chrono::prelude::*; +use iron::{Iron, Request, IronResult, Response, status}; +use mount::Mount; +use staticfile::Static; +use notify::{Watcher, RecursiveMode, watcher}; +use ws::{WebSocket, Sender}; +use gutenberg::Site; +use gutenberg::errors::{Result}; + + +use ::report_elapsed_time; + + +#[derive(Debug, PartialEq)] +enum ChangeKind { + Content, + Templates, + StaticFiles, +} + +const LIVE_RELOAD: &'static str = include_str!("livereload.js"); + + +fn livereload_handler(_: &mut Request) -> IronResult { + Ok(Response::with((status::Ok, LIVE_RELOAD.to_string()))) +} + + +fn rebuild_done_handling(broadcaster: &Sender, res: Result<()>, reload_path: &str) { + match res { + Ok(_) => { + broadcaster.send(format!(r#" + {{ + "command": "reload", + "path": "{}", + "originalPath": "", + "liveCSS": true, + "liveImg": true, + "protocol": ["http://livereload.com/protocols/official-7"] + }}"#, reload_path) + ).unwrap(); + }, + Err(e) => { + println!("Failed to build the site"); + println!("Error: {}", e); + for e in e.iter().skip(1) { + println!("Reason: {}", e) + } + } + } +} + + +// Most of it taken from mdbook +pub fn serve(interface: &str, port: &str) -> Result<()> { + println!("Building site..."); + let start = Instant::now(); + let mut site = Site::new(env::current_dir().unwrap())?; + site.enable_live_reload(); + site.build()?; + report_elapsed_time(start); + + let address = format!("{}:{}", interface, port); + let ws_address = format!("{}:{}", interface, "1112"); + + // Start a webserver that serves the `public` directory + let mut mount = Mount::new(); + mount.mount("/", Static::new(Path::new("public/"))); + mount.mount("/livereload.js", livereload_handler); + // Starts with a _ to not trigger the unused lint + // we need to assign to a variable otherwise it will block + let _iron = Iron::new(mount).http(address.as_str()).unwrap(); + println!("Web server is available at http://{}", address); + + // The websocket for livereload + let ws_server = WebSocket::new(|_| { + |_| { + Ok(()) + } + }).unwrap(); + let broadcaster = ws_server.broadcaster(); + thread::spawn(move || { + ws_server.listen(&*ws_address).unwrap(); + }); + + // And finally watching/reacting on file changes + let (tx, rx) = channel(); + let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap(); + watcher.watch("content/", RecursiveMode::Recursive).unwrap(); + watcher.watch("static/", RecursiveMode::Recursive).unwrap(); + watcher.watch("templates/", RecursiveMode::Recursive).unwrap(); + let pwd = format!("{}", env::current_dir().unwrap().display()); + println!("Listening for changes in {}/{{content, static, templates}}", pwd); + println!("Press CTRL+C to stop\n"); + + use notify::DebouncedEvent::*; + + loop { + // See https://github.com/spf13/hugo/blob/master/commands/hugo.go + // for a more complete version of that + match rx.recv() { + Ok(event) => { + match event { + Create(path) | + Write(path) | + Remove(path) | + Rename(_, path) => { + if is_temp_file(&path) { + continue; + } + + println!("Change detected @ {}", Local::now().format("%Y-%m-%d %H:%M:%S").to_string()); + let start = Instant::now(); + match detect_change_kind(&pwd, &path) { + (ChangeKind::Content, _) => { + println!("-> Content changed {}", path.display()); + // Force refresh + rebuild_done_handling(&broadcaster, site.rebuild_after_content_change(), "/x.js"); + }, + (ChangeKind::Templates, _) => { + println!("-> Template changed {}", path.display()); + // Force refresh + rebuild_done_handling(&broadcaster, site.rebuild_after_template_change(), "/x.js"); + }, + (ChangeKind::StaticFiles, p) => { + println!("-> Static file changes detected {}", path.display()); + rebuild_done_handling(&broadcaster, site.copy_static_directory(), &p); + }, + }; + report_elapsed_time(start); + } + _ => {} + } + }, + Err(e) => println!("Watch error: {:?}", e), + }; + } +} + + +/// Returns whether the path we received corresponds to a temp file create +/// by an editor +fn is_temp_file(path: &Path) -> bool { + let ext = path.extension(); + match ext { + Some(ex) => match ex.to_str().unwrap() { + "swp" | "swx" | "tmp" | ".DS_STORE" => true, + // jetbrains IDE + x if x.ends_with("jb_old___") => true, + x if x.ends_with("jb_tmp___") => true, + x if x.ends_with("jb_bak___") => true, + // vim + x if x.ends_with('~') => true, + _ => { + if let Some(filename) = path.file_stem() { + // emacs + filename.to_str().unwrap().starts_with('#') + } else { + false + } + } + }, + None => { + path.ends_with(".DS_STORE") + }, + } +} + + +/// Detect what changed from the given path so we have an idea what needs +/// to be reloaded +fn detect_change_kind(pwd: &str, path: &Path) -> (ChangeKind, String) { + let path_str = format!("{}", path.display()) + .replace(pwd, "") + .replace("\\", "/"); + let change_kind = if path_str.starts_with("/templates") { + ChangeKind::Templates + } else if path_str.starts_with("/content") { + ChangeKind::Content + } else if path_str.starts_with("/static") { + ChangeKind::StaticFiles + } else { + panic!("Got a change in an unexpected path: {}", path_str); + }; + + (change_kind, path_str) +} + +#[cfg(test)] +mod tests { + use std::path::Path; + + use super::{is_temp_file, detect_change_kind, ChangeKind}; + + #[test] + fn test_can_recognize_temp_files() { + let testcases = vec![ + Path::new("hello.swp"), + Path::new("hello.swx"), + Path::new(".DS_STORE"), + Path::new("hello.tmp"), + Path::new("hello.html.__jb_old___"), + Path::new("hello.html.__jb_tmp___"), + Path::new("hello.html.__jb_bak___"), + Path::new("hello.html~"), + Path::new("#hello.html"), + ]; + + for t in testcases { + println!("{:?}", t.display()); + assert!(is_temp_file(&t)); + } + } + + #[test] + fn test_can_detect_kind_of_changes() { + let testcases = vec![ + ( + (ChangeKind::Templates, "/templates/hello.html".to_string()), + "/home/vincent/site", Path::new("/home/vincent/site/templates/hello.html") + ), + ( + (ChangeKind::StaticFiles, "/static/site.css".to_string()), + "/home/vincent/site", Path::new("/home/vincent/site/static/site.css") + ), + ( + (ChangeKind::Content, "/content/posts/hello.md".to_string()), + "/home/vincent/site", Path::new("/home/vincent/site/content/posts/hello.md") + ), + ]; + + for (expected, pwd, path) in testcases { + println!("{:?}", path.display()); + assert_eq!(expected, detect_change_kind(&pwd, &path)); + } + } + + +} diff --git a/src/config.rs b/src/config.rs index 96696dbd..045f4fd0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,19 +7,28 @@ use toml::{Value as Toml, self}; use errors::{Result, ResultExt}; -// TODO: disable tag(s)/category(ies) page generation + +// TO ADD: +// highlight code theme +// generate_tags_pages +// generate_categories_pages + #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct Config { /// Title of the site pub title: String, /// Base URL of the site pub base_url: String, + + /// Whether to highlight all code blocks found in markdown files. Defaults to false + pub highlight_code: Option, /// Description of the site pub description: Option, /// The language used in the site. Defaults to "en" pub language_code: Option, - /// Whether to disable RSS generation, defaults to None (== generate RSS) - pub disable_rss: Option, + /// Whether to generate RSS, defaults to false + pub generate_rss: Option, + /// All user params set in [extra] in the config pub extra: Option>, } @@ -32,10 +41,19 @@ impl Config { Ok(c) => c, Err(e) => bail!(e) }; + if config.language_code.is_none() { config.language_code = Some("en".to_string()); } + if config.highlight_code.is_none() { + config.highlight_code = Some(false); + } + + if config.generate_rss.is_none() { + config.generate_rss = Some(false); + } + Ok(config) } @@ -48,6 +66,44 @@ impl Config { Config::parse(&content) } + + /// Makes a url, taking into account that the base url might have a trailing slash + pub fn make_permalink(&self, path: &str) -> String { + if self.base_url.ends_with('/') { + format!("{}{}", self.base_url, path) + } else { + format!("{}/{}", self.base_url, path) + } + } +} + +impl Default for Config { + /// Exists for testing purposes + fn default() -> Config { + Config { + title: "".to_string(), + base_url: "http://a-website.com/".to_string(), + highlight_code: Some(true), + description: None, + language_code: Some("en".to_string()), + generate_rss: Some(false), + extra: None, + } + } +} + + +/// Get and parse the config. +/// If it doesn't succeed, exit +pub fn get_config(path: &Path) -> Config { + match Config::from_file(path.join("config.toml")) { + Ok(c) => c, + Err(e) => { + println!("Failed to load config.toml"); + println!("Error: {}", e); + ::std::process::exit(1); + } + } } diff --git a/src/errors.rs b/src/errors.rs index 5ff689c0..589c5fcb 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -2,8 +2,7 @@ use tera; use toml; error_chain! { - errors { - } + errors {} links { Tera(tera::Error, tera::ErrorKind); diff --git a/src/front_matter.rs b/src/front_matter.rs index 384d19c9..c9d77321 100644 --- a/src/front_matter.rs +++ b/src/front_matter.rs @@ -1,21 +1,32 @@ use std::collections::HashMap; - +use std::path::Path; use toml; use tera::Value; +use chrono::prelude::*; +use regex::Regex; -use errors::{Result}; +use errors::{Result, ResultExt}; + + +lazy_static! { + static ref PAGE_RE: Regex = Regex::new(r"^\n?\+\+\+\n((?s).*(?-s))\+\+\+\n?((?s).*(?-s))$").unwrap(); +} /// The front matter of every page #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct FrontMatter { - // of the page + // Mandatory fields + + /// <title> of the page pub title: String, /// Description that appears when linked, e.g. on twitter pub description: String, + // Optional stuff + /// Date if we want to order pages (ie blog post) pub date: Option<String>, /// The page slug. Will be used instead of the filename if present @@ -31,9 +42,9 @@ pub struct FrontMatter { pub draft: Option<bool>, /// Only one category allowed pub category: Option<String>, - /// Optional layout, if we want to specify which tpl to render for that page + /// Optional template, if we want to specify which template to render for that page #[serde(skip_serializing)] - pub layout: Option<String>, + pub template: Option<String>, /// Any extra parameter present in the front matter pub extra: Option<HashMap<String, Value>>, } @@ -44,7 +55,7 @@ impl FrontMatter { bail!("Front matter of file is missing"); } - let mut f: FrontMatter = match toml::from_str(toml) { + let f: FrontMatter = match toml::from_str(toml) { Ok(d) => d, Err(e) => bail!(e), }; @@ -63,129 +74,40 @@ impl FrontMatter { Ok(f) } -} - -#[cfg(test)] -mod tests { - use super::{FrontMatter}; - use tera::to_value; - - - #[test] - fn test_can_parse_a_valid_front_matter() { - let content = r#" -title = "Hello" -description = "hey there""#; - let res = FrontMatter::parse(content); - println!("{:?}", res); - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(res.title, "Hello".to_string()); - assert_eq!(res.description, "hey there".to_string()); - } - - #[test] - fn test_can_parse_tags() { - let content = r#" -title = "Hello" -description = "hey there" -slug = "hello-world" -tags = ["rust", "html"]"#; - let res = FrontMatter::parse(content); - assert!(res.is_ok()); - let res = res.unwrap(); - - assert_eq!(res.title, "Hello".to_string()); - assert_eq!(res.slug.unwrap(), "hello-world".to_string()); - assert_eq!(res.tags.unwrap(), ["rust".to_string(), "html".to_string()]); - } - - #[test] - fn test_can_parse_extra_attributes_in_frontmatter() { - let content = r#" -title = "Hello" -description = "hey there" -slug = "hello-world" - -[extra] -language = "en" -authors = ["Bob", "Alice"]"#; - let res = FrontMatter::parse(content); - assert!(res.is_ok()); - let res = res.unwrap(); - - assert_eq!(res.title, "Hello".to_string()); - assert_eq!(res.slug.unwrap(), "hello-world".to_string()); - let extra = res.extra.unwrap(); - assert_eq!(extra.get("language").unwrap(), &to_value("en").unwrap()); - assert_eq!( - extra.get("authors").unwrap(), - &to_value(["Bob".to_string(), "Alice".to_string()]).unwrap() - ); - } - - #[test] - fn test_is_ok_with_url_instead_of_slug() { - let content = r#" -title = "Hello" -description = "hey there" -url = "hello-world""#; - let res = FrontMatter::parse(content); - assert!(res.is_ok()); - let res = res.unwrap(); - assert!(res.slug.is_none()); - assert_eq!(res.url.unwrap(), "hello-world".to_string()); - } - - #[test] - fn test_errors_with_empty_front_matter() { - let content = r#" "#; - let res = FrontMatter::parse(content); - assert!(res.is_err()); - } - - #[test] - fn test_errors_with_invalid_front_matter() { - let content = r#"title = 1\n"#; - let res = FrontMatter::parse(content); - assert!(res.is_err()); - } - - #[test] - fn test_errors_with_missing_required_value_front_matter() { - let content = r#"title = """#; - let res = FrontMatter::parse(content); - assert!(res.is_err()); - } - - #[test] - fn test_errors_on_non_string_tag() { - let content = r#" -title = "Hello" -description = "hey there" -slug = "hello-world" -tags = ["rust", 1]"#; - let res = FrontMatter::parse(content); - assert!(res.is_err()); - } - - #[test] - fn test_errors_on_present_but_empty_slug() { - let content = r#" -title = "Hello" -description = "hey there" -slug = """#; - let res = FrontMatter::parse(content); - assert!(res.is_err()); - } - #[test] - fn test_errors_on_present_but_empty_url() { - let content = r#" -title = "Hello" -description = "hey there" -url = """#; - let res = FrontMatter::parse(content); - assert!(res.is_err()); + /// Converts the date in the front matter, which can be in 2 formats, into a NaiveDateTime + pub fn parse_date(&self) -> Option<NaiveDateTime> { + match self.date { + Some(ref d) => { + if d.contains('T') { + DateTime::parse_from_rfc3339(d).ok().and_then(|s| Some(s.naive_local())) + } else { + NaiveDate::parse_from_str(d, "%Y-%m-%d").ok().and_then(|s| Some(s.and_hms(0,0,0))) + } + }, + None => None, + } } } + + +/// Split a file between the front matter and its content +/// It will parse the front matter as well and returns any error encountered +/// TODO: add tests +pub fn split_content(file_path: &Path, content: &str) -> Result<(FrontMatter, String)> { + if !PAGE_RE.is_match(content) { + bail!("Couldn't find front matter in `{}`. Did you forget to add `+++`?", file_path.to_string_lossy()); + } + + // 2. extract the front matter and the content + let caps = PAGE_RE.captures(content).unwrap(); + // caps[0] is the full match + let front_matter = &caps[1]; + let content = &caps[2]; + + // 3. create our page, parse front matter and assign all of that + let meta = FrontMatter::parse(front_matter) + .chain_err(|| format!("Error when parsing front matter of file `{}`", file_path.to_string_lossy()))?; + + Ok((meta, content.to_string())) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..3c5fe81b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,34 @@ +#[macro_use] +extern crate error_chain; +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate serde_derive; +extern crate serde; +extern crate toml; +extern crate walkdir; +extern crate pulldown_cmark; +extern crate regex; +extern crate tera; +extern crate glob; +extern crate syntect; +extern crate slug; +extern crate chrono; +#[cfg(test)] +extern crate tempdir; + +mod utils; +mod config; +pub mod errors; +mod page; +mod front_matter; +mod site; +mod markdown; +mod section; + +pub use site::Site; +pub use config::Config; +pub use front_matter::{FrontMatter, split_content}; +pub use page::{Page}; +pub use section::{Section}; +pub use utils::create_file; diff --git a/src/main.rs b/src/main.rs index b71b4c80..b0237a04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,44 +2,31 @@ extern crate clap; #[macro_use] extern crate error_chain; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate serde_derive; -extern crate serde; -extern crate toml; -extern crate walkdir; -extern crate pulldown_cmark; -extern crate regex; -extern crate tera; -extern crate glob; -extern crate syntect; +extern crate gutenberg; +extern crate chrono; + +extern crate staticfile; +extern crate iron; +extern crate mount; +extern crate notify; +extern crate ws; -mod utils; -mod config; -mod errors; +use std::time::Instant; +use chrono::Duration; + mod cmd; -mod page; -mod front_matter; -use config::Config; +// Print the time elapsed rounded to 1 decimal +fn report_elapsed_time(instant: Instant) { + let duration_ms = Duration::from_std(instant.elapsed()).unwrap().num_milliseconds() as f64; - -// Get and parse the config. -// If it doesn't succeed, exit -fn get_config() -> Config { - match Config::from_file("config.toml") { - Ok(c) => c, - Err(e) => { - println!("Failed to load config.toml"); - println!("Error: {}", e); - for e in e.iter().skip(1) { - println!("Reason: {}", e) - } - ::std::process::exit(1); - } + if duration_ms < 1000.0 { + println!("Done in {}ms.\n", duration_ms); + } else { + let duration_sec = duration_ms / 1000.0; + println!("Done in {:.1}s.\n", ((duration_sec * 10.0).round() / 10.0)); } } @@ -57,6 +44,11 @@ fn main() { (@subcommand build => (about: "Builds the site") ) + (@subcommand serve => + (about: "Serve the site. Rebuild and reload on change automatically") + (@arg interface: "Interface to bind on (default to 127.0.0.1)") + (@arg port: "Which port to use (default to 1111)") + ) ).get_matches(); match matches.subcommand() { @@ -64,7 +56,6 @@ fn main() { match cmd::create_new_project(matches.value_of("name").unwrap()) { Ok(()) => { println!("Project created"); - println!("You will now need to set a theme in `config.toml`"); }, Err(e) => { println!("Error: {}", e); @@ -73,9 +64,11 @@ fn main() { }; }, ("build", Some(_)) => { - match cmd::build(get_config()) { + println!("Building site"); + let start = Instant::now(); + match cmd::build() { Ok(()) => { - println!("Project built."); + report_elapsed_time(start); }, Err(e) => { println!("Failed to build the site"); @@ -87,6 +80,20 @@ fn main() { }, }; }, + ("serve", Some(matches)) => { + let interface = matches.value_of("interface").unwrap_or("127.0.0.1"); + let port = matches.value_of("port").unwrap_or("1111"); + match cmd::serve(interface, port) { + Ok(()) => (), + Err(e) => { + println!("Error: {}", e); + for e in e.iter().skip(1) { + println!("Reason: {}", e) + } + ::std::process::exit(1); + }, + }; + }, _ => unreachable!(), } } diff --git a/src/markdown.rs b/src/markdown.rs new file mode 100644 index 00000000..8bc6d339 --- /dev/null +++ b/src/markdown.rs @@ -0,0 +1,150 @@ +use std::borrow::Cow::Owned; + +use pulldown_cmark as cmark; +use self::cmark::{Parser, Event, Tag}; + +use syntect::easy::HighlightLines; +use syntect::parsing::SyntaxSet; +use syntect::highlighting::ThemeSet; +use syntect::html::{start_coloured_html_snippet, styles_to_coloured_html, IncludeBackground}; + + +// We need to put those in a struct to impl Send and sync +struct Setup { + syntax_set: SyntaxSet, + theme_set: ThemeSet, +} + +unsafe impl Send for Setup {} +unsafe impl Sync for Setup {} + +lazy_static!{ + static ref SETUP: Setup = Setup { + syntax_set: SyntaxSet::load_defaults_newlines(), + theme_set: ThemeSet::load_defaults() + }; +} + + +struct CodeHighlightingParser<'a> { + // The block we're currently highlighting + highlighter: Option<HighlightLines<'a>>, + parser: Parser<'a>, +} + +impl<'a> CodeHighlightingParser<'a> { + pub fn new(parser: Parser<'a>) -> CodeHighlightingParser<'a> { + CodeHighlightingParser { + highlighter: None, + parser: parser, + } + } +} + +impl<'a> Iterator for CodeHighlightingParser<'a> { + type Item = Event<'a>; + + fn next(&mut self) -> Option<Event<'a>> { + // Not using pattern matching to reduce indentation levels + let next_opt = self.parser.next(); + if next_opt.is_none() { + return None; + } + + let item = next_opt.unwrap(); + // Below we just look for the start of a code block and highlight everything + // until we see the end of a code block. + // Everything else happens as normal in pulldown_cmark + match item { + Event::Text(text) => { + // if we are in the middle of a code block + if let Some(ref mut highlighter) = self.highlighter { + let highlighted = &highlighter.highlight(&text); + let html = styles_to_coloured_html(highlighted, IncludeBackground::Yes); + Some(Event::Html(Owned(html))) + } else { + Some(Event::Text(text)) + } + }, + Event::Start(Tag::CodeBlock(ref info)) => { + let syntax = info + .split(' ') + .next() + .and_then(|lang| SETUP.syntax_set.find_syntax_by_token(lang)) + .unwrap_or_else(|| SETUP.syntax_set.find_syntax_plain_text()); + self.highlighter = Some( + HighlightLines::new(syntax, &SETUP.theme_set.themes["base16-ocean.dark"]) + ); + let snippet = start_coloured_html_snippet(&SETUP.theme_set.themes["base16-ocean.dark"]); + Some(Event::Html(Owned(snippet))) + }, + Event::End(Tag::CodeBlock(_)) => { + // reset highlight and close the code block + self.highlighter = None; + Some(Event::Html(Owned("</pre>".to_owned()))) + }, + _ => Some(item) + } + + } +} + +pub fn markdown_to_html(content: &str, highlight_code: bool) -> String { + let mut html = String::new(); + if highlight_code { + let parser = CodeHighlightingParser::new(Parser::new(content)); + cmark::html::push_html(&mut html, parser); + } else { + let parser = Parser::new(content); + cmark::html::push_html(&mut html, parser); + }; + html +} + + +#[cfg(test)] +mod tests { + use super::{markdown_to_html}; + + #[test] + fn test_markdown_to_html_simple() { + let res = markdown_to_html("# hello", true); + assert_eq!(res, "<h1>hello</h1>\n"); + } + + #[test] + fn test_markdown_to_html_code_block_highlighting_off() { + let res = markdown_to_html("```\n$ gutenberg server\n```", false); + assert_eq!( + res, + "<pre><code>$ gutenberg server\n</code></pre>\n" + ); + } + + #[test] + fn test_markdown_to_html_code_block_no_lang() { + let res = markdown_to_html("```\n$ gutenberg server\n$ ping\n```", true); + assert_eq!( + res, + "<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">$ gutenberg server\n</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">$ ping\n</span></pre>" + ); + } + + #[test] + fn test_markdown_to_html_code_block_with_lang() { + let res = markdown_to_html("```python\nlist.append(1)\n```", true); + assert_eq!( + res, + "<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">list</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">.</span><span style=\"background-color:#2b303b;color:#bf616a;\">append</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">(</span><span style=\"background-color:#2b303b;color:#d08770;\">1</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">)</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">\n</span></pre>" + ); + } + #[test] + fn test_markdown_to_html_code_block_with_unknown_lang() { + let res = markdown_to_html("```yolo\nlist.append(1)\n```", true); + // defaults to plain text + assert_eq!( + res, + "<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">list.append(1)\n</span></pre>" + ); + } +} diff --git a/src/page.rs b/src/page.rs index 0efb2695..be7d6edf 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,45 +1,78 @@ /// A page, can be a blog post or a basic page -use std::fs::File; -use std::io::prelude::*; -use std::path::Path; +use std::cmp::Ordering; +use std::fs::{read_dir}; +use std::path::{Path, PathBuf}; use std::result::Result as StdResult; -use pulldown_cmark as cmark; -use regex::Regex; use tera::{Tera, Context}; use serde::ser::{SerializeStruct, self}; +use slug::slugify; use errors::{Result, ResultExt}; use config::Config; -use front_matter::{FrontMatter}; +use front_matter::{FrontMatter, split_content}; +use markdown::markdown_to_html; +use utils::{read_file, find_content_components}; -lazy_static! { - static ref PAGE_RE: Regex = Regex::new(r"^\n?\+\+\+\n((?s).*(?-s))\+\+\+\n((?s).*(?-s))$").unwrap(); + +/// Looks into the current folder for the path and see if there's anything that is not a .md +/// file. Those will be copied next to the rendered .html file +fn find_related_assets(path: &Path) -> Vec<PathBuf> { + let mut assets = vec![]; + + for entry in read_dir(path).unwrap().filter_map(|e| e.ok()) { + let entry_path = entry.path(); + if entry_path.is_file() { + match entry_path.extension() { + Some(e) => match e.to_str() { + Some("md") => continue, + _ => assets.push(entry_path.to_path_buf()), + }, + None => continue, + } + } + } + + assets } -#[derive(Clone, Debug, PartialEq, Deserialize)] +#[derive(Clone, Debug, PartialEq)] pub struct Page { - /// .md filepath, excluding the content/ bit - #[serde(skip_serializing)] - pub filepath: String, + /// The .md path + pub file_path: PathBuf, + /// The parent directory of the file. Is actually the grand parent directory + /// if it's an asset folder + pub parent_path: PathBuf, /// The name of the .md file - #[serde(skip_serializing)] - pub filename: String, - /// The directories above our .md file are called sections - /// for example a file at content/kb/solutions/blabla.md will have 2 sections: + pub file_name: String, + /// The directories above our .md file + /// for example a file at content/kb/solutions/blabla.md will have 2 components: /// `kb` and `solutions` - #[serde(skip_serializing)] - pub sections: Vec<String>, + pub components: Vec<String>, /// The actual content of the page, in markdown - #[serde(skip_serializing)] pub raw_content: String, + /// All the non-md files we found next to the .md file + pub assets: Vec<PathBuf>, /// The HTML rendered of the page pub content: String, /// The front matter meta-data pub meta: FrontMatter, + + /// The slug of that page. + /// First tries to find the slug in the meta and defaults to filename otherwise + pub slug: String, + /// The relative URL of the page + pub url: String, + /// The full URL for that page + pub permalink: String, + /// The summary for the article, defaults to empty string + /// When <!-- more --> is found in the text, will take the content up to that part + /// as summary + pub summary: String, + /// The previous page, by date pub previous: Option<Box<Page>>, /// The next page, by date @@ -50,227 +83,200 @@ pub struct Page { impl Page { pub fn new(meta: FrontMatter) -> Page { Page { - filepath: "".to_string(), - filename: "".to_string(), - sections: vec![], + file_path: PathBuf::new(), + parent_path: PathBuf::new(), + file_name: "".to_string(), + components: vec![], raw_content: "".to_string(), + assets: vec![], content: "".to_string(), + slug: "".to_string(), + url: "".to_string(), + permalink: "".to_string(), + summary: "".to_string(), meta: meta, previous: None, next: None, } } - /// Get the slug for the page. - /// First tries to find the slug in the meta and defaults to filename otherwise - pub fn get_slug(&self) -> String { - if let Some(ref slug) = self.meta.slug { - slug.to_string() - } else { - self.filename.clone() - } + /// Get word count and estimated reading time + pub fn get_reading_analytics(&self) -> (usize, usize) { + // Only works for latin language but good enough for a start + let word_count: usize = self.raw_content.split_whitespace().count(); + + // https://help.medium.com/hc/en-us/articles/214991667-Read-time + // 275 seems a bit too high though + (word_count, (word_count / 200)) } - // Parse a page given the content of the .md file - // Files without front matter or with invalid front matter are considered - // erroneous - pub fn parse(filepath: &str, content: &str) -> Result<Page> { + /// Parse a page given the content of the .md file + /// Files without front matter or with invalid front matter are considered + /// erroneous + pub fn parse(file_path: &Path, content: &str, config: &Config) -> Result<Page> { // 1. separate front matter from content - if !PAGE_RE.is_match(content) { - bail!("Couldn't find front matter in `{}`. Did you forget to add `+++`?", filepath); + let (meta, content) = split_content(file_path, content)?; + let mut page = Page::new(meta); + page.file_path = file_path.to_path_buf(); + page.parent_path = page.file_path.parent().unwrap().to_path_buf(); + page.raw_content = content; + + // We try to be smart about highlighting code as it can be time-consuming + // If the global config disables it, then we do nothing. However, + // if we see a code block in the content, we assume that this page needs + // to be highlighted. It could potentially have false positive if the content + // has ``` in it but that seems kind of unlikely + let should_highlight = if config.highlight_code.unwrap() { + page.raw_content.contains("```") + } else { + false + }; + + page.content = markdown_to_html(&page.raw_content, should_highlight); + + if page.raw_content.contains("<!-- more -->") { + page.summary = { + let summary = page.raw_content.splitn(2, "<!-- more -->").collect::<Vec<&str>>()[0]; + markdown_to_html(summary, should_highlight) + } } - // 2. extract the front matter and the content - let caps = PAGE_RE.captures(content).unwrap(); - // caps[0] is the full match - let front_matter = &caps[1]; - let content = &caps[2]; + let path = Path::new(file_path); + page.file_name = path.file_stem().unwrap().to_string_lossy().to_string(); - // 3. create our page, parse front matter and assign all of that - let meta = FrontMatter::parse(&front_matter) - .chain_err(|| format!("Error when parsing front matter of file `{}`", filepath))?; - - let mut page = Page::new(meta); - page.filepath = filepath.to_string(); - page.raw_content = content.to_string(); - page.content = { - let mut html = String::new(); - let parser = cmark::Parser::new(&page.raw_content); - cmark::html::push_html(&mut html, parser); - html + page.slug = { + if let Some(ref slug) = page.meta.slug { + slug.trim().to_string() + } else { + slugify(page.file_name.clone()) + } }; // 4. Find sections // Pages with custom urls exists outside of sections - if page.meta.url.is_none() { - let path = Path::new(filepath); - page.filename = path.file_stem().expect("Couldn't get filename").to_string_lossy().to_string(); + if let Some(ref u) = page.meta.url { + page.url = u.trim().to_string(); + } else { + page.components = find_content_components(&page.file_path); + if !page.components.is_empty() { + // If we have a folder with an asset, don't consider it as a component + if page.file_name == "index" { + page.components.pop(); + // also set parent_path to grandparent instead + page.parent_path = page.parent_path.parent().unwrap().to_path_buf(); + } - // find out if we have sections - for section in path.parent().unwrap().components() { - page.sections.push(section.as_ref().to_string_lossy().to_string()); - } - - // now the url - // We get it from a combination of sections + slug - if !page.sections.is_empty() { - page.meta.url = Some(format!("/{}/{}", page.sections.join("/"), page.get_slug())); + // Don't add a trailing slash to sections + page.url = format!("{}/{}", page.components.join("/"), page.slug); } else { - page.meta.url = Some(format!("/{}", page.get_slug())); - }; + page.url = page.slug.clone(); + } } + page.permalink = config.make_permalink(&page.url); + Ok(page) } - pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Page> { + /// Read and parse a .md file into a Page struct + pub fn from_file<P: AsRef<Path>>(path: P, config: &Config) -> Result<Page> { let path = path.as_ref(); + let content = read_file(path)?; + let mut page = Page::parse(path, &content, config)?; + page.assets = find_related_assets(path.parent().unwrap()); - let mut content = String::new(); - File::open(path) - .chain_err(|| format!("Failed to open '{:?}'", path.display()))? - .read_to_string(&mut content)?; + if !page.assets.is_empty() && page.file_name != "index" { + bail!("Page `{}` has assets but is not named index.md", path.display()); + } + + Ok(page) - // Remove the content string from name - // Maybe get a path as an arg instead and use strip_prefix? - Page::parse(&path.strip_prefix("content").unwrap().to_string_lossy(), &content) } - fn get_layout_name(&self) -> String { - match self.meta.layout { + /// Renders the page using the default layout, unless specified in front-matter + pub fn render_html(&self, tera: &Tera, config: &Config) -> Result<String> { + let tpl_name = match self.meta.template { Some(ref l) => l.to_string(), None => "page.html".to_string() - } - } - - pub fn render_html(&mut self, tera: &Tera, config: &Config) -> Result<String> { - let tpl = self.get_layout_name(); + }; + // TODO: create a helper to create context to ensure all contexts + // have the same names let mut context = Context::new(); - context.add("site", config); + context.add("config", config); context.add("page", self); - tera.render(&tpl, &context) - .chain_err(|| "Error while rendering template") + tera.render(&tpl_name, &context) + .chain_err(|| format!("Failed to render page '{}'", self.file_name)) } } impl ser::Serialize for Page { fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error> where S: ser::Serializer { - let mut state = serializer.serialize_struct("page", 10)?; + let mut state = serializer.serialize_struct("page", 13)?; state.serialize_field("content", &self.content)?; state.serialize_field("title", &self.meta.title)?; state.serialize_field("description", &self.meta.description)?; state.serialize_field("date", &self.meta.date)?; - state.serialize_field("slug", &self.meta.slug)?; - state.serialize_field("url", &self.meta.url)?; + state.serialize_field("slug", &self.slug)?; + state.serialize_field("url", &format!("/{}", self.url))?; + state.serialize_field("permalink", &self.permalink)?; state.serialize_field("tags", &self.meta.tags)?; state.serialize_field("draft", &self.meta.draft)?; state.serialize_field("category", &self.meta.category)?; state.serialize_field("extra", &self.meta.extra)?; + let (word_count, reading_time) = self.get_reading_analytics(); + state.serialize_field("word_count", &word_count)?; + state.serialize_field("reading_time", &reading_time)?; state.end() } } -// Order pages by date, no-op for now -// TODO: impl PartialOrd on Vec<Page> so we can use sort()? -pub fn order_pages(pages: Vec<Page>) -> Vec<Page> { - pages +impl PartialOrd for Page { + fn partial_cmp(&self, other: &Page) -> Option<Ordering> { + if self.meta.date.is_none() { + return Some(Ordering::Less); + } + + if other.meta.date.is_none() { + return Some(Ordering::Greater); + } + + let this_date = self.meta.parse_date().unwrap(); + let other_date = other.meta.parse_date().unwrap(); + + if this_date > other_date { + return Some(Ordering::Less); + } + if this_date < other_date { + return Some(Ordering::Greater); + } + + Some(Ordering::Equal) + } } #[cfg(test)] mod tests { - use super::{Page}; + use tempdir::TempDir; + use std::fs::File; + + use super::{find_related_assets}; #[test] - fn test_can_parse_a_valid_page() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse("post.md", content); - assert!(res.is_ok()); - let page = res.unwrap(); + fn test_find_related_assets() { + let tmp_dir = TempDir::new("example").expect("create temp dir"); + File::create(tmp_dir.path().join("index.md")).unwrap(); + File::create(tmp_dir.path().join("example.js")).unwrap(); + File::create(tmp_dir.path().join("graph.jpg")).unwrap(); + File::create(tmp_dir.path().join("fail.png")).unwrap(); - assert_eq!(page.meta.title, "Hello".to_string()); - assert_eq!(page.meta.slug.unwrap(), "hello-world".to_string()); - assert_eq!(page.raw_content, "Hello world".to_string()); - assert_eq!(page.content, "<p>Hello world</p>\n".to_string()); - } - - #[test] - fn test_can_find_one_parent_directory() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse("posts/intro.md", content); - assert!(res.is_ok()); - let page = res.unwrap(); - assert_eq!(page.sections, vec!["posts".to_string()]); - } - - #[test] - fn test_can_find_multiple_parent_directories() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse("posts/intro/start.md", content); - assert!(res.is_ok()); - let page = res.unwrap(); - assert_eq!(page.sections, vec!["posts".to_string(), "intro".to_string()]); - } - - #[test] - fn test_can_make_url_from_sections_and_slug() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse("posts/intro/start.md", content); - assert!(res.is_ok()); - let page = res.unwrap(); - assert_eq!(page.meta.url.unwrap(), "/posts/intro/hello-world"); - } - - #[test] - fn test_can_make_url_from_sections_and_slug_root() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse("start.md", content); - assert!(res.is_ok()); - let page = res.unwrap(); - assert_eq!(page.meta.url.unwrap(), "/hello-world"); - } - - #[test] - fn test_errors_on_invalid_front_matter_format() { - let content = r#" -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse("start.md", content); - assert!(res.is_err()); + let assets = find_related_assets(tmp_dir.path()); + assert_eq!(assets.len(), 3); + assert_eq!(assets.iter().filter(|p| p.extension().unwrap() != "md").count(), 3); + assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "example.js").count(), 1); + assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "graph.jpg").count(), 1); + assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "fail.png").count(), 1); } } diff --git a/src/section.rs b/src/section.rs new file mode 100644 index 00000000..3013a447 --- /dev/null +++ b/src/section.rs @@ -0,0 +1,97 @@ +use std::path::{Path, PathBuf}; +use std::result::Result as StdResult; + +use tera::{Tera, Context}; +use serde::ser::{SerializeStruct, self}; + +use config::Config; +use front_matter::{FrontMatter, split_content}; +use errors::{Result, ResultExt}; +use utils::{read_file, find_content_components}; +use page::Page; + + +#[derive(Clone, Debug, PartialEq)] +pub struct Section { + /// The _index.md full path + pub file_path: PathBuf, + /// Path of the directory containing the _index.md file + pub parent_path: PathBuf, + /// The folder names from `content` to this section file + pub components: Vec<String>, + /// The relative URL of the page + pub url: String, + /// The full URL for that page + pub permalink: String, + /// The front matter meta-data + pub meta: FrontMatter, + /// All direct pages of that section + pub pages: Vec<Page>, + /// All direct subsections + pub subsections: Vec<Section>, +} + +impl Section { + pub fn new(file_path: &Path, meta: FrontMatter) -> Section { + Section { + file_path: file_path.to_path_buf(), + parent_path: file_path.parent().unwrap().to_path_buf(), + components: vec![], + url: "".to_string(), + permalink: "".to_string(), + meta: meta, + pages: vec![], + subsections: vec![], + } + } + + pub fn parse(file_path: &Path, content: &str, config: &Config) -> Result<Section> { + let (meta, _) = split_content(file_path, content)?; + let mut section = Section::new(file_path, meta); + section.components = find_content_components(§ion.file_path); + section.url = section.components.join("/"); + section.permalink = section.components.join("/"); + + section.permalink = config.make_permalink(§ion.url); + + Ok(section) + } + + /// Read and parse a .md file into a Page struct + pub fn from_file<P: AsRef<Path>>(path: P, config: &Config) -> Result<Section> { + let path = path.as_ref(); + let content = read_file(path)?; + + Section::parse(path, &content, config) + } + + /// Renders the page using the default layout, unless specified in front-matter + pub fn render_html(&self, tera: &Tera, config: &Config) -> Result<String> { + let tpl_name = match self.meta.template { + Some(ref l) => l.to_string(), + None => "section.html".to_string() + }; + + // TODO: create a helper to create context to ensure all contexts + // have the same names + let mut context = Context::new(); + context.add("config", config); + context.add("section", self); + + tera.render(&tpl_name, &context) + .chain_err(|| format!("Failed to render section '{}'", self.file_path.display())) + } +} + +impl ser::Serialize for Section { + fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error> where S: ser::Serializer { + let mut state = serializer.serialize_struct("section", 6)?; + state.serialize_field("title", &self.meta.title)?; + state.serialize_field("description", &self.meta.description)?; + state.serialize_field("url", &format!("/{}", self.url))?; + state.serialize_field("permalink", &self.permalink)?; + state.serialize_field("pages", &self.pages)?; + state.serialize_field("subsections", &self.subsections)?; + state.end() + } +} diff --git a/src/site.rs b/src/site.rs new file mode 100644 index 00000000..12709abf --- /dev/null +++ b/src/site.rs @@ -0,0 +1,449 @@ +use std::collections::{BTreeMap, HashMap}; +use std::iter::FromIterator; +use std::fs::{remove_dir_all, copy, remove_file}; +use std::path::{Path, PathBuf}; + +use glob::glob; +use tera::{Tera, Context}; +use slug::slugify; +use walkdir::WalkDir; + +use errors::{Result, ResultExt}; +use config::{Config, get_config}; +use page::{Page}; +use utils::{create_file, create_directory}; +use section::{Section}; + + +lazy_static! { + static ref GUTENBERG_TERA: Tera = { + let mut tera = Tera::default(); + tera.add_raw_templates(vec![ + ("rss.xml", include_str!("templates/rss.xml")), + ("sitemap.xml", include_str!("templates/sitemap.xml")), + ]).unwrap(); + tera + }; +} + + +#[derive(Debug, PartialEq)] +enum RenderList { + Tags, + Categories, +} + +/// A tag or category +#[derive(Debug, Serialize, PartialEq)] +struct ListItem { + name: String, + slug: String, + count: usize, +} + +impl ListItem { + pub fn new(name: &str, count: usize) -> ListItem { + ListItem { + name: name.to_string(), + slug: slugify(name), + count: count, + } + } +} + +#[derive(Debug)] +pub struct Site { + pub base_path: PathBuf, + pub config: Config, + pub pages: HashMap<PathBuf, Page>, + pub sections: BTreeMap<PathBuf, Section>, + pub templates: Tera, + live_reload: bool, + output_path: PathBuf, + pub tags: HashMap<String, Vec<PathBuf>>, + pub categories: HashMap<String, Vec<PathBuf>>, +} + +impl Site { + /// Parse a site at the given path. Defaults to the current dir + /// Passing in a path is only used in tests + pub fn new<P: AsRef<Path>>(path: P) -> Result<Site> { + let path = path.as_ref(); + + let tpl_glob = format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*"); + let mut tera = Tera::new(&tpl_glob).chain_err(|| "Error parsing templates")?; + tera.extend(&GUTENBERG_TERA)?; + + let mut site = Site { + base_path: path.to_path_buf(), + config: get_config(path), + pages: HashMap::new(), + sections: BTreeMap::new(), + templates: tera, + live_reload: false, + output_path: PathBuf::from("public"), + tags: HashMap::new(), + categories: HashMap::new(), + }; + site.parse()?; + + Ok(site) + } + + /// What the function name says + pub fn enable_live_reload(&mut self) { + self.live_reload = true; + } + + /// Used by tests to change the output path to a tmp dir + #[doc(hidden)] + pub fn set_output_path<P: AsRef<Path>>(&mut self, path: P) { + self.output_path = path.as_ref().to_path_buf(); + } + + /// Reads all .md files in the `content` directory and create pages + /// out of them + pub fn parse(&mut self) -> Result<()> { + let path = self.base_path.to_string_lossy().replace("\\", "/"); + let content_glob = format!("{}/{}", path, "content/**/*.md"); + + // parent_dir -> Section + let mut sections = BTreeMap::new(); + + // Glob is giving us the result order so _index will show up first + // for each directory + for entry in glob(&content_glob).unwrap().filter_map(|e| e.ok()) { + let path = entry.as_path(); + + if path.file_name().unwrap() == "_index.md" { + let section = Section::from_file(&path, &self.config)?; + sections.insert(section.parent_path.clone(), section); + } else { + let page = Page::from_file(&path, &self.config)?; + if sections.contains_key(&page.parent_path) { + sections.get_mut(&page.parent_path).unwrap().pages.push(page.clone()); + } + self.pages.insert(page.file_path.clone(), page); + } + } + // Find out the direct subsections of each subsection if there are some + let mut grandparent_paths = HashMap::new(); + for section in sections.values() { + let grand_parent = section.parent_path.parent().unwrap().to_path_buf(); + grandparent_paths.entry(grand_parent).or_insert_with(|| vec![]).push(section.clone()); + } + + for (parent_path, section) in &mut sections { + section.pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); + + match grandparent_paths.get(parent_path) { + Some(paths) => section.subsections.extend(paths.clone()), + None => continue, + }; + } + + self.sections = sections; + self.parse_tags_and_categories(); + + Ok(()) + } + + /// Separated from `parse` for easier testing + pub fn parse_tags_and_categories(&mut self) { + for page in self.pages.values() { + if let Some(ref category) = page.meta.category { + self.categories + .entry(category.to_string()) + .or_insert_with(|| vec![]) + .push(page.file_path.clone()); + } + + if let Some(ref tags) = page.meta.tags { + for tag in tags { + self.tags + .entry(tag.to_string()) + .or_insert_with(|| vec![]) + .push(page.file_path.clone()); + } + } + } + } + + /// Inject live reload script tag if in live reload mode + fn inject_livereload(&self, html: String) -> String { + if self.live_reload { + return html.replace( + "</body>", + r#"<script src="/livereload.js?port=1112&mindelay=10"></script></body>"# + ); + } + + html + } + + /// Copy the content of the `static` folder into the `public` folder + /// + /// TODO: only copy one file if possible because that would be a waste + /// to do re-copy the whole thing. Benchmark first to see if it's a big difference + pub fn copy_static_directory(&self) -> Result<()> { + let from = Path::new("static"); + let target = Path::new("public"); + + for entry in WalkDir::new(from).into_iter().filter_map(|e| e.ok()) { + let relative_path = entry.path().strip_prefix(&from).unwrap(); + let target_path = { + let mut target_path = target.to_path_buf(); + target_path.push(relative_path); + target_path + }; + + if entry.path().is_dir() { + if !target_path.exists() { + create_directory(&target_path)?; + } + } else { + if target_path.exists() { + remove_file(&target_path)?; + } + copy(entry.path(), &target_path)?; + } + } + Ok(()) + } + + /// Deletes the `public` directory if it exists + pub fn clean(&self) -> Result<()> { + if Path::new("public").exists() { + // Delete current `public` directory so we can start fresh + remove_dir_all("public").chain_err(|| "Couldn't delete `public` directory")?; + } + + Ok(()) + } + + pub fn rebuild_after_content_change(&mut self) -> Result<()> { + self.parse()?; + self.build() + } + + pub fn rebuild_after_template_change(&mut self) -> Result<()> { + self.templates.full_reload()?; + self.build_pages() + } + + pub fn build_pages(&self) -> Result<()> { + let public = self.output_path.clone(); + if !public.exists() { + create_directory(&public)?; + } + + let mut pages = vec![]; + + // First we render the pages themselves + for page in self.pages.values() { + // Copy the nesting of the content directory if we have sections for that page + let mut current_path = public.to_path_buf(); + + for component in page.url.split('/') { + current_path.push(component); + + if !current_path.exists() { + create_directory(¤t_path)?; + } + } + + // Make sure the folder exists + create_directory(¤t_path)?; + + // Finally, create a index.html file there with the page rendered + let output = page.render_html(&self.templates, &self.config)?; + create_file(current_path.join("index.html"), &self.inject_livereload(output))?; + + // Copy any asset we found previously into the same directory as the index.html + for asset in &page.assets { + let asset_path = asset.as_path(); + copy(&asset_path, ¤t_path.join(asset_path.file_name().unwrap()))?; + } + + pages.push(page); + } + + // Outputting categories and pages + self.render_categories_and_tags(RenderList::Categories)?; + self.render_categories_and_tags(RenderList::Tags)?; + + // And finally the index page + let mut context = Context::new(); + pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); + context.add("pages", &pages); + context.add("config", &self.config); + let index = self.templates.render("index.html", &context)?; + create_file(public.join("index.html"), &self.inject_livereload(index))?; + + Ok(()) + } + + /// Builds the site to the `public` directory after deleting it + pub fn build(&self) -> Result<()> { + self.clean()?; + self.build_pages()?; + self.render_sitemap()?; + + if self.config.generate_rss.unwrap() { + self.render_rss_feed()?; + } + + self.render_sections()?; + self.copy_static_directory() + } + + /// Render the /{categories, list} pages and each individual category/tag page + /// They are the same thing fundamentally, a list of pages with something in common + fn render_categories_and_tags(&self, kind: RenderList) -> Result<()> { + let items = match kind { + RenderList::Categories => &self.categories, + RenderList::Tags => &self.tags, + }; + + if items.is_empty() { + return Ok(()); + } + + let (list_tpl_name, single_tpl_name, name, var_name) = if kind == RenderList::Categories { + ("categories.html", "category.html", "categories", "category") + } else { + ("tags.html", "tag.html", "tags", "tag") + }; + + // Create the categories/tags directory first + let public = self.output_path.clone(); + let mut output_path = public.to_path_buf(); + output_path.push(name); + create_directory(&output_path)?; + + // Then render the index page for that kind. + // We sort by number of page in that category/tag + let mut sorted_items = vec![]; + for (item, count) in Vec::from_iter(items).into_iter().map(|(a, b)| (a, b.len())) { + sorted_items.push(ListItem::new(&item, count)); + } + sorted_items.sort_by(|a, b| b.count.cmp(&a.count)); + let mut context = Context::new(); + context.add(name, &sorted_items); + context.add("config", &self.config); + // And render it immediately + let list_output = self.templates.render(list_tpl_name, &context)?; + create_file(output_path.join("index.html"), &self.inject_livereload(list_output))?; + + // Now, each individual item + for (item_name, pages_paths) in items.iter() { + let mut pages: Vec<&Page> = self.pages + .iter() + .filter(|&(path, _)| pages_paths.contains(&path)) + .map(|(_, page)| page) + .collect(); + pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); + + let mut context = Context::new(); + let slug = slugify(&item_name); + context.add(var_name, &item_name); + context.add(&format!("{}_slug", var_name), &slug); + context.add("pages", &pages); + context.add("config", &self.config); + let single_output = self.templates.render(single_tpl_name, &context)?; + + create_directory(&output_path.join(&slug))?; + create_file( + output_path.join(&slug).join("index.html"), + &self.inject_livereload(single_output) + )?; + } + + Ok(()) + } + + fn render_sitemap(&self) -> Result<()> { + let mut context = Context::new(); + context.add("pages", &self.pages.values().collect::<Vec<&Page>>()); + context.add("sections", &self.sections.values().collect::<Vec<&Section>>()); + + let mut categories = vec![]; + if !self.categories.is_empty() { + categories.push(self.config.make_permalink("categories")); + for category in self.categories.keys() { + categories.push( + self.config.make_permalink(&format!("categories/{}", slugify(category))) + ); + } + } + context.add("categories", &categories); + + let mut tags = vec![]; + if !self.tags.is_empty() { + tags.push(self.config.make_permalink("tags")); + for tag in self.tags.keys() { + tags.push( + self.config.make_permalink(&format!("tags/{}", slugify(tag))) + ); + } + } + context.add("tags", &tags); + + let sitemap = self.templates.render("sitemap.xml", &context)?; + + create_file(self.output_path.join("sitemap.xml"), &sitemap)?; + + Ok(()) + } + + fn render_rss_feed(&self) -> Result<()> { + let mut context = Context::new(); + let mut pages = self.pages.values() + .filter(|p| p.meta.date.is_some()) + .take(15) // limit to the last 15 elements + .collect::<Vec<&Page>>(); + + // Don't generate a RSS feed if none of the pages has a date + if pages.is_empty() { + return Ok(()); + } + + pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); + context.add("pages", &pages); + context.add("last_build_date", &pages[0].meta.date); + context.add("config", &self.config); + + let rss_feed_url = if self.config.base_url.ends_with('/') { + format!("{}{}", self.config.base_url, "feed.xml") + } else { + format!("{}/{}", self.config.base_url, "feed.xml") + }; + context.add("feed_url", &rss_feed_url); + + let sitemap = self.templates.render("rss.xml", &context)?; + + create_file(self.output_path.join("rss.xml"), &sitemap)?; + + Ok(()) + } + + fn render_sections(&self) -> Result<()> { + let public = self.output_path.clone(); + + for section in self.sections.values() { + let mut output_path = public.to_path_buf(); + for component in §ion.components { + output_path.push(component); + + if !output_path.exists() { + create_directory(&output_path)?; + } + } + + let output = section.render_html(&self.templates, &self.config)?; + create_file(output_path.join("index.html"), &self.inject_livereload(output))?; + } + + Ok(()) + } +} diff --git a/src/templates/rss.xml b/src/templates/rss.xml new file mode 100644 index 00000000..53aae2f5 --- /dev/null +++ b/src/templates/rss.xml @@ -0,0 +1,20 @@ +<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"> + <channel> + <title>{{ config.title }} + {{ config.base_url }} + {{ config.description }} + Gutenberg + {{ config.language_code }} + + {{ last_build_date | date(format="%a, %d %b %Y %H:%M:%S %z") }} + {% for page in pages %} + + {{ page.title }} + {{ page.date | date(format="%a, %d %b %Y %H:%M:%S %z") }} + {{ page.permalink }} + {{ page.permalink }} + "{{ page.content | escape }}" + + {% endfor %} + + diff --git a/src/templates/sitemap.xml b/src/templates/sitemap.xml new file mode 100644 index 00000000..d867752c --- /dev/null +++ b/src/templates/sitemap.xml @@ -0,0 +1,25 @@ + + {% for page in pages %} + + {{ page.permalink | safe }} + {% if page.date %} + {{ page.date }} + {% endif %} + + {% endfor %} + {% for section in sections %} + + {{ section.permalink | safe }} + + {% endfor %} + {% for category in categories %} + + {{ category | safe }} + + {% endfor %} + {% for tag in tags %} + + {{ tag | safe }} + + {% endfor %} + diff --git a/src/utils.rs b/src/utils.rs index 3e0a09f5..3068112d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,8 +1,8 @@ use std::io::prelude::*; -use std::fs::{File}; +use std::fs::{File, create_dir}; use std::path::Path; -use errors::Result; +use errors::{Result, ResultExt}; pub fn create_file>(path: P, content: &str) -> Result<()> { @@ -10,3 +10,63 @@ pub fn create_file>(path: P, content: &str) -> Result<()> { file.write_all(content.as_bytes())?; Ok(()) } + +/// Very similar to `create_dir` from the std except it checks if the folder +/// exists before creating it +pub fn create_directory>(path: P) -> Result<()> { + let path = path.as_ref(); + if !path.exists() { + create_dir(path) + .chain_err(|| format!("Was not able to create folder {}", path.display()))?; + } + Ok(()) +} + + +/// Return the content of a file, with error handling added +pub fn read_file>(path: P) -> Result { + let path = path.as_ref(); + + let mut content = String::new(); + File::open(path) + .chain_err(|| format!("Failed to open '{:?}'", path.display()))? + .read_to_string(&mut content)?; + + Ok(content) +} + + +/// Takes a full path to a .md and returns only the components after the `content` directory +/// Will not return the filename as last component +pub fn find_content_components>(path: P) -> Vec { + let path = path.as_ref(); + let mut is_in_content = false; + let mut components = vec![]; + + for section in path.parent().unwrap().components() { + let component = section.as_ref().to_string_lossy(); + + if is_in_content { + components.push(component.to_string()); + continue; + } + + if component == "content" { + is_in_content = true; + } + } + + components +} + + +#[cfg(test)] +mod tests { + use super::{find_content_components}; + + #[test] + fn test_find_content_components() { + let res = find_content_components("/home/vincent/code/site/content/posts/tutorials/python.md"); + assert_eq!(res, ["posts".to_string(), "tutorials".to_string()]); + } +} diff --git a/sublime_themes/base16-ocean-dark.tmTheme b/sublime_themes/base16-ocean-dark.tmTheme new file mode 100644 index 00000000..19b34166 --- /dev/null +++ b/sublime_themes/base16-ocean-dark.tmTheme @@ -0,0 +1,593 @@ + + + + + author + Chris Kempson (http://chriskempson.com) + name + Base16 Ocean Dark + semanticClass + base16.ocean.dark + colorSpaceName + sRGB + gutterSettings + + background + #343d46 + divider + #343d46 + foreground + #65737e + selectionBackground + #4f5b66 + selectionForeground + #a7adba + + settings + + + settings + + background + #2b303b + caret + #c0c5ce + foreground + #c0c5ce + invisibles + #65737e + lineHighlight + #65737e30 + selection + #4f5b66 + guide + #3b5364 + activeGuide + #96b5b4 + stackGuide + #343d46 + + + + name + Text + scope + variable.parameter.function + settings + + foreground + #c0c5ce + + + + name + Comments + scope + comment, punctuation.definition.comment + settings + + foreground + #65737e + + + + name + Punctuation + scope + punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array + settings + + foreground + #c0c5ce + + + + name + Delimiters + scope + none + settings + + foreground + #c0c5ce + + + + name + Operators + scope + keyword.operator + settings + + foreground + #c0c5ce + + + + name + Keywords + scope + keyword + settings + + foreground + #b48ead + + + + name + Variables + scope + variable + settings + + foreground + #bf616a + + + + name + Functions + scope + entity.name.function, meta.require, support.function.any-method + settings + + foreground + #8fa1b3 + + + + name + Classes + scope + support.class, entity.name.class, entity.name.type.class + settings + + foreground + #ebcb8b + + + + name + Classes + scope + meta.class + settings + + foreground + #eff1f5 + + + + name + Methods + scope + keyword.other.special-method + settings + + foreground + #8fa1b3 + + + + name + Storage + scope + storage + settings + + foreground + #b48ead + + + + name + Support + scope + support.function + settings + + foreground + #96b5b4 + + + + name + Strings, Inherited Class + scope + string, constant.other.symbol, entity.other.inherited-class + settings + + foreground + #a3be8c + + + + name + Integers + scope + constant.numeric + settings + + foreground + #d08770 + + + + name + Floats + scope + none + settings + + foreground + #d08770 + + + + name + Boolean + scope + none + settings + + foreground + #d08770 + + + + name + Constants + scope + constant + settings + + foreground + #d08770 + + + + name + Tags + scope + entity.name.tag + settings + + foreground + #bf616a + + + + name + Attributes + scope + entity.other.attribute-name + settings + + foreground + #d08770 + + + + name + Attribute IDs + scope + entity.other.attribute-name.id, punctuation.definition.entity + settings + + foreground + #8fa1b3 + + + + name + Selector + scope + meta.selector + settings + + foreground + #b48ead + + + + name + Values + scope + none + settings + + foreground + #d08770 + + + + name + Headings + scope + markup.heading punctuation.definition.heading, entity.name.section + settings + + fontStyle + + foreground + #8fa1b3 + + + + name + Units + scope + keyword.other.unit + settings + + foreground + #d08770 + + + + name + Bold + scope + markup.bold, punctuation.definition.bold + settings + + fontStyle + bold + foreground + #ebcb8b + + + + name + Italic + scope + markup.italic, punctuation.definition.italic + settings + + fontStyle + italic + foreground + #b48ead + + + + name + Code + scope + markup.raw.inline + settings + + foreground + #a3be8c + + + + name + Link Text + scope + string.other.link + settings + + foreground + #bf616a + + + + name + Link Url + scope + meta.link + settings + + foreground + #d08770 + + + + name + Lists + scope + markup.list + settings + + foreground + #bf616a + + + + name + Quotes + scope + markup.quote + settings + + foreground + #d08770 + + + + name + Separator + scope + meta.separator + settings + + background + #4f5b66 + foreground + #c0c5ce + + + + name + Inserted + scope + markup.inserted, markup.inserted.git_gutter + settings + + foreground + #a3be8c + + + + name + Deleted + scope + markup.deleted, markup.deleted.git_gutter + settings + + foreground + #bf616a + + + + name + Changed + scope + markup.changed, markup.changed.git_gutter + settings + + foreground + #b48ead + + + + name + Ignored + scope + markup.ignored, markup.ignored.git_gutter + settings + + foreground + #4f5b66 + + + + name + Untracked + scope + markup.untracked, markup.untracked.git_gutter + settings + + foreground + #4f5b66 + + + + name + Colors + scope + constant.other.color + settings + + foreground + #96b5b4 + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #96b5b4 + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #96b5b4 + + + + name + Embedded + scope + punctuation.section.embedded, variable.interpolation + settings + + foreground + #ab7967 + + + + name + Invalid + scope + invalid.illegal + settings + + background + #bf616a + foreground + #2b303b + + + + name + GitGutter deleted + scope + markup.deleted.git_gutter + settings + + foreground + #F92672 + + + + name + GitGutter inserted + scope + markup.inserted.git_gutter + settings + + foreground + #A6E22E + + + + name + GitGutter changed + scope + markup.changed.git_gutter + settings + + foreground + #967EFB + + + + name + GitGutter ignored + scope + markup.ignored.git_gutter + settings + + foreground + #565656 + + + + name + GitGutter untracked + scope + markup.untracked.git_gutter + settings + + foreground + #565656 + + + + uuid + 59c1e2f2-7b41-46f9-91f2-1b4c6f5866f7 + + diff --git a/sublime_themes/base16-ocean-light.tmTheme b/sublime_themes/base16-ocean-light.tmTheme new file mode 100644 index 00000000..8d416e54 --- /dev/null +++ b/sublime_themes/base16-ocean-light.tmTheme @@ -0,0 +1,589 @@ + + + + + author + Chris Kempson (http://chriskempson.com) + name + Base16 Ocean Light + semanticClass + base16.ocean.light + colorSpaceName + sRGB + gutterSettings + + background + #eff1f5 + divider + #eff1f5 + foreground + #4f5b66 + selectionBackground + #eff1f5 + selectionForeground + #c0c5ce + + settings + + + settings + + background + #eff1f5 + caret + #4f5b66 + foreground + #4f5b66 + invisibles + #dfe1e8 + lineHighlight + #a7adba30 + selection + #dfe1e8 + shadow + #dfe1e8 + + + + name + Text + scope + variable.parameter.function + settings + + foreground + #4f5b66 + + + + name + Comments + scope + comment, punctuation.definition.comment + settings + + foreground + #a7adba + + + + name + Punctuation + scope + punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array + settings + + foreground + #4f5b66 + + + + name + Delimiters + scope + none + settings + + foreground + #4f5b66 + + + + name + Operators + scope + keyword.operator + settings + + foreground + #4f5b66 + + + + name + Keywords + scope + keyword + settings + + foreground + #b48ead + + + + name + Variables + scope + variable + settings + + foreground + #bf616a + + + + name + Functions + scope + entity.name.function, meta.require, support.function.any-method + settings + + foreground + #8fa1b3 + + + + name + Classes + scope + support.class, entity.name.class, entity.name.type.class + settings + + foreground + #d08770 + + + + name + Classes + scope + meta.class + settings + + foreground + #343d46 + + + + name + Methods + scope + keyword.other.special-method + settings + + foreground + #8fa1b3 + + + + name + Storage + scope + storage + settings + + foreground + #b48ead + + + + name + Support + scope + support.function + settings + + foreground + #96b5b4 + + + + name + Strings, Inherited Class + scope + string, constant.other.symbol, entity.other.inherited-class + settings + + foreground + #a3be8c + + + + name + Integers + scope + constant.numeric + settings + + foreground + #d08770 + + + + name + Floats + scope + none + settings + + foreground + #d08770 + + + + name + Boolean + scope + none + settings + + foreground + #d08770 + + + + name + Constants + scope + constant + settings + + foreground + #d08770 + + + + name + Tags + scope + entity.name.tag + settings + + foreground + #bf616a + + + + name + Attributes + scope + entity.other.attribute-name + settings + + foreground + #d08770 + + + + name + Attribute IDs + scope + entity.other.attribute-name.id, punctuation.definition.entity + settings + + foreground + #8fa1b3 + + + + name + Selector + scope + meta.selector + settings + + foreground + #b48ead + + + + name + Values + scope + none + settings + + foreground + #d08770 + + + + name + Headings + scope + markup.heading punctuation.definition.heading, entity.name.section + settings + + fontStyle + + foreground + #8fa1b3 + + + + name + Units + scope + keyword.other.unit + settings + + foreground + #d08770 + + + + name + Bold + scope + markup.bold, punctuation.definition.bold + settings + + fontStyle + bold + foreground + #d08770 + + + + name + Italic + scope + markup.italic, punctuation.definition.italic + settings + + fontStyle + italic + foreground + #b48ead + + + + name + Code + scope + markup.raw.inline + settings + + foreground + #a3be8c + + + + name + Link Text + scope + string.other.link + settings + + foreground + #bf616a + + + + name + Link Url + scope + meta.link + settings + + foreground + #d08770 + + + + name + Lists + scope + markup.list + settings + + foreground + #bf616a + + + + name + Quotes + scope + markup.quote + settings + + foreground + #d08770 + + + + name + Separator + scope + meta.separator + settings + + background + #dfe1e8 + foreground + #4f5b66 + + + + name + Inserted + scope + markup.inserted, markup.inserted.git_gutter + settings + + foreground + #a3be8c + + + + name + Deleted + scope + markup.deleted, markup.deleted.git_gutter + settings + + foreground + #bf616a + + + + name + Changed + scope + markup.changed, markup.changed.git_gutter + settings + + foreground + #b48ead + + + + name + Ignored + scope + markup.ignored, markup.ignored.git_gutter + settings + + foreground + #c0c5ce + + + + name + Untracked + scope + markup.untracked, markup.untracked.git_gutter + settings + + foreground + #c0c5ce + + + + name + Colors + scope + constant.other.color + settings + + foreground + #96b5b4 + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #96b5b4 + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #96b5b4 + + + + name + Embedded + scope + punctuation.section.embedded, variable.interpolation + settings + + foreground + #ab7967 + + + + name + Invalid + scope + invalid.illegal + settings + + background + #bf616a + foreground + #eff1f5 + + + + name + GitGutter deleted + scope + markup.deleted.git_gutter + settings + + foreground + #F92672 + + + + name + GitGutter inserted + scope + markup.inserted.git_gutter + settings + + foreground + #A6E22E + + + + name + GitGutter changed + scope + markup.changed.git_gutter + settings + + foreground + #967EFB + + + + name + GitGutter ignored + scope + markup.ignored.git_gutter + settings + + foreground + #565656 + + + + name + GitGutter untracked + scope + markup.untracked.git_gutter + settings + + foreground + #565656 + + + + uuid + 52997033-52ea-4534-af9f-7572613947d8 + + diff --git a/sublime_themes/gruvbox-dark.tmTheme b/sublime_themes/gruvbox-dark.tmTheme new file mode 100644 index 00000000..b068fc96 --- /dev/null +++ b/sublime_themes/gruvbox-dark.tmTheme @@ -0,0 +1,766 @@ + + + + + comment + Based on original gruvbox color scheme. + author + peaceant + name + gruvbox + settings + + + settings + + background + #282828 + + caret + #fcf9e3 + + foreground + #fdf4c1aa + + invisibles + #fabd2f + + lineHighlight + #3c3836 + + selection + #504945 + + bracketContentsForeground + #928374 + + bracketsForeground + #d5c4a1 + + guide + #3c3836 + + activeGuide + #a89984 + + stackGuide + #665c54 + + + + name + Punctuation + scope + punctuation.definition.tag + settings + + fontStyle + + foreground + #83a598 + + + + name + Punctuation + scope + punctuation.definition.entity + settings + + fontStyle + + foreground + #d3869b + + + + name + Constant + scope + constant + settings + + fontStyle + + foreground + #d3869b + + + + name + Constant escape + scope + constant.character.escape + settings + + fontStyle + + foreground + #b8bb26 + + + + name + Constant other + scope + constant.other + settings + + fontStyle + + foreground + #fdf4c1 + + + + name + Entity + scope + entity + settings + + fontStyle + + foreground + #8ec07c + + + + name + Keyword + scope + keyword.operator.comparison, keyword.operator, keyword.operator.symbolic, keyword.operator.string, keyword.operator.assignment, keyword.operator.arithmetic, keyword.operator.class, keyword.operator.key, keyword.operator.logical + settings + + fontStyle + + foreground + #fe8019 + + + + name + Keyword + scope + keyword, keyword.operator.new, keyword.other, keyword.control + settings + + fontStyle + + foreground + #fa5c4b + + + + name + Storage + scope + storage + settings + + fontStyle + + foreground + #fa5c4b + + + + name + String + scope + string -string.unquoted.old-plist -string.unquoted.heredoc, string.unquoted.heredoc string + settings + + fontStyle + + foreground + #b8bb26 + + + + name + Comment + scope + comment + settings + + fontStyle + italic + foreground + #928374 + + + + name + Regexp + scope + string.regexp constant.character.escape + settings + + foreground + #b8bb26 + + + + name + Support + scope + support + settings + + fontStyle + + foreground + #fabd2f + + + + name + Variable + scope + variable + settings + + fontStyle + + foreground + #fdf4c1 + + + + name + Lang Variable + scope + variable.language + settings + + fontStyle + + foreground + #fdf4c1 + + + + name + Function Call + scope + meta.function-call + settings + + foreground + #fdf4c1 + + + + name + Invalid + scope + invalid + settings + + background + #932b1e + foreground + #fdf4c1 + + + + name + Embedded Source + scope + text source, string.unquoted.heredoc, source source + settings + + fontStyle + + foreground + #fdf4c1 + + + + name + String embedded-source + scope + string.quoted source + settings + + fontStyle + + foreground + #b8bb26 + + + + name + String constant + scope + string + settings + + foreground + #b8bb26 + + + + + name + Support.constant + scope + support.constant + settings + + fontStyle + + foreground + #fabd2f + + + + name + Support.class + scope + support.class + settings + + fontStyle + + foreground + #8ec07c + + + + name + Meta.tag.A + scope + entity.name.tag + settings + + fontStyle + bold + foreground + #8ec07c + + + + name + Inner tag + scope + meta.tag, meta.tag entity + settings + + foreground + #8ec07c + + + + name + css colors + scope + constant.other.color.rgb-value + settings + + foreground + #83a598 + + + + name + css tag-name + scope + meta.selector.css entity.name.tag + settings + + foreground + #fa5c4b + + + + name + css#id + scope + meta.selector.css, entity.other.attribute-name.id + settings + + foreground + #b8bb26 + + + + name + css.class + scope + meta.selector.css entity.other.attribute-name.class + settings + + foreground + #b8bb26 + + + + name + css property-name: + scope + support.type.property-name.css + settings + + foreground + #8ec07c + + + + name + css @at-rule + scope + meta.preprocessor.at-rule keyword.control.at-rule + settings + + foreground + #fabd2f + + + + name + css additional-constants + scope + meta.property-value constant + settings + + foreground + #fabd2f + + + + name + css additional-constants + scope + meta.property-value support.constant.named-color.css + settings + + foreground + #fe8019 + + + + name + css constructor.argument + scope + meta.constructor.argument.css + settings + + foreground + #fabd2f + + + + + + + name + diff.header + scope + meta.diff, meta.diff.header + settings + + foreground + #83a598 + + + + name + diff.deleted + scope + markup.deleted + settings + + foreground + #fa5c4b + + + + name + diff.changed + scope + markup.changed + settings + + foreground + #fabd2f + + + + name + diff.inserted + scope + markup.inserted + settings + + foreground + #8ec07c + + + + + + + name + Bold Markup + scope + markup.bold + settings + + fontStyle + bold + + + + name + Italic Markup + scope + markup.italic + settings + + fontStyle + italic + + + + name + Heading Markup + scope + markup.heading + settings + + fontStyle + bold + foreground + #8ec07c + + + + + + + + + name + PHP: class name + scope + entity.name.type.class.php + settings + + foreground + #8ec07c + + + + name + PHP: Comment + scope + keyword.other.phpdoc + settings + + fontStyle + + foreground + #928374 + + + + + + name + CSS: numbers + scope + constant.numeric.css, keyword.other.unit.css + settings + + foreground + #d3869b + + + + name + CSS: entity dot, hash, comma, etc. + scope + punctuation.definition.entity.css + settings + + foreground + #b8bb26 + + + + + name + JS: variable + scope + variable.language.js + settings + + foreground + #fabd2f + + + + name + JS: unquoted labe + scope + string.unquoted.label.js + settings + + foreground + #fdf4c1 + + + + + name + Constant other sql + scope + constant.other.table-name.sql + settings + + fontStyle + + foreground + #b8bb26 + + + + name + Constant other sql + scope + constant.other.database-name.sql + settings + + fontStyle + + foreground + #b8bb26 + + + + + + + + name + dired directory + scope + storage.type.dired.item.directory, dired.item.directory + settings + + foreground + #8ec07c + + + + + + name + orgmode link + scope + orgmode.link + settings + + foreground + #fabd2f + fontStyle + underline + + + + name + orgmode page + scope + orgmode.page + settings + + foreground + #b8bb26 + + + + name + orgmode break + scope + orgmode.break + settings + + foreground + #d3869b + + + + name + orgmode headline + scope + orgmode.headline + settings + + foreground + #8ec07c + + + + name + orgmode tack + scope + orgmode.tack + settings + + foreground + #fabd2f + + + + name + orgmode follow up + scope + orgmode.follow_up + settings + + foreground + #fabd2f + + + + name + orgmode checkbox + scope + orgmode.checkbox + settings + + foreground + #fabd2f + + + + name + orgmode checkbox summary + scope + orgmode.checkbox.summary + settings + + foreground + #fabd2f + + + + name + orgmode tags + scope + orgmode.tags + settings + + foreground + #fa5c4b + + + + + uuid + 06CD1FB2-A00A-4F8C-97B2-60E131980454 + + + diff --git a/sublime_themes/gruvbox-light.tmTheme b/sublime_themes/gruvbox-light.tmTheme new file mode 100644 index 00000000..4bfc3a45 --- /dev/null +++ b/sublime_themes/gruvbox-light.tmTheme @@ -0,0 +1,774 @@ + + + + + comment + Based on original gruvbox color scheme. + author + Martin Radimec + name + gruvbox + settings + + + settings + + background + #FCF0CA + + caret + #3C3836 + + foreground + #282828aa + + invisibles + #b57614 + + lineHighlight + #EDDAB5 + + selection + #D6C3A3 + + bracketContentsForeground + #928374 + + bracketsForeground + #d5c4a1 + + guide + #EDDAB5 + + activeGuide + #7c6f64 + + stackGuide + #BEAD95 + + + + name + Punctuation + scope + punctuation.definition.tag + settings + + fontStyle + + foreground + #076678 + + + + name + Punctuation + scope + punctuation.definition.entity + settings + + fontStyle + + foreground + #8f3f71 + + + + name + Constant + scope + constant + settings + + fontStyle + + foreground + #8f3f71 + + + + name + Constant escape + scope + constant.character.escape + settings + + fontStyle + + foreground + #79740e + + + + name + Constant other + scope + constant.other + settings + + fontStyle + + foreground + #282828 + + + + name + Entity + scope + entity + settings + + fontStyle + + foreground + #407959 + + + + name + Keyword + scope + keyword.operator.comparison, keyword.operator, keyword.operator.symbolic, keyword.operator.string, keyword.operator.assignment, keyword.operator.arithmetic, keyword.operator.class, keyword.operator.key, keyword.operator.logical + settings + + fontStyle + + foreground + #B23C15 + + + + name + Keyword + scope + keyword, keyword.operator.new, keyword.other, keyword.control + settings + + fontStyle + + foreground + #9d0006 + + + + name + Storage + scope + storage + settings + + fontStyle + + foreground + #9d0006 + + + + name + String + scope + string -string.unquoted.old-plist -string.unquoted.heredoc, string.unquoted.heredoc string + settings + + fontStyle + + foreground + #79740e + + + + name + Comment + scope + comment + settings + + fontStyle + italic + foreground + #928374 + + + + name + Regexp + scope + string.regexp constant.character.escape + settings + + foreground + #79740e + + + + name + Support + scope + support + settings + + fontStyle + + foreground + #b57614 + + + + name + Variable + scope + variable + settings + + fontStyle + + foreground + #282828 + + + + name + Lang Variable + scope + variable.language + settings + + fontStyle + + foreground + #282828 + + + + name + Function Call + scope + meta.function-call + settings + + foreground + #282828 + + + + name + Invalid + scope + invalid + settings + + background + #932b1e + foreground + #282828 + + + + name + Embedded Source + scope + text source, string.unquoted.heredoc, source source + settings + + fontStyle + + foreground + #282828 + + + + name + String embedded-source + scope + string.quoted source + settings + + fontStyle + + foreground + #79740e + + + + name + String constant + scope + string + settings + + foreground + #79740e + + + + + name + Support.constant + scope + support.constant + settings + + fontStyle + + foreground + #b57614 + + + + name + Support.class + scope + support.class + settings + + fontStyle + + foreground + #407959 + + + + name + Meta.tag.A + scope + entity.name.tag + settings + + fontStyle + bold + foreground + #407959 + + + + name + Inner tag + scope + meta.tag, meta.tag entity + settings + + foreground + #407959 + + + + name + css colors + scope + constant.other.color.rgb-value + settings + + foreground + #076678 + + + + name + css tag-name + scope + meta.selector.css entity.name.tag + settings + + foreground + #9d0006 + + + + name + css#id + scope + meta.selector.css, entity.other.attribute-name.id + settings + + foreground + #79740e + + + + name + css.class + scope + meta.selector.css entity.other.attribute-name.class + settings + + foreground + #79740e + + + + name + css property-name: + scope + support.type.property-name.css + settings + + foreground + #407959 + + + + name + css @at-rule + scope + meta.preprocessor.at-rule keyword.control.at-rule + settings + + foreground + #b57614 + + + + name + css additional-constants + scope + meta.property-value constant + settings + + foreground + #b57614 + + + + name + css additional-constants + scope + meta.property-value support.constant.named-color.css + settings + + foreground + #B23C15 + + + + name + css constructor.argument + scope + meta.constructor.argument.css + settings + + foreground + #b57614 + + + + + + + name + diff.header + scope + meta.diff, meta.diff.header + settings + + background + #076678 + foreground + #282828 + + + + name + diff.deleted + scope + markup.deleted + settings + + background + #9d0006 + foreground + #282828 + + + + name + diff.changed + scope + markup.changed + settings + + background + #b57614 + foreground + #282828 + + + + name + diff.inserted + scope + markup.inserted + settings + + background + #407959 + foreground + #282828 + + + + + + + name + Bold Markup + scope + markup.bold + settings + + fontStyle + bold + + + + name + Italic Markup + scope + markup.italic + settings + + fontStyle + italic + + + + name + Heading Markup + scope + markup.heading + settings + + fontStyle + bold + foreground + #407959 + + + + + + + + + name + PHP: class name + scope + entity.name.type.class.php + settings + + foreground + #407959 + + + + name + PHP: Comment + scope + keyword.other.phpdoc + settings + + fontStyle + + foreground + #928374 + + + + + + name + CSS: numbers + scope + constant.numeric.css, keyword.other.unit.css + settings + + foreground + #8f3f71 + + + + name + CSS: entity dot, hash, comma, etc. + scope + punctuation.definition.entity.css + settings + + foreground + #79740e + + + + + name + JS: variable + scope + variable.language.js + settings + + foreground + #b57614 + + + + name + JS: unquoted labe + scope + string.unquoted.label.js + settings + + foreground + #282828 + + + + + name + Constant other sql + scope + constant.other.table-name.sql + settings + + fontStyle + + foreground + #79740e + + + + name + Constant other sql + scope + constant.other.database-name.sql + settings + + fontStyle + + foreground + #79740e + + + + + + + + name + dired directory + scope + storage.type.dired.item.directory, dired.item.directory + settings + + foreground + #407959 + + + + + + name + orgmode link + scope + orgmode.link + settings + + foreground + #b57614 + fontStyle + underline + + + + name + orgmode page + scope + orgmode.page + settings + + foreground + #79740e + + + + name + orgmode break + scope + orgmode.break + settings + + foreground + #8f3f71 + + + + name + orgmode headline + scope + orgmode.headline + settings + + foreground + #407959 + + + + name + orgmode tack + scope + orgmode.tack + settings + + foreground + #b57614 + + + + name + orgmode follow up + scope + orgmode.follow_up + settings + + foreground + #b57614 + + + + name + orgmode checkbox + scope + orgmode.checkbox + settings + + foreground + #b57614 + + + + name + orgmode checkbox summary + scope + orgmode.checkbox.summary + settings + + foreground + #b57614 + + + + name + orgmode tags + scope + orgmode.tags + settings + + foreground + #9d0006 + + + + + uuid + 06CD1FB2-A00A-4F8C-97B2-60E131980454 + + + diff --git a/sublime_themes/inspired-github.tmTheme b/sublime_themes/inspired-github.tmTheme new file mode 100644 index 00000000..c009512e --- /dev/null +++ b/sublime_themes/inspired-github.tmTheme @@ -0,0 +1,1725 @@ + + + + + + name + GitHub + settings + + + + + settings + + + background + #ffffff + foreground + #323232 + invisibles + #000000 + caret + #323232 + + + gutter + #ffffff + gutterForeground + #b3b3b3 + + + guide + #e8e8e8 + stackGuide + #e8e8e8 + activeGuide + #b3b3b3 + + + lineHighlight + #f5f5f5 + findHighlight + #f8eec7 + findHighlightForeground + #323232 + selection + #f8eec7 + selectionBorder + #ffffff + + + bracketsForeground + #63a35c + bracketsOptions + underline + bracketContentsForeground + #63a35c + bracketContentsOptions + underline + + + tagsForeground + #63a35c + tagsOptions + underline + + + + + + name + Comment + scope + comment + settings + + foreground + #969896 + fontStyle + italic + + + + + + name + String + scope + string + settings + + foreground + #183691 + + + + + + name + RegExp Operator + scope + regexp-operator + settings + + foreground + #a71d5d + + + + + + name + RegExp Character Class + scope + string.regexp.characterclass punctuation.definition.string.begin, string.regexp.characterclass punctuation.definition.string.end + settings + + foreground + #a71d5d + + + + + + name + Number + scope + constant.numeric + settings + + foreground + #0086b3 + + + + + + name + Built-in Constant + scope + constant.language + settings + + foreground + #0086b3 + + + + + + name + User-defined Constant + scope + constant.character, constant.other, variable.other.constant + settings + + foreground + #0086b3 + + + + + + name + Variable + scope + variable + settings + + foreground + #323232 + + + + + + name + Keyword + scope + keyword + settings + + foreground + #a71d5d + fontStyle + bold + + + + + + name + Bitwise + scope + bitwise-operator + settings + + foreground + #a71d5d + fontStyle + bold + + + + + + name + Storage + scope + storage + settings + + foreground + #a71d5d + fontStyle + bold + + + + + + name + Storage Type + scope + storage.type + settings + + foreground + #a71d5d + fontStyle + bold + + + + + + name + Class Name + scope + entity.name.class + settings + + foreground + #0086b3 + + + + + + name + Inherited Class + scope + entity.other.inherited-class + settings + + foreground + #0086b3 + + + + + + name + Function Name + scope + entity.name.function + settings + + foreground + #795da3 + fontStyle + bold + + + + + + name + Function Argument + scope + variable.parameter + settings + + foreground + #323232 + + + + + + name + Tag Name + scope + entity.name.tag + settings + + foreground + #63a35c + + + + + + name + Tag Attribute + scope + entity.other.attribute-name + settings + + foreground + #795da3 + + + + + + name + Library Function + scope + support.function + settings + + foreground + #62a35c + + + + + + name + Library Constant + scope + support.constant + settings + + foreground + #0086b3 + + + + + + name + Library Class + scope + support.type, support.class + settings + + foreground + #0086b3 + + + + + + name + Library Variable + scope + support.other.variable + settings + + foreground + #323232 + + + + + + name + Invalid + scope + invalid, invalid.illegal, invalid.deprecated + settings + + background + #f5f5f5 + foreground + #b52a1d + fontStyle + bold + + + + + + + + + name + Find-in-files Filename + scope + entity.name.filename.find-in-files + settings + + foreground + #323232 + fontStyle + bold + + + + name + Find-in-files Line Numbers + scope + constant.numeric.line-number.find-in-files, constant.numeric.line-number.match.find-in-files + settings + + foreground + #b3b3b3 + + + + + + + + + + name + Diff Header + scope + meta.diff.header + settings + + foreground + #969896 + background + #ffffff + fontStyle + italic + + + + + name + Diff Header + scope + meta.diff.header punctuation.definition.from-file.diff + settings + + foreground + #bd2c00 + background + #ffecec + fontStyle + italic bold + + + + + name + Diff Header + scope + meta.diff.header punctuation.definition.to-file.diff + settings + + foreground + #55a532 + background + #eaffea + fontStyle + italic bold + + + + + name + Diff Range + scope + meta.diff.range + settings + + foreground + #969896 + fontStyle + italic bold + + + + + name + Diff Deleted + scope + markup.deleted + settings + + background + #ffecec + + + + + name + Diff Deleted Punctuation + scope + markup.deleted punctuation.definition.inserted + settings + + foreground + #bd2c00 + fontStyle + bold + + + + + name + Diff Inserted + scope + markup.inserted + settings + + background + #eaffea + + + + + name + Diff Inserted Punctuation + scope + markup.inserted punctuation.definition.inserted + settings + + foreground + #55a532 + fontStyle + bold + + + + + + + + + + name + GitGutter Deleted + scope + markup.deleted.git_gutter + settings + + foreground + #bd2c00 + + + + + name + GitGutter Inserted + scope + markup.inserted.git_gutter + settings + + foreground + #55a532 + + + + + name + GitGutter Modified + scope + markup.changed.git_gutter + settings + + foreground + #0086B3 + + + + + name + GitGutter Ignored + scope + markup.ignored.git_gutter + settings + + foreground + #b3b3b3 + + + + + name + GitGutter Untracked + scope + markup.untracked.git_gutter + settings + + foreground + #b3b3b3 + + + + + + + + + + name + Entity Punctuation + scope + source.css punctuation.definition.entity + settings + + foreground + #323232 + + + + + name + Pseudo Selector + scope + source.css entity.other.attribute-name.pseudo-class, source.css entity.other.attribute-name.pseudo-element + settings + + foreground + #a71d5d + + + + + name + Property Value + scope + source.css meta.value, source.css support.constant, source.css support.function + settings + + foreground + #323232 + + + + + name + Color + scope + source.css constant.other.color + settings + + foreground + #ed6a43 + + + + + + + + + + name + Entity Punctuation + scope + source.scss punctuation.definition.entity + settings + + foreground + #323232 + + + + + name + Pseudo Selector + scope + source.scss entity.other.attribute-name.pseudo-class, source.scss entity.other.attribute-name.pseudo-element + settings + + foreground + #a71d5d + + + + + name + Color + scope + source.scss support.constant.property-value, source.scss support.function + settings + + foreground + #323232 + + + + + name + Variable + scope + source.scss variable + settings + + foreground + #a71d5d + + + + + + + + + + name + this + scope + variable.language.this.js + settings + + foreground + #ed6a43 + + + + + name + Function + scope + source.js entity.name.function + settings + + foreground + #323232 + fontStyle + regular + + + + + name + Function Definition + scope + source.js meta.function entity.name.function, source.js entity.name.function meta.function + settings + + foreground + #795da3 + fontStyle + bold + + + + + name + New Function + scope + entity.name.type.new.js + settings + + foreground + #795da3 + + + + + name + Function Prototype + scope + variable.language.prototype.js + settings + + foreground + #0086b3 + + + + + name + Support Function + scope + source.js support.function + settings + + foreground + #0086b3 + + + + + name + Function Prototype + scope + support.type.object.console.js + settings + + foreground + #795da3 + + + + + + + + + + name + JSON Property - 20 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 20 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 19 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 19 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 18 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 18 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 17 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 17 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 16 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 16 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 15 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 15 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 14 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 14 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 13 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 13 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 12 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 12 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 11 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 11 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 10 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 10 Deep + scope + meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 9 Deep + scope + meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 9 Deep + scope + meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 8 Deep + scope + meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 8 Deep + scope + meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 7 Deep + scope + meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 7 Deep + scope + meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 6 Deep + scope + meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 6 Deep + scope + meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 5 Deep + scope + meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 5 Deep + scope + meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 4 Deep + scope + meta meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 4 Deep + scope + meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 3 Deep + scope + meta meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 3 Deep + scope + meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 2 Deep + scope + meta meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 2 Deep + scope + meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property - 1 Deep + scope + meta meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value - 1 Deep + scope + meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + name + JSON Property + scope + meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #183691 + fontStyle + bold + + + + name + JSON Value + scope + meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #323232 + fontStyle + regular + + + + + + + + + + name + Keyword + scope + source.python keyword + settings + + fontStyle + bold + + + + + name + Storage + scope + source.python storage + settings + + fontStyle + bold + + + + + name + Storage Type + scope + source.python storage.type + settings + + fontStyle + bold + + + + + name + Function + scope + source.python entity.name.function + settings + + foreground + #323232 + fontStyle + bold + + + + + + + + + + name + Class + scope + source.php entity.name.type.class + settings + + foreground + #323232 + fontStyle + bold + + + + + + + + + + name + Language Variable + scope + variable.language.ruby + settings + + foreground + #ed6a43 + + + + + name + Module Name + scope + entity.name.type.module.ruby + settings + + foreground + #795da3 + fontStyle + bold + + + + + name + Class Name + scope + entity.name.type.class.ruby + settings + + foreground + #795da3 + fontStyle + bold + + + + + name + Inherited Class + scope + entity.other.inherited-class.ruby + settings + + foreground + #795da3 + fontStyle + bold + + + + + + + + + + name + Punctuation + scope + punctuation.definition.heading.markdown, punctuation.definition.italic.markdown, punctuation.definition.bold.markdown, punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.metadata.markdown, punctuation.definition.link.markdown, punctuation.definition.blockquote.markdown, punctuation.definition.raw.markdown + settings + + foreground + #a71d5d + + + + + name + Separator + scope + text.html.markdown meta.separator + settings + + foreground + #b3b3b3 + + + + + name + Heading + scope + text.html.markdown markup.heading + settings + + fontStyle + bold + + + + + name + Code Block + scope + text.html.markdown markup.raw.block + settings + + foreground + #323232 + + + + + name + Inline Code + scope + text.html.markdown markup.raw.inline + settings + + foreground + #323232 + + + + + name + Link and Image + scope + text.html.markdown meta.link, text.html.markdown meta.image + settings + + foreground + #4183c4 + + + + name + Link URL + scope + text.html.markdown markup.underline.link, text.html.markdown constant.other.reference + settings + + fontStyle + italic + + + + + name + List + scope + text.html.markdown markup.list + settings + + foreground + #ed6a43 + + + + + name + Bold + scope + text.html.markdown markup.bold + settings + + fontStyle + bold + + + + + name + Italic + scope + text.html.markdown markup.italic + settings + + fontStyle + italic + + + + + name + Bold Italic + scope + text.html.markdown markup.bold markup.italic + settings + + fontStyle + bold italic + + + + + name + Italic Bold + scope + text.html.markdown markup.italic markup.bold + settings + + fontStyle + italic bold + + + + + diff --git a/sublime_themes/kronuz.tmTheme b/sublime_themes/kronuz.tmTheme new file mode 100644 index 00000000..b0e33528 --- /dev/null +++ b/sublime_themes/kronuz.tmTheme @@ -0,0 +1,1843 @@ + + + + + author + github.com/Kronuz + colorSpaceName + sRGB + gutterSettings + + background + #073642 + divider + #586e75 + foreground + #839496 + selectionBackground + #586e75 + selectionForeground + #86c20e + + name + Kronuz + semanticClass + theme.kronuz + settings + + + settings + + activeGuide + #df940088 + background + #383838 + bracketContentsForeground + #f8f8f2a5 + bracketContentsOptions + underline + bracketsForeground + #ff9400 + bracketsOptions + foreground underline + caret + #ffffff + findHighlight + #000000 + findHighlightForeground + #cccccc + foreground + #e6e1dc + invisibles + #404040 + lineHighlight + #60606080 + selection + #3366ff66 + selectionBorder + #1c1c1c + stackGuide + #df940044 + tagsOptions + stippled_underline + + + + name + Comment + scope + comment + settings + + foreground + #95815e + + + + name + String + scope + string + settings + + foreground + #a5c261 + + + + name + String + scope + string.quoted.double + settings + + foreground + #c1be91 + + + + name + String.regexp + scope + string.regexp + settings + + foreground + #a5c261 + + + + name + Number + scope + constant.numeric + settings + + foreground + #a5c261 + + + + name + Constant (built-in) + scope + constant.language, meta.preprocessor + settings + + foreground + #6e9cbe + + + + name + Constant: (user-defined) + scope + constant.character, constant.other + settings + + foreground + #6d9cbe + + + + name + Constant (other variable) + scope + variable.other.constant + settings + + foreground + #da4939 + + + + name + Variable + scope + variable.language, variable.other + settings + + foreground + #d0d0ff + + + + name + Keyword + scope + keyword + settings + + foreground + #cc7833 + + + + name + Storage + scope + storage + settings + + foreground + #cc7833 + + + + name + Storage (type) + scope + storage.type + settings + + fontStyle + italic + foreground + #6e9cbe + + + + name + Function (definition) + scope + entity.name.function, keyword.other.name-of-parameter.objc + settings + + foreground + #ffc66d + + + + name + Function (argument) + scope + variable.parameter + settings + + fontStyle + italic + foreground + #fd971f + + + + name + Class (definition) + scope + entity.name.class + settings + + fontStyle + underline + foreground + #ffc66d + + + + name + Class (inherited) + scope + entity.other.inherited-class + settings + + fontStyle + italic underline + foreground + #ffc66d + + + + name + Block Parameter + scope + variable.other.block + settings + + foreground + #e6e1dc + + + + name + Library function + scope + support.function + settings + + foreground + #da4939 + + + + name + Library constant + scope + support.constant + settings + + foreground + #86c20e + + + + name + Library type + scope + support.type, support.class + settings + + fontStyle + italic + foreground + #6e9cbe + + + + name + Markup tag + scope + meta.tag, declaration.tag, entity.name.tag, entity.other.attribute-name + settings + + foreground + #e8bf6a + + + + name + Invalid + scope + invalid + settings + + background + #b90622 + foreground + #f8f8f0 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + background + #b90682 + foreground + #f8f8f0 + + + + name + String interpolation + scope + constant.character.escaped, constant.character.escape, string source, string source.ruby + settings + + foreground + #519f50 + + + + name + Guide + scope + guide + settings + + foreground + #4c4a4988 + + + + name + Source + scope + source.console + settings + + foreground + #c5c8c6 + + + + name + Diff Header + scope + meta.diff, meta.diff.header, meta.separator.diff, meta.diff.index, meta.diff.range + settings + + foreground + #95815e + + + + name + Diff Remove + scope + markup.deleted + settings + + foreground + #f92640 + + + + name + Diff Add + scope + markup.inserted + settings + + foreground + #86c20e + + + + name + Diff Change + scope + markup.changed + settings + + foreground + #e6db74 + + + + name + Diff Range + scope + meta.diff, meta.diff.range + settings + + foreground + #3bc0f0 + + + + name + TODO: Category Name + scope + todo.category.name + settings + + foreground + #e8bf6a + + + + name + TODO: Urgent + scope + todo.task.urgent + settings + + foreground + #feff00 + + + + name + TODO: Category Extras + scope + todo.category.extras + settings + + foreground + #bc9458 + + + + name + TODO: Task Dormant + scope + todo.task.dormant + settings + + foreground + #807c79 + + + + name + TODO: Task Complete + scope + todo.task.complete + settings + + foreground + #da4939 + + + + name + TODO: Task Question + scope + todo.task.question + settings + + foreground + #82a7e2 + + + + name + TODO: Task Large + scope + todo.task.large + settings + + foreground + #a5c261 + + + + name + HTML: Doctype/XML Processing + scope + meta.tag.sgml.doctype.xml, declaration.sgml.html declaration.doctype, declaration.sgml.html declaration.doctype entity, declaration.sgml.html declaration.doctype string, declaration.xml-processing, declaration.xml-processing entity, declaration.xml-processing string, doctype + settings + + foreground + #c8cecc + + + + name + HTML: Comment Block + scope + comment.block.html + settings + + foreground + #95815e + + + + name + HTML: Script + scope + entity.name.tag.script.html + settings + + fontStyle + italic + + + + name + HTML: Attribute punctuation + scope + text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html + settings + + foreground + #86c20e + + + + name + HTML: Attributes + scope + text.html.basic entity.other.attribute-name.html + settings + + foreground + #86c20e + + + + name + HTML: Quotation Marks + scope + text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html, punctuation.definition.string.begin.html, punctuation.definition.string.end.html + settings + + foreground + #e6e1dc + + + + name + HTML: Tags punctuation + scope + punctuation.definition.tag.end, punctuation.definition.tag.begin, punctuation.definition.tag + settings + + foreground + #e6e1dc + + + + name + Handlebars: Variable + scope + variable.parameter.handlebars + settings + + foreground + #f6aa11 + + + + name + Handlebars: Constant + scope + support.constant.handlebars, meta.function.block.start.handlebars + settings + + foreground + #6e9cbe + + + + name + CSS: @at-rule + scope + meta.preprocessor.at-rule keyword.control.at-rule + settings + + foreground + #f6aa11 + + + + name + CSS: #Id + scope + meta.selector.css entity.other.attribute-name.id + settings + + foreground + #f6aa11 + + + + name + CSS: .class + scope + meta.selector.css entity.other.attribute-name.class + settings + + foreground + #86c20e + + + + name + CSS: Property Name + scope + support.type.property-name.css + settings + + foreground + #6e9cbe + + + + name + CSS: Constructor Argument + scope + meta.constructor.argument.css + settings + + foreground + #f6aa11 + + + + name + CSS: {} + scope + punctuation.section.property-list.css + settings + + foreground + #e6e1dc + + + + name + CSS: Tag Punctuation + scope + punctuation.definition.tag.css + settings + + foreground + #f92672 + + + + name + CSS: : , + scope + punctuation.separator.key-value.css, punctuation.terminator.rule.css + settings + + foreground + #e6e1dc + + + + name + CSS :pseudo + scope + entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css, entity.other.attribute-name.pseudo-selector.css + settings + + foreground + #86c20e + + + + name + LESS variables + scope + variable.other.less + settings + + foreground + #e6e1dc + + + + name + LESS mixins + scope + entity.other.less.mixin + settings + + fontStyle + italic + foreground + #e0fdce + + + + name + LESS: Extend + scope + entity.other.attribute-name.pseudo-element.less + settings + + foreground + #ff9117 + + + + name + JS: Function Name + scope + meta.function.js, entity.name.function.js, support.function.dom.js + settings + + foreground + #86c20e + + + + name + JS: Storage Type + scope + storage.type.js + settings + + fontStyle + italic + foreground + #6e9cbe + + + + name + JS: Source + scope + text.html.basic source.js.embedded.html + settings + + foreground + #e6e1dc + + + + name + JS: Function + scope + storage.type.function.js + settings + + fontStyle + italic + foreground + #6e9cbe + + + + name + JS: Numeric Constant + scope + constant.numeric.js + settings + + foreground + #ae81ff + + + + name + JS: Literal language variable + scope + variable.language.arguments.js, variable.language.super.js, variable.language.this.js, variable.language.self.js, variable.language.proto.js, variable.language.constructor.js, variable.language.prototype.js + settings + + fontStyle + italic + foreground + #6e9cbe + + + + name + JS: [] + scope + meta.brace.square.js + settings + + foreground + #e6e1dc + + + + name + JS: () + scope + meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js + settings + + foreground + #e6e1dc + + + + name + JS: {} + scope + meta.brace.curly.js + settings + + foreground + #e6e1dc + + + + name + JSON String + scope + meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #cfcfc2 + + + + name + CoffeeScript String Interpolated + scope + punctuation.section.embedded.coffee + settings + + foreground + #e69f66 + + + + name + PHP: [] + scope + keyword.operator.index-start.php, keyword.operator.index-end.php + settings + + foreground + #e6e1dc + + + + name + PHP: Array + scope + meta.array.php + settings + + foreground + #e6e1dc + + + + name + PHP: Array() + scope + meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php + settings + + foreground + #e42e70 + + + + name + PHP: Array Construct + scope + support.function.construct.php + settings + + foreground + #e42e70 + + + + name + PHP: Storage Type Function + scope + storage.type.function.php + settings + + foreground + #f92672dd + + + + name + PHP: Numeric Constant + scope + constant.numeric.php + settings + + foreground + #be84ff + + + + name + PHP: New + scope + keyword.other.new.php + settings + + foreground + #f6aa11 + + + + name + PHP: :: + scope + support.class.php + settings + + foreground + #e6e1dc + + + + name + PHP: Other Property + scope + variable.other.property.php + settings + + foreground + #f6aa11 + + + + name + PHP: Class + scope + storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php + settings + + foreground + #86c20e + + + + name + PHP: Inherited Class + scope + meta.other.inherited-class.php + settings + + foreground + #86c20e + + + + name + PHP: Storage Type + scope + storage.type.php + settings + + foreground + #6e9cbe + + + + name + PHP: Function + scope + entity.name.function.php + settings + + foreground + #6e9cbe + + + + name + PHP: Function Construct + scope + support.function.construct.php + settings + + foreground + #86c20e + + + + name + PHP: Function Call + scope + entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php + settings + + foreground + #e6e1dc + + + + name + PHP: Comment + scope + keyword.other.phpdoc + settings + + foreground + #7c7865 + + + + name + PHP: Source Emebedded + scope + source.php.embedded.block.html + settings + + foreground + #e6e1dc + + + + name + Python: storage + scope + storage.type.class.python, storage.type.function.python, storage.modifier.global.python + settings + + foreground + #3bc0f0 + + + + name + Python: import + scope + keyword.control.import.python, keyword.control.import.from.python + settings + + foreground + #f92672dd + + + + name + Python: Support.exception + scope + support.type.exception.python + settings + + foreground + #6e9cbe + + + + name + Perl: variables + scope + punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl + settings + + foreground + #e42e70 + + + + name + Perl: functions + scope + support.function.perl + settings + + foreground + #6e9cbe + + + + name + Perl: comments + scope + comment.line.number-sign.perl + settings + + fontStyle + italic + foreground + #95815e + + + + name + Perl: quotes + scope + punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl + settings + + foreground + #e6e1dc + + + + name + Perl: char + scope + constant.character.escape.perl + settings + + foreground + #dc322f + + + + name + Ruby: Constant + scope + constant.language.ruby, constant.numeric.ruby + settings + + foreground + #ae81ff + + + + name + Ruby: Variable definition + scope + punctuation.definition.variable.ruby + settings + + foreground + #f6aa11 + + + + name + Ruby: Function Name + scope + meta.function.method.with-arguments.ruby + settings + + foreground + #86c20e + + + + name + Ruby: Variable + scope + variable.language.ruby + settings + + foreground + #e6e1dc + + + + name + Ruby: Function + scope + entity.name.function.ruby + settings + + foreground + #f6aa11 + + + + name + Ruby: Keyword Control + scope + keyword.control.ruby, keyword.control.def.ruby + settings + + fontStyle + bold + foreground + #86c20e + + + + name + Ruby: Class + scope + keyword.control.class.ruby, meta.class.ruby + settings + + foreground + #86c20e + + + + name + Ruby: Class Name + scope + entity.name.type.class.ruby + settings + + foreground + #6e9cbe + + + + name + Ruby: Keyword + scope + keyword.control.ruby + settings + + foreground + #86c20e + + + + name + Ruby: Support Class + scope + support.class.ruby + settings + + foreground + #6e9cbe + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #86c20e + + + + name + Ruby: Constant Other + scope + variable.other.constant.ruby + settings + + foreground + #6e9cbe + + + + name + Ruby: :symbol + scope + constant.other.symbol.ruby + settings + + foreground + #f6f080 + + + + name + Ruby: Punctuation Section + scope + punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby + settings + + foreground + #f92672 + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #e42e70 + + + + name + Markdown: plain + scope + text.html.markdown + settings + + foreground + #e6e1dc + + + + name + Markdown: linebreak + scope + text.html.markdown meta.dummy.line-break + settings + + foreground + #e0eddd + + + + name + Markdown: heading + scope + markdown.heading, markup.heading | markup.heading entity.name, markup.heading.markdown punctuation.definition.heading.markdown + settings + + foreground + #fd971f + + + + name + Markup: raw inline + scope + text.html.markdown markup.raw.inline + settings + + foreground + #ec3533 + + + + name + Markup: italic + scope + markup.italic + settings + + fontStyle + italic + foreground + #e42e70 + + + + name + Markup: bold + scope + markup.bold + settings + + fontStyle + bold + foreground + #f92672 + + + + name + Markup: underline + scope + markup.underline + settings + + fontStyle + underline + foreground + #86c20e + + + + name + Markup: strike + scope + markup.strike + settings + + fontStyle + + foreground + #cc4273 + + + + name + Markdown: Blockquote + scope + markup.quote, punctuation.definition.blockquote.markdown + settings + + fontStyle + italic + foreground + #6e9cbe + + + + name + Markup: Quote + scope + markup.quote + settings + + fontStyle + italic + foreground + #6e9cbe + + + + name + Markdown: Link + scope + string.other.link.title.markdown + settings + + fontStyle + underline + foreground + #6e9cbe + + + + name + Markup: Raw block + scope + markup.raw.block + settings + + foreground + #ae81ff + + + + name + Markdown: List Items Punctuation + scope + punctuation.definition.list_item.markdown + settings + + foreground + #e6e1dc + + + + name + Markdown: Raw Block fenced + scope + markup.raw.block.fenced.markdown + settings + + background + #20202060 + foreground + #e6e1dc + + + + name + Markdown: Fenced Bode Block + scope + punctuation.definition.fenced.markdown, variable.language.fenced.markdown + settings + + background + #20202060 + foreground + #636050 + + + + name + Markdown: Fenced Language + scope + variable.language.fenced.markdown + settings + + foreground + #7c7865 + + + + name + Markdown: Separator + scope + meta.separator + settings + + background + #ffffff0f + fontStyle + bold + foreground + #ffffff33 + + + + name + Markup: table + scope + markup.table + settings + + background + #ff3a281a + foreground + #b42a1d + + + + name + Shell: DOTFILES + scope + source.shell + settings + + foreground + #e6e1dc + + + + name + Shell: meta scope in loop + scope + meta.scope.for-in-loop.shell, meta.scope.while-loop.shell, variable.other.loop.shell + settings + + background + #20202020 + foreground + #e6e1dc + + + + name + Shell: meta scope in if + scope + meta.scope.if-block.shell + settings + + background + #20202020 + foreground + #e6e1dc + + + + name + Shell: meta scope in case + scope + meta.scope.case-block.shell + settings + + background + #20202020 + foreground + #e6e1dc + + + + name + Shell: Meta Block + scope + meta.scope.case-block.shell, meta.scope.case-body.shell + settings + + foreground + #fd971f + + + + name + Shell: Comment + scope + comment.line.number-sign.shell + settings + + fontStyle + italic + foreground + #7c7865 + + + + name + Shell: variable + scope + variable.other.normal.shell + settings + + foreground + #6e9cbe + + + + name + Shell: builtin + scope + support.function.builtin.shell + settings + + foreground + #6e9cbe + + + + name + Shell: Function name + scope + entity.name.function.shell + settings + + foreground + #86c20e + + + + name + Shell: keyword + scope + keyword.other.shell + settings + + foreground + #cc7833 + + + + name + Shell: [] + scope + punctuation.definition.logical-expression.shell + settings + + foreground + #e6e1dc + + + + name + Makefile: Comment + scope + comment.line.number-sign.makefile + settings + + foreground + #7c7865 + + + + name + Makefile: Comment punctuation + scope + punctuation.definition.comment.makefile + settings + + foreground + #7c7865 + + + + name + Makefile: Variables + scope + variable.other.makefile + settings + + foreground + #f92672 + + + + name + Makefile: Function name + scope + entity.name.function.makefile + settings + + foreground + #86c20e + + + + name + Makefile: Function + scope + meta.function.makefile + settings + + foreground + #6e9cbe + + + + name + GitGutter deleted + scope + markup.deleted.git_gutter + settings + + foreground + #F92672 + + + + name + GitGutter inserted + scope + markup.inserted.git_gutter + settings + + foreground + #A6E22E + + + + name + GitGutter changed + scope + markup.changed.git_gutter + settings + + foreground + #967EFB + + + + name + GitGutter ignored + scope + markup.ignored.git_gutter + settings + + foreground + #565656 + + + + name + GitGutter untracked + scope + markup.untracked.git_gutter + settings + + foreground + #565656 + + + + name + Nginx path + scope + string.other.path.nginx + settings + + foreground + #fc951e + + + + name + Django: Template Tag + scope + meta.scope.django.template.tag + settings + + background + #00000010 + + + + name + Django: Template Variable + scope + variable.other.django.template + settings + + background + #00000010 + + + + name + Django: Template Braces + scope + entity.other.django.tagbraces + settings + + foreground + #cc7833 + + + + name + Other: Removal + scope + other.package.exclude, other.remove + settings + + foreground + #d3201f + + + + name + Raw New Line: Carriage Rerturn + scope + glyph.carriage-return + settings + + foreground + #66cccc + + + + name + Raw New Line: New Line Glyph + scope + glyph.new-line + settings + + foreground + #f2777a + + + + uuid + 7126a769-fb8c-4004-9141-bd2f620fd3f4 + + diff --git a/sublime_themes/material-dark.tmTheme b/sublime_themes/material-dark.tmTheme new file mode 100644 index 00000000..4467f2c6 --- /dev/null +++ b/sublime_themes/material-dark.tmTheme @@ -0,0 +1,1011 @@ + + + + + author + Mattia Astorino + colorSpaceName + sRGB + name + Material-Theme-Darker + semanticClass + material.theme.darker + settings + + + settings + + activeGuide + #FFFFFF50 + background + #212121 + caret + #FFCC00 + findHighlight + #F8E71C + foreground + #eeffffff + guide + #42424270 + gutterForeground + #424242 + invisibles + #65737e + lineHighlight + #00000050 + popupCss + + selection + #61616150 + selectionBorder + #61616150 + shadow + #00000010 + stackGuide + #42424280 + + + + name + Comments + scope + comment, punctuation.definition.comment + settings + + fontStyle + italic + foreground + #4A4A4A + + + + name + Variable + scope + variable, string constant.other.placeholder + settings + + foreground + #eeffffff + + + + name + Colors + scope + constant.other.color + settings + + foreground + #ffffff + + + + name + Invalid + scope + invalid, invalid.illegal, invalid.broken + settings + + background + #FF5370 + foreground + #ffffff + + + + name + Unimplemented + scope + invalid.unimplemented + settings + + background + #C3E88D + foreground + #ffffff + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + background + #C792EA + foreground + #ffffff + + + + name + Keyword, Storage + scope + keyword, storage.type, storage.modifier + settings + + foreground + #C792EA + + + + name + Keyword, Storage + scope + storage.type, keyword.control + settings + + fontStyle + italic + + + + name + Operator, Misc + scope + keyword.operator, constant.other.color, punctuation, meta.tag, punctuation.definition.tag, punctuation.separator.inheritance.php, punctuation.definition.tag.html, punctuation.definition.tag.begin.html, punctuation.definition.tag.end.html, punctuation.section.embedded, keyword.other.template, keyword.other.substitution + settings + + foreground + #89DDFF + + + + name + Tag + scope + entity.name.tag, meta.tag.sgml, markup.deleted.git_gutter + settings + + foreground + #f07178 + + + + name + Function, Special Method, Block Level + scope + entity.name.function, meta.function-call, variable.function, support.function, keyword.other.special-method, meta.block-level + settings + + foreground + #82AAFF + + + + name + Other Variable, String Link + scope + support.other.variable, string.other.link + settings + + foreground + #f07178 + + + + name + Number, Constant, Function Argument, Tag Attribute, Embedded + scope + constant.numeric, constant.language, support.constant, constant.character, variable.parameter, keyword.other.unit + settings + + foreground + #F78C6C + + + + name + String, Symbols, Inherited Class, Markup Heading + scope + string, constant.other.symbol, constant.other.key, entity.other.inherited-class, markup.heading, markup.inserted.git_gutter, meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js + settings + + fontStyle + normal + foreground + #C3E88D + + + + name + Class, Support + scope + entity.name.class, entity.name.type.class, support.type, support.class, support.orther.namespace.use.php, meta.use.php, support.other.namespace.php, markup.changed.git_gutter, support.type.sys-types + settings + + foreground + #FFCB6B + + + + name + CSS Class and Support + scope + source.css support.type, source.sass support.type, source.scss support.type, source.less support.type, source.stylus support.type + settings + + foreground + #B2CCD6 + + + + name + Sub-methods + scope + entity.name.module.js, variable.import.parameter.js, variable.other.class.js + settings + + foreground + #FF5370 + + + + name + Language methods + scope + variable.language + settings + + fontStyle + italic + foreground + #FF5370 + + + + name + entity.name.method.js + scope + entity.name.method.js + settings + + foreground + #82AAFF + + + + name + meta.method.js + scope + meta.class-method.js entity.name.function.js, variable.function.constructor + settings + + foreground + #82AAFF + + + + name + Attributes + scope + entity.other.attribute-name + settings + + foreground + #C792EA + + + + name + HTML Attributes + scope + text.html.basic entity.other.attribute-name.html, text.html.basic entity.other.attribute-name + settings + + fontStyle + italic + foreground + #FFCB6B + + + + name + CSS Classes + scope + entity.other.attribute-name.class + settings + + foreground + #FFCB6B + + + + name + CSS Id + scope + source.sass keyword.control + settings + + foreground + #82AAFF + + + + name + Inserted + scope + markup.inserted + settings + + foreground + #C3E88D + + + + name + Deleted + scope + markup.deleted + settings + + foreground + #FF5370 + + + + name + Changed + scope + markup.changed + settings + + foreground + #C792EA + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #89DDFF + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #89DDFF + + + + name + URL + scope + *url*, *link*, *uri* + settings + + fontStyle + underline + + + + name + Search Results Nums + scope + constant.numeric.line-number.find-in-files - match + settings + + foreground + #C17E70 + + + + name + Search Results Lines + scope + entity.name.filename.find-in-files + settings + + foreground + #C3E88D + + + + name + Decorators + scope + tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js + settings + + fontStyle + italic + foreground + #82AAFF + + + + name + ES7 Bind Operator + scope + source.js constant.other.object.key.js string.unquoted.label.js + settings + + fontStyle + italic + foreground + #FF5370 + + + + name + JSON Key - Level 8 + scope + source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #C3E88D + + + + name + JSON Key - Level 7 + scope + source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #C792EA + + + + name + JSON Key - Level 6 + scope + source.json meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #f07178 + + + + name + JSON Key - Level 5 + scope + source.json meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #82AAFF + + + + name + JSON Key - Level 4 + scope + source.json meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #C17E70 + + + + name + JSON Key - Level 3 + scope + source.json meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #FF5370 + + + + name + JSON Key - Level 2 + scope + source.json meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #F78C6C + + + + name + JSON Key - Level 1 + scope + source.json meta meta.structure.dictionary.json string.quoted.double.json - meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta.structure.dictionary.json punctuation.definition.string - meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #FFCB6B + + + + name + JSON Key - Level 0 + scope + source.json meta.structure.dictionary.json string.quoted.double.json - meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json punctuation.definition.string - meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #C792EA + + + + name + Markdown - Plain + scope + text.html.markdown, punctuation.definition.list_item.markdown + settings + + foreground + #eeffffff + + + + name + Markdown - Markup Raw Inline + scope + text.html.markdown markup.raw.inline + settings + + foreground + #C792EA + + + + name + Markdown - Markup Raw Inline Punctuation + scope + text.html.markdown punctuation.definition.raw.markdown + settings + + foreground + #65737e + + + + name + Markdown - Line Break + scope + text.html.markdown meta.dummy.line-break + settings + + foreground + + + + + name + Markdown - Heading + scope + markdown.heading, markup.heading | markup.heading entity.name, markup.heading.markdown punctuation.definition.heading.markdown + settings + + foreground + #C3E88D + + + + name + Markup - Italic + scope + markup.italic + settings + + fontStyle + italic + foreground + #f07178 + + + + name + Markup - Bold + scope + markup.bold, markup.bold string + settings + + fontStyle + bold + foreground + #f07178 + + + + name + Markup - Bold & Italic + scope + markup.bold markup.italic, markup.italic markup.bold, markup.quote markup.bold, markup.bold markup.italic string, markup.italic markup.bold string, markup.quote markup.bold string + settings + + fontStyle + bold italic + + + + name + Markup - Underline + scope + markup.underline + settings + + fontStyle + underline + foreground + #F78C6C + + + + name + Markup - Strike + scope + markup.strike + settings + + fontStyle + strike + foreground + + + + + name + Markdown - Blockquote + scope + markup.quote punctuation.definition.blockquote.markdown + settings + + background + #65737e + foreground + #65737e + + + + name + Markup - Quote + scope + markup.quote + settings + + fontStyle + italic + foreground + + + + + name + Markdown - Link + scope + string.other.link.title.markdown + settings + + foreground + #82AAFF + + + + name + Markdown - Link Description + scope + string.other.link.description.title.markdown + settings + + foreground + #C792EA + + + + name + Markdown - Link Anchor + scope + constant.other.reference.link.markdown + settings + + foreground + #FFCB6B + + + + name + Markup - Raw Block + scope + markup.raw.block + settings + + foreground + #C792EA + + + + name + Markdown - Raw Block Fenced + scope + markup.raw.block.fenced.markdown + settings + + background + #00000050 + + + + name + Markdown - Fenced Bode Block + scope + punctuation.definition.fenced.markdown + settings + + background + #00000050 + + + + name + Markdown - Fenced Bode Block Variable + scope + markup.raw.block.fenced.markdown, variable.language.fenced.markdown, punctuation.section.class.end + settings + + foreground + #eeffffff + + + + name + Markdown - Fenced Language + scope + variable.language.fenced.markdown + settings + + fontStyle + + foreground + #65737e + + + + name + Markdown - Punctuation Definition + scope + text.html.markdown punctuation.definition + settings + + foreground + #4A4A4A + + + + name + Markdown HTML - Punctuation Definition + scope + text.html.markdown meta.disable-markdown punctuation.definition + settings + + foreground + #89DDFF + + + + name + Markdown - Separator + scope + meta.separator + settings + + background + #00000050 + fontStyle + bold + foreground + #65737e + + + + name + Markup - Table + scope + markup.table + settings + + background + + foreground + #eeffffff + + + + name + AceJump Label - Blue + scope + acejump.label.blue + settings + + background + #82AAFF + foreground + #ffffff + + + + name + AceJump Label - Green + scope + acejump.label.green + settings + + background + #C3E88D + foreground + #ffffff + + + + name + AceJump Label - Orange + scope + acejump.label.orange + settings + + background + #F78C6C + foreground + #ffffff + + + + name + AceJump Label - Purple + scope + acejump.label.purple + settings + + background + #C792EA + foreground + #ffffff + + + + name + SublimeLinter Warning + scope + sublimelinter.mark.warning + settings + + foreground + #FFCB6B + + + + name + SublimeLinter Gutter Mark + scope + sublimelinter.gutter-mark + settings + + foreground + #ffffff + + + + name + SublimeLinter Error + scope + sublimelinter.mark.error + settings + + foreground + #FF5370 + + + + name + SublimeLinter Annotation + scope + sublimelinter.annotations + settings + + background + #C17E70 + + + + name + GitGutter Ignored + scope + markup.ignored.git_gutter + settings + + foreground + #65737e + + + + name + GitGutter Untracked + scope + markup.untracked.git_gutter + settings + + foreground + #65737e + + + + name + GitGutter Inserted + scope + markup.inserted.git_gutter + settings + + foreground + #C3E88D + + + + name + GitGutter Changed + scope + markup.changed.git_gutter + settings + + foreground + #FFCB6B + + + + name + GitGutter Deleted + scope + markup.deleted.git_gutter + settings + + foreground + #FF5370 + + + + name + Bracket Curly + scope + brackethighlighter.default + settings + + foreground + #B2CCD6 + + + + name + Bracket Quote + scope + brackethighlighter.quote + settings + + foreground + #C3E88D + + + + name + Bracket Unmatched + scope + brackethighlighter.unmatched + settings + + foreground + #FF5370 + + + + uuid + 4F44C0F5-1F8D-4C52-8BAB-F0951904C1EC + + diff --git a/sublime_themes/material-light.tmTheme b/sublime_themes/material-light.tmTheme new file mode 100644 index 00000000..fa85508a --- /dev/null +++ b/sublime_themes/material-light.tmTheme @@ -0,0 +1,1011 @@ + + + + + author + Mattia Astorino + colorSpaceName + sRGB + name + Material-Theme-Lighter + semanticClass + material.theme.lighter + settings + + + settings + + activeGuide + #00000070 + background + #fafafa + caret + #27272790 + findHighlight + #F8E71C + foreground + #80CBC4 + guide + #B0BEC570 + gutterForeground + #CFD8DC + invisibles + #E7EAEC + lineHighlight + #90A4AE20 + popupCss + + selection + #80CBC440 + selectionBorder + #80CBC440 + shadow + #90A4AE50 + stackGuide + #B0BEC580 + + + + name + Comments + scope + comment, punctuation.definition.comment + settings + + fontStyle + italic + foreground + #CCD7DA + + + + name + Variable + scope + variable, string constant.other.placeholder + settings + + foreground + #80CBC4 + + + + name + Colors + scope + constant.other.color + settings + + foreground + #ffffff + + + + name + Invalid + scope + invalid, invalid.illegal, invalid.broken + settings + + background + #E53935 + foreground + #ffffff + + + + name + Unimplemented + scope + invalid.unimplemented + settings + + background + #91B859 + foreground + #ffffff + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + background + #7C4DFF + foreground + #ffffff + + + + name + Keyword, Storage + scope + keyword, storage.type, storage.modifier + settings + + foreground + #7C4DFF + + + + name + Keyword, Storage + scope + storage.type, keyword.control + settings + + fontStyle + italic + + + + name + Operator, Misc + scope + keyword.operator, constant.other.color, punctuation, meta.tag, punctuation.definition.tag, punctuation.separator.inheritance.php, punctuation.definition.tag.html, punctuation.definition.tag.begin.html, punctuation.definition.tag.end.html, punctuation.section.embedded, keyword.other.template, keyword.other.substitution + settings + + foreground + #39ADB5 + + + + name + Tag + scope + entity.name.tag, meta.tag.sgml, markup.deleted.git_gutter + settings + + foreground + #FF5370 + + + + name + Function, Special Method, Block Level + scope + entity.name.function, meta.function-call, variable.function, support.function, keyword.other.special-method, meta.block-level + settings + + foreground + #6182B8 + + + + name + Other Variable, String Link + scope + support.other.variable, string.other.link + settings + + foreground + #FF5370 + + + + name + Number, Constant, Function Argument, Tag Attribute, Embedded + scope + constant.numeric, constant.language, support.constant, constant.character, variable.parameter, keyword.other.unit + settings + + foreground + #F76D47 + + + + name + String, Symbols, Inherited Class, Markup Heading + scope + string, constant.other.symbol, constant.other.key, entity.other.inherited-class, markup.heading, markup.inserted.git_gutter, meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js + settings + + fontStyle + normal + foreground + #91B859 + + + + name + Class, Support + scope + entity.name.class, entity.name.type.class, support.type, support.class, support.orther.namespace.use.php, meta.use.php, support.other.namespace.php, markup.changed.git_gutter, support.type.sys-types + settings + + foreground + #FFB62C + + + + name + CSS Class and Support + scope + source.css support.type, source.sass support.type, source.scss support.type, source.less support.type, source.stylus support.type + settings + + foreground + #8796B0 + + + + name + Sub-methods + scope + entity.name.module.js, variable.import.parameter.js, variable.other.class.js + settings + + foreground + #E53935 + + + + name + Language methods + scope + variable.language + settings + + fontStyle + italic + foreground + #E53935 + + + + name + entity.name.method.js + scope + entity.name.method.js + settings + + foreground + #6182B8 + + + + name + meta.method.js + scope + meta.class-method.js entity.name.function.js, variable.function.constructor + settings + + foreground + #6182B8 + + + + name + Attributes + scope + entity.other.attribute-name + settings + + foreground + #7C4DFF + + + + name + HTML Attributes + scope + text.html.basic entity.other.attribute-name.html, text.html.basic entity.other.attribute-name + settings + + fontStyle + italic + foreground + #FFB62C + + + + name + CSS Classes + scope + entity.other.attribute-name.class + settings + + foreground + #FFB62C + + + + name + CSS Id + scope + source.sass keyword.control + settings + + foreground + #6182B8 + + + + name + Inserted + scope + markup.inserted + settings + + foreground + #91B859 + + + + name + Deleted + scope + markup.deleted + settings + + foreground + #E53935 + + + + name + Changed + scope + markup.changed + settings + + foreground + #7C4DFF + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #39ADB5 + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #39ADB5 + + + + name + URL + scope + *url*, *link*, *uri* + settings + + fontStyle + underline + + + + name + Search Results Nums + scope + constant.numeric.line-number.find-in-files - match + settings + + foreground + #C17E70 + + + + name + Search Results Lines + scope + entity.name.filename.find-in-files + settings + + foreground + #91B859 + + + + name + Decorators + scope + tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js + settings + + fontStyle + italic + foreground + #6182B8 + + + + name + ES7 Bind Operator + scope + source.js constant.other.object.key.js string.unquoted.label.js + settings + + fontStyle + italic + foreground + #E53935 + + + + name + JSON Key - Level 8 + scope + source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #91B859 + + + + name + JSON Key - Level 7 + scope + source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #7C4DFF + + + + name + JSON Key - Level 6 + scope + source.json meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #FF5370 + + + + name + JSON Key - Level 5 + scope + source.json meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #6182B8 + + + + name + JSON Key - Level 4 + scope + source.json meta meta meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #C17E70 + + + + name + JSON Key - Level 3 + scope + source.json meta meta meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #E53935 + + + + name + JSON Key - Level 2 + scope + source.json meta meta meta meta.structure.dictionary.json string.quoted.double.json - meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta meta meta.structure.dictionary.json punctuation.definition.string - meta meta meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #F76D47 + + + + name + JSON Key - Level 1 + scope + source.json meta meta.structure.dictionary.json string.quoted.double.json - meta meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta meta.structure.dictionary.json punctuation.definition.string - meta meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #FFB62C + + + + name + JSON Key - Level 0 + scope + source.json meta.structure.dictionary.json string.quoted.double.json - meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json punctuation.definition.string - meta.structure.dictionary.json meta.structure.dictionary.value.json punctuation.definition.string + settings + + foreground + #7C4DFF + + + + name + Markdown - Plain + scope + text.html.markdown, punctuation.definition.list_item.markdown + settings + + foreground + #80CBC4 + + + + name + Markdown - Markup Raw Inline + scope + text.html.markdown markup.raw.inline + settings + + foreground + #7C4DFF + + + + name + Markdown - Markup Raw Inline Punctuation + scope + text.html.markdown punctuation.definition.raw.markdown + settings + + foreground + #E7EAEC + + + + name + Markdown - Line Break + scope + text.html.markdown meta.dummy.line-break + settings + + foreground + + + + + name + Markdown - Heading + scope + markdown.heading, markup.heading | markup.heading entity.name, markup.heading.markdown punctuation.definition.heading.markdown + settings + + foreground + #91B859 + + + + name + Markup - Italic + scope + markup.italic + settings + + fontStyle + italic + foreground + #FF5370 + + + + name + Markup - Bold + scope + markup.bold, markup.bold string + settings + + fontStyle + bold + foreground + #FF5370 + + + + name + Markup - Bold & Italic + scope + markup.bold markup.italic, markup.italic markup.bold, markup.quote markup.bold, markup.bold markup.italic string, markup.italic markup.bold string, markup.quote markup.bold string + settings + + fontStyle + bold italic + + + + name + Markup - Underline + scope + markup.underline + settings + + fontStyle + underline + foreground + #F76D47 + + + + name + Markup - Strike + scope + markup.strike + settings + + fontStyle + strike + foreground + + + + + name + Markdown - Blockquote + scope + markup.quote punctuation.definition.blockquote.markdown + settings + + background + #E7EAEC + foreground + #E7EAEC + + + + name + Markup - Quote + scope + markup.quote + settings + + fontStyle + italic + foreground + + + + + name + Markdown - Link + scope + string.other.link.title.markdown + settings + + foreground + #6182B8 + + + + name + Markdown - Link Description + scope + string.other.link.description.title.markdown + settings + + foreground + #7C4DFF + + + + name + Markdown - Link Anchor + scope + constant.other.reference.link.markdown + settings + + foreground + #FFB62C + + + + name + Markup - Raw Block + scope + markup.raw.block + settings + + foreground + #7C4DFF + + + + name + Markdown - Raw Block Fenced + scope + markup.raw.block.fenced.markdown + settings + + background + #90A4AE20 + + + + name + Markdown - Fenced Bode Block + scope + punctuation.definition.fenced.markdown + settings + + background + #90A4AE20 + + + + name + Markdown - Fenced Bode Block Variable + scope + markup.raw.block.fenced.markdown, variable.language.fenced.markdown, punctuation.section.class.end + settings + + foreground + #80CBC4 + + + + name + Markdown - Fenced Language + scope + variable.language.fenced.markdown + settings + + fontStyle + + foreground + #E7EAEC + + + + name + Markdown - Punctuation Definition + scope + text.html.markdown punctuation.definition + settings + + foreground + #CCD7DA + + + + name + Markdown HTML - Punctuation Definition + scope + text.html.markdown meta.disable-markdown punctuation.definition + settings + + foreground + #39ADB5 + + + + name + Markdown - Separator + scope + meta.separator + settings + + background + #90A4AE20 + fontStyle + bold + foreground + #E7EAEC + + + + name + Markup - Table + scope + markup.table + settings + + background + + foreground + #80CBC4 + + + + name + AceJump Label - Blue + scope + acejump.label.blue + settings + + background + #6182B8 + foreground + #ffffff + + + + name + AceJump Label - Green + scope + acejump.label.green + settings + + background + #91B859 + foreground + #ffffff + + + + name + AceJump Label - Orange + scope + acejump.label.orange + settings + + background + #F76D47 + foreground + #ffffff + + + + name + AceJump Label - Purple + scope + acejump.label.purple + settings + + background + #7C4DFF + foreground + #ffffff + + + + name + SublimeLinter Warning + scope + sublimelinter.mark.warning + settings + + foreground + #FFB62C + + + + name + SublimeLinter Gutter Mark + scope + sublimelinter.gutter-mark + settings + + foreground + #ffffff + + + + name + SublimeLinter Error + scope + sublimelinter.mark.error + settings + + foreground + #E53935 + + + + name + SublimeLinter Annotation + scope + sublimelinter.annotations + settings + + background + #C17E70 + + + + name + GitGutter Ignored + scope + markup.ignored.git_gutter + settings + + foreground + #E7EAEC + + + + name + GitGutter Untracked + scope + markup.untracked.git_gutter + settings + + foreground + #E7EAEC + + + + name + GitGutter Inserted + scope + markup.inserted.git_gutter + settings + + foreground + #91B859 + + + + name + GitGutter Changed + scope + markup.changed.git_gutter + settings + + foreground + #FFB62C + + + + name + GitGutter Deleted + scope + markup.deleted.git_gutter + settings + + foreground + #E53935 + + + + name + Bracket Curly + scope + brackethighlighter.default + settings + + foreground + #8796B0 + + + + name + Bracket Quote + scope + brackethighlighter.quote + settings + + foreground + #91B859 + + + + name + Bracket Unmatched + scope + brackethighlighter.unmatched + settings + + foreground + #E53935 + + + + uuid + 133d1250-19c6-4565-bc93-b37fd36f7fc9 + + diff --git a/sublime_themes/monokai.tmTheme b/sublime_themes/monokai.tmTheme new file mode 100644 index 00000000..edf20142 --- /dev/null +++ b/sublime_themes/monokai.tmTheme @@ -0,0 +1,297 @@ + + + + + + + + + name + Monokai + settings + + + settings + + background + #272822 + caret + #F8F8F0 + foreground + #F8F8F2 + invisibles + #3B3A32 + lineHighlight + #3E3D32 + selection + #49483E + + + + name + Comment + scope + comment + settings + + foreground + #75715E + + + + name + String + scope + string + settings + + foreground + #E6DB74 + + + + name + Number + scope + constant.numeric + settings + + foreground + #AE81FF + + + + name + Built-in constant + scope + constant.language + settings + + foreground + #AE81FF + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #AE81FF + + + + name + Variable + scope + variable + settings + + fontStyle + + + + + name + Keyword + scope + keyword + settings + + foreground + #F92672 + + + + name + Storage + scope + storage + settings + + fontStyle + + foreground + #F92672 + + + + name + Storage type + scope + storage.type + settings + + fontStyle + italic + foreground + #66D9EF + + + + name + Class name + scope + entity.name.class + settings + + fontStyle + underline + foreground + #A6E22E + + + + name + Inherited class + scope + entity.other.inherited-class + settings + + fontStyle + italic underline + foreground + #A6E22E + + + + name + Function name + scope + entity.name.function + settings + + fontStyle + + foreground + #A6E22E + + + + name + Function argument + scope + variable.parameter + settings + + fontStyle + italic + foreground + #FD971F + + + + name + Tag name + scope + entity.name.tag + settings + + fontStyle + + foreground + #F92672 + + + + name + Tag attribute + scope + entity.other.attribute-name + settings + + fontStyle + + foreground + #A6E22E + + + + name + Library function + scope + support.function + settings + + fontStyle + + foreground + #66D9EF + + + + name + Library constant + scope + support.constant + settings + + fontStyle + + foreground + #66D9EF + + + + name + Library class/type + scope + support.type, support.class + settings + + fontStyle + italic + foreground + #66D9EF + + + + name + Library variable + scope + support.other.variable + settings + + fontStyle + + + + + name + Invalid + scope + invalid + settings + + background + #F92672 + fontStyle + + foreground + #F8F8F0 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + background + #AE81FF + foreground + #F8F8F0 + + + + uuid + D8D5E82E-3D5B-46B5-B38E-8C841C21347D + colorSpaceName + sRGB + semanticClass + theme.dark.monokai + + \ No newline at end of file diff --git a/sublime_themes/solarized-dark.tmTheme b/sublime_themes/solarized-dark.tmTheme new file mode 100644 index 00000000..b39a1395 --- /dev/null +++ b/sublime_themes/solarized-dark.tmTheme @@ -0,0 +1,1189 @@ + + + + + name + Solarized (dark) + settings + + + + + settings + + background + #002b36 + caret + #eee8d5 + foreground + #839496 + gutter + #073642 + invisibles + #586e75 + lineHighlight + #073642 + selection + #2c4c55 + selectionBorder + #586e75 + + + + + + + + + + + name + Comment + scope + comment, meta.documentation + settings + + foreground + #586e75 + + + + name + String + scope + string + settings + + foreground + #2aa198 + + + + name + Regexp + scope + string.regexp + settings + + foreground + #2aa198 + + + + name + Escape \ char + scope + constant.character.escape + settings + + foreground + #dc322f + + + + name + Number + scope + constant.numeric + settings + + foreground + #6c71c4 + + + + name + Variable + scope + variable + settings + + foreground + #268bd2 + + + + name + Keyword + scope + keyword + settings + + foreground + #859900 + + + + name + Import + scope + meta.import keyword, keyword.control.import, keyword.control.import.from, keyword.other.import, keyword.control.at-rule.include, keyword.control.at-rule.import + settings + + foreground + #cb4b16 + + + + name + Arithmetical, Assignment, Comparision Operators + scope + keyword.operator.comparison, keyword.operator.assignment, keyword.operator.arithmetic + settings + + foreground + #657b83 + + + + name + Storage + scope + storage + settings + + foreground + #859900 + + + + name + Class + scope + keyword.control.class, meta.class, entity.name.class, entity.name.type.class + settings + + foreground + #b58900 + + + + name + Library class + scope + support.type, support.class + settings + + foreground + #859900 + + + + name + Function name + scope + entity.name.function + settings + + foreground + #b58900 + + + + name + Variable start + scope + punctuation.definition.variable + settings + + foreground + #859900 + + + + name + Built-in constant + scope + constant.language, meta.preprocessor + settings + + foreground + #b58900 + + + + name + Support.construct + scope + support.function.construct, keyword.other.new + settings + + foreground + #dc322f + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #cb4b16 + + + + name + Tag name + scope + entity.name.tag + settings + + foreground + #268bd2 + + + + name + Tag start/end + scope + punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end + settings + + foreground + #586e75 + + + + name + Library function + scope + support.function + settings + + foreground + #859900 + + + + name + Continuation + scope + punctuation.separator.continuation + settings + + foreground + #dc322f + + + + name + Storage Type + scope + storage.type + settings + + foreground + #268bd2 + + + + name + Exception + scope + support.type.exception + settings + + foreground + #cb4b16 + + + + name + Special + scope + keyword.other.special-method + settings + + foreground + #cb4b16 + + + + name + Invalid + scope + invalid + settings + + background + #6e2e32 + + + + name + Quoted String + scope + string.quoted.double, string.quoted.single + settings + + foreground + #2aa198 + + + + name + Quoted Single + scope + punctuation.definition.string.begin, punctuation.definition.string.end + settings + + foreground + #839496 + + + + name + [] + scope + meta.brace.square + settings + + foreground + #268bd2 + + + + name + () + scope + meta.brace.round, punctuation.definition.parameters.begin, punctuation.definition.parameters.end + settings + + foreground + #657b83 + + + + name + {} + scope + meta.brace.curly + settings + + foreground + #657b83 + + + + + + + + name + CSS: Standard color value + scope + support.constant.color, invalid.deprecated.color.w3c-non-standard-color-name.scss + settings + + foreground + #b58900 + + + + name + CSS: Selector > [] and non-spec tags + scope + meta.selector.css + settings + + foreground + #657b83 + + + + name + CSS: Tag + scope + entity.name.tag.css, entity.name.tag.scss, source.less keyword.control.html.elements, source.sass keyword.control.untitled + settings + + foreground + #b58900 + + + + name + CSS .class + scope + entity.other.attribute-name.class.css, entity.other.attribute-name.class.sass + settings + + foreground + #b58900 + + + + name + CSS: #id + scope + source.css entity.other.attribute-name.id, source.less entity.other.attribute-name.id, source.scss entity.other.attribute-name.id, source.sass entity.other.attribute-name.id + settings + + foreground + #b58900 + + + + name + CSS :pseudo + scope + entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class, entity.other.attribute-name.tag.pseudo-class + settings + + foreground + #268bd2 + + + + + + name + HTML: = + scope + text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html + settings + + foreground + #657b83 + + + + name + HTML: something= + scope + text.html.basic entity.other.attribute-name.html, meta.tag.xml entity.other.attribute-name + settings + + foreground + #b58900 + + + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #859900 + + + + name + Ruby: Constant Other + scope + variable.other.constant.ruby + settings + + foreground + #b58900 + + + + name + Ruby: :symbol + scope + constant.other.symbol.ruby + settings + + foreground + #2aa198 + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #cb4b16 + + + + + + name + PHP: Array() + scope + meta.array support.function.construct.php + settings + + foreground + #b58900 + + + + + + name + C: Preprocessor + scope + entity.name.function.preprocessor.c, meta.preprocessor.c.include, meta.preprocessor.macro.c + settings + + foreground + #cb4b16 + + + + name + C: include + scope + meta.preprocessor.c.include string, meta.preprocessor.c.include punctuation.definition.string.begin, meta.preprocessor.c.include punctuation.definition.string.end + settings + + foreground + #2aa198 + + + + + + name + Other: Removal + scope + other.package.exclude, other.remove + settings + + foreground + #dc322f + + + + name + Other: Add + scope + other.add + settings + + foreground + #2aa198 + + + + + + name + Tex: {} + scope + punctuation.section.group.tex , punctuation.definition.arguments.begin.latex, punctuation.definition.arguments.end.latex, punctuation.definition.arguments.latex + settings + + foreground + #dc322f + + + + name + Tex: {text} + scope + meta.group.braces.tex + settings + + foreground + #b58900 + + + + name + Tex: Other Math + scope + string.other.math.tex + settings + + foreground + #b58900 + + + + name + Tex: {var} + scope + variable.parameter.function.latex + settings + + foreground + #cb4b16 + + + + name + Tex: Math \\ + scope + punctuation.definition.constant.math.tex + settings + + foreground + #dc322f + + + + name + Tex: Constant Math + scope + text.tex.latex constant.other.math.tex, constant.other.general.math.tex, constant.other.general.math.tex, constant.character.math.tex + settings + + foreground + #2aa198 + + + + name + Tex: Other Math String + scope + string.other.math.tex + settings + + foreground + #b58900 + + + + name + Tex: $ + scope + punctuation.definition.string.begin.tex, punctuation.definition.string.end.tex + settings + + foreground + #dc322f + + + + name + Tex: \label + scope + keyword.control.label.latex, text.tex.latex constant.other.general.math.tex + settings + + foreground + #2aa198 + + + + name + Tex: \label { } + scope + variable.parameter.definition.label.latex + settings + + foreground + #dc322f + + + + name + Tex: Function + scope + support.function.be.latex + settings + + foreground + #859900 + + + + name + Tex: Support Function Section + scope + support.function.section.latex + settings + + foreground + #cb4b16 + + + + name + Tex: Support Function + scope + support.function.general.tex + settings + + foreground + #2aa198 + + + + name + Tex: Reference Label + scope + keyword.control.ref.latex + settings + + foreground + #2aa198 + + + + + + name + Python: storage + scope + storage.type.class.python, storage.type.function.python, storage.modifier.global.python + settings + + foreground + #859900 + + + + name + Python: Support.exception + scope + support.type.exception.python + settings + + foreground + #b58900 + + + + + + name + Shell: meta scope in loop + scope + meta.scope.for-in-loop.shell, variable.other.loop.shell + settings + + foreground + #586e75 + + + + name + Shell: Meta Block + scope + meta.scope.case-block.shell, meta.scope.case-body.shell + settings + + foreground + #586e75 + + + + name + Shell: [] + scope + punctuation.definition.logical-expression.shell + settings + + foreground + #dc322f + + + + + + name + Java: storage import + scope + storage.modifier.import.java + settings + + foreground + #93a1a1 + + + + + + name + Perl: functions + scope + support.function.perl + settings + + foreground + #268bd2 + + + + + + name + diff: header + scope + meta.diff, meta.diff.header + settings + + foreground + #586e75 + + + + name + diff: range + scope + meta.diff.range + settings + + foreground + #268bd2 + + + + name + diff: deleted + scope + markup.deleted + settings + + foreground + #dc322f + + + + name + diff: changed + scope + markup.changed + settings + + foreground + #2aa198 + + + + name + diff: inserted + scope + markup.inserted + settings + + foreground + #859900 + + + + + + Name + Markdown heading + scope + markup.heading, punctuation.definition.heading.markdown + settings + + foreground + #b58900 + + + + name + Markdown quote + scope + markup.quote + settings + + foreground + #859900 + + + + name + Markdown em + scope + markup.italic + settings + + fontStyle + italic + + + + Name + Markdown strong + scope + markup.bold + settings + + fontStyle + bold + + + + Name + Markdown reference + scope + markup.underline.link.markdown, meta.link.reference constant.other.reference.link.markdown + settings + + foreground + #2aa198 + + + + Name + Markdown reference list + scope + constant.other.reference.link.markdown + settings + + foreground + #6c71c4 + + + + Name + Markdown linebreak + scope + meta.paragraph.markdown meta.dummy.line-break + settings + + background + #586e75 + + + + + + name + SublimeLinter Annotations + scope + sublimelinter.notes + settings + + background + #586e75 + foreground + #586e75 + + + + name + SublimeLinter Error Outline + scope + sublimelinter.outline.illegal + settings + + background + #586e75 + foreground + #586e75 + + + + name + SublimeLinter Error Underline + scope + sublimelinter.underline.illegal + settings + + background + #dc322f + + + + name + SublimeLinter Warning Outline + scope + sublimelinter.outline.warning + settings + + background + #839496 + foreground + #839496 + + + + name + SublimeLinter Warning Underline + scope + sublimelinter.underline.warning + settings + + background + #b58900 + + + + name + SublimeLinter Violation Outline + scope + sublimelinter.outline.violation + settings + + background + #657b83 + foreground + #657b83 + + + + name + SublimeLinter Violation Underline + scope + sublimelinter.underline.violation + settings + + background + #cb4b16 + + + + name + SublimeLinter Warning + scope + sublimelinter.mark.warning + settings + + foreground + #b58900 + + + + name + SublimeLinter Error + scope + sublimelinter.mark.error + settings + + foreground + #dc322f + + + + name + SublimeLinter Gutter Mark + scope + sublimelinter.gutter-mark + settings + + foreground + #657b83 + + + + + + name + SublimeBracketHighlighter + scope + brackethighlighter.all + settings + + foreground + #586e75 + + + + + + name + Find In Files: File Name + scope + entity.name.filename.find-in-files + settings + + foreground + #2aa198 + + + + name + Find In Files: Line numbers + scope + constant.numeric.line-number.find-in-files + settings + + foreground + #586e75 + + + + + + name + GitGutter deleted + scope + markup.deleted.git_gutter + settings + + foreground + #dc322f + + + + name + GitGutter inserted + scope + markup.inserted.git_gutter + settings + + foreground + #859900 + + + + name + GitGutter changed + scope + markup.changed.git_gutter + settings + + foreground + #b58900 + + + + + + name + JavaScript Variables + scope + variable.other.readwrite.js, variable.other.object.js, variable.other.constant.js + settings + + foreground + #839496 + + + + name + JavaScript Functions + scope + variable.function.js + settings + + foreground + #b58900 + + + + name + JavaScript punctation inside class + scope + meta.class punctuation + settings + + foreground + #839496 + + + + name + JavaScript Classes + scope + variable.language.this.js, variable.language.super.js + settings + + foreground + #d33682 + + + + uuid + 5815b34d-fb7d-4593-bf0c-4f41f8b1f0a9 + + diff --git a/sublime_themes/solarized-light.tmTheme b/sublime_themes/solarized-light.tmTheme new file mode 100644 index 00000000..ed7956bc --- /dev/null +++ b/sublime_themes/solarized-light.tmTheme @@ -0,0 +1,1189 @@ + + + + + name + Solarized (light) + settings + + + + + settings + + background + #fdf6e3 + caret + #073642 + foreground + #657b83 + gutter + #eee8d5 + invisibles + #eee8d5 + lineHighlight + #eee8d5 + selection + #eee8d5 + selectionBorder + #c0c4bb + + + + + + + + + + + name + Comment + scope + comment, meta.documentation + settings + + foreground + #93a1a1 + + + + name + String + scope + string + settings + + foreground + #2aa198 + + + + name + Regexp + scope + string.regexp + settings + + foreground + #2aa198 + + + + name + Escape \ char + scope + constant.character.escape + settings + + foreground + #dc322f + + + + name + Number + scope + constant.numeric + settings + + foreground + #6c71c4 + + + + name + Variable + scope + variable + settings + + foreground + #268bd2 + + + + name + Keyword + scope + keyword + settings + + foreground + #859900 + + + + name + Import + scope + meta.import keyword, keyword.control.import, keyword.control.import.from, keyword.other.import, keyword.control.at-rule.include, keyword.control.at-rule.import + settings + + foreground + #cb4b16 + + + + name + Arithmetical, Assignment, Comparision Operators + scope + keyword.operator.comparison, keyword.operator.assignment, keyword.operator.arithmetic + settings + + foreground + #657b83 + + + + name + Storage + scope + storage + settings + + foreground + #859900 + + + + name + Class + scope + keyword.control.class, meta.class, entity.name.class, entity.name.type.class + settings + + foreground + #b58900 + + + + name + Library class + scope + support.type, support.class + settings + + foreground + #859900 + + + + name + Function name + scope + entity.name.function + settings + + foreground + #b58900 + + + + name + Variable start + scope + punctuation.definition.variable + settings + + foreground + #859900 + + + + name + Built-in constant + scope + constant.language, meta.preprocessor + settings + + foreground + #b58900 + + + + name + Support.construct + scope + support.function.construct, keyword.other.new + settings + + foreground + #dc322f + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #cb4b16 + + + + name + Tag name + scope + entity.name.tag + settings + + foreground + #268bd2 + + + + name + Tag start/end + scope + punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end + settings + + foreground + #93a1a1 + + + + name + Library function + scope + support.function + settings + + foreground + #859900 + + + + name + Continuation + scope + punctuation.separator.continuation + settings + + foreground + #dc322f + + + + name + Storage Type + scope + storage.type + settings + + foreground + #268bd2 + + + + name + Exception + scope + support.type.exception + settings + + foreground + #cb4b16 + + + + name + Special + scope + keyword.other.special-method + settings + + foreground + #cb4b16 + + + + name + Invalid + scope + invalid + settings + + background + #ec9489 + + + + name + Quoted String + scope + string.quoted.double, string.quoted.single + settings + + foreground + #2aa198 + + + + name + Quoted Single + scope + punctuation.definition.string.begin, punctuation.definition.string.end + settings + + foreground + #839496 + + + + name + [] + scope + meta.brace.square + settings + + foreground + #268bd2 + + + + name + () + scope + meta.brace.round, punctuation.definition.parameters.begin, punctuation.definition.parameters.end + settings + + foreground + #657b83 + + + + name + {} + scope + meta.brace.curly + settings + + foreground + #657b83 + + + + + + + + name + CSS: Standard color value + scope + support.constant.color, invalid.deprecated.color.w3c-non-standard-color-name.scss + settings + + foreground + #b58900 + + + + name + CSS: Selector > [] and non-spec tags + scope + meta.selector.css + settings + + foreground + #657b83 + + + + name + CSS: Tag + scope + entity.name.tag.css, entity.name.tag.scss, source.less keyword.control.html.elements, source.sass keyword.control.untitled + settings + + foreground + #b58900 + + + + name + CSS .class + scope + entity.other.attribute-name.class.css, entity.other.attribute-name.class.sass + settings + + foreground + #b58900 + + + + name + CSS: #id + scope + source.css entity.other.attribute-name.id, source.less entity.other.attribute-name.id, source.scss entity.other.attribute-name.id, source.sass entity.other.attribute-name.id + settings + + foreground + #b58900 + + + + name + CSS :pseudo + scope + entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class, entity.other.attribute-name.tag.pseudo-class + settings + + foreground + #268bd2 + + + + + + name + HTML: = + scope + text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html + settings + + foreground + #657b83 + + + + name + HTML: something= + scope + text.html.basic entity.other.attribute-name.html, meta.tag.xml entity.other.attribute-name + settings + + foreground + #b58900 + + + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #859900 + + + + name + Ruby: Constant Other + scope + variable.other.constant.ruby + settings + + foreground + #b58900 + + + + name + Ruby: :symbol + scope + constant.other.symbol.ruby + settings + + foreground + #2aa198 + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #cb4b16 + + + + + + name + PHP: Array() + scope + meta.array support.function.construct.php + settings + + foreground + #b58900 + + + + + + name + C: Preprocessor + scope + entity.name.function.preprocessor.c, meta.preprocessor.c.include, meta.preprocessor.macro.c + settings + + foreground + #cb4b16 + + + + name + C: include + scope + meta.preprocessor.c.include string.quoted.other.lt-gt.include.c, meta.preprocessor.c.include punctuation.definition.string.begin.c, meta.preprocessor.c.include punctuation.definition.string.end.c + settings + + foreground + #2aa198 + + + + + + name + Other: Removal + scope + other.package.exclude, other.remove + settings + + foreground + #dc322f + + + + name + Other: Add + scope + other.add + settings + + foreground + #2aa198 + + + + + + name + Tex: {} + scope + punctuation.section.group.tex , punctuation.definition.arguments.begin.latex, punctuation.definition.arguments.end.latex, punctuation.definition.arguments.latex + settings + + foreground + #dc322f + + + + name + Tex: {text} + scope + meta.group.braces.tex + settings + + foreground + #b58900 + + + + name + Tex: Other Math + scope + string.other.math.tex + settings + + foreground + #b58900 + + + + name + Tex: {var} + scope + variable.parameter.function.latex + settings + + foreground + #cb4b16 + + + + name + Tex: Math \\ + scope + punctuation.definition.constant.math.tex + settings + + foreground + #dc322f + + + + name + Tex: Constant Math + scope + text.tex.latex constant.other.math.tex, constant.other.general.math.tex, constant.other.general.math.tex, constant.character.math.tex + settings + + foreground + #2aa198 + + + + name + Tex: Other Math String + scope + string.other.math.tex + settings + + foreground + #b58900 + + + + name + Tex: $ + scope + punctuation.definition.string.begin.tex, punctuation.definition.string.end.tex + settings + + foreground + #dc322f + + + + name + Tex: \label + scope + keyword.control.label.latex, text.tex.latex constant.other.general.math.tex + settings + + foreground + #2aa198 + + + + name + Tex: \label { } + scope + variable.parameter.definition.label.latex + settings + + foreground + #dc322f + + + + name + Tex: Function + scope + support.function.be.latex + settings + + foreground + #859900 + + + + name + Tex: Support Function Section + scope + support.function.section.latex + settings + + foreground + #cb4b16 + + + + name + Tex: Support Function + scope + support.function.general.tex + settings + + foreground + #2aa198 + + + + name + Tex: Reference Label + scope + keyword.control.ref.latex + settings + + foreground + #2aa198 + + + + + + name + Python: storage + scope + storage.type.class.python, storage.type.function.python, storage.modifier.global.python + settings + + foreground + #859900 + + + + name + Python: Support.exception + scope + support.type.exception.python + settings + + foreground + #b58900 + + + + + + name + Shell: meta scope in loop + scope + meta.scope.for-in-loop.shell, variable.other.loop.shell + settings + + foreground + #586e75 + + + + name + Shell: Meta Block + scope + meta.scope.case-block.shell, meta.scope.case-body.shell + settings + + foreground + #586e75 + + + + name + Shell: [] + scope + punctuation.definition.logical-expression.shell + settings + + foreground + #dc322f + + + + + + name + Java: storage import + scope + storage.modifier.import.java + settings + + foreground + #586e75 + + + + + + name + Perl: functions + scope + support.function.perl + settings + + foreground + #268bd2 + + + + + + name + diff: header + scope + meta.diff, meta.diff.header + settings + + foreground + #93a1a1 + + + + name + diff: range + scope + meta.diff.range + settings + + foreground + #268bd2 + + + + name + diff: deleted + scope + markup.deleted + settings + + foreground + #dc322f + + + + name + diff: changed + scope + markup.changed + settings + + foreground + #2aa198 + + + + name + diff: inserted + scope + markup.inserted + settings + + foreground + #859900 + + + + + + Name + Markdown heading + scope + markup.heading, punctuation.definition.heading.markdown + settings + + foreground + #b58900 + + + + name + Markdown quote + scope + markup.quote + settings + + foreground + #859900 + + + + name + Markdown em + scope + markup.italic + settings + + fontStyle + italic + + + + Name + Markdown strong + scope + markup.bold + settings + + fontStyle + bold + + + + Name + Markdown reference + scope + markup.underline.link.markdown, meta.link.reference constant.other.reference.link.markdown + settings + + foreground + #2aa198 + + + + Name + Markdown reference list + scope + constant.other.reference.link.markdown + settings + + foreground + #6c71c4 + + + + Name + Markdown linebreak + scope + meta.paragraph.markdown meta.dummy.line-break + settings + + background + #eee8d5 + + + + + + name + SublimeLinter Annotations + scope + sublimelinter.notes + settings + + background + #eee8d5 + foreground + #eee8d5 + + + + name + SublimeLinter Error Outline + scope + sublimelinter.outline.illegal + settings + + background + #93a1a1 + foreground + #93a1a1 + + + + name + SublimeLinter Error Underline + scope + sublimelinter.underline.illegal + settings + + background + #dc322f + + + + name + SublimeLinter Warning Outline + scope + sublimelinter.outline.warning + settings + + background + #839496 + foreground + #839496 + + + + name + SublimeLinter Warning Underline + scope + sublimelinter.underline.warning + settings + + background + #b58900 + + + + name + SublimeLinter Violation Outline + scope + sublimelinter.outline.violation + settings + + background + #657b83 + foreground + #657b83 + + + + name + SublimeLinter Violation Underline + scope + sublimelinter.underline.violation + settings + + background + #cb4b16 + + + + name + SublimeLinter Warning + scope + sublimelinter.mark.warning + settings + + foreground + #b58900 + + + + name + SublimeLinter Error + scope + sublimelinter.mark.error + settings + + foreground + #dc322f + + + + name + SublimeLinter Gutter Mark + scope + sublimelinter.gutter-mark + settings + + foreground + #657b83 + + + + + + name + SublimeBracketHighlighter + scope + brackethighlighter.all + settings + + foreground + #93a1a1 + + + + + + name + Find In Files: File Name + scope + entity.name.filename.find-in-files + settings + + foreground + #2aa198 + + + + name + Find In Files: Line numbers + scope + constant.numeric.line-number.find-in-files + settings + + foreground + #93a1a1 + + + + + + name + GitGutter deleted + scope + markup.deleted.git_gutter + settings + + foreground + #dc322f + + + + name + GitGutter inserted + scope + markup.inserted.git_gutter + settings + + foreground + #859900 + + + + name + GitGutter changed + scope + markup.changed.git_gutter + settings + + foreground + #b58900 + + + + + + name + JavaScript Variables + scope + variable.other.readwrite.js, variable.other.object.js, variable.other.constant.js + settings + + foreground + #657b83 + + + + name + JavaScript Functions + scope + variable.function.js + settings + + foreground + #b58900 + + + + name + JavaScript punctation inside class + scope + meta.class punctuation + settings + + foreground + #657b83 + + + + name + JavaScript Classes + scope + variable.language.this.js, variable.language.super.js + settings + + foreground + #d33682 + + + + uuid + ca238b9c-28f7-42d4-9670-bd0829ef864e + + diff --git a/test_site/config.toml b/test_site/config.toml new file mode 100644 index 00000000..ba0629c8 --- /dev/null +++ b/test_site/config.toml @@ -0,0 +1,7 @@ +title = "My site" +base_url = "https://replace-this-with-your-url.com" +highlight_code = true + + +[extra.author] +name = "Vincent Prouillet" diff --git a/test_site/content/posts/_index.md b/test_site/content/posts/_index.md new file mode 100644 index 00000000..93ed2520 --- /dev/null +++ b/test_site/content/posts/_index.md @@ -0,0 +1,4 @@ ++++ +title = "Posts" +description = "" ++++ diff --git a/test_site/content/posts/fixed-slug.md b/test_site/content/posts/fixed-slug.md new file mode 100644 index 00000000..3eff97db --- /dev/null +++ b/test_site/content/posts/fixed-slug.md @@ -0,0 +1,7 @@ ++++ +title = "Fixed slug" +description = "" +slug = "something-else" ++++ + +A simple page with a slug defined diff --git a/test_site/content/posts/fixed-url.md b/test_site/content/posts/fixed-url.md new file mode 100644 index 00000000..e51171ea --- /dev/null +++ b/test_site/content/posts/fixed-url.md @@ -0,0 +1,7 @@ ++++ +title = "Fixed URL" +description = "" +url = "a-fixed-url" ++++ + +A simple page with fixed url diff --git a/test_site/content/posts/no-section/simple.md b/test_site/content/posts/no-section/simple.md new file mode 100644 index 00000000..43bfcc60 --- /dev/null +++ b/test_site/content/posts/no-section/simple.md @@ -0,0 +1,6 @@ ++++ +title = "Simple" +description = "" ++++ + +A simple page diff --git a/test_site/content/posts/python.md b/test_site/content/posts/python.md new file mode 100644 index 00000000..ae5f25f2 --- /dev/null +++ b/test_site/content/posts/python.md @@ -0,0 +1,6 @@ ++++ +title = "Python in posts" +description = "" ++++ + +Same filename but different path diff --git a/test_site/content/posts/simple.md b/test_site/content/posts/simple.md new file mode 100644 index 00000000..43bfcc60 --- /dev/null +++ b/test_site/content/posts/simple.md @@ -0,0 +1,6 @@ ++++ +title = "Simple" +description = "" ++++ + +A simple page diff --git a/test_site/content/posts/tutorials/_index.md b/test_site/content/posts/tutorials/_index.md new file mode 100644 index 00000000..049aa01f --- /dev/null +++ b/test_site/content/posts/tutorials/_index.md @@ -0,0 +1,4 @@ ++++ +title = "Tutorials" +description = "" ++++ diff --git a/test_site/content/posts/tutorials/devops/_index.md b/test_site/content/posts/tutorials/devops/_index.md new file mode 100644 index 00000000..b4f4ab5d --- /dev/null +++ b/test_site/content/posts/tutorials/devops/_index.md @@ -0,0 +1,4 @@ ++++ +title = "DevOps" +description = "" ++++ diff --git a/test_site/content/posts/tutorials/devops/docker.md b/test_site/content/posts/tutorials/devops/docker.md new file mode 100644 index 00000000..eb0073a9 --- /dev/null +++ b/test_site/content/posts/tutorials/devops/docker.md @@ -0,0 +1,6 @@ ++++ +title = "Docker" +description = "" ++++ + +A simple page diff --git a/test_site/content/posts/tutorials/devops/nix.md b/test_site/content/posts/tutorials/devops/nix.md new file mode 100644 index 00000000..f12ccb62 --- /dev/null +++ b/test_site/content/posts/tutorials/devops/nix.md @@ -0,0 +1,6 @@ ++++ +title = "Nix" +description = "" ++++ + +A simple page diff --git a/test_site/content/posts/tutorials/programming/_index.md b/test_site/content/posts/tutorials/programming/_index.md new file mode 100644 index 00000000..d46aac2f --- /dev/null +++ b/test_site/content/posts/tutorials/programming/_index.md @@ -0,0 +1,4 @@ ++++ +title = "Programming" +description = "" ++++ diff --git a/test_site/content/posts/tutorials/programming/python.md b/test_site/content/posts/tutorials/programming/python.md new file mode 100644 index 00000000..8a0a68d1 --- /dev/null +++ b/test_site/content/posts/tutorials/programming/python.md @@ -0,0 +1,6 @@ ++++ +title = "Python tutorial" +description = "" ++++ + +A simple page diff --git a/test_site/content/posts/tutorials/programming/rust.md b/test_site/content/posts/tutorials/programming/rust.md new file mode 100644 index 00000000..b2173237 --- /dev/null +++ b/test_site/content/posts/tutorials/programming/rust.md @@ -0,0 +1,6 @@ ++++ +title = "Rust" +description = "" ++++ + +A simple page diff --git a/test_site/content/posts/with-assets/index.md b/test_site/content/posts/with-assets/index.md new file mode 100644 index 00000000..2000dfd0 --- /dev/null +++ b/test_site/content/posts/with-assets/index.md @@ -0,0 +1,7 @@ ++++ +title = "With assets" +description = "hey there" +slug = "with-assets" ++++ + +Hello world diff --git a/test_site/content/posts/with-assets/with.js b/test_site/content/posts/with-assets/with.js new file mode 100644 index 00000000..e69de29b diff --git a/test_site/static/scripts/hello.js b/test_site/static/scripts/hello.js new file mode 100644 index 00000000..e69de29b diff --git a/test_site/static/site.css b/test_site/static/site.css new file mode 100644 index 00000000..b05faf8e --- /dev/null +++ b/test_site/static/site.css @@ -0,0 +1,3 @@ +body { + color: red; +} diff --git a/test_site/templates/categories.html b/test_site/templates/categories.html new file mode 100644 index 00000000..9ac110eb --- /dev/null +++ b/test_site/templates/categories.html @@ -0,0 +1,3 @@ +{% for category in categories %} + {{ category.name }} {{ category.slug }} {{ category.count }} +{% endfor %} diff --git a/test_site/templates/category.html b/test_site/templates/category.html new file mode 100644 index 00000000..70079cbc --- /dev/null +++ b/test_site/templates/category.html @@ -0,0 +1,8 @@ +Category: {{ category }} + + +{% for page in pages %} + +{% endfor %} diff --git a/test_site/templates/index.html b/test_site/templates/index.html new file mode 100644 index 00000000..417d614f --- /dev/null +++ b/test_site/templates/index.html @@ -0,0 +1,27 @@ + + + + + + + + + + + {{ config.title }} + + + +
+ {% block content %} +
+ {% for page in pages %} + + {% endfor %} +
+ {% endblock content %} +
+ + diff --git a/test_site/templates/page.html b/test_site/templates/page.html new file mode 100644 index 00000000..ff68f1f8 --- /dev/null +++ b/test_site/templates/page.html @@ -0,0 +1,5 @@ +{% extends "index.html" %} + +{% block content %} + {{ page.content | safe }} +{% endblock content %} diff --git a/test_site/templates/section.html b/test_site/templates/section.html new file mode 100644 index 00000000..cf4b1d17 --- /dev/null +++ b/test_site/templates/section.html @@ -0,0 +1,10 @@ +{% extends "index.html" %} + +{% block content %} + {% for page in section.pages %} + {{page.title}} + {% endfor %} + {% for subsection in section.subsections %} + {{subsection.title}} + {% endfor %} +{% endblock content %} diff --git a/test_site/templates/tag.html b/test_site/templates/tag.html new file mode 100644 index 00000000..62f6c1a7 --- /dev/null +++ b/test_site/templates/tag.html @@ -0,0 +1,7 @@ +Tag: {{ tag }} + +{% for page in pages %} + +{% endfor %} diff --git a/test_site/templates/tags.html b/test_site/templates/tags.html new file mode 100644 index 00000000..8a0b2543 --- /dev/null +++ b/test_site/templates/tags.html @@ -0,0 +1,3 @@ +{% for tag in tags %} + {{ tag.name }} {{ tag.slug }} {{ tag.count }} +{% endfor %} diff --git a/tests/front_matter.rs b/tests/front_matter.rs new file mode 100644 index 00000000..14291c64 --- /dev/null +++ b/tests/front_matter.rs @@ -0,0 +1,197 @@ +extern crate gutenberg; +extern crate tera; + +use std::path::Path; + +use gutenberg::{FrontMatter, split_content}; +use tera::to_value; + + +#[test] +fn test_can_parse_a_valid_front_matter() { + let content = r#" +title = "Hello" +description = "hey there""#; + let res = FrontMatter::parse(content); + println!("{:?}", res); + assert!(res.is_ok()); + let res = res.unwrap(); + assert_eq!(res.title, "Hello".to_string()); + assert_eq!(res.description, "hey there".to_string()); +} + +#[test] +fn test_can_parse_tags() { + let content = r#" +title = "Hello" +description = "hey there" +slug = "hello-world" +tags = ["rust", "html"]"#; + let res = FrontMatter::parse(content); + assert!(res.is_ok()); + let res = res.unwrap(); + + assert_eq!(res.title, "Hello".to_string()); + assert_eq!(res.slug.unwrap(), "hello-world".to_string()); + assert_eq!(res.tags.unwrap(), ["rust".to_string(), "html".to_string()]); +} + +#[test] +fn test_can_parse_extra_attributes_in_frontmatter() { + let content = r#" +title = "Hello" +description = "hey there" +slug = "hello-world" + +[extra] +language = "en" +authors = ["Bob", "Alice"]"#; + let res = FrontMatter::parse(content); + assert!(res.is_ok()); + let res = res.unwrap(); + + assert_eq!(res.title, "Hello".to_string()); + assert_eq!(res.slug.unwrap(), "hello-world".to_string()); + let extra = res.extra.unwrap(); + assert_eq!(extra.get("language").unwrap(), &to_value("en").unwrap()); + assert_eq!( + extra.get("authors").unwrap(), + &to_value(["Bob".to_string(), "Alice".to_string()]).unwrap() + ); +} + +#[test] +fn test_is_ok_with_url_instead_of_slug() { + let content = r#" +title = "Hello" +description = "hey there" +url = "hello-world""#; + let res = FrontMatter::parse(content); + assert!(res.is_ok()); + let res = res.unwrap(); + assert!(res.slug.is_none()); + assert_eq!(res.url.unwrap(), "hello-world".to_string()); +} + +#[test] +fn test_errors_with_empty_front_matter() { + let content = r#" "#; + let res = FrontMatter::parse(content); + assert!(res.is_err()); +} + +#[test] +fn test_errors_with_invalid_front_matter() { + let content = r#"title = 1\n"#; + let res = FrontMatter::parse(content); + assert!(res.is_err()); +} + +#[test] +fn test_errors_with_missing_required_value_front_matter() { + let content = r#"title = """#; + let res = FrontMatter::parse(content); + assert!(res.is_err()); +} + +#[test] +fn test_errors_on_non_string_tag() { + let content = r#" +title = "Hello" +description = "hey there" +slug = "hello-world" +tags = ["rust", 1]"#; + let res = FrontMatter::parse(content); + assert!(res.is_err()); +} + +#[test] +fn test_errors_on_present_but_empty_slug() { + let content = r#" +title = "Hello" +description = "hey there" +slug = """#; + let res = FrontMatter::parse(content); + assert!(res.is_err()); +} + +#[test] +fn test_errors_on_present_but_empty_url() { + let content = r#" +title = "Hello" +description = "hey there" +url = """#; + let res = FrontMatter::parse(content); + assert!(res.is_err()); +} + +#[test] +fn test_parse_date_yyyy_mm_dd() { + let content = r#" +title = "Hello" +description = "hey there" +date = "2016-10-10""#; + let res = FrontMatter::parse(content).unwrap(); + assert!(res.parse_date().is_some()); +} + +#[test] +fn test_parse_date_rfc3339() { + let content = r#" +title = "Hello" +description = "hey there" +date = "2002-10-02T15:00:00Z""#; + let res = FrontMatter::parse(content).unwrap(); + assert!(res.parse_date().is_some()); +} + +#[test] +fn test_cant_parse_random_date_format() { + let content = r#" +title = "Hello" +description = "hey there" +date = "2002/10/12""#; + let res = FrontMatter::parse(content).unwrap(); + assert!(res.parse_date().is_none()); +} + + +#[test] +fn test_can_split_content_valid() { + let content = r#" ++++ +title = "Title" +description = "hey there" +date = "2002/10/12" ++++ +Hello +"#; + let (front_matter, content) = split_content(Path::new(""), content).unwrap(); + assert_eq!(content, "Hello\n"); + assert_eq!(front_matter.title, "Title"); +} + +#[test] +fn test_can_split_content_with_only_frontmatter_valid() { + let content = r#" ++++ +title = "Title" +description = "hey there" +date = "2002/10/12" ++++"#; + let (front_matter, content) = split_content(Path::new(""), content).unwrap(); + assert_eq!(content, ""); + assert_eq!(front_matter.title, "Title"); +} + +#[test] +fn test_error_if_cannot_locate_frontmatter() { + let content = r#" ++++ +title = "Title" +description = "hey there" +date = "2002/10/12" +"#; + let res = split_content(Path::new(""), content); + assert!(res.is_err()); +} diff --git a/tests/page.rs b/tests/page.rs new file mode 100644 index 00000000..fc8dacc3 --- /dev/null +++ b/tests/page.rs @@ -0,0 +1,249 @@ +extern crate gutenberg; +extern crate tempdir; + +use tempdir::TempDir; + +use std::fs::File; +use std::path::Path; + +use gutenberg::{Page, Config}; + + +#[test] +fn test_can_parse_a_valid_page() { + let content = r#" ++++ +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::parse(Path::new("post.md"), content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + + assert_eq!(page.meta.title, "Hello".to_string()); + assert_eq!(page.meta.slug.unwrap(), "hello-world".to_string()); + assert_eq!(page.raw_content, "Hello world".to_string()); + assert_eq!(page.content, "

Hello world

\n".to_string()); +} + +#[test] +fn test_can_find_one_parent_directory() { + let content = r#" ++++ +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::parse(Path::new("content/posts/intro.md"), content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.components, vec!["posts".to_string()]); +} + +#[test] +fn test_can_find_multiple_parent_directories() { + let content = r#" ++++ +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::parse(Path::new("content/posts/intro/start.md"), content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.components, vec!["posts".to_string(), "intro".to_string()]); +} + +#[test] +fn test_can_make_url_from_sections_and_slug() { + let content = r#" ++++ +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let mut conf = Config::default(); + conf.base_url = "http://hello.com/".to_string(); + let res = Page::parse(Path::new("content/posts/intro/start.md"), content, &conf); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.url, "posts/intro/hello-world"); + assert_eq!(page.permalink, "http://hello.com/posts/intro/hello-world"); +} + +#[test] +fn test_can_make_permalink_with_non_trailing_slash_base_url() { + let content = r#" ++++ +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let mut conf = Config::default(); + conf.base_url = "http://hello.com".to_string(); + let res = Page::parse(Path::new("content/posts/intro/hello-world.md"), content, &conf); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.url, "posts/intro/hello-world"); + assert_eq!(page.permalink, format!("{}{}", conf.base_url, "/posts/intro/hello-world")); +} + +#[test] +fn test_can_make_url_from_slug_only() { + let content = r#" ++++ +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::parse(Path::new("start.md"), content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.url, "hello-world"); + assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "hello-world")); +} + +#[test] +fn test_errors_on_invalid_front_matter_format() { + let content = r#" +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::parse(Path::new("start.md"), content, &Config::default()); + assert!(res.is_err()); +} + +#[test] +fn test_can_make_slug_from_non_slug_filename() { + let content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +Hello world"#; + let res = Page::parse(Path::new("file with space.md"), content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.slug, "file-with-space"); + assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "file-with-space")); +} + +#[test] +fn test_trim_slug_if_needed() { + let content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +Hello world"#; + let res = Page::parse(Path::new(" file with space.md"), content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.slug, "file-with-space"); + assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "file-with-space")); +} + +#[test] +fn test_reading_analytics_short() { + let content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +Hello world"#; + let res = Page::parse(Path::new("hello.md"), content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + let (word_count, reading_time) = page.get_reading_analytics(); + assert_eq!(word_count, 2); + assert_eq!(reading_time, 0); +} + +#[test] +fn test_reading_analytics_long() { + let mut content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +Hello world"#.to_string(); + for _ in 0..1000 { + content.push_str(" Hello world"); + } + let res = Page::parse(Path::new("hello.md"), &content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + let (word_count, reading_time) = page.get_reading_analytics(); + assert_eq!(word_count, 2002); + assert_eq!(reading_time, 10); +} + +#[test] +fn test_automatic_summary_is_empty_string() { + let content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +Hello world"#.to_string(); + let res = Page::parse(Path::new("hello.md"), &content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.summary, ""); +} + +#[test] +fn test_can_specify_summary() { + let content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +Hello world + +"#.to_string(); + let res = Page::parse(Path::new("hello.md"), &content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.summary, "

Hello world

\n"); +} + +#[test] +fn test_can_auto_detect_when_highlighting_needed() { + let content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +``` +Hey there +``` +"#.to_string(); + let mut config = Config::default(); + config.highlight_code = Some(true); + let res = Page::parse(Path::new("hello.md"), &content, &config); + assert!(res.is_ok()); + let page = res.unwrap(); + assert!(page.content.starts_with(" { + { + let mut path = $root.clone(); + for component in $path.split("/") { + path = path.join(component); + } + Path::new(&path).exists() + } + } +} + +macro_rules! file_contains { + ($root: expr, $path: expr, $text: expr) => { + { + let mut path = $root.clone(); + for component in $path.split("/") { + path = path.join(component); + } + let mut file = File::open(&path).unwrap(); + let mut s = String::new(); + file.read_to_string(&mut s).unwrap(); + s.contains($text) + } + } +} + +#[test] +fn test_can_build_site_without_live_reload() { + let mut path = env::current_dir().unwrap().to_path_buf(); + path.push("test_site"); + let mut site = Site::new(&path).unwrap(); + let tmp_dir = TempDir::new("example").expect("create temp dir"); + let public = &tmp_dir.path().join("public"); + site.set_output_path(&public); + site.build().unwrap(); + + assert!(Path::new(&public).exists()); + + assert!(file_exists!(public, "index.html")); + assert!(file_exists!(public, "sitemap.xml")); + assert!(file_exists!(public, "a-fixed-url/index.html")); + + assert!(file_exists!(public, "posts/python/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html")); + assert!(file_exists!(public, "posts/with-assets/index.html")); + + // Sections + assert!(file_exists!(public, "posts/index.html")); + assert!(file_exists!(public, "posts/tutorials/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/index.html")); + assert!(file_exists!(public, "posts/tutorials/programming/index.html")); + // TODO: add assertion for syntax highlighting + + // No tags or categories + assert_eq!(file_exists!(public, "categories/index.html"), false); + assert_eq!(file_exists!(public, "tags/index.html"), false); + + // no live reload code + assert_eq!(file_contains!(public, "index.html", "/livereload.js?port=1112&mindelay=10"), false); + + // Both pages and sections are in the sitemap + assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/posts/simple")); + assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/posts")); +} + +#[test] +fn test_can_build_site_with_live_reload() { + let mut path = env::current_dir().unwrap().to_path_buf(); + path.push("test_site"); + let mut site = Site::new(&path).unwrap(); + let tmp_dir = TempDir::new("example").expect("create temp dir"); + let public = &tmp_dir.path().join("public"); + site.set_output_path(&public); + site.enable_live_reload(); + site.build().unwrap(); + + assert!(Path::new(&public).exists()); + + assert!(file_exists!(public, "index.html")); + assert!(file_exists!(public, "sitemap.xml")); + assert!(file_exists!(public, "a-fixed-url/index.html")); + + assert!(file_exists!(public, "posts/python/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html")); + assert!(file_exists!(public, "posts/with-assets/index.html")); + + // Sections + assert!(file_exists!(public, "posts/index.html")); + assert!(file_exists!(public, "posts/tutorials/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/index.html")); + assert!(file_exists!(public, "posts/tutorials/programming/index.html")); + // TODO: add assertion for syntax highlighting + + // No tags or categories + assert_eq!(file_exists!(public, "categories/index.html"), false); + assert_eq!(file_exists!(public, "tags/index.html"), false); + + // no live reload code + assert!(file_contains!(public, "index.html", "/livereload.js?port=1112&mindelay=10")); +} + +#[test] +fn test_can_build_site_with_categories() { + let mut path = env::current_dir().unwrap().to_path_buf(); + path.push("test_site"); + let mut site = Site::new(&path).unwrap(); + + for (i, page) in site.pages.values_mut().enumerate() { + page.meta.category = if i % 2 == 0 { + Some("A".to_string()) + } else { + Some("B".to_string()) + }; + } + site.parse_tags_and_categories(); + let tmp_dir = TempDir::new("example").expect("create temp dir"); + let public = &tmp_dir.path().join("public"); + site.set_output_path(&public); + site.build().unwrap(); + + assert!(Path::new(&public).exists()); + assert_eq!(site.categories.len(), 2); + + assert!(file_exists!(public, "index.html")); + assert!(file_exists!(public, "sitemap.xml")); + assert!(file_exists!(public, "a-fixed-url/index.html")); + + assert!(file_exists!(public, "posts/python/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html")); + assert!(file_exists!(public, "posts/with-assets/index.html")); + + // Sections + assert!(file_exists!(public, "posts/index.html")); + assert!(file_exists!(public, "posts/tutorials/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/index.html")); + assert!(file_exists!(public, "posts/tutorials/programming/index.html")); + // TODO: add assertion for syntax highlighting + + // Categories are there + assert!(file_exists!(public, "categories/index.html")); + assert!(file_exists!(public, "categories/a/index.html")); + assert!(file_exists!(public, "categories/b/index.html")); + // Tags aren't + assert_eq!(file_exists!(public, "tags/index.html"), false); + + // Categories are in the sitemap + assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/categories")); + assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/categories/a")); +} + +#[test] +fn test_can_build_site_with_tags() { + let mut path = env::current_dir().unwrap().to_path_buf(); + path.push("test_site"); + let mut site = Site::new(&path).unwrap(); + + for (i, page) in site.pages.values_mut().enumerate() { + page.meta.tags = if i % 2 == 0 { + Some(vec!["tag1".to_string(), "tag2".to_string()]) + } else { + Some(vec!["tag with space".to_string()]) + }; + } + site.parse_tags_and_categories(); + + let tmp_dir = TempDir::new("example").expect("create temp dir"); + let public = &tmp_dir.path().join("public"); + site.set_output_path(&public); + site.build().unwrap(); + + assert!(Path::new(&public).exists()); + assert_eq!(site.tags.len(), 3); + + assert!(file_exists!(public, "index.html")); + assert!(file_exists!(public, "sitemap.xml")); + assert!(file_exists!(public, "a-fixed-url/index.html")); + + assert!(file_exists!(public, "posts/python/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html")); + assert!(file_exists!(public, "posts/with-assets/index.html")); + + // Sections + assert!(file_exists!(public, "posts/index.html")); + assert!(file_exists!(public, "posts/tutorials/index.html")); + assert!(file_exists!(public, "posts/tutorials/devops/index.html")); + assert!(file_exists!(public, "posts/tutorials/programming/index.html")); + // TODO: add assertion for syntax highlighting + + // Tags are there + assert!(file_exists!(public, "tags/index.html")); + assert!(file_exists!(public, "tags/tag1/index.html")); + assert!(file_exists!(public, "tags/tag2/index.html")); + assert!(file_exists!(public, "tags/tag-with-space/index.html")); + // Categories aren't + assert_eq!(file_exists!(public, "categories/index.html"), false); + // Tags are in the sitemap + assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/tags")); + assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/tags/tag-with-space")); +}