Compare commits

...

88 Commits

Author SHA1 Message Date
Eric Huss
9a9eb0124a Merge pull request #1447 from ehuss/bump-version
Update to 0.4.6.
2021-01-14 17:36:08 -08:00
Eric Huss
257374d76b Update to 0.4.6. 2021-01-14 17:27:54 -08:00
Eric Huss
1a0c296532 Merge pull request #1426 from ehuss/search-mark-words
Fix search highlighting with multiple words.
2021-01-14 17:01:52 -08:00
Eric Huss
9b4ab72a80 Merge pull request #1418 from ehuss/relative-renderer-command
Fix relative paths for renderer commands.
2021-01-14 17:01:41 -08:00
Eric Huss
b1c2e466e7 Merge pull request #1438 from pierwill/edit-docs
Add intra-docs links to docs
2021-01-13 14:26:44 -08:00
Eric Huss
cdea0f6b61 Add missing parenthesis in doc comment. 2021-01-13 14:26:14 -08:00
pierwill
e9b0be7090 Add intra-docs links to docs
Also fixes some punctuation and changes some wording.
2021-01-10 14:51:30 -08:00
Tatsuya Kawano
218e200117 Fix a wrong version 0.4.4 in Cargo.toml (Should be 0.4.5) (#1435) 2021-01-07 14:56:21 +01:00
Eric Huss
3d55375f61 Update theme CSS docs. (#1431) 2021-01-07 01:56:20 +01:00
Eric Huss
77e7cfd22b Change init --theme to place theme in root. (#1432) 2021-01-07 01:29:38 +01:00
Eric Huss
76cd39e5e2 Merge pull request #1390 from sburris0/gitlabci
Guide: Add instructions for publishing via GitLab Pages
2021-01-06 13:11:58 -08:00
Eric Huss
09e7bb76dc Remove mark from URL on escape. (#1427) 2021-01-05 19:31:16 +01:00
Eric Huss
28387130c0 Fix search highlighting with multiple words. 2021-01-04 14:20:36 -08:00
Eric Huss
33d3d9c3ec Merge pull request #1389 from avitex/search-chapter-name
Add chapter name to search result breadcrumbs
2021-01-04 14:01:30 -08:00
Eric Huss
e651f4d734 Merge pull request #1420 from apatniv/clippy_remove_clone
Clippy lint: Remove unnecessary clone
2021-01-04 11:33:37 -08:00
Eric Huss
87d2cd9845 Merge pull request #1421 from apatniv/clippy_use_single_char
clippy: use char instead of str
2021-01-04 11:31:06 -08:00
Pietro Albini
32abeef088 fix xss in the search page
Thanks to Kamil Vavra for responsibly disclosing the vulnerability
according to Rust's Security Policy.
2021-01-04 07:14:57 -08:00
Eric Huss
5de9b6841e Update changelog for 0.4.5 2021-01-04 07:13:30 -08:00
apatniv
95e0743bc0 clippy: use char instead of str 2020-12-31 15:37:34 -05:00
apatniv
3c97525743 Clippy lint: Remove unnecessary clone 2020-12-31 15:18:37 -05:00
Eric Huss
9a65c8ab92 Fix relative paths for renderer commands. 2020-12-30 17:46:29 -08:00
Eric Huss
a64a7b7470 Merge pull request #1405 from francis-du/master
fix: readerer get theme dir path bug
2020-12-28 09:22:11 -08:00
francis-du
fd4137a9ea fix: readerer get theme dir path bug 2020-12-28 09:20:23 -08:00
Vivek Bharath Akupatni
a3d4febe3e Provide useful feedback if user executes command in different folder (#1407)
Provides better feedback if user executes in a different folder than what is expected by mdbook

After the changes `mdbook build`
```
2020-12-19 14:27:35 [ERROR] (mdbook::utils): Error: Couldn't open SUMMARY.md in "/Users/vicky/rust/source_codes/mdbook_testing/src/src" directory
2020-12-19 14:27:35 [ERROR] (mdbook::utils):    Caused By: No such file or directory (os error 2)
```

Previously: `mdbook build`
```
2020-12-19 14:28:46 [ERROR] (mdbook::utils): Error: Couldn't open SUMMARY.md
2020-12-19 14:28:46 [ERROR] (mdbook::utils):    Caused By: No such file or directory (os error 2)
```
2020-12-27 12:45:11 -08:00
Maxime BORGES
7af4b1dfe8 [README] Add optional directory parameter for the init command (#1409)
With the current description of the command, I was expecting to get a directory named with the project name, but the files were created in the current directory.
I Think a more precise description would help first-time users.
2020-12-23 10:03:31 -08:00
Eric Huss
ba6bffac5a Merge pull request #1410 from maximeborges/patch-2
[guide/format/theme/index-hbs] `chapter_title` and `book_title` are inverted
2020-12-23 08:55:46 -08:00
Maxime BORGES
6201e577fe [guide/format/theme/index-hbs] chapter_title and book_title are inverted
Looking into the code, we can confirm that the implementation is `{{ chapter_title }} - {{ book_title }}` and not `{{ book_title }} - {{ chapter_title }}` as written in the guide:
4c951d530d/src/renderer/html_handlebars/hbs_renderer.rs (L69)
2020-12-22 22:36:58 +01:00
Eric Huss
cf2459f730 Merge pull request #1393 from apatniv/fixing_error
Missing chapters Error Reporting: Add file name
2020-12-14 08:33:36 -08:00
Eric Huss
45a481049e Merge pull request #1399 from u7693/issue-1396
Show path in the error message (#1396)
2020-12-14 08:08:05 -08:00
Kousuke Takaki
6bcabcbb6b Improve error message 2020-12-14 16:11:01 +09:00
apatniv
ef993e8cc2 Run rust formmater 2020-12-05 20:27:03 -05:00
apatniv
a3a5386da0 Add more context regarding which missing file creation failed 2020-12-05 20:17:45 -05:00
Eric Huss
3ab911afa1 Merge pull request #1392 from lzanini/master
Add Katex preprocessor to 3rd Party Plugins
2020-12-04 10:53:21 -08:00
Spencer Burris
4615ce2f8c Remove --debug from GitLab CI 2020-12-04 09:12:00 -08:00
Lucas Zanini
7cb8087469 katex preprocessor
Added the katex preprocessor to the list of 3rd Party Plugins
2020-12-03 23:54:12 +01:00
Spencer Burris
d1721667b6 Add instructions for publishing via GitLab Pages 2020-12-01 13:25:28 -08:00
avitex
1038f0b7f5 Fix search index tests 2020-11-26 09:02:11 +11:00
avitex
942cc12a74 Add chapter name to search result breadcrumbs 2020-11-25 14:46:49 +11:00
Eric Huss
59f2a9bf4e Merge pull request #1373 from avisionh/docs/ci-guide-update
Docs: CI guide update
2020-11-13 08:19:52 -08:00
A Ho
75d0f1efd4 Suggest dplyv2 changes to .travis.yml as a note
This is following @ehuss' comment to not recommend something currently in beta release.
2020-11-13 09:40:33 +00:00
Eric Huss
552e3378cf Merge pull request #1378 from daynin/serialize-build-section
allow to serialize the "build" section
2020-11-12 10:41:12 -08:00
Sergey Golovin
7c0ddff96a allow to serialize the "build" section 2020-11-12 19:32:32 +03:00
Eric Huss
07e72757d3 Merge pull request #1376 from dtolnay/html
Escape `<` and `>` in rendered toc to match handlebars' escaping in <title>
2020-11-10 14:46:24 -08:00
Eric Huss
58f66a146d Merge pull request #1375 from dtolnay/playground
Fix stray spacing after #playground code
2020-11-10 14:06:09 -08:00
Eric Huss
643d5ecc5c Merge pull request #1285 from FrankHB/patch-1
Handled UTF-8 BOM
2020-11-10 14:02:01 -08:00
David Tolnay
c712ba7aab Escape <> in rendered toc 2020-11-08 22:26:30 -08:00
David Tolnay
1450070f73 Fix stray spacing after #playground code 2020-11-05 21:43:04 -08:00
A Ho
e310dfc605 Add avisionh to contributors
This is for contributing to the travis deployments chapter.
2020-11-05 22:28:54 +00:00
A Ho
cbfd75a821 Update CI section in guide for travis dpl-v2
This is so that the instructions work when deploying the book to GitHub pages via the gh-pages branch.
2020-11-05 21:43:52 +00:00
Eric Huss
eaa6914205 Merge pull request #1360 from ehuss/release-next
Release 0.4.4
2020-10-20 08:06:27 -07:00
Eric Huss
a76557a678 Release 0.4.4 2020-10-20 07:58:24 -07:00
Eric Huss
01836ba5d4 Merge pull request #1348 from ehuss/github-deprecated-action-commands
Update deprecated GitHub Actions commands.
2020-10-20 07:48:26 -07:00
Eric Huss
46ce077de6 Update deprecated GitHub Actions commands. 2020-10-08 10:00:06 -07:00
Eric Huss
f7c9180d80 Fix typo in changelog 2020-10-08 09:46:39 -07:00
FrankHB
9e9cf49c50 Added a test.
Signed-off-by: FrankHB <frankhb1989@gmail.com>
2020-10-07 22:50:25 +08:00
Camelid
4c951d530d List supported Highlight.js languages in guide (#1345)
* List supported Highlight.js languages in guide

Generated using the technique described in
https://github.com/rust-lang/mdBook/issues/1275#issuecomment-655903967.

* Improve wording in guide
2020-09-30 01:56:31 +02:00
FrankHB
780fb979a0 Avoided the redundant allocation.
Signed-off-by: FrankHB <frankhb1989@gmail.com>
2020-09-29 18:01:06 +08:00
Camelid
b77942d3c8 Rename book-example to guide (#1336)
`book-example` is a bit of a strange name given that it's not just an
example.
2020-09-23 03:16:09 +02:00
Eric Huss
d0deee90b0 Merge pull request #1335 from ehuss/fix-print
Fix print icon.
2020-09-22 13:34:15 -07:00
Eric Huss
e6ac8ecdd9 Fix print icon. 2020-09-22 13:24:13 -07:00
Eric Huss
d1f5ecc103 Merge pull request #1169 from rossmacarthur/ft/no-print
Add config option to disable print html, css, and icon
2020-09-22 11:50:22 -07:00
Ross MacArthur
e0b247e9d6 Add config option to disable print html, css, and icon 2020-09-22 11:40:02 -07:00
Eric Huss
db8a2821ea Merge pull request #1323 from iffyio/copy-symlinks
Resolve full file paths when copying files
2020-09-22 10:51:50 -07:00
Eric Huss
39d7130019 Merge pull request #1325 from camelid/patch-2
Improve README wording
2020-09-12 06:19:41 -07:00
Camelid
2eccb457d2 gitignore: Ignore Vim temporary and swap files (#1328) 2020-09-11 15:10:38 +02:00
Camelid
d1682d27fb Improve README wording 2020-09-10 13:28:24 -07:00
Eric Huss
a94a940ff7 Fix macOS CI deploy take 2. 2020-09-09 12:05:14 -07:00
Eric Huss
daf402e1dc Merge pull request #1324 from ehuss/purge
Fix macOS CI deploy.
2020-09-09 11:47:00 -07:00
Eric Huss
5ebd2c0527 Fix macOS CI deploy. 2020-09-09 10:00:48 -07:00
ifeanyi
b349e8abc9 Fix windows typo 2020-09-09 17:57:45 +02:00
ifeanyi
e225586953 Resolve full file paths when copying files
Currently, the `copy_files` function doesn't support symlink files due to
its use of `DirEntry::metadata` - To avoid this issue, this patch
resolves the file path first before checking for metadata.

Fixes #1157
2020-09-09 17:42:14 +02:00
Eric Huss
cf7663f800 Merge pull request #1317 from ehuss/release-next
Release 0.4.3
2020-09-08 08:21:17 -07:00
Eric Huss
3155c63e88 Release 0.4.3 2020-09-08 08:06:05 -07:00
Eric Huss
4df9ec90af Merge pull request #1307 from camelid/prefer-bundled-scp
Prefer bundled version of Source Code Pro
2020-09-06 10:58:23 -07:00
Camelid
73cabeb904 Remove local version from @font-face
It's unlikely that the bundled version wouldn't load, and it's
especially unlikely that the page would load but the bundled version
would not.

Also, if it doesn't load, it should fall back to another monospace font,
which is fine.
2020-09-06 10:34:11 -07:00
Eric Huss
4b773024ae Merge pull request #1309 from nerosnm/add-missing-space
Fix missing space before draft chapter titles
2020-09-06 09:40:55 -07:00
Eric Huss
33ea661350 Merge pull request #1310 from dtolnay/nojekyll
End .nojekyll file with newline
2020-09-06 09:21:59 -07:00
Eric Huss
1b18740b56 Merge pull request #1311 from dtolnay/cname
Support emitting CNAME file for publishing at a custom domain
2020-09-06 09:21:29 -07:00
Eric Huss
6fed9e52f9 Merge pull request #1313 from guswynn/master
collect all test failures before failing
2020-09-06 09:12:42 -07:00
Eric Huss
fd59dc73e5 Adjust wording 2020-09-06 09:11:53 -07:00
Eric Huss
146bea48c6 Merge pull request #1314 from camelid/patch-1
Fix grammar
2020-09-06 08:59:11 -07:00
Camelid
efb5bc285d Fix grammar
who -> which
2020-09-04 13:21:37 -07:00
Gus Wynn
5ea8e55aea collect all test failures before failing 2020-09-03 18:36:51 -07:00
David Tolnay
1acf23ff73 Support emitting CNAME file for publishing at a custom domain 2020-09-02 11:24:48 -07:00
David Tolnay
69cc1fa005 End .nojekyll file with newline
Before:

    /path/to$  cat book/.nojekyll
    This file makes sure that Github Pages doesn't process mdBook's output./path/to$  ▎

After:

    /path/to$  cat book/.nojekyll
    This file makes sure that Github Pages doesn't process mdBook's output.
    /path/to$  ▎
2020-09-02 11:06:19 -07:00
Søren Mortensen
2fb489137b Wrap draft chapter titles in a <div>
Fixes the problem of a missing space before the title of draft chapters,
due to the title not being wrapped in an `<a></a>`.
2020-08-31 10:00:03 +01:00
Camelid
4d9eb9b4b4 Prefer bundled version of Source Code Pro
This prevents an issue with Firefox 80 on macOS that prevents syntax
highlighting from working.
2020-08-29 13:22:51 -07:00
FrankHB
65d9eb6f7e Handled UTF-8 BOM
Fixed #1155 .
2020-07-25 13:02:44 +08:00
60 changed files with 723 additions and 211 deletions

View File

@@ -31,12 +31,12 @@ jobs:
- name: Install Rust (rustup)
run: rustup update stable --no-self-update && rustup default stable
- name: Build book
run: cargo run -- build book-example
run: cargo run -- build guide
- name: Deploy to GitHub
env:
GITHUB_DEPLOY_KEY: ${{ secrets.GITHUB_DEPLOY_KEY }}
run: |
touch book-example/book/.nojekyll
touch guide/book/.nojekyll
curl -LsSf https://raw.githubusercontent.com/rust-lang/simpleinfra/master/setup-deploy-keys/src/deploy.rs | rustc - -o /tmp/deploy
cd book-example/book
cd guide/book
/tmp/deploy

6
.gitignore vendored
View File

@@ -4,10 +4,14 @@ target
.DS_Store
book-test
book-example/book
guide/book
.vscode
tests/dummy_book/book/
# Ignore Jetbrains specific files.
.idea/
# Ignore Vim temporary and swap files.
*.sw?
*~

View File

@@ -1,5 +1,86 @@
# Changelog
## mdBook 0.4.6
[eaa6914...1a0c296](https://github.com/rust-lang/mdBook/compare/eaa6914...1a0c296)
### Changed
- The chapter name is now included in the search breadcrumbs.
[#1389](https://github.com/rust-lang/mdBook/pull/1389)
- Pressing Escape will remove the `?highlight` argument from the URL.
[#1427](https://github.com/rust-lang/mdBook/pull/1427)
- `mdbook init --theme` will now place the theme in the root of the book
directory instead of in the `src` directory.
[#1432](https://github.com/rust-lang/mdBook/pull/1432)
- A custom renderer that sets the `command` to a relative path now interprets
the relative path relative to the book root. Previously it was inconsistent
based on the platform (either relative to the current directory, or relative
to the renderer output directory). Paths relative to the output directory
are still supported with a deprecation warning.
[#1418](https://github.com/rust-lang/mdBook/pull/1418)
- The `theme` directory in the config is now interpreted as relative to the
book root, instead of the current directory.
[#1405](https://github.com/rust-lang/mdBook/pull/1405)
- Handle UTF-8 BOM for chapter sources.
[#1285](https://github.com/rust-lang/mdBook/pull/1285)
- Removed extra whitespace added to `{{#playground}}` snippets.
[#1375](https://github.com/rust-lang/mdBook/pull/1375)
### Fixed
- Clicking on a search result with multiple search words will now correctly
highlight all of the words.
[#1426](https://github.com/rust-lang/mdBook/pull/1426)
- Properly handle `<` and `>` characters in the table of contents.
[#1376](https://github.com/rust-lang/mdBook/pull/1376)
- Fixed to properly serialize the `build` table in the config, which prevented
setting it in the API.
[#1378](https://github.com/rust-lang/mdBook/pull/1378)
## mdBook 0.4.5
[eaa6914...f66df09](https://github.com/rust-lang/mdBook/compare/eaa6914...f66df09)
### Fixed
- Fixed XSS in the search page.
[CVE-2020-26297](https://groups.google.com/g/rustlang-security-announcements/c/3-sO6of29O0)
[648c9ae](https://github.com/rust-lang/mdBook/commit/648c9ae772bec83f0a5954d17b4287d5bb1d6606)
## mdBook 0.4.4
[4df9ec9...01836ba](https://github.com/rust-lang/mdBook/compare/4df9ec9...01836ba)
### Added
- Added the `output.html.print.enable` configuration value to disable the
"print" page.
[#1169](https://github.com/rust-lang/mdBook/pull/1169)
- Added a list of supported languages for syntax-highlighting to the
documentation.
[#1345](https://github.com/rust-lang/mdBook/pull/1345)
### Fixed
- Now supports symbolic links for files in the `src` directory.
[#1323](https://github.com/rust-lang/mdBook/pull/1323)
## mdBook 0.4.3
[9278b83...4df9ec9](https://github.com/rust-lang/mdBook/compare/9278b83...4df9ec9)
### Added
- Added `output.html.cname` option to emit a `CNAME` file which is used by
GitHub Pages to know which domain is being used.
[#1311](https://github.com/rust-lang/mdBook/pull/1311)
### Changed
- `mdbook test` no longer stops on the first test failure, but instead will
run all the tests.
[#1313](https://github.com/rust-lang/mdBook/pull/1313)
- Removed the `local` font source for Source Code Pro, as the locally
installed font may not render properly on FireFox on macOS.
[#1307](https://github.com/rust-lang/mdBook/pull/1307)
### Fixed
- Added newline to end of `.nojekyll` file.
[#1310](https://github.com/rust-lang/mdBook/pull/1310)
- Fixed missing space before draft chapter titles.
[#1309](https://github.com/rust-lang/mdBook/pull/1309)
## mdBook 0.4.2
[649f355...9278b83](https://github.com/rust-lang/mdBook/compare/649f355...9278b83)

2
Cargo.lock generated
View File

@@ -723,7 +723,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]]
name = "mdbook"
version = "0.4.2"
version = "0.4.6"
dependencies = [
"ammonia",
"anyhow",

View File

@@ -1,6 +1,6 @@
[package]
name = "mdbook"
version = "0.4.2"
version = "0.4.6"
authors = [
"Mathieu David <mathieudavid@mathieudavid.org>",
"Michael-F-Bryan <michaelfbryan@gmail.com>",
@@ -8,7 +8,7 @@ authors = [
]
documentation = "http://rust-lang.github.io/mdBook/index.html"
edition = "2018"
exclude = ["/book-example/*"]
exclude = ["/guide/*"]
keywords = ["book", "gitbook", "rustbook", "markdown"]
license = "MPL-2.0"
readme = "README.md"

View File

@@ -85,16 +85,17 @@ There are multiple ways to install mdBook.
## Usage
mdBook will primarily be used as a command line tool, even though it exposes
mdBook is primarily used as a command line tool, even though it exposes
all its functionality as a Rust crate for integration in other projects.
Here are the main commands you will want to run. For a more exhaustive
explanation, check out the [User Guide].
- `mdbook init`
- `mdbook init <directory>`
The init command will create a directory with the minimal boilerplate to
start with.
start with. If the `<directory>` parameter is omitted, the current
directory will be used.
```
book-test/
@@ -149,6 +150,7 @@ preprocessors are:
the url `foo/` when published to a browser
- `links` - a built-in preprocessor (enabled by default) for expanding the
`{{# playground}}` and `{{# include}}` helpers in a chapter.
- [`katex`](https://github.com/lzanini/mdbook-katex) - a preprocessor rendering LaTex equations to HTML.
Renderers are given the final book so they can do something with it. This is
typically used for, as the name suggests, rendering the document in a particular
@@ -209,7 +211,7 @@ tagged [E-Easy] and **we will gladly mentor you** so that you can successfully
go through the process of fixing a bug or adding a new feature! Let us know if
you need any help.
For more info about contributing, check out our [contribution guide] who helps
For more info about contributing, check out our [contribution guide] which helps
you go through the build and contribution process!
There is also a [rendered version][master-docs] of the latest API docs

View File

@@ -21,4 +21,4 @@ case $1 in
;;
esac
echo "##[add-path]$PWD/hub/bin"
echo "$PWD/hub/bin" >> $GITHUB_PATH

View File

@@ -15,10 +15,20 @@ export CARGO_PROFILE_RELEASE_LTO=true
cargo build --bin mdbook --release
cd target/release
case $1 in
ubuntu* | macos*)
ubuntu*)
asset="mdbook-$TAG-$host.tar.gz"
tar czf ../../$asset mdbook
;;
macos*)
asset="mdbook-$TAG-$host.tar.gz"
# There is a bug with BSD tar on macOS where the first 8MB of the file are
# sometimes all NUL bytes. See https://github.com/actions/cache/issues/403
# and https://github.com/rust-lang/cargo/issues/8603 for some more
# information. An alternative solution here is to install GNU tar, but
# flushing the disk cache seems to work, too.
sudo /usr/sbin/purge
tar czf ../../$asset mdbook
;;
windows*)
asset="mdbook-$TAG-$host.zip"
7z a ../../$asset mdbook.exe

View File

@@ -17,7 +17,7 @@
- [Syntax highlighting](format/theme/syntax-highlighting.md)
- [Editor](format/theme/editor.md)
- [MathJax Support](format/mathjax.md)
- [mdBook specific features](format/mdbook.md)
- [mdBook-specific features](format/mdbook.md)
- [Continuous Integration](continuous-integration.md)
- [For Developers](for_developers/README.md)
- [Preprocessors](for_developers/preprocessors.md)

View File

@@ -39,6 +39,9 @@ permissions (or "repo" for private repositories). Go to your repository's Travis
CI settings page and add an environment variable named `GITHUB_TOKEN` that is
marked secure and *not* shown in the logs.
Whilst still in your repository's settings page, navigate to Options and change the
Source on GitHub pages to `gh-pages`.
Then, append this snippet to your `.travis.yml` and update the path to the
`book` directory:
@@ -55,6 +58,40 @@ deploy:
That's it!
Note: Travis has a new [dplv2](https://blog.travis-ci.com/2019-08-27-deployment-tooling-dpl-v2-preview-release) configuration that is currently in beta. To use this new format, update your `.travis.yml` file to:
```yaml
language: rust
os: linux
dist: xenial
cache:
- cargo
rust:
- stable
before_script:
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
- (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
- cargo install-update -a
script:
- mdbook build path/to/mybook && mdbook test path/to/mybook
deploy:
provider: pages
strategy: git
edge: true
cleanup: false
github-token: $GITHUB_TOKEN
local-dir: path/to/mybook/book
keep-history: false
on:
branch: master
target_branch: gh-pages
```
### Deploying to GitHub Pages manually
If your CI doesn't support GitHub pages, or you're deploying somewhere else
@@ -87,3 +124,31 @@ deploy: book
git commit -m "deployed on $(shell date) by ${USER}" && \
git push origin gh-pages
```
## Deploying Your Book to GitLab Pages
Inside your repository's project root, create a file named `.gitlab-ci.yml` with the following contents:
```yml
stages:
- deploy
pages:
stage: deploy
image: rust:alpine
variables:
CARGO_HOME: $CI_PROJECT_DIR/cargo
before_script:
- export PATH="$PATH:$CARGO_HOME/bin"
- mdbook --version || cargo install mdbook
script:
- mdbook build -d public
only:
- master
artifacts:
paths:
- public
cache:
paths:
- $CARGO_HOME/bin
```
After you commit and push this new file, GitLab CI will run and your book will be available!

View File

@@ -187,6 +187,9 @@ The following configuration options are available:
- **additional-js:** If you need to add some behaviour to your book without
removing the current behaviour, you can specify a set of JavaScript files that
will be loaded alongside the default one.
- **print:** A subtable for configuration print settings. mdBook by default adds
support for printing out the book as a single page. This is accessed using the
print icon on the top right of the book.
- **no-section-label:** mdBook by defaults adds section label in table of
contents column. For example, "1.", "2.1". Set this option to true to disable
those labels. Defaults to `false`.
@@ -210,6 +213,17 @@ The following configuration options are available:
- **site-url:** The url where the book will be hosted. This is required to ensure
navigation links and script/css imports in the 404 file work correctly, even when accessing
urls in subdirectories. Defaults to `/`.
- **cname:** The DNS subdomain or apex domain at which your book will be hosted.
This string will be written to a file named CNAME in the root of your site, as
required by GitHub Pages (see [*Managing a custom domain for your GitHub Pages
site*][custom domain]).
[custom domain]: https://docs.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site
Available configuration options for the `[output.html.print]` table:
- **enable:** Enable print support. When `false`, all print support will not be
rendered. Defaults to `true`.
Available configuration options for the `[output.html.fold]` table:
@@ -273,8 +287,12 @@ no-section-label = false
git-repository-url = "https://github.com/rust-lang/mdBook"
git-repository-icon = "fa-github"
site-url = "/example-book/"
cname = "myproject.rs"
input-404 = "not-found.md"
[output.html.print]
enable = true
[output.html.fold]
enable = false
level = 0

View File

@@ -1,9 +1,9 @@
# mdBook-specific markdown
# mdBook-specific features
## Hiding code lines
There is a feature in mdBook that lets you hide code lines by prepending them
with a `#` [in the same way that Rustdoc does][rustdoc-hide].
with a `#` [like you would with Rustdoc][rustdoc-hide].
[rustdoc-hide]: https://doc.rust-lang.org/stable/rustdoc/documentation-tests.html#hiding-portions-of-the-example
@@ -37,7 +37,7 @@ With the following syntax, you can include files into your book:
The path to the file has to be relative from the current source file.
mdBook will interpret included files as markdown. Since the include command
mdBook will interpret included files as Markdown. Since the include command
is usually used for inserting code snippets and examples, you will often
wrap the command with ```` ``` ```` to display the file contents without
interpretting them.

View File

@@ -14,9 +14,11 @@ Here are the files you can override:
- **_index.hbs_** is the handlebars template.
- **_head.hbs_** is appended to the HTML `<head>` section.
- **_header.hbs_** content is appended on top of every book page.
- **_book.css_** is the style used in the output. If you want to change the
design of your book, this is probably the file you want to modify. Sometimes
in conjunction with `index.hbs` when you want to radically change the layout.
- **_css/_** contains the CSS files for styling the book.
- **_css/chrome.css_** is for UI elements.
- **_css/general.css_** is the base styles.
- **_css/print.css_** is the style for printer output.
- **_css/variables.css_** contains variables used in other CSS files.
- **_book.js_** is mostly used to add client side functionality, like hiding /
un-hiding the sidebar, changing the theme, ...
- **_highlight.js_** is the JavaScript that is used to highlight code snippets,

View File

@@ -19,7 +19,7 @@ Here is a list of the properties that are exposed:
- ***language*** Language of the book in the form `en`, as specified in `book.toml` (if not specified, defaults to `en`). To use in <code
class="language-html">\<html lang="{{ language }}"></code> for example.
- ***title*** Title used for the current page. This is identical to `{{ book_title }} - {{ chapter_title }}` unless `book_title` is not set in which case it just defaults to the `chapter_title`.
- ***title*** Title used for the current page. This is identical to `{{ chapter_title }} - {{ book_title }}` unless `book_title` is not set in which case it just defaults to the `chapter_title`.
- ***book_title*** Title of the book, as specified in `book.toml`
- ***chapter_title*** Title of the current chapter, as listed in `SUMMARY.md`

View File

@@ -1,16 +1,67 @@
# Syntax Highlighting
For syntax highlighting I use [Highlight.js](https://highlightjs.org) with a
custom theme.
mdBook uses [Highlight.js](https://highlightjs.org) with a custom theme
for syntax highlighting.
Automatic language detection has been turned off, so you will probably want to
specify the programming language you use like this
specify the programming language you use like this:
<pre><code class="language-markdown">```rust
~~~markdown
```rust
fn main() {
// Some code
}
```</code></pre>
```
~~~
## Supported languages
These languages are supported by default, but you can add more by supplying
your own `highlight.js` file:
- apache
- armasm
- bash
- c
- coffeescript
- cpp
- csharp
- css
- d
- diff
- go
- handlebars
- haskell
- http
- ini
- java
- javascript
- json
- julia
- kotlin
- less
- lua
- makefile
- markdown
- nginx
- objectivec
- perl
- php
- plaintext
- properties
- python
- r
- ruby
- rust
- scala
- scss
- shell
- sql
- swift
- typescript
- x86asm
- xml
- yaml
## Custom theme
Like the rest of the theme, the files used for syntax highlighting can be

View File

@@ -16,5 +16,6 @@ shout-out to them!
- [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))
If you feel you're missing from this list, feel free to add yourself in a PR.
If you feel you're missing from this list, feel free to add yourself in a PR.

View File

@@ -14,11 +14,12 @@ pub fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book>
let summary_md = src_dir.join("SUMMARY.md");
let mut summary_content = String::new();
File::open(summary_md)
.with_context(|| "Couldn't open SUMMARY.md")?
File::open(&summary_md)
.with_context(|| format!("Couldn't open SUMMARY.md in {:?} directory", src_dir))?
.read_to_string(&mut summary_content)?;
let summary = parse_summary(&summary_content).with_context(|| "Summary parsing failed")?;
let summary = parse_summary(&summary_content)
.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")?;
@@ -49,7 +50,9 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> {
}
debug!("Creating missing file {}", filename.display());
let mut f = File::create(&filename)?;
let mut f = File::create(&filename).with_context(|| {
format!("Unable to create missing file: {}", filename.display())
})?;
writeln!(f, "# {}", link.name)?;
}
}
@@ -63,7 +66,7 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> {
/// A dumb tree structure representing a book.
///
/// For the moment a book is just a collection of `BookItems` which are
/// For the moment a book is just a collection of [`BookItems`] which are
/// accessible by either iterating (immutably) over the book with [`iter()`], or
/// recursively applying a closure to each section to mutate the chapters, using
/// [`for_each_mut()`].
@@ -157,7 +160,7 @@ pub struct Chapter {
pub sub_items: Vec<BookItem>,
/// The chapter's location, relative to the `SUMMARY.md` file.
pub path: Option<PathBuf>,
/// An ordered list of the names of each chapter above this one, in the hierarchy.
/// An ordered list of the names of each chapter above this one in the hierarchy.
pub parent_names: Vec<String>,
}
@@ -178,8 +181,8 @@ impl Chapter {
}
}
/// Create a new draft chapter that is not attached to a source markdown file and has
/// thus no content.
/// Create a new draft chapter that is not attached to a source markdown file (and thus
/// has no content).
pub fn new_draft(name: &str, parent_names: Vec<String>) -> Self {
Chapter {
name: name.to_string(),
@@ -190,7 +193,7 @@ impl Chapter {
}
}
/// Check if the chapter is a draft chapter, meaning it has no path to a source markdown file
/// Check if the chapter is a draft chapter, meaning it has no path to a source markdown file.
pub fn is_draft_chapter(&self) -> bool {
match self.path {
Some(_) => false,
@@ -264,6 +267,10 @@ fn load_chapter<P: AsRef<Path>>(
format!("Unable to read \"{}\" ({})", link.name, location.display())
})?;
if content.as_bytes().starts_with(b"\xef\xbb\xbf") {
content.replace_range(..3, "");
}
let stripped = location
.strip_prefix(&src_dir)
.expect("Chapters are always inside a book");
@@ -273,7 +280,7 @@ fn load_chapter<P: AsRef<Path>>(
Chapter::new_draft(&link.name, parent_names.clone())
};
let mut sub_item_parents = parent_names.clone();
let mut sub_item_parents = parent_names;
ch.number = link.number.clone();
@@ -295,8 +302,6 @@ fn load_chapter<P: AsRef<Path>>(
///
/// This struct shouldn't be created directly, instead prefer the
/// [`Book::iter()`] method.
///
/// [`Book::iter()`]: struct.Book.html#method.iter
pub struct BookItems<'a> {
items: VecDeque<&'a BookItem>,
}
@@ -393,6 +398,29 @@ And here is some \
assert_eq!(got, should_be);
}
#[test]
fn load_a_single_chapter_with_utf8_bom_from_disk() {
let temp_dir = TempFileBuilder::new().prefix("book").tempdir().unwrap();
let chapter_path = temp_dir.path().join("chapter_1.md");
File::create(&chapter_path)
.unwrap()
.write_all(("\u{feff}".to_owned() + DUMMY_SRC).as_bytes())
.unwrap();
let link = Link::new("Chapter 1", chapter_path);
let should_be = Chapter::new(
"Chapter 1",
DUMMY_SRC.to_string(),
"chapter_1.md",
Vec::new(),
);
let got = load_chapter(&link, temp_dir.path(), Vec::new()).unwrap();
assert_eq!(got, should_be);
}
#[test]
fn cant_load_a_nonexistent_chapter() {
let link = Link::new("Chapter 1", "/foo/bar/baz.md");

View File

@@ -28,7 +28,7 @@ impl BookBuilder {
}
}
/// Set the `Config` to be used.
/// Set the [`Config`] to be used.
pub fn with_config(&mut self, cfg: Config) -> &mut BookBuilder {
self.config = cfg;
self
@@ -109,12 +109,8 @@ impl BookBuilder {
fn copy_across_theme(&self) -> Result<()> {
debug!("Copying theme");
let themedir = self
.config
.html_config()
.and_then(|html| html.theme)
.unwrap_or_else(|| self.config.book.src.join("theme"));
let themedir = self.root.join(themedir);
let html_config = self.config.html_config().unwrap_or_default();
let themedir = html_config.theme_dir(&self.root);
if !themedir.exists() {
debug!(
@@ -128,7 +124,9 @@ impl BookBuilder {
index.write_all(theme::INDEX)?;
let cssdir = themedir.join("css");
fs::create_dir(&cssdir)?;
if !cssdir.exists() {
fs::create_dir(&cssdir)?;
}
let mut general_css = File::create(cssdir.join("general.css"))?;
general_css.write_all(theme::GENERAL_CSS)?;
@@ -136,8 +134,10 @@ impl BookBuilder {
let mut chrome_css = File::create(cssdir.join("chrome.css"))?;
chrome_css.write_all(theme::CHROME_CSS)?;
let mut print_css = File::create(cssdir.join("print.css"))?;
print_css.write_all(theme::PRINT_CSS)?;
if html_config.print.enable {
let mut print_css = File::create(cssdir.join("print.css"))?;
print_css.write_all(theme::PRINT_CSS)?;
}
let mut variables_css = File::create(cssdir.join("variables.css"))?;
variables_css.write_all(theme::VARIABLES_CSS)?;

View File

@@ -40,7 +40,7 @@ pub struct MDBook {
pub book: Book,
renderers: Vec<Box<dyn Renderer>>,
/// List of pre-processors to be run on the book
/// List of pre-processors to be run on the book.
preprocessors: Vec<Box<dyn Preprocessor>>,
}
@@ -78,7 +78,7 @@ impl MDBook {
MDBook::load_with_config(book_root, config)
}
/// Load a book from its root directory using a custom config.
/// Load a book from its root directory using a custom `Config`.
pub fn load_with_config<P: Into<PathBuf>>(book_root: P, config: Config) -> Result<MDBook> {
let root = book_root.into();
@@ -97,7 +97,7 @@ impl MDBook {
})
}
/// Load a book from its root directory using a custom config and a custom summary.
/// Load a book from its root directory using a custom `Config` and a custom summary.
pub fn load_with_config_and_summary<P: Into<PathBuf>>(
book_root: P,
config: Config,
@@ -121,7 +121,7 @@ impl MDBook {
}
/// Returns a flat depth-first iterator over the elements of the book,
/// it returns an [BookItem enum](bookitem.html):
/// it returns a [`BookItem`] enum:
/// `(section: String, bookitem: &BookItem)`
///
/// ```no_run
@@ -180,7 +180,7 @@ impl MDBook {
Ok(())
}
/// Run the entire build process for a particular `Renderer`.
/// Run the entire build process for a particular [`Renderer`].
pub fn execute_build_process(&self, renderer: &dyn Renderer) -> Result<()> {
let mut preprocessed_book = self.book.clone();
let preprocess_ctx = PreprocessorContext::new(
@@ -219,14 +219,14 @@ impl MDBook {
}
/// You can change the default renderer to another one by using this method.
/// The only requirement is for your renderer to implement the [`Renderer`
/// trait](../renderer/trait.Renderer.html)
/// The only requirement is that your renderer implement the [`Renderer`]
/// trait.
pub fn with_renderer<R: Renderer + 'static>(&mut self, renderer: R) -> &mut Self {
self.renderers.push(Box::new(renderer));
self
}
/// Register a [`Preprocessor`](../preprocess/trait.Preprocessor.html) to be used when rendering the book.
/// Register a [`Preprocessor`] to be used when rendering the book.
pub fn with_preprocessor<P: Preprocessor + 'static>(&mut self, preprocessor: P) -> &mut Self {
self.preprocessors.push(Box::new(preprocessor));
self
@@ -250,6 +250,7 @@ impl MDBook {
// Index Preprocessor is disabled so that chapter paths continue to point to the
// actual markdown files.
let mut failed = false;
for item in book.iter() {
if let BookItem::Chapter(ref ch) = *item {
let chapter_path = match ch.path {
@@ -282,7 +283,8 @@ impl MDBook {
let output = cmd.output()?;
if !output.status.success() {
bail!(
failed = true;
error!(
"rustdoc returned an error:\n\
\n--- stdout\n{}\n--- stderr\n{}",
String::from_utf8_lossy(&output.stdout),
@@ -291,6 +293,9 @@ impl MDBook {
}
}
}
if failed {
bail!("One or more tests failed");
}
Ok(())
}
@@ -298,7 +303,7 @@ impl MDBook {
/// artefacts.
///
/// If there is only 1 renderer, put it in the directory pointed to by the
/// `build.build_dir` key in `Config`. If there is more than one then the
/// `build.build_dir` key in [`Config`]. If there is more than one then the
/// renderer gets its own directory within the main build dir.
///
/// i.e. If there were only one renderer (in this case, the HTML renderer):

View File

@@ -28,15 +28,11 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
// If flag `--theme` is present, copy theme to src
if args.is_present("theme") {
config.set("output.html.theme", "src/theme")?;
let theme_dir = book_dir.join("theme");
println!();
println!("Copying the default theme to {}", theme_dir.display());
// Skip this if `--force` is present
if !args.is_present("force") {
// Print warning
println!();
println!(
"Copying the default theme to {}",
builder.config().book.src.display()
);
if !args.is_present("force") && theme_dir.exists() {
println!("This could potentially overwrite files already present in that directory.");
print!("\nAre you sure you want to continue? (y/n) ");

View File

@@ -2,7 +2,7 @@
//!
//! The main entrypoint of the `config` module is the `Config` struct. This acts
//! essentially as a bag of configuration information, with a couple
//! pre-determined tables (`BookConfig` and `BuildConfig`) as well as support
//! pre-determined tables ([`BookConfig`] and [`BuildConfig`]) as well as support
//! for arbitrary data which is exposed to plugins and alternative backends.
//!
//!
@@ -352,6 +352,11 @@ impl Serialize for Config {
let book_config = Value::try_from(&self.book).expect("should always be serializable");
table.insert("book", book_config);
if self.build != BuildConfig::default() {
let build_config = Value::try_from(&self.build).expect("should always be serializable");
table.insert("build", build_config);
}
if self.rust != RustConfig::default() {
let rust_config = Value::try_from(&self.rust).expect("should always be serializable");
table.insert("rust", rust_config);
@@ -495,6 +500,8 @@ pub struct HtmlConfig {
/// Playground settings.
#[serde(alias = "playpen")]
pub playground: Playground,
/// Print settings.
pub print: Print,
/// Don't render section labels.
pub no_section_label: bool,
/// Search settings. If `None`, the default will be used.
@@ -508,6 +515,13 @@ pub struct HtmlConfig {
pub input_404: Option<String>,
/// Absolute url to site, used to emit correct paths for the 404 page, which might be accessed in a deeply nested directory
pub site_url: Option<String>,
/// The DNS subdomain or apex domain at which your book will be hosted. This
/// string will be written to a file named CNAME in the root of your site,
/// as required by GitHub Pages (see [*Managing a custom domain for your
/// GitHub Pages site*][custom domain]).
///
/// [custom domain]: https://docs.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site
pub cname: Option<String>,
/// This is used as a bit of a workaround for the `mdbook serve` command.
/// Basically, because you set the websocket port from the command line, the
/// `mdbook serve` command needs a way to let the HTML renderer know where
@@ -535,12 +549,14 @@ impl Default for HtmlConfig {
additional_js: Vec::new(),
fold: Fold::default(),
playground: Playground::default(),
print: Print::default(),
no_section_label: false,
search: None,
git_repository_url: None,
git_repository_icon: None,
input_404: None,
site_url: None,
cname: None,
livereload_url: None,
redirect: HashMap::new(),
}
@@ -558,6 +574,20 @@ impl HtmlConfig {
}
}
/// Configuration for how to render the print icon, print.html, and print.css.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct Print {
/// Whether print support is enabled.
pub enable: bool,
}
impl Default for Print {
fn default() -> Self {
Self { enable: true }
}
}
/// Configuration for how to fold chapters of sidebar.
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]

View File

@@ -76,9 +76,9 @@
//! access to the various methods for working with the [`Config`].
//!
//! [user guide]: https://rust-lang.github.io/mdBook/
//! [`RenderContext`]: renderer/struct.RenderContext.html
//! [`RenderContext`]: renderer::RenderContext
//! [relevant chapter]: https://rust-lang.github.io/mdBook/for_developers/backends.html
//! [`Config`]: config/struct.Config.html
//! [`Config`]: config::Config
#![deny(missing_docs)]
#![deny(rust_2018_idioms)]

View File

@@ -171,15 +171,15 @@ mod tests {
use crate::MDBook;
use std::path::Path;
fn book_example() -> MDBook {
let example = Path::new(env!("CARGO_MANIFEST_DIR")).join("book-example");
fn guide() -> MDBook {
let example = Path::new(env!("CARGO_MANIFEST_DIR")).join("guide");
MDBook::load(example).unwrap()
}
#[test]
fn round_trip_write_and_parse_input() {
let cmd = CmdPreprocessor::new("test".to_string(), "test".to_string());
let md = book_example();
let md = guide();
let ctx = PreprocessorContext::new(
md.root.clone(),
md.config.clone(),

View File

@@ -335,7 +335,7 @@ impl<'a> Link<'a> {
LinkType::Playground(ref pat, ref attrs) => {
let target = base.join(pat);
let contents = fs::read_to_string(&target).with_context(|| {
let mut contents = fs::read_to_string(&target).with_context(|| {
format!(
"Could not read file for link {} ({})",
self.link_text,
@@ -343,8 +343,11 @@ impl<'a> Link<'a> {
)
})?;
let ftype = if !attrs.is_empty() { "rust," } else { "rust" };
if !contents.ends_with('\n') {
contents.push('\n');
}
Ok(format!(
"```{}{}\n{}\n```\n",
"```{}{}\n{}```\n",
ftype,
attrs.join(","),
contents

View File

@@ -184,13 +184,19 @@ impl HtmlHandlebars {
write_file(
destination,
".nojekyll",
b"This file makes sure that Github Pages doesn't process mdBook's output.",
b"This file makes sure that Github Pages doesn't process mdBook's output.\n",
)?;
if let Some(cname) = &html_config.cname {
write_file(destination, "CNAME", format!("{}\n", cname).as_bytes())?;
}
write_file(destination, "book.js", &theme.js)?;
write_file(destination, "css/general.css", &theme.general_css)?;
write_file(destination, "css/chrome.css", &theme.chrome_css)?;
write_file(destination, "css/print.css", &theme.print_css)?;
if html_config.print.enable {
write_file(destination, "css/print.css", &theme.print_css)?;
}
write_file(destination, "css/variables.css", &theme.variables_css)?;
if let Some(contents) = &theme.favicon_png {
write_file(destination, "favicon.png", &contents)?;
@@ -360,7 +366,7 @@ impl HtmlHandlebars {
// Note: all paths are relative to the build directory, so the
// leading slash in an absolute path means nothing (and would mess
// up `root.join(original)`).
let original = original.trim_start_matches("/");
let original = original.trim_start_matches('/');
let filename = root.join(original);
self.emit_redirect(handlebars, &filename, new)?;
}
@@ -446,7 +452,7 @@ impl Renderer for HtmlHandlebars {
let mut handlebars = Handlebars::new();
let theme_dir = match html_config.theme {
Some(ref theme) => theme.to_path_buf(),
Some(ref theme) => ctx.root.join(theme),
None => ctx.root.join("theme"),
};
@@ -512,14 +518,16 @@ impl Renderer for HtmlHandlebars {
}
// Render the handlebars template with the data
debug!("Render template");
let rendered = handlebars.render("index", &data)?;
if html_config.print.enable {
debug!("Render template");
let rendered = handlebars.render("index", &data)?;
let rendered =
self.post_process(rendered, &html_config.playground, ctx.config.rust.edition);
let rendered =
self.post_process(rendered, &html_config.playground, ctx.config.rust.edition);
utils::fs::write_file(&destination, "print.html", rendered.as_bytes())?;
debug!("Creating print.html ✓");
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)
@@ -640,8 +648,9 @@ fn make_data(
data.insert("playground_copyable".to_owned(), json!(true));
}
data.insert("fold_enable".to_owned(), json!((html_config.fold.enable)));
data.insert("fold_level".to_owned(), json!((html_config.fold.level)));
data.insert("print_enable".to_owned(), json!(html_config.print.enable));
data.insert("fold_enable".to_owned(), json!(html_config.fold.enable));
data.insert("fold_level".to_owned(), json!(html_config.fold.level));
let search = html_config.search.clone();
if cfg!(feature = "search") {
@@ -890,10 +899,10 @@ fn partition_source(s: &str) -> (String, String) {
if !header || after_header {
after_header = true;
after.push_str(line);
after.push_str("\n");
after.push('\n');
} else {
before.push_str(line);
before.push_str("\n");
before.push('\n');
}
}

View File

@@ -1,4 +1,5 @@
use std::collections::BTreeMap;
use std::io;
use std::path::Path;
use crate::utils;
@@ -102,38 +103,38 @@ impl HelperDef for RenderToc {
// Part title
if let Some(title) = item.get("part") {
out.write("<li class=\"part-title\">")?;
out.write(title)?;
write_escaped(out, title)?;
out.write("</li>")?;
continue;
}
// Link
let path_exists = if let Some(path) = item.get("path") {
if !path.is_empty() {
out.write("<a href=\"")?;
let path_exists = if let Some(path) =
item.get("path")
.and_then(|p| if p.is_empty() { None } else { Some(p) })
{
out.write("<a href=\"")?;
let tmp = Path::new(item.get("path").expect("Error: path should be Some(_)"))
.with_extension("html")
.to_str()
.unwrap()
// Hack for windows who tends to use `\` as separator instead of `/`
.replace("\\", "/");
let tmp = Path::new(item.get("path").expect("Error: path should be Some(_)"))
.with_extension("html")
.to_str()
.unwrap()
// Hack for windows who tends to use `\` as separator instead of `/`
.replace("\\", "/");
// Add link
out.write(&utils::fs::path_to_root(&current_path))?;
out.write(&tmp)?;
out.write("\"")?;
// Add link
out.write(&utils::fs::path_to_root(&current_path))?;
out.write(&tmp)?;
out.write("\"")?;
if path == &current_path {
out.write(" class=\"active\"")?;
}
out.write(">")?;
true
} else {
false
if path == &current_path {
out.write(" class=\"active\"")?;
}
out.write(">")?;
true
} else {
out.write("<div>")?;
false
};
@@ -160,11 +161,13 @@ impl HelperDef for RenderToc {
html::push_html(&mut markdown_parsed_name, parser);
// write to the handlebars template
out.write(&markdown_parsed_name)?;
write_escaped(out, &markdown_parsed_name)?;
}
if path_exists {
out.write("</a>")?;
} else {
out.write("</div>")?;
}
// Render expand/collapse toggle
@@ -202,3 +205,18 @@ fn write_li_open_tag(
li.push_str("\">");
out.write(&li)
}
fn write_escaped(out: &mut dyn Output, mut title: &str) -> io::Result<()> {
let needs_escape: &[char] = &['<', '>'];
while let Some(next) = title.find(needs_escape) {
out.write(&title[..next])?;
match title.as_bytes()[next] {
b'<' => out.write("&lt;")?,
b'>' => out.write("&gt;")?,
_ => unreachable!(),
}
title = &title[next + 1..];
}
out.write(title)?;
Ok(())
}

View File

@@ -95,6 +95,8 @@ fn render_item(
let mut breadcrumbs = chapter.parent_names.clone();
let mut footnote_numbers = HashMap::new();
breadcrumbs.push(chapter.name.clone());
while let Some(event) = p.next() {
match event {
Event::Start(Tag::Heading(i)) if i <= max_section_depth => {

View File

@@ -20,7 +20,7 @@ mod markdown_renderer;
use shlex::Shlex;
use std::fs;
use std::io::{self, ErrorKind, Read};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use crate::book::Book;
@@ -34,12 +34,9 @@ use toml::Value;
/// provide your own renderer, there are two main renderer implementations that
/// 99% of users will ever use:
///
/// - [HtmlHandlebars] - the built-in HTML renderer
/// - [CmdRenderer] - a generic renderer which shells out to a program to do the
/// - [`HtmlHandlebars`] - the built-in HTML renderer
/// - [`CmdRenderer`] - a generic renderer which shells out to a program to do the
/// actual rendering
///
/// [HtmlHandlebars]: struct.HtmlHandlebars.html
/// [CmdRenderer]: struct.CmdRenderer.html
pub trait Renderer {
/// The `Renderer`'s name.
fn name(&self) -> &str;
@@ -133,14 +130,44 @@ impl CmdRenderer {
CmdRenderer { name, cmd }
}
fn compose_command(&self) -> Result<Command> {
fn compose_command(&self, root: &Path, destination: &Path) -> Result<Command> {
let mut words = Shlex::new(&self.cmd);
let executable = match words.next() {
Some(e) => e,
let exe = match words.next() {
Some(e) => PathBuf::from(e),
None => bail!("Command string was empty"),
};
let mut cmd = Command::new(executable);
let exe = if exe.components().count() == 1 {
// Search PATH for the executable.
exe
} else {
// Relative paths are preferred to be relative to the book root.
let abs_exe = root.join(&exe);
if abs_exe.exists() {
abs_exe
} else {
// Historically paths were relative to the destination, but
// this is not the preferred way.
let legacy_path = destination.join(&exe);
if legacy_path.exists() {
warn!(
"Renderer command `{}` uses a path relative to the \
renderer output directory `{}`. This was previously \
accepted, but has been deprecated. Relative executable \
paths should be relative to the book root.",
exe.display(),
destination.display()
);
legacy_path
} else {
// Let this bubble through to later be handled by
// handle_render_command_error.
abs_exe.to_path_buf()
}
}
};
let mut cmd = Command::new(exe);
for arg in words {
cmd.arg(arg);
@@ -195,7 +222,7 @@ impl Renderer for CmdRenderer {
let _ = fs::create_dir_all(&ctx.destination);
let mut child = match self
.compose_command()?
.compose_command(&ctx.root, &ctx.destination)?
.stdin(Stdio::piped())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())

View File

@@ -96,6 +96,5 @@
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 500;
src: local('Source Code Pro Medium'), local('SourceCodePro-Medium'),
url('source-code-pro-v11-all-charsets-500.woff2') format('woff2');
src: url('source-code-pro-v11-all-charsets-500.woff2') format('woff2');
}

View File

@@ -29,7 +29,9 @@
<link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
<link rel="stylesheet" href="{{ path_to_root }}css/general.css">
<link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
{{#if print_enable}}
<link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
{{/if}}
<!-- Fonts -->
<link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
@@ -136,9 +138,11 @@
<h1 class="menu-title">{{ book_title }}</h1>
<div class="right-buttons">
{{#if print_enable}}
<a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
{{/if}}
{{#if git_repository_url}}
<a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa {{git_repository_icon}}"></i>

View File

@@ -145,6 +145,11 @@ window.search = window.search || {};
url.push("");
}
// encodeURIComponent escapes all chars that could allow an XSS except
// for '. Due to that we also manually replace ' with its url-encoded
// representation (%27).
var searchterms = encodeURIComponent(searchterms.join(" ")).replace(/\'/g, "%27");
return '<a href="' + path_to_root + url[0] + '?' + URL_MARK_PARAM + '=' + searchterms + '#' + url[1]
+ '" aria-details="teaser_' + teaser_count + '">' + result.doc.breadcrumbs + '</a>'
+ '<span class="teaser" id="teaser_' + teaser_count + '" aria-label="Search Result Teaser">'
@@ -291,7 +296,7 @@ window.search = window.search || {};
}
if (url.params.hasOwnProperty(URL_MARK_PARAM)) {
var words = url.params[URL_MARK_PARAM].split(' ');
var words = decodeURIComponent(url.params[URL_MARK_PARAM]).split(' ');
marker.mark(words, {
exclude: mark_exclude
});
@@ -422,6 +427,7 @@ window.search = window.search || {};
delete url.params[URL_MARK_PARAM];
url.hash = "";
} else {
delete url.params[URL_MARK_PARAM];
delete url.params[URL_SEARCH_PARAM];
}
// A new search will also add a new history item, so the user can go back

View File

@@ -110,7 +110,10 @@ pub fn copy_files_except_ext(
for entry in fs::read_dir(from)? {
let entry = entry?;
let metadata = entry.metadata()?;
let metadata = entry
.path()
.metadata()
.with_context(|| format!("Failed to read {:?}", entry.path()))?;
// If the entry is a dir and the recursive option is enabled, call itself
if metadata.is_dir() && recursive {
@@ -187,7 +190,17 @@ pub fn get_404_output_file(input_404: &Option<String>) -> String {
#[cfg(test)]
mod tests {
use super::copy_files_except_ext;
use std::fs;
use std::{fs, io::Result, path::Path};
#[cfg(target_os = "windows")]
fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
std::os::windows::fs::symlink_file(src, dst)
}
#[cfg(not(target_os = "windows"))]
fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
std::os::unix::fs::symlink(src, dst)
}
#[test]
fn copy_files_except_ext_test() {
@@ -218,6 +231,12 @@ mod tests {
if let Err(err) = fs::File::create(&tmp.path().join("sub_dir_exists/file.txt")) {
panic!("Could not create sub_dir_exists/file.txt: {}", err);
}
if let Err(err) = symlink(
&tmp.path().join("file.png"),
&tmp.path().join("symlink.png"),
) {
panic!("Could not symlink file.png: {}", err);
}
// Create output dir
if let Err(err) = fs::create_dir(&tmp.path().join("output")) {
@@ -249,5 +268,8 @@ mod tests {
if !(&tmp.path().join("output/sub_dir_exists/file.txt")).exists() {
panic!("output/sub_dir/file.png should exist")
}
if !(&tmp.path().join("output/symlink.png")).exists() {
panic!("output/symlink.png should exist")
}
}
}

View File

@@ -70,7 +70,7 @@ pub fn take_rustdoc_include_lines<R: RangeBounds<usize>>(s: &str, range: R) -> S
output.push_str("# ");
}
output.push_str(line);
output.push_str("\n");
output.push('\n');
}
output.pop();
output
@@ -95,7 +95,7 @@ pub fn take_rustdoc_include_anchored_lines(s: &str, anchor: &str) -> String {
None => {
if !ANCHOR_START.is_match(l) {
output.push_str(l);
output.push_str("\n");
output.push('\n');
}
}
}
@@ -106,7 +106,7 @@ pub fn take_rustdoc_include_anchored_lines(s: &str, anchor: &str) -> String {
} else if !ANCHOR_END.is_match(l) {
output.push_str("# ");
output.push_str(l);
output.push_str("\n");
output.push('\n');
}
}

View File

@@ -53,7 +53,7 @@ impl TomlExt for Value {
}
fn split(key: &str) -> Option<(&str, &str)> {
let ix = key.find(".")?;
let ix = key.find('.')?;
let (head, tail) = key.split_at(ix);
// splitting will leave the "."

View File

@@ -2,7 +2,7 @@
use mdbook::config::Config;
use mdbook::MDBook;
#[cfg(not(windows))]
use std::fs;
use std::path::Path;
use tempfile::{Builder as TempFileBuilder, TempDir};
@@ -71,6 +71,45 @@ fn backends_receive_render_context_via_stdin() {
assert!(got.is_ok());
}
#[test]
fn relative_command_path() {
// Checks behavior of relative paths for the `command` setting.
let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap();
let renderers = temp.path().join("renderers");
fs::create_dir(&renderers).unwrap();
rust_exe(
&renderers,
"myrenderer",
r#"fn main() {
std::fs::write("output", "test").unwrap();
}"#,
);
let do_test = |cmd_path| {
let mut config = Config::default();
config
.set("output.html", toml::value::Table::new())
.unwrap();
config.set("output.myrenderer.command", cmd_path).unwrap();
let md = MDBook::init(&temp.path())
.with_config(config)
.build()
.unwrap();
let output = temp.path().join("book/myrenderer/output");
assert!(!output.exists());
md.build().unwrap();
assert!(output.exists());
fs::remove_file(output).unwrap();
};
// Legacy paths work, relative to the output directory.
if cfg!(windows) {
do_test("../../renderers/myrenderer.exe");
} else {
do_test("../../renderers/myrenderer");
}
// Modern path, relative to the book directory.
do_test("renderers/myrenderer");
}
fn dummy_book_with_backend(
name: &str,
command: &str,
@@ -112,3 +151,14 @@ fn success_cmd() -> &'static str {
"true"
}
}
fn rust_exe(temp: &Path, name: &str, src: &str) {
let rs = temp.join(name).with_extension("rs");
fs::write(&rs, src).unwrap();
let status = std::process::Command::new("rustc")
.arg(rs)
.current_dir(temp)
.status()
.expect("rustc should run");
assert!(status.success());
}

View File

@@ -135,11 +135,11 @@ fn recursive_copy<A: AsRef<Path>, B: AsRef<Path>>(from: A, to: B) -> Result<()>
}
pub fn new_copy_of_example_book() -> Result<TempDir> {
let temp = TempFileBuilder::new().prefix("book-example").tempdir()?;
let temp = TempFileBuilder::new().prefix("guide").tempdir()?;
let book_example = Path::new(env!("CARGO_MANIFEST_DIR")).join("book-example");
let guide = Path::new(env!("CARGO_MANIFEST_DIR")).join("guide");
recursive_copy(book_example, temp.path())?;
recursive_copy(guide, temp.path())?;
Ok(temp)
}

View File

@@ -91,6 +91,12 @@ fn run_mdbook_init_with_custom_book_and_src_locations() {
file
);
}
let contents = fs::read_to_string(temp.path().join("book.toml")).unwrap();
assert_eq!(
contents,
"[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"in\"\n\n[build]\nbuild-dir = \"out\"\ncreate-missing = true\nuse-default-preprocessors = true\n"
);
}
#[test]
@@ -102,3 +108,37 @@ fn book_toml_isnt_required() {
md.build().unwrap();
}
#[test]
fn copy_theme() {
let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap();
MDBook::init(temp.path()).copy_theme(true).build().unwrap();
let expected = vec![
"book.js",
"css/chrome.css",
"css/general.css",
"css/print.css",
"css/variables.css",
"favicon.png",
"favicon.svg",
"highlight.css",
"highlight.js",
"index.hbs",
];
let theme_dir = temp.path().join("theme");
let mut actual: Vec<_> = walkdir::WalkDir::new(&theme_dir)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| !e.file_type().is_dir())
.map(|e| {
e.path()
.strip_prefix(&theme_dir)
.unwrap()
.to_str()
.unwrap()
.replace('\\', "/")
})
.collect();
actual.sort();
assert_eq!(actual, expected);
}

View File

@@ -345,7 +345,7 @@ fn create_missing_file_with_config() {
}
/// This makes sure you can include a Rust file with `{{#playground example.rs}}`.
/// Specification is in `book-example/src/format/rust.md`
/// Specification is in `guide/src/format/rust.md`
#[test]
fn able_to_include_playground_files_in_chapters() {
let temp = DummyBook::new().build().unwrap();
@@ -595,7 +595,10 @@ mod search {
docs[&summary]["body"],
"Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode Second Chapter Nested Chapter Conclusion"
);
assert_eq!(docs[&summary]["breadcrumbs"], "First Chapter » Summary");
assert_eq!(
docs[&summary]["breadcrumbs"],
"First Chapter » Includes » Summary"
);
assert_eq!(docs[&conclusion]["body"], "I put &lt;HTML&gt; in here!");
}

View File

@@ -27,234 +27,234 @@
"docInfo": {
"0": {
"body": 9,
"breadcrumbs": 2,
"breadcrumbs": 4,
"title": 2
},
"1": {
"body": 3,
"breadcrumbs": 1,
"breadcrumbs": 2,
"title": 1
},
"10": {
"body": 16,
"breadcrumbs": 3,
"breadcrumbs": 4,
"title": 1
},
"11": {
"body": 3,
"breadcrumbs": 4,
"breadcrumbs": 5,
"title": 2
},
"12": {
"body": 4,
"breadcrumbs": 3,
"breadcrumbs": 4,
"title": 1
},
"13": {
"body": 12,
"breadcrumbs": 3,
"breadcrumbs": 4,
"title": 1
},
"14": {
"body": 2,
"breadcrumbs": 3,
"breadcrumbs": 4,
"title": 1
},
"15": {
"body": 3,
"breadcrumbs": 3,
"breadcrumbs": 4,
"title": 1
},
"16": {
"body": 29,
"breadcrumbs": 5,
"breadcrumbs": 6,
"title": 3
},
"17": {
"body": 20,
"breadcrumbs": 2,
"breadcrumbs": 4,
"title": 2
},
"18": {
"body": 18,
"breadcrumbs": 7,
"breadcrumbs": 9,
"title": 5
},
"19": {
"body": 0,
"breadcrumbs": 3,
"breadcrumbs": 5,
"title": 1
},
"2": {
"body": 2,
"breadcrumbs": 2,
"breadcrumbs": 4,
"title": 2
},
"20": {
"body": 3,
"breadcrumbs": 1,
"breadcrumbs": 2,
"title": 1
},
"3": {
"body": 0,
"breadcrumbs": 1,
"breadcrumbs": 3,
"title": 1
},
"4": {
"body": 4,
"breadcrumbs": 4,
"breadcrumbs": 6,
"title": 2
},
"5": {
"body": 1,
"breadcrumbs": 3,
"breadcrumbs": 5,
"title": 1
},
"6": {
"body": 21,
"breadcrumbs": 9,
"breadcrumbs": 11,
"title": 7
},
"7": {
"body": 6,
"breadcrumbs": 8,
"breadcrumbs": 10,
"title": 6
},
"8": {
"body": 6,
"breadcrumbs": 6,
"breadcrumbs": 8,
"title": 4
},
"9": {
"body": 0,
"breadcrumbs": 3,
"breadcrumbs": 4,
"title": 1
}
},
"docs": {
"0": {
"body": "This file is just here to cause the index preprocessor to run. Does a pretty good job, too.",
"breadcrumbs": "Dummy Book",
"breadcrumbs": "Dummy Book » Dummy Book",
"id": "0",
"title": "Dummy Book"
},
"1": {
"body": "Here's some interesting text...",
"breadcrumbs": "Introduction",
"breadcrumbs": "Introduction » Introduction",
"id": "1",
"title": "Introduction"
},
"10": {
"body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode Second Chapter Nested Chapter Conclusion",
"breadcrumbs": "First Chapter » Summary",
"breadcrumbs": "First Chapter » Includes » Summary",
"id": "10",
"title": "Summary"
},
"11": {
"body": "Tests for some markdown output.",
"breadcrumbs": "First Chapter » Markdown tests",
"breadcrumbs": "First Chapter » Markdown » Markdown tests",
"id": "11",
"title": "Markdown tests"
},
"12": {
"body": "foo bar baz bim",
"breadcrumbs": "First Chapter » Tables",
"breadcrumbs": "First Chapter » Markdown » Tables",
"id": "12",
"title": "Tables"
},
"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 » Footnotes",
"breadcrumbs": "First Chapter » Markdown » Footnotes",
"id": "13",
"title": "Footnotes"
},
"14": {
"body": "strikethrough example",
"breadcrumbs": "First Chapter » Strikethrough",
"breadcrumbs": "First Chapter » Markdown » Strikethrough",
"id": "14",
"title": "Strikethrough"
},
"15": {
"body": "Apples Broccoli Carrots",
"breadcrumbs": "First Chapter » Tasklisks",
"breadcrumbs": "First Chapter » Markdown » Tasklisks",
"id": "15",
"title": "Tasklisks"
},
"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 stress tests",
"breadcrumbs": "First Chapter » Unicode » Unicode stress tests",
"id": "16",
"title": "Unicode stress tests"
},
"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",
"breadcrumbs": "Second Chapter » Second Chapter",
"id": "17",
"title": "Second Chapter"
},
"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 » Testing relative links for the print page",
"breadcrumbs": "Second Chapter » Nested Chapter » Testing relative links for the print page",
"id": "18",
"title": "Testing relative links for the print page"
},
"19": {
"body": "",
"breadcrumbs": "Second Chapter » Some section",
"breadcrumbs": "Second Chapter » Nested Chapter » Some section",
"id": "19",
"title": "Some section"
},
"2": {
"body": "more text.",
"breadcrumbs": "First Chapter",
"breadcrumbs": "First Chapter » First Chapter",
"id": "2",
"title": "First Chapter"
},
"20": {
"body": "I put &lt;HTML&gt; in here!",
"breadcrumbs": "Conclusion",
"breadcrumbs": "Conclusion » Conclusion",
"id": "20",
"title": "Conclusion"
},
"3": {
"body": "",
"breadcrumbs": "Some Section",
"breadcrumbs": "First Chapter » Some Section",
"id": "3",
"title": "Some Section"
},
"4": {
"body": "This file has some testable code. assert!(true);",
"breadcrumbs": "First Chapter » Nested Chapter",
"breadcrumbs": "First Chapter » Nested Chapter » Nested Chapter",
"id": "4",
"title": "Nested Chapter"
},
"5": {
"body": "assert!(true);",
"breadcrumbs": "First Chapter » Some Section",
"breadcrumbs": "First Chapter » Nested Chapter » Some Section",
"id": "5",
"title": "Some Section"
},
"6": {
"body": "// The next line will cause a `rendered_output` test to fail if the anchor feature is broken in\n// such a way that the content between anchors isn't included.\n// unique-string-for-anchor-test\nassert!(true);",
"breadcrumbs": "First Chapter » Anchors include the part of a file between special comments",
"breadcrumbs": "First Chapter » Nested Chapter » Anchors include the part of a file between special comments",
"id": "6",
"title": "Anchors include the part of a file between special comments"
},
"7": {
"body": "# fn some_function() {\n# assert!(true);\n# }\n# fn main() { some_function();\n}",
"breadcrumbs": "First Chapter » Rustdoc include adds the rest of the file as hidden",
"breadcrumbs": "First Chapter » Nested Chapter » Rustdoc include adds the rest of the file as hidden",
"id": "7",
"title": "Rustdoc include adds the rest of the file as hidden"
},
"8": {
"body": "# fn some_other_function() {\n# assert!(true);\n# }\n# fn main() { some_other_function();\n}",
"breadcrumbs": "First Chapter » Rustdoc include works with anchors too",
"breadcrumbs": "First Chapter » Nested Chapter » Rustdoc include works with anchors too",
"id": "8",
"title": "Rustdoc include works with anchors too"
},
"9": {
"body": "",
"breadcrumbs": "First Chapter » Includes",
"breadcrumbs": "First Chapter » Includes » Includes",
"id": "9",
"title": "Includes"
}
@@ -3048,7 +3048,7 @@
"df": 2,
"docs": {
"0": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
},
"10": {
"tf": 1.0
@@ -3222,7 +3222,7 @@
"df": 0,
"docs": {},
"r": {
"df": 17,
"df": 18,
"docs": {
"10": {
"tf": 2.23606797749979
@@ -3246,31 +3246,34 @@
"tf": 1.0
},
"17": {
"tf": 1.4142135623730951
},
"18": {
"tf": 1.0
},
"19": {
"tf": 1.0
},
"2": {
"tf": 1.4142135623730951
},
"4": {
"tf": 1.7320508075688772
},
"5": {
"18": {
"tf": 1.4142135623730951
},
"19": {
"tf": 1.4142135623730951
},
"2": {
"tf": 1.7320508075688772
},
"3": {
"tf": 1.0
},
"4": {
"tf": 2.0
},
"5": {
"tf": 1.4142135623730951
},
"6": {
"tf": 1.0
"tf": 1.4142135623730951
},
"7": {
"tf": 1.0
"tf": 1.4142135623730951
},
"8": {
"tf": 1.0
"tf": 1.4142135623730951
},
"9": {
"tf": 1.0
@@ -3379,7 +3382,7 @@
"tf": 1.0
},
"20": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
}
}
}
@@ -3467,7 +3470,7 @@
"df": 2,
"docs": {
"0": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
},
"10": {
"tf": 1.0
@@ -3672,7 +3675,7 @@
"df": 0,
"docs": {},
"t": {
"df": 15,
"df": 16,
"docs": {
"10": {
"tf": 1.4142135623730951
@@ -3699,7 +3702,10 @@
"tf": 1.0
},
"2": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
},
"3": {
"tf": 1.0
},
"4": {
"tf": 1.0
@@ -3964,7 +3970,7 @@
"df": 5,
"docs": {
"10": {
"tf": 1.0
"tf": 1.4142135623730951
},
"6": {
"tf": 1.7320508075688772
@@ -3976,7 +3982,7 @@
"tf": 1.4142135623730951
},
"9": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
}
}
},
@@ -4065,7 +4071,7 @@
"df": 2,
"docs": {
"1": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
},
"10": {
"tf": 1.0
@@ -4282,13 +4288,25 @@
"df": 0,
"docs": {},
"n": {
"df": 2,
"df": 6,
"docs": {
"10": {
"tf": 1.0
},
"11": {
"tf": 1.7320508075688772
"tf": 2.0
},
"12": {
"tf": 1.0
},
"13": {
"tf": 1.0
},
"14": {
"tf": 1.0
},
"15": {
"tf": 1.0
}
}
}
@@ -4361,13 +4379,31 @@
"df": 0,
"docs": {},
"t": {
"df": 2,
"df": 8,
"docs": {
"10": {
"tf": 1.4142135623730951
},
"18": {
"tf": 1.0
},
"19": {
"tf": 1.0
},
"4": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
},
"5": {
"tf": 1.0
},
"6": {
"tf": 1.0
},
"7": {
"tf": 1.0
},
"8": {
"tf": 1.0
}
}
}
@@ -4843,7 +4879,7 @@
"tf": 1.0
},
"17": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
},
"18": {
"tf": 1.0
@@ -5385,7 +5421,7 @@
"tf": 1.0
},
"16": {
"tf": 1.4142135623730951
"tf": 1.7320508075688772
}
}
},