From 1ae0702494e45d90c55a8f3734c218551e22f34d Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 16 Jul 2018 10:54:05 +0200 Subject: [PATCH] Custom taxonomies (#330) --- CHANGELOG.md | 7 + Cargo.lock | 274 +++++++++--------- components/config/src/lib.rs | 43 ++- components/content/src/page.rs | 5 +- components/front_matter/src/page.rs | 65 ++--- components/imageproc/src/lib.rs | 9 + components/pagination/Cargo.toml | 1 + components/pagination/src/lib.rs | 144 +++++++-- components/rebuild/src/lib.rs | 69 ++--- components/site/src/lib.rs | 158 +++++----- components/site/tests/site.rs | 71 +---- components/taxonomies/src/lib.rs | 181 ++++++------ components/templates/src/builtins/rss.xml | 8 +- components/templates/src/builtins/sitemap.xml | 11 +- components/templates/src/global_fns.rs | 56 ++-- components/templates/src/lib.rs | 1 - components/utils/src/templates.rs | 4 +- docs/content/documentation/content/page.md | 9 +- .../documentation/content/tags-categories.md | 23 -- .../documentation/content/taxonomies.md | 27 ++ .../getting-started/configuration.md | 15 +- .../documentation/templates/pagination.md | 9 +- .../templates/tags-categories.md | 31 -- .../documentation/templates/taxonomies.md | 53 ++++ test_site/config.toml | 4 + test_site/templates/categories.html | 3 - test_site/templates/categories/list.html | 3 + .../{category.html => categories/single.html} | 2 +- .../{category.html => categories/single.html} | 4 +- 29 files changed, 685 insertions(+), 605 deletions(-) delete mode 100644 docs/content/documentation/content/tags-categories.md create mode 100644 docs/content/documentation/content/taxonomies.md delete mode 100644 docs/content/documentation/templates/tags-categories.md create mode 100644 docs/content/documentation/templates/taxonomies.md delete mode 100644 test_site/templates/categories.html create mode 100644 test_site/templates/categories/list.html rename test_site/templates/{category.html => categories/single.html} (54%) rename test_site/themes/sample/templates/{category.html => categories/single.html} (75%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 908aa8d1..2dd20cd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## 0.4.0 (unreleased) +### Breaking + +- Taxonomies have been rewritten from scratch to allow custom ones with RSS and pagination +- `get_taxonomy_url` has been renamed to `get_taxonomy` and will now return the full taxonomy +instead of just the URL + +### Others - Fix `serve` not working with the config flag - Websocket port on `live` will not get the first available port instead of a fixed one - Rewrite markdown rendering to fix all known issues with shortcodes diff --git a/Cargo.lock b/Cargo.lock index 15d46e13..457bdb23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -22,7 +22,7 @@ dependencies = [ [[package]] name = "actix-web" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -33,25 +33,25 @@ dependencies = [ "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "http-range 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -60,8 +60,8 @@ dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -72,7 +72,7 @@ dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -82,7 +82,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -94,11 +94,11 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -158,7 +158,7 @@ name = "backtrace-sys" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -186,7 +186,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -240,14 +240,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -284,7 +284,7 @@ name = "cmake" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -300,8 +300,8 @@ dependencies = [ "errors 0.1.0", "globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "highlighting 0.1.0", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -316,7 +316,7 @@ dependencies = [ "globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rendering 0.1.0", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -330,7 +330,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -369,7 +369,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -383,7 +383,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -433,7 +433,7 @@ dependencies = [ [[package]] name = "dtoa" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -457,11 +457,11 @@ name = "elasticlunr-rs" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rust-stemmers 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "strum_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -607,10 +607,10 @@ version = "0.1.0" dependencies = [ "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "errors 0.1.0", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -663,7 +663,7 @@ dependencies = [ [[package]] name = "futures" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -671,7 +671,7 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -682,8 +682,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getopts" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "gif" @@ -704,7 +707,7 @@ name = "globset" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -716,7 +719,7 @@ name = "gutenberg" version = "0.4.0" dependencies = [ "actix 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "content 0.1.0", @@ -728,7 +731,7 @@ dependencies = [ "site 0.1.0", "term-painter 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "utils 0.1.0", "ws 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -741,12 +744,12 @@ dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -754,7 +757,7 @@ dependencies = [ name = "highlighting" version = "0.1.0" dependencies = [ - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -787,7 +790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -807,7 +810,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "idna" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -838,7 +841,7 @@ version = "0.1.0" dependencies = [ "errors 0.1.0", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -889,7 +892,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -917,7 +920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -986,8 +989,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1022,7 +1025,7 @@ dependencies = [ [[package]] name = "mime_guess" -version = "2.0.0-alpha.5" +version = "2.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1036,7 +1039,7 @@ name = "miniz-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1152,7 +1155,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1236,7 +1239,7 @@ version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "onig_sys 68.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1277,8 +1280,9 @@ dependencies = [ "content 0.1.0", "errors 0.1.0", "front_matter 0.1.0", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "taxonomies 0.1.0", "tera 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", "utils 0.1.0", ] @@ -1371,7 +1375,7 @@ dependencies = [ "base64 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1413,7 +1417,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1477,7 +1481,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1514,7 +1518,7 @@ name = "regex" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1526,7 +1530,7 @@ name = "regex" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1573,8 +1577,8 @@ dependencies = [ "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "templates 0.1.0", @@ -1596,8 +1600,8 @@ name = "rust-stemmers" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1660,7 +1664,7 @@ dependencies = [ "content 0.1.0", "elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "errors 0.1.0", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1669,7 +1673,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1679,12 +1683,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1697,10 +1701,10 @@ name = "serde_json" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1708,10 +1712,10 @@ name = "serde_urlencoded" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1748,8 +1752,8 @@ dependencies = [ "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "sass-rs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "search 0.1.0", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "taxonomies 0.1.0", "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "templates 0.1.0", @@ -1818,7 +1822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "string" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1826,11 +1830,11 @@ name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1928,12 +1932,12 @@ dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "onig 3.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "plist 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1947,8 +1951,8 @@ dependencies = [ "content 0.1.0", "errors 0.1.0", "front_matter 0.1.0", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", "utils 0.1.0", @@ -1984,7 +1988,7 @@ dependencies = [ "content 0.1.0", "errors 0.1.0", "imageproc 0.1.0", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "taxonomies 0.1.0", "tera 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2010,14 +2014,14 @@ dependencies = [ "error-chain 0.11.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.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2060,7 +2064,7 @@ name = "thread_local" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2079,14 +2083,14 @@ name = "tokio" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2097,7 +2101,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2107,7 +2111,7 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2124,17 +2128,17 @@ name = "tokio-executor" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2143,7 +2147,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2152,7 +2156,7 @@ name = "tokio-reactor" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2165,7 +2169,7 @@ name = "tokio-signal" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2180,7 +2184,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2189,11 +2193,11 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2205,7 +2209,7 @@ name = "tokio-timer" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2215,7 +2219,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2228,7 +2232,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2238,14 +2242,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2254,9 +2258,9 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "ipconfig 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2274,7 +2278,7 @@ name = "unicase" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2282,7 +2286,7 @@ name = "unicase" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2333,11 +2337,11 @@ dependencies = [ [[package]] name = "url" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2379,7 +2383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "version_check" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2459,7 +2463,7 @@ dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.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.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2489,10 +2493,10 @@ dependencies = [ [metadata] "checksum actix 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7f0b2daad36916ccd2b162dbc5a04a74df642a29391b1a341c8ee3e82026cb16" -"checksum actix-web 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "e35bb192338dc7726564b0bdf2d49d43cbf4c7845231a82527f5f302bdb8f477" +"checksum actix-web 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "cebfb353ebcae66f93c190b80ef12b8c82557413856e3e65dbaab662a48ec72d" "checksum actix_derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b1dc922654b9aca7a8a31eab875fde804fa9fbd67f220f2e457787b23590f2" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0ba20154ea1f47ce2793322f049c5646cc6d0fa9759d5f333f286e507bf8080" +"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" "checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" @@ -2512,7 +2516,7 @@ dependencies = [ "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" "checksum bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd32989a66957d3f0cba6588f15d4281a733f4e9ffc43fcd2385f57d3bf99ff" "checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0" -"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d" +"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275" "checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" "checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" @@ -2529,7 +2533,7 @@ dependencies = [ "checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" -"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum duct 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "166298c17c5b4fe5997b962c2f22e887c7c5adc44308eb9103ce5b66af45a423" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee" @@ -2554,10 +2558,10 @@ dependencies = [ "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" -"checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" +"checksum futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "884dbe32a6ae4cd7da5c6db9b78114449df9953b8d490c9d7e1b51720b922c62" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" -"checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" +"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3414b424657317e708489d2857d9575f4403698428b040b609b9d1c1a84a2c" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142754da2c9b3722affd909f9e27f2a6700a7a303f362971e0a74c652005a43d" @@ -2568,18 +2572,18 @@ dependencies = [ "checksum http-range 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2e4003e6fd05ea9109db00415e670b11f511a42e567ff2d5d771cbdfa24e02" "checksum httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b6288d7db100340ca12873fd4d08ad1b8f206a9457798dfb17c018a33fee540" "checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" -"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" +"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a" "checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" "checksum inflate 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6f53b811ee8e2057ccf9643ca6b4277de90efaf5e61e55fd5254576926bb4245" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipconfig 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec4e18c0a0d4340870c14284293632d8421f419008371422dd327892b88877c" -"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" +"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" +"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" "checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" @@ -2595,7 +2599,7 @@ dependencies = [ "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fe51c8699d2dc522bf8c1ebe26ea2193d151fb54bcdfd7d0318750c189994cd9" -"checksum mime_guess 2.0.0-alpha.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a78b5e2283080d5a8ba68216171b4fe34f6ccdd909bb29be16ce8a9a831341" +"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" "checksum mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4fcfcb32d63961fb6f367bfd5d21e4600b92cd310f71f9dca25acae196eb1560" @@ -2663,8 +2667,8 @@ dependencies = [ "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)" = "210e5a3b159c566d7527e9b22e44be73f2e0fcc330bb78fef4dbccb56d2e74c8" -"checksum serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)" = "dd724d68017ae3a7e63600ee4b2fdb3cad2158ffd1821d44aff4580f63e2b593" +"checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" +"checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" "checksum serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "84b8035cabe9b35878adec8ac5fe03d5f6bc97ff6edd7ccb96b44c1276ba390e" "checksum serde_urlencoded 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e703cef904312097cfceab9ce131ff6bbe09e8c964a0703345a5f49238757bc1" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" @@ -2678,7 +2682,7 @@ dependencies = [ "checksum smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "312a7df010092e73d6bbaf141957e868d4f30efd2bfd9bb1028ad91abec58514" "checksum socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "962a516af4d3a7c272cb3a1d50a8cc4e5b41802e4ad54cfb7bee8ba61d37d703" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" -"checksum string 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31f98b200e7caca9efca50fc0aa69cd58a5ec81d5f6e75b2f3ecaad2e998972a" +"checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" @@ -2705,12 +2709,12 @@ dependencies = [ "checksum tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "881e9645b81c2ce95fcb799ded2c29ffb9f25ef5bef909089a420e5961dd8ccb" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" -"checksum tokio-fs 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc42bae2f6e33865b99069d95bcddfc85c9f0849b4e7e7399eeee71956ef34d7" +"checksum tokio-fs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40697ecbea5660df15b15d50a077386477d2f6a35002adf01ce76ff9dd9dce48" "checksum tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a5c9635ee806f26d302b8baa1e145689a280d8f5aa8d0552e7344808da54cc21" "checksum tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e00ec63bbec2c97ce1178cb0587b2c438b2f6b09d3ee54a33c45a9cf0d530810" "checksum tokio-signal 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f46863230f9a05cf52d173721ec391b9c5782a2465f593029922b8782b9ffe" "checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" -"checksum tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c3873a6d8d0b636e024e77b9a82eaab6739578a06189ecd0e731c7308fbc5d" +"checksum tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "24ab84f574027b0e875378f31575cf175360891919e93a3490f07e76e00e4efb" "checksum tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "028b94314065b90f026a21826cffd62a4e40a92cda3e5c069cc7b02e5945f5e9" "checksum tokio-udp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43eb534af6e8f37d43ab1b612660df14755c42bd003c5f8d2475ee78cc4600c0" "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" @@ -2727,12 +2731,12 @@ dependencies = [ "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unidecode 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" +"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" +"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" diff --git a/components/config/src/lib.rs b/components/config/src/lib.rs index 6c6951e2..00234e8a 100644 --- a/components/config/src/lib.rs +++ b/components/config/src/lib.rs @@ -28,6 +28,40 @@ use theme::Theme; static DEFAULT_BASE_URL: &'static str = "http://a-website.com"; +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Taxonomy { + /// The name used in the URL, usually the plural + pub name: String, + /// If this is set, the list of individual taxonomy term page will be paginated + /// by this much + pub paginate: Option, + pub paginate_path: Option, + /// Whether to generate a RSS feed only for each taxonomy term, defaults to false + pub rss: bool, +} + +impl Taxonomy { + pub fn is_paginated(&self) -> bool { + if let Some(paginate_by) = self.paginate { + paginate_by > 0 + } else { + false + } + } +} + +impl Default for Taxonomy { + fn default() -> Taxonomy { + Taxonomy { + name: String::new(), + paginate: None, + paginate_path: None, + rss: false, + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct Config { @@ -56,10 +90,8 @@ pub struct Config { pub generate_rss: bool, /// The number of articles to include in the RSS feed. Defaults to 10_000 pub rss_limit: usize, - /// Whether to generate tags and individual tag pages if some pages have them. Defaults to true - pub generate_tags_pages: bool, - /// Whether to generate categories and individual tag categories if some pages have them. Defaults to true - pub generate_categories_pages: bool, + + pub taxonomies: Vec, /// Whether to compile the `sass` directory and output the css files into the static folder pub compile_sass: bool, @@ -191,8 +223,7 @@ impl Default for Config { default_language: "en".to_string(), generate_rss: false, rss_limit: 10_000, - generate_tags_pages: true, - generate_categories_pages: true, + taxonomies: Vec::new(), compile_sass: false, build_search_index: false, ignored_content: Vec::new(), diff --git a/components/content/src/page.rs b/components/content/src/page.rs index 07a2aad5..780faf23 100644 --- a/components/content/src/page.rs +++ b/components/content/src/page.rs @@ -238,7 +238,7 @@ impl Default for Page { impl ser::Serialize for Page { fn serialize(&self, serializer: S) -> StdResult where S: ser::Serializer { - let mut state = serializer.serialize_struct("page", 21)?; + let mut state = serializer.serialize_struct("page", 20)?; state.serialize_field("content", &self.content)?; state.serialize_field("title", &self.meta.title)?; state.serialize_field("description", &self.meta.description)?; @@ -258,8 +258,7 @@ impl ser::Serialize for Page { state.serialize_field("components", &self.components)?; state.serialize_field("permalink", &self.permalink)?; state.serialize_field("summary", &self.summary)?; - state.serialize_field("tags", &self.meta.tags)?; - state.serialize_field("category", &self.meta.category)?; + state.serialize_field("taxonomies", &self.meta.taxonomies)?; state.serialize_field("extra", &self.meta.extra)?; let (word_count, reading_time) = get_reading_analytics(&self.raw_content); state.serialize_field("word_count", &word_count)?; diff --git a/components/front_matter/src/page.rs b/components/front_matter/src/page.rs index 0b33a3a2..afbfc5b5 100644 --- a/components/front_matter/src/page.rs +++ b/components/front_matter/src/page.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::result::{Result as StdResult}; use chrono::prelude::*; @@ -80,10 +81,7 @@ pub struct PageFrontMatter { /// otherwise is set after parsing front matter and sections /// Can't be an empty string if present pub path: Option, - /// Tags, not to be confused with categories - pub tags: Option>, - /// Only one category allowed. Can't be an empty string if present - pub category: Option, + pub taxonomies: HashMap>, /// Integer to use to order content. Lowest is at the bottom, highest first pub order: Option, /// Integer to use to order content. Highest is at the bottom, lowest first @@ -122,12 +120,6 @@ impl PageFrontMatter { } } - if let Some(ref category) = f.category { - if category == "" { - bail!("`category` can't be empty if present") - } - } - f.extra = match fix_toml_dates(f.extra) { Value::Object(o) => o, _ => unreachable!("Got something other than a table in page extra"), @@ -155,13 +147,6 @@ impl PageFrontMatter { pub fn weight(&self) -> usize { self.weight.unwrap() } - - pub fn has_tags(&self) -> bool { - match self.tags { - Some(ref t) => !t.is_empty(), - None => false - } - } } impl Default for PageFrontMatter { @@ -173,8 +158,7 @@ impl Default for PageFrontMatter { draft: false, slug: None, path: None, - tags: None, - category: None, + taxonomies: HashMap::new(), order: None, weight: None, aliases: Vec::new(), @@ -211,21 +195,6 @@ mod tests { assert_eq!(res.description.unwrap(), "hey there".to_string()) } - #[test] - fn can_parse_tags() { - let content = r#" - title = "Hello" - description = "hey there" - slug = "hello-world" - tags = ["rust", "html"]"#; - let res = PageFrontMatter::parse(content); - assert!(res.is_ok()); - let res = res.unwrap(); - - assert_eq!(res.title.unwrap(), "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 errors_with_invalid_front_matter() { @@ -234,17 +203,6 @@ mod tests { assert!(res.is_err()); } - #[test] - fn errors_on_non_string_tag() { - let content = r#" - title = "Hello" - description = "hey there" - slug = "hello-world" - tags = ["rust", 1]"#; - let res = PageFrontMatter::parse(content); - assert!(res.is_err()); - } - #[test] fn errors_on_present_but_empty_slug() { let content = r#" @@ -344,4 +302,21 @@ mod tests { assert!(res.is_ok()); assert_eq!(res.unwrap().extra["something"]["some-date"], to_value("2002-14-01").unwrap()); } + + #[test] + fn can_parse_taxonomies() { + let content = r#" +title = "Hello World" + +[taxonomies] +tags = ["Rust", "JavaScript"] +categories = ["Dev"] +"#; + let res = PageFrontMatter::parse(content); + println!("{:?}", res); + assert!(res.is_ok()); + let res2 = res.unwrap(); + assert_eq!(res2.taxonomies["categories"], vec!["Dev"]); + assert_eq!(res2.taxonomies["tags"], vec!["Rust", "JavaScript"]); + } } diff --git a/components/imageproc/src/lib.rs b/components/imageproc/src/lib.rs index 19316849..bbf0e7ee 100644 --- a/components/imageproc/src/lib.rs +++ b/components/imageproc/src/lib.rs @@ -328,6 +328,11 @@ impl Processor { } pub fn prune(&self) -> Result<()> { + // Do not create folders if they don't exist + if !self.resized_path.exists() { + return Ok(()); + } + ufs::ensure_directory_exists(&self.resized_path)?; let entries = fs::read_dir(&self.resized_path)?; for entry in entries { @@ -350,6 +355,10 @@ impl Processor { } pub fn do_process(&mut self) -> Result<()> { + if !self.img_ops.is_empty() { + ufs::ensure_directory_exists(&self.resized_path)?; + } + self.img_ops.par_iter().map(|(hash, op)| { let target = self.resized_path.join(Self::op_filename(*hash, op.collision_id)); op.perform(&self.content_path, &target) diff --git a/components/pagination/Cargo.toml b/components/pagination/Cargo.toml index 0ee865f8..7fed69cb 100644 --- a/components/pagination/Cargo.toml +++ b/components/pagination/Cargo.toml @@ -12,6 +12,7 @@ errors = { path = "../errors" } config = { path = "../config" } content = { path = "../content" } utils = { path = "../utils" } +taxonomies = { path = "../taxonomies" } [dev-dependencies] front_matter = { path = "../front_matter" } diff --git a/components/pagination/src/lib.rs b/components/pagination/src/lib.rs index 42724c08..dc0c1404 100644 --- a/components/pagination/src/lib.rs +++ b/components/pagination/src/lib.rs @@ -6,6 +6,7 @@ extern crate errors; extern crate config; extern crate content; extern crate utils; +extern crate taxonomies; #[cfg(test)] extern crate front_matter; @@ -18,6 +19,14 @@ use errors::{Result, ResultExt}; use config::Config; use content::{Page, Section}; use utils::templates::render_template; +use taxonomies::{Taxonomy, TaxonomyItem}; + + +#[derive(Clone, Debug, PartialEq)] +enum PaginationRoot<'a> { + Section(&'a Section), + Taxonomy(&'a Taxonomy), +} /// A list of all the pages in the paginator with their index and links @@ -63,22 +72,62 @@ pub struct Paginator<'a> { pub pagers: Vec>, /// How many content pages on a paginated page at max paginate_by: usize, - /// The section struct we're building the paginator for - section: &'a Section, + /// The thing we are creating the paginator for: section or taxonomy + root: PaginationRoot<'a>, + // Those below can be obtained from the root but it would make the code more complex than needed + pub permalink: String, + path: String, + pub paginate_path: String, + is_index: bool, } impl<'a> Paginator<'a> { - /// Create a new paginator + /// Create a new paginator from a section /// It will always at least create one pager (the first) even if there are no pages to paginate - pub fn new(all_pages: &'a [Page], section: &'a Section) -> Paginator<'a> { + pub fn from_section(all_pages: &'a [Page], section: &'a Section) -> Paginator<'a> { let paginate_by = section.meta.paginate_by.unwrap(); + let mut paginator = Paginator { + all_pages, + pagers: vec![], + paginate_by, + root: PaginationRoot::Section(section), + permalink: section.permalink.clone(), + path: section.path.clone(), + paginate_path: section.meta.paginate_path.clone(), + is_index: section.is_index(), + }; + + paginator.fill_pagers(); + paginator + } + + /// Create a new paginator from a taxonomy + /// It will always at least create one pager (the first) even if there are no pages to paginate + pub fn from_taxonomy(taxonomy: &'a Taxonomy, item: &'a TaxonomyItem) -> Paginator<'a> { + let paginate_by = taxonomy.kind.paginate.unwrap(); + let mut paginator = Paginator { + all_pages: &item.pages, + pagers: vec![], + paginate_by, + root: PaginationRoot::Taxonomy(taxonomy), + permalink: item.permalink.clone(), + path: format!("{}/{}", taxonomy.kind.name, item.slug), + paginate_path: taxonomy.kind.paginate_path.clone().unwrap_or_else(|| "pages".to_string()), + is_index: false, + }; + + paginator.fill_pagers(); + paginator + } + + fn fill_pagers(&mut self) { let mut pages = vec![]; let mut current_page = vec![]; - for page in all_pages { + for page in self.all_pages { current_page.push(page); - if current_page.len() == paginate_by { + if current_page.len() == self.paginate_by { pages.push(current_page); current_page = vec![]; } @@ -91,17 +140,23 @@ impl<'a> Paginator<'a> { for (index, page) in pages.iter().enumerate() { // First page has no pagination path if index == 0 { - pagers.push(Pager::new(1, page.clone(), section.permalink.clone(), section.path.clone())); + pagers.push(Pager::new(1, page.clone(), self.permalink.clone(), self.path.clone())); continue; } - let page_path = format!("{}/{}/", section.meta.paginate_path, index + 1); - let permalink = format!("{}{}", section.permalink, page_path); - let pager_path = if section.is_index() { + let page_path = format!("{}/{}/", self.paginate_path, index + 1); + let permalink = format!("{}{}", self.permalink, page_path); + + let pager_path = if self.is_index { page_path } else { - format!("{}{}", section.path, page_path) + if self.path.ends_with("/") { + format!("{}{}", self.path, page_path) + } else { + format!("{}/{}", self.path, page_path) + } }; + pagers.push(Pager::new( index + 1, page.clone(), @@ -112,15 +167,10 @@ impl<'a> Paginator<'a> { // We always have the index one at least if pagers.is_empty() { - pagers.push(Pager::new(1, vec![], section.permalink.clone(), section.path.clone())); + pagers.push(Pager::new(1, vec![], self.permalink.clone(), self.path.clone())); } - Paginator { - all_pages, - pagers, - paginate_by, - section, - } + self.pagers = pagers; } pub fn build_paginator_context(&self, current_pager: &Pager) -> HashMap<&str, Value> { @@ -130,7 +180,7 @@ impl<'a> Paginator<'a> { // Global variables paginator.insert("paginate_by", to_value(self.paginate_by).unwrap()); - paginator.insert("first", to_value(&self.section.permalink).unwrap()); + paginator.insert("first", to_value(&self.permalink).unwrap()); let last_pager = &self.pagers[self.pagers.len() - 1]; paginator.insert("last", to_value(&last_pager.permalink).unwrap()); paginator.insert( @@ -163,13 +213,22 @@ impl<'a> Paginator<'a> { pub fn render_pager(&self, pager: &Pager, config: &Config, tera: &Tera) -> Result { let mut context = Context::new(); context.add("config", &config); - context.add("section", self.section); + let template_name = match self.root { + PaginationRoot::Section(s) => { + context.add("section", &s); + s.get_template_name() + }, + PaginationRoot::Taxonomy(t) => { + context.add("taxonomy", &t.kind); + format!("{}/single.html", t.kind.name) + }, + }; context.add("current_url", &pager.permalink); context.add("current_path", &pager.path); context.add("paginator", &self.build_paginator_context(pager)); - render_template(&self.section.get_template_name(), tera, &context, &config.theme) - .chain_err(|| format!("Failed to render pager {} of section '{}'", pager.index, self.section.file.path.display())) + render_template(&template_name, tera, &context, &config.theme) + .chain_err(|| format!("Failed to render pager {}", pager.index)) } } @@ -179,6 +238,8 @@ mod tests { use front_matter::SectionFrontMatter; use content::{Page, Section}; + use config::{Taxonomy as TaxonomyConfig}; + use taxonomies::{Taxonomy, TaxonomyItem}; use super::Paginator; @@ -205,7 +266,7 @@ mod tests { Page::default(), ]; let section = create_section(false); - let paginator = Paginator::new(pages.as_slice(), §ion); + let paginator = Paginator::from_section(pages.as_slice(), §ion); assert_eq!(paginator.pagers.len(), 2); assert_eq!(paginator.pagers[0].index, 1); @@ -227,7 +288,7 @@ mod tests { Page::default(), ]; let section = create_section(true); - let paginator = Paginator::new(pages.as_slice(), §ion); + let paginator = Paginator::from_section(pages.as_slice(), §ion); assert_eq!(paginator.pagers.len(), 2); assert_eq!(paginator.pagers[0].index, 1); @@ -249,7 +310,7 @@ mod tests { Page::default(), ]; let section = create_section(false); - let paginator = Paginator::new(pages.as_slice(), §ion); + let paginator = Paginator::from_section(pages.as_slice(), §ion); assert_eq!(paginator.pagers.len(), 2); let context = paginator.build_paginator_context(&paginator.pagers[0]); @@ -268,4 +329,37 @@ mod tests { assert_eq!(context["previous"], to_value("https://vincent.is/posts/").unwrap()); assert_eq!(context["current_index"], to_value(2).unwrap()); } + + #[test] + fn test_can_create_paginator_for_taxonomy() { + let pages = vec![ + Page::default(), + Page::default(), + Page::default(), + ]; + let taxonomy_def = TaxonomyConfig { + name: "tags".to_string(), + paginate: Some(2), + ..TaxonomyConfig::default() + }; + let taxonomy_item = TaxonomyItem { + name: "Something".to_string(), + slug: "something".to_string(), + permalink: "https://vincent.is/tags/something/".to_string(), + pages, + }; + let taxonomy = Taxonomy {kind: taxonomy_def, items: vec![taxonomy_item.clone()]}; + let paginator = Paginator::from_taxonomy(&taxonomy, &taxonomy_item); + assert_eq!(paginator.pagers.len(), 2); + + assert_eq!(paginator.pagers[0].index, 1); + assert_eq!(paginator.pagers[0].pages.len(), 2); + assert_eq!(paginator.pagers[0].permalink, "https://vincent.is/tags/something/"); + assert_eq!(paginator.pagers[0].path, "tags/something"); + + assert_eq!(paginator.pagers[1].index, 2); + assert_eq!(paginator.pagers[1].pages.len(), 1); + assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/tags/something/pages/2/"); + assert_eq!(paginator.pagers[1].path, "tags/something/pages/2/"); + } } diff --git a/components/rebuild/src/lib.rs b/components/rebuild/src/lib.rs index fac94802..675388a0 100644 --- a/components/rebuild/src/lib.rs +++ b/components/rebuild/src/lib.rs @@ -26,10 +26,8 @@ pub fn find_parent_section<'a>(site: &'a Site, page: &Page) -> Option<&'a Sectio #[derive(Debug, Clone, Copy, PartialEq)] pub enum PageChangesNeeded { - /// Editing `tags` - Tags, - /// Editing `categories` - Categories, + /// Editing `taxonomies` + Taxonomies, /// Editing `date`, `order` or `weight` Sort, /// Editing anything causes a re-render of the page @@ -85,12 +83,8 @@ fn find_section_front_matter_changes(current: &SectionFrontMatter, new: &Section fn find_page_front_matter_changes(current: &PageFrontMatter, other: &PageFrontMatter) -> Vec { let mut changes_needed = vec![]; - if current.tags != other.tags { - changes_needed.push(PageChangesNeeded::Tags); - } - - if current.category != other.category { - changes_needed.push(PageChangesNeeded::Categories); + if current.taxonomies != other.taxonomies { + changes_needed.push(PageChangesNeeded::Taxonomies); } if current.date != other.date || current.order != other.order || current.weight != other.weight { @@ -117,8 +111,8 @@ fn delete_element(site: &mut Site, path: &Path, is_section: bool) -> Result<()> if let Some(p) = site.pages.remove(path) { site.permalinks.remove(&p.file.relative); - if p.meta.has_tags() || p.meta.category.is_some() { - site.populate_tags_and_categories(); + if !p.meta.taxonomies.is_empty() { + site.populate_taxonomies(); } // if there is a parent section, we will need to re-render it @@ -208,26 +202,14 @@ fn handle_page_editing(site: &mut Site, path: &Path) -> Result<()> { } // Front matter changed - let mut taxonomies_populated = false; let mut sections_populated = false; for changes in find_page_front_matter_changes(&site.pages[path].meta, &prev.meta) { // Sort always comes first if present so the rendering will be fine match changes { - PageChangesNeeded::Tags => { - if !taxonomies_populated { - site.populate_tags_and_categories(); - taxonomies_populated = true; - } + PageChangesNeeded::Taxonomies => { + site.populate_taxonomies(); site.register_tera_global_fns(); - site.render_tags()?; - }, - PageChangesNeeded::Categories => { - if !taxonomies_populated { - site.populate_tags_and_categories(); - taxonomies_populated = true; - } - site.register_tera_global_fns(); - site.render_categories()?; + site.render_taxonomies()?; }, PageChangesNeeded::Sort => { let section_path = match find_parent_section(site, &site.pages[path]) { @@ -258,7 +240,7 @@ fn handle_page_editing(site: &mut Site, path: &Path) -> Result<()> { // It's a new page! None => { site.populate_sections(); - site.populate_tags_and_categories(); + site.populate_taxonomies(); site.register_tera_global_fns(); // No need to optimise that yet, we can revisit if it becomes an issue site.build() @@ -322,10 +304,9 @@ pub fn after_template_change(site: &mut Site, path: &Path) -> Result<()> { match filename { "sitemap.xml" => site.render_sitemap(), - "rss.xml" => site.render_rss_feed(), + "rss.xml" => site.render_rss_feed(None, None), "robots.txt" => site.render_robots(), - "categories.html" | "category.html" => site.render_categories(), - "tags.html" | "tag.html" => site.render_tags(), + "single.html" | "list.html" => site.render_taxonomies(), "page.html" => { site.render_sections()?; site.render_orphan_pages() @@ -345,8 +326,7 @@ pub fn after_template_change(site: &mut Site, path: &Path) -> Result<()> { site.populate_sections(); site.render_sections()?; site.render_orphan_pages()?; - site.render_categories()?; - site.render_tags() + site.render_taxonomies() }, } } @@ -354,6 +334,8 @@ pub fn after_template_change(site: &mut Site, path: &Path) -> Result<()> { #[cfg(test)] mod tests { + use std::collections::HashMap; + use front_matter::{PageFrontMatter, SectionFrontMatter, SortBy}; use super::{ find_page_front_matter_changes, find_section_front_matter_changes, @@ -361,24 +343,21 @@ mod tests { }; #[test] - fn can_find_tag_changes_in_page_frontmatter() { - let new = PageFrontMatter { tags: Some(vec!["a tag".to_string()]), ..PageFrontMatter::default() }; + fn can_find_taxonomy_changes_in_page_frontmatter() { + let mut taxonomies = HashMap::new(); + taxonomies.insert("tags".to_string(), vec!["a tag".to_string()]); + let new = PageFrontMatter { taxonomies, ..PageFrontMatter::default() }; let changes = find_page_front_matter_changes(&PageFrontMatter::default(), &new); - assert_eq!(changes, vec![PageChangesNeeded::Tags, PageChangesNeeded::Render]); - } - - #[test] - fn can_find_category_changes_in_page_frontmatter() { - let current = PageFrontMatter { category: Some("a category".to_string()), ..PageFrontMatter::default() }; - let changes = find_page_front_matter_changes(¤t, &PageFrontMatter::default()); - assert_eq!(changes, vec![PageChangesNeeded::Categories, PageChangesNeeded::Render]); + assert_eq!(changes, vec![PageChangesNeeded::Taxonomies, PageChangesNeeded::Render]); } #[test] fn can_find_multiple_changes_in_page_frontmatter() { - let current = PageFrontMatter { category: Some("a category".to_string()), order: Some(1), ..PageFrontMatter::default() }; + let mut taxonomies = HashMap::new(); + taxonomies.insert("categories".to_string(), vec!["a category".to_string()]); + let current = PageFrontMatter { taxonomies, order: Some(1), ..PageFrontMatter::default() }; let changes = find_page_front_matter_changes(¤t, &PageFrontMatter::default()); - assert_eq!(changes, vec![PageChangesNeeded::Categories, PageChangesNeeded::Sort, PageChangesNeeded::Render]); + assert_eq!(changes, vec![PageChangesNeeded::Taxonomies, PageChangesNeeded::Sort, PageChangesNeeded::Render]); } #[test] diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index 3109f5db..f12299b6 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -39,7 +39,7 @@ use utils::net::get_available_port; use content::{Page, Section, populate_previous_and_next_pages, sort_pages}; use templates::{GUTENBERG_TERA, global_fns, render_redirect_template}; use front_matter::{SortBy, InsertAnchor}; -use taxonomies::Taxonomy; +use taxonomies::{Taxonomy, find_taxonomies}; use pagination::Paginator; use rayon::prelude::*; @@ -74,8 +74,7 @@ pub struct Site { pub output_path: PathBuf, content_path: PathBuf, pub static_path: PathBuf, - pub tags: Option, - pub categories: Option, + pub taxonomies: Vec, /// A map of all .md files (section and pages) and their permalink /// We need that if there are relative links in the content that need to be resolved pub permalinks: HashMap, @@ -128,8 +127,7 @@ impl Site { output_path: path.join("public"), content_path, static_path, - tags: None, - categories: None, + taxonomies: Vec::new(), permalinks: HashMap::new(), }; @@ -248,7 +246,7 @@ impl Site { self.register_early_global_fns(); self.render_markdown()?; self.populate_sections(); - self.populate_tags_and_categories(); + self.populate_taxonomies(); self.register_tera_global_fns(); Ok(()) @@ -302,7 +300,7 @@ impl Site { self.tera.register_global_function("get_section", global_fns::make_get_section(&self.sections)); self.tera.register_global_function( "get_taxonomy_url", - global_fns::make_get_taxonomy_url(self.tags.clone(), self.categories.clone()) + global_fns::make_get_taxonomy(self.taxonomies.clone()) ); } @@ -409,15 +407,12 @@ impl Site { } /// Find all the tags and categories if it's asked in the config - pub fn populate_tags_and_categories(&mut self) { - let generate_tags_pages = self.config.generate_tags_pages; - let generate_categories_pages = self.config.generate_categories_pages; - if !generate_tags_pages && !generate_categories_pages { + pub fn populate_taxonomies(&mut self) { + if self.config.taxonomies.is_empty() { return; } - // TODO: can we pass a reference? - let (tags, categories) = Taxonomy::find_tags_and_categories( + self.taxonomies = find_taxonomies( &self.config, self.pages .values() @@ -426,12 +421,6 @@ impl Site { .collect::>() .as_slice() ); - if generate_tags_pages { - self.tags = Some(tags); - } - if generate_categories_pages { - self.categories = Some(categories); - } } /// Inject live reload script tag if in live reload mode @@ -524,14 +513,11 @@ impl Site { self.render_orphan_pages()?; self.render_sitemap()?; if self.config.generate_rss { - self.render_rss_feed()?; + self.render_rss_feed(None, None)?; } self.render_404()?; self.render_robots()?; - // `render_categories` and `render_tags` will check whether the config allows - // them to render or not - self.render_categories()?; - self.render_tags()?; + self.render_taxonomies()?; if let Some(ref theme) = self.config.theme { let theme_path = self.base_path.join("themes").join(theme); @@ -681,19 +667,11 @@ impl Site { ) } - /// Renders all categories and the single category pages if there are some - pub fn render_categories(&self) -> Result<()> { - if let Some(ref categories) = self.categories { - self.render_taxonomy(categories)?; - } - - Ok(()) - } - - /// Renders all tags and the single tag pages if there are some - pub fn render_tags(&self) -> Result<()> { - if let Some(ref tags) = self.tags { - self.render_taxonomy(tags)?; + /// Renders all taxonomies with at least one non-draft post + pub fn render_taxonomies(&self) -> Result<()> { + // TODO: make parallel? + for taxonomy in &self.taxonomies { + self.render_taxonomy(taxonomy)?; } Ok(()) @@ -705,8 +683,8 @@ impl Site { } ensure_directory_exists(&self.output_path)?; - let output_path = self.output_path.join(&taxonomy.get_list_name()); - let list_output = taxonomy.render_list(&self.tera, &self.config)?; + let output_path = self.output_path.join(&taxonomy.kind.name); + let list_output = taxonomy.render_all_terms(&self.tera, &self.config)?; create_directory(&output_path)?; create_file(&output_path.join("index.html"), &self.inject_livereload(list_output))?; @@ -714,12 +692,25 @@ impl Site { .items .par_iter() .map(|item| { - let single_output = taxonomy.render_single_item(item, &self.tera, &self.config)?; - create_directory(&output_path.join(&item.slug))?; - create_file( - &output_path.join(&item.slug).join("index.html"), - &self.inject_livereload(single_output) - ) + if taxonomy.kind.rss { + // TODO: can we get rid of `clone()`? + self.render_rss_feed( + Some(item.pages.clone()), + Some(&PathBuf::from(format!("{}/{}", taxonomy.kind.name, item.slug))) + )?; + } + + if taxonomy.kind.is_paginated() { + self.render_paginated(&output_path, &Paginator::from_taxonomy(&taxonomy, item)) + } else { + let single_output = taxonomy.render_term(item, &self.tera, &self.config)?; + let path = output_path.join(&item.slug); + create_directory(&path)?; + create_file( + &path.join("index.html"), + &self.inject_livereload(single_output), + ) + } }) .fold(|| Ok(()), Result::and) .reduce(|| Ok(()), Result::and) @@ -752,31 +743,19 @@ impl Site { sections.sort_by(|a, b| a.permalink.cmp(&b.permalink)); context.add("sections", §ions); - let mut categories = vec![]; - if let Some(ref c) = self.categories { - let name = c.get_list_name(); - categories.push(SitemapEntry::new(self.config.make_permalink(&name), None)); - for item in &c.items { - categories.push( - SitemapEntry::new(self.config.make_permalink(&format!("{}/{}", &name, item.slug)), None), - ); + let mut taxonomies = vec![]; + for taxonomy in &self.taxonomies { + let name = &taxonomy.kind.name; + let mut terms = vec![]; + terms.push(SitemapEntry::new(self.config.make_permalink(name), None)); + for item in &taxonomy.items { + terms.push(SitemapEntry::new(self.config.make_permalink(&format!("{}/{}", &name, item.slug)), None)); } + terms.sort_by(|a, b| a.permalink.cmp(&b.permalink)); + taxonomies.push(terms); } - categories.sort_by(|a, b| a.permalink.cmp(&b.permalink)); - context.add("categories", &categories); + context.add("taxonomies", &taxonomies); - let mut tags = vec![]; - if let Some(ref t) = self.tags { - let name = t.get_list_name(); - tags.push(SitemapEntry::new(self.config.make_permalink(&name), None)); - for item in &t.items { - tags.push( - SitemapEntry::new(self.config.make_permalink(&format!("{}/{}", &name, item.slug)), None), - ); - } - } - tags.sort_by(|a, b| a.permalink.cmp(&b.permalink)); - context.add("tags", &tags); context.add("config", &self.config); let sitemap = &render_template("sitemap.xml", &self.tera, &context, &self.config.theme)?; @@ -786,14 +765,20 @@ impl Site { Ok(()) } - pub fn render_rss_feed(&self) -> Result<()> { + /// Renders a RSS feed for the given path and at the given path + /// If both arguments are `None`, it will render only the RSS feed for the whole + /// site at the root folder. + pub fn render_rss_feed(&self, all_pages: Option>, base_path: Option<&PathBuf>) -> Result<()> { ensure_directory_exists(&self.output_path)?; let mut context = Context::new(); - let pages = self.pages.values() + let pages = all_pages + // TODO: avoid that cloned(). + // It requires having `sort_pages` take references of Page + .unwrap_or_else(|| self.pages.values().cloned().collect::>()) + .into_iter() .filter(|p| p.meta.date.is_some() && !p.is_draft()) - .cloned() - .collect::>(); + .collect::>(); // Don't generate a RSS feed if none of the pages has a date if pages.is_empty() { @@ -802,20 +787,32 @@ impl Site { let (sorted_pages, _) = sort_pages(pages, SortBy::Date); context.add("last_build_date", &sorted_pages[0].meta.date.clone().map(|d| d.to_string())); - // limit to the last n elements) + // limit to the last n elements context.add("pages", &sorted_pages.iter().take(self.config.rss_limit).collect::>()); context.add("config", &self.config); - let rss_feed_url = if self.config.base_url.ends_with('/') { - format!("{}{}", self.config.base_url, "rss.xml") + let rss_feed_url = if let Some(ref base) = base_path { + self.config.make_permalink(&base.join("rss.xml").to_string_lossy()) } else { - format!("{}/{}", self.config.base_url, "rss.xml") + self.config.make_permalink("rss.xml") }; + context.add("feed_url", &rss_feed_url); let feed = &render_template("rss.xml", &self.tera, &context, &self.config.theme)?; - create_file(&self.output_path.join("rss.xml"), feed)?; + if let Some(ref base) = base_path { + let mut output_path = self.output_path.clone().to_path_buf(); + for component in base.components() { + output_path.push(component); + if !output_path.exists() { + create_directory(&output_path)?; + } + } + create_file(&output_path.join("rss.xml"), feed)?; + } else { + create_file(&self.output_path.join("rss.xml"), feed)?; + } Ok(()) } @@ -854,7 +851,7 @@ impl Site { } if section.meta.is_paginated() { - self.render_paginated(&output_path, section)?; + self.render_paginated(&output_path, &Paginator::from_section(§ion.pages, section))?; } else { let output = section.render_html(&self.tera, &self.config)?; create_file(&output_path.join("index.html"), &self.inject_livereload(output))?; @@ -894,11 +891,10 @@ impl Site { } /// Renders a list of pages when the section/index is wanting pagination. - pub fn render_paginated(&self, output_path: &Path, section: &Section) -> Result<()> { + pub fn render_paginated(&self, output_path: &Path, paginator: &Paginator) -> Result<()> { ensure_directory_exists(&self.output_path)?; - let paginator = Paginator::new(§ion.pages, section); - let folder_path = output_path.join(§ion.meta.paginate_path); + let folder_path = output_path.join(&paginator.paginate_path); create_directory(&folder_path)?; paginator @@ -913,7 +909,7 @@ impl Site { create_file(&page_path.join("index.html"), &self.inject_livereload(output))?; } else { create_file(&output_path.join("index.html"), &self.inject_livereload(output))?; - create_file(&page_path.join("index.html"), &render_redirect_template(§ion.permalink, &self.tera)?)?; + create_file(&page_path.join("index.html"), &render_redirect_template(&paginator.permalink, &self.tera)?)?; } Ok(()) }) diff --git a/components/site/tests/site.rs b/components/site/tests/site.rs index ddb01de5..3d030ee0 100644 --- a/components/site/tests/site.rs +++ b/components/site/tests/site.rs @@ -1,6 +1,7 @@ extern crate site; extern crate tempfile; +use std::collections::HashMap; use std::env; use std::path::Path; use std::fs::File; @@ -209,28 +210,27 @@ fn can_build_site_with_live_reload() { } #[test] -fn can_build_site_with_categories() { +fn can_build_site_with_taxonomies() { let mut path = env::current_dir().unwrap().parent().unwrap().parent().unwrap().to_path_buf(); path.push("test_site"); let mut site = Site::new(&path, "config.toml").unwrap(); - site.config.generate_categories_pages = true; site.load().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()) + page.meta.taxonomies = { + let mut taxonomies = HashMap::new(); + taxonomies.insert("categories".to_string(), vec![if i % 2 == 0 { "A" } else { "B" }.to_string()]); + taxonomies }; } - site.populate_tags_and_categories(); + site.populate_taxonomies(); let tmp_dir = tempdir().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.unwrap().len(), 2); + assert_eq!(site.taxonomies.len(), 1); assert!(file_exists!(public, "index.html")); assert!(file_exists!(public, "sitemap.xml")); @@ -246,12 +246,13 @@ fn can_build_site_with_categories() { 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")); + assert!(file_exists!(public, "categories/a/rss.xml")); + assert!(file_contains!(public, "categories/a/rss.xml", "https://replace-this-with-your-url.com/categories/a/rss.xml")); // Extending from a theme works assert!(file_contains!(public, "categories/a/index.html", "EXTENDED")); // Tags aren't @@ -262,58 +263,6 @@ fn can_build_site_with_categories() { assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/categories/a/")); } -#[test] -fn can_build_site_with_tags() { - let mut path = env::current_dir().unwrap().parent().unwrap().parent().unwrap().to_path_buf(); - path.push("test_site"); - let mut site = Site::new(&path, "config.toml").unwrap(); - site.config.generate_tags_pages = true; - site.load().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.populate_tags_and_categories(); - - let tmp_dir = tempdir().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.unwrap().len(), 3); - - assert!(file_exists!(public, "index.html")); - assert!(file_exists!(public, "sitemap.xml")); - assert!(file_exists!(public, "robots.txt")); - 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/")); -} - #[test] fn can_build_site_and_insert_anchor_links() { let mut path = env::current_dir().unwrap().parent().unwrap().parent().unwrap().to_path_buf(); diff --git a/components/taxonomies/src/lib.rs b/components/taxonomies/src/lib.rs index b18a9647..f576c843 100644 --- a/components/taxonomies/src/lib.rs +++ b/components/taxonomies/src/lib.rs @@ -14,19 +14,13 @@ use std::collections::HashMap; use slug::slugify; use tera::{Context, Tera}; -use config::Config; +use config::{Config, Taxonomy as TaxonomyConfig}; use errors::{Result, ResultExt}; use content::{Page, sort_pages}; use front_matter::SortBy; use utils::templates::render_template; -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum TaxonomyKind { - Tags, - Categories, -} - /// A tag or category #[derive(Debug, Clone, Serialize, PartialEq)] pub struct TaxonomyItem { @@ -37,15 +31,14 @@ pub struct TaxonomyItem { } impl TaxonomyItem { - pub fn new(name: &str, kind: TaxonomyKind, config: &Config, pages: Vec) -> TaxonomyItem { + pub fn new(name: &str, path: &str, config: &Config, pages: Vec) -> TaxonomyItem { // Taxonomy are almost always used for blogs so we filter by dates // and it's not like we can sort things across sections by anything other // than dates let (mut pages, ignored_pages) = sort_pages(pages, SortBy::Date); let slug = slugify(name); let permalink = { - let kind_path = if kind == TaxonomyKind::Tags { "tags" } else { "categories" }; - config.make_permalink(&format!("/{}/{}", kind_path, slug)) + config.make_permalink(&format!("/{}/{}", path, slug)) }; // We still append pages without dates at the end @@ -61,49 +54,19 @@ impl TaxonomyItem { } /// All the tags or categories -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize)] pub struct Taxonomy { - pub kind: TaxonomyKind, + pub kind: TaxonomyConfig, // this vec is sorted by the count of item pub items: Vec, } impl Taxonomy { - pub fn find_tags_and_categories(config: &Config, all_pages: &[Page]) -> (Taxonomy, Taxonomy) { - let mut tags = HashMap::new(); - let mut categories = HashMap::new(); - - // Find all the tags/categories first - for page in all_pages { - if let Some(ref category) = page.meta.category { - categories - .entry(category.to_string()) - .or_insert_with(|| vec![]) - .push(page.clone()); - } - - if let Some(ref t) = page.meta.tags { - for tag in t { - tags - .entry(tag.to_string()) - .or_insert_with(|| vec![]) - .push(page.clone()); - } - } - } - - // Then make TaxonomyItem out of them, after sorting it - let tags_taxonomy = Taxonomy::new(TaxonomyKind::Tags, config, tags); - let categories_taxonomy = Taxonomy::new(TaxonomyKind::Categories, config, categories); - - (tags_taxonomy, categories_taxonomy) - } - - fn new(kind: TaxonomyKind, config: &Config, items: HashMap>) -> Taxonomy { + fn new(kind: TaxonomyConfig, config: &Config, items: HashMap>) -> Taxonomy { let mut sorted_items = vec![]; - for (name, pages) in &items { + for (name, pages) in items { sorted_items.push( - TaxonomyItem::new(name, kind, config, pages.clone()) + TaxonomyItem::new(&name, &kind.name, config, pages) ); } sorted_items.sort_by(|a, b| a.name.cmp(&b.name)); @@ -122,69 +85,123 @@ impl Taxonomy { self.len() == 0 } - pub fn get_single_item_name(&self) -> String { - match self.kind { - TaxonomyKind::Tags => "tag".to_string(), - TaxonomyKind::Categories => "category".to_string(), - } - } - - pub fn get_list_name(&self) -> String { - match self.kind { - TaxonomyKind::Tags => "tags".to_string(), - TaxonomyKind::Categories => "categories".to_string(), - } - } - - pub fn render_single_item(&self, item: &TaxonomyItem, tera: &Tera, config: &Config) -> Result { - let name = self.get_single_item_name(); + pub fn render_term(&self, item: &TaxonomyItem, tera: &Tera, config: &Config) -> Result { let mut context = Context::new(); context.add("config", config); - context.add(&name, item); - context.add("current_url", &config.make_permalink(&format!("{}/{}", name, item.slug))); - context.add("current_path", &format!("/{}/{}", name, item.slug)); + context.add("term", item); + context.add("taxonomy", &self.kind); + context.add("current_url", &config.make_permalink(&format!("{}/{}", self.kind.name, item.slug))); + context.add("current_path", &format!("/{}/{}", self.kind.name, item.slug)); - render_template(&format!("{}.html", name), tera, &context, &config.theme) - .chain_err(|| format!("Failed to render {} page.", name)) + render_template(&format!("{}/single.html", self.kind.name), tera, &context, &config.theme) + .chain_err(|| format!("Failed to render single term {} page.", self.kind.name)) } - pub fn render_list(&self, tera: &Tera, config: &Config) -> Result { - let name = self.get_list_name(); + pub fn render_all_terms(&self, tera: &Tera, config: &Config) -> Result { let mut context = Context::new(); context.add("config", config); - context.add(&name, &self.items); - context.add("current_url", &config.make_permalink(&name)); - context.add("current_path", &name); + context.add("terms", &self.items); + context.add("taxonomy", &self.kind); + context.add("current_url", &config.make_permalink(&self.kind.name)); + context.add("current_path", &self.kind.name); - render_template(&format!("{}.html", name), tera, &context, &config.theme) - .chain_err(|| format!("Failed to render {} page.", name)) + render_template(&format!("{}/list.html", self.kind.name), tera, &context, &config.theme) + .chain_err(|| format!("Failed to render a list of {} page.", self.kind.name)) } } +pub fn find_taxonomies(config: &Config, all_pages: &[Page]) -> Vec { + let taxonomies_def = { + let mut m = HashMap::new(); + for t in &config.taxonomies { + m.insert(t.name.clone(), t); + } + m + }; + let mut all_taxonomies = HashMap::new(); + + // Find all the taxonomies first + for page in all_pages { + for (name, val) in &page.meta.taxonomies { + if taxonomies_def.contains_key(name) { + all_taxonomies + .entry(name) + .or_insert_with(|| HashMap::new()); + + for v in val { + all_taxonomies.get_mut(name) + .unwrap() + .entry(v.to_string()) + .or_insert_with(|| vec![]) + .push(page.clone()); + } + } else { + // TODO: bail with error + } + } + } + + let mut taxonomies = vec![]; + + for (name, taxo) in all_taxonomies { + taxonomies.push(Taxonomy::new(taxonomies_def[name].clone(), config, taxo)); + } + + taxonomies +} + + #[cfg(test)] mod tests { use super::*; + use std::collections::HashMap; - use config::Config; + use config::{Config, Taxonomy}; use content::Page; #[test] fn can_make_taxonomies() { - let config = Config::default(); + let mut config = Config::default(); + config.taxonomies = vec![ + Taxonomy {name: "categories".to_string(), ..Taxonomy::default()}, + Taxonomy {name: "tags".to_string(), ..Taxonomy::default()}, + Taxonomy {name: "authors".to_string(), ..Taxonomy::default()}, + ]; let mut page1 = Page::default(); - page1.meta.tags = Some(vec!["rust".to_string(), "db".to_string()]); - page1.meta.category = Some("Programming tutorials".to_string()); + let mut taxo_page1 = HashMap::new(); + taxo_page1.insert("tags".to_string(), vec!["rust".to_string(), "db".to_string()]); + taxo_page1.insert("categories".to_string(), vec!["Programming tutorials".to_string()]); + page1.meta.taxonomies = taxo_page1; let mut page2 = Page::default(); - page2.meta.tags = Some(vec!["rust".to_string(), "js".to_string()]); - page2.meta.category = Some("Other".to_string()); + let mut taxo_page2 = HashMap::new(); + taxo_page2.insert("tags".to_string(), vec!["rust".to_string(), "js".to_string()]); + taxo_page2.insert("categories".to_string(), vec!["Other".to_string()]); + page2.meta.taxonomies = taxo_page2; let mut page3 = Page::default(); - page3.meta.tags = Some(vec!["js".to_string()]); + let mut taxo_page3 = HashMap::new(); + taxo_page3.insert("tags".to_string(), vec!["js".to_string()]); + taxo_page3.insert("authors".to_string(), vec!["Vincent Prouillet".to_string()]); + page3.meta.taxonomies = taxo_page3; let pages = vec![page1, page2, page3]; - let (tags, categories) = Taxonomy::find_tags_and_categories(&config, &pages); - + let taxonomies = find_taxonomies(&config, &pages); + let (tags, categories, authors) = { + let mut t = None; + let mut c = None; + let mut a = None; + for x in taxonomies { + match x.kind.name.as_ref() { + "tags" => t = Some(x), + "categories" => c = Some(x), + "authors" => a = Some(x), + _ => unreachable!(), + } + } + (t.unwrap(), c.unwrap(), a.unwrap()) + }; assert_eq!(tags.items.len(), 3); assert_eq!(categories.items.len(), 2); + assert_eq!(authors.items.len(), 1); assert_eq!(tags.items[0].name, "db"); assert_eq!(tags.items[0].slug, "db"); diff --git a/components/templates/src/builtins/rss.xml b/components/templates/src/builtins/rss.xml index 35b7fbcd..3baccf84 100644 --- a/components/templates/src/builtins/rss.xml +++ b/components/templates/src/builtins/rss.xml @@ -1,18 +1,18 @@ {{ config.title }} - {{ config.base_url }} + {{ config.base_url | safe }} {{ config.description }} Gutenberg {{ config.default_language }} - + {{ 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.permalink | safe }} + {{ page.permalink | safe }} {% if page.summary %}{{ page.summary }}{% else %}{{ page.content }}{% endif %} {% endfor %} diff --git a/components/templates/src/builtins/sitemap.xml b/components/templates/src/builtins/sitemap.xml index 3ee6bbcb..6eba3d74 100644 --- a/components/templates/src/builtins/sitemap.xml +++ b/components/templates/src/builtins/sitemap.xml @@ -12,14 +12,11 @@ {{ section.permalink | safe }} {% endfor %} - {% for category in categories %} + {% for taxonomy in taxonomies %} + {% for entry in taxonomy %} - {{ category.permalink | safe }} - - {% endfor %} - {% for tag in tags %} - - {{ tag.permalink | safe }} + {{ entry.permalink | safe }} + {% endfor %} {% endfor %} diff --git a/components/templates/src/global_fns.rs b/components/templates/src/global_fns.rs index 5db2da89..e02d0e95 100644 --- a/components/templates/src/global_fns.rs +++ b/components/templates/src/global_fns.rs @@ -134,36 +134,25 @@ pub fn make_get_url(permalinks: HashMap, config: Config) -> Glob }) } -pub fn make_get_taxonomy_url(tags: Option, categories: Option) -> GlobalFn { +pub fn make_get_taxonomy(all_taxonomies: Vec) -> GlobalFn { + let mut taxonomies = HashMap::new(); + for taxonomy in all_taxonomies { + taxonomies.insert(taxonomy.kind.name.clone(), taxonomy); + } Box::new(move |args| -> Result { let kind = required_arg!( String, args.get("kind"), - "`get_taxonomy_url` requires a `kind` argument with a string value" + "`get_taxonomy` requires a `kind` argument with a string value" ); - let name = required_arg!( - String, - args.get("name"), - "`get_taxonomy_url` requires a `name` argument with a string value" - ); - let container = match kind.as_ref() { - "tag" => &tags, - "category" => &categories, - _ => return Err( - "`get_taxonomy_url` can only get `tag` or `category` for the `kind` argument".into() + let container = match taxonomies.get(&kind) { + Some(c) => c, + None => return Err( + format!("`get_taxonomy` received an unknown taxonomy as kind: {}", kind).into() ), }; - if let Some(ref c) = *container { - for item in &c.items { - if item.name == name { - return Ok(to_value(item.permalink.clone()).unwrap()); - } - } - bail!("`get_taxonomy_url`: couldn't find `{}` in `{}` taxonomy", name, kind); - } else { - bail!("`get_taxonomy_url` tried to get a taxonomy of kind `{}` but there isn't any", kind); - } + return Ok(to_value(container).unwrap()); }) } @@ -217,14 +206,14 @@ pub fn make_resize_image(imageproc: Arc>) -> GlobalF #[cfg(test)] mod tests { - use super::{make_get_url, make_get_taxonomy_url, make_trans}; + use super::{make_get_url, make_get_taxonomy, make_trans}; use std::collections::HashMap; use tera::to_value; - use config::Config; - use taxonomies::{Taxonomy, TaxonomyKind, TaxonomyItem}; + use config::{Config, Taxonomy as TaxonomyConfig}; + use taxonomies::{Taxonomy, TaxonomyItem}; #[test] @@ -268,28 +257,27 @@ mod tests { } #[test] - fn can_get_tag_url() { + fn can_get_taxonomy() { + let taxo_config = TaxonomyConfig {name: "tags".to_string(), ..TaxonomyConfig::default()}; let tag = TaxonomyItem::new( "Prog amming", - TaxonomyKind::Tags, + "tags", &Config::default(), vec![], ); let tags = Taxonomy { - kind: TaxonomyKind::Tags, + kind: taxo_config, items: vec![tag], }; - let static_fn = make_get_taxonomy_url(Some(tags), None); + let static_fn = make_get_taxonomy(vec![tags.clone()]); // can find it correctly let mut args = HashMap::new(); - args.insert("kind".to_string(), to_value("tag").unwrap()); - args.insert("name".to_string(), to_value("Prog amming").unwrap()); - assert_eq!(static_fn(args).unwrap(), "http://a-website.com/tags/prog-amming/"); + args.insert("kind".to_string(), to_value("tags").unwrap()); + assert_eq!(static_fn(args).unwrap(), to_value(&tags).unwrap()); // and errors if it can't find it let mut args = HashMap::new(); - args.insert("kind".to_string(), to_value("tag").unwrap()); - args.insert("name".to_string(), to_value("random").unwrap()); + args.insert("kind".to_string(), to_value("something-else").unwrap()); assert!(static_fn(args).is_err()); } diff --git a/components/templates/src/lib.rs b/components/templates/src/lib.rs index ce0fe912..dbf1d158 100644 --- a/components/templates/src/lib.rs +++ b/components/templates/src/lib.rs @@ -5,7 +5,6 @@ extern crate tera; extern crate base64; extern crate pulldown_cmark; -#[macro_use] extern crate errors; extern crate utils; extern crate content; diff --git a/components/utils/src/templates.rs b/components/utils/src/templates.rs index c7432abb..68a0818d 100644 --- a/components/utils/src/templates.rs +++ b/components/utils/src/templates.rs @@ -41,8 +41,8 @@ pub fn render_template(name: &str, tera: &Tera, context: &Context, theme: &Optio "page.html" => { render_default_tpl!(name, "https://www.getgutenberg.io/documentation/templates/pages-sections/#page-variables") }, - "tag.html" | "tags.html" | "category.html" | "categories.html" => { - render_default_tpl!(name, "https://www.getgutenberg.io/documentation/templates/tags-categories/") + "single.html" | "list.html" => { + render_default_tpl!(name, "https://www.getgutenberg.io/documentation/templates/taxonomies/") }, _ => bail!("Tried to render `{}` but the template wasn't found", name) } diff --git a/docs/content/documentation/content/page.md b/docs/content/documentation/content/page.md index fb3f962d..04cb6c23 100644 --- a/docs/content/documentation/content/page.md +++ b/docs/content/documentation/content/page.md @@ -38,11 +38,10 @@ slug = "" # It should not start with a `/` and the slash will be removed if it does path = "" -# An array of strings allowing you to group pages with them -tags = [] - -# An overarching category name for that page, allowing you to group pages with it -category = "" +# A dict of taxonomies: the key is the name of the taxonomy which must match +# one of the taxonomy defined in `config.toml` and the value is a list of +# strings +[taxonomies] # The order as defined in the Section page order = 0 diff --git a/docs/content/documentation/content/tags-categories.md b/docs/content/documentation/content/tags-categories.md deleted file mode 100644 index 20eae9e8..00000000 --- a/docs/content/documentation/content/tags-categories.md +++ /dev/null @@ -1,23 +0,0 @@ -+++ -title = "Tags & Categories" -weight = 90 -+++ - -Gutenberg has built-in support for basic taxonomies: tags and categories. - -Those taxonomies are automatically built across the whole site based on -the `tags` and `category` fields of the front-matter: you do not need to define -that a tag or a category exists. You have to set `generate_tags_pages` and/or -`generate_categories_pages` in your [config.toml](./documentation/getting-started/configuration.md). - -The taxonomy pages will only be created if at least one item is found and -are available at the following paths: - -```plain -$BASE_URL/tags/ -$BASE_URL/tags/$TAG_SLUG -$BASE_URL/categories/ -$BASE_URL/categories/$CATEGORY_SLUG -``` - -It is currently not possible to change those paths or to create custom taxonomies. diff --git a/docs/content/documentation/content/taxonomies.md b/docs/content/documentation/content/taxonomies.md new file mode 100644 index 00000000..77ab8026 --- /dev/null +++ b/docs/content/documentation/content/taxonomies.md @@ -0,0 +1,27 @@ ++++ +title = "Taxonomies" +weight = 90 ++++ + +Gutenberg has built-in support for taxonomies. + +The first step is to define the taxonomies in your [config.toml](./documentation/getting-started/configuration.md). + +A taxonomy has 4 variables: + +- `name`: a required string that will be used in the URLs, usually the plural version (i.e. tags, categories etc) +- `paginate`: if this is set to a number, each term page will be paginated by this much. +- `paginate_path`: if set, will be the path used by paginated page and the page number will be appended after it. +For example the default would be page/1 +- `rss`: if set to `true`, a RSS feed will be generated for each individual term. + +Once this is done, you can then set taxonomies in your content and Gutenberg will pick +them up. + +The taxonomy pages will only be created if at least one non-draft page is found and +are available at the following paths: + +```plain +$BASE_URL/$NAME/ +$BASE_URL/$NAME/$SLUG +``` diff --git a/docs/content/documentation/getting-started/configuration.md b/docs/content/documentation/getting-started/configuration.md index 0cf21b79..87cae5e2 100644 --- a/docs/content/documentation/getting-started/configuration.md +++ b/docs/content/documentation/getting-started/configuration.md @@ -40,13 +40,14 @@ generate_rss = false # The number of articles to include in the RSS feed rss_limit = 20 -# Whether to generate a tags page and individual -# tag pages for pages with tags -generate_tags_pages = false - -# Whether to generate a categories page and individual -# category pages for pages with a category -generate_categories_pages = false +# The taxonomies to be rendered for that site and their configuration +# Example: +# taxonomies = [ +# {name: "tags", rss: true}, # each tag will have its own RSS feed +# {name: "categories", paginate: 5}, # 5 terms per page +# ] +# +taxonomies = [] # Whether to compile the Sass files found in the `sass` directory compile_sass = false diff --git a/docs/content/documentation/templates/pagination.md b/docs/content/documentation/templates/pagination.md index e9561c0b..ccbf6ab9 100644 --- a/docs/content/documentation/templates/pagination.md +++ b/docs/content/documentation/templates/pagination.md @@ -3,9 +3,14 @@ title = "Pagination" weight = 30 +++ +Two things can get paginated: a section or a taxonomy term. + A paginated section gets the same `section` variable as a normal -[section page](./documentation/templates/pages-sections.md#section-variables). -In addition, a paginated section gets a `paginator` variable of the `Pager` type: +[section page](./documentation/templates/pages-sections.md#section-variables) +while a paginated taxonomy gets the a `taxonomy` variable of type `TaxonomyConfig`, equivalent +to the taxonomy definition in the `config.toml`. + +In addition, a paginated page gets a `paginator` variable of the `Pager` type: ```ts // How many items per page diff --git a/docs/content/documentation/templates/tags-categories.md b/docs/content/documentation/templates/tags-categories.md deleted file mode 100644 index db5adf33..00000000 --- a/docs/content/documentation/templates/tags-categories.md +++ /dev/null @@ -1,31 +0,0 @@ -+++ -title = "Tags & Categories" -weight = 40 -+++ - -Tags and categories actually get the same data but with different variable names. -The default templates for those pages are the following: - -- `tags.html`: list of tags, gets variable `tags` sorted alphabetically -- `tag.html`: individual tag, gets variable `tag` -- `categories.html`: list of categories, gets variable `categories` sorted alphabetically -- `category.html`: individual category, gets variable `category` - -You can override any of those templates by putting one with the same name in the `templates` directory. -`tags` and `categories` both are an array of `TaxonomyItem` sorted alphabetically, while `tag` and `category` -are a `TaxonomyItem`. - -A `TaxonomyItem` has the following fields: - -```ts -name: String; -slug: String; -permalink: String; -pages: Array; -``` - -As `pages` can span many sections, the `pages` array is sorted by date. - -Currently, there is no way to define different taxonomy templates per section, change -the path used for them or paginate them. - diff --git a/docs/content/documentation/templates/taxonomies.md b/docs/content/documentation/templates/taxonomies.md new file mode 100644 index 00000000..a9e8576e --- /dev/null +++ b/docs/content/documentation/templates/taxonomies.md @@ -0,0 +1,53 @@ ++++ +title = "Taxonomies" +weight = 40 ++++ + +The default templates for the taxonomies pages are the following: + +- `$TAXONOMY_NAME/single.html` +- `$TAXONOMY_NAME/list.html` + +You can override any of those templates by putting one with the same path in the `templates` directory. + +First, a `TaxonomyTerm` has the following fields: + +```ts +name: String; +slug: String; +permalink: String; +pages: Array; +``` + +## Non-paginated taxonomies +If a taxonomy is not paginated, the templates get the following variables: + +### Single term (`single.html`) +```ts +// The site config +config: Config; +// The data of the taxonomy, from the config +taxonomy: TaxonomyConfig; +// The current full permalink for that page +current_url: String; +// The current path for that page +current_path: String; +// The current term being rendered +term: TaxonomyTerm; +``` + +### Taxonomy list (`list.html`) +```ts +// The site config +config: Config; +// The data of the taxonomy, from the config +taxonomy: TaxonomyConfig; +// The current full permalink for that page +current_url: String; +// The current path for that page +current_path: String; +// All terms for that taxonomy +terms: Array; +``` + +## Paginated taxonomies diff --git a/test_site/config.toml b/test_site/config.toml index 4b1caeda..b667b9b8 100644 --- a/test_site/config.toml +++ b/test_site/config.toml @@ -6,5 +6,9 @@ generate_rss = true rss_limit = 2 theme = "sample" +taxonomies = [ + {name = "categories", rss = true}, +] + [extra.author] name = "Vincent Prouillet" diff --git a/test_site/templates/categories.html b/test_site/templates/categories.html deleted file mode 100644 index 59813456..00000000 --- a/test_site/templates/categories.html +++ /dev/null @@ -1,3 +0,0 @@ -{% for category in categories %} - {{ category.name }} {{ category.slug }} {{ category.pages | length }} -{% endfor %} diff --git a/test_site/templates/categories/list.html b/test_site/templates/categories/list.html new file mode 100644 index 00000000..3b8116f1 --- /dev/null +++ b/test_site/templates/categories/list.html @@ -0,0 +1,3 @@ +{% for term in terms %} + {{ term.name }} {{ term.slug }} {{ term.pages | length }} +{% endfor %} diff --git a/test_site/templates/category.html b/test_site/templates/categories/single.html similarity index 54% rename from test_site/templates/category.html rename to test_site/templates/categories/single.html index f7904310..23dd537c 100644 --- a/test_site/templates/category.html +++ b/test_site/templates/categories/single.html @@ -1,4 +1,4 @@ -{% extends "sample/templates/category.html" %} +{% extends "sample/templates/categories/single.html" %} {% block extra_category %} EXTENDED diff --git a/test_site/themes/sample/templates/category.html b/test_site/themes/sample/templates/categories/single.html similarity index 75% rename from test_site/themes/sample/templates/category.html rename to test_site/themes/sample/templates/categories/single.html index 7a016ae2..cd3df713 100644 --- a/test_site/themes/sample/templates/category.html +++ b/test_site/themes/sample/templates/categories/single.html @@ -1,7 +1,7 @@ -Category: {{ category.name }} +Category: {{ term.name }} -{% for page in category.pages %} +{% for page in term.pages %}