diff --git a/Cargo.lock b/Cargo.lock index 6f698e2..8561de3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,15 +13,14 @@ dependencies = [ [[package]] name = "ammonia" -version = "3.1.2" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e445c26125ff80316eaea16e812d717b147b82a68682bd4730f74d4845c8b35" +checksum = "ea9f21d23d82bae9d33c21080572af1fa749788e68234b5d8fa5e39d3e0783ed" dependencies = [ "html5ever", "lazy_static", "maplit", "markup5ever_rcdom", - "matches", "tendril", "url", ] @@ -37,9 +36,31 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.52" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" + +[[package]] +name = "async-recursion" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "atty" @@ -54,9 +75,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -91,6 +112,15 @@ dependencies = [ "generic-array 0.14.5", ] +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array 0.14.5", +] + [[package]] name = "block-padding" version = "0.1.5" @@ -171,9 +201,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7" +checksum = "5177fac1ab67102d8989464efd043c6ff44191b1557ec1ddd489b4f7e1447e77" dependencies = [ "atty", "bitflags", @@ -193,6 +223,16 @@ dependencies = [ "libc", ] +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array 0.14.5", + "typenum", +] + [[package]] name = "digest" version = "0.8.1" @@ -211,6 +251,16 @@ dependencies = [ "generic-array 0.14.5", ] +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", +] + [[package]] name = "elasticlunr-rs" version = "2.3.14" @@ -245,6 +295,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "filetime" version = "0.2.15" @@ -310,19 +369,34 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" dependencies = [ "mac", "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -330,15 +404,32 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-macro" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", @@ -347,26 +438,29 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -413,9 +507,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ "cfg-if 1.0.0", "libc", @@ -439,9 +533,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" dependencies = [ "bytes", "fnv", @@ -458,9 +552,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.2.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2483bce82dd3ed52509d0117e4a30a488bd608be250ed7a0185301314239ed31" +checksum = "25546a65e5cf1f471f3438796fc634650b31d7fcde01d444c309aeb28b92e3a8" dependencies = [ "log", "pest", @@ -478,9 +572,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "headers" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4eb0471fcb85846d8b0690695ef354f9afb11cb03cac2e1d7c9253351afb0" +checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" dependencies = [ "base64", "bitflags", @@ -489,7 +583,7 @@ dependencies = [ "http", "httpdate", "mime", - "sha-1 0.9.8", + "sha-1 0.10.0", ] [[package]] @@ -541,7 +635,7 @@ checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] @@ -557,9 +651,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" @@ -578,9 +672,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" dependencies = [ "bytes", "futures-channel", @@ -591,7 +685,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -613,9 +707,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", "hashbrown", @@ -659,12 +753,6 @@ dependencies = [ "libc", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.1" @@ -695,15 +783,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -798,13 +886,17 @@ dependencies = [ name = "mdbook-graphviz" version = "0.1.4" dependencies = [ - "clap 3.1.1", + "async-recursion", + "async-trait", + "clap 3.1.2", + "futures", "lazy_static", "mdbook", "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", "serde_json", + "tokio", "toml", ] @@ -822,9 +914,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -851,9 +943,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" dependencies = [ "libc", "log", @@ -932,9 +1024,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi 0.3.9", ] @@ -968,6 +1060,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -1079,7 +1177,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_shared", + "phf_shared 0.8.0", ] [[package]] @@ -1089,7 +1187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ "phf_generator", - "phf_shared", + "phf_shared 0.8.0", ] [[package]] @@ -1098,7 +1196,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ - "phf_shared", + "phf_shared 0.8.0", "rand 0.7.3", ] @@ -1111,6 +1209,15 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.0.10" @@ -1166,9 +1273,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd16514d1af5f7a71f909a44ef253cdb712a376d7ebc8ae4a471a9be9743548" +checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" dependencies = [ "bitflags", "getopts", @@ -1199,9 +1306,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] @@ -1216,20 +1323,19 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", "rand_pcg", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -1267,7 +1373,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", ] [[package]] @@ -1279,15 +1385,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_pcg" version = "0.2.1" @@ -1367,15 +1464,15 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.133" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" [[package]] name = "serde_derive" -version = "1.0.133" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -1384,23 +1481,23 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.74" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -1430,17 +1527,37 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "shlex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "siphasher" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" [[package]] name = "slab" @@ -1450,15 +1567,15 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi 0.3.9", @@ -1466,14 +1583,14 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923f0f39b6267d37d23ce71ae7235602134b250ace715dd2c90421998ddac0c6" +checksum = "33994d0838dc2d152d17a62adf608a869b5e846b65b389af7f3dbc1de45c5b26" dependencies = [ "lazy_static", "new_debug_unreachable", "parking_lot", - "phf_shared", + "phf_shared 0.10.0", "precomputed-hash", "serde", ] @@ -1485,7 +1602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97" dependencies = [ "phf_generator", - "phf_shared", + "phf_shared 0.8.0", "proc-macro2", "quote", ] @@ -1522,9 +1639,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.84" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -1533,13 +1650,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.8.4", "redox_syscall", "remove_dir_all", "winapi 0.3.9", @@ -1627,16 +1744,19 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ "bytes", "libc", "memchr", - "mio 0.7.14", + "mio 0.8.0", "num_cpus", + "once_cell", "pin-project-lite", + "signal-hook-registry", + "socket2", "tokio-macros", "winapi 0.3.9", ] @@ -1713,9 +1833,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" dependencies = [ "cfg-if 1.0.0", "log", @@ -1725,9 +1845,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" dependencies = [ "lazy_static", ] @@ -1750,7 +1870,7 @@ dependencies = [ "http", "httparse", "log", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.8", "thiserror", "url", @@ -1795,9 +1915,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" diff --git a/Cargo.toml b/Cargo.toml index a76c76e..ef6db8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,11 @@ pulldown-cmark-to-cmark = "10.0" lazy_static = "1.4.0" regex = "1.5" toml = "0.5" + +tokio = { version = "1.17", features = ["process"] } +futures = "0.3" +async-trait = "0.1" +async-recursion = "1.0" + +[dev-dependencies] +tokio = { version = "1.17", features = ["process", "time"] } \ No newline at end of file diff --git a/src/preprocessor.rs b/src/preprocessor.rs index 3e94235..9568939 100644 --- a/src/preprocessor.rs +++ b/src/preprocessor.rs @@ -1,6 +1,9 @@ +use core::mem; use std::marker::PhantomData; use std::path::PathBuf; +use async_recursion::async_recursion; +use futures::future; use mdbook::book::{Book, Chapter}; use mdbook::errors::Result; use mdbook::preprocess::{Preprocessor, PreprocessorContext}; @@ -18,6 +21,7 @@ pub static INFO_STRING_PREFIX: &str = "dot process"; pub struct GraphvizPreprocessor; pub struct Graphviz { + src_dir: PathBuf, _phantom: PhantomData<*const R>, } @@ -35,31 +39,25 @@ impl Preprocessor for GraphvizPreprocessor { .unwrap_or(false); let src_dir = ctx.root.clone().join(&ctx.config.book.src); - let mut error = Ok(()); - - book.for_each_mut(|item: &mut BookItem| { - // only continue editing the book if we don't have any errors - if error.is_ok() { - if let BookItem::Chapter(ref mut chapter) = item { - let path = match chapter.path.as_ref() { - Some(path) => path, - None => return, - }; - let mut full_path = src_dir.join(path); - - // remove the chapter filename - full_path.pop(); - - error = if !output_to_file { - Graphviz::::new().process_chapter(chapter, full_path) - } else { - Graphviz::::new().process_chapter(chapter, full_path) - }; + + // we really only need 1 thread since we're just calling out to the Graphviz CLI + tokio::runtime::Builder::new_current_thread() + .enable_io() + .build() + .unwrap() + .block_on(async { + if !output_to_file { + Graphviz::::new(src_dir) + .process_sub_items(&mut book.sections) + .await + } else { + Graphviz::::new(src_dir) + .process_sub_items(&mut book.sections) + .await } - } - }); + })?; - error.map(|_| book) + Ok(book) } fn supports_renderer(&self, _renderer: &str) -> bool { @@ -69,73 +67,110 @@ impl Preprocessor for GraphvizPreprocessor { } impl Graphviz { - fn new() -> Graphviz { - Graphviz { + pub fn new(src_dir: PathBuf) -> Graphviz { + Self { + src_dir, _phantom: PhantomData, } } - fn process_chapter(&self, chapter: &mut Chapter, chapter_path: PathBuf) -> Result<()> { + #[async_recursion(?Send)] + async fn process_sub_items(&'async_recursion self, items: &mut Vec) -> Result<()> { + let mut item_futures = Vec::with_capacity(items.len()); + for item in mem::take(items) { + item_futures.push(async { + match item { + BookItem::Chapter(chapter) if chapter.path.is_some() => { + self.process_chapter(chapter).await.map(BookItem::Chapter) + } + item => { + // pass through all non-chapters + Ok(item) + } + } + }); + } + + *items = future::join_all(item_futures) + .await + .into_iter() + .collect::, _>>()?; + + Ok(()) + } + + #[async_recursion(?Send)] + async fn process_chapter(&self, mut chapter: Chapter) -> Result { + // make sure to process our chapter sub-items + self.process_sub_items(&mut chapter.sub_items).await?; + + // assume we've already filtered out all the draft chapters + let mut chapter_path = self.src_dir.join(chapter.path.as_ref().unwrap()); + // remove the chapter filename + chapter_path.pop(); + let mut buf = String::with_capacity(chapter.content.len()); let mut graphviz_block_builder: Option = None; let mut image_index = 0; - let event_results: Result>> = new_cmark_parser(&chapter.content, false) - .map(|e| { - if let Some(mut builder) = graphviz_block_builder.take() { - match e { - Event::Text(ref text) => { - builder.append_code(&**text); - graphviz_block_builder = Some(builder); - - Ok(vec![]) - } - Event::End(Tag::CodeBlock(CodeBlockKind::Fenced(ref info_string))) => { - assert_eq!( - Some(0), - (&**info_string).find(INFO_STRING_PREFIX), - "We must close our graphviz block" - ); - - // finish our digraph - let block = builder.build(image_index); - image_index += 1; - - R::render_graphviz(block) - } - _ => { - graphviz_block_builder = Some(builder); - - Ok(vec![]) - } + let events = new_cmark_parser(&chapter.content, false); + let mut event_futures = Vec::new(); + + for e in events { + if let Some(mut builder) = graphviz_block_builder.take() { + match e { + Event::Text(ref text) => { + builder.append_code(&**text); + graphviz_block_builder = Some(builder); } - } else { - match e { - Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info_string))) - if (&**info_string).find(INFO_STRING_PREFIX) == Some(0) => - { - graphviz_block_builder = Some(GraphvizBlockBuilder::new( - &**info_string, - &chapter.name.clone(), - chapter_path.clone(), - )); - - Ok(vec![]) - } - _ => Ok(vec![e]), + Event::End(Tag::CodeBlock(CodeBlockKind::Fenced(ref info_string))) => { + assert_eq!( + Some(0), + (&**info_string).find(INFO_STRING_PREFIX), + "We must close our graphviz block" + ); + + // finish our digraph + let block = builder.build(image_index); + image_index += 1; + + event_futures.push(R::render_graphviz(block)); + } + _ => { + graphviz_block_builder = Some(builder); } } - }) - .collect(); + } else { + match e { + Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info_string))) + if (&**info_string).find(INFO_STRING_PREFIX) == Some(0) => + { + graphviz_block_builder = Some(GraphvizBlockBuilder::new( + &**info_string, + &chapter.name.clone(), + chapter_path.clone(), + )); + } + _ => { + // pass through all events that don't impact our Graphviz block + event_futures.push(Box::pin(async { Ok(vec![e]) })); + } + } + } + } - // get our result and combine our internal Vecs - let events = event_results?.into_iter().flatten(); + let events = future::join_all(event_futures) + .await + .into_iter() + .collect::, _>>()? + .into_iter() + .flatten(); cmark(events, &mut buf)?; chapter.content = buf; - Ok(()) + Ok(chapter) } } @@ -194,6 +229,7 @@ impl GraphvizBlockBuilder { } } +#[derive(Debug)] pub struct GraphvizBlock { pub graph_name: String, pub code: String, @@ -244,15 +280,20 @@ fn normalize_id(content: &str) -> String { #[cfg(test)] mod test { + use async_trait::async_trait; + use super::*; + use std::time::{Duration, Instant}; + static CHAPTER_NAME: &str = "Test Chapter"; static NORMALIZED_CHAPTER_NAME: &str = "test_chapter"; struct NoopRenderer; + #[async_trait] impl GraphvizRenderer for NoopRenderer { - fn render_graphviz<'a>(block: GraphvizBlock) -> Result>> { + async fn render_graphviz<'a>(block: GraphvizBlock) -> Result>> { let file_name = block.file_name(); let output_path = block.output_path(); let GraphvizBlock { @@ -265,8 +306,8 @@ mod test { } } - #[test] - fn only_preprocess_flagged_blocks() { + #[tokio::test] + async fn only_preprocess_flagged_blocks() { let expected = r#"# Chapter ````dot @@ -274,67 +315,62 @@ digraph Test { a -> b } ````"#; - - let mut chapter = new_chapter(expected.into()); - - process_chapter(&mut chapter).unwrap(); + let chapter = process_chapter(new_chapter(expected)).await.unwrap(); assert_eq!(chapter.content, expected); } - #[test] - fn no_name() { - let mut chapter = new_chapter( + #[tokio::test] + async fn no_name() { + let chapter = new_chapter( r#"# Chapter ```dot process digraph Test { a -> b } ``` -"# - .into(), +"#, ); let expected = format!( r#"# Chapter -{}_0.generated.svg|"./{}_0.generated.svg"||0"#, +{}_0.generated.svg|"/./book/{}_0.generated.svg"||0"#, NORMALIZED_CHAPTER_NAME, NORMALIZED_CHAPTER_NAME ); - process_chapter(&mut chapter).unwrap(); + let chapter = process_chapter(chapter).await.unwrap(); assert_eq!(chapter.content, expected); } - #[test] - fn named_blocks() { - let mut chapter = new_chapter( + #[tokio::test] + async fn named_blocks() { + let chapter = new_chapter( r#"# Chapter ```dot process Graph Name digraph Test { a -> b } ``` -"# - .into(), +"#, ); let expected = format!( r#"# Chapter -{}_graph_name_0.generated.svg|"./{}_graph_name_0.generated.svg"|Graph Name|0"#, +{}_graph_name_0.generated.svg|"/./book/{}_graph_name_0.generated.svg"|Graph Name|0"#, NORMALIZED_CHAPTER_NAME, NORMALIZED_CHAPTER_NAME ); - process_chapter(&mut chapter).unwrap(); + let chapter = process_chapter(chapter).await.unwrap(); assert_eq!(chapter.content, expected); } - #[test] - fn preserve_escaping() { - let mut chapter = new_chapter( + #[tokio::test] + async fn preserve_escaping() { + let chapter = new_chapter( r#"# Chapter *asteriks* @@ -346,8 +382,7 @@ digraph Test { a -> b } ``` -"# - .into(), +"#, ); let expected = format!( @@ -357,18 +392,18 @@ digraph Test { /*asteriks/* ( \int x dx = \frac{{x^2}}{{2}} + C) -{}_graph_name_0.generated.svg|"./{}_graph_name_0.generated.svg"|Graph Name|0"#, +{}_graph_name_0.generated.svg|"/./book/{}_graph_name_0.generated.svg"|Graph Name|0"#, NORMALIZED_CHAPTER_NAME, NORMALIZED_CHAPTER_NAME ); - process_chapter(&mut chapter).unwrap(); + let chapter = process_chapter(chapter).await.unwrap(); assert_eq!(chapter.content, expected); } - #[test] - fn preserve_tables() { - let mut chapter = new_chapter( + #[tokio::test] + async fn preserve_tables() { + let chapter = new_chapter( r#"# Chapter |Tables|Are|Cool| @@ -382,8 +417,7 @@ digraph Test { a -> b } ``` -"# - .into(), +"#, ); let expected = format!( @@ -395,22 +429,144 @@ digraph Test { |col 2 is|centered|$12| |col 3 is|right-aligned|$1| -{}_graph_name_0.generated.svg|"./{}_graph_name_0.generated.svg"|Graph Name|0"#, +{}_graph_name_0.generated.svg|"/./book/{}_graph_name_0.generated.svg"|Graph Name|0"#, + NORMALIZED_CHAPTER_NAME, NORMALIZED_CHAPTER_NAME + ); + + let chapter = process_chapter(chapter).await.unwrap(); + + assert_eq!(chapter.content, expected); + } + + const SLEEP_DURATION: Duration = Duration::from_millis(100); + struct SleepyRenderer; + #[async_trait] + impl GraphvizRenderer for SleepyRenderer { + async fn render_graphviz<'a>(_block: GraphvizBlock) -> Result>> { + tokio::time::sleep(SLEEP_DURATION).await; + Ok(vec![Event::Text("".into())]) + } + } + + /// Test that we are actually running Graphviz concurrently + #[tokio::test] + async fn concurrent_execution() { + const TOTAL_CHAPTERS: usize = 10; + let mut chapters = Vec::with_capacity(TOTAL_CHAPTERS); + for _ in 0..TOTAL_CHAPTERS { + chapters.push(BookItem::Chapter(new_chapter( + r#"# Chapter +```dot process Graph Name +digraph Test { + a -> b +} +``` +"#, + ))); + } + + let start = Instant::now(); + Graphviz::::new(PathBuf::from("/")) + .process_sub_items(&mut chapters) + .await + .unwrap(); + let duration = start.elapsed(); + + for item in chapters { + if let BookItem::Chapter(chapter) = item { + // make sure we used the correct renderer + assert_eq!(chapter.content, "# Chapter\n\n"); + } else { + panic!("We should only have chapters here"); + } + } + + assert!( + duration < SLEEP_DURATION * 2, + "{:?} should be less than 2 * {:?} since we expect some variation when running", + duration, + SLEEP_DURATION + ); + } + + /// Test that we correctly process Chapter sub-items + #[tokio::test] + async fn chapter_sub_items() { + let content = r#"# Chapter + +```dot process Graph Name +digraph Test { + a -> b +} +``` +"#; + let mut chapter = new_chapter(content); + chapter + .sub_items + .push(BookItem::Chapter(new_chapter(content))); + + let expected = format!( + r#"# Chapter + +{}_graph_name_0.generated.svg|"/./book/{}_graph_name_0.generated.svg"|Graph Name|0"#, NORMALIZED_CHAPTER_NAME, NORMALIZED_CHAPTER_NAME ); - process_chapter(&mut chapter).unwrap(); + let mut chapter = process_chapter(chapter).await.unwrap(); assert_eq!(chapter.content, expected); + if let BookItem::Chapter(child_chapter) = chapter.sub_items.remove(0) { + assert_eq!(child_chapter.content, expected); + } } - fn process_chapter(chapter: &mut Chapter) -> Result<()> { - let graphviz = Graphviz::::new(); + #[tokio::test] + async fn skip_draft_chapters() { + let draft_chapter = Chapter::new_draft(CHAPTER_NAME, vec![]); + let mut book_items = vec![ + BookItem::Chapter(draft_chapter.clone()), + BookItem::Chapter(new_chapter( + r#"# Chapter +```dot process Graph Name +digraph Test { + a -> b +} +``` +"#, + )), + ]; + + Graphviz::::new(PathBuf::from("/")) + .process_sub_items(&mut book_items) + .await + .unwrap(); + + assert_eq!( + book_items, + vec![ + BookItem::Chapter(draft_chapter), + BookItem::Chapter(new_chapter(format!( + r#"# Chapter + +{}_graph_name_0.generated.svg|"/./book/{}_graph_name_0.generated.svg"|Graph Name|0"#, + NORMALIZED_CHAPTER_NAME, NORMALIZED_CHAPTER_NAME + ))) + ] + ) + } - graphviz.process_chapter(chapter, PathBuf::from("./")) + async fn process_chapter(chapter: Chapter) -> Result { + Graphviz::::new(PathBuf::from("/")) + .process_chapter(chapter) + .await } - fn new_chapter(content: String) -> Chapter { - Chapter::new(CHAPTER_NAME, content.into(), PathBuf::from("./"), vec![]) + fn new_chapter(content: S) -> Chapter { + Chapter::new( + CHAPTER_NAME, + content.to_string(), + PathBuf::from("./book/chapter.md"), + vec![], + ) } } diff --git a/src/renderer.rs b/src/renderer.rs index 952ff33..af92778 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -1,22 +1,31 @@ use std::io; -use std::io::Write; -use std::process::{Child, Command, Stdio}; +use std::process::Stdio; +use tokio::process::{Child, Command}; +use async_trait::async_trait; use mdbook::errors::Result; use pulldown_cmark::{Event, LinkType, Tag}; use regex::Regex; use crate::preprocessor::GraphvizBlock; +use tokio::io::AsyncWriteExt; +#[async_trait] pub trait GraphvizRenderer { - fn render_graphviz<'a>(block: GraphvizBlock) -> Result>>; + async fn render_graphviz<'a>(block: GraphvizBlock) -> Result>>; } pub struct CLIGraphviz; +#[async_trait] impl GraphvizRenderer for CLIGraphviz { - fn render_graphviz<'a>(GraphvizBlock { code, .. }: GraphvizBlock) -> Result>> { - let output = call_graphviz(&["-Tsvg"], &code)?.wait_with_output()?; + async fn render_graphviz<'a>( + GraphvizBlock { code, .. }: GraphvizBlock, + ) -> Result>> { + let output = call_graphviz(&["-Tsvg"], &code) + .await? + .wait_with_output() + .await?; if output.status.success() { let graph_svg = String::from_utf8(output.stdout)?; @@ -32,8 +41,9 @@ impl GraphvizRenderer for CLIGraphviz { pub struct CLIGraphvizToFile; +#[async_trait] impl GraphvizRenderer for CLIGraphvizToFile { - fn render_graphviz<'a>(block: GraphvizBlock) -> Result>> { + async fn render_graphviz<'a>(block: GraphvizBlock) -> Result>> { let file_name = block.file_name(); let output_path = block.output_path(); let GraphvizBlock { @@ -44,8 +54,10 @@ impl GraphvizRenderer for CLIGraphvizToFile { .to_str() .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Couldn't build output path"))?; - if call_graphviz(&["-Tsvg", "-o", output_path_str], &code)? - .wait()? + if call_graphviz(&["-Tsvg", "-o", output_path_str], &code) + .await? + .wait() + .await? .success() { let image_tag = Tag::Image(LinkType::Inline, file_name.into(), graph_name.into()); @@ -61,7 +73,7 @@ impl GraphvizRenderer for CLIGraphvizToFile { } } -fn call_graphviz(args: &[&str], code: &str) -> Result { +async fn call_graphviz(args: &[&str], code: &str) -> Result { let mut child = Command::new("dot") .args(args) .stdin(Stdio::piped()) @@ -70,7 +82,7 @@ fn call_graphviz(args: &[&str], code: &str) -> Result { .spawn()?; if let Some(mut stdin) = child.stdin.take() { - stdin.write_all(code.as_bytes())?; + stdin.write_all(code.as_bytes()).await?; } Ok(child) @@ -97,8 +109,8 @@ fn format_output(output: String) -> String { mod test { use super::*; - #[test] - fn inline_events() { + #[tokio::test] + async fn inline_events() { let code = r#"digraph Test { a -> b }"#; let block = GraphvizBlock { @@ -109,7 +121,10 @@ mod test { index: 0, }; - let mut events = CLIGraphviz::render_graphviz(block).unwrap().into_iter(); + let mut events = CLIGraphviz::render_graphviz(block) + .await + .unwrap() + .into_iter(); if let Some(Event::Html(_)) = events.next() { } else { panic!("Unexpected next event")