diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9e3c7b97..bd3c7558 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,7 @@ jobs: rust: stable - build: msrv os: ubuntu-latest - rust: 1.45.0 + rust: 1.46.0 steps: - uses: actions/checkout@master - name: Install Rust diff --git a/CHANGELOG.md b/CHANGELOG.md index bee6f058..209e9fb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,72 @@ # Changelog +## mdBook 0.4.13 +[e6629cd...f55028b](https://github.com/rust-lang/mdBook/compare/e6629cd...f55028b) + +### Added + +- Added the ability to specify the preprocessor order. + [#1607](https://github.com/rust-lang/mdBook/pull/1607) + +### Fixed + +- Include chapters with no headers in the search index + [#1637](https://github.com/rust-lang/mdBook/pull/1637) +- Switched to the `opener` crate for opening a web browser, which should fix + some issues with blocking. + [#1656](https://github.com/rust-lang/mdBook/pull/1656) +- Fixed clicking the border of the theme switcher breaking the theme selection. + [#1651](https://github.com/rust-lang/mdBook/pull/1651) + +## mdBook 0.4.12 +[14add9c...8b4e488](https://github.com/rust-lang/mdBook/compare/14add9c...8b4e488) + +### Changed +- Reverted the change to update to highlight.js 11, as it broke hidden code lines. + [#1597](https://github.com/rust-lang/mdBook/pull/1621) + +## mdBook 0.4.11 +[e440094...2cf00d0](https://github.com/rust-lang/mdBook/compare/e440094...2cf00d0) + +### Added +- Added support for Rust 2021 edition. + [#1596](https://github.com/rust-lang/mdBook/pull/1596) +- Added `mdbook completions` subcommand which provides shell completions. + [#1425](https://github.com/rust-lang/mdBook/pull/1425) +- Added `--title` and `--ignore` flags to `mdbook init` to avoid the + interactive input. + [#1559](https://github.com/rust-lang/mdBook/pull/1559) + +### Changed +- If running a Rust example does not have any output, it now displays the text + "No output" instead of not showing anything. + [#1599](https://github.com/rust-lang/mdBook/pull/1599) +- Code block language tags can now be separated by space or tab (along with + commas) to match the behavior of other sites like GitHub and rustdoc. + [#1469](https://github.com/rust-lang/mdBook/pull/1469) +- Updated `warp` (the web server) to the latest version. + This also updates the minimum supported Rust version to 1.46. + [#1612](https://github.com/rust-lang/mdBook/pull/1612) +- Updated to highlight.js 11. This has various highlighting improvements. + [#1597](https://github.com/rust-lang/mdBook/pull/1597) + +### Fixed +- Inline code blocks inside a header are no longer highlighted when + `output.html.playground.editable` is `true`. + [#1613](https://github.com/rust-lang/mdBook/pull/1613) + +## mdBook 0.4.10 +[2f7293a...dc2062a](https://github.com/rust-lang/mdBook/compare/2f7293a...dc2062a) + +### Changed +- Reverted breaking change in 0.4.9 that removed the `__non_exhaustive` marker + on the `Book` struct. + [#1572](https://github.com/rust-lang/mdBook/pull/1572) +- Updated handlebars to 4.0. + [#1550](https://github.com/rust-lang/mdBook/pull/1550) +- Removed the `chapter_begin` id on the print page's chapter separators. + [#1541](https://github.com/rust-lang/mdBook/pull/1541) + ## mdBook 0.4.9 [7e01cf9...d325c60](https://github.com/rust-lang/mdBook/compare/7e01cf9...d325c60) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..e3708bc4 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# The Rust Code of Conduct + +The Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31a44761..924cfdba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,6 @@ If you have come here to learn how to contribute to mdBook, we have some tips fo First of all, don't hesitate to ask questions! Use the [issue tracker](https://github.com/rust-lang/mdBook/issues), no question is too simple. -If we don't respond in a couple of days, ping us @Michael-F-Bryan, @budziq, @steveklabnik, @frewsxcv it might just be that we forgot. :wink: ### Issues to work on @@ -46,7 +45,7 @@ mdBook builds on stable Rust, if you want to build mdBook from source, here are 0. Navigate into the newly created `mdBook` directory 0. Run `cargo build` -The resulting binary can be found in `mdBook/target/debug/` under the name `mdBook` or `mdBook.exe`. +The resulting binary can be found in `mdBook/target/debug/` under the name `mdbook` or `mdbook.exe`. ### Code Quality @@ -106,3 +105,26 @@ and [rustfmt](https://github.com/rust-lang/rustfmt) on the code first. This is not a requirement though and will never block a pull-request from being merged. That's it, happy contributions! :tada: :tada: :tada: + +## Browser compatibility and testing + +Currently we don't have a strict browser compatibility matrix due to our limited resources. +We generally strive to keep mdBook compatible with a relatively recent browser on all of the most major platforms. +That is, supporting Chrome, Safari, Firefox, Edge on Windows, macOS, Linux, iOS, and Android. +If possible, do your best to avoid breaking older browser releases. + +Any change to the HTML or styling is encouraged to manually check on as many browsers and platforms that you can. +Unfortunately at this time we don't have any automated UI or browser testing, so your assistance in testing is appreciated. + +## Updating higlight.js + +The following are instructions for updating [highlight.js](https://highlightjs.org/). + +1. Clone the repository at +1. Check out a tagged release (like `10.1.1`). +1. Run `npm install` +1. Run `node tools/build.js :common apache armasm coffeescript d handlebars haskell http julia nginx properties r scala x86asm yaml` +1. Compare the language list that it spits out to the one in [`syntax-highlighting.md`](https://github.com/camelid/mdBook/blob/master/guide/src/format/theme/syntax-highlighting.md). If any are missing, add them to the list and rebuild (and update these docs). If any are added to the common set, add them to `syntax-highlighting.md`. +1. Copy `build/highlight.min.js` to mdbook's directory [`highlight.js`](https://github.com/rust-lang/mdBook/blob/master/src/theme/highlight.js). +1. Be sure to check the highlight.js [CHANGES](https://github.com/highlightjs/highlight.js/blob/main/CHANGES.md) for any breaking changes. Breaking changes that would affect users will need to wait until the next major release. +1. Build mdbook with the new file and build some books with the new version and compare the output with a variety of languages to see if anything changes. (TODO: It would be nice to have a demo file in the repo to help with this.) diff --git a/Cargo.lock b/Cargo.lock index 0cb94333..3f6c5e12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "ammonia" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee7d6eb157f337c5cedc95ddf17f0cbc36d36eb7763c8e0d1c1aeb3722f6279" +checksum = "2e445c26125ff80316eaea16e812d717b147b82a68682bd4730f74d4845c8b35" dependencies = [ "html5ever", "lazy_static", @@ -37,9 +37,23 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" +checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" + +[[package]] +name = "assert_cmd" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20831bd004dda4c7c372c19cdabff369f794a95e955b3f13fe460e3e1ae95f" +dependencies = [ + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] [[package]] name = "atty" @@ -58,12 +72,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "base64" version = "0.13.0" @@ -87,9 +95,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" @@ -121,6 +129,17 @@ dependencies = [ "byte-tools", ] +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", +] + [[package]] name = "byte-tools" version = "0.3.1" @@ -133,12 +152,6 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - [[package]] name = "bytes" version = "1.0.1" @@ -187,9 +200,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.1.1" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec1028182c380cc45a2e2c5ec841134f2dfd0f8f5f0a5bcd68004f81b5efdf4" +checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" dependencies = [ "libc", ] @@ -210,6 +223,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.8.1" @@ -229,10 +248,10 @@ dependencies = [ ] [[package]] -name = "dtoa" -version = "0.4.8" +name = "doc-comment" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" @@ -242,9 +261,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "elasticlunr-rs" -version = "2.3.11" +version = "2.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "959fbc9a6ebced545cbe365fdce5e25c6ab7683f2ca4ecc9fb9d0db663bf73d5" +checksum = "515a402b5acb08002194dd926065be7733003bb37ac0f030dfd39160028238e1" dependencies = [ "lazy_static", "regex", @@ -276,9 +295,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" dependencies = [ "cfg-if 1.0.0", "libc", @@ -286,6 +305,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "fnv" version = "1.0.7" @@ -349,9 +377,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253" +checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" dependencies = [ "futures-channel", "futures-core", @@ -363,9 +391,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25" +checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" dependencies = [ "futures-core", "futures-sink", @@ -373,22 +401,23 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815" +checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" [[package]] name = "futures-io" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04" +checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" [[package]] name = "futures-macro" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b" +checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" dependencies = [ + "autocfg", "proc-macro-hack", "proc-macro2", "quote", @@ -397,27 +426,28 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23" +checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" [[package]] name = "futures-task" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc" +checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" [[package]] name = "futures-util" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025" +checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" dependencies = [ + "autocfg", "futures-core", "futures-macro", "futures-sink", "futures-task", - "pin-project-lite 0.2.6", + "pin-project-lite", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -465,9 +495,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", "libc", @@ -491,11 +521,11 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" -version = "0.2.7" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" +checksum = "d7f3675cfef6a30c8031cf9e6493ebdc3bb3272a3fea3923c4210d1830e6a472" dependencies = [ - "bytes 0.5.6", + "bytes", "fnv", "futures-core", "futures-sink", @@ -506,14 +536,13 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "tracing-futures", ] [[package]] name = "handlebars" -version = "4.0.0" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f0fe89affef47e2c9729030a8f6e79df34cb66b8a44ecf91dad43f31150559" +checksum = "fd85ecabdb47308d28d3a4113224fefcab2510ccb4e463aee0a1362eb84c756a" dependencies = [ "log", "pest", @@ -525,9 +554,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "headers" @@ -535,13 +564,13 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" dependencies = [ - "base64 0.13.0", + "base64", "bitflags", - "bytes 1.0.1", + "bytes", "headers-core", "http", "mime", - "sha-1 0.9.5", + "sha-1 0.9.7", "time", ] @@ -556,18 +585,18 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" dependencies = [ "unicode-segmentation", ] [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] @@ -592,32 +621,33 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" dependencies = [ - "bytes 1.0.1", + "bytes", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.3.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" dependencies = [ - "bytes 0.5.6", + "bytes", "http", + "pin-project-lite", ] [[package]] name = "httparse" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" -version = "0.3.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" [[package]] name = "humantime" @@ -630,11 +660,11 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.10" +version = "0.14.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" +checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -644,7 +674,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project 1.0.7", + "pin-project-lite", "socket2", "tokio", "tower-service", @@ -665,9 +695,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", "hashbrown", @@ -695,11 +725,11 @@ dependencies = [ [[package]] name = "input_buffer" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" +checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" dependencies = [ - "bytes 0.5.6", + "bytes", ] [[package]] @@ -712,10 +742,19 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "0.4.7" +name = "itertools" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "kernel32-sys" @@ -741,9 +780,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.94" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" +checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" [[package]] name = "log" @@ -794,16 +833,17 @@ dependencies = [ [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mdbook" -version = "0.4.9" +version = "0.4.13" dependencies = [ "ammonia", "anyhow", + "assert_cmd", "chrono", "clap", "elasticlunr-rs", @@ -815,7 +855,8 @@ dependencies = [ "log", "memchr", "notify", - "open", + "opener", + "predicates", "pretty_assertions", "pulldown-cmark", "regex", @@ -828,15 +869,16 @@ dependencies = [ "tempfile", "tokio", "toml", + "topological-sort", "walkdir", "warp", ] [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "mime" @@ -867,12 +909,25 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.2", "net2", "slab", "winapi 0.2.8", ] +[[package]] +name = "mio" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +dependencies = [ + "libc", + "log", + "miow 0.3.7", + "ntapi", + "winapi 0.3.9", +] + [[package]] name = "mio-extras" version = "2.0.6" @@ -881,7 +936,7 @@ checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ "lazycell", "log", - "mio", + "mio 0.6.23", "slab", ] @@ -897,6 +952,15 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "net2" version = "0.2.37" @@ -915,10 +979,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] -name = "notify" -version = "4.0.16" +name = "normalize-line-endings" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2599080e87c9bd051ddb11b10074f4da7b1223298df65d4c2ec5bcf309af1533" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "notify" +version = "4.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" dependencies = [ "bitflags", "filetime", @@ -926,12 +996,21 @@ dependencies = [ "fsevent-sys", "inotify", "libc", - "mio", + "mio 0.6.23", "mio-extras", "walkdir", "winapi 0.3.9", ] +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -951,6 +1030,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "opaque-debug" version = "0.2.3" @@ -964,12 +1053,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "open" -version = "1.7.0" +name = "opener" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1711eb4b31ce4ad35b0f316d8dfba4fe5c7ad601c448446d84aae7a896627b20" +checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952" dependencies = [ - "which", + "bstr", "winapi 0.3.9", ] @@ -1071,38 +1160,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.28" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" dependencies = [ - "pin-project-internal 0.4.28", -] - -[[package]] -name = "pin-project" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" -dependencies = [ - "pin-project-internal 1.0.7", + "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.28" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ "proc-macro2", "quote", @@ -1111,15 +1180,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.1.12" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - -[[package]] -name = "pin-project-lite" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" [[package]] name = "pin-utils" @@ -1139,6 +1202,36 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "predicates" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc3d91237f5de3bcd9d927e24d03b495adb6135097b001cea7403e2d573d00a9" +dependencies = [ + "difflib", + "float-cmp", + "itertools", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" + +[[package]] +name = "predicates-tree" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2" +dependencies = [ + "predicates-core", + "treeline", +] + [[package]] name = "pretty_assertions" version = "0.6.1" @@ -1165,9 +1258,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" dependencies = [ "unicode-xid", ] @@ -1221,14 +1314,14 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.2", - "rand_hc 0.3.0", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", ] [[package]] @@ -1243,12 +1336,12 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -1262,11 +1355,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.2", + "getrandom 0.2.3", ] [[package]] @@ -1280,11 +1373,11 @@ dependencies = [ [[package]] name = "rand_hc" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] @@ -1298,9 +1391,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -1316,6 +1409,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" version = "0.6.25" @@ -1383,15 +1482,15 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.125" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1" [[package]] name = "serde_derive" -version = "1.0.125" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3" dependencies = [ "proc-macro2", "quote", @@ -1400,9 +1499,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" dependencies = [ "itoa", "ryu", @@ -1411,14 +1510,14 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ - "dtoa", + "form_urlencoded", "itoa", + "ryu", "serde", - "url", ] [[package]] @@ -1435,9 +1534,9 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659df5fc3ce22274daac600ffb845300bd2125bcfaec047823075afdab81c00" +checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", @@ -1454,23 +1553,22 @@ checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d" [[package]] name = "siphasher" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27" +checksum = "729a25c17d72b06c68cb47955d44fda88ad2d3e7d77e025663fdd69b93dd71a1" [[package]] name = "slab" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" [[package]] name = "socket2" -version = "0.3.19" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" dependencies = [ - "cfg-if 1.0.0", "libc", "winapi 0.3.9", ] @@ -1508,15 +1606,15 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strum" -version = "0.18.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" +checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" [[package]] name = "strum_macros" -version = "0.18.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" dependencies = [ "heck", "proc-macro2", @@ -1526,9 +1624,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" +checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" dependencies = [ "proc-macro2", "quote", @@ -1543,7 +1641,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", "libc", - "rand 0.8.3", + "rand 0.8.4", "redox_syscall", "remove_dir_all", "winapi 0.3.9", @@ -1590,9 +1688,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" dependencies = [ "tinyvec_macros", ] @@ -1605,27 +1703,26 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "0.2.25" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "iovec", - "lazy_static", + "autocfg", + "bytes", + "libc", "memchr", - "mio", - "pin-project-lite 0.1.12", - "slab", + "mio 0.7.13", + "num_cpus", + "pin-project-lite", "tokio-macros", + "winapi 0.3.9", ] [[package]] name = "tokio-macros" -version = "0.2.6" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" dependencies = [ "proc-macro2", "quote", @@ -1633,29 +1730,40 @@ dependencies = [ ] [[package]] -name = "tokio-tungstenite" -version = "0.11.0" +name = "tokio-stream" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9e878ad426ca286e4dcae09cbd4e1973a7f8987d97570e2469703dd7f5720c" +checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b" dependencies = [ "futures-util", "log", - "pin-project 0.4.28", + "pin-project", "tokio", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.3.1" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-core", "futures-sink", "log", - "pin-project-lite 0.1.12", + "pin-project-lite", "tokio", ] @@ -1668,6 +1776,12 @@ dependencies = [ "serde", ] +[[package]] +name = "topological-sort" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c" + [[package]] name = "tower-service" version = "0.3.1" @@ -1682,28 +1796,24 @@ checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.6", + "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8" dependencies = [ "lazy_static", ] [[package]] -name = "tracing-futures" -version = "0.2.5" +name = "treeline" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project 1.0.7", - "tracing", -] +checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "try-lock" @@ -1713,19 +1823,19 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23" +checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" dependencies = [ - "base64 0.12.3", + "base64", "byteorder", - "bytes 0.5.6", + "bytes", "http", "httparse", "input_buffer", "log", - "rand 0.7.3", - "sha-1 0.9.5", + "rand 0.8.4", + "sha-1 0.9.7", "url", "utf-8", ] @@ -1753,27 +1863,24 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" [[package]] name = "unicode-normalization" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-width" @@ -1799,12 +1906,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "urlencoding" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593" - [[package]] name = "utf-8" version = "0.7.6" @@ -1823,6 +1924,15 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.3.2" @@ -1846,11 +1956,11 @@ dependencies = [ [[package]] name = "warp" -version = "0.2.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f41be6df54c97904af01aa23e613d4521eed7ab23537cede692d4058f6449407" +checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054" dependencies = [ - "bytes 0.5.6", + "bytes", "futures", "headers", "http", @@ -1858,17 +1968,18 @@ dependencies = [ "log", "mime", "mime_guess", - "pin-project 0.4.28", + "percent-encoding", + "pin-project", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", + "tokio-stream", "tokio-tungstenite", + "tokio-util", "tower-service", "tracing", - "tracing-futures", - "urlencoding", ] [[package]] @@ -1883,16 +1994,6 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" -[[package]] -name = "which" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe" -dependencies = [ - "either", - "libc", -] - [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index aca00e5c..dd0b17bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mdbook" -version = "0.4.9" +version = "0.4.13" authors = [ "Mathieu David ", "Michael-F-Bryan ", @@ -24,7 +24,7 @@ handlebars = "4.0" lazy_static = "1.0" log = "0.4" memchr = "2.0" -open = "1.1" +opener = "0.5" pulldown-cmark = "0.7.0" regex = "1.0.0" serde = "1.0" @@ -33,6 +33,7 @@ serde_json = "1.0" shlex = "1" tempfile = "3.0" toml = "0.5.1" +topological-sort = "0.1.0" # Watch feature notify = { version = "4.0", optional = true } @@ -40,14 +41,16 @@ gitignore = { version = "1.0", optional = true } # Serve feature futures-util = { version = "0.3.4", optional = true } -tokio = { version = "0.2.18", features = ["macros"], optional = true } -warp = { version = "0.2.2", default-features = false, features = ["websocket"], optional = true } +tokio = { version = "1", features = ["macros", "rt-multi-thread"], optional = true } +warp = { version = "0.3.1", default-features = false, features = ["websocket"], optional = true } # Search feature elasticlunr-rs = { version = "2.3", optional = true, default-features = false } ammonia = { version = "3", optional = true } [dev-dependencies] +assert_cmd = "1" +predicates = "2" select = "0.5" semver = "0.11.0" pretty_assertions = "0.6" diff --git a/README.md b/README.md index 7c5b32f0..f611d6ac 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ of a book in order to validate links or run tests. Some existing renderers are: preprocessors. - [`linkcheck`] - a backend which will check that all links are valid - [`epub`] - an experimental EPUB generator +- [`man`] - a backend that generates manual pages from the book > **Note for Developers:** Feel free to send us a PR if you've developed your > own plugin and want it mentioned here. @@ -234,3 +235,4 @@ All the code in this repository is released under the ***Mozilla Public License [master-docs]: http://rust-lang.github.io/mdBook/ [`linkcheck`]: https://crates.io/crates/mdbook-linkcheck [`epub`]: https://crates.io/crates/mdbook-epub +[`man`]: https://crates.io/crates/mdbook-man diff --git a/examples/nop-preprocessor.rs b/examples/nop-preprocessor.rs index 38764207..486fd86d 100644 --- a/examples/nop-preprocessor.rs +++ b/examples/nop-preprocessor.rs @@ -37,7 +37,7 @@ fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> { let book_version = Version::parse(&ctx.mdbook_version)?; let version_req = VersionReq::parse(mdbook::MDBOOK_VERSION)?; - if version_req.matches(&book_version) != true { + if !version_req.matches(&book_version) { eprintln!( "Warning: The {} plugin was built against version {} of mdbook, \ but we're being called from version {}", @@ -55,7 +55,7 @@ fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> { fn handle_supports(pre: &dyn Preprocessor, sub_args: &ArgMatches) -> ! { let renderer = sub_args.value_of("renderer").expect("Required argument"); - let supported = pre.supports_renderer(&renderer); + let supported = pre.supports_renderer(renderer); // Signal whether the renderer is supported by exiting with 1 or 0. if supported { diff --git a/guide/src/README.md b/guide/src/README.md index 99e55bce..ac6f48e7 100644 --- a/guide/src/README.md +++ b/guide/src/README.md @@ -1,25 +1,40 @@ -# mdBook +# Introduction -**mdBook** is a command line tool and Rust crate to create books using Markdown -(as by the [CommonMark](https://commonmark.org/) specification) files. It's very -similar to Gitbook but written in [Rust](http://www.rust-lang.org). +**mdBook** is a command line tool and Rust crate to create books with Markdown. The output resembles tools like Gitbook, +and is ideal for creating product or API documentation, tutorials, course materials or anything that requires a clean, +easily navigable and customizable presentation. mdBook is written in [Rust](https://www.rust-lang.org); its performance +and simplicity made it ideal for use as a tool to publish directly to hosted websites such +as [GitHub Pages](https://pages.github.com) via automation. This guide, in fact, serves as both the mdBook documentation +and a fine example of what mdBook produces. -What you are reading serves as an example of the output of mdBook and at the -same time as a high-level documentation. +mdBook includes built in support for both preprocessing your Markdown and alternative renderers for producing formats +other than HTML. These facilities also enable other functionality such as +validation. [Searching](https://crates.io/search?q=mdbook&sort=relevance) Rust's [crates.io](https://crates.io) is a +great way to discover more extensions. -mdBook is free and open source, you can find the source code on -[GitHub](https://github.com/rust-lang/mdBook). Issues and feature -requests can be posted on the [GitHub issue -tracker](https://github.com/rust-lang/mdBook/issues). +## API Documentation -## API docs +In addition to the above features, mdBook also has a Rust [API](https://docs.rs/mdbook/*/mdbook/). This allows you to +write your own preprocessor or renderer, as well as incorporate mdBook features into other applications. +The [For Developers](for_developers) section of this guide contains more information and some examples. -Alongside this book you can also read the [API -docs](https://docs.rs/mdbook/*/mdbook/) generated by Rustdoc if you would like -to use mdBook as a crate or write a new renderer and need a more low-level -overview. +## Markdown + +mdBook's [parser](https://github.com/raphlinus/pulldown-cmark) adheres to the [CommonMark](https://commonmark.org/) +specification. You can take a quick [tutorial](https://commonmark.org/help/tutorial/), +or [try out](https://spec.commonmark.org/dingus/) CommonMark in real time. For a more in-depth experience, check out the +[Markdown Guide](https://www.markdownguide.org). + +## Contributing + +mdBook is free and open source. You can find the source code on +[GitHub](https://github.com/rust-lang/mdBook) and issues and feature requests can be posted on +the [GitHub issue tracker](https://github.com/rust-lang/mdBook/issues). mdBook relies on the community to fix bugs and +add features: if you'd like to contribute, please read +the [CONTRIBUTING](https://github.com/rust-lang/mdBook/blob/master/CONTRIBUTING.md) guide and consider opening +a [pull request](https://github.com/rust-lang/mdBook/pulls). ## License -mdBook, all the source code, is released under the [Mozilla Public License -v2.0](https://www.mozilla.org/MPL/2.0/). +The mdBook source and documentation are released under +the [Mozilla Public License v2.0](https://www.mozilla.org/MPL/2.0/). diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index d95410cc..37e9fca0 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -- [mdBook](README.md) +- [Introduction](README.md) - [Command Line Tool](cli/README.md) - [init](cli/init.md) - [build](cli/build.md) diff --git a/guide/src/cli/init.md b/guide/src/cli/init.md index a0a407c5..99c0be09 100644 --- a/guide/src/cli/init.md +++ b/guide/src/cli/init.md @@ -52,3 +52,19 @@ directory called `theme` in your source directory so that you can modify it. The theme is selectively overwritten, this means that if you don't want to overwrite a specific file, just delete it and the default file will be used. + +#### --title + +Specify a title for the book. If not supplied, an interactive prompt will ask for +a title. + +```bash +mdbook init --title="my amazing book" +``` + +#### --ignore + +Create a `.gitignore` file configured to ignore the `book` directory created when [building] a book. +If not supplied, an interactive prompt will ask whether it should be created. + +[building]: build.md diff --git a/guide/src/cli/test.md b/guide/src/cli/test.md index c13e8809..e134dc9b 100644 --- a/guide/src/cli/test.md +++ b/guide/src/cli/test.md @@ -43,7 +43,17 @@ mdbook test path/to/book The `--library-path` (`-L`) option allows you to add directories to the library search path used by `rustdoc` when it builds and tests the examples. Multiple directories can be specified with multiple options (`-L foo -L bar`) or with a -comma-delimited list (`-L foo,bar`). +comma-delimited list (`-L foo,bar`). The path should point to the Cargo +[build cache](https://doc.rust-lang.org/cargo/guide/build-cache.html) `deps` directory that +contains the build output of your project. For example, if your Rust project's book is in a directory +named `my-book`, the following command would include the crate's dependencies when running `test`: + +```shell +mdbook test my-book -L target/debug/deps/ +``` + +See the `rustdoc` command-line [documentation](https://doc.rust-lang.org/rustdoc/command-line-arguments.html#-l--library-path-where-to-look-for-dependencies) +for more information. #### --dest-dir diff --git a/guide/src/continuous-integration.md b/guide/src/continuous-integration.md index 11862010..ce075040 100644 --- a/guide/src/continuous-integration.md +++ b/guide/src/continuous-integration.md @@ -26,7 +26,7 @@ before_script: - cargo install-update -a script: - - mdbook build path/to/mybook && mdbook test path/to/mybook + - mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook ``` ## Deploying Your Book to GitHub Pages @@ -50,10 +50,10 @@ deploy: provider: pages skip-cleanup: true github-token: $GITHUB_TOKEN - local-dir: path/to/mybook/book + local-dir: book # In case of custom book path: path/to/mybook/book keep-history: false on: - branch: master + branch: main ``` That's it! @@ -77,7 +77,7 @@ before_script: - cargo install-update -a script: - - mdbook build path/to/mybook && mdbook test path/to/mybook + - mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook deploy: provider: pages @@ -85,10 +85,10 @@ deploy: edge: true cleanup: false github-token: $GITHUB_TOKEN - local-dir: path/to/mybook/book + local-dir: book # In case of custom book path: path/to/mybook/book keep-history: false on: - branch: master + branch: main target_branch: gh-pages ``` @@ -140,15 +140,15 @@ pages: - export PATH="$PATH:$CARGO_HOME/bin" - mdbook --version || cargo install mdbook script: - - mdbook build -d public - only: - - master + - mdbook build -d public + rules: + - if: '$CI_COMMIT_REF_NAME == "master"' artifacts: - paths: - - public + paths: + - public cache: paths: - - $CARGO_HOME/bin + - $CARGO_HOME/bin ``` After you commit and push this new file, GitLab CI will run and your book will be available! diff --git a/guide/src/for_developers/backends.md b/guide/src/for_developers/backends.md index 5b958067..fcc44a47 100644 --- a/guide/src/for_developers/backends.md +++ b/guide/src/for_developers/backends.md @@ -13,6 +13,7 @@ rough example of how this is accomplished in practice. - [mdbook-epub] - an EPUB renderer - [mdbook-test] - a program to run the book's contents through [rust-skeptic] to verify everything compiles and runs correctly (similar to `rustdoc --test`) +- [mdbook-man] - generate manual pages from the book This page will step you through creating your own alternative backend in the form of a simple word counting program. Although it will be written in Rust, there's @@ -377,6 +378,7 @@ the source code or ask questions. [mdbook-linkcheck]: https://github.com/Michael-F-Bryan/mdbook-linkcheck [mdbook-epub]: https://github.com/Michael-F-Bryan/mdbook-epub [mdbook-test]: https://github.com/Michael-F-Bryan/mdbook-test +[mdbook-man]: https://github.com/vv9k/mdbook-man [rust-skeptic]: https://github.com/budziq/rust-skeptic [`RenderContext`]: https://docs.rs/mdbook/*/mdbook/renderer/struct.RenderContext.html [`RenderContext::from_json()`]: https://docs.rs/mdbook/*/mdbook/renderer/struct.RenderContext.html#method.from_json diff --git a/guide/src/for_developers/preprocessors.md b/guide/src/for_developers/preprocessors.md index 6b2b6633..074d1c3c 100644 --- a/guide/src/for_developers/preprocessors.md +++ b/guide/src/for_developers/preprocessors.md @@ -34,8 +34,15 @@ command = "python3 /path/to/foo.py" renderer = ["html", "epub"] ``` -In typical unix style, all inputs to the plugin will be written to `stdin` as -JSON and `mdbook` will read from `stdout` if it is expecting output. +Once the preprocessor has been defined and the build process starts, mdBook executes the command defined in the `preprocessor.foo.command` key twice. +The first time it runs the preprocessor to determine if it supports the given renderer. +mdBook passes two arguments to the process: the first argument is the string `supports` and the second argument is the renderer name. +The preprocessor should exit with a status code 0 if it supports the given renderer, or return a non-zero exit code if it does not. + +If the preprocessor supports the renderer, then mdbook runs it a second time, passing JSON data into stdin. +The JSON consists of an array of `[context, book]` where `context` is the serialized object [`PreprocessorContext`] and `book` is a [`Book`] object containing the content of the book. + +The preprocessor should return the JSON format of the [`Book`] object to stdout, with any modifications it wishes to perform. The easiest way to get started is by creating your own implementation of the `Preprocessor` trait (e.g. in `lib.rs`) and then creating a shell binary which @@ -106,6 +113,33 @@ fn remove_emphasis( For everything else, have a look [at the complete example][example]. +## Implementing a preprocessor with a different language + +The fact that mdBook utilizes stdin and stdout to communicate with the preprocessors makes it easy to implement them in a language other than Rust. +The following code shows how to implement a simple preprocessor in Python, which will modify the content of the first chapter. +The example below follows the configuration shown above with `preprocessor.foo.command` actually pointing to a Python script. + +```python +import json +import sys + + +if __name__ == '__main__': + if len(sys.argv) > 1: # we check if we received any argument + if sys.argv[1] == "supports": + # then we are good to return an exit status code of 0, since the other argument will just be the renderer's name + sys.exit(0) + + # load both the context and the book representations from stdin + context, book = json.load(sys.stdin) + # and now, we can just modify the content of the first chapter + book['sections'][0]['Chapter']['content'] = '# Hello' + # we are done with the book's modification, we can just print it to stdout, + print(json.dumps(book)) +``` + + + [preprocessor-docs]: https://docs.rs/mdbook/latest/mdbook/preprocess/trait.Preprocessor.html [pc]: https://crates.io/crates/pulldown-cmark [pctc]: https://crates.io/crates/pulldown-cmark-to-cmark @@ -113,3 +147,5 @@ For everything else, have a look [at the complete example][example]. [an example no-op preprocessor]: https://github.com/rust-lang/mdBook/blob/master/examples/nop-preprocessor.rs [`CmdPreprocessor::parse_input()`]: https://docs.rs/mdbook/latest/mdbook/preprocess/trait.Preprocessor.html#method.parse_input [`Book::for_each_mut()`]: https://docs.rs/mdbook/latest/mdbook/book/struct.Book.html#method.for_each_mut +[`PreprocessorContext`]: https://docs.rs/mdbook/latest/mdbook/preprocess/struct.PreprocessorContext.html +[`Book`]: https://docs.rs/mdbook/latest/mdbook/book/struct.Book.html diff --git a/guide/src/format/configuration/general.md b/guide/src/format/configuration/general.md index 20396fac..1c3884fb 100644 --- a/guide/src/format/configuration/general.md +++ b/guide/src/format/configuration/general.md @@ -63,8 +63,8 @@ Options for the Rust language, relevant to running tests and playground integration. - **edition**: Rust edition to use by default for the code snippets. Default - is "2015". Individual code blocks can be controlled with the `edition2015` - or `edition2018` annotations, such as: + is "2015". Individual code blocks can be controlled with the `edition2015`, + `edition2018` or `edition2021` annotations, such as: ~~~text ```rust,edition2015 diff --git a/guide/src/format/configuration/preprocessors.md b/guide/src/format/configuration/preprocessors.md index be614cac..8d3e1dc6 100644 --- a/guide/src/format/configuration/preprocessors.md +++ b/guide/src/format/configuration/preprocessors.md @@ -56,3 +56,25 @@ be overridden by adding a `command` field. [preprocessor.random] command = "python random.py" ``` + +### Require A Certain Order + +The order in which preprocessors are run can be controlled with the `before` and `after` fields. +For example, suppose you want your `linenos` preprocessor to process lines that may have been `{{#include}}`d; then you want it to run after the built-in `links` preprocessor, which you can require using either the `before` or `after` field: + +```toml +[preprocessor.linenos] +after = [ "links" ] +``` + +or + +```toml +[preprocessor.links] +before = [ "linenos" ] +``` + +It would also be possible, though redundant, to specify both of the above in the same config file. + +Preprocessors having the same priority specified through `before` and `after` are sorted by name. +Any infinite loops will be detected and produce an error. diff --git a/guide/src/format/configuration/renderers.md b/guide/src/format/configuration/renderers.md index e3d1a397..3f16216c 100644 --- a/guide/src/format/configuration/renderers.md +++ b/guide/src/format/configuration/renderers.md @@ -188,13 +188,13 @@ Enable it by adding an empty table to your `book.toml` as follows: There are no configuration options for the Markdown renderer at this time; only whether it is enabled or disabled. -See [the preprocessors documentation](#configuring-preprocessors) for how to +See [the preprocessors documentation](preprocessors.md) for how to specify which preprocessors should run before the Markdown renderer. ### Custom Renderers A custom renderer can be enabled by adding a `[output.foo]` table to your -`book.toml`. Similar to [preprocessors](#configuring-preprocessors) this will +`book.toml`. Similar to [preprocessors](preprocessors.md) this will instruct `mdbook` to pass a representation of the book to `mdbook-foo` for rendering. See the [alternative backends] chapter for more detail. diff --git a/guide/src/format/mdbook.md b/guide/src/format/mdbook.md index 169a8baa..6c691473 100644 --- a/guide/src/format/mdbook.md +++ b/guide/src/format/mdbook.md @@ -21,7 +21,7 @@ Will render as ```rust # fn main() { let x = 5; - let y = 7; + let y = 6; println!("{}", x + y); # } diff --git a/guide/src/misc/contributors.md b/guide/src/misc/contributors.md index 587842e7..362a21fe 100644 --- a/guide/src/misc/contributors.md +++ b/guide/src/misc/contributors.md @@ -15,8 +15,10 @@ shout-out to them! - [projektir](https://github.com/projektir) - [Phaiax](https://github.com/Phaiax) - Matt Ickstadt ([mattico](https://github.com/mattico)) -- Weihang Lo ([@weihanglo](https://github.com/weihanglo)) -- Avision Ho ([@avisionh](https://github.com/avisionh)) -- Vivek Akupatni ([@apatniv](https://github.com/apatniv)) +- Weihang Lo ([weihanglo](https://github.com/weihanglo)) +- Avision Ho ([avisionh](https://github.com/avisionh)) +- Vivek Akupatni ([apatniv](https://github.com/apatniv)) +- Eric Huss ([ehuss](https://github.com/ehuss)) +- Josh Rotenberg ([joshrotenberg](https://github.com/joshrotenberg)) If you feel you're missing from this list, feel free to add yourself in a PR. diff --git a/src/book/book.rs b/src/book/book.rs index e3d87600..da2a0a3c 100644 --- a/src/book/book.rs +++ b/src/book/book.rs @@ -22,7 +22,7 @@ pub fn load_book>(src_dir: P, cfg: &BuildConfig) -> Result .with_context(|| format!("Summary parsing failed for file={:?}", summary_md))?; if cfg.create_missing { - create_missing(&src_dir, &summary).with_context(|| "Unable to create missing chapters")?; + create_missing(src_dir, &summary).with_context(|| "Unable to create missing chapters")?; } load_book_from_disk(&summary, src_dir) @@ -74,10 +74,10 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> { /// [`iter()`]: #method.iter /// [`for_each_mut()`]: #method.for_each_mut #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] pub struct Book { /// The sections in this book. pub sections: Vec, + __non_exhaustive: (), } impl Book { @@ -225,7 +225,10 @@ pub(crate) fn load_book_from_disk>(summary: &Summary, src_dir: P) chapters.push(chapter); } - Ok(Book { sections: chapters }) + Ok(Book { + sections: chapters, + __non_exhaustive: (), + }) } fn load_summary_item + Clone>( @@ -378,7 +381,7 @@ And here is some \ root.nested_items.push(second.clone().into()); root.nested_items.push(SummaryItem::Separator); - root.nested_items.push(second.clone().into()); + root.nested_items.push(second.into()); (root, temp_dir) } @@ -451,7 +454,7 @@ And here is some \ sub_items: vec![ BookItem::Chapter(nested.clone()), BookItem::Separator, - BookItem::Chapter(nested.clone()), + BookItem::Chapter(nested), ], }); diff --git a/src/book/mod.rs b/src/book/mod.rs index 286234bd..df140797 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -20,6 +20,7 @@ use std::process::Command; use std::string::ToString; use tempfile::Builder as TempFileBuilder; use toml::Value; +use topological_sort::TopologicalSort; use crate::errors::*; use crate::preprocess::{ @@ -274,6 +275,10 @@ impl MDBook { RustEdition::E2018 => { cmd.args(&["--edition", "2018"]); } + RustEdition::E2021 => { + cmd.args(&["--edition", "2021"]) + .args(&["-Z", "unstable-options"]); + } } } @@ -368,12 +373,7 @@ fn determine_renderers(config: &Config) -> Vec> { renderers } -fn default_preprocessors() -> Vec> { - vec![ - Box::new(LinkPreprocessor::new()), - Box::new(IndexPreprocessor::new()), - ] -} +const DEFAULT_PREPROCESSORS: &[&'static str] = &["links", "index"]; fn is_default_preprocessor(pre: &dyn Preprocessor) -> bool { let name = pre.name(); @@ -382,36 +382,127 @@ fn is_default_preprocessor(pre: &dyn Preprocessor) -> bool { /// Look at the `MDBook` and try to figure out what preprocessors to run. fn determine_preprocessors(config: &Config) -> Result>> { - let mut preprocessors = Vec::new(); + // Collect the names of all preprocessors intended to be run, and the order + // in which they should be run. + let mut preprocessor_names = TopologicalSort::::new(); if config.build.use_default_preprocessors { - preprocessors.extend(default_preprocessors()); + for name in DEFAULT_PREPROCESSORS { + preprocessor_names.insert(name.to_string()); + } } if let Some(preprocessor_table) = config.get("preprocessor").and_then(Value::as_table) { - for key in preprocessor_table.keys() { - match key.as_ref() { - "links" => preprocessors.push(Box::new(LinkPreprocessor::new())), - "index" => preprocessors.push(Box::new(IndexPreprocessor::new())), - name => preprocessors.push(interpret_custom_preprocessor( - name, - &preprocessor_table[name], - )), + for (name, table) in preprocessor_table.iter() { + preprocessor_names.insert(name.to_string()); + + let exists = |name| { + (config.build.use_default_preprocessors && DEFAULT_PREPROCESSORS.contains(&name)) + || preprocessor_table.contains_key(name) + }; + + if let Some(before) = table.get("before") { + let before = before.as_array().ok_or_else(|| { + Error::msg(format!( + "Expected preprocessor.{}.before to be an array", + name + )) + })?; + for after in before { + let after = after.as_str().ok_or_else(|| { + Error::msg(format!( + "Expected preprocessor.{}.before to contain strings", + name + )) + })?; + + if !exists(after) { + // Only warn so that preprocessors can be toggled on and off (e.g. for + // troubleshooting) without having to worry about order too much. + warn!( + "preprocessor.{}.after contains \"{}\", which was not found", + name, after + ); + } else { + preprocessor_names.add_dependency(name, after); + } + } + } + + if let Some(after) = table.get("after") { + let after = after.as_array().ok_or_else(|| { + Error::msg(format!( + "Expected preprocessor.{}.after to be an array", + name + )) + })?; + for before in after { + let before = before.as_str().ok_or_else(|| { + Error::msg(format!( + "Expected preprocessor.{}.after to contain strings", + name + )) + })?; + + if !exists(before) { + // See equivalent warning above for rationale + warn!( + "preprocessor.{}.before contains \"{}\", which was not found", + name, before + ); + } else { + preprocessor_names.add_dependency(before, name); + } + } } } } - Ok(preprocessors) + // Now that all links have been established, queue preprocessors in a suitable order + let mut preprocessors = Vec::with_capacity(preprocessor_names.len()); + // `pop_all()` returns an empty vector when no more items are not being depended upon + for mut names in std::iter::repeat_with(|| preprocessor_names.pop_all()) + .take_while(|names| !names.is_empty()) + { + // The `topological_sort` crate does not guarantee a stable order for ties, even across + // runs of the same program. Thus, we break ties manually by sorting. + // Careful: `str`'s default sorting, which we are implicitly invoking here, uses code point + // values ([1]), which may not be an alphabetical sort. + // As mentioned in [1], doing so depends on locale, which is not desirable for deciding + // preprocessor execution order. + // [1]: https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html#impl-Ord-14 + names.sort(); + for name in names { + let preprocessor: Box = match name.as_str() { + "links" => Box::new(LinkPreprocessor::new()), + "index" => Box::new(IndexPreprocessor::new()), + _ => { + // The only way to request a custom preprocessor is through the `preprocessor` + // table, so it must exist, be a table, and contain the key. + let table = &config.get("preprocessor").unwrap().as_table().unwrap()[&name]; + let command = get_custom_preprocessor_cmd(&name, table); + Box::new(CmdPreprocessor::new(name, command)) + } + }; + preprocessors.push(preprocessor); + } + } + + // "If `pop_all` returns an empty vector and `len` is not 0, there are cyclic dependencies." + // Normally, `len() == 0` is equivalent to `is_empty()`, so we'll use that. + if preprocessor_names.is_empty() { + Ok(preprocessors) + } else { + Err(Error::msg("Cyclic dependency detected in preprocessors")) + } } -fn interpret_custom_preprocessor(key: &str, table: &Value) -> Box { - let command = table +fn get_custom_preprocessor_cmd(key: &str, table: &Value) -> String { + table .get("command") .and_then(Value::as_str) .map(ToString::to_string) - .unwrap_or_else(|| format!("mdbook-{}", key)); - - Box::new(CmdPreprocessor::new(key.to_string(), command)) + .unwrap_or_else(|| format!("mdbook-{}", key)) } fn interpret_custom_renderer(key: &str, table: &Value) -> Box { @@ -511,8 +602,8 @@ mod tests { assert!(got.is_ok()); assert_eq!(got.as_ref().unwrap().len(), 2); - assert_eq!(got.as_ref().unwrap()[0].name(), "links"); - assert_eq!(got.as_ref().unwrap()[1].name(), "index"); + assert_eq!(got.as_ref().unwrap()[0].name(), "index"); + assert_eq!(got.as_ref().unwrap()[1].name(), "links"); } #[test] @@ -559,9 +650,123 @@ mod tests { // make sure the `preprocessor.random` table exists let random = cfg.get_preprocessor("random").unwrap(); - let random = interpret_custom_preprocessor("random", &Value::Table(random.clone())); + let random = get_custom_preprocessor_cmd("random", &Value::Table(random.clone())); - assert_eq!(random.cmd(), "python random.py"); + assert_eq!(random, "python random.py"); + } + + #[test] + fn preprocessor_before_must_be_array() { + let cfg_str = r#" + [preprocessor.random] + before = 0 + "#; + + let cfg = Config::from_str(cfg_str).unwrap(); + + assert!(determine_preprocessors(&cfg).is_err()); + } + + #[test] + fn preprocessor_after_must_be_array() { + let cfg_str = r#" + [preprocessor.random] + after = 0 + "#; + + let cfg = Config::from_str(cfg_str).unwrap(); + + assert!(determine_preprocessors(&cfg).is_err()); + } + + #[test] + fn preprocessor_order_is_honored() { + let cfg_str = r#" + [preprocessor.random] + before = [ "last" ] + after = [ "index" ] + + [preprocessor.last] + after = [ "links", "index" ] + "#; + + let cfg = Config::from_str(cfg_str).unwrap(); + + let preprocessors = determine_preprocessors(&cfg).unwrap(); + let index = |name| { + preprocessors + .iter() + .enumerate() + .find(|(_, preprocessor)| preprocessor.name() == name) + .unwrap() + .0 + }; + let assert_before = |before, after| { + if index(before) >= index(after) { + eprintln!("Preprocessor order:"); + for preprocessor in &preprocessors { + eprintln!(" {}", preprocessor.name()); + } + panic!("{} should come before {}", before, after); + } + }; + + assert_before("index", "random"); + assert_before("index", "last"); + assert_before("random", "last"); + assert_before("links", "last"); + } + + #[test] + fn cyclic_dependencies_are_detected() { + let cfg_str = r#" + [preprocessor.links] + before = [ "index" ] + + [preprocessor.index] + before = [ "links" ] + "#; + + let cfg = Config::from_str(cfg_str).unwrap(); + + assert!(determine_preprocessors(&cfg).is_err()); + } + + #[test] + fn dependencies_dont_register_undefined_preprocessors() { + let cfg_str = r#" + [preprocessor.links] + before = [ "random" ] + "#; + + let cfg = Config::from_str(cfg_str).unwrap(); + + let preprocessors = determine_preprocessors(&cfg).unwrap(); + + assert!(preprocessors + .iter() + .find(|preprocessor| preprocessor.name() == "random") + .is_none()); + } + + #[test] + fn dependencies_dont_register_builtin_preprocessors_if_disabled() { + let cfg_str = r#" + [preprocessor.random] + before = [ "links" ] + + [build] + use-default-preprocessors = false + "#; + + let cfg = Config::from_str(cfg_str).unwrap(); + + let preprocessors = determine_preprocessors(&cfg).unwrap(); + + assert!(preprocessors + .iter() + .find(|preprocessor| preprocessor.name() == "links") + .is_none()); } #[test] diff --git a/src/book/summary.rs b/src/book/summary.rs index 822a7c76..981e1079 100644 --- a/src/book/summary.rs +++ b/src/book/summary.rs @@ -382,7 +382,7 @@ impl<'a> SummaryParser<'a> { } Some(ev @ Event::Start(Tag::List(..))) => { self.back(ev); - let mut bunch_of_items = self.parse_nested_numbered(&root_number)?; + let mut bunch_of_items = self.parse_nested_numbered(root_number)?; // if we've resumed after something like a rule the root sections // will be numbered from 1. We need to manually go back and update diff --git a/src/cmd/init.rs b/src/cmd/init.rs index cccc1671..ed0aa17d 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -1,5 +1,5 @@ use crate::get_book_dir; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, Arg, ArgMatches, SubCommand}; use mdbook::config; use mdbook::errors::Result; use mdbook::MDBook; @@ -18,6 +18,21 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { ) .arg_from_usage("--theme 'Copies the default theme into your source folder'") .arg_from_usage("--force 'Skips confirmation prompts'") + .arg( + Arg::with_name("title") + .long("title") + .takes_value(true) + .help("Sets the book title") + .required(false), + ) + .arg( + Arg::with_name("ignore") + .long("ignore") + .takes_value(true) + .possible_values(&["none", "git"]) + .help("Creates a VCS ignore file (i.e. .gitignore)") + .required(false), + ) } // Init command implementation @@ -25,7 +40,6 @@ pub fn execute(args: &ArgMatches) -> Result<()> { let book_dir = get_book_dir(args); let mut builder = MDBook::init(&book_dir); let mut config = config::Config::default(); - // If flag `--theme` is present, copy theme to src if args.is_present("theme") { let theme_dir = book_dir.join("theme"); @@ -45,13 +59,23 @@ pub fn execute(args: &ArgMatches) -> Result<()> { } } - println!("\nDo you want a .gitignore to be created? (y/n)"); - - if confirm() { - builder.create_gitignore(true); + if let Some(ignore) = args.value_of("ignore") { + match ignore { + "git" => builder.create_gitignore(true), + _ => builder.create_gitignore(false), + }; + } else { + println!("\nDo you want a .gitignore to be created? (y/n)"); + if confirm() { + builder.create_gitignore(true); + } } - config.book.title = request_book_title(); + config.book.title = if args.is_present("title") { + args.value_of("title").map(String::from) + } else { + request_book_title() + }; if let Some(author) = get_author_name() { debug!("Obtained user name from gitconfig: {:?}", author); diff --git a/src/config.rs b/src/config.rs index c384192c..bf4aabbb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -467,6 +467,9 @@ pub struct RustConfig { #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] /// Rust edition to use for the code. pub enum RustEdition { + /// The 2021 edition of Rust + #[serde(rename = "2021")] + E2021, /// The 2018 edition of Rust #[serde(rename = "2018")] E2018, @@ -855,6 +858,26 @@ mod tests { assert_eq!(got.rust, rust_should_be); } + #[test] + fn edition_2021() { + let src = r#" + [book] + title = "mdBook Documentation" + description = "Create book from markdown files. Like Gitbook but implemented in Rust" + authors = ["Mathieu David"] + src = "./source" + [rust] + edition = "2021" + "#; + + let rust_should_be = RustConfig { + edition: Some(RustEdition::E2021), + }; + + let got = Config::from_str(src).unwrap(); + assert_eq!(got.rust, rust_should_be); + } + #[test] fn load_arbitrary_output_type() { #[derive(Debug, Deserialize, PartialEq)] diff --git a/src/main.rs b/src/main.rs index 76a46fa6..1f286d2d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,9 @@ extern crate clap; #[macro_use] extern crate log; +use anyhow::anyhow; use chrono::Local; -use clap::{App, AppSettings, ArgMatches}; +use clap::{App, AppSettings, Arg, ArgMatches, Shell, SubCommand}; use env_logger::Builder; use log::LevelFilter; use mdbook::utils; @@ -20,7 +21,40 @@ const VERSION: &str = concat!("v", crate_version!()); fn main() { init_logger(); - // Create a list of valid arguments and sub-commands + let app = create_clap_app(); + + // Check which subcomamnd the user ran... + let res = match app.get_matches().subcommand() { + ("init", Some(sub_matches)) => cmd::init::execute(sub_matches), + ("build", Some(sub_matches)) => cmd::build::execute(sub_matches), + ("clean", Some(sub_matches)) => cmd::clean::execute(sub_matches), + #[cfg(feature = "watch")] + ("watch", Some(sub_matches)) => cmd::watch::execute(sub_matches), + #[cfg(feature = "serve")] + ("serve", Some(sub_matches)) => cmd::serve::execute(sub_matches), + ("test", Some(sub_matches)) => cmd::test::execute(sub_matches), + ("completions", Some(sub_matches)) => (|| { + let shell: Shell = sub_matches + .value_of("shell") + .ok_or_else(|| anyhow!("Shell name missing."))? + .parse() + .map_err(|s| anyhow!("Invalid shell: {}", s))?; + + create_clap_app().gen_completions_to("mdbook", shell, &mut std::io::stdout().lock()); + Ok(()) + })(), + (_, _) => unreachable!(), + }; + + if let Err(e) = res { + utils::log_backtrace(&e); + + std::process::exit(101); + } +} + +/// Create a list of valid arguments and sub-commands +fn create_clap_app<'a, 'b>() -> App<'a, 'b> { let app = App::new(crate_name!()) .about(crate_description!()) .author("Mathieu David ") @@ -35,31 +69,26 @@ fn main() { .subcommand(cmd::init::make_subcommand()) .subcommand(cmd::build::make_subcommand()) .subcommand(cmd::test::make_subcommand()) - .subcommand(cmd::clean::make_subcommand()); + .subcommand(cmd::clean::make_subcommand()) + .subcommand( + SubCommand::with_name("completions") + .about("Generate shell completions for your shell to stdout") + .arg( + Arg::with_name("shell") + .takes_value(true) + .possible_values(&Shell::variants()) + .help("the shell to generate completions for") + .value_name("SHELL") + .required(true), + ), + ); #[cfg(feature = "watch")] let app = app.subcommand(cmd::watch::make_subcommand()); #[cfg(feature = "serve")] let app = app.subcommand(cmd::serve::make_subcommand()); - // Check which subcomamnd the user ran... - let res = match app.get_matches().subcommand() { - ("init", Some(sub_matches)) => cmd::init::execute(sub_matches), - ("build", Some(sub_matches)) => cmd::build::execute(sub_matches), - ("clean", Some(sub_matches)) => cmd::clean::execute(sub_matches), - #[cfg(feature = "watch")] - ("watch", Some(sub_matches)) => cmd::watch::execute(sub_matches), - #[cfg(feature = "serve")] - ("serve", Some(sub_matches)) => cmd::serve::execute(sub_matches), - ("test", Some(sub_matches)) => cmd::test::execute(sub_matches), - (_, _) => unreachable!(), - }; - - if let Err(e) = res { - utils::log_backtrace(&e); - - std::process::exit(101); - } + app } fn init_logger() { @@ -103,7 +132,8 @@ fn get_book_dir(args: &ArgMatches) -> PathBuf { } fn open>(path: P) { - if let Err(e) = open::that(path) { + info!("Opening web browser"); + if let Err(e) = opener::open(path) { error!("Error opening web browser: {}", e); } } diff --git a/src/preprocess/cmd.rs b/src/preprocess/cmd.rs index 44654ffe..c47fd5d2 100644 --- a/src/preprocess/cmd.rs +++ b/src/preprocess/cmd.rs @@ -49,7 +49,7 @@ impl CmdPreprocessor { fn write_input_to_child(&self, child: &mut Child, book: &Book, ctx: &PreprocessorContext) { let stdin = child.stdin.take().expect("Child has stdin"); - if let Err(e) = self.write_input(stdin, &book, &ctx) { + if let Err(e) = self.write_input(stdin, book, ctx) { // Looks like the backend hung up before we could finish // sending it the render context. Log the error and keep going warn!("Error writing the RenderContext to the backend, {}", e); diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index bc7c1a92..e8da5b4a 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -54,16 +54,14 @@ impl HtmlHandlebars { let content = ch.content.clone(); let content = utils::render_markdown(&content, ctx.html_config.curly_quotes); - let fixed_content = utils::render_markdown_with_path( - &ch.content, - ctx.html_config.curly_quotes, - Some(&path), - ); + let fixed_content = + utils::render_markdown_with_path(&ch.content, ctx.html_config.curly_quotes, Some(path)); if !ctx.is_index { // Add page break between chapters // See https://developer.mozilla.org/en-US/docs/Web/CSS/break-before and https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-before // Add both two CSS properties because of the compatibility issue - print_content.push_str(r#"
"#); + print_content + .push_str(r#"
"#); } print_content.push_str(&fixed_content); @@ -177,7 +175,7 @@ impl HtmlHandlebars { let rendered = self.post_process(rendered, &html_config.playground, ctx.config.rust.edition); let output_file = get_404_output_file(&html_config.input_404); - utils::fs::write_file(&destination, output_file, rendered.as_bytes())?; + utils::fs::write_file(destination, output_file, rendered.as_bytes())?; debug!("Creating 404.html ✓"); Ok(()) } @@ -222,10 +220,10 @@ impl HtmlHandlebars { } write_file(destination, "css/variables.css", &theme.variables_css)?; if let Some(contents) = &theme.favicon_png { - write_file(destination, "favicon.png", &contents)?; + write_file(destination, "favicon.png", contents)?; } if let Some(contents) = &theme.favicon_svg { - write_file(destination, "favicon.svg", &contents)?; + write_file(destination, "favicon.svg", contents)?; } write_file(destination, "highlight.css", &theme.highlight_css)?; write_file(destination, "tomorrow-night.css", &theme.tomorrow_night_css)?; @@ -508,7 +506,7 @@ impl Renderer for HtmlHandlebars { debug!("Register handlebars helpers"); self.register_hbs_helpers(&mut handlebars, &html_config); - let mut data = make_data(&ctx.root, &book, &ctx.config, &html_config, &theme)?; + let mut data = make_data(&ctx.root, book, &ctx.config, &html_config, &theme)?; // Print version let mut print_content = String::new(); @@ -551,14 +549,14 @@ impl Renderer for HtmlHandlebars { let rendered = self.post_process(rendered, &html_config.playground, ctx.config.rust.edition); - utils::fs::write_file(&destination, "print.html", rendered.as_bytes())?; + utils::fs::write_file(destination, "print.html", rendered.as_bytes())?; debug!("Creating print.html ✓"); } debug!("Copy static files"); - self.copy_static_files(&destination, &theme, &html_config) + self.copy_static_files(destination, &theme, &html_config) .with_context(|| "Unable to copy across static files")?; - self.copy_additional_css_and_js(&html_config, &ctx.root, &destination) + self.copy_additional_css_and_js(&html_config, &ctx.root, destination) .with_context(|| "Unable to copy across additional CSS and JS")?; // Render search index @@ -566,7 +564,7 @@ impl Renderer for HtmlHandlebars { { let search = html_config.search.unwrap_or_default(); if search.enable { - super::search::create_files(&search, &destination, &book)?; + super::search::create_files(&search, destination, book)?; } } @@ -574,7 +572,7 @@ impl Renderer for HtmlHandlebars { .context("Unable to emit redirects")?; // Copy all remaining files, avoid a recursive copy from/to the book build dir - utils::fs::copy_files_except_ext(&src_dir, &destination, true, Some(&build_dir), &["md"])?; + utils::fs::copy_files_except_ext(&src_dir, destination, true, Some(&build_dir), &["md"])?; Ok(()) } @@ -835,13 +833,15 @@ fn add_playground_pre( { let contains_e2015 = classes.contains("edition2015"); let contains_e2018 = classes.contains("edition2018"); - let edition_class = if contains_e2015 || contains_e2018 { + let contains_e2021 = classes.contains("edition2021"); + let edition_class = if contains_e2015 || contains_e2018 || contains_e2021 { // the user forced edition, we should not overwrite it "" } else { match edition { Some(RustEdition::E2015) => " edition2015", Some(RustEdition::E2018) => " edition2018", + Some(RustEdition::E2021) => " edition2021", None => "", } }; @@ -980,7 +980,7 @@ mod tests { ]; for (src, should_be) in inputs { - let got = build_header_links(&src); + let got = build_header_links(src); assert_eq!(got, should_be); } } @@ -1063,4 +1063,28 @@ mod tests { assert_eq!(&*got, *should_be); } } + #[test] + fn add_playground_edition2021() { + let inputs = [ + ("x()", + "
\n#![allow(unused)]\nfn main() {\nx()\n}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ]; + for (src, should_be) in &inputs { + let got = add_playground_pre( + src, + &Playground { + editable: true, + ..Playground::default() + }, + Some(RustEdition::E2021), + ); + assert_eq!(&*got, *should_be); + } + } } diff --git a/src/renderer/html_handlebars/helpers/navigation.rs b/src/renderer/html_handlebars/helpers/navigation.rs index 3ff99560..83bdadb3 100644 --- a/src/renderer/html_handlebars/helpers/navigation.rs +++ b/src/renderer/html_handlebars/helpers/navigation.rs @@ -91,7 +91,7 @@ fn find_chapter( match item.get("path") { Some(path) if !path.is_empty() => { if let Some(previous) = previous { - if let Some(item) = target.find(&base_path, &path, &item, &previous)? { + if let Some(item) = target.find(&base_path, path, &item, &previous)? { return Ok(Some(item)); } } diff --git a/src/renderer/html_handlebars/helpers/toc.rs b/src/renderer/html_handlebars/helpers/toc.rs index bde5383e..a2ea501d 100644 --- a/src/renderer/html_handlebars/helpers/toc.rs +++ b/src/renderer/html_handlebars/helpers/toc.rs @@ -142,7 +142,7 @@ impl HelperDef for RenderToc { // Section does not necessarily exist if let Some(section) = item.get("section") { out.write("")?; - out.write(§ion)?; + out.write(section)?; out.write(" ")?; } } diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs index e9da2196..5d9a5dc9 100644 --- a/src/renderer/html_handlebars/search.rs +++ b/src/renderer/html_handlebars/search.rs @@ -17,10 +17,10 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> let mut doc_urls = Vec::with_capacity(book.sections.len()); for item in book.iter() { - render_item(&mut index, &search_config, &mut doc_urls, item)?; + render_item(&mut index, search_config, &mut doc_urls, item)?; } - let index = write_to_json(index, &search_config, doc_urls)?; + let index = write_to_json(index, search_config, doc_urls)?; debug!("Writing search index ✓"); if index.len() > 10_000_000 { warn!("searchindex.json is very large ({} bytes)", index.len()); @@ -134,7 +134,7 @@ fn render_item( // in an HtmlBlock tag. We must collect consecutive Html events // into a block ourselves. while let Some(Event::Html(html)) = p.peek() { - html_block.push_str(&html); + html_block.push_str(html); p.next(); } @@ -165,7 +165,12 @@ fn render_item( } } - if !heading.is_empty() { + if !body.is_empty() || !heading.is_empty() { + if heading.is_empty() { + if let Some(chapter) = breadcrumbs.first() { + heading = chapter.clone(); + } + } // Make sure the last section is added to the index add_doc( index, diff --git a/src/theme/book.js b/src/theme/book.js index 5e386369..d40440c7 100644 --- a/src/theme/book.js +++ b/src/theme/book.js @@ -108,9 +108,12 @@ function playground_text(playground) { let text = playground_text(code_block); let classes = code_block.querySelector('code').classList; - let has_2018 = classes.contains("edition2018"); - let edition = has_2018 ? "2018" : "2015"; - + let edition = "2015"; + if(classes.contains("edition2018")) { + edition = "2018"; + } else if(classes.contains("edition2021")) { + edition = "2021"; + } var params = { version: "stable", optimize: "0", @@ -133,7 +136,15 @@ function playground_text(playground) { body: JSON.stringify(params) }) .then(response => response.json()) - .then(response => result_block.innerText = response.result) + .then(response => { + if (response.result.trim() === '') { + result_block.innerText = "No output"; + result_block.classList.add("result-no-output"); + } else { + result_block.innerText = response.result; + result_block.classList.remove("result-no-output"); + } + }) .catch(error => result_block.innerText = "Playground Communication: " + error.message); } @@ -151,12 +162,13 @@ function playground_text(playground) { if (window.ace) { // language-rust class needs to be removed for editable // blocks or highlightjs will capture events - Array - .from(document.querySelectorAll('code.editable')) + code_nodes + .filter(function (node) {return node.classList.contains("editable"); }) .forEach(function (block) { block.classList.remove('language-rust'); }); Array - .from(document.querySelectorAll('code:not(.editable)')) + code_nodes + .filter(function (node) {return !node.classList.contains("editable"); }) .forEach(function (block) { hljs.highlightBlock(block); }); } else { code_nodes.forEach(function (block) { hljs.highlightBlock(block); }); @@ -359,7 +371,14 @@ function playground_text(playground) { }); themePopup.addEventListener('click', function (e) { - var theme = e.target.id || e.target.parentElement.id; + var theme; + if (e.target.className === "theme") { + theme = e.target.id; + } else if (e.target.parentElement.className === "theme") { + theme = e.target.parentElement.id; + } else { + return; + } set_theme(theme); }); diff --git a/src/theme/css/general.css b/src/theme/css/general.css index 2cf347f9..63317b39 100644 --- a/src/theme/css/general.css +++ b/src/theme/css/general.css @@ -175,3 +175,7 @@ blockquote { margin: 5px 0px; font-weight: bold; } + +.result-no-output { + font-style: italic; +} diff --git a/src/theme/css/variables.css b/src/theme/css/variables.css index 9ff64d6b..56b634bc 100644 --- a/src/theme/css/variables.css +++ b/src/theme/css/variables.css @@ -67,7 +67,7 @@ --links: #2b79a2; - --inline-code-color: #c5c8c6;; + --inline-code-color: #c5c8c6; --theme-popup-bg: #141617; --theme-popup-border: #43484d; @@ -147,7 +147,7 @@ --links: #2b79a2; - --inline-code-color: #c5c8c6;; + --inline-code-color: #c5c8c6; --theme-popup-bg: #161923; --theme-popup-border: #737480; @@ -228,7 +228,7 @@ --links: #2b79a2; - --inline-code-color: #c5c8c6;; + --inline-code-color: #c5c8c6; --theme-popup-bg: #141617; --theme-popup-border: #43484d; diff --git a/src/utils/fs.rs b/src/utils/fs.rs index 2d5ce8b7..a933d548 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -247,7 +247,7 @@ mod tests { } if let Err(e) = - copy_files_except_ext(&tmp.path(), &tmp.path().join("output"), true, None, &["md"]) + copy_files_except_ext(tmp.path(), &tmp.path().join("output"), true, None, &["md"]) { panic!("Error while executing the function:\n{:?}", e); } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 7453f2f2..2352517a 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -228,7 +228,14 @@ impl EventQuoteConverter { fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> { match event { Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => { - let info: String = info.chars().filter(|ch| !ch.is_whitespace()).collect(); + let info: String = info + .chars() + .map(|x| match x { + ' ' | '\t' => ',', + _ => x, + }) + .filter(|ch| !ch.is_whitespace()) + .collect(); Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(CowStr::from(info)))) } @@ -372,7 +379,7 @@ more text with spaces ``` "#; - let expected = r#"
+ let expected = r#"
"#; assert_eq!(render_markdown(input, false), expected); assert_eq!(render_markdown(input, true), expected); diff --git a/tests/cli/build.rs b/tests/cli/build.rs new file mode 100644 index 00000000..16b6b79b --- /dev/null +++ b/tests/cli/build.rs @@ -0,0 +1,29 @@ +use crate::dummy_book::DummyBook; + +use assert_cmd::Command; + +#[test] +fn mdbook_cli_dummy_book_generates_index_html() { + let temp = DummyBook::new().build().unwrap(); + + // doesn't exist before + assert!(!temp.path().join("book").exists()); + + let mut cmd = Command::cargo_bin("mdbook").unwrap(); + cmd.arg("build").current_dir(temp.path()); + cmd.assert() + .success() + .stderr( + predicates::str::is_match(r##"Stack depth exceeded in first[\\/]recursive.md."##) + .unwrap(), + ) + .stderr(predicates::str::contains( + r##"[INFO] (mdbook::book): Running the html backend"##, + )); + + // exists afterward + assert!(temp.path().join("book").exists()); + + let index_file = temp.path().join("book/index.html"); + assert!(index_file.exists()); +} diff --git a/tests/cli/mod.rs b/tests/cli/mod.rs new file mode 100644 index 00000000..a73a4031 --- /dev/null +++ b/tests/cli/mod.rs @@ -0,0 +1,2 @@ +mod build; +mod test; diff --git a/tests/cli/test.rs b/tests/cli/test.rs new file mode 100644 index 00000000..d974654d --- /dev/null +++ b/tests/cli/test.rs @@ -0,0 +1,34 @@ +use crate::dummy_book::DummyBook; + +use assert_cmd::Command; +use predicates::boolean::PredicateBooleanExt; + +#[test] +fn mdbook_cli_can_correctly_test_a_passing_book() { + let temp = DummyBook::new().with_passing_test(true).build().unwrap(); + + let mut cmd = Command::cargo_bin("mdbook").unwrap(); + cmd.arg("test").current_dir(temp.path()); + cmd.assert().success() + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]README.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]intro.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]first[\\/]index.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]first[\\/]nested.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"rustdoc returned an error:\n\n"##).unwrap().not()) + .stderr(predicates::str::is_match(r##"Nested_Chapter::Rustdoc_include_works_with_anchors_too \(line \d+\) ... FAILED"##).unwrap().not()); +} + +#[test] +fn mdbook_cli_detects_book_with_failing_tests() { + let temp = DummyBook::new().with_passing_test(false).build().unwrap(); + + let mut cmd = Command::cargo_bin("mdbook").unwrap(); + cmd.arg("test").current_dir(temp.path()); + cmd.assert().failure() + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]README.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]intro.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]first[\\/]index.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"Testing file: "([^"]+)[\\/]first[\\/]nested.md""##).unwrap()) + .stderr(predicates::str::is_match(r##"rustdoc returned an error:\n\n"##).unwrap()) + .stderr(predicates::str::is_match(r##"Nested_Chapter::Rustdoc_include_works_with_anchors_too \(line \d+\) ... FAILED"##).unwrap()); +} diff --git a/tests/cli_tests.rs b/tests/cli_tests.rs new file mode 100644 index 00000000..0b005d01 --- /dev/null +++ b/tests/cli_tests.rs @@ -0,0 +1,2 @@ +mod cli; +mod dummy_book; diff --git a/tests/dummy_book/src/SUMMARY.md b/tests/dummy_book/src/SUMMARY.md index 7e9d3d1f..e12e1254 100644 --- a/tests/dummy_book/src/SUMMARY.md +++ b/tests/dummy_book/src/SUMMARY.md @@ -12,6 +12,7 @@ - [Recursive](first/recursive.md) - [Markdown](first/markdown.md) - [Unicode](first/unicode.md) + - [No Headers](first/no-headers.md) - [Second Chapter](second.md) - [Nested Chapter](second/nested.md) diff --git a/tests/dummy_book/src/first/no-headers.md b/tests/dummy_book/src/first/no-headers.md new file mode 100644 index 00000000..8f9a6d17 --- /dev/null +++ b/tests/dummy_book/src/first/no-headers.md @@ -0,0 +1,3 @@ +Capybara capybara capybara. + +Capybara capybara capybara. \ No newline at end of file diff --git a/tests/rendered_output.rs b/tests/rendered_output.rs index c6f998d6..5ec6e64b 100644 --- a/tests/rendered_output.rs +++ b/tests/rendered_output.rs @@ -34,6 +34,7 @@ const TOC_SECOND_LEVEL: &[&str] = &[ "1.3. Recursive", "1.4. Markdown", "1.5. Unicode", + "1.6. No Headers", "2.1. Nested Chapter", ]; @@ -264,7 +265,7 @@ fn root_index_html() -> Result { fn check_second_toc_level() { let doc = root_index_html().unwrap(); let mut should_be = Vec::from(TOC_SECOND_LEVEL); - should_be.sort(); + should_be.sort_unstable(); let pred = descendants!( Class("chapter"), @@ -288,7 +289,7 @@ fn check_first_toc_level() { let mut should_be = Vec::from(TOC_TOP_LEVEL); should_be.extend(TOC_SECOND_LEVEL); - should_be.sort(); + should_be.sort_unstable(); let pred = descendants!( Class("chapter"), @@ -535,7 +536,7 @@ fn redirects_are_emitted_correctly() { let mut redirect_file = md.build_dir_for("html"); // append everything except the bits that make it absolute // (e.g. "/" or "C:\") - redirect_file.extend(remove_absolute_components(&original)); + redirect_file.extend(remove_absolute_components(original)); let contents = fs::read_to_string(&redirect_file).unwrap(); assert!(contents.contains(redirect)); } @@ -552,7 +553,7 @@ fn edit_url_has_default_src_dir_edit_url() { edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}" "#; - write_file(&temp.path(), "book.toml", book_toml.as_bytes()).unwrap(); + write_file(temp.path(), "book.toml", book_toml.as_bytes()).unwrap(); let md = MDBook::load(temp.path()).unwrap(); md.build().unwrap(); @@ -560,7 +561,7 @@ fn edit_url_has_default_src_dir_edit_url() { let index_html = temp.path().join("book").join("index.html"); assert_contains_strings( index_html, - &vec![ + &[ r#"href="https://github.com/rust-lang/mdBook/edit/master/guide/src/README.md" title="Suggest an edit""#, ], ); @@ -578,7 +579,7 @@ fn edit_url_has_configured_src_dir_edit_url() { edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}" "#; - write_file(&temp.path(), "book.toml", book_toml.as_bytes()).unwrap(); + write_file(temp.path(), "book.toml", book_toml.as_bytes()).unwrap(); let md = MDBook::load(temp.path()).unwrap(); md.build().unwrap(); @@ -586,7 +587,7 @@ fn edit_url_has_configured_src_dir_edit_url() { let index_html = temp.path().join("book").join("index.html"); assert_contains_strings( index_html, - &vec![ + &[ r#"href="https://github.com/rust-lang/mdBook/edit/master/guide/src2/README.md" title="Suggest an edit""#, ], ); @@ -611,7 +612,7 @@ mod search { let index = fs::read_to_string(index).unwrap(); let index = index.trim_start_matches("Object.assign(window.search, "); let index = index.trim_end_matches(");"); - serde_json::from_str(&index).unwrap() + serde_json::from_str(index).unwrap() } #[test] @@ -631,6 +632,7 @@ mod search { let introduction = get_doc_ref("intro.html#introduction"); let some_section = get_doc_ref("first/index.html#some-section"); let summary = get_doc_ref("first/includes.html#summary"); + let no_headers = get_doc_ref("first/no-headers.html"); let conclusion = get_doc_ref("conclusion.html#conclusion"); let bodyidx = &index["index"]["index"]["body"]["root"]; @@ -644,13 +646,21 @@ mod search { assert_eq!(docs[&some_section]["body"], ""); assert_eq!( docs[&summary]["body"], - "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode Second Chapter Nested Chapter Conclusion" + "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode No Headers Second Chapter Nested Chapter Conclusion" ); assert_eq!( docs[&summary]["breadcrumbs"], "First Chapter » Includes » Summary" ); assert_eq!(docs[&conclusion]["body"], "I put <HTML> in here!"); + assert_eq!( + docs[&no_headers]["breadcrumbs"], + "First Chapter » No Headers" + ); + assert_eq!( + docs[&no_headers]["body"], + "Capybara capybara capybara. Capybara capybara capybara." + ); } // Setting this to `true` may cause issues with `cargo watch`, diff --git a/tests/searchindex_fixture.json b/tests/searchindex_fixture.json index 7e7e3359..32c44a1b 100644 --- a/tests/searchindex_fixture.json +++ b/tests/searchindex_fixture.json @@ -11,12 +11,14 @@ "first/nested.html#rustdoc-include-works-with-anchors-too", "first/includes.html#includes", "first/includes.html#summary", + "first/recursive.html", "first/markdown.html#markdown-tests", "first/markdown.html#tables", "first/markdown.html#footnotes", "first/markdown.html#strikethrough", "first/markdown.html#tasklisks", "first/unicode.html#unicode-stress-tests", + "first/no-headers.html", "second.html#second-chapter", "second/nested.html#testing-relative-links-for-the-print-page", "second/nested.html#some-section", @@ -36,61 +38,71 @@ "title": 1 }, "10": { - "body": 16, + "body": 17, "breadcrumbs": 4, "title": 1 }, "11": { + "body": 44, + "breadcrumbs": 3, + "title": 2 + }, + "12": { "body": 3, "breadcrumbs": 5, "title": 2 }, - "12": { + "13": { "body": 4, "breadcrumbs": 4, "title": 1 }, - "13": { + "14": { "body": 12, "breadcrumbs": 4, "title": 1 }, - "14": { + "15": { "body": 2, "breadcrumbs": 4, "title": 1 }, - "15": { + "16": { "body": 3, "breadcrumbs": 4, "title": 1 }, - "16": { + "17": { "body": 29, "breadcrumbs": 6, "title": 3 }, - "17": { + "18": { + "body": 6, + "breadcrumbs": 3, + "title": 2 + }, + "19": { "body": 20, "breadcrumbs": 4, "title": 2 }, - "18": { - "body": 18, - "breadcrumbs": 9, - "title": 5 - }, - "19": { - "body": 0, - "breadcrumbs": 5, - "title": 1 - }, "2": { "body": 2, "breadcrumbs": 4, "title": 2 }, "20": { + "body": 18, + "breadcrumbs": 9, + "title": 5 + }, + "21": { + "body": 0, + "breadcrumbs": 5, + "title": 1 + }, + "22": { "body": 3, "breadcrumbs": 2, "title": 1 @@ -145,64 +157,64 @@ "title": "Introduction" }, "10": { - "body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode Second Chapter Nested Chapter Conclusion", + "body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode No Headers Second Chapter Nested Chapter Conclusion", "breadcrumbs": "First Chapter » Includes » Summary", "id": "10", "title": "Summary" }, "11": { - "body": "Tests for some markdown output.", - "breadcrumbs": "First Chapter » Markdown » Markdown tests", + "body": "Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world Around the world, around the world", + "breadcrumbs": "First Chapter » Recursive", "id": "11", - "title": "Markdown tests" + "title": "First Chapter" }, "12": { - "body": "foo bar baz bim", - "breadcrumbs": "First Chapter » Markdown » Tables", + "body": "Tests for some markdown output.", + "breadcrumbs": "First Chapter » Markdown » Markdown tests", "id": "12", - "title": "Tables" + "title": "Markdown tests" }, "13": { - "body": "Footnote example [1] , or with a word [2] . This is a footnote. A longer footnote. With multiple lines. Third line.", - "breadcrumbs": "First Chapter » Markdown » Footnotes", + "body": "foo bar baz bim", + "breadcrumbs": "First Chapter » Markdown » Tables", "id": "13", - "title": "Footnotes" + "title": "Tables" }, "14": { - "body": "strikethrough example", - "breadcrumbs": "First Chapter » Markdown » Strikethrough", + "body": "Footnote example [1] , or with a word [2] . This is a footnote. A longer footnote. With multiple lines. Third line.", + "breadcrumbs": "First Chapter » Markdown » Footnotes", "id": "14", - "title": "Strikethrough" + "title": "Footnotes" }, "15": { - "body": "Apples Broccoli Carrots", - "breadcrumbs": "First Chapter » Markdown » Tasklisks", + "body": "strikethrough example", + "breadcrumbs": "First Chapter » Markdown » Strikethrough", "id": "15", - "title": "Tasklisks" + "title": "Strikethrough" }, "16": { - "body": "Please be careful editing, this contains carefully crafted characters. Two byte character: spatiëring Combining character: spatiëring Three byte character: 书こんにちは Four byte character: 𐌀‮𐌁‮𐌂‮𐌃‮𐌄‮𐌅‮𐌆‮𐌇‮𐌈‬ Right-to-left: مرحبا Emoticons: 🔊 😍 💜 1️⃣ right-to-left mark: hello באמת!‏ Zalgo: ǫ̛̖̱̗̝͈̋͒͋̏ͥͫ̒̆ͩ̏͌̾͊͐ͪ̾̚", - "breadcrumbs": "First Chapter » Unicode » Unicode stress tests", + "body": "Apples Broccoli Carrots", + "breadcrumbs": "First Chapter » Markdown » Tasklisks", "id": "16", - "title": "Unicode stress tests" + "title": "Tasklisks" }, "17": { - "body": "This makes sure you can insert runnable Rust files. fn main() { println!(\"Hello World!\");\n#\n# // You can even hide lines! :D\n# println!(\"I am hidden! Expand the code snippet to see me\");\n}", - "breadcrumbs": "Second Chapter » Second Chapter", + "body": "Please be careful editing, this contains carefully crafted characters. Two byte character: spatiëring Combining character: spatiëring Three byte character: 书こんにちは Four byte character: 𐌀‮𐌁‮𐌂‮𐌃‮𐌄‮𐌅‮𐌆‮𐌇‮𐌈‬ Right-to-left: مرحبا Emoticons: 🔊 😍 💜 1️⃣ right-to-left mark: hello באמת!‏ Zalgo: ǫ̛̖̱̗̝͈̋͒͋̏ͥͫ̒̆ͩ̏͌̾͊͐ͪ̾̚", + "breadcrumbs": "First Chapter » Unicode » Unicode stress tests", "id": "17", - "title": "Second Chapter" + "title": "Unicode stress tests" }, "18": { - "body": "When we link to the first section , it should work on both the print page and the non-print page. A fragment link should work. Link outside . Some image HTML Link", - "breadcrumbs": "Second Chapter » Nested Chapter » Testing relative links for the print page", + "body": "Capybara capybara capybara. Capybara capybara capybara.", + "breadcrumbs": "First Chapter » No Headers", "id": "18", - "title": "Testing relative links for the print page" + "title": "First Chapter" }, "19": { - "body": "", - "breadcrumbs": "Second Chapter » Nested Chapter » Some section", + "body": "This makes sure you can insert runnable Rust files. fn main() { println!(\"Hello World!\");\n#\n# // You can even hide lines! :D\n# println!(\"I am hidden! Expand the code snippet to see me\");\n}", + "breadcrumbs": "Second Chapter » Second Chapter", "id": "19", - "title": "Some section" + "title": "Second Chapter" }, "2": { "body": "more text.", @@ -211,9 +223,21 @@ "title": "First Chapter" }, "20": { + "body": "When we link to the first section , it should work on both the print page and the non-print page. A fragment link should work. Link outside . Some image HTML Link", + "breadcrumbs": "Second Chapter » Nested Chapter » Testing relative links for the print page", + "id": "20", + "title": "Testing relative links for the print page" + }, + "21": { + "body": "", + "breadcrumbs": "Second Chapter » Nested Chapter » Some section", + "id": "21", + "title": "Some section" + }, + "22": { "body": "I put <HTML> in here!", "breadcrumbs": "Conclusion » Conclusion", - "id": "20", + "id": "22", "title": "Conclusion" }, "3": { @@ -259,7 +283,7 @@ "title": "Includes" } }, - "length": 21, + "length": 23, "save": true }, "fields": [ @@ -273,10 +297,10 @@ "1": { "df": 2, "docs": { - "13": { + "14": { "tf": 1.0 }, - "16": { + "17": { "tf": 1.0 } } @@ -284,7 +308,7 @@ "2": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -340,13 +364,37 @@ "l": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } } } }, + "r": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "n": { + "d": { + "df": 1, + "docs": { + "11": { + "tf": 4.69041575982343 + } + } + }, + "df": 0, + "docs": {} + } + } + } + }, "s": { "df": 0, "docs": {}, @@ -411,7 +459,7 @@ "r": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -419,7 +467,7 @@ "z": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -461,7 +509,7 @@ "m": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -491,7 +539,7 @@ "h": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -515,7 +563,7 @@ "i": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } @@ -555,7 +603,7 @@ "e": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.7320508075688772 } } @@ -567,13 +615,41 @@ "a": { "df": 0, "docs": {}, + "p": { + "df": 0, + "docs": {}, + "y": { + "b": { + "a": { + "df": 0, + "docs": {}, + "r": { + "a": { + "df": 1, + "docs": { + "18": { + "tf": 2.449489742783178 + } + } + }, + "df": 0, + "docs": {} + } + }, + "df": 0, + "docs": {} + }, + "df": 0, + "docs": {} + } + }, "r": { "df": 0, "docs": {}, "e": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } }, @@ -592,7 +668,7 @@ "i": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -611,7 +687,7 @@ "t": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } @@ -651,12 +727,18 @@ "df": 0, "docs": {}, "r": { - "df": 4, + "df": 6, "docs": { "10": { "tf": 2.0 }, - "17": { + "11": { + "tf": 1.0 + }, + "18": { + "tf": 1.0 + }, + "19": { "tf": 1.0 }, "2": { @@ -678,7 +760,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 2.23606797749979 } } @@ -701,7 +783,7 @@ "e": { "df": 2, "docs": { - "17": { + "19": { "tf": 1.0 }, "4": { @@ -722,7 +804,7 @@ "n": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -768,7 +850,7 @@ "10": { "tf": 1.0 }, - "20": { + "22": { "tf": 1.0 } } @@ -788,7 +870,7 @@ "n": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -826,7 +908,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -840,7 +922,7 @@ "d": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } }, @@ -880,7 +962,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -908,7 +990,7 @@ "n": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -930,7 +1012,7 @@ "n": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -950,10 +1032,10 @@ "l": { "df": 2, "docs": { - "13": { + "14": { "tf": 1.0 }, - "14": { + "15": { "tf": 1.0 } } @@ -971,7 +1053,7 @@ "d": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -1040,7 +1122,7 @@ "0": { "tf": 1.0 }, - "17": { + "19": { "tf": 1.0 }, "4": { @@ -1062,16 +1144,22 @@ "df": 0, "docs": {}, "t": { - "df": 3, + "df": 5, "docs": { "10": { "tf": 1.0 }, + "11": { + "tf": 1.0 + }, "18": { "tf": 1.0 }, "2": { "tf": 1.0 + }, + "20": { + "tf": 1.0 } } } @@ -1081,7 +1169,7 @@ "n": { "df": 3, "docs": { - "17": { + "19": { "tf": 1.0 }, "7": { @@ -1098,7 +1186,7 @@ "o": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } }, @@ -1114,7 +1202,7 @@ "t": { "df": 1, "docs": { - "13": { + "14": { "tf": 2.0 } } @@ -1129,7 +1217,7 @@ "r": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -1155,7 +1243,7 @@ "t": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -1193,6 +1281,26 @@ "df": 0, "docs": {}, "e": { + "a": { + "d": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "r": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + } + } + }, + "df": 0, + "docs": {} + }, "df": 0, "docs": {}, "l": { @@ -1204,7 +1312,7 @@ "o": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -1228,7 +1336,7 @@ "0": { "tf": 1.0 }, - "20": { + "22": { "tf": 1.0 } } @@ -1246,7 +1354,7 @@ "n": { "df": 2, "docs": { - "17": { + "19": { "tf": 1.0 }, "7": { @@ -1261,7 +1369,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -1279,7 +1387,7 @@ "l": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -1297,7 +1405,7 @@ "g": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -1369,7 +1477,7 @@ "t": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -1486,7 +1594,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.4142135623730951 } } @@ -1502,10 +1610,10 @@ "e": { "df": 3, "docs": { - "13": { + "14": { "tf": 1.4142135623730951 }, - "17": { + "19": { "tf": 1.0 }, "6": { @@ -1516,7 +1624,7 @@ "k": { "df": 1, "docs": { - "18": { + "20": { "tf": 2.23606797749979 } } @@ -1538,7 +1646,7 @@ "r": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -1570,7 +1678,7 @@ "t": { "df": 1, "docs": { - "20": { + "22": { "tf": 1.0 } } @@ -1598,7 +1706,7 @@ "n": { "df": 3, "docs": { - "17": { + "19": { "tf": 1.0 }, "7": { @@ -1616,7 +1724,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -1641,7 +1749,7 @@ "10": { "tf": 1.0 }, - "11": { + "12": { "tf": 1.4142135623730951 } } @@ -1651,7 +1759,7 @@ }, "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -1694,7 +1802,7 @@ "l": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -1745,7 +1853,7 @@ "n": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -1770,7 +1878,7 @@ "t": { "df": 1, "docs": { - "11": { + "12": { "tf": 1.0 } } @@ -1784,7 +1892,7 @@ "d": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -1806,7 +1914,7 @@ "e": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.7320508075688772 } } @@ -1837,7 +1945,7 @@ "s": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -1919,7 +2027,7 @@ "t": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.7320508075688772 } }, @@ -1947,7 +2055,7 @@ "o": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -1959,7 +2067,7 @@ "i": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -1985,7 +2093,7 @@ "t": { "df": 1, "docs": { - "20": { + "22": { "tf": 1.0 } } @@ -2021,7 +2129,7 @@ "l": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -2107,7 +2215,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.4142135623730951 } } @@ -2133,7 +2241,7 @@ "l": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -2171,7 +2279,7 @@ }, "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -2196,7 +2304,7 @@ "10": { "tf": 1.0 }, - "17": { + "19": { "tf": 1.0 } } @@ -2217,10 +2325,10 @@ "n": { "df": 4, "docs": { - "18": { + "20": { "tf": 1.0 }, - "19": { + "21": { "tf": 1.0 }, "3": { @@ -2240,7 +2348,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -2264,7 +2372,7 @@ "t": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -2381,7 +2489,7 @@ "r": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -2394,7 +2502,7 @@ "r": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -2445,7 +2553,7 @@ "s": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -2482,7 +2590,7 @@ "h": { "df": 1, "docs": { - "14": { + "15": { "tf": 1.4142135623730951 } } @@ -2555,7 +2663,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -2571,7 +2679,7 @@ "l": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -2597,7 +2705,7 @@ "k": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } @@ -2635,13 +2743,13 @@ }, "df": 4, "docs": { - "11": { + "12": { "tf": 1.4142135623730951 }, - "16": { + "17": { "tf": 1.0 }, - "18": { + "20": { "tf": 1.0 }, "6": { @@ -2676,7 +2784,7 @@ "d": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -2694,7 +2802,7 @@ "e": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -2708,7 +2816,7 @@ "o": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -2732,7 +2840,7 @@ "10": { "tf": 1.0 }, - "16": { + "17": { "tf": 1.0 } } @@ -2780,7 +2888,7 @@ "d": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -2790,7 +2898,7 @@ "k": { "df": 2, "docs": { - "18": { + "20": { "tf": 1.4142135623730951 }, "8": { @@ -2800,9 +2908,12 @@ }, "l": { "d": { - "df": 1, + "df": 2, "docs": { - "17": { + "11": { + "tf": 4.69041575982343 + }, + "19": { "tf": 1.0 } } @@ -2826,7 +2937,7 @@ "o": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -2844,10 +2955,10 @@ "1": { "df": 2, "docs": { - "13": { + "14": { "tf": 1.0 }, - "16": { + "17": { "tf": 1.0 } } @@ -2855,7 +2966,7 @@ "2": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -2911,13 +3022,37 @@ "l": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } } } }, + "r": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "n": { + "d": { + "df": 1, + "docs": { + "11": { + "tf": 4.69041575982343 + } + } + }, + "df": 0, + "docs": {} + } + } + } + }, "s": { "df": 0, "docs": {}, @@ -2982,7 +3117,7 @@ "r": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -2990,7 +3125,7 @@ "z": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -3032,7 +3167,7 @@ "m": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -3062,7 +3197,7 @@ "h": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -3086,7 +3221,7 @@ "i": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } @@ -3126,7 +3261,7 @@ "e": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.7320508075688772 } } @@ -3138,13 +3273,41 @@ "a": { "df": 0, "docs": {}, + "p": { + "df": 0, + "docs": {}, + "y": { + "b": { + "a": { + "df": 0, + "docs": {}, + "r": { + "a": { + "df": 1, + "docs": { + "18": { + "tf": 2.449489742783178 + } + } + }, + "df": 0, + "docs": {} + } + }, + "df": 0, + "docs": {} + }, + "df": 0, + "docs": {} + } + }, "r": { "df": 0, "docs": {}, "e": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } }, @@ -3163,7 +3326,7 @@ "i": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3182,7 +3345,7 @@ "t": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } @@ -3222,13 +3385,13 @@ "df": 0, "docs": {}, "r": { - "df": 18, + "df": 20, "docs": { "10": { "tf": 2.23606797749979 }, "11": { - "tf": 1.0 + "tf": 1.4142135623730951 }, "12": { "tf": 1.0 @@ -3246,17 +3409,23 @@ "tf": 1.0 }, "17": { - "tf": 1.7320508075688772 + "tf": 1.0 }, "18": { "tf": 1.4142135623730951 }, "19": { - "tf": 1.4142135623730951 + "tf": 1.7320508075688772 }, "2": { "tf": 1.7320508075688772 }, + "20": { + "tf": 1.4142135623730951 + }, + "21": { + "tf": 1.4142135623730951 + }, "3": { "tf": 1.0 }, @@ -3291,7 +3460,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 2.23606797749979 } } @@ -3314,7 +3483,7 @@ "e": { "df": 2, "docs": { - "17": { + "19": { "tf": 1.0 }, "4": { @@ -3335,7 +3504,7 @@ "n": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3381,7 +3550,7 @@ "10": { "tf": 1.0 }, - "20": { + "22": { "tf": 1.7320508075688772 } } @@ -3401,7 +3570,7 @@ "n": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3439,7 +3608,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3453,7 +3622,7 @@ "d": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } }, @@ -3493,7 +3662,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3521,7 +3690,7 @@ "n": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3543,7 +3712,7 @@ "n": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -3563,10 +3732,10 @@ "l": { "df": 2, "docs": { - "13": { + "14": { "tf": 1.0 }, - "14": { + "15": { "tf": 1.0 } } @@ -3584,7 +3753,7 @@ "d": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -3653,7 +3822,7 @@ "0": { "tf": 1.0 }, - "17": { + "19": { "tf": 1.0 }, "4": { @@ -3675,13 +3844,13 @@ "df": 0, "docs": {}, "t": { - "df": 16, + "df": 18, "docs": { "10": { "tf": 1.4142135623730951 }, "11": { - "tf": 1.0 + "tf": 1.4142135623730951 }, "12": { "tf": 1.0 @@ -3698,12 +3867,18 @@ "16": { "tf": 1.0 }, - "18": { + "17": { "tf": 1.0 }, + "18": { + "tf": 1.4142135623730951 + }, "2": { "tf": 1.7320508075688772 }, + "20": { + "tf": 1.0 + }, "3": { "tf": 1.0 }, @@ -3733,7 +3908,7 @@ "n": { "df": 3, "docs": { - "17": { + "19": { "tf": 1.0 }, "7": { @@ -3750,7 +3925,7 @@ "o": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } }, @@ -3766,7 +3941,7 @@ "t": { "df": 1, "docs": { - "13": { + "14": { "tf": 2.23606797749979 } } @@ -3781,7 +3956,7 @@ "r": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3807,7 +3982,7 @@ "t": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -3845,6 +4020,29 @@ "df": 0, "docs": {}, "e": { + "a": { + "d": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "r": { + "df": 2, + "docs": { + "10": { + "tf": 1.0 + }, + "18": { + "tf": 1.0 + } + } + } + } + }, + "df": 0, + "docs": {} + }, "df": 0, "docs": {}, "l": { @@ -3856,7 +4054,7 @@ "o": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -3880,7 +4078,7 @@ "0": { "tf": 1.0 }, - "20": { + "22": { "tf": 1.0 } } @@ -3898,7 +4096,7 @@ "n": { "df": 2, "docs": { - "17": { + "19": { "tf": 1.0 }, "7": { @@ -3913,7 +4111,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -3931,7 +4129,7 @@ "l": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -3949,7 +4147,7 @@ "g": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -4021,7 +4219,7 @@ "t": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -4138,7 +4336,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.4142135623730951 } } @@ -4154,10 +4352,10 @@ "e": { "df": 3, "docs": { - "13": { + "14": { "tf": 1.4142135623730951 }, - "17": { + "19": { "tf": 1.0 }, "6": { @@ -4168,7 +4366,7 @@ "k": { "df": 1, "docs": { - "18": { + "20": { "tf": 2.449489742783178 } } @@ -4190,7 +4388,7 @@ "r": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -4222,7 +4420,7 @@ "t": { "df": 1, "docs": { - "20": { + "22": { "tf": 1.0 } } @@ -4250,7 +4448,7 @@ "n": { "df": 3, "docs": { - "17": { + "19": { "tf": 1.0 }, "7": { @@ -4268,7 +4466,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -4293,11 +4491,8 @@ "10": { "tf": 1.0 }, - "11": { - "tf": 2.0 - }, "12": { - "tf": 1.0 + "tf": 2.0 }, "13": { "tf": 1.0 @@ -4307,6 +4502,9 @@ }, "15": { "tf": 1.0 + }, + "16": { + "tf": 1.0 } } } @@ -4315,7 +4513,7 @@ }, "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -4358,7 +4556,7 @@ "l": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -4384,10 +4582,10 @@ "10": { "tf": 1.4142135623730951 }, - "18": { + "20": { "tf": 1.0 }, - "19": { + "21": { "tf": 1.0 }, "4": { @@ -4427,7 +4625,7 @@ "n": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -4452,7 +4650,7 @@ "t": { "df": 1, "docs": { - "11": { + "12": { "tf": 1.0 } } @@ -4466,7 +4664,7 @@ "d": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -4488,7 +4686,7 @@ "e": { "df": 1, "docs": { - "18": { + "20": { "tf": 2.0 } } @@ -4519,7 +4717,7 @@ "s": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -4601,7 +4799,7 @@ "t": { "df": 1, "docs": { - "18": { + "20": { "tf": 2.0 } }, @@ -4629,7 +4827,7 @@ "o": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -4641,7 +4839,7 @@ "i": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -4667,7 +4865,7 @@ "t": { "df": 1, "docs": { - "20": { + "22": { "tf": 1.0 } } @@ -4688,10 +4886,13 @@ "df": 0, "docs": {}, "s": { - "df": 1, + "df": 2, "docs": { "10": { "tf": 1.0 + }, + "11": { + "tf": 1.0 } } } @@ -4703,7 +4904,7 @@ "l": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.4142135623730951 } } @@ -4789,7 +4990,7 @@ "t": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.4142135623730951 } } @@ -4815,7 +5016,7 @@ "l": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -4853,7 +5054,7 @@ }, "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -4878,13 +5079,13 @@ "10": { "tf": 1.0 }, - "17": { + "19": { "tf": 1.7320508075688772 }, - "18": { + "20": { "tf": 1.0 }, - "19": { + "21": { "tf": 1.0 } } @@ -4905,10 +5106,10 @@ "n": { "df": 4, "docs": { - "18": { + "20": { "tf": 1.0 }, - "19": { + "21": { "tf": 1.4142135623730951 }, "3": { @@ -4928,7 +5129,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -4952,7 +5153,7 @@ "t": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -5069,7 +5270,7 @@ "r": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -5082,7 +5283,7 @@ "r": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -5133,7 +5334,7 @@ "s": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.4142135623730951 } } @@ -5170,7 +5371,7 @@ "h": { "df": 1, "docs": { - "14": { + "15": { "tf": 1.7320508075688772 } } @@ -5243,7 +5444,7 @@ "e": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -5259,7 +5460,7 @@ "l": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.4142135623730951 } } @@ -5285,7 +5486,7 @@ "k": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.4142135623730951 } } @@ -5323,13 +5524,13 @@ }, "df": 4, "docs": { - "11": { + "12": { "tf": 1.7320508075688772 }, - "16": { + "17": { "tf": 1.4142135623730951 }, - "18": { + "20": { "tf": 1.4142135623730951 }, "6": { @@ -5364,7 +5565,7 @@ "d": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -5382,7 +5583,7 @@ "e": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -5396,7 +5597,7 @@ "o": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -5420,7 +5621,7 @@ "10": { "tf": 1.0 }, - "16": { + "17": { "tf": 1.7320508075688772 } } @@ -5468,7 +5669,7 @@ "d": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -5478,7 +5679,7 @@ "k": { "df": 2, "docs": { - "18": { + "20": { "tf": 1.4142135623730951 }, "8": { @@ -5488,9 +5689,12 @@ }, "l": { "d": { - "df": 1, + "df": 2, "docs": { - "17": { + "11": { + "tf": 4.69041575982343 + }, + "19": { "tf": 1.0 } } @@ -5514,7 +5718,7 @@ "o": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -5637,9 +5841,15 @@ "df": 0, "docs": {}, "r": { - "df": 3, + "df": 5, "docs": { - "17": { + "11": { + "tf": 1.0 + }, + "18": { + "tf": 1.0 + }, + "19": { "tf": 1.0 }, "2": { @@ -5697,7 +5907,7 @@ "s": { "df": 1, "docs": { - "20": { + "22": { "tf": 1.0 } } @@ -5764,8 +5974,14 @@ "df": 0, "docs": {}, "t": { - "df": 1, + "df": 3, "docs": { + "11": { + "tf": 1.0 + }, + "18": { + "tf": 1.0 + }, "2": { "tf": 1.0 } @@ -5792,7 +6008,7 @@ "t": { "df": 1, "docs": { - "13": { + "14": { "tf": 1.0 } } @@ -5912,7 +6128,7 @@ "k": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -5940,7 +6156,7 @@ "n": { "df": 1, "docs": { - "11": { + "12": { "tf": 1.0 } } @@ -5986,7 +6202,7 @@ "e": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -6019,7 +6235,7 @@ "t": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -6037,7 +6253,7 @@ "l": { "df": 1, "docs": { - "18": { + "20": { "tf": 1.0 } } @@ -6101,7 +6317,7 @@ "d": { "df": 1, "docs": { - "17": { + "19": { "tf": 1.0 } } @@ -6122,7 +6338,7 @@ "n": { "df": 3, "docs": { - "19": { + "21": { "tf": 1.0 }, "3": { @@ -6183,7 +6399,7 @@ "s": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } } @@ -6220,7 +6436,7 @@ "h": { "df": 1, "docs": { - "14": { + "15": { "tf": 1.0 } } @@ -6273,7 +6489,7 @@ "l": { "df": 1, "docs": { - "12": { + "13": { "tf": 1.0 } } @@ -6299,7 +6515,7 @@ "k": { "df": 1, "docs": { - "15": { + "16": { "tf": 1.0 } } @@ -6321,13 +6537,13 @@ "t": { "df": 3, "docs": { - "11": { + "12": { "tf": 1.0 }, - "16": { + "17": { "tf": 1.0 }, - "18": { + "20": { "tf": 1.0 } } @@ -6349,7 +6565,7 @@ "d": { "df": 1, "docs": { - "16": { + "17": { "tf": 1.0 } }