added watch command with optional auto-reload

master
Kenton Hamaluik 5 years ago
parent 5b0cc03ac8
commit 8b25596a8a

379
Cargo.lock generated

@ -169,6 +169,23 @@ name = "byteorder"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bytes"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "c2-chacha"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
version = "1.0.47"
@ -221,6 +238,16 @@ dependencies = [
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "colored"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "comrak"
version = "0.6.2"
@ -283,6 +310,27 @@ name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fern"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "filetime"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "flate2"
version = "1.0.13"
@ -299,6 +347,37 @@ name = "fnv"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fsevent"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fsevent-sys"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fxhash"
version = "0.2.1"
@ -315,6 +394,16 @@ dependencies = [
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "getrandom"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glob"
version = "0.3.0"
@ -328,6 +417,11 @@ dependencies = [
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "httparse"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "humansize"
version = "1.1.0"
@ -341,11 +435,56 @@ dependencies = [
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "idna"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "inotify"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "inotify-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -389,6 +528,7 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -396,6 +536,11 @@ name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.2.1"
@ -409,6 +554,46 @@ dependencies = [
"adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio-extras"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miow"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mkbook"
version = "0.3.0"
@ -417,11 +602,25 @@ dependencies = [
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"comrak 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"sass-rs 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"syntect 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net2"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -433,6 +632,24 @@ dependencies = [
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "notify"
version = "4.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
version = "0.1.41"
@ -490,6 +707,11 @@ name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pest"
version = "2.1.2"
@ -547,6 +769,11 @@ dependencies = [
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ppv-lite86"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.30"
@ -584,6 +811,43 @@ dependencies = [
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_chacha"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
@ -692,6 +956,16 @@ name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.8.0"
@ -817,6 +1091,22 @@ name = "unchecked-index"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-bidi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-normalization"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-width"
version = "0.1.6"
@ -837,6 +1127,16 @@ name = "unicode_categories"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "vec_map"
version = "0.8.1"
@ -857,6 +1157,11 @@ dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasi"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "which"
version = "2.0.1"
@ -866,6 +1171,11 @@ dependencies = [
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
@ -875,6 +1185,11 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
@ -902,6 +1217,32 @@ dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ws"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xml-rs"
version = "0.8.0"
@ -935,12 +1276,15 @@ dependencies = [
"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
"checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8"
"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "433e7ac7d511768127ed85b0c4947f47a254131e37864b2dc13f52aa32cd37e5"
"checksum comrak 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea4c29f52463abf5c7a3ae33dd9b404e2031af82f547cfe65bfac17ba785ea2e"
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
@ -948,15 +1292,28 @@ dependencies = [
"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa"
"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d"
"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6"
"checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0"
"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 fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120"
"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
@ -965,9 +1322,15 @@ dependencies = [
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625"
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
"checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b"
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72"
@ -975,17 +1338,23 @@ dependencies = [
"checksum onig_sys 69.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a8d4efbf5f59cece01f539305191485b651acb3785b9d5eef05749f0496514e"
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a"
"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0"
"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547"
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
"checksum plist 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a9f075f6394100e7c105ed1af73fb1859d6fd14e49d4290d578120beb167f"
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
@ -1000,6 +1369,8 @@ dependencies = [
"checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043"
"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92"
@ -1015,18 +1386,26 @@ dependencies = [
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
"checksum unchecked-index 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf"
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9"
"checksum ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"
"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"

@ -28,6 +28,10 @@ serde = { version = "1.0", features = ["derive"] }
toml = "0.5"
lazy_static = "1.4"
chrono = "0.4"
notify = "4.0"
ws = "0.9"
fern = { version = "0.5", features = ["colored"] }
log = { version = "0.4", features = ["max_level_debug", "release_max_level_info", "std", "serde"] }
[build-dependencies]
sass-rs = "0.2"

@ -35,6 +35,7 @@ SUBCOMMANDS:
build build the book
help Prints this message or the help of the given subcommand(s)
init initialize a mkbook directory tree
watch build the book and continually rebuild whenever the source changes
```
### The Init Command
@ -77,3 +78,24 @@ OPTIONS:
-i, --in <in> an optional directory to take the book sources from [default: src]
-o, --out <out> an optional directory to render the contents into [default: book]
```
### The Watch Command
The watch command is basically the same as the `build` command, however after building it continues to monitor the source directory and if _any_ changes are made (a file is saved, renamed, removed, created, etc), the entire book is re-built. In the future, this will hopefully be smarter but for now it just the whole thing at once. Stop watching using <kbd>Ctrl+C</kbd> or sending `SIGINT`.
```sh
$ mkbook build --help
mkbook-watch
build the book and continually rebuild whenever the source changes
USAGE:
mkbook watch [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-i, --in <in> an optional directory to take the book sources from [default: src]
-o, --out <out> an optional directory to render the contents into [default: book]
```

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//01-introduction/index.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -124,6 +124,7 @@
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">build</span><span style="color:#d3d0c8;"> build the book
</span><span style="color:#d3d0c8;"> </span><span style="color:#66cccc;">help</span><span style="color:#d3d0c8;"> Prints this message or the help of the given subcommand(s)
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">init</span><span style="color:#d3d0c8;"> initialize a mkbook directory tree
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">watch</span><span style="color:#d3d0c8;"> build the book and continually rebuild whenever the source changes
</span></pre>
<h3><a href="#the-init-command" aria-hidden="true" class="anchor" id="headerthe-init-command"></a>The Init Command</h3>
<p>The init command is a tool to help you get started, and will create an initial <code>README.md</code> file and a stub of your first chapter.</p>
@ -160,6 +161,24 @@
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">-i,</span><span style="color:#f2777a;"> --in </span><span style="color:#d3d0c8;">&lt;in&gt; an optional directory to take the book sources from </span><span style="color:#cc99cc;">[</span><span style="color:#d3d0c8;">default: src</span><span style="color:#cc99cc;">]
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">-o,</span><span style="color:#f2777a;"> --out </span><span style="color:#d3d0c8;">&lt;out&gt; an optional directory to render the contents into </span><span style="color:#cc99cc;">[</span><span style="color:#d3d0c8;">default: book</span><span style="color:#cc99cc;">]
</span></pre>
<h3><a href="#the-watch-command" aria-hidden="true" class="anchor" id="headerthe-watch-command"></a>The Watch Command</h3>
<p>The watch command is basically the same as the <code>build</code> command, however after building it continues to monitor the source directory and if <em>any</em> changes are made (a file is saved, renamed, removed, created, etc), the entire book is re-built. In the future, this will hopefully be smarter but for now it just the whole thing at once. Stop watching using <kbd>Ctrl+C</kbd> or sending <code>SIGINT</code>.</p>
<pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">$</span><span style="color:#d3d0c8;"> mkbook build</span><span style="color:#f2777a;"> --help
</span><span style="color:#6699cc;">mkbook-watch
</span><span style="color:#6699cc;">build</span><span style="color:#d3d0c8;"> the book and continually rebuild whenever the source changes
</span><span style="color:#d3d0c8;">
</span><span style="color:#6699cc;">USAGE:
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">mkbook</span><span style="color:#d3d0c8;"> watch </span><span style="color:#cc99cc;">[</span><span style="color:#d3d0c8;">OPTIONS</span><span style="color:#cc99cc;">]
</span><span style="color:#d3d0c8;">
</span><span style="color:#6699cc;">FLAGS:
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">-h,</span><span style="color:#f2777a;"> --help</span><span style="color:#d3d0c8;"> Prints help information
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">-V,</span><span style="color:#f2777a;"> --version</span><span style="color:#d3d0c8;"> Prints version information
</span><span style="color:#d3d0c8;">
</span><span style="color:#6699cc;">OPTIONS:
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">-i,</span><span style="color:#f2777a;"> --in </span><span style="color:#d3d0c8;">&lt;in&gt; an optional directory to take the book sources from </span><span style="color:#cc99cc;">[</span><span style="color:#d3d0c8;">default: src</span><span style="color:#cc99cc;">]
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">-o,</span><span style="color:#f2777a;"> --out </span><span style="color:#d3d0c8;">&lt;out&gt; an optional directory to render the contents into </span><span style="color:#cc99cc;">[</span><span style="color:#d3d0c8;">default: book</span><span style="color:#cc99cc;">]
</span></pre>
@ -176,5 +195,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//02-markdown/01-commonmark.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -164,5 +164,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//02-markdown/02-syntax-highlighting.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -625,5 +625,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//02-markdown/03-plantuml-diagrams.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -137,5 +137,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//02-markdown/04-katex-formulas.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css" integrity="sha384-zB1R0rpPzHqg7Kpt0Aljp8JPLqbXI3bhnPWROx27a9N0Ll6ZP/+DiW/UqRcLbRjq" crossorigin="anonymous">
</head>
<body>
@ -145,5 +145,6 @@ M834 80h400000v40h-400000z'/></svg></span></span></span><span class="vlist-s">
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//02-markdown/index.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -132,5 +132,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//03-frontmatter/index.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -162,5 +162,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//04-structure/index.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -199,5 +199,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//05-customization/index.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -123,5 +123,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -12,7 +12,7 @@
<meta property="og:url" content="https://hamaluik.github.io/mkbook//06-how-it-works/index.html" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body>
@ -124,5 +124,6 @@
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</article>
</body>
</html>

@ -14,14 +14,14 @@
&lt;p&gt;This tool aims to work somewhat similarly to &lt;em&gt;mdbook&lt;&#x2f;em&gt;, but is generally intended to be a more minimal alternative that is customized more towards my needs and desires than anything else.&lt;&#x2f;p&gt;
" />
<meta property="book:author" content="Kenton Hamaluik" />
<meta property="book:release_date" content="2019-12-01T18:55:05.215513238+00:00" />
<meta property="book:release_date" content="2019-12-02T20:05:16.402897505+00:00" />
</head>
<body class="toc">
<header>
<h1>The mkbook Book</h1>
<h2>by Kenton Hamaluik</h2>
<time datetime="2019-12-01T18:55:05.215513238+00:00">Dec 1, 2019</time>
<time datetime="2019-12-02T20:05:16.402897505+00:00">Dec 2, 2019</time>
</header>
<article>
<p><em>mkbook</em> is my simpler alternative to <a href="https://crates.io/crates/mdbook">mdbook</a> which is a great tool, but for which I really dislike some of the decisions they took, such as relying on javascript for highlighting and navigation, and including a lot of bells and whistles such as javascript-based search.</p>
@ -77,5 +77,6 @@
</ol>
</nav>
<footer><p>&copy; 2019 Kenton Hamaluik</p></footer>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -29,4 +29,24 @@ pub fn build_cli() -> App<'static, 'static> {
.help("an optional directory to render the contents into")
)
)
.subcommand(SubCommand::with_name("watch")
.about("build the book and continually rebuild whenever the source changes")
.arg(Arg::with_name("in")
.short("i")
.long("in")
.default_value("src")
.help("an optional directory to take the book sources from")
)
.arg(Arg::with_name("out")
.short("o")
.long("out")
.default_value("book")
.help("an optional directory to render the contents into")
)
.arg(Arg::with_name("reload")
.short("r")
.long("reload")
.help("inject live-reload code so that the page automatically reloads on regeneration")
)
)
}

@ -1,7 +1,7 @@
#[macro_use]
extern crate lazy_static;
use std::path::PathBuf;
use std::path::{PathBuf, Path};
use std::{fs, io};
use comrak::ComrakOptions;
use syntect::{parsing::SyntaxSet, highlighting::{ThemeSet, Theme}};
@ -85,7 +85,7 @@ fn create_katex_inline(src: &str) -> Result<String, Box<dyn std::error::Error>>
.spawn() {
Ok(c) => c,
Err(e) => {
eprintln!("[WARNING] failed to launch katex, not rendering math block: {:?}", e);
log::warn!("failed to launch katex, not rendering math block: {:?}", e);
return Ok(format_code("", src)?.output);
}
};
@ -95,12 +95,12 @@ fn create_katex_inline(src: &str) -> Result<String, Box<dyn std::error::Error>>
let output = child.wait_with_output()?;
if !output.status.success() {
eprintln!("failed to generate katex, exit code: {:?}", output.status.code());
eprintln!("katex STDOUT:");
eprintln!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
eprintln!("katex STDERR:");
eprintln!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
eprintln!("/katex output");
log::error!("failed to generate katex, exit code: {:?}", output.status.code());
log::error!("katex STDOUT:");
log::error!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
log::error!("katex STDERR:");
log::error!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
log::error!("/katex output");
return Ok(format_code("", src)?.output);
}
let rendered: String = String::from_utf8(output.stdout)?;
@ -122,7 +122,7 @@ fn create_plantuml_svg(src: &str) -> Result<String, Box<dyn std::error::Error>>
.spawn() {
Ok(c) => c,
Err(e) => {
eprintln!("[WARNING] failed to launch plantuml, not rendering plantuml block: {:?}", e);
log::warn!("failed to launch plantuml, not rendering plantuml block: {:?}", e);
return Ok(format_code("", src)?.output);
}
};
@ -132,12 +132,12 @@ fn create_plantuml_svg(src: &str) -> Result<String, Box<dyn std::error::Error>>
let output = child.wait_with_output()?;
if !output.status.success() {
eprintln!("failed to generate plantuml, exit code: {:?}", output.status.code());
eprintln!("plantuml STDOUT:");
eprintln!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
eprintln!("plantuml STDERR:");
eprintln!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
eprintln!("/plantuml output");
log::error!("failed to generate plantuml, exit code: {:?}", output.status.code());
log::error!("plantuml STDOUT:");
log::error!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
log::error!("plantuml STDERR:");
log::error!("{}", String::from_utf8_lossy(output.stdout.as_ref()));
log::error!("/plantuml output");
return Ok(format_code("", src)?.output);
}
let svg: String = String::from_utf8(output.stdout)?;
@ -278,15 +278,17 @@ struct IndexTemplate<'a, 'b, 'c> {
chapters: &'b Vec<Chapter>,
book_description: &'c str,
include_katex_css: bool,
include_reload_script: bool,
}
fn generate_index<W: io::Write>(book: &FrontMatter, content: String, include_katex_css: bool, chapters: &Vec<Chapter>, mut output: W) -> Result<(), Box<dyn std::error::Error>> {
fn generate_index<W: io::Write>(book: &FrontMatter, content: String, include_katex_css: bool, chapters: &Vec<Chapter>, mut output: W, include_reload_script: bool) -> Result<(), Box<dyn std::error::Error>> {
// fill out our template
let template = IndexTemplate {
book,
chapters,
book_description: &content,
include_katex_css,
include_reload_script,
};
// and render!
@ -306,9 +308,10 @@ struct PageTemplate<'a, 'b, 'c, 'd, 'e, 'g> {
next_chapter: Option<&'e Chapter>,
book: &'g FrontMatter,
include_katex_css: bool,
include_reload_script: bool,
}
fn format_page<W: io::Write>(book: &FrontMatter, chapter: &Chapter, chapters: &Vec<Chapter>, prev_chapter: Option<&Chapter>, next_chapter: Option<&Chapter>, content: &str, include_katex_css: bool, mut output: W) -> Result<(), Box<dyn std::error::Error>> {
fn format_page<W: io::Write>(book: &FrontMatter, chapter: &Chapter, chapters: &Vec<Chapter>, prev_chapter: Option<&Chapter>, next_chapter: Option<&Chapter>, content: &str, include_katex_css: bool, mut output: W, include_reload_script: bool) -> Result<(), Box<dyn std::error::Error>> {
// fill out our template
let template = PageTemplate {
chapter,
@ -318,6 +321,7 @@ fn format_page<W: io::Write>(book: &FrontMatter, chapter: &Chapter, chapters: &V
next_chapter,
book,
include_katex_css,
include_reload_script,
};
// and render!
@ -327,27 +331,278 @@ fn format_page<W: io::Write>(book: &FrontMatter, chapter: &Chapter, chapters: &V
Ok(())
}
fn build<PIn: AsRef<Path>, POut: AsRef<Path>>(src: PIn, dest: POut, include_reload_script: bool) -> Result<(), Box<dyn std::error::Error>> {
let src = PathBuf::from(src.as_ref());
let dest = PathBuf::from(dest.as_ref());
std::fs::create_dir_all(&dest)?;
// load our book
let book_readme_path = src.join("README.md");
let (book_front, book_description) = if book_readme_path.exists() {
let contents = fs::read_to_string(&book_readme_path)?;
let (front, contents) = extract_frontmatter(&contents)?;
(front, contents)
}
else {
let content = String::new();
(None, content)
};
let book_front = FrontMatter::from_root(book_front.unwrap_or_default());
let FormatResponse { output, include_katex_css } = format_markdown(&book_description)?;
let book_description = output;
// load all our chapters
let mut chapters: Vec<Chapter> = Vec::default();
for entry in src.read_dir()? {
let entry = entry?;
let path = entry.path();
if entry.file_type()?.is_dir() {
// try to find a `README.md` file and parse it to get the chapter's title, fall back to the directory
// name if we can't do that
let chapter_name = path.file_name().map(std::ffi::OsStr::to_str).flatten().unwrap_or_default();
let index_path = path.join("README.md");
let (front, contents) = if index_path.exists() {
let contents = fs::read_to_string(&index_path)?;
let (front, contents) = extract_frontmatter(&contents)?;
let front = front.unwrap_or_default().into_front(&book_front, chapter_name, &format!("{}/index.html", chapter_name));
(front, contents)
}
else {
(ParsedFrontMatter::default().into_front(&book_front, chapter_name, &format!("{}/index.html", chapter_name)), String::new())
};
let mut chapter: Chapter = Chapter {
front,
sections: Vec::default(),
source: path.clone(),
contents,
};
for entry in path.read_dir()? {
let entry = entry?;
let path = entry.path();
if let Some("md") = path.extension().map(std::ffi::OsStr::to_str).flatten() {
let name = path.file_stem().map(std::ffi::OsStr::to_str).flatten();
if name.is_none() { continue; }
let name = name.unwrap();
if name == "README" {
continue;
}
let contents = fs::read_to_string(&path)?;
let (front, contents) = extract_frontmatter(&contents)?;
let front = front.unwrap_or_default().into_front(&book_front, name, &format!("{}/{}.html", chapter_name, name));
chapter.sections.push(Chapter {
front,
sections: Vec::new(),
source: path,
contents,
});
}
}
chapters.push(chapter);
}
else if let Some("md") = path.extension().map(std::ffi::OsStr::to_str).flatten() {
let name = path.file_stem().map(std::ffi::OsStr::to_str).flatten();
if name.is_none() { continue; }
let name = name.unwrap();
if name == "README" {
continue;
}
let contents = fs::read_to_string(&path)?;
let (front, contents) = extract_frontmatter(&contents)?;
let front = front.unwrap_or_default().into_front(&book_front, name, &format!("{}/index.html", name));
chapters.push(Chapter {
front,
sections: Vec::new(),
source: path,
contents,
});
}
}
// sort all the chapters
chapters.sort_by(|a, b| a.front.url.cmp(&b.front.url));
for chapter in chapters.iter_mut() {
chapter.sections.sort_by(|a, b| a.front.url.cmp(&b.front.url));
}
// generate our index
let index_out_path = dest.join("index.html");
let index_out = fs::File::create(&index_out_path)?;
let index_out = io::BufWriter::new(index_out);
generate_index(&book_front, book_description, include_katex_css, &chapters, index_out, include_reload_script)?;
log::info!("Rendered index into `{}`", index_out_path.display());
// compile markdown and write the actual pages
let mut prev_chapter = None;
for (chapter_index, chapter) in chapters.iter().enumerate() {
// render the index
let chapter_root = dest.join(chapter.source.file_stem().map(std::ffi::OsStr::to_str).flatten().unwrap());
let out = chapter_root.join("index.html");
log::info!("Rendering `{}` into `{}`...", chapter.source.display(), out.display());
fs::create_dir_all(&chapter_root)?;
let outfile = fs::File::create(&out)?;
let outfile = io::BufWriter::new(outfile);
let FormatResponse { output, include_katex_css } = format_markdown(&chapter.contents)?;
let next_chapter =
if chapter.sections.len() > 0 {
Some(chapter.sections.iter().nth(0).expect("section 0 exists"))
}
else if chapter_index < chapters.len() - 1 {
Some(chapters.iter().nth(chapter_index + 1).expect("chapter n+1 exists"))
}
else {
None
};
format_page(&book_front, &chapter, &chapters, prev_chapter, next_chapter, &output, include_katex_css, outfile, include_reload_script)?;
prev_chapter = Some(chapter);
// now the sections
for (section_index, section) in chapter.sections.iter().enumerate() {
let name = section.source.file_stem().map(std::ffi::OsStr::to_str).flatten().unwrap();
let out = chapter_root.join(&format!("{}.html", name));
log::info!("Rendering `{}` into `{}`...", section.source.display(), out.display());
let outfile = fs::File::create(&out)?;
let outfile = io::BufWriter::new(outfile);
let FormatResponse { output, include_katex_css } = format_markdown(&section.contents)?;
let next_chapter = if section_index < chapter.sections.len() - 1 {
Some(chapter.sections.iter().nth(section_index + 1).expect("chapter n+1 exists"))
}
else if chapter_index < chapters.len() - 1 {
Some(chapters.iter().nth(chapter_index + 1).expect("chapter n+1 exists"))
}
else {
None
};
format_page(&book_front, &section, &chapters, prev_chapter, next_chapter, &output, include_katex_css, outfile, include_reload_script)?;
prev_chapter = Some(section);
}
}
// save the assets
fs::write(dest.join("style.css"), STYLESHEET)?;
log::info!("Wrote {}", dest.join("style.css").display());
fs::write(dest.join("favicon.ico"), ASSET_FAVICON)?;
log::info!("Wrote {}", dest.join("favicon.ico").display());
fs::write(dest.join("icons.svg"), ASSET_ICONS)?;
log::info!("Wrote {}", dest.join("icons.svg").display());
log::info!("Done!");
Ok(())
}
struct ReloadClient {
sender: std::sync::Arc<ws::Sender>,
reload: std::sync::Arc<std::sync::atomic::AtomicBool>,
quitloop: std::sync::Arc<std::sync::atomic::AtomicBool>,
}
impl ReloadClient {
pub fn new(sender: ws::Sender, reload: std::sync::Arc<std::sync::atomic::AtomicBool>) -> ReloadClient {
ReloadClient {
sender: std::sync::Arc::new(sender),
reload,
quitloop: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)),
}
}
}
impl ws::Handler for ReloadClient {
fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
log::info!("reload client connected");
let out = self.sender.clone();
let reload = self.reload.clone();
let quitloop = self.quitloop.clone();
std::thread::spawn(move || {
'sendloop: loop {
let send_reload = reload.load(std::sync::atomic::Ordering::SeqCst);
if send_reload {
log::debug!("sending reload signal...");
out.send("reload").expect("can send reload signal");
log::debug!(" ok!");
}
let quit = quitloop.load(std::sync::atomic::Ordering::SeqCst);
if quit {
break 'sendloop;
}
// check at 10 Hz
std::thread::sleep(std::time::Duration::from_millis(100));
}
log::warn!("shutting down reload connection");
if let Err(e) = out.shutdown() {
log::error!("failed to shut down reload connection: {:?}", e);
}
});
Ok(())
}
fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
log::debug!("reload connection closed: {:?}: {}", code, reason);
//self.quitloop.store(true, std::sync::atomic::Ordering::SeqCst);
}
fn on_shutdown(&mut self) {
log::debug!("reload connection shutdown");
self.quitloop.store(true, std::sync::atomic::Ordering::SeqCst);
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let matches = cli::build_cli().get_matches();
use fern::colors::{Color, ColoredLevelConfig};
let colors_level = ColoredLevelConfig::new()
.error(Color::Red)
.warn(Color::Yellow)
.info(Color::Cyan)
.debug(Color::Magenta)
.trace(Color::BrightBlack);
fern::Dispatch::new()
.format(move |out, message, record| {
out.finish(format_args!(
"[{date}][\x1B[96m{target}\x1B[0m][{level}\x1B[0m] {message}",
date = chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
target = record.target(),
level = colors_level.color(record.level()),
message = message,
));
})
.level_for("ws", log::LevelFilter::Info)
.chain(std::io::stdout())
.apply()?;
if let Some(submatches) = matches.subcommand_matches("init") {
let dest = submatches.value_of("directory").expect("directory value");
let dest = PathBuf::from(dest);
println!("Initializing a book into {}...", dest.display());
log::info!("Initializing a book into {}...", dest.display());
fs::create_dir_all(&dest)?;
let book_readme_path = dest.join("README.md");
fs::write(&book_readme_path, ASSET_DEFAULT_README)?;
let intro_path = dest.join("01-introduction.md");
fs::write(&intro_path, ASSET_DEFAULT_INTRODUCTION)?;
println!("Done!");
log::info!("Done!");
println!("You can now build your book by running:");
log::info!("You can now build your book by running:");
if dest.display().to_string() != "src" {
println!("mkbook build -i {}", dest.display());
log::info!("mkbook build -i {}", dest.display());
}
else {
println!("mkbook build");
log::info!("mkbook build");
}
Ok(())
@ -355,179 +610,45 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
else if let Some(submatches) = matches.subcommand_matches("build") {
let src = submatches.value_of("in").expect("in value");
let dest = submatches.value_of("out").expect("out value");
let src = PathBuf::from(src);
let dest = PathBuf::from(dest);
std::fs::create_dir_all(&dest)?;
// load our book
let book_readme_path = src.join("README.md");
let (book_front, book_description) = if book_readme_path.exists() {
let contents = fs::read_to_string(&book_readme_path)?;
let (front, contents) = extract_frontmatter(&contents)?;
(front, contents)
}
else {
let content = String::new();
(None, content)
};
let book_front = FrontMatter::from_root(book_front.unwrap_or_default());
let FormatResponse { output, include_katex_css } = format_markdown(&book_description)?;
let book_description = output;
// load all our chapters
let mut chapters: Vec<Chapter> = Vec::default();
for entry in src.read_dir()? {
let entry = entry?;
let path = entry.path();
if entry.file_type()?.is_dir() {
// try to find a `README.md` file and parse it to get the chapter's title, fall back to the directory
// name if we can't do that
let chapter_name = path.file_name().map(std::ffi::OsStr::to_str).flatten().unwrap_or_default();
let index_path = path.join("README.md");
let (front, contents) = if index_path.exists() {
let contents = fs::read_to_string(&index_path)?;
let (front, contents) = extract_frontmatter(&contents)?;
let front = front.unwrap_or_default().into_front(&book_front, chapter_name, &format!("{}/index.html", chapter_name));
(front, contents)
}
else {
(ParsedFrontMatter::default().into_front(&book_front, chapter_name, &format!("{}/index.html", chapter_name)), String::new())
};
let mut chapter: Chapter = Chapter {
front,
sections: Vec::default(),
source: path.clone(),
contents,
};
for entry in path.read_dir()? {
let entry = entry?;
let path = entry.path();
if let Some("md") = path.extension().map(std::ffi::OsStr::to_str).flatten() {
let name = path.file_stem().map(std::ffi::OsStr::to_str).flatten();
if name.is_none() { continue; }
let name = name.unwrap();
if name == "README" {
continue;
}
build(src, dest, false)
}
else if let Some(submatches) = matches.subcommand_matches("watch") {
let reload_trigger = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
let do_reload = submatches.is_present("reload");
let contents = fs::read_to_string(&path)?;
let (front, contents) = extract_frontmatter(&contents)?;
let front = front.unwrap_or_default().into_front(&book_front, name, &format!("{}/{}.html", chapter_name, name));
chapter.sections.push(Chapter {
front,
sections: Vec::new(),
source: path,
contents,
});
}
}
chapters.push(chapter);
}
else if let Some("md") = path.extension().map(std::ffi::OsStr::to_str).flatten() {
let name = path.file_stem().map(std::ffi::OsStr::to_str).flatten();
if name.is_none() { continue; }
let name = name.unwrap();
if name == "README" {
continue;
}
let contents = fs::read_to_string(&path)?;
let (front, contents) = extract_frontmatter(&contents)?;
let front = front.unwrap_or_default().into_front(&book_front, name, &format!("{}/index.html", name));
chapters.push(Chapter {
front,
sections: Vec::new(),
source: path,
contents,
});
}
}
// sort all the chapters
chapters.sort_by(|a, b| a.front.url.cmp(&b.front.url));
for chapter in chapters.iter_mut() {
chapter.sections.sort_by(|a, b| a.front.url.cmp(&b.front.url));
if do_reload {
let reload_trigger = reload_trigger.clone();
std::thread::spawn(move || {
log::info!("starting livereload service");
ws::listen("127.0.0.1:3456", |out| ReloadClient::new(out, reload_trigger.clone())).expect("can launch livereload service");
});
}
// generate our index
let index_out_path = dest.join("index.html");
let index_out = fs::File::create(&index_out_path)?;
let index_out = io::BufWriter::new(index_out);
generate_index(&book_front, book_description, include_katex_css, &chapters, index_out)?;
println!("Rendered index into `{}`", index_out_path.display());
// compile markdown and write the actual pages
let mut prev_chapter = None;
for (chapter_index, chapter) in chapters.iter().enumerate() {
// render the index
let chapter_root = dest.join(chapter.source.file_stem().map(std::ffi::OsStr::to_str).flatten().unwrap());
let out = chapter_root.join("index.html");
print!("Rendering `{}` into `{}`...", chapter.source.display(), out.display());
fs::create_dir_all(&chapter_root)?;
let outfile = fs::File::create(&out)?;
let outfile = io::BufWriter::new(outfile);
let FormatResponse { output, include_katex_css } = format_markdown(&chapter.contents)?;
let next_chapter =
if chapter.sections.len() > 0 {
Some(chapter.sections.iter().nth(0).expect("section 0 exists"))
}
else if chapter_index < chapters.len() - 1 {
Some(chapters.iter().nth(chapter_index + 1).expect("chapter n+1 exists"))
}
else {
None
};
format_page(&book_front, &chapter, &chapters, prev_chapter, next_chapter, &output, include_katex_css, outfile)?;
prev_chapter = Some(chapter);
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
println!(" done!");
// now the sections
for (section_index, section) in chapter.sections.iter().enumerate() {
let name = section.source.file_stem().map(std::ffi::OsStr::to_str).flatten().unwrap();
let out = chapter_root.join(&format!("{}.html", name));
print!("Rendering `{}` into `{}`...", section.source.display(), out.display());
let outfile = fs::File::create(&out)?;
let outfile = io::BufWriter::new(outfile);
let FormatResponse { output, include_katex_css } = format_markdown(&section.contents)?;
let next_chapter = if section_index < chapter.sections.len() - 1 {
Some(chapter.sections.iter().nth(section_index + 1).expect("chapter n+1 exists"))
}
else if chapter_index < chapters.len() - 1 {
Some(chapters.iter().nth(chapter_index + 1).expect("chapter n+1 exists"))
let src = submatches.value_of("in").expect("in value");
let dest = submatches.value_of("out").expect("out value");
build(src, dest, do_reload)?;
let (tx, rx) = std::sync::mpsc::channel();
let mut watcher: RecommendedWatcher = Watcher::new(tx, std::time::Duration::from_secs(1))?;
watcher.watch(src, RecursiveMode::Recursive)?;
loop {
match rx.recv() {
Ok(notify::DebouncedEvent::NoticeWrite(_)) | Ok(notify::DebouncedEvent::NoticeRemove(_)) => {},
Ok(_) => {
build(src, dest, do_reload)?;
reload_trigger.store(true, std::sync::atomic::Ordering::SeqCst);
std::thread::sleep(std::time::Duration::from_millis(150));
reload_trigger.store(false, std::sync::atomic::Ordering::SeqCst);
},
Err(e) => {
log::error!("watch error: {:?}", e);
return Err(Box::from(e));
}
else {
None
};
format_page(&book_front, &section, &chapters, prev_chapter, next_chapter, &output, include_katex_css, outfile)?;
prev_chapter = Some(section);
println!(" done!");
}
}
// save the assets
fs::write(dest.join("style.css"), STYLESHEET)?;
println!("Wrote {}", dest.join("style.css").display());
fs::write(dest.join("favicon.ico"), ASSET_FAVICON)?;
println!("Wrote {}", dest.join("favicon.ico").display());
fs::write(dest.join("icons.svg"), ASSET_ICONS)?;
println!("Wrote {}", dest.join("icons.svg").display());
println!("Done!");
Ok(())
}
else {
cli::build_cli().print_long_help()?;

@ -50,6 +50,7 @@ body {
font-family: $font-sansserif;
margin-bottom: 0;
text-align: right;
color: #eeeeee;
}
}

@ -3,5 +3,5 @@
@import 'layout';
@import 'toc';
@import 'icons';
@import 'darktheme';
//@import 'darktheme';
@import 'print';

@ -42,5 +42,8 @@
</ol>
</nav>
<footer><p>&copy; {{ book.pubdate|year }} {{ book.author }}</p></footer>
{% if include_reload_script %}
{% include "reload.html" %}
{% endif %}
</body>
</html>

@ -99,5 +99,8 @@
{% endmatch %}
<footer><p>&copy; {{ book.pubdate|year }} {{ book.author }}</p></footer>
</article>
{% if include_reload_script %}
{% include "reload.html" %}
{% endif %}
</body>
</html>

@ -0,0 +1,17 @@
<script>
console.info("connecting to reload server...");
var reloadSocket = new WebSocket("ws://127.0.0.1:3456");
reloadSocket.onopen = function(event) {
console.info("connected to reload server");
};
reloadSocket.onclose = function(event) {
console.info("reload server hung up!");
};
reloadSocket.onerror = function(event) {
console.error("reload server connection error:", event);
};
reloadSocket.onmessage = function(event) {
console.info("recieved reload command");
window.location.reload();
};
</script>
Loading…
Cancel
Save