mirror of
https://github.com/rust-lang/mdBook.git
synced 2025-12-28 13:51:10 -05:00
Compare commits
52 Commits
ehuss-patc
...
v0.5.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fff6087f36 | ||
|
|
922f0d8ad4 | ||
|
|
ab1325b213 | ||
|
|
63b159741b | ||
|
|
4a9a517f27 | ||
|
|
700839f77f | ||
|
|
152132458e | ||
|
|
054da77b6a | ||
|
|
9a5e8dbb0a | ||
|
|
63c45cd879 | ||
|
|
bc7ca458b6 | ||
|
|
07fb33f5da | ||
|
|
7d1566860c | ||
|
|
f0117ec3df | ||
|
|
22065ebc79 | ||
|
|
5905bf1d85 | ||
|
|
1646e4923a | ||
|
|
1e190137c3 | ||
|
|
4417f8cb0a | ||
|
|
cc7f8be496 | ||
|
|
051fc9f01d | ||
|
|
d0bde467e0 | ||
|
|
475951c9ee | ||
|
|
5b2cc1735b | ||
|
|
1c00395230 | ||
|
|
9799326590 | ||
|
|
2546c8cc60 | ||
|
|
33c9b4063e | ||
|
|
f66fd92f32 | ||
|
|
541e16335b | ||
|
|
6cc40cb5f7 | ||
|
|
37f8a79d4d | ||
|
|
385246a9ef | ||
|
|
7619f9a91c | ||
|
|
f27c3aea4c | ||
|
|
b3bd103742 | ||
|
|
7e5fa3565b | ||
|
|
6d9f49cbc5 | ||
|
|
8670bcc540 | ||
|
|
005f4d648a | ||
|
|
59343b525d | ||
|
|
e8d7dd6f57 | ||
|
|
54175698d5 | ||
|
|
07ed00e8f7 | ||
|
|
ab8a4dfa5a | ||
|
|
e2c954f693 | ||
|
|
b2111a3f91 | ||
|
|
8ba833feb2 | ||
|
|
7124f4c7de | ||
|
|
1cc4cbb202 | ||
|
|
405f407260 | ||
|
|
eaa778bebd |
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@@ -78,9 +78,9 @@ jobs:
|
||||
- name: Install Rust
|
||||
run: bash ci/install-rust.sh stable x86_64-unknown-linux-gnu
|
||||
- name: Install npm
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
- name: Install browser-ui-test
|
||||
run: npm install
|
||||
- name: Run eslint
|
||||
@@ -119,7 +119,7 @@ jobs:
|
||||
- name: Install cargo-semver-checks
|
||||
run: |
|
||||
mkdir installed-bins
|
||||
curl -Lf https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.44.0/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz \
|
||||
curl -Lf https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.45.0/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz \
|
||||
| tar -xz --directory=./installed-bins
|
||||
echo `pwd`/installed-bins >> $GITHUB_PATH
|
||||
- run: cargo semver-checks --workspace
|
||||
|
||||
1
.github/workflows/update-dependencies.yml
vendored
1
.github/workflows/update-dependencies.yml
vendored
@@ -8,6 +8,7 @@ jobs:
|
||||
update:
|
||||
name: Update dependencies
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'rust-lang/mdBook'
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Rust
|
||||
|
||||
49
CHANGELOG.md
49
CHANGELOG.md
@@ -58,6 +58,13 @@ The following is a summary of the changes that may require your attention when u
|
||||
[#2847](https://github.com/rust-lang/mdBook/pull/2847)
|
||||
- Added support for admonitions. These are enabled by default, with the option `output.html.admonitions` to disable it.
|
||||
[#2851](https://github.com/rust-lang/mdBook/pull/2851)
|
||||
- Header ID generation has some minor changes to bring the ID generation closer to other tools and sites:
|
||||
- IDs now use Unicode lowercase instead of ASCII lowercase.
|
||||
[#2922](https://github.com/rust-lang/mdBook/pull/2922)
|
||||
- Headers that start or end with HTML characters like `<`, `&`, or `>` now replace those characters in the link ID with `-` instead of being stripped.
|
||||
[#2844](https://github.com/rust-lang/mdBook/pull/2844)
|
||||
- Headers are no longer modified if the tag is manually written HTML.
|
||||
[#2913](https://github.com/rust-lang/mdBook/pull/2913)
|
||||
|
||||
### CLI changes
|
||||
|
||||
@@ -76,7 +83,7 @@ The following is a summary of the changes that may require your attention when u
|
||||
- [`mdbook-markdown`](https://docs.rs/mdbook-markdown/latest/mdbook_markdown/) — The Markdown renderer. If you are processing markdown, this is the crate you should depend on. This is essentially a thin wrapper around `pulldown-cmark`, and re-exports that crate so that you can ensure the version stays in sync with mdBook.
|
||||
- [`mdbook-summary`](https://docs.rs/mdbook-summary/latest/mdbook_summary/) — The `SUMMARY.md` parser.
|
||||
- [`mdbook-html`](https://docs.rs/mdbook-html/latest/mdbook_html/) — The HTML renderer.
|
||||
- [`mdbook-core`](https://docs.rs/mdbook-core/latest/mdbook_core/) — An internal library that is used by the other crates for shared types. You should not depend on this crate directly since types from this crate are rexported from the other crates as appropriate.
|
||||
- [`mdbook-core`](https://docs.rs/mdbook-core/latest/mdbook_core/) — An internal library that is used by the other crates for shared types. You should not depend on this crate directly since types from this crate are re-exported from the other crates as appropriate.
|
||||
- Changes to `Config`:
|
||||
- [`Config::get`](https://docs.rs/mdbook-core/latest/mdbook_core/config/struct.Config.html#method.get) is now generic over the return value, using `serde` to deserialize the value. It also returns a `Result` to handle deserialization errors. [#2773](https://github.com/rust-lang/mdBook/pull/2773)
|
||||
- Removed `Config::get_deserialized`. Use `Config::get` instead.
|
||||
@@ -102,6 +109,46 @@ The following is a summary of the changes that may require your attention when u
|
||||
- Various functions in the `utils::fs` module have been removed, renamed, or reworked.
|
||||
- Most of the functions in the `utils` module have been moved, removed, or made private.
|
||||
|
||||
## mdBook 0.5.0-beta.2
|
||||
[v0.5.0-beta.1...v0.5.0-beta.2](https://github.com/rust-lang/mdBook/compare/v0.5.0-beta.1...v0.5.0-beta.2)
|
||||
|
||||
### Added
|
||||
|
||||
- Added a warning when a Font Awesome icon is missing.
|
||||
[#2915](https://github.com/rust-lang/mdBook/pull/2915)
|
||||
- Added some trace logging for event processing.
|
||||
[#2911](https://github.com/rust-lang/mdBook/pull/2911)
|
||||
- Added `Config::contains_key`.
|
||||
[#2910](https://github.com/rust-lang/mdBook/pull/2910)
|
||||
|
||||
### Changed
|
||||
|
||||
- Heading IDs are now lowercase.
|
||||
[#2922](https://github.com/rust-lang/mdBook/pull/2922)
|
||||
- Updated cargo dependencies.
|
||||
[#2916](https://github.com/rust-lang/mdBook/pull/2916)
|
||||
- Removed italics for in quotes/comments in code blocks with the `ayu` theme.
|
||||
[#2904](https://github.com/rust-lang/mdBook/pull/2904)
|
||||
- Exposed "search" feature from mdbook-driver.
|
||||
[#2907](https://github.com/rust-lang/mdBook/pull/2907)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed rust fenced code blocks with an indent.
|
||||
[#2905](https://github.com/rust-lang/mdBook/pull/2905)
|
||||
- Headers and `dt` tags are no longer modified if the tag is manually written HTML.
|
||||
[#2913](https://github.com/rust-lang/mdBook/pull/2913)
|
||||
- Fixed print page links for internal links to non-chapters.
|
||||
[#2914](https://github.com/rust-lang/mdBook/pull/2914)
|
||||
- Better handling for unbalanced HTML tags.
|
||||
[#2924](https://github.com/rust-lang/mdBook/pull/2924)
|
||||
- Handle unclosed HTML tags inside a markdown element.
|
||||
[#2927](https://github.com/rust-lang/mdBook/pull/2927)
|
||||
- Fixed missing font-awesome icons in the guide.
|
||||
[#2926](https://github.com/rust-lang/mdBook/pull/2926)
|
||||
- Hide the sidebar resize indicator when JS isn't available.
|
||||
[#2923](https://github.com/rust-lang/mdBook/pull/2923)
|
||||
|
||||
## mdBook 0.5.0-beta.1
|
||||
[v0.5.0-alpha.1...v0.5.0-beta.1](https://github.com/rust-lang/mdBook/compare/v0.5.0-alpha.1...v0.5.0-beta.1)
|
||||
|
||||
|
||||
96
Cargo.lock
generated
96
Cargo.lock
generated
@@ -4,9 +4,9 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -194,9 +194,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.12.0"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
|
||||
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
@@ -217,18 +217,18 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.50"
|
||||
version = "4.5.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623"
|
||||
checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.50"
|
||||
version = "4.5.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0"
|
||||
checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -239,9 +239,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.59"
|
||||
version = "4.5.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2348487adcd4631696ced64ccdb40d38ac4d31cae7f2eec8817fcea1b9d1c43c"
|
||||
checksum = "8e602857739c5a4291dfa33b5a298aeac9006185229a700e5810a3ef7272d971"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
@@ -332,7 +332,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -343,7 +343,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -370,7 +370,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -380,7 +380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -514,7 +514,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -585,9 +585,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.17"
|
||||
version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eab69130804d941f8075cfd713bf8848a2c3b3f201a9457a11e6f87e1ab62305"
|
||||
checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
@@ -765,9 +765,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.24"
|
||||
version = "0.4.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81776e6f9464432afcc28d03e52eb101c93b6f0566f52aef2427663e700f0403"
|
||||
checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"globset",
|
||||
@@ -811,9 +811,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
@@ -936,7 +936,7 @@ checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -956,7 +956,7 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
||||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -996,7 +996,7 @@ version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-core"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"regex",
|
||||
@@ -1009,7 +1009,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-driver"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
@@ -1031,7 +1031,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-html"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ego-tree",
|
||||
@@ -1056,7 +1056,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-markdown"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"pulldown-cmark",
|
||||
"regex",
|
||||
@@ -1065,7 +1065,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-preprocessor"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mdbook-core",
|
||||
@@ -1085,7 +1085,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-renderer"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mdbook-core",
|
||||
@@ -1095,7 +1095,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-summary"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mdbook-core",
|
||||
@@ -1228,9 +1228,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.1"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "opener"
|
||||
@@ -1308,7 +1308,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1426,9 +1426,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1650,7 +1650,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1767,9 +1767,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "snapbox"
|
||||
version = "0.6.22"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "805d09a74586d9b17061e5be6ee5f8cc37e5982c349948114ffc5f68093fe5ec"
|
||||
checksum = "96fa1ce81be900d083b30ec2d481e6658c2acfaa2cfc7be45ccc2cc1b820edb3"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -1789,9 +1789,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "snapbox-macros"
|
||||
version = "0.3.10"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16569f53ca23a41bb6f62e0a5084aa1661f4814a67fa33696a79073e03a664af"
|
||||
checksum = "3b750c344002d7cc69afb9da00ebd9b5c0f8ac2eb7d115d9d45d5b5f47718d74"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
]
|
||||
@@ -1850,9 +1850,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.107"
|
||||
version = "2.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b"
|
||||
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1916,7 +1916,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1951,7 +1951,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2098,7 +2098,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2177,9 +2177,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.19"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
@@ -2396,5 +2396,5 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.107",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
24
Cargo.toml
24
Cargo.toml
@@ -27,8 +27,8 @@ rust-version = "1.88.0" # Keep in sync with installation.md and .github/workflow
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0.100"
|
||||
axum = "0.8.6"
|
||||
clap = { version = "4.5.50", features = ["cargo", "wrap_help"] }
|
||||
clap_complete = "4.5.59"
|
||||
clap = { version = "4.5.51", features = ["cargo", "wrap_help"] }
|
||||
clap_complete = "4.5.60"
|
||||
ego-tree = "0.10.0"
|
||||
elasticlunr-rs = "3.0.2"
|
||||
font-awesome-as-a-crate = "0.3.0"
|
||||
@@ -38,14 +38,14 @@ handlebars = "6.3.2"
|
||||
hex = "0.4.3"
|
||||
html5ever = "0.35.0"
|
||||
indexmap = "2.12.0"
|
||||
ignore = "0.4.24"
|
||||
mdbook-core = { path = "crates/mdbook-core", version = "0.5.0-beta.1" }
|
||||
mdbook-driver = { path = "crates/mdbook-driver", version = "0.5.0-beta.1" }
|
||||
mdbook-html = { path = "crates/mdbook-html", version = "0.5.0-beta.1" }
|
||||
mdbook-markdown = { path = "crates/mdbook-markdown", version = "0.5.0-beta.1" }
|
||||
mdbook-preprocessor = { path = "crates/mdbook-preprocessor", version = "0.5.0-beta.1" }
|
||||
mdbook-renderer = { path = "crates/mdbook-renderer", version = "0.5.0-beta.1" }
|
||||
mdbook-summary = { path = "crates/mdbook-summary", version = "0.5.0-beta.1" }
|
||||
ignore = "0.4.25"
|
||||
mdbook-core = { path = "crates/mdbook-core", version = "0.5.0-beta.2" }
|
||||
mdbook-driver = { path = "crates/mdbook-driver", version = "0.5.0-beta.2" }
|
||||
mdbook-html = { path = "crates/mdbook-html", version = "0.5.0-beta.2" }
|
||||
mdbook-markdown = { path = "crates/mdbook-markdown", version = "0.5.0-beta.2" }
|
||||
mdbook-preprocessor = { path = "crates/mdbook-preprocessor", version = "0.5.0-beta.2" }
|
||||
mdbook-renderer = { path = "crates/mdbook-renderer", version = "0.5.0-beta.2" }
|
||||
mdbook-summary = { path = "crates/mdbook-summary", version = "0.5.0-beta.2" }
|
||||
memchr = "2.7.6"
|
||||
notify = "8.2.0"
|
||||
notify-debouncer-mini = "0.7.0"
|
||||
@@ -59,7 +59,7 @@ serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.145"
|
||||
sha2 = "0.10.9"
|
||||
shlex = "1.3.0"
|
||||
snapbox = "0.6.22"
|
||||
snapbox = "0.6.23"
|
||||
tempfile = "3.23.0"
|
||||
tokio = "1.48.0"
|
||||
toml = "0.9.8"
|
||||
@@ -71,7 +71,7 @@ walkdir = "2.5.0"
|
||||
|
||||
[package]
|
||||
name = "mdbook"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
authors = [
|
||||
"Mathieu David <mathieudavid@mathieudavid.org>",
|
||||
"Michael-F-Bryan <michaelfbryan@gmail.com>",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-core"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
description = "The base support library for mdbook, intended for internal use only"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
@@ -209,6 +209,23 @@ impl Config {
|
||||
.transpose()
|
||||
}
|
||||
|
||||
/// Returns whether the config contains the given dotted key name.
|
||||
///
|
||||
/// The key can have dotted indices to access nested items (e.g.
|
||||
/// `preprocessor.foo.bar` will check if that key is set in the config).
|
||||
///
|
||||
/// This can only access the `output` and `preprocessor` tables.
|
||||
pub fn contains_key(&self, name: &str) -> bool {
|
||||
if let Some(key) = name.strip_prefix("output.") {
|
||||
self.output.read(key)
|
||||
} else if let Some(key) = name.strip_prefix("preprocessor.") {
|
||||
self.preprocessor.read(key)
|
||||
} else {
|
||||
panic!("invalid key `{name}`");
|
||||
}
|
||||
.is_some()
|
||||
}
|
||||
|
||||
/// Returns the configuration for all preprocessors.
|
||||
pub fn preprocessors<'de, T: Deserialize<'de>>(&self) -> Result<BTreeMap<String, T>> {
|
||||
self.preprocessor
|
||||
@@ -1161,4 +1178,24 @@ mod tests {
|
||||
"Failed to deserialize `preprocessor.foo.x`"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_key() {
|
||||
let src = r#"
|
||||
[preprocessor.foo]
|
||||
x = 123
|
||||
[output.foo.sub]
|
||||
y = 'x'
|
||||
"#;
|
||||
let cfg = Config::from_str(src).unwrap();
|
||||
assert!(cfg.contains_key("preprocessor.foo"));
|
||||
assert!(cfg.contains_key("preprocessor.foo.x"));
|
||||
assert!(!cfg.contains_key("preprocessor.bar"));
|
||||
assert!(!cfg.contains_key("preprocessor.foo.y"));
|
||||
assert!(cfg.contains_key("output.foo"));
|
||||
assert!(cfg.contains_key("output.foo.sub"));
|
||||
assert!(cfg.contains_key("output.foo.sub.y"));
|
||||
assert!(!cfg.contains_key("output.bar"));
|
||||
assert!(!cfg.contains_key("output.foo.sub.z"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-driver"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
description = "High-level library for running mdBook"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-html"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
description = "mdBook HTML renderer"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
@@ -534,6 +534,11 @@ html:not(.sidebar-resizing) .sidebar {
|
||||
cursor: col-resize;
|
||||
width: calc(var(--sidebar-resize-indicator-width) - var(--sidebar-resize-indicator-space));
|
||||
}
|
||||
|
||||
html:not(.js) .sidebar-resize-handle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* sidebar-hidden */
|
||||
#mdbook-sidebar-toggle-anchor:not(:checked) ~ .sidebar {
|
||||
transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width)));
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::html::{ChapterTree, Element, serialize};
|
||||
use crate::utils::{ToUrlPath, id_from_content, normalize_path, unique_id};
|
||||
use mdbook_core::static_regex;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::{Component, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Takes all the chapter trees, modifies them to be suitable to render for
|
||||
/// the print page, and returns an string of all the chapters rendered to a
|
||||
@@ -166,13 +166,9 @@ fn rewrite_links(
|
||||
{
|
||||
lookup_key.pop();
|
||||
lookup_key.push(href_path);
|
||||
let normalized = normalize_path(&lookup_key);
|
||||
// If this points outside of the book, don't modify it.
|
||||
let is_outside = matches!(
|
||||
normalized.components().next(),
|
||||
Some(Component::ParentDir | Component::RootDir)
|
||||
);
|
||||
if is_outside || !href_path.ends_with(".html") {
|
||||
lookup_key = normalize_path(&lookup_key);
|
||||
let is_a_chapter = path_to_root_id.contains_key(&lookup_key);
|
||||
if !is_a_chapter {
|
||||
// Make the link relative to the print page location.
|
||||
let mut rel_path = normalize_path(&base.join(href_path)).to_url_path();
|
||||
if let Some(anchor) = caps.name("anchor") {
|
||||
@@ -184,10 +180,7 @@ fn rewrite_links(
|
||||
}
|
||||
}
|
||||
|
||||
let lookup_key = normalize_path(&lookup_key);
|
||||
|
||||
let anchor = caps.name("anchor");
|
||||
let id = match anchor {
|
||||
let id = match caps.name("anchor") {
|
||||
Some(anchor_id) => {
|
||||
let anchor_id = anchor_id.as_str().to_string();
|
||||
match id_remap.get(&lookup_key) {
|
||||
@@ -204,7 +197,15 @@ fn rewrite_links(
|
||||
}
|
||||
None => match path_to_root_id.get(&lookup_key) {
|
||||
Some(id) => id.to_string(),
|
||||
None => continue,
|
||||
None => {
|
||||
// This should be guaranteed that either the
|
||||
// chapter itself is in the map (for anchor-only
|
||||
// links), or the is_a_chapter check above.
|
||||
panic!(
|
||||
"internal error: expected `{lookup_key:?}` to be in \
|
||||
root map (chapter path is `{html_path:?}`)"
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
el.insert_attr(attr, format!("#{id}").into());
|
||||
|
||||
@@ -19,7 +19,7 @@ use pulldown_cmark::{Alignment, CodeBlockKind, CowStr, Event, LinkType, Tag, Tag
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ops::Deref;
|
||||
use tracing::{error, warn};
|
||||
use tracing::{trace, warn};
|
||||
|
||||
/// Helper to create a [`QualName`].
|
||||
macro_rules! attr_qual_name {
|
||||
@@ -77,6 +77,8 @@ pub(crate) struct Element {
|
||||
pub(crate) attrs: Attributes,
|
||||
/// True if this tag ends with `/>`.
|
||||
pub(crate) self_closing: bool,
|
||||
/// True if this was raw HTML written in the markdown.
|
||||
pub(crate) was_raw: bool,
|
||||
}
|
||||
|
||||
impl Element {
|
||||
@@ -87,6 +89,7 @@ impl Element {
|
||||
name,
|
||||
attrs: Attributes::new(),
|
||||
self_closing: false,
|
||||
was_raw: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,25 +303,10 @@ where
|
||||
/// The main processing loop. Processes all events until the end.
|
||||
fn process_events(&mut self) {
|
||||
while let Some(event) = self.events.next() {
|
||||
trace!("event={event:?}");
|
||||
match event {
|
||||
Event::Start(tag) => self.start_tag(tag),
|
||||
Event::End(tag) => {
|
||||
self.pop();
|
||||
match tag {
|
||||
TagEnd::TableHead => {
|
||||
self.table_state = TableState::Body;
|
||||
self.push(Node::Element(Element::new("tbody")));
|
||||
}
|
||||
TagEnd::TableCell => {
|
||||
self.table_cell_index += 1;
|
||||
}
|
||||
TagEnd::Table => {
|
||||
// Pop tbody or thead
|
||||
self.pop();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Event::End(tag) => self.end_tag(tag),
|
||||
Event::Text(text) => {
|
||||
self.append_text(text.into_tendril());
|
||||
}
|
||||
@@ -374,6 +362,7 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
self.finish_stack();
|
||||
self.collect_footnote_defs();
|
||||
}
|
||||
|
||||
@@ -593,47 +582,59 @@ where
|
||||
self.push(Node::Element(element));
|
||||
}
|
||||
|
||||
fn end_tag(&mut self, tag: TagEnd) {
|
||||
// TODO: This should validate that the event stack is properly
|
||||
// synchronized with the tag stack. That, would likely require keeping
|
||||
// a parallel "expected end tag" with the tag stack, since mapping a
|
||||
// pulldown-cmark event tag to an HTML tag isn't always clear.
|
||||
//
|
||||
// Check for unclosed HTML tags when exiting a markdown event.
|
||||
while let Some(node_id) = self.tag_stack.last() {
|
||||
let node = self.tree.get(*node_id).unwrap().value();
|
||||
let Node::Element(el) = node else {
|
||||
break;
|
||||
};
|
||||
if !el.was_raw {
|
||||
break;
|
||||
}
|
||||
warn!(
|
||||
"unclosed HTML tag `<{}>` found in `{}` while exiting {tag:?}\n\
|
||||
HTML tags must be closed before exiting a markdown element.",
|
||||
el.name.local,
|
||||
self.options.path.display(),
|
||||
);
|
||||
self.pop();
|
||||
}
|
||||
self.pop();
|
||||
match tag {
|
||||
TagEnd::TableHead => {
|
||||
self.table_state = TableState::Body;
|
||||
self.push(Node::Element(Element::new("tbody")));
|
||||
}
|
||||
TagEnd::TableCell => {
|
||||
self.table_cell_index += 1;
|
||||
}
|
||||
TagEnd::Table => {
|
||||
// Pop tbody or thead
|
||||
self.pop();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given some HTML, parse it into [`Node`] elements and append them to
|
||||
/// the current node.
|
||||
fn append_html(&mut self, html: &str) {
|
||||
let tokens = parse_html(&html);
|
||||
let mut is_raw = false;
|
||||
for token in tokens {
|
||||
trace!("html token={token:?}");
|
||||
match token {
|
||||
Token::DoctypeToken(_) => {}
|
||||
Token::TagToken(tag) => {
|
||||
match tag.kind {
|
||||
TagKind::StartTag => {
|
||||
let is_closed = is_void_element(&tag.name) || tag.self_closing;
|
||||
is_raw = matches!(&*tag.name, "script" | "style");
|
||||
let name = QualName::new(None, html5ever::ns!(html), tag.name);
|
||||
let attrs = tag
|
||||
.attrs
|
||||
.into_iter()
|
||||
.map(|attr| (attr.name, attr.value))
|
||||
.collect();
|
||||
let mut el = Element {
|
||||
name,
|
||||
attrs,
|
||||
self_closing: tag.self_closing,
|
||||
};
|
||||
fix_html_link(&mut el);
|
||||
self.push(Node::Element(el));
|
||||
if is_closed {
|
||||
// No end element.
|
||||
self.pop();
|
||||
}
|
||||
}
|
||||
TagKind::EndTag => {
|
||||
is_raw = false;
|
||||
if self.is_html_tag_matching(&tag.name) {
|
||||
self.pop();
|
||||
}
|
||||
// else the stack is corrupt. I'm not really sure
|
||||
// what to do here...
|
||||
}
|
||||
}
|
||||
}
|
||||
Token::TagToken(tag) => match tag.kind {
|
||||
TagKind::StartTag => self.start_html_tag(tag, &mut is_raw),
|
||||
TagKind::EndTag => self.end_html_tag(tag, &mut is_raw),
|
||||
},
|
||||
Token::CommentToken(comment) => {
|
||||
self.append(Node::Comment(comment));
|
||||
}
|
||||
@@ -658,22 +659,59 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds an open HTML tag.
|
||||
fn start_html_tag(&mut self, tag: html5ever::tokenizer::Tag, is_raw: &mut bool) {
|
||||
let is_closed = is_void_element(&tag.name) || tag.self_closing;
|
||||
*is_raw = matches!(&*tag.name, "script" | "style");
|
||||
let name = QualName::new(None, html5ever::ns!(html), tag.name);
|
||||
let attrs = tag
|
||||
.attrs
|
||||
.into_iter()
|
||||
.map(|attr| (attr.name, attr.value))
|
||||
.collect();
|
||||
let mut el = Element {
|
||||
name,
|
||||
attrs,
|
||||
self_closing: tag.self_closing,
|
||||
was_raw: true,
|
||||
};
|
||||
fix_html_link(&mut el);
|
||||
self.push(Node::Element(el));
|
||||
if is_closed {
|
||||
// No end element.
|
||||
self.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/// Closes the given HTML tag.
|
||||
fn end_html_tag(&mut self, tag: html5ever::tokenizer::Tag, is_raw: &mut bool) {
|
||||
*is_raw = false;
|
||||
if self.is_html_tag_matching(&tag.name) {
|
||||
self.pop();
|
||||
} else {
|
||||
// The proper thing to do here is to recover. However, the HTML
|
||||
// parsing algorithm for that is quite complex. See
|
||||
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody
|
||||
// and the adoption agency algorithm.
|
||||
warn!(
|
||||
"unexpected HTML end tag `</{}>` found in `{}`\n\
|
||||
Check that the HTML tags are properly balanced.",
|
||||
tag.name,
|
||||
self.options.path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// This is used to verify HTML parsing keeps the stack of tags in sync.
|
||||
fn is_html_tag_matching(&self, name: &str) -> bool {
|
||||
let current = self.tree.get(self.current_node).unwrap().value();
|
||||
if let Node::Element(el) = current
|
||||
&& el.name() == name
|
||||
{
|
||||
return true;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
error!(
|
||||
"internal error: HTML tag stack out of sync.\n
|
||||
path: `{}`\n\
|
||||
current={current:?}\n\
|
||||
pop name: {name}",
|
||||
self.options.path.display()
|
||||
);
|
||||
false
|
||||
}
|
||||
|
||||
/// Eats all pulldown-cmark events until the next `End` matching the
|
||||
@@ -730,6 +768,40 @@ where
|
||||
output
|
||||
}
|
||||
|
||||
/// Deals with any unclosed elements on the stack.
|
||||
fn finish_stack(&mut self) {
|
||||
while let Some(node_id) = self.tag_stack.pop() {
|
||||
let node = self.tree.get(node_id).unwrap().value();
|
||||
match node {
|
||||
Node::Fragment => {}
|
||||
Node::Element(el) => {
|
||||
if el.was_raw {
|
||||
warn!(
|
||||
"unclosed HTML tag `<{}>` found in `{}`",
|
||||
el.name.local,
|
||||
self.options.path.display()
|
||||
);
|
||||
} else {
|
||||
panic!(
|
||||
"internal error: expected empty tag stack.\n
|
||||
path: `{}`\n\
|
||||
element={el:?}",
|
||||
self.options.path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
node => {
|
||||
panic!(
|
||||
"internal error: expected empty tag stack.\n
|
||||
path: `{}`\n\
|
||||
node={node:?}",
|
||||
self.options.path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends a new footnote reference.
|
||||
fn footnote_reference(&mut self, name: CowStr<'event>) {
|
||||
let len = self.footnote_numbers.len() + 1;
|
||||
@@ -840,6 +912,11 @@ where
|
||||
for heading in headings {
|
||||
let node = self.tree.get(heading).unwrap();
|
||||
let el = node.value().as_element().unwrap();
|
||||
// Don't modify tags if they were manually written HTML. The
|
||||
// user probably had some intent, and we don't want to mess it up.
|
||||
if el.was_raw {
|
||||
continue;
|
||||
}
|
||||
let href = if let Some(id) = el.attr("id") {
|
||||
format!("#{id}")
|
||||
} else {
|
||||
@@ -966,19 +1043,29 @@ where
|
||||
new_classes += class;
|
||||
}
|
||||
}
|
||||
if icon.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !icon.is_empty()
|
||||
&& let Ok(svg) = fa::svg(type_, &icon)
|
||||
{
|
||||
let mut span = Element::new("span");
|
||||
span.insert_attr("class", new_classes.into());
|
||||
for (name, value) in &i_el.attrs {
|
||||
if *name != attr_qual_name!("class") {
|
||||
span.attrs.insert(name.clone(), value.clone());
|
||||
match fa::svg(type_, &icon) {
|
||||
Ok(svg) => {
|
||||
let mut span = Element::new("span");
|
||||
span.insert_attr("class", new_classes.into());
|
||||
for (name, value) in &i_el.attrs {
|
||||
if *name != attr_qual_name!("class") {
|
||||
span.attrs.insert(name.clone(), value.clone());
|
||||
}
|
||||
}
|
||||
*node.value() = Node::Element(span);
|
||||
node.append(Node::RawData(svg.into()));
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"failed to find Font Awesome icon for icon `{icon}` \
|
||||
with type `{type_}` in `{}`: {e}",
|
||||
self.options.path.display()
|
||||
);
|
||||
}
|
||||
*node.value() = Node::Element(span);
|
||||
node.append(Node::RawData(svg.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,12 +74,22 @@ pub(crate) fn unique_id(id: &str, used: &mut HashSet<String>) -> String {
|
||||
|
||||
/// Generates an HTML id from the given text.
|
||||
pub(crate) fn id_from_content(content: &str) -> String {
|
||||
// This is intended to be close to how header ID generation is done in
|
||||
// other sites and tools, but is not 100% the same. Not all sites and
|
||||
// tools use the same algorithm. See these for more information:
|
||||
//
|
||||
// - https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#section-links
|
||||
// - https://docs.gitlab.com/user/markdown/#heading-ids-and-links
|
||||
// - https://pandoc.org/MANUAL.html#extension-auto_identifiers
|
||||
// - https://kramdown.gettalong.org/converter/html#auto-ids
|
||||
// - https://docs.rs/comrak/latest/comrak/options/struct.Extension.html#structfield.header_ids
|
||||
content
|
||||
.trim()
|
||||
.to_lowercase()
|
||||
.chars()
|
||||
.filter_map(|ch| {
|
||||
if ch.is_alphanumeric() || ch == '_' || ch == '-' {
|
||||
Some(ch.to_ascii_lowercase())
|
||||
Some(ch)
|
||||
} else if ch.is_whitespace() {
|
||||
Some('-')
|
||||
} else {
|
||||
@@ -120,6 +130,6 @@ mod tests {
|
||||
assert_eq!(id_from_content("한국어"), "한국어");
|
||||
assert_eq!(id_from_content(""), "");
|
||||
assert_eq!(id_from_content("中文標題 CJK title"), "中文標題-cjk-title");
|
||||
assert_eq!(id_from_content("Über"), "Über");
|
||||
assert_eq!(id_from_content("Über"), "über");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-markdown"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
description = "Markdown processing used in mdBook"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-preprocessor"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
description = "Library to assist implementing an mdBook preprocessor"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-renderer"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
description = "Library to assist implementing an mdBook renderer"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook-summary"
|
||||
version = "0.5.0-beta.1"
|
||||
version = "0.5.0-beta.2"
|
||||
description = "Summary parser for mdBook"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
@@ -145,9 +145,9 @@ The following configuration options are available:
|
||||
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
|
||||
repository link. Defaults to `fab-github` which looks like <i class="fa fab-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>.
|
||||
If you are not using GitHub, another option to consider is `fa-code-fork` which looks like <i class="fas fa-code-fork"></i>.
|
||||
- **edit-url-template:** Edit url template, when provided shows a
|
||||
"Suggest an edit" button (which looks like <i class="fa fa-edit"></i>) for directly jumping to editing the currently
|
||||
"Suggest an edit" button (which looks like <i class="fas fa-pencil"></i>) for directly jumping to editing the currently
|
||||
viewed page. For e.g. GitHub projects set this to
|
||||
`https://github.com/<owner>/<repo>/edit/<branch>/{path}` or for
|
||||
Bitbucket projects set it to
|
||||
@@ -178,7 +178,7 @@ The following configuration options are available:
|
||||
### `[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.
|
||||
By default, mdBook will include an icon on the top right of the book (which looks like <i class="fas fa-print"></i>) that will print the book as a single page.
|
||||
|
||||
```toml
|
||||
[output.html.print]
|
||||
|
||||
@@ -73,7 +73,7 @@ nothidden():
|
||||
|
||||
## 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.
|
||||
Rust language code blocks will automatically get a play button (<i class="fas 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
|
||||
|
||||
@@ -42,7 +42,7 @@ 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 <kbd>/</kbd> or <kbd>S</kbd> key on the keyboard will open an input box for entering search terms.
|
||||
Pressing the search icon <i class="fas fa-magnifying-glass"></i> in the menu bar, or pressing the <kbd>/</kbd> or <kbd>S</kbd> 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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"browser-ui-test": "0.22.2",
|
||||
"browser-ui-test": "0.22.3",
|
||||
"eslint": "^9.34.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -157,6 +157,10 @@ fn definition_lists() {
|
||||
.check_main_file(
|
||||
"book/definition_lists.html",
|
||||
file!["markdown/definition_lists/expected_disabled/definition_lists.html"],
|
||||
)
|
||||
.check_main_file(
|
||||
"book/html_definition_lists.html",
|
||||
file!["markdown/definition_lists/expected_disabled/html_definition_lists.html"],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,4 +62,8 @@ const x = 'some *text* inside';
|
||||
</style>
|
||||
<style media="(width < 500px)">
|
||||
.bar { background-color: green }
|
||||
</style>
|
||||
</style>
|
||||
<h2 id="manual-headers"><a class="header" href="#manual-headers">Manual headers</a></h2>
|
||||
<h2 id="my header"><a href="#foo">My Header</a></h2>
|
||||
|
||||
<h3>Another header</h3>
|
||||
@@ -92,3 +92,9 @@ const x = 'some *text* inside';
|
||||
<style media="(width < 500px)">
|
||||
.bar { background-color: green }
|
||||
</style>
|
||||
|
||||
## Manual headers
|
||||
|
||||
<h2 id="my header"><a href="#foo">My Header</a></h2>
|
||||
|
||||
<h3>Another header</h3>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<h1 id="html-definition-lists"><a class="header" href="#html-definition-lists">HTML definition lists</a></h1>
|
||||
<p>Test for definition lists manually written in HTML.</p>
|
||||
<dl>
|
||||
|
||||
<dt>Some tag</dt>
|
||||
|
||||
|
||||
<dd>Some defintion</dd>
|
||||
|
||||
|
||||
<dt class="myclass" id="myid"><a class="option-anchor" href="#foo">Another definition</a></dt>
|
||||
|
||||
|
||||
<dd class="def-class">A definition.</dd>
|
||||
|
||||
</dl>
|
||||
@@ -0,0 +1,16 @@
|
||||
<h1 id="html-definition-lists"><a class="header" href="#html-definition-lists">HTML definition lists</a></h1>
|
||||
<p>Test for definition lists manually written in HTML.</p>
|
||||
<dl>
|
||||
|
||||
<dt>Some tag</dt>
|
||||
|
||||
|
||||
<dd>Some defintion</dd>
|
||||
|
||||
|
||||
<dt class="myclass" id="myid"><a class="option-anchor" href="#foo">Another definition</a></dt>
|
||||
|
||||
|
||||
<dd class="def-class">A definition.</dd>
|
||||
|
||||
</dl>
|
||||
@@ -1,3 +1,4 @@
|
||||
# Summary
|
||||
|
||||
- [Definition lists](./definition_lists.md)
|
||||
- [HTML definition lists](./html_definition_lists.md)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# HTML definition lists
|
||||
|
||||
Test for definition lists manually written in HTML.
|
||||
|
||||
<dl>
|
||||
<dt>Some tag</dt>
|
||||
<dd>Some defintion</dd>
|
||||
<dt class="myclass" id="myid"><a class="option-anchor" href="#foo">Another definition</a></dt>
|
||||
<dd class="def-class">A definition.</dd>
|
||||
</dl>
|
||||
@@ -9,6 +9,10 @@ both the print page and the non-print page.</p>
|
||||
<p>A <a href="#some-section">fragment link</a> should work.</p>
|
||||
<p>Link <a href="../std/foo/bar.html">outside</a>.</p>
|
||||
<p>Link <a href="../std/foo/bar.html#panic">outside with anchor</a>.</p>
|
||||
<p>Link <a href="first/alpha/beta.html">inside but doesn’t exist</a>.
|
||||
Link <a href="first/alpha/beta.html#anchor">inside but doesn’t exist with anchor</a>.
|
||||
Link <a href="first/alpha/gamma.html">inside to html</a>.
|
||||
Link <a href="first/alpha/gamma.html#anchor">inside to html with anchor</a>.</p>
|
||||
<p><img src="images/picture.png" alt="Some image"></p>
|
||||
<p><a href="#first-nested">HTML Link</a></p>
|
||||
<img src="images/picture.png" alt="raw html">
|
||||
|
||||
@@ -11,6 +11,11 @@ Link [outside](../../std/foo/bar.html).
|
||||
|
||||
Link [outside with anchor](../../std/foo/bar.html#panic).
|
||||
|
||||
Link [inside but doesn't exist](../first/alpha/beta.md).
|
||||
Link [inside but doesn't exist with anchor](../first/alpha/beta.md#anchor).
|
||||
Link [inside to html](../first/alpha/gamma.html).
|
||||
Link [inside to html with anchor](../first/alpha/gamma.html#anchor).
|
||||
|
||||

|
||||
|
||||
<a href="../first/nested.md">HTML Link</a>
|
||||
|
||||
@@ -47,7 +47,17 @@ fn first_chapter_is_copied_as_index_even_if_not_first_elem() {
|
||||
// Fontawesome `<i>` tag support.
|
||||
#[test]
|
||||
fn fontawesome() {
|
||||
BookTest::from_dir("rendering/fontawesome").check_all_main_files();
|
||||
BookTest::from_dir("rendering/fontawesome")
|
||||
.run("build", |cmd| {
|
||||
cmd.expect_stderr(str![[r#"
|
||||
INFO Book building has started
|
||||
INFO Running the html backend
|
||||
WARN failed to find Font Awesome icon for icon `does-not-exist` with type `regular` in `fa.md`: Invalid Font Awesome icon name: visit https://fontawesome.com/icons?d=gallery&m=free to see valid names
|
||||
INFO HTML book written to `[ROOT]/book`
|
||||
|
||||
"#]]);
|
||||
})
|
||||
.check_all_main_files();
|
||||
}
|
||||
|
||||
// Tests the rendering when setting the default rust edition.
|
||||
@@ -229,3 +239,68 @@ fn html_blocks() {
|
||||
fn code_block_fenced_with_indent() {
|
||||
BookTest::from_dir("rendering/code_blocks_fenced_with_indent").check_all_main_files();
|
||||
}
|
||||
|
||||
// Unclosed HTML tags.
|
||||
//
|
||||
// Note that the HTML parsing algorithm is much more complicated than what
|
||||
// this is checking.
|
||||
#[test]
|
||||
fn unclosed_html_tags() {
|
||||
BookTest::init(|_| {})
|
||||
.change_file("src/chapter_1.md", "<div>x<span>foo<i>xyz")
|
||||
.run("build", |cmd| {
|
||||
cmd.expect_stderr(str![[r#"
|
||||
INFO Book building has started
|
||||
INFO Running the html backend
|
||||
WARN unclosed HTML tag `<i>` found in `chapter_1.md`
|
||||
WARN unclosed HTML tag `<span>` found in `chapter_1.md`
|
||||
WARN unclosed HTML tag `<div>` found in `chapter_1.md`
|
||||
INFO HTML book written to `[ROOT]/book`
|
||||
|
||||
"#]]);
|
||||
})
|
||||
.check_main_file(
|
||||
"book/chapter_1.html",
|
||||
str!["<div>x<span>foo<i>xyz</i></span></div>"],
|
||||
);
|
||||
}
|
||||
|
||||
// Test for HTML tags out of sync.
|
||||
#[test]
|
||||
fn unbalanced_html_tags() {
|
||||
BookTest::init(|_| {})
|
||||
.change_file("src/chapter_1.md", "<div>x<span>foo</div></span>")
|
||||
.run("build", |cmd| {
|
||||
cmd.expect_stderr(str![[r#"
|
||||
INFO Book building has started
|
||||
INFO Running the html backend
|
||||
WARN unexpected HTML end tag `</div>` found in `chapter_1.md`
|
||||
Check that the HTML tags are properly balanced.
|
||||
WARN unclosed HTML tag `<div>` found in `chapter_1.md`
|
||||
INFO HTML book written to `[ROOT]/book`
|
||||
|
||||
"#]]);
|
||||
})
|
||||
.check_main_file("book/chapter_1.html", str!["<div>x<span>foo</span></div>"]);
|
||||
}
|
||||
|
||||
// Test for bug with unbalanced HTML handling in the heading.
|
||||
#[test]
|
||||
fn heading_with_unbalanced_html() {
|
||||
BookTest::init(|_| {})
|
||||
.change_file("src/chapter_1.md", "### Option<T>")
|
||||
.run("build", |cmd| {
|
||||
cmd.expect_stderr(str![[r#"
|
||||
INFO Book building has started
|
||||
INFO Running the html backend
|
||||
WARN unclosed HTML tag `<t>` found in `chapter_1.md` while exiting Heading(H3)
|
||||
HTML tags must be closed before exiting a markdown element.
|
||||
INFO HTML book written to `[ROOT]/book`
|
||||
|
||||
"#]]);
|
||||
})
|
||||
.check_main_file(
|
||||
"book/chapter_1.html",
|
||||
str![[r##"<h3 id="option"><a class="header" href="#option">Option<t></t></a></h3>"##]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
<p><span class="fa-svg extra-class" id="example1"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M47.6 300.4L228.3 469.1c7.5 7 17.4 10.9 27.7 10.9s20.2-3.9 27.7-10.9L464.4 300.4c30.4-28.3 47.6-68 47.6-109.5v-5.8c0-69.9-50.5-129.5-119.4-141C347 36.5 300.6 51.4 268 84L256 96 244 84c-32.6-32.6-79-47.5-124.6-39.9C50.5 55.6 0 115.2 0 185.1v5.8c0 41.5 17.2 81.2 47.6 109.5z"/></svg></span></p>
|
||||
<p><span class="fa-svg"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M272 304h-96C78.8 304 0 382.8 0 480c0 17.67 14.33 32 32 32h384c17.67 0 32-14.33 32-32C448 382.8 369.2 304 272 304zM48.99 464C56.89 400.9 110.8 352 176 352h96c65.16 0 119.1 48.95 127 112H48.99zM224 256c70.69 0 128-57.31 128-128c0-70.69-57.31-128-128-128S96 57.31 96 128C96 198.7 153.3 256 224 256zM224 48c44.11 0 80 35.89 80 80c0 44.11-35.89 80-80 80S144 172.1 144 128C144 83.89 179.9 48 224 48z"/></svg></span></p>
|
||||
<p><span class="fa-svg"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M448 48V384C385 407 366 416 329 416C266 416 242 384 179 384C159 384 143 388 128 392V328C143 324 159 320 179 320C242 320 266 352 329 352C349 352 364 349 384 343V135C364 141 349 144 329 144C266 144 242 112 179 112C128 112 104 133 64 141V448C64 466 50 480 32 480S0 466 0 448V64C0 46 14 32 32 32S64 46 64 64V77C104 69 128 48 179 48C242 48 266 80 329 80C366 80 385 71 448 48Z"/></svg></span></p>
|
||||
<p><i class="fas fa-heart">Some text here.</i></p>
|
||||
<p><i class="fas fa-heart">Text prevents translation.</i></p>
|
||||
<p><i class="fa fa-does-not-exist"></i></p>
|
||||
@@ -6,4 +6,6 @@
|
||||
|
||||
<i class="fab fa-font-awesome"></i>
|
||||
|
||||
<i class="fas fa-heart">Some text here.</i>
|
||||
<i class="fas fa-heart">Text prevents translation.</i>
|
||||
|
||||
<i class="fa fa-does-not-exist"></i>
|
||||
|
||||
Reference in New Issue
Block a user