Merge remote-tracking branch 'upstream/master' into localization
# Conflicts: # .gitignore # guide/src/en/cli/completions.md # guide/src/en/format/images/rust-logo-blk.svg # guide/src/en/format/markdown.md # guide/src/en/misc/introduction.md # src/renderer/html_handlebars/hbs_renderer.rs # src/utils/mod.rs
This commit is contained in:
commit
7305e8c60d
|
@ -48,4 +48,4 @@ jobs:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
run: rustup update stable && rustup default stable && rustup component add rustfmt
|
run: rustup update stable && rustup default stable && rustup component add rustfmt
|
||||||
- run: cargo fmt -- --check
|
- run: cargo fmt --check
|
||||||
|
|
|
@ -9,6 +9,7 @@ guide/book
|
||||||
.vscode
|
.vscode
|
||||||
tests/dummy_book/book/
|
tests/dummy_book/book/
|
||||||
tests/localized_book/book/
|
tests/localized_book/book/
|
||||||
|
test_book/book/
|
||||||
|
|
||||||
# Ignore Jetbrains specific files.
|
# Ignore Jetbrains specific files.
|
||||||
.idea/
|
.idea/
|
||||||
|
|
50
CHANGELOG.md
50
CHANGELOG.md
|
@ -1,5 +1,55 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## mdBook 0.4.15
|
||||||
|
[5eb7d46...68a5c09](https://github.com/rust-lang/mdBook/compare/5eb7d46...68a5c09)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Major update to expand the documentation located at <https://rust-lang.github.io/mdBook/>.
|
||||||
|
[#1709](https://github.com/rust-lang/mdBook/pull/1709)
|
||||||
|
[#1710](https://github.com/rust-lang/mdBook/pull/1710)
|
||||||
|
- Updated the markdown parser with various fixes for common-mark compliance.
|
||||||
|
[#1712](https://github.com/rust-lang/mdBook/pull/1712)
|
||||||
|
|
||||||
|
## mdBook 0.4.14
|
||||||
|
[ffa8284...c9b6be8](https://github.com/rust-lang/mdBook/compare/ffa8284...c9b6be8)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- The 2021 Rust edition option has been stabilized.
|
||||||
|
[#1642](https://github.com/rust-lang/mdBook/pull/1642)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Header anchors no longer include any HTML tags. Previously only a small
|
||||||
|
subset were excluded.
|
||||||
|
[#1683](https://github.com/rust-lang/mdBook/pull/1683)
|
||||||
|
- Deprecated the google-analytics option. Books using this option should place
|
||||||
|
the appropriate code in the `theme/head.hbs` file instead.
|
||||||
|
[#1675](https://github.com/rust-lang/mdBook/pull/1675)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Updated the markdown parser which brings in a few small fixes and removes
|
||||||
|
the custom smart quote handling.
|
||||||
|
[#1668](https://github.com/rust-lang/mdBook/pull/1668)
|
||||||
|
- Fixed iOS Safari enlarging text when going into landscape mode.
|
||||||
|
[#1685](https://github.com/rust-lang/mdBook/pull/1685)
|
||||||
|
|
||||||
|
## 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
|
## mdBook 0.4.12
|
||||||
[14add9c...8b4e488](https://github.com/rust-lang/mdBook/compare/14add9c...8b4e488)
|
[14add9c...8b4e488](https://github.com/rust-lang/mdBook/compare/14add9c...8b4e488)
|
||||||
|
|
||||||
|
|
|
@ -127,4 +127,4 @@ The following are instructions for updating [highlight.js](https://highlightjs.o
|
||||||
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. 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. 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. 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.)
|
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. The [test_book](https://github.com/rust-lang/mdBook/tree/master/test_book) contains a chapter with many languages to examine.
|
||||||
|
|
|
@ -41,6 +41,20 @@ version = "1.0.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf"
|
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]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -115,6 +129,17 @@ dependencies = [
|
||||||
"byte-tools",
|
"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]]
|
[[package]]
|
||||||
name = "byte-tools"
|
name = "byte-tools"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -198,6 +223,12 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "difflib"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
|
@ -216,6 +247,18 @@ dependencies = [
|
||||||
"generic-array 0.14.4",
|
"generic-array 0.14.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "doc-comment"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "elasticlunr-rs"
|
name = "elasticlunr-rs"
|
||||||
version = "2.3.13"
|
version = "2.3.13"
|
||||||
|
@ -262,6 +305,15 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"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]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -421,15 +473,6 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getopts"
|
|
||||||
version = "0.2.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-width",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
|
@ -689,6 +732,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
|
@ -778,10 +830,11 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mdbook"
|
name = "mdbook"
|
||||||
version = "0.4.12"
|
version = "0.4.15"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"assert_cmd",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"elasticlunr-rs",
|
"elasticlunr-rs",
|
||||||
|
@ -794,7 +847,8 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
"notify",
|
"notify",
|
||||||
"open",
|
"opener",
|
||||||
|
"predicates",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -807,6 +861,7 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
|
"topological-sort",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"warp",
|
"warp",
|
||||||
]
|
]
|
||||||
|
@ -915,6 +970,12 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "normalize-line-endings"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notify"
|
name = "notify"
|
||||||
version = "4.0.17"
|
version = "4.0.17"
|
||||||
|
@ -984,12 +1045,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open"
|
name = "opener"
|
||||||
version = "2.0.1"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b46b233de7d83bc167fe43ae2dda3b5b84e80e09cceba581e4decb958a4896bf"
|
checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pathdiff",
|
"bstr",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1002,12 +1063,6 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pathdiff"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "877630b3de15c0b64cc52f659345724fbf6bdad9bd9566699fc53688f3c34a34"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
@ -1139,6 +1194,36 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
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]]
|
[[package]]
|
||||||
name = "pretty_assertions"
|
name = "pretty_assertions"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -1174,12 +1259,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pulldown-cmark"
|
name = "pulldown-cmark"
|
||||||
version = "0.7.2"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55"
|
checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"getopts",
|
|
||||||
"memchr",
|
"memchr",
|
||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
|
@ -1316,6 +1400,12 @@ dependencies = [
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.25"
|
version = "0.6.25"
|
||||||
|
@ -1365,21 +1455,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.11.0"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
|
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
||||||
dependencies = [
|
|
||||||
"semver-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver-parser"
|
|
||||||
version = "0.10.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
|
|
||||||
dependencies = [
|
|
||||||
"pest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
|
@ -1677,6 +1755,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "topological-sort"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1704,6 +1788,12 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "treeline"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try-lock"
|
name = "try-lock"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -1813,6 +1903,15 @@ version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
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]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mdbook"
|
name = "mdbook"
|
||||||
version = "0.4.12"
|
version = "0.4.15"
|
||||||
authors = [
|
authors = [
|
||||||
"Mathieu David <mathieudavid@mathieudavid.org>",
|
"Mathieu David <mathieudavid@mathieudavid.org>",
|
||||||
"Michael-F-Bryan <michaelfbryan@gmail.com>",
|
"Michael-F-Bryan <michaelfbryan@gmail.com>",
|
||||||
|
@ -25,8 +25,8 @@ http = "0.2.4"
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
memchr = "2.0"
|
memchr = "2.0"
|
||||||
open = "2.0"
|
opener = "0.5"
|
||||||
pulldown-cmark = "0.7.0"
|
pulldown-cmark = { version = "0.9.1", default-features = false }
|
||||||
regex = "1.0.0"
|
regex = "1.0.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
@ -34,6 +34,7 @@ serde_json = "1.0"
|
||||||
shlex = "1"
|
shlex = "1"
|
||||||
tempfile = "3.0"
|
tempfile = "3.0"
|
||||||
toml = "0.5.1"
|
toml = "0.5.1"
|
||||||
|
topological-sort = "0.1.0"
|
||||||
|
|
||||||
# Watch feature
|
# Watch feature
|
||||||
notify = { version = "4.0", optional = true }
|
notify = { version = "4.0", optional = true }
|
||||||
|
@ -49,8 +50,10 @@ elasticlunr-rs = { version = "2.3", optional = true, default-features = false }
|
||||||
ammonia = { version = "3", optional = true }
|
ammonia = { version = "3", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
assert_cmd = "1"
|
||||||
|
predicates = "2"
|
||||||
select = "0.5"
|
select = "0.5"
|
||||||
semver = "0.11.0"
|
semver = "1.0"
|
||||||
pretty_assertions = "0.6"
|
pretty_assertions = "0.6"
|
||||||
walkdir = "2.0"
|
walkdir = "2.0"
|
||||||
|
|
||||||
|
|
224
README.md
224
README.md
|
@ -6,233 +6,15 @@
|
||||||
|
|
||||||
mdBook is a utility to create modern online books from Markdown files.
|
mdBook is a utility to create modern online books from Markdown files.
|
||||||
|
|
||||||
|
Check out the **[User Guide]** for a list of features and installation and usage information.
|
||||||
|
The User Guide also serves as a demonstration to showcase what a book looks like.
|
||||||
|
|
||||||
## What does it look like?
|
If you are interested in contributing to the development of mdBook, check out the [Contribution Guide].
|
||||||
|
|
||||||
The [User Guide] for mdBook has been written in Markdown and is using mdBook to
|
|
||||||
generate the online book-like website you can read. The documentation uses the
|
|
||||||
latest version on GitHub and showcases the available features.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
There are multiple ways to install mdBook.
|
|
||||||
|
|
||||||
1. **Binaries**
|
|
||||||
|
|
||||||
Binaries are available for download [here][releases]. Make sure to put the
|
|
||||||
path to the binary into your `PATH`.
|
|
||||||
|
|
||||||
2. **From Crates.io**
|
|
||||||
|
|
||||||
This requires at least [Rust] 1.39 and Cargo to be installed. Once you have installed
|
|
||||||
Rust, type the following in the terminal:
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo install mdbook
|
|
||||||
```
|
|
||||||
|
|
||||||
This will download and compile mdBook for you, the only thing left to do is
|
|
||||||
to add the Cargo bin directory to your `PATH`.
|
|
||||||
|
|
||||||
**Note for automatic deployment**
|
|
||||||
|
|
||||||
If you are using a script to do automatic deployments using Travis or
|
|
||||||
another CI server, we recommend that you specify a semver version range for
|
|
||||||
mdBook when you install it through your script!
|
|
||||||
|
|
||||||
This will constrain the server to install the latest **non-breaking**
|
|
||||||
version of mdBook and will prevent your books from failing to build because
|
|
||||||
we released a new version.
|
|
||||||
|
|
||||||
You can also disable default features to speed up compile time.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo install mdbook --no-default-features --features output --vers "^0.1.0"
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **From Git**
|
|
||||||
|
|
||||||
The version published to crates.io will ever so slightly be behind the
|
|
||||||
version hosted here on GitHub. If you need the latest version you can build
|
|
||||||
the git version of mdBook yourself. Cargo makes this ***super easy***!
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo install --git https://github.com/rust-lang/mdBook.git mdbook
|
|
||||||
```
|
|
||||||
|
|
||||||
Again, make sure to add the Cargo bin directory to your `PATH`.
|
|
||||||
|
|
||||||
4. **For Contributions**
|
|
||||||
|
|
||||||
If you want to contribute to mdBook you will have to clone the repository on
|
|
||||||
your local machine:
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/rust-lang/mdBook.git
|
|
||||||
```
|
|
||||||
|
|
||||||
`cd` into `mdBook/` and run
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo build
|
|
||||||
```
|
|
||||||
|
|
||||||
The resulting binary can be found in `mdBook/target/debug/` under the name
|
|
||||||
`mdBook` or `mdBook.exe`.
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
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 <directory>`
|
|
||||||
|
|
||||||
The init command will create a directory with the minimal boilerplate to
|
|
||||||
start with. If the `<directory>` parameter is omitted, the current
|
|
||||||
directory will be used.
|
|
||||||
|
|
||||||
```
|
|
||||||
book-test/
|
|
||||||
├── book
|
|
||||||
└── src
|
|
||||||
├── chapter_1.md
|
|
||||||
└── SUMMARY.md
|
|
||||||
```
|
|
||||||
|
|
||||||
`book` and `src` are both directories. `src` contains the markdown files
|
|
||||||
that will be used to render the output to the `book` directory.
|
|
||||||
|
|
||||||
Please, take a look at the [CLI docs] for more information and some neat tricks.
|
|
||||||
|
|
||||||
- `mdbook build`
|
|
||||||
|
|
||||||
This is the command you will run to render your book, it reads the
|
|
||||||
`SUMMARY.md` file to understand the structure of your book, takes the
|
|
||||||
markdown files in the source directory as input and outputs static html
|
|
||||||
pages that you can upload to a server.
|
|
||||||
|
|
||||||
- `mdbook watch`
|
|
||||||
|
|
||||||
When you run this command, mdbook will watch your markdown files to rebuild
|
|
||||||
the book on every change. This avoids having to come back to the terminal
|
|
||||||
to type `mdbook build` over and over again.
|
|
||||||
|
|
||||||
- `mdbook serve`
|
|
||||||
|
|
||||||
Does the same thing as `mdbook watch` but additionally serves the book at
|
|
||||||
`http://localhost:3000` (port is changeable) and reloads the browser when a
|
|
||||||
change occurs.
|
|
||||||
|
|
||||||
- `mdbook clean`
|
|
||||||
|
|
||||||
Delete directory in which generated book is located.
|
|
||||||
|
|
||||||
### 3rd Party Plugins
|
|
||||||
|
|
||||||
The way a book is loaded and rendered can be configured by the user via third
|
|
||||||
party plugins. These plugins are just programs which will be invoked during the
|
|
||||||
build process and are split into roughly two categories, *preprocessors* and
|
|
||||||
*renderers*.
|
|
||||||
|
|
||||||
Preprocessors are used to transform a book before it is sent to a renderer.
|
|
||||||
One example would be to replace all occurrences of
|
|
||||||
`{{#include some_file.ext}}` with the contents of that file. Some existing
|
|
||||||
preprocessors are:
|
|
||||||
|
|
||||||
- `index` - a built-in preprocessor (enabled by default) which will transform
|
|
||||||
all `README.md` chapters to `index.md` so `foo/README.md` can be accessed via
|
|
||||||
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
|
|
||||||
format, however there's nothing stopping a renderer from doing static analysis
|
|
||||||
of a book in order to validate links or run tests. Some existing renderers are:
|
|
||||||
|
|
||||||
- `html` - the built-in renderer which will generate a HTML version of the book
|
|
||||||
- `markdown` - the built-in renderer (disabled by default) which will run
|
|
||||||
preprocessors then output the resulting Markdown. Useful for debugging
|
|
||||||
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.
|
|
||||||
|
|
||||||
A preprocessor or renderer is enabled by installing the appropriate program and
|
|
||||||
then mentioning it in the book's `book.toml` file.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ cargo install mdbook-linkcheck
|
|
||||||
$ edit book.toml && cat book.toml
|
|
||||||
[book]
|
|
||||||
title = "My Awesome Book"
|
|
||||||
authors = ["Michael-F-Bryan"]
|
|
||||||
|
|
||||||
[output.html]
|
|
||||||
|
|
||||||
[output.linkcheck] # enable the "mdbook-linkcheck" renderer
|
|
||||||
|
|
||||||
$ mdbook build
|
|
||||||
2018-10-20 13:57:51 [INFO] (mdbook::book): Book building has started
|
|
||||||
2018-10-20 13:57:51 [INFO] (mdbook::book): Running the html backend
|
|
||||||
2018-10-20 13:57:53 [INFO] (mdbook::book): Running the linkcheck backend
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information on the plugin system, consult the [User Guide].
|
|
||||||
|
|
||||||
### As a library
|
|
||||||
|
|
||||||
Aside from the command line interface, this crate can also be used as a
|
|
||||||
library. This means that you could integrate it in an existing project, like a
|
|
||||||
web-app for example. Since the command line interface is just a wrapper around
|
|
||||||
the library functionality, when you use this crate as a library you have full
|
|
||||||
access to all the functionality of the command line interface with an easy to
|
|
||||||
use API and more!
|
|
||||||
|
|
||||||
See the [User Guide] and the [API docs] for more information.
|
|
||||||
|
|
||||||
## Contributions
|
|
||||||
|
|
||||||
Contributions are highly appreciated and encouraged! Don't hesitate to
|
|
||||||
participate to discussions in the issues, propose new features and ask for
|
|
||||||
help.
|
|
||||||
|
|
||||||
If you are just starting out with Rust, there are a series of issues that are
|
|
||||||
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] which helps
|
|
||||||
you go through the build and contribution process!
|
|
||||||
|
|
||||||
There is also a [rendered version][master-docs] of the latest API docs
|
|
||||||
available, for those hacking on `master`.
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
All the code in this repository is released under the ***Mozilla Public License v2.0***, for more information take a look at the [LICENSE] file.
|
All the code in this repository is released under the ***Mozilla Public License v2.0***, for more information take a look at the [LICENSE] file.
|
||||||
|
|
||||||
|
|
||||||
[User Guide]: https://rust-lang.github.io/mdBook/
|
[User Guide]: https://rust-lang.github.io/mdBook/
|
||||||
[API docs]: https://docs.rs/mdbook/*/mdbook/
|
|
||||||
[E-Easy]: https://github.com/rust-lang/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AE-Easy
|
|
||||||
[contribution guide]: https://github.com/rust-lang/mdBook/blob/master/CONTRIBUTING.md
|
[contribution guide]: https://github.com/rust-lang/mdBook/blob/master/CONTRIBUTING.md
|
||||||
[LICENSE]: https://github.com/rust-lang/mdBook/blob/master/LICENSE
|
[LICENSE]: https://github.com/rust-lang/mdBook/blob/master/LICENSE
|
||||||
[releases]: https://github.com/rust-lang/mdBook/releases
|
|
||||||
[Rust]: https://www.rust-lang.org/
|
|
||||||
[CLI docs]: http://rust-lang.github.io/mdBook/cli/init.html
|
|
||||||
[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
|
|
||||||
|
|
|
@ -1,29 +1,30 @@
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
**mdBook** is a command line tool and Rust crate to create books with Markdown. The output resembles tools like Gitbook,
|
**mdBook** is a command line tool to create books with Markdown.
|
||||||
and is ideal for creating product or API documentation, tutorials, course materials or anything that requires a clean,
|
It 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
|
easily navigable and customizable presentation.
|
||||||
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.
|
|
||||||
|
|
||||||
mdBook includes built in support for both preprocessing your Markdown and alternative renderers for producing formats
|
* Lightweight [Markdown] syntax helps you focus more on your content
|
||||||
other than HTML. These facilities also enable other functionality such as
|
* Integrated [search] support
|
||||||
validation. [Searching](https://crates.io/search?q=mdbook&sort=relevance) Rust's [crates.io](https://crates.io) is a
|
* Color [syntax highlighting] for code blocks for many different languages
|
||||||
great way to discover more extensions.
|
* [Theme] files allow customizing the formatting of the output
|
||||||
|
* [Preprocessors] can provide extensions for custom syntax and modifying content
|
||||||
|
* [Backends] can render the output to multiple formats
|
||||||
|
* Written in [Rust] for speed, safety, and simplicity
|
||||||
|
* Automated testing of [Rust code samples]
|
||||||
|
|
||||||
## API Documentation
|
This guide is an example of what mdBook produces.
|
||||||
|
mdBook is used by the Rust programming language project, and [The Rust Programming Language][trpl] book is another fine example of mdBook in action.
|
||||||
|
|
||||||
In addition to the above features, mdBook also has a Rust [API](https://docs.rs/mdbook/*/mdbook/). This allows you to
|
[Markdown]: format/markdown.md
|
||||||
write your own preprocessor or renderer, as well as incorporate mdBook features into other applications.
|
[search]: guide/reading.md#search
|
||||||
The [For Developers](for_developers) section of this guide contains more information and some examples.
|
[syntax highlighting]: format/theme/syntax-highlighting.md
|
||||||
|
[theme]: format/theme/index.html
|
||||||
## Markdown
|
[preprocessors]: format/configuration/preprocessors.md
|
||||||
|
[backends]: format/configuration/renderers.md
|
||||||
mdBook's [parser](https://github.com/raphlinus/pulldown-cmark) adheres to the [CommonMark](https://commonmark.org/)
|
[Rust]: https://www.rust-lang.org/
|
||||||
specification. You can take a quick [tutorial](https://commonmark.org/help/tutorial/),
|
[trpl]: https://doc.rust-lang.org/book/
|
||||||
or [try out](https://spec.commonmark.org/dingus/) CommonMark in real time. For a more in-depth experience, check out the
|
[Rust code samples]: cli/test.md
|
||||||
[Markdown Guide](https://www.markdownguide.org).
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
- [Introduction](README.md)
|
[Introduction](README.md)
|
||||||
|
|
||||||
|
# User Guide
|
||||||
|
|
||||||
|
- [Installation](guide/installation.md)
|
||||||
|
- [Reading Books](guide/reading.md)
|
||||||
|
- [Creating a Book](guide/creating.md)
|
||||||
|
|
||||||
|
# Reference Guide
|
||||||
|
|
||||||
- [Command Line Tool](cli/README.md)
|
- [Command Line Tool](cli/README.md)
|
||||||
- [init](cli/init.md)
|
- [init](cli/init.md)
|
||||||
- [build](cli/build.md)
|
- [build](cli/build.md)
|
||||||
|
@ -8,6 +17,7 @@
|
||||||
- [serve](cli/serve.md)
|
- [serve](cli/serve.md)
|
||||||
- [test](cli/test.md)
|
- [test](cli/test.md)
|
||||||
- [clean](cli/clean.md)
|
- [clean](cli/clean.md)
|
||||||
|
- [completions](cli/completions.md)
|
||||||
- [Format](format/README.md)
|
- [Format](format/README.md)
|
||||||
- [SUMMARY.md](format/summary.md)
|
- [SUMMARY.md](format/summary.md)
|
||||||
- [Draft chapter]()
|
- [Draft chapter]()
|
||||||
|
@ -23,6 +33,7 @@
|
||||||
- [Editor](format/theme/editor.md)
|
- [Editor](format/theme/editor.md)
|
||||||
- [MathJax Support](format/mathjax.md)
|
- [MathJax Support](format/mathjax.md)
|
||||||
- [mdBook-specific features](format/mdbook.md)
|
- [mdBook-specific features](format/mdbook.md)
|
||||||
|
- [Markdown](format/markdown.md)
|
||||||
- [Continuous Integration](continuous-integration.md)
|
- [Continuous Integration](continuous-integration.md)
|
||||||
- [For Developers](for_developers/README.md)
|
- [For Developers](for_developers/README.md)
|
||||||
- [Preprocessors](for_developers/preprocessors.md)
|
- [Preprocessors](for_developers/preprocessors.md)
|
||||||
|
|
|
@ -1,55 +1,14 @@
|
||||||
# Command Line Tool
|
# Command Line Tool
|
||||||
|
|
||||||
mdBook can be used either as a command line tool or a [Rust
|
The `mdbook` command-line tool is used to create and build books.
|
||||||
crate](https://crates.io/crates/mdbook). Let's focus on the command line tool
|
After you have [installed](../guide/installation.md) `mdbook`, you can run the `mdbook help` command in your terminal to view the available commands.
|
||||||
capabilities first.
|
|
||||||
|
|
||||||
## Install From Binaries
|
This following sections provide in-depth information on the different commands available.
|
||||||
|
|
||||||
Precompiled binaries are provided for major platforms on a best-effort basis.
|
* [`mdbook init <directory>`](init.md) — Creates a new book with minimal boilerplate to start with.
|
||||||
Visit [the releases page](https://github.com/rust-lang/mdBook/releases)
|
* [`mdbook build`](build.md) — Renders the book.
|
||||||
to download the appropriate version for your platform.
|
* [`mdbook watch`](watch.md) — Rebuilds the book any time a source file changes.
|
||||||
|
* [`mdbook serve`](serve.md) — Runs a web server to view the book, and rebuilds on changes.
|
||||||
## Install From Source
|
* [`mdbook test`](test.md) — Tests Rust code samples.
|
||||||
|
* [`mdbook clean`](clean.md) — Deletes the rendered output.
|
||||||
mdBook can also be installed by compiling the source code on your local machine.
|
* [`mdbook completions`](completions.md) — Support for shell auto-completion.
|
||||||
|
|
||||||
### Pre-requisite
|
|
||||||
|
|
||||||
mdBook is written in **[Rust](https://www.rust-lang.org/)** and therefore needs
|
|
||||||
to be compiled with **Cargo**. If you haven't already installed Rust, please go
|
|
||||||
ahead and [install it](https://www.rust-lang.org/tools/install) now.
|
|
||||||
|
|
||||||
### Install Crates.io version
|
|
||||||
|
|
||||||
Installing mdBook is relatively easy if you already have Rust and Cargo
|
|
||||||
installed. You just have to type this snippet in your terminal:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cargo install mdbook
|
|
||||||
```
|
|
||||||
|
|
||||||
This will fetch the source code for the latest release from
|
|
||||||
[Crates.io](https://crates.io/) and compile it. You will have to add Cargo's
|
|
||||||
`bin` directory to your `PATH`.
|
|
||||||
|
|
||||||
Run `mdbook help` in your terminal to verify if it works. Congratulations, you
|
|
||||||
have installed mdBook!
|
|
||||||
|
|
||||||
|
|
||||||
### Install Git version
|
|
||||||
|
|
||||||
The **[git version](https://github.com/rust-lang/mdBook)** contains all
|
|
||||||
the latest bug-fixes and features, that will be released in the next version on
|
|
||||||
**Crates.io**, if you can't wait until the next release. You can build the git
|
|
||||||
version yourself. Open your terminal and navigate to the directory of you
|
|
||||||
choice. We need to clone the git repository and then build it with Cargo.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone --depth=1 https://github.com/rust-lang/mdBook.git
|
|
||||||
cd mdBook
|
|
||||||
cargo build --release
|
|
||||||
```
|
|
||||||
|
|
||||||
The executable `mdbook` will be in the `./target/release` folder, this should be
|
|
||||||
added to the path.
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The completions command
|
||||||
|
|
||||||
|
The completions command is used to generate auto-completions for some common shells.
|
||||||
|
This means when you type `mdbook` in your shell, you can then press your shell's auto-complete key (usually the Tab key) and it may display what the valid options are, or finish partial input.
|
||||||
|
|
||||||
|
The completions first need to be installed for your shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mdbook completions bash > ~/.local/share/bash-completion/completions/mdbook
|
||||||
|
```
|
||||||
|
|
||||||
|
The command prints a completion script for the given shell.
|
||||||
|
Run `mdbook completions --help` for a list of supported shells.
|
||||||
|
|
||||||
|
Where to place the completions depend on which shell you are using and your operating system.
|
||||||
|
Consult your shell's documentation for more information one where to place the script.
|
|
@ -1,154 +1,121 @@
|
||||||
# Running `mdbook` in Continuous Integration
|
# Running `mdbook` in Continuous Integration
|
||||||
|
|
||||||
While the following examples use Travis CI, their principles should
|
There are a variety of services such as [GitHub Actions] or [GitLab CI/CD] which can be used to test and deploy your book automatically.
|
||||||
straightforwardly transfer to other continuous integration providers as well.
|
|
||||||
|
|
||||||
## Ensuring Your Book Builds and Tests Pass
|
The following provides some general guidelines on how to configure your service to run mdBook.
|
||||||
|
Specific recipes can be found at the [Automated Deployment] wiki page.
|
||||||
|
|
||||||
Here is a sample Travis CI `.travis.yml` configuration that ensures `mdbook
|
[GitHub Actions]: https://docs.github.com/en/actions
|
||||||
build` and `mdbook test` run successfully. The key to fast CI turnaround times
|
[GitLab CI/CD]: https://docs.gitlab.com/ee/ci/
|
||||||
is caching `mdbook` installs, so that you aren't compiling `mdbook` on every CI
|
[Automated Deployment]: https://github.com/rust-lang/mdBook/wiki/Automated-Deployment
|
||||||
run.
|
|
||||||
|
|
||||||
```yaml
|
## Installing mdBook
|
||||||
language: rust
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
cache:
|
There are several different strategies for installing mdBook.
|
||||||
- cargo
|
The particular method depends on your needs and preferences.
|
||||||
|
|
||||||
rust:
|
### Pre-compiled binaries
|
||||||
- stable
|
|
||||||
|
|
||||||
before_script:
|
Perhaps the easiest method is to use the pre-compiled binaries found on the [GitHub Releases page][releases].
|
||||||
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
|
A simple approach would be to use the popular `curl` CLI tool to download the executable:
|
||||||
- (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
|
|
||||||
- cargo install-update -a
|
|
||||||
|
|
||||||
script:
|
```sh
|
||||||
- mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook
|
mkdir bin
|
||||||
|
curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.15/mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin
|
||||||
|
bin/mdbook build
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deploying Your Book to GitHub Pages
|
Some considerations for this approach:
|
||||||
|
|
||||||
Following these instructions will result in your book being published to GitHub
|
* This is relatively fast, and does not necessarily require dealing with caching.
|
||||||
pages after a successful CI run on your repository's `master` branch.
|
* This does not require installing Rust.
|
||||||
|
* Specifying a specific URL means you have to manually update your script to get a new version.
|
||||||
|
This may be a benefit if you want to lock to a specific version.
|
||||||
|
However, some users prefer to automatically get a newer version when they are published.
|
||||||
|
* You are reliant on the GitHub CDN being available.
|
||||||
|
|
||||||
First, create a new GitHub "Personal Access Token" with the "public_repo"
|
[releases]: https://github.com/rust-lang/mdBook/releases
|
||||||
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
|
### Building from source
|
||||||
Source on GitHub pages to `gh-pages`.
|
|
||||||
|
|
||||||
Then, append this snippet to your `.travis.yml` and update the path to the
|
Building from source will require having Rust installed.
|
||||||
`book` directory:
|
Some services have Rust pre-installed, but if your service does not, you will need to add a step to install it.
|
||||||
|
|
||||||
```yaml
|
After Rust is installed, `cargo install` can be used to build and install mdBook.
|
||||||
deploy:
|
We recommend using a SemVer version specifier so that you get the latest **non-breaking** version of mdBook.
|
||||||
provider: pages
|
For example:
|
||||||
skip-cleanup: true
|
|
||||||
github-token: $GITHUB_TOKEN
|
```sh
|
||||||
local-dir: book # In case of custom book path: path/to/mybook/book
|
cargo install mdbook --no-default-features --features search --vers "^0.4" --locked
|
||||||
keep-history: false
|
|
||||||
on:
|
|
||||||
branch: main
|
|
||||||
```
|
```
|
||||||
|
|
||||||
That's it!
|
This includes several recommended options:
|
||||||
|
|
||||||
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:
|
* `--no-default-features` — Disables features like the HTTP server used by `mdbook serve` that is likely not needed on CI.
|
||||||
|
This will speed up the build time significantly.
|
||||||
|
* `--features search` — Disabling default features means you should then manually enable features that you want, such as the built-in [search] capability.
|
||||||
|
* `--vers "^0.4"` — This will install the most recent version of the `0.4` series.
|
||||||
|
However, versions after like `0.5.0` won't be installed, as they may break your build.
|
||||||
|
Cargo will automatically upgrade mdBook if you have an older version already installed.
|
||||||
|
* `--locked` — This will use the dependencies that were used when mdBook was released.
|
||||||
|
Without `--locked`, it will use the latest version of all dependencies, which may include some fixes since the last release, but may also (rarely) cause build problems.
|
||||||
|
|
||||||
```yaml
|
You will likely want to investigate caching options, as building mdBook can be somewhat slow.
|
||||||
language: rust
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
|
|
||||||
cache:
|
[search]: guide/reading.md#search
|
||||||
- cargo
|
|
||||||
|
|
||||||
rust:
|
## Running tests
|
||||||
- stable
|
|
||||||
|
|
||||||
before_script:
|
You may want to run tests using [`mdbook test`] every time you push a change or create a pull request.
|
||||||
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
|
This can be used to validate Rust code examples in the book.
|
||||||
- (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
|
|
||||||
- cargo install-update -a
|
|
||||||
|
|
||||||
script:
|
This will require having Rust installed.
|
||||||
- mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook
|
Some services have Rust pre-installed, but if your service does not, you will need to add a step to install it.
|
||||||
|
|
||||||
deploy:
|
Other than making sure the appropriate version of Rust is installed, there's not much more than just running `mdbook test` from the book directory.
|
||||||
provider: pages
|
|
||||||
strategy: git
|
You may also want to consider running other kinds of tests, like [mdbook-linkcheck] which will check for broken links.
|
||||||
edge: true
|
Or if you have your own style checks, spell checker, or any other tests it might be good to run them in CI.
|
||||||
cleanup: false
|
|
||||||
github-token: $GITHUB_TOKEN
|
[`mdbook test`]: cli/test.md
|
||||||
local-dir: book # In case of custom book path: path/to/mybook/book
|
[mdbook-linkcheck]: https://github.com/Michael-F-Bryan/mdbook-linkcheck#continuous-integration
|
||||||
keep-history: false
|
|
||||||
on:
|
## Deploying
|
||||||
branch: main
|
|
||||||
target_branch: gh-pages
|
You may want to automatically deploy your book.
|
||||||
|
Some may want to do this with every time a change is pushed, and others may want to only deploy when a specific release is tagged.
|
||||||
|
|
||||||
|
You'll also need to understand the specifics on how to push a change to your web service.
|
||||||
|
For example, [GitHub Pages] just requires committing the output onto a specific git branch.
|
||||||
|
Other services may require using something like SSH to connect to a remote server.
|
||||||
|
|
||||||
|
The basic outline is that you need to run `mdbook build` to generate the output, and then transfer the files (which are in the `book` directory) to the correct location.
|
||||||
|
|
||||||
|
You may then want to consider if you need to invalidate any caches on your web service.
|
||||||
|
|
||||||
|
See the [Automated Deployment] wiki page for examples of various different services.
|
||||||
|
|
||||||
|
[GitHub Pages]: https://docs.github.com/en/pages
|
||||||
|
|
||||||
|
### 404 handling
|
||||||
|
|
||||||
|
mdBook automatically generates a 404 page to be used for broken links.
|
||||||
|
The default output is a file named `404.html` at the root of the book.
|
||||||
|
Some services like [GitHub Pages] will automatically use this page for broken links.
|
||||||
|
For other services, you may want to consider configuring the web server to use this page as it will provide the reader navigation to get back to the book.
|
||||||
|
|
||||||
|
If your book is not deployed at the root of the domain, then you should set the [`output.html.site-url`] setting so that the 404 page works correctly.
|
||||||
|
It needs to know where the book is deployed in order to load the static files (like CSS) correctly.
|
||||||
|
For example, this guide is deployed at <https://rust-lang.github.io/mdBook/>, and the `site-url` setting is configured like this:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# book.toml
|
||||||
|
[output.html]
|
||||||
|
site-url = "/mdBook/"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Deploying to GitHub Pages manually
|
You can customize the look of the 404 page by creating a file named `src/404.md` in your book.
|
||||||
|
If you want to use a different filename, you can set [`output.html.input-404`] to a different filename.
|
||||||
|
|
||||||
If your CI doesn't support GitHub pages, or you're deploying somewhere else
|
[`output.html.site-url`]: format/configuration/renderers.md#html-renderer-options
|
||||||
with integrations such as Github Pages:
|
[`output.html.input-404`]: format/configuration/renderers.md#html-renderer-options
|
||||||
*note: you may want to use different tmp dirs*:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$> git worktree add /tmp/book gh-pages
|
|
||||||
$> mdbook build
|
|
||||||
$> rm -rf /tmp/book/* # this won't delete the .git directory
|
|
||||||
$> cp -rp book/* /tmp/book/
|
|
||||||
$> cd /tmp/book
|
|
||||||
$> git add -A
|
|
||||||
$> git commit 'new book message'
|
|
||||||
$> git push origin gh-pages
|
|
||||||
$> cd -
|
|
||||||
```
|
|
||||||
|
|
||||||
Or put this into a Makefile rule:
|
|
||||||
|
|
||||||
```makefile
|
|
||||||
.PHONY: deploy
|
|
||||||
deploy: book
|
|
||||||
@echo "====> deploying to github"
|
|
||||||
git worktree add /tmp/book gh-pages
|
|
||||||
rm -rf /tmp/book/*
|
|
||||||
cp -rp book/* /tmp/book/
|
|
||||||
cd /tmp/book && \
|
|
||||||
git add -A && \
|
|
||||||
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
|
|
||||||
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!
|
|
||||||
|
|
|
@ -24,8 +24,9 @@ The process of rendering a book project goes through several steps.
|
||||||
exist
|
exist
|
||||||
- Load the book chapters into memory
|
- Load the book chapters into memory
|
||||||
- Discover which preprocessors/backends should be used
|
- Discover which preprocessors/backends should be used
|
||||||
2. Run the preprocessors
|
2. For each backend:
|
||||||
3. Call each backend in turn
|
1. Run all the preprocessors.
|
||||||
|
2. Call the backend to render the processed result.
|
||||||
|
|
||||||
|
|
||||||
## Using `mdbook` as a Library
|
## Using `mdbook` as a Library
|
||||||
|
|
|
@ -5,23 +5,17 @@ rendering process. This program is passed a JSON representation of the book and
|
||||||
configuration information via `stdin`. Once the backend receives this
|
configuration information via `stdin`. Once the backend receives this
|
||||||
information it is free to do whatever it wants.
|
information it is free to do whatever it wants.
|
||||||
|
|
||||||
There are already several alternative backends on GitHub which can be used as a
|
See [Configuring Renderers](../format/configuration/renderers.md) for more information about using backends.
|
||||||
rough example of how this is accomplished in practice.
|
|
||||||
|
|
||||||
- [mdbook-linkcheck] - a simple program for verifying the book doesn't contain
|
The community has developed several backends.
|
||||||
any broken links
|
See the [Third Party Plugins] wiki page for a list of available backends.
|
||||||
- [mdbook-epub] - an EPUB renderer
|
|
||||||
- [mdbook-test] - a program to run the book's contents through [rust-skeptic] to
|
## Setting Up
|
||||||
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
|
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
|
of a simple word counting program. Although it will be written in Rust, there's
|
||||||
no reason why it couldn't be accomplished using something like Python or Ruby.
|
no reason why it couldn't be accomplished using something like Python or Ruby.
|
||||||
|
|
||||||
|
|
||||||
## Setting Up
|
|
||||||
|
|
||||||
First you'll want to create a new binary program and add `mdbook` as a
|
First you'll want to create a new binary program and add `mdbook` as a
|
||||||
dependency.
|
dependency.
|
||||||
|
|
||||||
|
@ -330,39 +324,6 @@ generation or a warning).
|
||||||
All environment variables are passed through to the backend, allowing you to use
|
All environment variables are passed through to the backend, allowing you to use
|
||||||
the usual `RUST_LOG` to control logging verbosity.
|
the usual `RUST_LOG` to control logging verbosity.
|
||||||
|
|
||||||
## Handling missing backends
|
|
||||||
|
|
||||||
If you enable a backend that isn't installed, the default behavior is to throw an error:
|
|
||||||
|
|
||||||
```text
|
|
||||||
The command `mdbook-wordcount` wasn't found, is the "wordcount" backend installed?
|
|
||||||
If you want to ignore this error when the "wordcount" backend is not installed,
|
|
||||||
set `optional = true` in the `[output.wordcount]` section of the book.toml configuration file.
|
|
||||||
```
|
|
||||||
|
|
||||||
This behavior can be changed by marking the backend as optional.
|
|
||||||
|
|
||||||
```diff
|
|
||||||
[book]
|
|
||||||
title = "mdBook Documentation"
|
|
||||||
description = "Create book from markdown files. Like Gitbook but implemented in Rust"
|
|
||||||
authors = ["Mathieu David", "Michael-F-Bryan"]
|
|
||||||
|
|
||||||
[output.html]
|
|
||||||
|
|
||||||
[output.wordcount]
|
|
||||||
command = "python /path/to/wordcount.py"
|
|
||||||
+ optional = true
|
|
||||||
```
|
|
||||||
|
|
||||||
This demotes the error to a warning, and it will instead look like this:
|
|
||||||
|
|
||||||
```text
|
|
||||||
The command was not found, but was marked as optional.
|
|
||||||
Command: wordcount
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Wrapping Up
|
## Wrapping Up
|
||||||
|
|
||||||
Although contrived, hopefully this example was enough to show how you'd create
|
Although contrived, hopefully this example was enough to show how you'd create
|
||||||
|
@ -375,11 +336,7 @@ as a good example of how it's done in real life, so feel free to skim through
|
||||||
the source code or ask questions.
|
the source code or ask questions.
|
||||||
|
|
||||||
|
|
||||||
[mdbook-linkcheck]: https://github.com/Michael-F-Bryan/mdbook-linkcheck
|
[Third Party Plugins]: https://github.com/rust-lang/mdBook/wiki/Third-party-plugins
|
||||||
[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`]: https://docs.rs/mdbook/*/mdbook/renderer/struct.RenderContext.html
|
||||||
[`RenderContext::from_json()`]: https://docs.rs/mdbook/*/mdbook/renderer/struct.RenderContext.html#method.from_json
|
[`RenderContext::from_json()`]: https://docs.rs/mdbook/*/mdbook/renderer/struct.RenderContext.html#method.from_json
|
||||||
[`semver`]: https://crates.io/crates/semver
|
[`semver`]: https://crates.io/crates/semver
|
||||||
|
|
|
@ -5,35 +5,18 @@ book is loaded and before it gets rendered, allowing you to update and mutate
|
||||||
the book. Possible use cases are:
|
the book. Possible use cases are:
|
||||||
|
|
||||||
- Creating custom helpers like `\{{#include /path/to/file.md}}`
|
- Creating custom helpers like `\{{#include /path/to/file.md}}`
|
||||||
- Updating links so `[some chapter](some_chapter.md)` is automatically changed
|
|
||||||
to `[some chapter](some_chapter.html)` for the HTML renderer
|
|
||||||
- Substituting in latex-style expressions (`$$ \frac{1}{3} $$`) with their
|
- Substituting in latex-style expressions (`$$ \frac{1}{3} $$`) with their
|
||||||
mathjax equivalents
|
mathjax equivalents
|
||||||
|
|
||||||
|
See [Configuring Preprocessors](../format/configuration/preprocessors.md) for more information about using preprocessors.
|
||||||
|
|
||||||
## Hooking Into MDBook
|
## Hooking Into MDBook
|
||||||
|
|
||||||
MDBook uses a fairly simple mechanism for discovering third party plugins.
|
MDBook uses a fairly simple mechanism for discovering third party plugins.
|
||||||
A new table is added to `book.toml` (e.g. `preprocessor.foo` for the `foo`
|
A new table is added to `book.toml` (e.g. `[preprocessor.foo]` for the `foo`
|
||||||
preprocessor) and then `mdbook` will try to invoke the `mdbook-foo` program as
|
preprocessor) and then `mdbook` will try to invoke the `mdbook-foo` program as
|
||||||
part of the build process.
|
part of the build process.
|
||||||
|
|
||||||
A preprocessor can be hard-coded to specify which backend(s) it should be run
|
|
||||||
for with the `preprocessor.foo.renderer` key. For example, it doesn't make sense for
|
|
||||||
[MathJax](../format/mathjax.md) to be used for non-HTML renderers.
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[book]
|
|
||||||
title = "My Book"
|
|
||||||
authors = ["Michael-F-Bryan"]
|
|
||||||
|
|
||||||
[preprocessor.foo]
|
|
||||||
# The command can also be specified manually
|
|
||||||
command = "python3 /path/to/foo.py"
|
|
||||||
# Only run the `foo` preprocessor for the HTML and EPUB renderer
|
|
||||||
renderer = ["html", "epub"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Once the preprocessor has been defined and the build process starts, mdBook executes the command defined in the `preprocessor.foo.command` key twice.
|
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.
|
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.
|
mdBook passes two arguments to the process: the first argument is the string `supports` and the second argument is the renderer name.
|
||||||
|
@ -78,7 +61,7 @@ The `chapter.content` is just a string which happens to be markdown. While it's
|
||||||
entirely possible to use regular expressions or do a manual find & replace,
|
entirely possible to use regular expressions or do a manual find & replace,
|
||||||
you'll probably want to process the input into something more computer-friendly.
|
you'll probably want to process the input into something more computer-friendly.
|
||||||
The [`pulldown-cmark`][pc] crate implements a production-quality event-based
|
The [`pulldown-cmark`][pc] crate implements a production-quality event-based
|
||||||
Markdown parser, with the [`pulldown-cmark-to-cmark`][pctc] allowing you to
|
Markdown parser, with the [`pulldown-cmark-to-cmark`][pctc] crate allowing you to
|
||||||
translate events back into markdown text.
|
translate events back into markdown text.
|
||||||
|
|
||||||
The following code block shows how to remove all emphasis from markdown,
|
The following code block shows how to remove all emphasis from markdown,
|
||||||
|
|
|
@ -62,6 +62,11 @@ language = "en"
|
||||||
Options for the Rust language, relevant to running tests and playground
|
Options for the Rust language, relevant to running tests and playground
|
||||||
integration.
|
integration.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[rust]
|
||||||
|
edition = "2015" # the default edition for code blocks
|
||||||
|
```
|
||||||
|
|
||||||
- **edition**: Rust edition to use by default for the code snippets. Default
|
- **edition**: Rust edition to use by default for the code snippets. Default
|
||||||
is "2015". Individual code blocks can be controlled with the `edition2015`,
|
is "2015". Individual code blocks can be controlled with the `edition2015`,
|
||||||
`edition2018` or `edition2021` annotations, such as:
|
`edition2018` or `edition2021` annotations, such as:
|
||||||
|
@ -77,8 +82,16 @@ integration.
|
||||||
|
|
||||||
This controls the build process of your book.
|
This controls the build process of your book.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[build]
|
||||||
|
build-dir = "book" # the directory where the output is placed
|
||||||
|
create-missing = true # whether or not to create missing pages
|
||||||
|
use-default-preprocessors = true # use the default preprocessors
|
||||||
|
```
|
||||||
|
|
||||||
- **build-dir:** The directory to put the rendered book in. By default this is
|
- **build-dir:** The directory to put the rendered book in. By default this is
|
||||||
`book/` in the book's root directory.
|
`book/` in the book's root directory.
|
||||||
|
This can overridden with the `--dest-dir` CLI option.
|
||||||
- **create-missing:** By default, any missing files specified in `SUMMARY.md`
|
- **create-missing:** By default, any missing files specified in `SUMMARY.md`
|
||||||
will be created when the book is built (i.e. `create-missing = true`). If this
|
will be created when the book is built (i.e. `create-missing = true`). If this
|
||||||
is `false` then the build process will instead exit with an error if any files
|
is `false` then the build process will instead exit with an error if any files
|
||||||
|
|
|
@ -1,51 +1,58 @@
|
||||||
# Configuring Preprocessors
|
# Configuring Preprocessors
|
||||||
|
|
||||||
The following preprocessors are available and included by default:
|
Preprocessors are extensions that can modify the raw Markdown source before it gets sent to the renderer.
|
||||||
|
|
||||||
- `links`: Expand the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars
|
The following preprocessors are built-in and included by default:
|
||||||
|
|
||||||
|
- `links`: Expands the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars
|
||||||
helpers in a chapter to include the contents of a file.
|
helpers in a chapter to include the contents of a file.
|
||||||
|
See [Including files] for more.
|
||||||
- `index`: Convert all chapter files named `README.md` into `index.md`. That is
|
- `index`: Convert all chapter files named `README.md` into `index.md`. That is
|
||||||
to say, all `README.md` would be rendered to an index file `index.html` in the
|
to say, all `README.md` would be rendered to an index file `index.html` in the
|
||||||
rendered book.
|
rendered book.
|
||||||
|
|
||||||
|
The built-in preprocessors can be disabled with the [`build.use-default-preprocessors`] config option.
|
||||||
|
|
||||||
**book.toml**
|
The community has developed several preprocessors.
|
||||||
```toml
|
See the [Third Party Plugins] wiki page for a list of available preprocessors.
|
||||||
[build]
|
|
||||||
build-dir = "build"
|
|
||||||
create-missing = false
|
|
||||||
|
|
||||||
[preprocessor.links]
|
For information on how to create a new preprocessor, see the [Preprocessors for Developers] chapter.
|
||||||
|
|
||||||
[preprocessor.index]
|
[Including files]: ../mdbook.md#including-files
|
||||||
```
|
[`build.use-default-preprocessors`]: general.md#build-options
|
||||||
|
[Third Party Plugins]: https://github.com/rust-lang/mdBook/wiki/Third-party-plugins
|
||||||
|
[Preprocessors for Developers]: ../../for_developers/preprocessors.md
|
||||||
|
|
||||||
### Custom Preprocessor Configuration
|
## Custom Preprocessor Configuration
|
||||||
|
|
||||||
Like renderers, preprocessor will need to be given its own table (e.g.
|
Preprocessors can be added by including a `preprocessor` table in `book.toml` with the name of the preprocessor.
|
||||||
`[preprocessor.mathjax]`). In the section, you may then pass extra
|
For example, if you have a preprocessor called `mdbook-example`, then you can include it with:
|
||||||
configuration to the preprocessor by adding key-value pairs to the table.
|
|
||||||
|
|
||||||
For example
|
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[preprocessor.links]
|
[preprocessor.example]
|
||||||
# set the renderers this preprocessor will run for
|
|
||||||
renderers = ["html"]
|
|
||||||
some_extra_feature = true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Locking a Preprocessor dependency to a renderer
|
With this table, mdBook will execute the `mdbook-example` preprocessor.
|
||||||
|
|
||||||
|
This table can include additional key-value pairs that are specific to the preprocessor.
|
||||||
|
For example, if our example prepocessor needed some extra configuration options:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[preprocessor.example]
|
||||||
|
some-extra-feature = true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Locking a Preprocessor dependency to a renderer
|
||||||
|
|
||||||
You can explicitly specify that a preprocessor should run for a renderer by
|
You can explicitly specify that a preprocessor should run for a renderer by
|
||||||
binding the two together.
|
binding the two together.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[preprocessor.mathjax]
|
[preprocessor.example]
|
||||||
renderers = ["html"] # mathjax only makes sense with the HTML renderer
|
renderers = ["html"] # example preprocessor only runs with the HTML renderer
|
||||||
```
|
```
|
||||||
|
|
||||||
### Provide Your Own Command
|
## Provide Your Own Command
|
||||||
|
|
||||||
By default when you add a `[preprocessor.foo]` table to your `book.toml` file,
|
By default when you add a `[preprocessor.foo]` table to your `book.toml` file,
|
||||||
`mdbook` will try to invoke the `mdbook-foo` executable. If you want to use a
|
`mdbook` will try to invoke the `mdbook-foo` executable. If you want to use a
|
||||||
|
@ -56,3 +63,25 @@ be overridden by adding a `command` field.
|
||||||
[preprocessor.random]
|
[preprocessor.random]
|
||||||
command = "python random.py"
|
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.
|
||||||
|
|
|
@ -1,9 +1,115 @@
|
||||||
# Configuring Renderers
|
# Configuring Renderers
|
||||||
|
|
||||||
### HTML renderer options
|
Renderers (also called "backends") are responsible for creating the output of the book.
|
||||||
|
|
||||||
The HTML renderer has a couple of options as well. All the options for the
|
The following backends are built-in:
|
||||||
renderer need to be specified under the TOML table `[output.html]`.
|
|
||||||
|
* [`html`](#html-renderer-options) — This renders the book to HTML.
|
||||||
|
This is enabled by default if no other `[output]` tables are defined in `book.toml`.
|
||||||
|
* [`markdown`](#markdown-renderer) — This outputs the book as markdown after running the preprocessors.
|
||||||
|
This is useful for debugging preprocessors.
|
||||||
|
|
||||||
|
The community has developed several backends.
|
||||||
|
See the [Third Party Plugins] wiki page for a list of available backends.
|
||||||
|
|
||||||
|
For information on how to create a new backend, see the [Backends for Developers] chapter.
|
||||||
|
|
||||||
|
[Third Party Plugins]: https://github.com/rust-lang/mdBook/wiki/Third-party-plugins
|
||||||
|
[Backends for Developers]: ../../for_developers/backends.md
|
||||||
|
|
||||||
|
## Output tables
|
||||||
|
|
||||||
|
Backends can be added by including a `output` table in `book.toml` with the name of the backend.
|
||||||
|
For example, if you have a backend called `mdbook-wordcount`, then you can include it with:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.wordcount]
|
||||||
|
```
|
||||||
|
|
||||||
|
With this table, mdBook will execute the `mdbook-wordcount` backend.
|
||||||
|
|
||||||
|
This table can include additional key-value pairs that are specific to the backend.
|
||||||
|
For example, if our example backend needed some extra configuration options:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.wordcount]
|
||||||
|
ignores = ["Example Chapter"]
|
||||||
|
```
|
||||||
|
|
||||||
|
If you define any `[output]` tables, then the `html` backend is not enabled by default.
|
||||||
|
If you want to keep the `html` backend running, then just include it in the `book.toml` file.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[book]
|
||||||
|
title = "My Awesome Book"
|
||||||
|
|
||||||
|
[output.wordcount]
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
```
|
||||||
|
|
||||||
|
If more than one `output` table is included, this changes the behavior for the layout of the output directory.
|
||||||
|
If there is only one backend, then it places its output directly in the `book` directory (see [`build.build-dir`] to override this location).
|
||||||
|
If there is more than one backend, then each backend is placed in a separate directory underneath `book`.
|
||||||
|
For example, the above would have directories `book/html` and `book/wordcount`.
|
||||||
|
|
||||||
|
[`build.build-dir`]: general.md#build-options
|
||||||
|
|
||||||
|
### Custom backend commands
|
||||||
|
|
||||||
|
By default when you add an `[output.foo]` table to your `book.toml` file,
|
||||||
|
`mdbook` will try to invoke the `mdbook-foo` executable.
|
||||||
|
If you want to use a different program name or pass in command-line arguments,
|
||||||
|
this behaviour can be overridden by adding a `command` field.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.random]
|
||||||
|
command = "python random.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Optional backends
|
||||||
|
|
||||||
|
If you enable a backend that isn't installed, the default behavior is to throw an error.
|
||||||
|
This behavior can be changed by marking the backend as optional:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.wordcount]
|
||||||
|
optional = true
|
||||||
|
```
|
||||||
|
|
||||||
|
This demotes the error to a warning.
|
||||||
|
|
||||||
|
|
||||||
|
## HTML renderer options
|
||||||
|
|
||||||
|
The HTML renderer has a variety of options detailed below.
|
||||||
|
They should be specified in the `[output.html]` table of the `book.toml` file.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# Example book.toml file with all output options.
|
||||||
|
[book]
|
||||||
|
title = "Example book"
|
||||||
|
authors = ["John Doe", "Jane Doe"]
|
||||||
|
description = "The example book covers examples."
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
theme = "my-theme"
|
||||||
|
default-theme = "light"
|
||||||
|
preferred-dark-theme = "navy"
|
||||||
|
curly-quotes = true
|
||||||
|
mathjax-support = false
|
||||||
|
copy-fonts = true
|
||||||
|
additional-css = ["custom.css", "custom2.css"]
|
||||||
|
additional-js = ["custom.js"]
|
||||||
|
no-section-label = false
|
||||||
|
git-repository-url = "https://github.com/rust-lang/mdBook"
|
||||||
|
git-repository-icon = "fa-github"
|
||||||
|
edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}"
|
||||||
|
site-url = "/example-book/"
|
||||||
|
cname = "myproject.rs"
|
||||||
|
input-404 = "not-found.md"
|
||||||
|
```
|
||||||
|
|
||||||
The following configuration options are available:
|
The following configuration options are available:
|
||||||
|
|
||||||
|
@ -21,8 +127,8 @@ The following configuration options are available:
|
||||||
- **mathjax-support:** Adds support for [MathJax](../mathjax.md). Defaults to
|
- **mathjax-support:** Adds support for [MathJax](../mathjax.md). Defaults to
|
||||||
`false`.
|
`false`.
|
||||||
- **copy-fonts:** Copies fonts.css and respective font files to the output directory and use them in the default theme. Defaults to `true`.
|
- **copy-fonts:** Copies fonts.css and respective font files to the output directory and use them in the default theme. Defaults to `true`.
|
||||||
- **google-analytics:** If you use Google Analytics, this option lets you enable
|
- **google-analytics:** This field has been deprecated and will be removed in a future release.
|
||||||
it by simply specifying your ID in the configuration file.
|
Use the `theme/head.hbs` file to add the appropriate Google Analytics code instead.
|
||||||
- **additional-css:** If you need to slightly change the appearance of your book
|
- **additional-css:** If you need to slightly change the appearance of your book
|
||||||
without overwriting the whole style, you can specify a set of stylesheets that
|
without overwriting the whole style, you can specify a set of stylesheets that
|
||||||
will be loaded after the default ones where you can surgically change the
|
will be loaded after the default ones where you can surgically change the
|
||||||
|
@ -30,34 +136,22 @@ The following configuration options are available:
|
||||||
- **additional-js:** If you need to add some behaviour to your book without
|
- **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
|
removing the current behaviour, you can specify a set of JavaScript files that
|
||||||
will be loaded alongside the default one.
|
will be loaded alongside the default one.
|
||||||
- **print:** A subtable for configuration print settings. mdBook by default adds
|
- **no-section-label:** mdBook by defaults adds numeric section labels in the table of
|
||||||
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
|
contents column. For example, "1.", "2.1". Set this option to true to disable
|
||||||
those labels. Defaults to `false`.
|
those labels. Defaults to `false`.
|
||||||
- **fold:** A subtable for configuring sidebar section-folding behavior.
|
|
||||||
- **playground:** A subtable for configuring various playground settings.
|
|
||||||
- **search:** A subtable for configuring the in-browser search functionality.
|
|
||||||
mdBook must be compiled with the `search` feature enabled (on by default).
|
|
||||||
- **git-repository-url:** A url to the git repository for the book. If provided
|
- **git-repository-url:** A url to the git repository for the book. If provided
|
||||||
an icon link will be output in the menu bar of the book.
|
an icon link will be output in the menu bar of the book.
|
||||||
- **git-repository-icon:** The FontAwesome icon class to use for the git
|
- **git-repository-icon:** The FontAwesome icon class to use for the git
|
||||||
repository link. Defaults to `fa-github`.
|
repository link. Defaults to `fa-github` which looks like <i class="fa fa-github"></i>.
|
||||||
|
If you are not using GitHub, another option to consider is `fa-code-fork` which looks like <i class="fa fa-code-fork"></i>.
|
||||||
- **edit-url-template:** Edit url template, when provided shows a
|
- **edit-url-template:** Edit url template, when provided shows a
|
||||||
"Suggest an edit" button for directly jumping to editing the currently
|
"Suggest an edit" button (which looks like <i class="fa fa-edit"></i>) for directly jumping to editing the currently
|
||||||
viewed page. For e.g. GitHub projects set this to
|
viewed page. For e.g. GitHub projects set this to
|
||||||
`https://github.com/<owner>/<repo>/edit/master/{path}` or for
|
`https://github.com/<owner>/<repo>/edit/master/{path}` or for
|
||||||
Bitbucket projects set it to
|
Bitbucket projects set it to
|
||||||
`https://bitbucket.org/<owner>/<repo>/src/master/{path}?mode=edit`
|
`https://bitbucket.org/<owner>/<repo>/src/master/{path}?mode=edit`
|
||||||
where {path} will be replaced with the full path of the file in the
|
where {path} will be replaced with the full path of the file in the
|
||||||
repository.
|
repository.
|
||||||
- **redirect:** A subtable used for generating redirects when a page is moved.
|
|
||||||
The table contains key-value pairs where the key is where the redirect file
|
|
||||||
needs to be created, as an absolute path from the build directory, (e.g.
|
|
||||||
`/appendices/bibliography.html`). The value can be any valid URI the
|
|
||||||
browser should navigate to (e.g. `https://rust-lang.org/`,
|
|
||||||
`/overview.html`, or `../bibliography.html`).
|
|
||||||
- **input-404:** The name of the markdown file used for missing files.
|
- **input-404:** The name of the markdown file used for missing files.
|
||||||
The corresponding output file will be the same, with the extension replaced with `html`.
|
The corresponding output file will be the same, with the extension replaced with `html`.
|
||||||
Defaults to `404.md`.
|
Defaults to `404.md`.
|
||||||
|
@ -71,19 +165,49 @@ The following configuration options are available:
|
||||||
|
|
||||||
[custom domain]: https://docs.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site
|
[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:
|
### `[output.html.print]`
|
||||||
|
|
||||||
|
The `[output.html.print]` table provides options for controlling the printable output.
|
||||||
|
By default, mdBook will include an icon on the top right of the book (which looks like <i class="fa fa-print"></i>) that will print the book as a single page.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.html.print]
|
||||||
|
enable = true # include support for printable output
|
||||||
|
page-break = true # insert page-break after each chapter
|
||||||
|
```
|
||||||
|
|
||||||
- **enable:** Enable print support. When `false`, all print support will not be
|
- **enable:** Enable print support. When `false`, all print support will not be
|
||||||
rendered. Defaults to `true`.
|
rendered. Defaults to `true`.
|
||||||
|
- **page-break** Insert page breaks between chapters. Defaults to `true`.
|
||||||
|
|
||||||
Available configuration options for the `[output.html.fold]` table:
|
### `[output.html.fold]`
|
||||||
|
|
||||||
|
The `[output.html.fold]` table provides options for controlling folding of the chapter listing in the navigation sidebar.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.html.fold]
|
||||||
|
enable = false # whether or not to enable section folding
|
||||||
|
level = 0 # the depth to start folding
|
||||||
|
```
|
||||||
|
|
||||||
- **enable:** Enable section-folding. When off, all folds are open.
|
- **enable:** Enable section-folding. When off, all folds are open.
|
||||||
Defaults to `false`.
|
Defaults to `false`.
|
||||||
- **level:** The higher the more folded regions are open. When level is 0, all
|
- **level:** The higher the more folded regions are open. When level is 0, all
|
||||||
folds are closed. Defaults to `0`.
|
folds are closed. Defaults to `0`.
|
||||||
|
|
||||||
Available configuration options for the `[output.html.playground]` table:
|
### `[output.html.playground]`
|
||||||
|
|
||||||
|
The `[output.html.playground]` table provides options for controlling Rust sample code blocks, and their integration with the [Rust Playground].
|
||||||
|
|
||||||
|
[Rust Playground]: https://play.rust-lang.org/
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.html.playground]
|
||||||
|
editable = false # allows editing the source code
|
||||||
|
copyable = true # include the copy button for copying code snippets
|
||||||
|
copy-js = true # includes the JavaScript for the code editor
|
||||||
|
line-numbers = false # displays line numbers for editable code
|
||||||
|
```
|
||||||
|
|
||||||
- **editable:** Allow editing the source code. Defaults to `false`.
|
- **editable:** Allow editing the source code. Defaults to `false`.
|
||||||
- **copyable:** Display the copy button on code snippets. Defaults to `true`.
|
- **copyable:** Display the copy button on code snippets. Defaults to `true`.
|
||||||
|
@ -93,7 +217,26 @@ Available configuration options for the `[output.html.playground]` table:
|
||||||
|
|
||||||
[Ace]: https://ace.c9.io/
|
[Ace]: https://ace.c9.io/
|
||||||
|
|
||||||
Available configuration options for the `[output.html.search]` table:
|
### `[output.html.search]`
|
||||||
|
|
||||||
|
The `[output.html.search]` table provides options for controlling the built-in text [search].
|
||||||
|
mdBook must be compiled with the `search` feature enabled (on by default).
|
||||||
|
|
||||||
|
[search]: ../../guide/reading.md#search
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[output.html.search]
|
||||||
|
enable = true # enables the search feature
|
||||||
|
limit-results = 30 # maximum number of search results
|
||||||
|
teaser-word-count = 30 # number of words used for a search result teaser
|
||||||
|
use-boolean-and = true # multiple search terms must all match
|
||||||
|
boost-title = 2 # ranking boost factor for matches in headers
|
||||||
|
boost-hierarchy = 1 # ranking boost factor for matches in page names
|
||||||
|
boost-paragraph = 1 # ranking boost factor for matches in text
|
||||||
|
expand = true # partial words will match longer terms
|
||||||
|
heading-split-level = 3 # link results to heading levels
|
||||||
|
copy-js = true # include Javascript code for search
|
||||||
|
```
|
||||||
|
|
||||||
- **enable:** Enables the search feature. Defaults to `true`.
|
- **enable:** Enables the search feature. Defaults to `true`.
|
||||||
- **limit-results:** The maximum number of search results. Defaults to `30`.
|
- **limit-results:** The maximum number of search results. Defaults to `30`.
|
||||||
|
@ -116,62 +259,24 @@ Available configuration options for the `[output.html.search]` table:
|
||||||
- **copy-js:** Copy JavaScript files for the search implementation to the output
|
- **copy-js:** Copy JavaScript files for the search implementation to the output
|
||||||
directory. Defaults to `true`.
|
directory. Defaults to `true`.
|
||||||
|
|
||||||
This shows all available HTML output options in the **book.toml**:
|
### `[output.html.redirect]`
|
||||||
|
|
||||||
|
The `[output.html.redirect]` table provides a way to add redirects.
|
||||||
|
This is useful when you move, rename, or remove a page to ensure that links to the old URL will go to the new location.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[book]
|
|
||||||
title = "Example book"
|
|
||||||
authors = ["John Doe", "Jane Doe"]
|
|
||||||
description = "The example book covers examples."
|
|
||||||
|
|
||||||
[output.html]
|
|
||||||
theme = "my-theme"
|
|
||||||
default-theme = "light"
|
|
||||||
preferred-dark-theme = "navy"
|
|
||||||
curly-quotes = true
|
|
||||||
mathjax-support = false
|
|
||||||
copy-fonts = true
|
|
||||||
google-analytics = "UA-123456-7"
|
|
||||||
additional-css = ["custom.css", "custom2.css"]
|
|
||||||
additional-js = ["custom.js"]
|
|
||||||
no-section-label = false
|
|
||||||
git-repository-url = "https://github.com/rust-lang/mdBook"
|
|
||||||
git-repository-icon = "fa-github"
|
|
||||||
edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}"
|
|
||||||
site-url = "/example-book/"
|
|
||||||
cname = "myproject.rs"
|
|
||||||
input-404 = "not-found.md"
|
|
||||||
|
|
||||||
[output.html.print]
|
|
||||||
enable = true
|
|
||||||
|
|
||||||
[output.html.fold]
|
|
||||||
enable = false
|
|
||||||
level = 0
|
|
||||||
|
|
||||||
[output.html.playground]
|
|
||||||
editable = false
|
|
||||||
copy-js = true
|
|
||||||
line-numbers = false
|
|
||||||
|
|
||||||
[output.html.search]
|
|
||||||
enable = true
|
|
||||||
limit-results = 30
|
|
||||||
teaser-word-count = 30
|
|
||||||
use-boolean-and = true
|
|
||||||
boost-title = 2
|
|
||||||
boost-hierarchy = 1
|
|
||||||
boost-paragraph = 1
|
|
||||||
expand = true
|
|
||||||
heading-split-level = 3
|
|
||||||
copy-js = true
|
|
||||||
|
|
||||||
[output.html.redirect]
|
[output.html.redirect]
|
||||||
"/appendices/bibliography.html" = "https://rustc-dev-guide.rust-lang.org/appendix/bibliography.html"
|
"/appendices/bibliography.html" = "https://rustc-dev-guide.rust-lang.org/appendix/bibliography.html"
|
||||||
"/other-installation-methods.html" = "../infra/other-installation-methods.html"
|
"/other-installation-methods.html" = "../infra/other-installation-methods.html"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Markdown Renderer
|
The table contains key-value pairs where the key is where the redirect file needs to be created, as an absolute path from the build directory, (e.g. `/appendices/bibliography.html`).
|
||||||
|
The value can be any valid URI the browser should navigate to (e.g. `https://rust-lang.org/`, `/overview.html`, or `../bibliography.html`).
|
||||||
|
|
||||||
|
This will generate an HTML page which will automatically redirect to the given location.
|
||||||
|
Note that the source location does not support `#` anchor redirects.
|
||||||
|
|
||||||
|
## Markdown Renderer
|
||||||
|
|
||||||
The Markdown renderer will run preprocessors and then output the resulting
|
The Markdown renderer will run preprocessors and then output the resulting
|
||||||
Markdown. This is mostly useful for debugging preprocessors, especially in
|
Markdown. This is mostly useful for debugging preprocessors, especially in
|
||||||
|
@ -190,20 +295,3 @@ only whether it is enabled or disabled.
|
||||||
|
|
||||||
See [the preprocessors documentation](preprocessors.md) for how to
|
See [the preprocessors documentation](preprocessors.md) for how to
|
||||||
specify which preprocessors should run before the Markdown renderer.
|
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](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.
|
|
||||||
|
|
||||||
The custom renderer has access to all the fields within its table (i.e.
|
|
||||||
anything under `[output.foo]`). mdBook checks for two common fields:
|
|
||||||
|
|
||||||
- **command:** The command to execute for this custom renderer. Defaults to
|
|
||||||
the name of the renderer with the `mdbook-` prefix (such as `mdbook-foo`).
|
|
||||||
- **optional:** If `true`, then the command will be ignored if it is not
|
|
||||||
installed, otherwise mdBook will fail with an error. Defaults to `false`.
|
|
||||||
|
|
||||||
[alternative backends]: ../../for_developers/backends.md
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<svg height="144" width="144" xmlns="http://www.w3.org/2000/svg"><path d="m71.05 23.68c-26.06 0-47.27 21.22-47.27 47.27s21.22 47.27 47.27 47.27 47.27-21.22 47.27-47.27-21.22-47.27-47.27-47.27zm-.07 4.2a3.1 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm7.12 5.12a38.27 38.27 0 0 1 26.2 18.66l-3.67 8.28c-.63 1.43.02 3.11 1.44 3.75l7.06 3.13a38.27 38.27 0 0 1 .08 6.64h-3.93c-.39 0-.55.26-.55.64v1.8c0 4.24-2.39 5.17-4.49 5.4-2 .23-4.21-.84-4.49-2.06-1.18-6.63-3.14-8.04-6.24-10.49 3.85-2.44 7.85-6.05 7.85-10.87 0-5.21-3.57-8.49-6-10.1-3.42-2.25-7.2-2.7-8.22-2.7h-40.6a38.27 38.27 0 0 1 21.41-12.08l4.79 5.02c1.08 1.13 2.87 1.18 4 .09zm-44.2 23.02a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm74.15.14a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm-68.29.5h5.42v24.44h-10.94a38.27 38.27 0 0 1 -1.24-14.61l6.7-2.98c1.43-.64 2.08-2.31 1.44-3.74zm22.62.26h12.91c.67 0 4.71.77 4.71 3.8 0 2.51-3.1 3.41-5.65 3.41h-11.98zm0 17.56h9.89c.9 0 4.83.26 6.08 5.28.39 1.54 1.26 6.56 1.85 8.17.59 1.8 2.98 5.4 5.53 5.4h16.14a38.27 38.27 0 0 1 -3.54 4.1l-6.57-1.41c-1.53-.33-3.04.65-3.37 2.18l-1.56 7.28a38.27 38.27 0 0 1 -31.91-.15l-1.56-7.28c-.33-1.53-1.83-2.51-3.36-2.18l-6.43 1.38a38.27 38.27 0 0 1 -3.32-3.92h31.27c.35 0 .59-.06.59-.39v-11.06c0-.32-.24-.39-.59-.39h-9.15zm-14.43 25.33a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm46.05.14a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11z"/><path d="m115.68 70.95a44.63 44.63 0 0 1 -44.63 44.63 44.63 44.63 0 0 1 -44.63-44.63 44.63 44.63 0 0 1 44.63-44.63 44.63 44.63 0 0 1 44.63 44.63zm-.84-4.31 6.96 4.31-6.96 4.31 5.98 5.59-7.66 2.87 4.78 6.65-8.09 1.32 3.4 7.46-8.19-.29 1.88 7.98-7.98-1.88.29 8.19-7.46-3.4-1.32 8.09-6.65-4.78-2.87 7.66-5.59-5.98-4.31 6.96-4.31-6.96-5.59 5.98-2.87-7.66-6.65 4.78-1.32-8.09-7.46 3.4.29-8.19-7.98 1.88 1.88-7.98-8.19.29 3.4-7.46-8.09-1.32 4.78-6.65-7.66-2.87 5.98-5.59-6.96-4.31 6.96-4.31-5.98-5.59 7.66-2.87-4.78-6.65 8.09-1.32-3.4-7.46 8.19.29-1.88-7.98 7.98 1.88-.29-8.19 7.46 3.4 1.32-8.09 6.65 4.78 2.87-7.66 5.59 5.98 4.31-6.96 4.31 6.96 5.59-5.98 2.87 7.66 6.65-4.78 1.32 8.09 7.46-3.4-.29 8.19 7.98-1.88-1.88 7.98 8.19-.29-3.4 7.46 8.09 1.32-4.78 6.65 7.66 2.87z" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/></svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1,222 @@
|
||||||
|
# Markdown
|
||||||
|
|
||||||
|
mdBook's [parser](https://github.com/raphlinus/pulldown-cmark) adheres to the [CommonMark](https://commonmark.org/) specification with some extensions described below.
|
||||||
|
You can take a quick [tutorial](https://commonmark.org/help/tutorial/),
|
||||||
|
or [try out](https://spec.commonmark.org/dingus/) CommonMark in real time. A complete Markdown overview is out of scope for
|
||||||
|
this documentation, but below is a high level overview of some of the basics. For a more in-depth experience, check out the
|
||||||
|
[Markdown Guide](https://www.markdownguide.org).
|
||||||
|
|
||||||
|
## Text and Paragraphs
|
||||||
|
|
||||||
|
Text is rendered relatively predictably:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Here is a line of text.
|
||||||
|
|
||||||
|
This is a new line.
|
||||||
|
```
|
||||||
|
|
||||||
|
Will look like you might expect:
|
||||||
|
|
||||||
|
Here is a line of text.
|
||||||
|
|
||||||
|
This is a new line.
|
||||||
|
|
||||||
|
## Headings
|
||||||
|
|
||||||
|
Headings use the `#` marker and should be on a line by themselves. More `#` mean smaller headings:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
### A heading
|
||||||
|
|
||||||
|
Some text.
|
||||||
|
|
||||||
|
#### A smaller heading
|
||||||
|
|
||||||
|
More text.
|
||||||
|
```
|
||||||
|
|
||||||
|
### A heading
|
||||||
|
|
||||||
|
Some text.
|
||||||
|
|
||||||
|
#### A smaller heading
|
||||||
|
|
||||||
|
More text.
|
||||||
|
|
||||||
|
## Lists
|
||||||
|
|
||||||
|
Lists can be unordered or ordered. Ordered lists will order automatically:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
* milk
|
||||||
|
* eggs
|
||||||
|
* butter
|
||||||
|
|
||||||
|
1. carrots
|
||||||
|
1. celery
|
||||||
|
1. radishes
|
||||||
|
```
|
||||||
|
|
||||||
|
* milk
|
||||||
|
* eggs
|
||||||
|
* butter
|
||||||
|
|
||||||
|
1. carrots
|
||||||
|
1. celery
|
||||||
|
1. radishes
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
Linking to a URL or local file is easy:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Use [mdBook](https://github.com/rust-lang/mdBook).
|
||||||
|
|
||||||
|
Read about [mdBook](mdBook.md).
|
||||||
|
|
||||||
|
A bare url: <https://www.rust-lang.org>.
|
||||||
|
```
|
||||||
|
|
||||||
|
Use [mdBook](https://github.com/rust-lang/mdBook).
|
||||||
|
|
||||||
|
Read about [mdBook](mdBook.md).
|
||||||
|
|
||||||
|
A bare url: <https://www.rust-lang.org>.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Relative links that end with `.md` will be converted to the `.html` extension.
|
||||||
|
It is recommended to use `.md` links when possible.
|
||||||
|
This is useful when viewing the Markdown file outside of mdBook, for example on GitHub or GitLab which render Markdown automatically.
|
||||||
|
|
||||||
|
Links to `README.md` will be converted to `index.html`.
|
||||||
|
This is done since some services like GitHub render README files automatically, but web servers typically expect the root file to be called `index.html`.
|
||||||
|
|
||||||
|
You can link to individual headings with `#` fragments.
|
||||||
|
For example, `mdbook.md#text-and-paragraphs` would link to the [Text and Paragraphs](#text-and-paragraphs) section above.
|
||||||
|
The ID is created by transforming the heading such as converting to lowercase and replacing spaces with dashes.
|
||||||
|
You can click on any heading and look at the URL in your browser to see what the fragment looks like.
|
||||||
|
|
||||||
|
## Images
|
||||||
|
|
||||||
|
Including images is simply a matter of including a link to them, much like in the _Links_ section above. The following markdown
|
||||||
|
includes the Rust logo SVG image found in the `images` directory at the same level as this file:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![The Rust Logo](images/rust-logo-blk.svg)
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces the following HTML when built with mdBook:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<p><img src="images/rust-logo-blk.svg" alt="The Rust Logo" /></p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Which, of course displays the image like so:
|
||||||
|
|
||||||
|
![The Rust Logo](images/rust-logo-blk.svg)
|
||||||
|
|
||||||
|
## Extensions
|
||||||
|
|
||||||
|
mdBook has several extensions beyond the standard CommonMark specification.
|
||||||
|
|
||||||
|
### Strikethrough
|
||||||
|
|
||||||
|
Text may be rendered with a horizontal line through the center by wrapping the
|
||||||
|
text with two tilde characters on each side:
|
||||||
|
|
||||||
|
```text
|
||||||
|
An example of ~~strikethrough text~~.
|
||||||
|
```
|
||||||
|
|
||||||
|
This example will render as:
|
||||||
|
|
||||||
|
> An example of ~~strikethrough text~~.
|
||||||
|
|
||||||
|
This follows the [GitHub Strikethrough extension][strikethrough].
|
||||||
|
|
||||||
|
### Footnotes
|
||||||
|
|
||||||
|
A footnote generates a small numbered link in the text which when clicked
|
||||||
|
takes the reader to the footnote text at the bottom of the item. The footnote
|
||||||
|
label is written similarly to a link reference with a caret at the front. The
|
||||||
|
footnote text is written like a link reference definition, with the text
|
||||||
|
following the label. Example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
This is an example of a footnote[^note].
|
||||||
|
|
||||||
|
[^note]: This text is the contents of the footnote, which will be rendered
|
||||||
|
towards the bottom.
|
||||||
|
```
|
||||||
|
|
||||||
|
This example will render as:
|
||||||
|
|
||||||
|
> This is an example of a footnote[^note].
|
||||||
|
>
|
||||||
|
> [^note]: This text is the contents of the footnote, which will be rendered
|
||||||
|
> towards the bottom.
|
||||||
|
|
||||||
|
The footnotes are automatically numbered based on the order the footnotes are
|
||||||
|
written.
|
||||||
|
|
||||||
|
### Tables
|
||||||
|
|
||||||
|
Tables can be written using pipes and dashes to draw the rows and columns of
|
||||||
|
the table. These will be translated to HTML table matching the shape. Example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
| Header1 | Header2 |
|
||||||
|
|---------|---------|
|
||||||
|
| abc | def |
|
||||||
|
```
|
||||||
|
|
||||||
|
This example will render similarly to this:
|
||||||
|
|
||||||
|
| Header1 | Header2 |
|
||||||
|
|---------|---------|
|
||||||
|
| abc | def |
|
||||||
|
|
||||||
|
See the specification for the [GitHub Tables extension][tables] for more
|
||||||
|
details on the exact syntax supported.
|
||||||
|
|
||||||
|
### Task lists
|
||||||
|
|
||||||
|
Task lists can be used as a checklist of items that have been completed.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```md
|
||||||
|
- [x] Complete task
|
||||||
|
- [ ] Incomplete task
|
||||||
|
```
|
||||||
|
|
||||||
|
This will render as:
|
||||||
|
|
||||||
|
> - [x] Complete task
|
||||||
|
> - [ ] Incomplete task
|
||||||
|
|
||||||
|
See the specification for the [task list extension] for more details.
|
||||||
|
|
||||||
|
### Smart punctuation
|
||||||
|
|
||||||
|
Some ASCII punctuation sequences will be automatically turned into fancy Unicode
|
||||||
|
characters:
|
||||||
|
|
||||||
|
| ASCII sequence | Unicode |
|
||||||
|
|----------------|---------|
|
||||||
|
| `--` | – |
|
||||||
|
| `---` | — |
|
||||||
|
| `...` | … |
|
||||||
|
| `"` | “ or ”, depending on context |
|
||||||
|
| `'` | ‘ or ’, depending on context |
|
||||||
|
|
||||||
|
So, no need to manually enter those Unicode characters!
|
||||||
|
|
||||||
|
This feature is disabled by default.
|
||||||
|
To enable it, see the [`output.html.curly-quotes`] config option.
|
||||||
|
|
||||||
|
[strikethrough]: https://github.github.com/gfm/#strikethrough-extension-
|
||||||
|
[tables]: https://github.github.com/gfm/#tables-extension-
|
||||||
|
[task list extension]: https://github.github.com/gfm/#task-list-items-extension-
|
||||||
|
[`output.html.curly-quotes`]: configuration/renderers.md#html-renderer-options
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
There is a feature in mdBook that lets you hide code lines by prepending them
|
There is a feature in mdBook that lets you hide code lines by prepending them
|
||||||
with a `#` [like you would with Rustdoc][rustdoc-hide].
|
with a `#` [like you would with Rustdoc][rustdoc-hide].
|
||||||
|
This currently only works with Rust language code blocks.
|
||||||
|
|
||||||
[rustdoc-hide]: https://doc.rust-lang.org/stable/rustdoc/documentation-tests.html#hiding-portions-of-the-example
|
[rustdoc-hide]: https://doc.rust-lang.org/stable/rustdoc/documentation-tests.html#hiding-portions-of-the-example
|
||||||
|
|
||||||
|
@ -27,6 +28,60 @@ Will render as
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The code block has an eyeball icon (<i class="fa fa-eye"></i>) which will toggle the visibility of the hidden lines.
|
||||||
|
|
||||||
|
## Rust Playground
|
||||||
|
|
||||||
|
Rust language code blocks will automatically get a play button (<i class="fa fa-play"></i>) which will execute the code and display the output just below the code block.
|
||||||
|
This works by sending the code to the [Rust Playground].
|
||||||
|
|
||||||
|
```rust
|
||||||
|
println!("Hello, World!");
|
||||||
|
```
|
||||||
|
|
||||||
|
If there is no `main` function, then the code is automatically wrapped inside one.
|
||||||
|
|
||||||
|
If you wish to disable the play button, you can include the `noplayground` option on the code block like this:
|
||||||
|
|
||||||
|
~~~markdown
|
||||||
|
```rust,noplayground
|
||||||
|
let mut name = String::new();
|
||||||
|
std::io::stdin().read_line(&mut name).expect("failed to read line");
|
||||||
|
println!("Hello {}!", name);
|
||||||
|
```
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Rust code block attributes
|
||||||
|
|
||||||
|
Additional attributes can be included in Rust code blocks with comma, space, or tab-separated terms just after the language term. For example:
|
||||||
|
|
||||||
|
~~~markdown
|
||||||
|
```rust,ignore
|
||||||
|
# This example won't be tested.
|
||||||
|
panic!("oops!");
|
||||||
|
```
|
||||||
|
~~~
|
||||||
|
|
||||||
|
These are particularly important when using [`mdbook test`] to test Rust examples.
|
||||||
|
These use the same attributes as [rustdoc attributes], with a few additions:
|
||||||
|
|
||||||
|
* `editable` — Enables the [editor].
|
||||||
|
* `noplayground` — Removes the play button, but will still be tested.
|
||||||
|
* `mdbook-runnable` — Forces the play button to be displayed.
|
||||||
|
This is intended to be combined with the `ignore` attribute for examples that should not be tested, but you want to allow the reader to run.
|
||||||
|
* `ignore` — Will not be tested and no play button is shown, but it is still highlighted as Rust syntax.
|
||||||
|
* `should_panic` — When executed, it should produce a panic.
|
||||||
|
* `no_run` — The code is compiled when tested, but it is not run.
|
||||||
|
The play button is also not shown.
|
||||||
|
* `compile_fail` — The code should fail to compile.
|
||||||
|
* `edition2015`, `edition2018`, `edition2021` — Forces the use of a specific Rust edition.
|
||||||
|
See [`rust.edition`] to set this globally.
|
||||||
|
|
||||||
|
[`mdbook test`]: ../cli/test.md
|
||||||
|
[rustdoc attributes]: https://doc.rust-lang.org/rustdoc/documentation-tests.html#attributes
|
||||||
|
[editor]: theme/editor.md
|
||||||
|
[`rust.edition`]: configuration/general.md#rust-options
|
||||||
|
|
||||||
## Including files
|
## Including files
|
||||||
|
|
||||||
With the following syntax, you can include files into your book:
|
With the following syntax, you can include files into your book:
|
||||||
|
@ -191,6 +246,17 @@ Here is what a rendered code snippet looks like:
|
||||||
|
|
||||||
{{#playground example.rs}}
|
{{#playground example.rs}}
|
||||||
|
|
||||||
|
Any additional values passed after the filename will be included as attributes of the code block.
|
||||||
|
For example `\{{#playground example.rs editable}}` will create the code block like the following:
|
||||||
|
|
||||||
|
~~~markdown
|
||||||
|
```rust,editable
|
||||||
|
# Contents of example.rs here.
|
||||||
|
```
|
||||||
|
~~~
|
||||||
|
|
||||||
|
And the `editable` attribute will enable the [editor] as described at [Rust code block attributes](#rust-code-block-attributes).
|
||||||
|
|
||||||
[Rust Playground]: https://play.rust-lang.org/
|
[Rust Playground]: https://play.rust-lang.org/
|
||||||
|
|
||||||
## Controlling page \<title\>
|
## Controlling page \<title\>
|
||||||
|
|
|
@ -35,7 +35,7 @@ to be ignored at best, or may cause an error when attempting to build the book.
|
||||||
Titles are optional, and the numbered chapters can be broken into as many
|
Titles are optional, and the numbered chapters can be broken into as many
|
||||||
parts as desired.
|
parts as desired.
|
||||||
```markdown
|
```markdown
|
||||||
# My Part Tile
|
# My Part Title
|
||||||
|
|
||||||
- [First Chapter](relative/path/to/markdown.md)
|
- [First Chapter](relative/path/to/markdown.md)
|
||||||
```
|
```
|
||||||
|
|
|
@ -35,9 +35,13 @@ built-in ones, they will not get updated with new fixes / features.
|
||||||
**Note:** When you override a file, it is possible that you break some
|
**Note:** When you override a file, it is possible that you break some
|
||||||
functionality. Therefore I recommend to use the file from the default theme as
|
functionality. Therefore I recommend to use the file from the default theme as
|
||||||
template and only add / modify what you need. You can copy the default theme
|
template and only add / modify what you need. You can copy the default theme
|
||||||
into your source directory automatically by using `mdbook init --theme` just
|
into your source directory automatically by using `mdbook init --theme` and just
|
||||||
remove the files you don't want to override.
|
remove the files you don't want to override.
|
||||||
|
|
||||||
|
`mdbook init --theme` will not create every file listed above.
|
||||||
|
Some files, such as `head.hbs`, do not have built-in equivalents.
|
||||||
|
Just create the file if you need it.
|
||||||
|
|
||||||
If you completely replace all built-in themes, be sure to also set
|
If you completely replace all built-in themes, be sure to also set
|
||||||
[`output.html.preferred-dark-theme`] in the config, which defaults to the
|
[`output.html.preferred-dark-theme`] in the config, which defaults to the
|
||||||
built-in `navy` theme.
|
built-in `navy` theme.
|
||||||
|
|
|
@ -12,12 +12,14 @@ editable = true
|
||||||
To make a specific block available for editing, the attribute `editable` needs
|
To make a specific block available for editing, the attribute `editable` needs
|
||||||
to be added to it:
|
to be added to it:
|
||||||
|
|
||||||
<pre><code class="language-markdown">```rust,editable
|
~~~markdown
|
||||||
|
```rust,editable
|
||||||
fn main() {
|
fn main() {
|
||||||
let number = 5;
|
let number = 5;
|
||||||
print!("{}", number);
|
print!("{}", number);
|
||||||
}
|
}
|
||||||
```</code></pre>
|
```
|
||||||
|
~~~
|
||||||
|
|
||||||
The above will result in this editable playground:
|
The above will result in this editable playground:
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Introduction
|
|
||||||
|
|
||||||
A frontmatter chapter.
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# User Guide
|
||||||
|
|
||||||
|
This user guide provides an introduction to basic concepts of using mdBook.
|
||||||
|
|
||||||
|
- [Installation](installation.md)
|
||||||
|
- [Reading Books](reading.md)
|
||||||
|
- [Creating a Book](creating.md)
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Creating a Book
|
||||||
|
|
||||||
|
Once you have the `mdbook` CLI tool installed, you can use it to create and render a book.
|
||||||
|
|
||||||
|
## Initializing a book
|
||||||
|
|
||||||
|
The `mdbook init` command will create a new directory containing an empty book for you to get started.
|
||||||
|
Give it the name of the directory that you want to create:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mdbook init my-first-book
|
||||||
|
```
|
||||||
|
|
||||||
|
It will ask a few questions before generating the book.
|
||||||
|
After answering the questions, you can change the current directory into the new book:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd my-first-book
|
||||||
|
```
|
||||||
|
|
||||||
|
There are several ways to render a book, but one of the easiest methods is to use the `serve` command, which will build your book and start a local webserver:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mdbook serve --open
|
||||||
|
```
|
||||||
|
|
||||||
|
The `--open` option will open your default web browser to view your new book.
|
||||||
|
You can leave the server running even while you edit the content of the book, and `mdbook` will automatically rebuild the output *and* automatically refresh your web browser.
|
||||||
|
|
||||||
|
Check out the [CLI Guide](../cli/index.html) for more information about other `mdbook` commands and CLI options.
|
||||||
|
|
||||||
|
## Anatomy of a book
|
||||||
|
|
||||||
|
A book is built from several files which define the settings and layout of the book.
|
||||||
|
|
||||||
|
### `book.toml`
|
||||||
|
|
||||||
|
In the root of your book, there is a `book.toml` file which contains settings for describing how to build your book.
|
||||||
|
This is written in the [TOML markup language](https://toml.io/).
|
||||||
|
The default settings are usually good enough to get you started.
|
||||||
|
When you are interested in exploring more features and options that mdBook provides, check out the [Configuration chapter](../format/configuration/index.html) for more details.
|
||||||
|
|
||||||
|
A very basic `book.toml` can be as simple as this:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[book]
|
||||||
|
title = "My First Book"
|
||||||
|
```
|
||||||
|
|
||||||
|
### `SUMMARY.md`
|
||||||
|
|
||||||
|
The next major part of a book is the summary file located at `src/SUMMARY.md`.
|
||||||
|
This file contains a list of all the chapters in the book.
|
||||||
|
Before a chapter can be viewed, it must be added to this list.
|
||||||
|
|
||||||
|
Here's a basic summary file with a few chapters:
|
||||||
|
|
||||||
|
```md
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
[Introduction](README.md)
|
||||||
|
|
||||||
|
- [My First Chapter](my-first-chapter.md)
|
||||||
|
- [Nested example](nested/README.md)
|
||||||
|
- [Sub-chapter](nested/sub-chapter.md)
|
||||||
|
```
|
||||||
|
|
||||||
|
Try opening up `src/SUMMARY.md` in your editor and adding a few chapters.
|
||||||
|
If any of the chapter files do not exist, `mdbook` will automatically create them for you.
|
||||||
|
|
||||||
|
For more details on other formatting options for the summary file, check out the [Summary chapter](../format/summary.md).
|
||||||
|
|
||||||
|
### Source files
|
||||||
|
|
||||||
|
The content of your book is all contained in the `src` directory.
|
||||||
|
Each chapter is a separate Markdown file.
|
||||||
|
Typically, each chapter starts with a level 1 heading with the title of the chapter.
|
||||||
|
|
||||||
|
```md
|
||||||
|
# My First Chapter
|
||||||
|
|
||||||
|
Fill out your content here.
|
||||||
|
```
|
||||||
|
|
||||||
|
The precise layout of the files is up to you.
|
||||||
|
The organization of the files will correspond to the HTML files generated, so keep in mind that the file layout is part of the URL of each chapter.
|
||||||
|
|
||||||
|
While the `mdbook serve` command is running, you can open any of the chapter files and start editing them.
|
||||||
|
Each time you save the file, `mdbook` will rebuild the book and refresh your web browser.
|
||||||
|
|
||||||
|
Check out the [Markdown chapter](../format/markdown.md) for more information on formatting the content of your chapters.
|
||||||
|
|
||||||
|
All other files in the `src` directory will be included in the output.
|
||||||
|
So if you have images or other static files, just include them somewhere in the `src` directory.
|
||||||
|
|
||||||
|
## Publishing a book
|
||||||
|
|
||||||
|
Once you've written your book, you may want to host it somewhere for others to view.
|
||||||
|
The first step is to build the output of the book.
|
||||||
|
This can be done with the `mbdook build` command in the same directory where the `book.toml` file is located:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mdbook build
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate a directory named `book` which contains the HTML content of your book.
|
||||||
|
You can then place this directory on any web server to host it.
|
||||||
|
|
||||||
|
For more information about publishing and deploying, check out the [Continuous Integration chapter](../continuous-integration.md) for more.
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
There are multiple ways to install the mdBook CLI tool.
|
||||||
|
Choose any one of the methods below that best suit your needs.
|
||||||
|
If you are installing mdBook for automatic deployment, check out the [continuous integration] chapter for more examples on how to install.
|
||||||
|
|
||||||
|
[continuous integration]: ../continuous-integration.md
|
||||||
|
|
||||||
|
## Pre-compiled binaries
|
||||||
|
|
||||||
|
Executable binaries are available for download on the [GitHub Releases page][releases].
|
||||||
|
Download the binary for your platform (Windows, macOS, or Linux) and extract the archive.
|
||||||
|
The archive contains an `mdbook` executable which you can run to build your books.
|
||||||
|
|
||||||
|
To make it easier to run, put the path to the binary into your `PATH`.
|
||||||
|
|
||||||
|
[releases]: https://github.com/rust-lang/mdBook/releases
|
||||||
|
|
||||||
|
## Build from source using Rust
|
||||||
|
|
||||||
|
To build the `mdbook` executable from source, you will first need to install Rust and Cargo.
|
||||||
|
Follow the instructions on the [Rust installation page].
|
||||||
|
mdBook currently requires at least Rust version 1.46.
|
||||||
|
|
||||||
|
Once you have installed Rust, the following command can be used to build and install mdBook:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install mdbook
|
||||||
|
```
|
||||||
|
|
||||||
|
This will automatically download mdBook from [crates.io], build it, and install it in Cargo's global binary directory (`~/.cargo/bin/` by default).
|
||||||
|
|
||||||
|
[Rust installation page]: https://www.rust-lang.org/tools/install
|
||||||
|
[crates.io]: https://crates.io/
|
||||||
|
|
||||||
|
### Installing the latest master version
|
||||||
|
|
||||||
|
The version published to crates.io will ever so slightly be behind the version hosted on GitHub.
|
||||||
|
If you need the latest version you can build the git version of mdBook yourself.
|
||||||
|
Cargo makes this ***super easy***!
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install --git https://github.com/rust-lang/mdBook.git mdbook
|
||||||
|
```
|
||||||
|
|
||||||
|
Again, make sure to add the Cargo bin directory to your `PATH`.
|
||||||
|
|
||||||
|
If you are interested in making modifications to mdBook itself, check out the [Contributing Guide] for more information.
|
||||||
|
|
||||||
|
[Contributing Guide]: https://github.com/rust-lang/mdBook/blob/master/CONTRIBUTING.md
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Reading Books
|
||||||
|
|
||||||
|
This chapter gives an introduction on how to interact with a book produced by mdBook.
|
||||||
|
This assumes you are reading an HTML book.
|
||||||
|
The options and formatting will be different for other output formats such as PDF.
|
||||||
|
|
||||||
|
A book is organized into *chapters*.
|
||||||
|
Each chapter is a separate page.
|
||||||
|
Chapters can be nested into a hierarchy of sub-chapters.
|
||||||
|
Typically, each chapter will be organized into a series of *headings* to subdivide a chapter.
|
||||||
|
|
||||||
|
## Navigation
|
||||||
|
|
||||||
|
There are several methods for navigating through the chapters of a book.
|
||||||
|
|
||||||
|
The **sidebar** on the left provides a list of all chapters.
|
||||||
|
Clicking on any of the chapter titles will load that page.
|
||||||
|
|
||||||
|
The sidebar may not automatically appear if the window is too narrow, particularly on mobile displays.
|
||||||
|
In that situation, the menu icon (three horizontal bars) at the top-left of the page can be pressed to open and close the sidebar.
|
||||||
|
|
||||||
|
The **arrow buttons** at the bottom of the page can be used to navigate to the previous or the next chapter.
|
||||||
|
|
||||||
|
The **left and right arrow keys** on the keyboard can be used to navigate to the previous or the next chapter.
|
||||||
|
|
||||||
|
## Top menu bar
|
||||||
|
|
||||||
|
The menu bar at the top of the page provides some icons for interacting with the book.
|
||||||
|
The icons displayed will depend on the settings of how the book was generated.
|
||||||
|
|
||||||
|
| Icon | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| <i class="fa fa-bars"></i> | Opens and closes the chapter listing sidebar. |
|
||||||
|
| <i class="fa fa-paint-brush"></i> | Opens a picker to choose a different color theme. |
|
||||||
|
| <i class="fa fa-search"></i> | Opens a search bar for searching within the book. |
|
||||||
|
| <i class="fa fa-print"></i> | Instructs the web browser to print the entire book. |
|
||||||
|
| <i class="fa fa-github"></i> | Opens a link to the website that hosts the source code of the book. |
|
||||||
|
| <i class="fa fa-edit"></i> | Opens a page to directly edit the source of the page you are currently reading. |
|
||||||
|
|
||||||
|
Tapping the menu bar will scroll the page to the top.
|
||||||
|
|
||||||
|
## Search
|
||||||
|
|
||||||
|
Each book has a built-in search system.
|
||||||
|
Pressing the search icon (<i class="fa fa-search"></i>) in the menu bar, or pressing the `S` key on the keyboard will open an input box for entering search terms.
|
||||||
|
Typing some terms will show matching chapters and sections in real time.
|
||||||
|
|
||||||
|
Clicking any of the results will jump to that section.
|
||||||
|
The up and down arrow keys can be used to navigate the results, and enter will open the highlighted section.
|
||||||
|
|
||||||
|
After loading a search result, the matching search terms will be highlighted in the text.
|
||||||
|
Clicking a highlighted word or pressing the `Esc` key will remove the highlighting.
|
||||||
|
|
||||||
|
## Code blocks
|
||||||
|
|
||||||
|
mdBook books are often used for programming projects, and thus support highlighting code blocks and samples.
|
||||||
|
Code blocks may contain several different icons for interacting with them:
|
||||||
|
|
||||||
|
| Icon | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| <i class="fa fa-copy"></i> | Copies the code block into your local clipboard, to allow pasting into another application. |
|
||||||
|
| <i class="fa fa-play"></i> | For Rust code examples, this will execute the sample code and display the compiler output just below the example (see [playground]). |
|
||||||
|
| <i class="fa fa-eye"></i> | For Rust code examples, this will toggle visibility of "hidden" lines. Sometimes, larger examples will hide lines which are not particularly relevant to what is being illustrated (see [hiding code lines]). |
|
||||||
|
| <i class="fa fa-history"></i> | For [editable code examples][editor], this will undo any changes you have made. |
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
println!("Hello, World!");
|
||||||
|
```
|
||||||
|
|
||||||
|
[editor]: ../format/theme/editor.md
|
||||||
|
[playground]: ../format/mdbook.md#rust-playground
|
||||||
|
[hiding code lines]: ../format/mdbook.md#hiding-code-lines
|
268
src/book/mod.rs
268
src/book/mod.rs
|
@ -22,6 +22,7 @@ use std::string::ToString;
|
||||||
use tempfile::Builder as TempFileBuilder;
|
use tempfile::Builder as TempFileBuilder;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
use topological_sort::TopologicalSort;
|
||||||
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::preprocess::{
|
use crate::preprocess::{
|
||||||
|
@ -86,6 +87,20 @@ impl MDBook {
|
||||||
|
|
||||||
config.update_from_env();
|
config.update_from_env();
|
||||||
|
|
||||||
|
if config
|
||||||
|
.html_config()
|
||||||
|
.map_or(false, |html| html.google_analytics.is_some())
|
||||||
|
{
|
||||||
|
warn!(
|
||||||
|
"The output.html.google-analytics field has been deprecated; \
|
||||||
|
it will be removed in a future release.\n\
|
||||||
|
Consider placing the appropriate site tag code into the \
|
||||||
|
theme/head.hbs file instead.\n\
|
||||||
|
The tracking code may be found in the Google Analytics Admin page.\n\
|
||||||
|
"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if log_enabled!(log::Level::Trace) {
|
if log_enabled!(log::Level::Trace) {
|
||||||
for line in format!("Config: {:#?}", config).lines() {
|
for line in format!("Config: {:#?}", config).lines() {
|
||||||
trace!("{}", line);
|
trace!("{}", line);
|
||||||
|
@ -350,8 +365,7 @@ impl MDBook {
|
||||||
cmd.args(&["--edition", "2018"]);
|
cmd.args(&["--edition", "2018"]);
|
||||||
}
|
}
|
||||||
RustEdition::E2021 => {
|
RustEdition::E2021 => {
|
||||||
cmd.args(&["--edition", "2021"])
|
cmd.args(&["--edition", "2021"]);
|
||||||
.args(&["-Z", "unstable-options"]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,12 +485,7 @@ fn determine_renderers(config: &Config) -> Vec<Box<dyn Renderer>> {
|
||||||
renderers
|
renderers
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_preprocessors() -> Vec<Box<dyn Preprocessor>> {
|
const DEFAULT_PREPROCESSORS: &[&'static str] = &["links", "index"];
|
||||||
vec![
|
|
||||||
Box::new(LinkPreprocessor::new()),
|
|
||||||
Box::new(IndexPreprocessor::new()),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_default_preprocessor(pre: &dyn Preprocessor) -> bool {
|
fn is_default_preprocessor(pre: &dyn Preprocessor) -> bool {
|
||||||
let name = pre.name();
|
let name = pre.name();
|
||||||
|
@ -485,36 +494,127 @@ fn is_default_preprocessor(pre: &dyn Preprocessor) -> bool {
|
||||||
|
|
||||||
/// Look at the `MDBook` and try to figure out what preprocessors to run.
|
/// Look at the `MDBook` and try to figure out what preprocessors to run.
|
||||||
fn determine_preprocessors(config: &Config) -> Result<Vec<Box<dyn Preprocessor>>> {
|
fn determine_preprocessors(config: &Config) -> Result<Vec<Box<dyn Preprocessor>>> {
|
||||||
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::<String>::new();
|
||||||
|
|
||||||
if config.build.use_default_preprocessors {
|
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) {
|
if let Some(preprocessor_table) = config.get("preprocessor").and_then(Value::as_table) {
|
||||||
for key in preprocessor_table.keys() {
|
for (name, table) in preprocessor_table.iter() {
|
||||||
match key.as_ref() {
|
preprocessor_names.insert(name.to_string());
|
||||||
"links" => preprocessors.push(Box::new(LinkPreprocessor::new())),
|
|
||||||
"index" => preprocessors.push(Box::new(IndexPreprocessor::new())),
|
let exists = |name| {
|
||||||
name => preprocessors.push(interpret_custom_preprocessor(
|
(config.build.use_default_preprocessors && DEFAULT_PREPROCESSORS.contains(&name))
|
||||||
name,
|
|| preprocessor_table.contains_key(name)
|
||||||
&preprocessor_table[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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<dyn Preprocessor> = 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)
|
Ok(preprocessors)
|
||||||
|
} else {
|
||||||
|
Err(Error::msg("Cyclic dependency detected in preprocessors"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpret_custom_preprocessor(key: &str, table: &Value) -> Box<CmdPreprocessor> {
|
fn get_custom_preprocessor_cmd(key: &str, table: &Value) -> String {
|
||||||
let command = table
|
table
|
||||||
.get("command")
|
.get("command")
|
||||||
.and_then(Value::as_str)
|
.and_then(Value::as_str)
|
||||||
.map(ToString::to_string)
|
.map(ToString::to_string)
|
||||||
.unwrap_or_else(|| format!("mdbook-{}", key));
|
.unwrap_or_else(|| format!("mdbook-{}", key))
|
||||||
|
|
||||||
Box::new(CmdPreprocessor::new(key.to_string(), command))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpret_custom_renderer(key: &str, table: &Value) -> Box<CmdRenderer> {
|
fn interpret_custom_renderer(key: &str, table: &Value) -> Box<CmdRenderer> {
|
||||||
|
@ -614,8 +714,8 @@ mod tests {
|
||||||
|
|
||||||
assert!(got.is_ok());
|
assert!(got.is_ok());
|
||||||
assert_eq!(got.as_ref().unwrap().len(), 2);
|
assert_eq!(got.as_ref().unwrap().len(), 2);
|
||||||
assert_eq!(got.as_ref().unwrap()[0].name(), "links");
|
assert_eq!(got.as_ref().unwrap()[0].name(), "index");
|
||||||
assert_eq!(got.as_ref().unwrap()[1].name(), "index");
|
assert_eq!(got.as_ref().unwrap()[1].name(), "links");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -662,9 +762,123 @@ mod tests {
|
||||||
|
|
||||||
// make sure the `preprocessor.random` table exists
|
// make sure the `preprocessor.random` table exists
|
||||||
let random = cfg.get_preprocessor("random").unwrap();
|
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]
|
#[test]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use memchr::{self, Memchr};
|
use memchr::{self, Memchr};
|
||||||
use pulldown_cmark::{self, Event, Tag};
|
use pulldown_cmark::{self, Event, HeadingLevel, Tag};
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
@ -161,7 +161,7 @@ impl From<Link> for SummaryItem {
|
||||||
/// > match the following regex: "[^<>\n[]]+".
|
/// > match the following regex: "[^<>\n[]]+".
|
||||||
struct SummaryParser<'a> {
|
struct SummaryParser<'a> {
|
||||||
src: &'a str,
|
src: &'a str,
|
||||||
stream: pulldown_cmark::OffsetIter<'a>,
|
stream: pulldown_cmark::OffsetIter<'a, 'a>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
|
||||||
/// We can't actually put an event back into the `OffsetIter` stream, so instead we store it
|
/// We can't actually put an event back into the `OffsetIter` stream, so instead we store it
|
||||||
|
@ -263,7 +263,7 @@ impl<'a> SummaryParser<'a> {
|
||||||
loop {
|
loop {
|
||||||
match self.next_event() {
|
match self.next_event() {
|
||||||
Some(ev @ Event::Start(Tag::List(..)))
|
Some(ev @ Event::Start(Tag::List(..)))
|
||||||
| Some(ev @ Event::Start(Tag::Heading(1))) => {
|
| Some(ev @ Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
|
||||||
if is_prefix {
|
if is_prefix {
|
||||||
// we've finished prefix chapters and are at the start
|
// we've finished prefix chapters and are at the start
|
||||||
// of the numbered section.
|
// of the numbered section.
|
||||||
|
@ -302,10 +302,10 @@ impl<'a> SummaryParser<'a> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Event::Start(Tag::Heading(1))) => {
|
Some(Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
|
||||||
debug!("Found a h1 in the SUMMARY");
|
debug!("Found a h1 in the SUMMARY");
|
||||||
|
|
||||||
let tags = collect_events!(self.stream, end Tag::Heading(1));
|
let tags = collect_events!(self.stream, end Tag::Heading(HeadingLevel::H1, ..));
|
||||||
Some(stringify_events(tags))
|
Some(stringify_events(tags))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +375,7 @@ impl<'a> SummaryParser<'a> {
|
||||||
}
|
}
|
||||||
// The expectation is that pulldown cmark will terminate a paragraph before a new
|
// The expectation is that pulldown cmark will terminate a paragraph before a new
|
||||||
// heading, so we can always count on this to return without skipping headings.
|
// heading, so we can always count on this to return without skipping headings.
|
||||||
Some(ev @ Event::Start(Tag::Heading(1))) => {
|
Some(ev @ Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
|
||||||
// we're starting a new part
|
// we're starting a new part
|
||||||
self.back(ev);
|
self.back(ev);
|
||||||
break;
|
break;
|
||||||
|
@ -527,10 +527,10 @@ impl<'a> SummaryParser<'a> {
|
||||||
fn parse_title(&mut self) -> Option<String> {
|
fn parse_title(&mut self) -> Option<String> {
|
||||||
loop {
|
loop {
|
||||||
match self.next_event() {
|
match self.next_event() {
|
||||||
Some(Event::Start(Tag::Heading(1))) => {
|
Some(Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
|
||||||
debug!("Found a h1 in the SUMMARY");
|
debug!("Found a h1 in the SUMMARY");
|
||||||
|
|
||||||
let tags = collect_events!(self.stream, end Tag::Heading(1));
|
let tags = collect_events!(self.stream, end Tag::Heading(HeadingLevel::H1, ..));
|
||||||
return Some(stringify_events(tags));
|
return Some(stringify_events(tags));
|
||||||
}
|
}
|
||||||
// Skip a HTML element such as a comment line.
|
// Skip a HTML element such as a comment line.
|
||||||
|
|
|
@ -758,11 +758,16 @@ impl HtmlConfig {
|
||||||
pub struct Print {
|
pub struct Print {
|
||||||
/// Whether print support is enabled.
|
/// Whether print support is enabled.
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
/// Insert page breaks between chapters. Default: `true`.
|
||||||
|
pub page_break: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Print {
|
impl Default for Print {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { enable: true }
|
Self {
|
||||||
|
enable: true,
|
||||||
|
page_break: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ fn get_build_opts(args: &ArgMatches) -> BuildOpts {
|
||||||
|
|
||||||
fn open<P: AsRef<OsStr>>(path: P) {
|
fn open<P: AsRef<OsStr>>(path: P) {
|
||||||
info!("Opening web browser");
|
info!("Opening web browser");
|
||||||
if let Err(e) = open::that(path) {
|
if let Err(e) = opener::open(path) {
|
||||||
error!("Error opening web browser: {}", e);
|
error!("Error opening web browser: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,7 +261,7 @@ impl HtmlHandlebars {
|
||||||
ctx.html_config.curly_quotes,
|
ctx.html_config.curly_quotes,
|
||||||
Some(&md_ctx),
|
Some(&md_ctx),
|
||||||
);
|
);
|
||||||
if !ctx.is_index {
|
if !ctx.is_index && ctx.html_config.print.page_break {
|
||||||
// Add page break between chapters
|
// 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
|
// 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
|
// Add both two CSS properties because of the compatibility issue
|
||||||
|
|
|
@ -85,7 +85,7 @@ fn render_item(
|
||||||
.with_context(|| "Could not convert HTML path to str")?;
|
.with_context(|| "Could not convert HTML path to str")?;
|
||||||
let anchor_base = utils::fs::normalize_path(filepath);
|
let anchor_base = utils::fs::normalize_path(filepath);
|
||||||
|
|
||||||
let mut p = utils::new_cmark_parser(&chapter.content).peekable();
|
let mut p = utils::new_cmark_parser(&chapter.content, false).peekable();
|
||||||
|
|
||||||
let mut in_heading = false;
|
let mut in_heading = false;
|
||||||
let max_section_depth = u32::from(search_config.heading_split_level);
|
let max_section_depth = u32::from(search_config.heading_split_level);
|
||||||
|
@ -99,7 +99,7 @@ fn render_item(
|
||||||
|
|
||||||
while let Some(event) = p.next() {
|
while let Some(event) = p.next() {
|
||||||
match event {
|
match event {
|
||||||
Event::Start(Tag::Heading(i)) if i <= max_section_depth => {
|
Event::Start(Tag::Heading(i, ..)) if i as u32 <= max_section_depth => {
|
||||||
if !heading.is_empty() {
|
if !heading.is_empty() {
|
||||||
// Section finished, the next heading is following now
|
// Section finished, the next heading is following now
|
||||||
// Write the data to the index, and clear it for the next section
|
// Write the data to the index, and clear it for the next section
|
||||||
|
@ -118,7 +118,7 @@ fn render_item(
|
||||||
|
|
||||||
in_heading = true;
|
in_heading = true;
|
||||||
}
|
}
|
||||||
Event::End(Tag::Heading(i)) if i <= max_section_depth => {
|
Event::End(Tag::Heading(i, ..)) if i as u32 <= max_section_depth => {
|
||||||
in_heading = false;
|
in_heading = false;
|
||||||
section_id = Some(utils::id_from_content(&heading));
|
section_id = Some(utils::id_from_content(&heading));
|
||||||
breadcrumbs.push(heading.clone());
|
breadcrumbs.push(heading.clone());
|
||||||
|
|
|
@ -371,7 +371,14 @@ function playground_text(playground) {
|
||||||
});
|
});
|
||||||
|
|
||||||
themePopup.addEventListener('click', function (e) {
|
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);
|
set_theme(theme);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ html {
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
background-color: var(--bg);
|
background-color: var(--bg);
|
||||||
text-size-adjust: none;
|
text-size-adjust: none;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
|
|
||||||
--links: #2b79a2;
|
--links: #2b79a2;
|
||||||
|
|
||||||
--inline-code-color: #c5c8c6;;
|
--inline-code-color: #c5c8c6;
|
||||||
|
|
||||||
--theme-popup-bg: #141617;
|
--theme-popup-bg: #141617;
|
||||||
--theme-popup-border: #43484d;
|
--theme-popup-border: #43484d;
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
|
|
||||||
--links: #2b79a2;
|
--links: #2b79a2;
|
||||||
|
|
||||||
--inline-code-color: #c5c8c6;;
|
--inline-code-color: #c5c8c6;
|
||||||
|
|
||||||
--theme-popup-bg: #161923;
|
--theme-popup-bg: #161923;
|
||||||
--theme-popup-border: #737480;
|
--theme-popup-border: #737480;
|
||||||
|
@ -228,7 +228,7 @@
|
||||||
|
|
||||||
--links: #2b79a2;
|
--links: #2b79a2;
|
||||||
|
|
||||||
--inline-code-color: #c5c8c6;;
|
--inline-code-color: #c5c8c6;
|
||||||
|
|
||||||
--theme-popup-bg: #141617;
|
--theme-popup-bg: #141617;
|
||||||
--theme-popup-border: #43484d;
|
--theme-popup-border: #43484d;
|
||||||
|
|
119
src/utils/mod.rs
119
src/utils/mod.rs
|
@ -76,19 +76,11 @@ pub fn id_from_content(content: &str) -> String {
|
||||||
let mut content = content.to_string();
|
let mut content = content.to_string();
|
||||||
|
|
||||||
// Skip any tags or html-encoded stuff
|
// Skip any tags or html-encoded stuff
|
||||||
const REPL_SUB: &[&str] = &[
|
lazy_static! {
|
||||||
"<em>",
|
static ref HTML: Regex = Regex::new(r"(<.*?>)").unwrap();
|
||||||
"</em>",
|
}
|
||||||
"<code>",
|
content = HTML.replace_all(&content, "").into();
|
||||||
"</code>",
|
const REPL_SUB: &[&str] = &["<", ">", "&", "'", """];
|
||||||
"<strong>",
|
|
||||||
"</strong>",
|
|
||||||
"<",
|
|
||||||
">",
|
|
||||||
"&",
|
|
||||||
"'",
|
|
||||||
""",
|
|
||||||
];
|
|
||||||
for sub in REPL_SUB {
|
for sub in REPL_SUB {
|
||||||
content = content.replace(sub, "");
|
content = content.replace(sub, "");
|
||||||
}
|
}
|
||||||
|
@ -264,12 +256,15 @@ pub fn render_markdown(text: &str, curly_quotes: bool) -> String {
|
||||||
render_markdown_with_path(text, curly_quotes, None)
|
render_markdown_with_path(text, curly_quotes, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_cmark_parser(text: &str) -> Parser<'_> {
|
pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_, '_> {
|
||||||
let mut opts = Options::empty();
|
let mut opts = Options::empty();
|
||||||
opts.insert(Options::ENABLE_TABLES);
|
opts.insert(Options::ENABLE_TABLES);
|
||||||
opts.insert(Options::ENABLE_FOOTNOTES);
|
opts.insert(Options::ENABLE_FOOTNOTES);
|
||||||
opts.insert(Options::ENABLE_STRIKETHROUGH);
|
opts.insert(Options::ENABLE_STRIKETHROUGH);
|
||||||
opts.insert(Options::ENABLE_TASKLISTS);
|
opts.insert(Options::ENABLE_TASKLISTS);
|
||||||
|
if curly_quotes {
|
||||||
|
opts.insert(Options::ENABLE_SMART_PUNCTUATION);
|
||||||
|
}
|
||||||
Parser::new_ext(text, opts)
|
Parser::new_ext(text, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,52 +274,15 @@ pub fn render_markdown_with_path(
|
||||||
ctx: Option<&RenderMarkdownContext>,
|
ctx: Option<&RenderMarkdownContext>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut s = String::with_capacity(text.len() * 3 / 2);
|
let mut s = String::with_capacity(text.len() * 3 / 2);
|
||||||
let p = new_cmark_parser(text);
|
let p = new_cmark_parser(text, curly_quotes);
|
||||||
let mut converter = EventQuoteConverter::new(curly_quotes);
|
|
||||||
let events = p
|
let events = p
|
||||||
.map(clean_codeblock_headers)
|
.map(clean_codeblock_headers)
|
||||||
.map(|event| adjust_links(event, ctx))
|
.map(|event| adjust_links(event, ctx));
|
||||||
.map(|event| converter.convert(event));
|
|
||||||
|
|
||||||
html::push_html(&mut s, events);
|
html::push_html(&mut s, events);
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EventQuoteConverter {
|
|
||||||
enabled: bool,
|
|
||||||
convert_text: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventQuoteConverter {
|
|
||||||
fn new(enabled: bool) -> Self {
|
|
||||||
EventQuoteConverter {
|
|
||||||
enabled,
|
|
||||||
convert_text: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert<'a>(&mut self, event: Event<'a>) -> Event<'a> {
|
|
||||||
if !self.enabled {
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
match event {
|
|
||||||
Event::Start(Tag::CodeBlock(_)) => {
|
|
||||||
self.convert_text = false;
|
|
||||||
event
|
|
||||||
}
|
|
||||||
Event::End(Tag::CodeBlock(_)) => {
|
|
||||||
self.convert_text = true;
|
|
||||||
event
|
|
||||||
}
|
|
||||||
Event::Text(ref text) if self.convert_text => {
|
|
||||||
Event::Text(CowStr::from(convert_quotes_to_curly(text)))
|
|
||||||
}
|
|
||||||
_ => event,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> {
|
fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> {
|
||||||
match event {
|
match event {
|
||||||
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => {
|
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => {
|
||||||
|
@ -343,38 +301,6 @@ fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_quotes_to_curly(original_text: &str) -> String {
|
|
||||||
// We'll consider the start to be "whitespace".
|
|
||||||
let mut preceded_by_whitespace = true;
|
|
||||||
|
|
||||||
original_text
|
|
||||||
.chars()
|
|
||||||
.map(|original_char| {
|
|
||||||
let converted_char = match original_char {
|
|
||||||
'\'' => {
|
|
||||||
if preceded_by_whitespace {
|
|
||||||
'‘'
|
|
||||||
} else {
|
|
||||||
'’'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'"' => {
|
|
||||||
if preceded_by_whitespace {
|
|
||||||
'“'
|
|
||||||
} else {
|
|
||||||
'”'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => original_char,
|
|
||||||
};
|
|
||||||
|
|
||||||
preceded_by_whitespace = original_char.is_whitespace();
|
|
||||||
|
|
||||||
converted_char
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Prints a "backtrace" of some `Error`.
|
/// Prints a "backtrace" of some `Error`.
|
||||||
pub fn log_backtrace(e: &Error) {
|
pub fn log_backtrace(e: &Error) {
|
||||||
error!("Error: {}", e);
|
error!("Error: {}", e);
|
||||||
|
@ -588,6 +514,10 @@ more text with spaces
|
||||||
);
|
);
|
||||||
assert_eq!(id_from_content("## **Bold** title"), "bold-title");
|
assert_eq!(id_from_content("## **Bold** title"), "bold-title");
|
||||||
assert_eq!(id_from_content("## `Code` title"), "code-title");
|
assert_eq!(id_from_content("## `Code` title"), "code-title");
|
||||||
|
assert_eq!(
|
||||||
|
id_from_content("## title <span dir=rtl>foo</span>"),
|
||||||
|
"title-foo"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -621,23 +551,4 @@ more text with spaces
|
||||||
assert_eq!(normalize_id(""), "");
|
assert_eq!(normalize_id(""), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod convert_quotes_to_curly {
|
|
||||||
use super::super::convert_quotes_to_curly;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_converts_single_quotes() {
|
|
||||||
assert_eq!(convert_quotes_to_curly("'one', 'two'"), "‘one’, ‘two’");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_converts_double_quotes() {
|
|
||||||
assert_eq!(convert_quotes_to_curly(r#""one", "two""#), "“one”, “two”");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_treats_tab_as_whitespace() {
|
|
||||||
assert_eq!(convert_quotes_to_curly("\t'one'"), "\t‘one’");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
[book]
|
||||||
|
title = "mdBook test book"
|
||||||
|
description = "A demo book to test and validate changes"
|
||||||
|
authors = ["YJDoc2"]
|
||||||
|
language = "en"
|
||||||
|
|
||||||
|
[rust]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
mathjax-support = true
|
||||||
|
|
||||||
|
[output.html.playground]
|
||||||
|
editable = true
|
||||||
|
line-numbers = true
|
||||||
|
|
||||||
|
[output.html.search]
|
||||||
|
limit-results = 20
|
||||||
|
use-boolean-and = true
|
||||||
|
boost-title = 2
|
||||||
|
boost-hierarchy = 2
|
||||||
|
boost-paragraph = 1
|
||||||
|
expand = true
|
||||||
|
heading-split-level = 2
|
||||||
|
|
||||||
|
[output.html.redirect]
|
||||||
|
"/format/config.html" = "configuration/index.html"
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Demo Book
|
||||||
|
|
||||||
|
This is a simple demo book, which is intended to be used for verifying and validating style changes in mdBook.
|
||||||
|
This contains dummy examples of various markdown elements and code languages, so that one can check changes made in mdBook styles.
|
||||||
|
|
||||||
|
This rough outline is :
|
||||||
|
|
||||||
|
- individual : contains basic markdown elements such as headings, paragraphs, links etc.
|
||||||
|
- languages : contains a `hello world` in each of supported language to see changes in syntax highlighting
|
||||||
|
- rust : contains language examples specific to rust, such as play pen, runnable examples etc.
|
||||||
|
|
||||||
|
This is more for checking and fixing style, rather than verifying that correct code is generated for given markdown, that is better handled in tests.
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
[Prefix Chapter](prefix.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [Introduction](README.md)
|
||||||
|
- [Draft Chapter]()
|
||||||
|
|
||||||
|
# Actual Markdown Tag Examples
|
||||||
|
|
||||||
|
- [Markdown Individual tags](individual/README.md)
|
||||||
|
- [Heading](individual/heading.md)
|
||||||
|
- [Paragraphs](individual/paragraph.md)
|
||||||
|
- [Line Break](individual/linebreak.md)
|
||||||
|
- [Emphasis](individual/emphasis.md)
|
||||||
|
- [Blockquote](individual/blockquote.md)
|
||||||
|
- [List](individual/list.md)
|
||||||
|
- [Code](individual/code.md)
|
||||||
|
- [Image](individual/image.md)
|
||||||
|
- [Links and Horizontal Rule](individual/link_hr.md)
|
||||||
|
- [Tables](individual/table.md)
|
||||||
|
- [Tasks](individual/task.md)
|
||||||
|
- [Strikethrough](individual/strikethrough.md)
|
||||||
|
- [Mixed](individual/mixed.md)
|
||||||
|
- [Languages](languages/README.md)
|
||||||
|
- [Syntax Highlight](languages/highlight.md)
|
||||||
|
- [Rust Specific](rust/README.md)
|
||||||
|
- [Rust Codeblocks](rust/rust_codeblock.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[Suffix Chapter](suffix.md)
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Individual Common mark tags
|
||||||
|
|
||||||
|
This contains following tags:
|
||||||
|
|
||||||
|
- Headings
|
||||||
|
- Paragraphs
|
||||||
|
- Line breaks
|
||||||
|
- Emphasis
|
||||||
|
- Blockquotes
|
||||||
|
- Lists
|
||||||
|
- Code blocks
|
||||||
|
- Images
|
||||||
|
- Links and Horizontal rules
|
||||||
|
- Github tables
|
||||||
|
- Github Task Lists
|
||||||
|
- Strikethrough
|
||||||
|
- Mixed
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Blockquote
|
||||||
|
|
||||||
|
> This is a quoted sentence.
|
||||||
|
|
||||||
|
> This is a quoted paragraph
|
||||||
|
>
|
||||||
|
> separated lines
|
||||||
|
> here
|
||||||
|
|
||||||
|
> Nested
|
||||||
|
>
|
||||||
|
> > Quoted
|
||||||
|
> > Paragraph
|
||||||
|
|
||||||
|
> ### And now,
|
||||||
|
>
|
||||||
|
> **Let us _introduce_**
|
||||||
|
> All kinds of
|
||||||
|
>
|
||||||
|
> - tags
|
||||||
|
> - etc
|
||||||
|
> - stuff
|
||||||
|
>
|
||||||
|
> 1. In
|
||||||
|
> 2. The
|
||||||
|
> 3. blockquote
|
||||||
|
>
|
||||||
|
> > cause we can
|
||||||
|
> >
|
||||||
|
> > > Cause we can
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Code
|
||||||
|
|
||||||
|
This section only does simple code blocks and inline code, detailed syntax highlight and stuff is in the languages section
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
|
This is a codeblock
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This line contains `inline code`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
````
|
||||||
|
escaping ``` in ```, fun, isn't is?
|
||||||
|
````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```bash,editable
|
||||||
|
This is an editable codeblock
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// This links to a playpen
|
||||||
|
```
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Emphasis
|
||||||
|
|
||||||
|
This has **bold text** in between normal.
|
||||||
|
|
||||||
|
This has _italic text_ in between normal.
|
||||||
|
|
||||||
|
A **line** having _both_, bold and italic text.
|
||||||
|
|
||||||
|
**A bold line _having_ italic text**
|
||||||
|
|
||||||
|
_An Italic line having **bold** text_
|
||||||
|
|
||||||
|
Now this is going **_out of hands_**.
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Chapter Heading
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Really Big Heading
|
||||||
|
|
||||||
|
## Big Heading
|
||||||
|
|
||||||
|
### Normal-ish Heading
|
||||||
|
|
||||||
|
#### Small Heading...?
|
||||||
|
|
||||||
|
##### Really Small Heading
|
||||||
|
|
||||||
|
###### Is it even a heading anymore - heading
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Images
|
||||||
|
|
||||||
|
For copyright and trademark information on these images, please check [rust-artwork repository](https://github.com/rust-lang/rust-artworkhttps://github.com/rust-lang/rust-artwork)
|
||||||
|
|
||||||
|
## A 16x16 image
|
||||||
|
|
||||||
|
![16x16 rust-lang logo](http://rust-lang.org/logos/rust-logo-16x16.png)
|
||||||
|
|
||||||
|
## A 32x32 image
|
||||||
|
|
||||||
|
![32x32 rust-lang logo](http://rust-lang.org/logos/rust-logo-32x32-blk.png)
|
||||||
|
|
||||||
|
## A 256x256 image
|
||||||
|
|
||||||
|
![256x256 rust-lang logo](http://rust-lang.org/logos/rust-logo-256x256.png)
|
||||||
|
|
||||||
|
## A 512x512 image
|
||||||
|
|
||||||
|
![512x512 rust-lang logo](http://rust-lang.org/logos/rust-logo-512x512-blk.png)
|
||||||
|
|
||||||
|
## A large image
|
||||||
|
|
||||||
|
![2018 rust-conf art](https://raw.githubusercontent.com/rust-lang/rust-artwork/master/2018-RustConf/lucy-mountain-climber.png)
|
||||||
|
|
||||||
|
## A SVG image
|
||||||
|
|
||||||
|
![2018 rust-conf art svg](https://raw.githubusercontent.com/rust-lang/rust-artwork/461afe27d8e02451cf9f46e507f2c2a71d2b276b/2018-RustConf/lucy-mountain-climber.svg)
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Line breaks
|
||||||
|
|
||||||
|
This is a long
|
||||||
|
line with a couple of
|
||||||
|
line breaks in <br/>
|
||||||
|
between : both with two
|
||||||
|
spaces and return, <br/>
|
||||||
|
and with HTML tags.
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Links and Horizontal Rule
|
||||||
|
|
||||||
|
This is followed by a Horizontal rule
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
And this is preceded by a horizontal rule.
|
||||||
|
|
||||||
|
[This](www.rust-lang.org) should link to rust-lang website
|
||||||
|
[So should this][rl].
|
||||||
|
**[This][rl]** is a strong link.
|
||||||
|
_[This][rl]_ is italic.
|
||||||
|
**_[This][rl]_** is both.
|
||||||
|
|
||||||
|
[rl]: www.rust-lang.org
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Lists
|
||||||
|
|
||||||
|
1. A
|
||||||
|
2. Normal
|
||||||
|
3. Ordered
|
||||||
|
4. List
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
1. A
|
||||||
|
1. Nested
|
||||||
|
2. List
|
||||||
|
2. But
|
||||||
|
3. Still
|
||||||
|
4. Normal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- An
|
||||||
|
- Unordered
|
||||||
|
- Normal
|
||||||
|
- List
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- Nested
|
||||||
|
- Unordered
|
||||||
|
- List
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- This
|
||||||
|
1. Is
|
||||||
|
2. Normal
|
||||||
|
- ?!
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Mixed
|
||||||
|
|
||||||
|
This contains all tags randomly mixed together, to make sure style changes in one does not affect others.
|
||||||
|
|
||||||
|
### A heading
|
||||||
|
|
||||||
|
**Quite a Strong statement , to make**
|
||||||
|
|
||||||
|
~~No, cross that~~
|
||||||
|
|
||||||
|
> Whose **quote** is this
|
||||||
|
>
|
||||||
|
> > And ~~this~~
|
||||||
|
> >
|
||||||
|
> > > - and
|
||||||
|
> > > - this
|
||||||
|
> > > - also
|
||||||
|
|
||||||
|
```
|
||||||
|
You encountered a wild codepen
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust,editable
|
||||||
|
// The codepen is editable and runnable
|
||||||
|
fn main(){
|
||||||
|
println!("Hello world!");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A random image sprinkled in between
|
||||||
|
|
||||||
|
![16x16 rust-lang logo](http://rust-lang.org/logos/rust-logo-16x16.png)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- ~~An unordered list~~
|
||||||
|
- **Hello**
|
||||||
|
- _World_
|
||||||
|
- What
|
||||||
|
1. Should
|
||||||
|
2. be
|
||||||
|
3. `put`
|
||||||
|
4. here?
|
||||||
|
|
||||||
|
| col1 | col2 | col 3 | col 4 | col 5 | col 6 |
|
||||||
|
| ---- | ---- | ----- | ----- | ----- | ----- |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | val6 |
|
||||||
|
|
||||||
|
| col1 | col2 | col 3 | An Questionable table header | col 5 | col 6 |
|
||||||
|
| ---- | ---- | ----- | ---------------------------- | ----- | ---------------------------------------- |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | An equally Questionable long table value |
|
||||||
|
|
||||||
|
### Things to do
|
||||||
|
|
||||||
|
- [x] Add individual tags
|
||||||
|
- [ ] Add language examples
|
||||||
|
- [ ] Add rust specific examples
|
||||||
|
|
||||||
|
And another image
|
||||||
|
|
||||||
|
![2018 rust-conf art svg](https://raw.githubusercontent.com/rust-lang/rust-artwork/461afe27d8e02451cf9f46e507f2c2a71d2b276b/2018-RustConf/lucy-mountain-climber.svg)
|
|
@ -0,0 +1,25 @@
|
||||||
|
Just a simple paragraph.
|
||||||
|
|
||||||
|
Let's stress test this.
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer elit lorem, eleifend eu leo sit amet, suscipit feugiat libero. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Proin congue lectus sit amet lacus venenatis, ac sollicitudin purus condimentum. Suspendisse pretium volutpat sapien at gravida. In tincidunt, sem non accumsan consectetur, leo libero porttitor dolor, at imperdiet erat nibh quis leo. Cras dictum erat augue, quis pharetra justo porttitor posuere. Aenean sed lacinia justo, vel suscipit nisl. Etiam eleifend id mauris at gravida. Aliquam molestie cursus lorem pulvinar sollicitudin. Nam et ex dignissim, posuere sem non, pellentesque lacus. Morbi vulputate sed lorem et convallis. Duis non turpis eget elit posuere volutpat. Donec accumsan euismod enim, id consequat ex rhoncus ac. Pellentesque ac felis nisl. Duis imperdiet vel tellus ac iaculis.
|
||||||
|
|
||||||
|
Vivamus nec tempus enim. Integer in ligula eget elit ornare vulputate id et est. Proin mi elit, sagittis nec urna et, iaculis imperdiet neque. Vestibulum placerat cursus dolor. Donec eu sodales nulla. Praesent ac tellus eros. Donec venenatis ligula id ex porttitor malesuada. Aliquam maximus, nisi in fringilla finibus, ante elit rhoncus dui, placerat semper nisl tellus quis odio. Cras luctus magna ultrices dolor pharetra volutpat. Maecenas non enim vitae ligula efficitur aliquet id quis quam. In sagittis mollis magna eu porta. Morbi at nulla et ante elementum pharetra in sed est. Nam commodo purus enim.
|
||||||
|
|
||||||
|
Ut non elit sit amet urna luctus facilisis vel et sapien. Morbi nec metus at libero imperdiet sollicitudin eget quis lacus. Donec in ipsum at enim accumsan tempor vel sed magna. Aliquam non imperdiet neque. Etiam pharetra neque sed pretium interdum. Suspendisse potenti. Phasellus varius, lectus quis dapibus faucibus, purus mauris accumsan nibh, vel tempor quam metus nec sem. Nunc sagittis suscipit lorem eu finibus. Nullam augue leo, imperdiet vel diam et, vulputate scelerisque turpis. Nullam ut volutpat diam. Praesent cursus accumsan dui a commodo. Vivamus sed libero sed turpis facilisis rutrum id sed ligula. Ut id sollicitudin dui. Nulla pulvinar commodo lectus. Cras ut quam congue, consectetur dolor ac, consequat ante.
|
||||||
|
|
||||||
|
Curabitur scelerisque sed leo eu facilisis. Nam faucibus neque eget dictum hendrerit. Duis efficitur ex sed vulputate volutpat. Praesent condimentum nisl ac sapien efficitur laoreet. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut ut nibh elit. Nunc a neque lobortis, tempus diam vitae, interdum magna. Aenean eget nisl sed justo volutpat interdum. Mauris malesuada ex nisl, a dignissim dui elementum eget. Suspendisse potenti.
|
||||||
|
|
||||||
|
Praesent congue fringilla sem sed faucibus. Vivamus malesuada eget mauris at molestie. In sed faucibus nulla. Vivamus elementum accumsan metus quis suscipit. Maecenas interdum est nulla. Cras volutpat cursus nibh quis sollicitudin. Morbi vitae massa laoreet, aliquet tellus quis, consectetur ipsum. Mauris euismod congue purus non condimentum. Etiam laoreet mi vel sem consectetur gravida. Vestibulum volutpat magna nunc, vitae ultrices risus commodo eu.
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer elit lorem, eleifend eu leo sit amet, suscipit feugiat libero. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Proin congue lectus sit amet lacus venenatis, ac sollicitudin purus condimentum. Suspendisse pretium volutpat sapien at gravida. In tincidunt, sem non accumsan consectetur, leo libero porttitor dolor, at imperdiet erat nibh quis leo. Cras dictum erat augue, quis pharetra justo porttitor posuere. Aenean sed lacinia justo, vel suscipit nisl. Etiam eleifend id mauris at gravida. Aliquam molestie cursus lorem pulvinar sollicitudin. Nam et ex dignissim, posuere sem non, pellentesque lacus. Morbi vulputate sed lorem et convallis. Duis non turpis eget elit posuere volutpat. Donec accumsan euismod enim, id consequat ex rhoncus ac. Pellentesque ac felis nisl. Duis imperdiet vel tellus ac iaculis.
|
||||||
|
|
||||||
|
Vivamus nec tempus enim. Integer in ligula eget elit ornare vulputate id et est. Proin mi elit, sagittis nec urna et, iaculis imperdiet neque. Vestibulum placerat cursus dolor. Donec eu sodales nulla. Praesent ac tellus eros. Donec venenatis ligula id ex porttitor malesuada. Aliquam maximus, nisi in fringilla finibus, ante elit rhoncus dui, placerat semper nisl tellus quis odio. Cras luctus magna ultrices dolor pharetra volutpat. Maecenas non enim vitae ligula efficitur aliquet id quis quam. In sagittis mollis magna eu porta. Morbi at nulla et ante elementum pharetra in sed est. Nam commodo purus enim.
|
||||||
|
|
||||||
|
Ut non elit sit amet urna luctus facilisis vel et sapien. Morbi nec metus at libero imperdiet sollicitudin eget quis lacus. Donec in ipsum at enim accumsan tempor vel sed magna. Aliquam non imperdiet neque. Etiam pharetra neque sed pretium interdum. Suspendisse potenti. Phasellus varius, lectus quis dapibus faucibus, purus mauris accumsan nibh, vel tempor quam metus nec sem. Nunc sagittis suscipit lorem eu finibus. Nullam augue leo, imperdiet vel diam et, vulputate scelerisque turpis. Nullam ut volutpat diam. Praesent cursus accumsan dui a commodo. Vivamus sed libero sed turpis facilisis rutrum id sed ligula. Ut id sollicitudin dui. Nulla pulvinar commodo lectus. Cras ut quam congue, consectetur dolor ac, consequat ante.
|
||||||
|
|
||||||
|
Curabitur scelerisque sed leo eu facilisis. Nam faucibus neque eget dictum hendrerit. Duis efficitur ex sed vulputate volutpat. Praesent condimentum nisl ac sapien efficitur laoreet. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut ut nibh elit. Nunc a neque lobortis, tempus diam vitae, interdum magna. Aenean eget nisl sed justo volutpat interdum. Mauris malesuada ex nisl, a dignissim dui elementum eget. Suspendisse potenti.
|
||||||
|
|
||||||
|
Praesent congue fringilla sem sed faucibus. Vivamus malesuada eget mauris at molestie. In sed faucibus nulla. Vivamus elementum accumsan metus quis suscipit. Maecenas interdum est nulla. Cras volutpat cursus nibh quis sollicitudin. Morbi vitae massa laoreet, aliquet tellus quis, consectetur ipsum. Mauris euismod congue purus non condimentum. Etiam laoreet mi vel sem consectetur gravida. Vestibulum volutpat magna nunc, vitae ultrices risus commodo eu.
|
||||||
|
|
||||||
|
Hopefully everything above was rendered nicely, on both desktop and mobile.
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Strikethrough
|
||||||
|
|
||||||
|
~~This is Striked~~
|
||||||
|
|
||||||
|
~~This is **strong**, _italic_ , **_both_** and striked~~
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Tables
|
||||||
|
|
||||||
|
| col1 | col2 |
|
||||||
|
| ---- | ---- |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| col1 | col2 |
|
||||||
|
| ---- | ---- |
|
||||||
|
| val1 | val2 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| col1 | col2 | col 3 | col 4 | col 5 | col 6 |
|
||||||
|
| ---- | ---- | ----- | ----- | ----- | ----- |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | val6 |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | val6 |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | val6 |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | val6 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| col1 | col2 | col 3 | col 4 | col 5 | col 6 |
|
||||||
|
| -------------------------------------------------------------------------------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----- | -------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| This is a simple demo book, which is intended to be used for verifying and validating style changes in mdBook. | val2 | val3 | val5 | val4 | val6 |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | val6 |
|
||||||
|
| val1 | val2 | val3 | val5 | val4 | This is a simple demo book, which is intended to be used for verifying and validating style changes in mdBook. |
|
||||||
|
| val1 | val2 | This is a simple demo book, which is intended to be used for verifying and validating style changes in mdBook. | This is a simple demo book, which is intended to be used for verifying and validating style changes in mdBook. | val4 | val6 |
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Tasks
|
||||||
|
|
||||||
|
- [ ] Task 1
|
||||||
|
- [ ] Task 2
|
||||||
|
- [x] Completed Task 1
|
||||||
|
- [x] Completed Task 2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [ ] **Important Task**
|
||||||
|
- [x] _Completed Important task_
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Syntax Highlighting
|
||||||
|
|
||||||
|
This Currently contains following languages
|
||||||
|
|
||||||
|
- 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
|
|
@ -0,0 +1,927 @@
|
||||||
|
# Syntax Highlights
|
||||||
|
|
||||||
|
## apache
|
||||||
|
|
||||||
|
```apache
|
||||||
|
# rewrite`s rules for wordpress pretty url
|
||||||
|
LoadModule rewrite_module modules/mod_rewrite.so
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteRule . index.php [NC,L]
|
||||||
|
|
||||||
|
ExpiresActive On
|
||||||
|
ExpiresByType application/x-javascript "access plus 1 days"
|
||||||
|
|
||||||
|
Order Deny,Allow
|
||||||
|
Allow from All
|
||||||
|
|
||||||
|
<Location /maps/>
|
||||||
|
RewriteMap map txt:map.txt
|
||||||
|
RewriteMap lower int:tolower
|
||||||
|
RewriteCond %{REQUEST_URI} ^/([^/.]+)\.html$ [NC]
|
||||||
|
RewriteCond ${map:${lower:%1}|NOT_FOUND} !NOT_FOUND
|
||||||
|
RewriteRule .? /index.php?q=${map:${lower:%1}} [NC,L]
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
20.164.151.111 - - [20/Aug/2015:22:20:18 -0400] "GET /mywebpage/index.php HTTP/1.1" 403 772 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
## armasm
|
||||||
|
|
||||||
|
```armasm
|
||||||
|
.data
|
||||||
|
|
||||||
|
/* Data segment: define our message string and calculate its length. */
|
||||||
|
msg:
|
||||||
|
.ascii "Hello, ARM!\n"
|
||||||
|
len = . - msg
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/* Our application's entry point. */
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
/* syscall write(int fd, const void *buf, size_t count) */
|
||||||
|
mov %r0, $1 /* fd := STDOUT_FILENO */
|
||||||
|
ldr %r1, =msg /* buf := msg */
|
||||||
|
ldr %r2, =len /* count := len */
|
||||||
|
mov %r7, $4 /* write is syscall #4 */
|
||||||
|
swi $0 /* invoke syscall */
|
||||||
|
|
||||||
|
/* syscall exit(int status) */
|
||||||
|
mov %r0, $0 /* status := 0 */
|
||||||
|
mov %r7, $1 /* exit is syscall #1 */
|
||||||
|
swi $0 /* invoke syscall */
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## bash
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
###### CONFIG
|
||||||
|
ACCEPTED_HOSTS="/root/.hag_accepted.conf"
|
||||||
|
BE_VERBOSE=false
|
||||||
|
|
||||||
|
if [ "$UID" -ne 0 ]
|
||||||
|
then
|
||||||
|
echo "Superuser rights required"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
genApacheConf(){
|
||||||
|
echo -e "# Host ${HOME_DIR}$1/$2 :"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '"quoted"' | tr -d \" > text.txt
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## c
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdio.h>
|
||||||
|
void main(int argc,char ** argv){
|
||||||
|
printf("Hello World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## coffeescript
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
grade = (student, period=(if b? then 7 else 6)) ->
|
||||||
|
if student.excellentWork
|
||||||
|
"A+"
|
||||||
|
else if student.okayStuff
|
||||||
|
if student.triedHard then "B" else "B-"
|
||||||
|
else
|
||||||
|
"C"
|
||||||
|
|
||||||
|
class Animal extends Being
|
||||||
|
constructor: (@name) ->
|
||||||
|
|
||||||
|
move: (meters) ->
|
||||||
|
alert @name + " moved #{meters}m."
|
||||||
|
```
|
||||||
|
|
||||||
|
## cpp
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
int main() {
|
||||||
|
cout << "Hello, World!" << endl; // This prints Hello, World!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## csharp
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System;
|
||||||
|
class App
|
||||||
|
{
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Hello World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## css
|
||||||
|
|
||||||
|
```css
|
||||||
|
@font-face {
|
||||||
|
font-family: Chunkfive;
|
||||||
|
src: url('Chunkfive.otf');
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
.usertext {
|
||||||
|
color: #f0f0f0;
|
||||||
|
background: #600;
|
||||||
|
font-family: Chunkfive, sans;
|
||||||
|
--heading-1: 30px/32px Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
@import url(print.css);
|
||||||
|
@media print {
|
||||||
|
a[href^='http']::after {
|
||||||
|
content: attr(href);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## d
|
||||||
|
|
||||||
|
```d
|
||||||
|
/* This program prints a
|
||||||
|
hello world message
|
||||||
|
to the console. */
|
||||||
|
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
writeln("Hello, World!");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## diff
|
||||||
|
|
||||||
|
```diff
|
||||||
|
Index: languages/ini.js
|
||||||
|
===================================================================
|
||||||
|
--- languages/ini.js (revision 199)
|
||||||
|
+++ languages/ini.js (revision 200)
|
||||||
|
@@ -1,8 +1,7 @@
|
||||||
|
hljs.LANGUAGES.ini =
|
||||||
|
{
|
||||||
|
case_insensitive: true,
|
||||||
|
- defaultMode:
|
||||||
|
- {
|
||||||
|
+ defaultMode: {
|
||||||
|
contains: ['comment', 'title', 'setting'],
|
||||||
|
illegal: '[^\\s]'
|
||||||
|
},
|
||||||
|
|
||||||
|
*** /path/to/original timestamp
|
||||||
|
--- /path/to/new timestamp
|
||||||
|
***************
|
||||||
|
*** 1,3 ****
|
||||||
|
--- 1,9 ----
|
||||||
|
+ This is an important
|
||||||
|
+ notice! It should
|
||||||
|
+ therefore be located at
|
||||||
|
+ the beginning of this
|
||||||
|
+ document!
|
||||||
|
|
||||||
|
! compress the size of the
|
||||||
|
! changes.
|
||||||
|
|
||||||
|
It is important to spell
|
||||||
|
```
|
||||||
|
|
||||||
|
## go
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Hello World!")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## handlebars
|
||||||
|
|
||||||
|
```handlebars
|
||||||
|
<div class='entry'>
|
||||||
|
{{! only show if author exists }}
|
||||||
|
{{#if author}}
|
||||||
|
<h1>{{firstName}} {{lastName}}</h1>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
## haskell
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn "Hello World!"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## http
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /task?id=1 HTTP/1.1
|
||||||
|
Host: example.org
|
||||||
|
Content-Type: application/json; charset=utf-8
|
||||||
|
Content-Length: 137
|
||||||
|
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"extended": true,
|
||||||
|
"results": [
|
||||||
|
{"value": 0, "type": "int64"},
|
||||||
|
{"value": 1.0e+3, "type": "decimal"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## ini
|
||||||
|
|
||||||
|
```ini
|
||||||
|
; boilerplate
|
||||||
|
[package]
|
||||||
|
name = "some_name"
|
||||||
|
authors = ["Author"]
|
||||||
|
description = "This is \
|
||||||
|
a description"
|
||||||
|
|
||||||
|
[[lib]]
|
||||||
|
name = ${NAME}
|
||||||
|
default = True
|
||||||
|
auto = no
|
||||||
|
counter = 1_000
|
||||||
|
```
|
||||||
|
|
||||||
|
## java
|
||||||
|
|
||||||
|
```java
|
||||||
|
class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## javascript
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function $initHighlight(block, cls) {
|
||||||
|
try {
|
||||||
|
if (cls.search(/\bno\-highlight\b/) != -1)
|
||||||
|
return process(block, true, 0x0F) +
|
||||||
|
` class="${cls}"`;
|
||||||
|
} catch (e) {
|
||||||
|
/* handle exception */
|
||||||
|
}
|
||||||
|
for (var i = 0 / 2; i < classes.length; i++) {
|
||||||
|
if (checkCondition(classes[i]) === undefined)
|
||||||
|
console.log('undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<web-component>{block}</web-component>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export $initHighlight;
|
||||||
|
```
|
||||||
|
|
||||||
|
## json
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "apples",
|
||||||
|
"count": [12000, 20000],
|
||||||
|
"description": { "text": "...", "sensitive": false }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "oranges",
|
||||||
|
"count": [17500, null],
|
||||||
|
"description": { "text": "...", "sensitive": false }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## julia
|
||||||
|
|
||||||
|
```julia
|
||||||
|
# function to calculate the volume of a sphere
|
||||||
|
function sphere_vol(r)
|
||||||
|
# julia allows Unicode names (in UTF-8 encoding)
|
||||||
|
# so either "pi" or the symbol π can be used
|
||||||
|
return 4/3*pi*r^3
|
||||||
|
end
|
||||||
|
|
||||||
|
# functions can also be defined more succinctly
|
||||||
|
quadratic(a, sqr_term, b) = (-b + sqr_term) / 2a
|
||||||
|
|
||||||
|
# calculates x for 0 = a*x^2+b*x+c, arguments types can be defined in function definitions
|
||||||
|
function quadratic2(a::Float64, b::Float64, c::Float64)
|
||||||
|
# unlike other languages 2a is equivalent to 2*a
|
||||||
|
# a^2 is used instead of a**2 or pow(a,2)
|
||||||
|
sqr_term = sqrt(b^2-4a*c)
|
||||||
|
r1 = quadratic(a, sqr_term, b)
|
||||||
|
r2 = quadratic(a, -sqr_term, b)
|
||||||
|
# multiple values can be returned from a function using tuples
|
||||||
|
# if the return keyword is omitted, the last term is returned
|
||||||
|
r1, r2
|
||||||
|
end
|
||||||
|
|
||||||
|
vol = sphere_vol(3)
|
||||||
|
```
|
||||||
|
|
||||||
|
## kotlin
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
package org.kotlinlang.play
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
println("Hello, World!")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## less
|
||||||
|
|
||||||
|
```less
|
||||||
|
@import 'fruits';
|
||||||
|
|
||||||
|
@rhythm: 1.5em;
|
||||||
|
|
||||||
|
@media screen and (min-resolution: 2dppx) {
|
||||||
|
body {
|
||||||
|
font-size: 125%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section > .foo + #bar:hover [href*='less'] {
|
||||||
|
margin: @rhythm 0 0 @rhythm;
|
||||||
|
padding: calc(5% + 20px);
|
||||||
|
background: #f00ba7 url(http://placehold.alpha-centauri/42.png) no-repeat;
|
||||||
|
background-image: linear-gradient(-135deg, wheat, fuchsia) !important ;
|
||||||
|
background-blend-mode: multiply;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: /* ? */ 'Omega';
|
||||||
|
src: url('../fonts/omega-webfont.woff?v=2.0.2');
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-baz::before {
|
||||||
|
display: inline-block;
|
||||||
|
font-family: 'Omega', Alpha, sans-serif;
|
||||||
|
content: '\f085';
|
||||||
|
color: rgba(98, 76 /* or 54 */, 231, 0.75);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## lua
|
||||||
|
|
||||||
|
```lua
|
||||||
|
--[[
|
||||||
|
Simple signal/slot implementation
|
||||||
|
]]
|
||||||
|
local signal_mt = {
|
||||||
|
__index = {
|
||||||
|
register = table.insert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function signal_mt.__index:emit(... --[[ Comment in params ]])
|
||||||
|
for _, slot in ipairs(self) do
|
||||||
|
slot(self, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function create_signal()
|
||||||
|
return setmetatable({}, signal_mt)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Signal test
|
||||||
|
local signal = create_signal()
|
||||||
|
signal:register(function(signal, ...)
|
||||||
|
print(...)
|
||||||
|
end)
|
||||||
|
signal:emit('Answer to Life, the Universe, and Everything:', 42)
|
||||||
|
|
||||||
|
--[==[ [=[ [[
|
||||||
|
Nested ]]
|
||||||
|
multi-line ]=]
|
||||||
|
comment ]==]
|
||||||
|
[==[ Nested
|
||||||
|
[=[ multi-line
|
||||||
|
[[ string
|
||||||
|
]] ]=] ]==]
|
||||||
|
```
|
||||||
|
|
||||||
|
## makefile
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
# Makefile
|
||||||
|
|
||||||
|
BUILDDIR = _build
|
||||||
|
EXTRAS ?= $(BUILDDIR)/extras
|
||||||
|
|
||||||
|
.PHONY: main clean
|
||||||
|
|
||||||
|
main:
|
||||||
|
@echo "Building main facility..."
|
||||||
|
build_main $(BUILDDIR)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILDDIR)/*
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## markdown
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# hello world
|
||||||
|
|
||||||
|
you can write text [with links](http://example.com) inline or [link references][1].
|
||||||
|
|
||||||
|
- one _thing_ has *em*phasis
|
||||||
|
- two **things** are **bold**
|
||||||
|
|
||||||
|
[1]: http://example.com
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# hello world
|
||||||
|
|
||||||
|
<this_is inline="xml"></this_is>
|
||||||
|
|
||||||
|
> markdown is so cool
|
||||||
|
|
||||||
|
so are code segments
|
||||||
|
|
||||||
|
1. one thing (yeah!)
|
||||||
|
2. two thing `i can write code`, and `more` wipee!
|
||||||
|
```
|
||||||
|
|
||||||
|
## nginx
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
user www www;
|
||||||
|
worker_processes 2;
|
||||||
|
pid /var/run/nginx.pid;
|
||||||
|
error_log /var/log/nginx.error_log debug | info | notice | warn | error | crit;
|
||||||
|
|
||||||
|
events {
|
||||||
|
connections 2000;
|
||||||
|
use kqueue | rtsig | epoll | /dev/poll | select | poll;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] '
|
||||||
|
'"$request" $status $bytes_sent '
|
||||||
|
'"$http_referer" "$http_user_agent" '
|
||||||
|
'"$gzip_ratio"';
|
||||||
|
|
||||||
|
send_timeout 3m;
|
||||||
|
client_header_buffer_size 1k;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_min_length 1100;
|
||||||
|
|
||||||
|
#lingering_time 30;
|
||||||
|
|
||||||
|
server {
|
||||||
|
server_name one.example.com www.one.example.com;
|
||||||
|
access_log /var/log/nginx.access_log main;
|
||||||
|
|
||||||
|
rewrite (.*) /index.php?page=$1 break;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1/;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
charset koi8-r;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
fastcgi_pass 127.0.0.1:9000;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(jpg|jpeg|gif)$ {
|
||||||
|
root /spool/www;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## objectivec
|
||||||
|
|
||||||
|
```objectivec
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
int main(int argc, const char * argv[]) {
|
||||||
|
@mylak {
|
||||||
|
NSLog(@"Hello World!");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## perl
|
||||||
|
|
||||||
|
```perl
|
||||||
|
print "Hello World!\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
## php
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
echo "Hello World!";
|
||||||
|
?>
|
||||||
|
```
|
||||||
|
|
||||||
|
## plaintext
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
I think this is simply plain text?
|
||||||
|
Hello World!
|
||||||
|
```
|
||||||
|
|
||||||
|
## properties
|
||||||
|
|
||||||
|
```properties
|
||||||
|
# .properties
|
||||||
|
! Exclamation mark = comments, too
|
||||||
|
|
||||||
|
key1 = value1
|
||||||
|
key2 : value2
|
||||||
|
key3 value3
|
||||||
|
key\ spaces multiline\
|
||||||
|
value4
|
||||||
|
empty_key
|
||||||
|
! Key can contain escaped chars
|
||||||
|
\:\= = value5
|
||||||
|
```
|
||||||
|
|
||||||
|
## python
|
||||||
|
|
||||||
|
```python
|
||||||
|
@requires_authorization(roles=["ADMIN"])
|
||||||
|
def somefunc(param1='', param2=0):
|
||||||
|
r'''A docstring'''
|
||||||
|
if param1 > param2: # interesting
|
||||||
|
print 'Gre\'ater'
|
||||||
|
return (param2 - param1 + 1 + 0b10l) or None
|
||||||
|
|
||||||
|
class SomeClass:
|
||||||
|
pass
|
||||||
|
|
||||||
|
>>> message = '''interpreter
|
||||||
|
... prompt'''
|
||||||
|
```
|
||||||
|
|
||||||
|
## r
|
||||||
|
|
||||||
|
```r
|
||||||
|
require(stats)
|
||||||
|
|
||||||
|
#' Compute different averages
|
||||||
|
#'
|
||||||
|
#' @param x \code{numeric} vector of sample data
|
||||||
|
#' @param type \code{character} vector of length 1 specifying the average type
|
||||||
|
#' @return \code{centre} returns the sample average according to the chosen method.
|
||||||
|
#' @examples
|
||||||
|
#' centre(rcauchy(10), "mean")
|
||||||
|
#' @export
|
||||||
|
centre <- function(x, type) {
|
||||||
|
switch(type,
|
||||||
|
mean = mean(x),
|
||||||
|
median = median(x),
|
||||||
|
trimmed = mean(x, trim = .1))
|
||||||
|
}
|
||||||
|
x <- rcauchy(10)
|
||||||
|
centre(x, "mean")
|
||||||
|
|
||||||
|
library(ggplot2)
|
||||||
|
|
||||||
|
models <- tibble::tribble(
|
||||||
|
~model_name, ~ formula,
|
||||||
|
"length-width", Sepal.Length ~ Petal.Width + Petal.Length,
|
||||||
|
"interaction", Sepal.Length ~ Petal.Width * Petal.Length
|
||||||
|
)
|
||||||
|
|
||||||
|
iris %>%
|
||||||
|
nest_by(Species) %>%
|
||||||
|
left_join(models, by = character()) %>%
|
||||||
|
rowwise(Species, model_name) %>%
|
||||||
|
mutate(model = list(lm(formula, data = data))) %>%
|
||||||
|
summarise(broom::glance(model))
|
||||||
|
```
|
||||||
|
|
||||||
|
## ruby
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# The Greeter class
|
||||||
|
class Greeter
|
||||||
|
def initialize(name)
|
||||||
|
@name = name.capitalize
|
||||||
|
end
|
||||||
|
|
||||||
|
def salute
|
||||||
|
puts "Hello #{@name}!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
g = Greeter.new("world")
|
||||||
|
g.salute
|
||||||
|
```
|
||||||
|
|
||||||
|
## rust
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn main()->(){
|
||||||
|
println!("Hello World!");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## scala
|
||||||
|
|
||||||
|
```scala
|
||||||
|
/**
|
||||||
|
* A person has a name and an age.
|
||||||
|
*/
|
||||||
|
case class Person(name: String, age: Int)
|
||||||
|
|
||||||
|
abstract class Vertical extends CaseJeu
|
||||||
|
case class Haut(a: Int) extends Vertical
|
||||||
|
case class Bas(name: String, b: Double) extends Vertical
|
||||||
|
|
||||||
|
sealed trait Ior[+A, +B]
|
||||||
|
case class Left[A](a: A) extends Ior[A, Nothing]
|
||||||
|
case class Right[B](b: B) extends Ior[Nothing, B]
|
||||||
|
case class Both[A, B](a: A, b: B) extends Ior[A, B]
|
||||||
|
|
||||||
|
trait Functor[F[_]] {
|
||||||
|
def map[A, B](fa: F[A], f: A => B): F[B]
|
||||||
|
}
|
||||||
|
|
||||||
|
// beware Int.MinValue
|
||||||
|
def absoluteValue(n: Int): Int =
|
||||||
|
if (n < 0) -n else n
|
||||||
|
|
||||||
|
def interp(n: Int): String =
|
||||||
|
s"there are $n ${color} balloons.\n"
|
||||||
|
|
||||||
|
type ξ[A] = (A, A)
|
||||||
|
|
||||||
|
trait Hist { lhs =>
|
||||||
|
def ⊕(rhs: Hist): Hist
|
||||||
|
}
|
||||||
|
|
||||||
|
def gsum[A: Ring](as: Seq[A]): A =
|
||||||
|
as.foldLeft(Ring[A].zero)(_ + _)
|
||||||
|
|
||||||
|
val actions: List[Symbol] =
|
||||||
|
'init :: 'read :: 'write :: 'close :: Nil
|
||||||
|
```
|
||||||
|
|
||||||
|
## scss
|
||||||
|
|
||||||
|
```scss
|
||||||
|
import "compass/reset";
|
||||||
|
|
||||||
|
// variables
|
||||||
|
$colorGreen: #008000;
|
||||||
|
$colorGreenDark: darken($colorGreen, 10);
|
||||||
|
|
||||||
|
@mixin container {
|
||||||
|
max-width: 980px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mixins with parameters
|
||||||
|
@mixin button($color:green) {
|
||||||
|
@if ($color == green) {
|
||||||
|
background-color: #008000;
|
||||||
|
}
|
||||||
|
@else if ($color == red) {
|
||||||
|
background-color: #B22222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@include button(red);
|
||||||
|
}
|
||||||
|
|
||||||
|
div,
|
||||||
|
.navbar,
|
||||||
|
#header,
|
||||||
|
input[type="input"] {
|
||||||
|
font-family: "Helvetica Neue", Arial, sans-serif;
|
||||||
|
width: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-12 > [class*="spans"] {
|
||||||
|
border-left: 1px solid #B5C583;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## shell
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ echo $EDITOR
|
||||||
|
vim
|
||||||
|
$ git checkout main
|
||||||
|
Switched to branch 'main'
|
||||||
|
Your branch is up-to-date with 'origin/main'.
|
||||||
|
$ git push
|
||||||
|
Everything up-to-date
|
||||||
|
$ echo 'All
|
||||||
|
> done!'
|
||||||
|
All
|
||||||
|
done!
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## sql
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE "topic" (
|
||||||
|
"id" integer NOT NULL PRIMARY KEY,
|
||||||
|
"forum_id" integer NOT NULL,
|
||||||
|
"subject" varchar(255) NOT NULL
|
||||||
|
);
|
||||||
|
ALTER TABLE "topic"
|
||||||
|
ADD CONSTRAINT forum_id FOREIGN KEY ("forum_id")
|
||||||
|
REFERENCES "forum" ("id");
|
||||||
|
|
||||||
|
-- Initials
|
||||||
|
insert into "topic" ("forum_id", "subject")
|
||||||
|
values (2, 'D''artagnian');
|
||||||
|
```
|
||||||
|
|
||||||
|
## swift
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objc class Person: Entity {
|
||||||
|
var name: String!
|
||||||
|
var age: Int!
|
||||||
|
|
||||||
|
init(name: String, age: Int) {
|
||||||
|
/* /* ... */ */
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a descriptive string for this person
|
||||||
|
func description(offset: Int = 0) -> String {
|
||||||
|
return "\(name) is \(age + offset) years old"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## typescript
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class MyClass {
|
||||||
|
public static myValue: string;
|
||||||
|
constructor(init: string) {
|
||||||
|
this.myValue = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
import fs = require("fs");
|
||||||
|
module MyModule {
|
||||||
|
export interface MyInterface extends Other {
|
||||||
|
myProperty: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare magicNumber number;
|
||||||
|
myArray.forEach(() => { }); // fat arrow syntax
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## x86asm
|
||||||
|
|
||||||
|
```x86asm
|
||||||
|
section .text
|
||||||
|
extern _MessageBoxA@16
|
||||||
|
%if __NASM_VERSION_ID__ >= 0x02030000
|
||||||
|
safeseh handler ; register handler as "safe handler"
|
||||||
|
%endif
|
||||||
|
|
||||||
|
handler:
|
||||||
|
push dword 1 ; MB_OKCANCEL
|
||||||
|
push dword caption
|
||||||
|
push dword text
|
||||||
|
push dword 0
|
||||||
|
call _MessageBoxA@16
|
||||||
|
sub eax,1 ; incidentally suits as return value
|
||||||
|
; for exception handler
|
||||||
|
ret
|
||||||
|
|
||||||
|
global _main
|
||||||
|
_main: push dword handler
|
||||||
|
push dword [fs:0]
|
||||||
|
mov dword [fs:0], esp
|
||||||
|
xor eax,eax
|
||||||
|
mov eax, dword[eax] ; cause exception
|
||||||
|
pop dword [fs:0] ; disengage exception handler
|
||||||
|
add esp, 4
|
||||||
|
ret
|
||||||
|
|
||||||
|
avx2: vzeroupper
|
||||||
|
push rbx
|
||||||
|
mov rbx, rsp
|
||||||
|
sub rsp, 0h20
|
||||||
|
vmovdqa ymm0, [rcx]
|
||||||
|
vpaddb ymm0, [rdx]
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
|
||||||
|
text: db 'OK to rethrow, CANCEL to generate core dump',0
|
||||||
|
caption:db 'SEGV',0
|
||||||
|
|
||||||
|
section .drectve info
|
||||||
|
db '/defaultlib:user32.lib /defaultlib:msvcrt.lib '
|
||||||
|
```
|
||||||
|
|
||||||
|
## xml
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Title</title>
|
||||||
|
|
||||||
|
<style>body {width: 500px;}</style>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
function $init() {return true;}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p checked class="title" id='title'>Title</p>
|
||||||
|
<!-- here goes the rest of the page -->
|
||||||
|
</body>
|
||||||
|
```
|
||||||
|
|
||||||
|
## yaml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
# comment
|
||||||
|
string_1: "Bar"
|
||||||
|
string_2: 'bar'
|
||||||
|
string_3: bar
|
||||||
|
inline_keys_ignored: sompath/name/file.jpg
|
||||||
|
keywords_in_yaml:
|
||||||
|
- true
|
||||||
|
- false
|
||||||
|
- TRUE
|
||||||
|
- FALSE
|
||||||
|
- 21
|
||||||
|
- 21.0
|
||||||
|
- !!str 123
|
||||||
|
"quoted_key": &foobar
|
||||||
|
bar: foo
|
||||||
|
foo:
|
||||||
|
"foo": bar
|
||||||
|
|
||||||
|
reference: *foobar
|
||||||
|
|
||||||
|
multiline_1: |
|
||||||
|
Multiline
|
||||||
|
String
|
||||||
|
multiline_2: >
|
||||||
|
Multiline
|
||||||
|
String
|
||||||
|
multiline_3: "
|
||||||
|
Multiline string
|
||||||
|
"
|
||||||
|
|
||||||
|
ansible_variables: "foo {{variable}}"
|
||||||
|
|
||||||
|
array_nested:
|
||||||
|
- a
|
||||||
|
- b: 1
|
||||||
|
c: 2
|
||||||
|
- b
|
||||||
|
- comment
|
||||||
|
```
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Prefix Chapter
|
||||||
|
|
||||||
|
This is to verify the placement and style of prefix chapter in book index.
|
|
@ -0,0 +1 @@
|
||||||
|
# Rust specific code examples
|
|
@ -0,0 +1,27 @@
|
||||||
|
## Rust codeblocks
|
||||||
|
|
||||||
|
This contains various examples of codeblocks, specific to rust
|
||||||
|
|
||||||
|
## Simple
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn main(){
|
||||||
|
println!("Hello world!");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## With Hidden lines
|
||||||
|
|
||||||
|
```rust
|
||||||
|
# fn main(){
|
||||||
|
println!("Hello world!");
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Editable
|
||||||
|
|
||||||
|
```rust,editable
|
||||||
|
fn main(){
|
||||||
|
println!("Hello world!");
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Suffix Chapter
|
||||||
|
|
||||||
|
This is to verify the placement and style of suffix chapter in book index.
|
|
@ -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());
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
mod build;
|
||||||
|
mod test;
|
|
@ -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());
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
mod cli;
|
||||||
|
mod dummy_book;
|
|
@ -0,0 +1,12 @@
|
||||||
|
# This will allow users to self assign, and/or drop assignment
|
||||||
|
[assign]
|
||||||
|
|
||||||
|
|
||||||
|
[relabel]
|
||||||
|
allow-unauthenticated = [
|
||||||
|
# For Issue areas
|
||||||
|
"A-*",
|
||||||
|
"E-Help-Wanted",
|
||||||
|
"Bug",
|
||||||
|
"Feature-Request"
|
||||||
|
]
|
Loading…
Reference in New Issue