Compare commits

...

53 Commits

Author SHA1 Message Date
carlocorradini
9730cd0aaa fix: additional-css UNIX style path normalization 2023-12-18 12:20:54 +00:00
Tom Milligan
dc219f755d Merge pull request #155 from tommilligan/prep-1.14.0
chore: prep v0.14.0 release
2023-11-16 01:04:35 +01:00
Tom Milligan
a2524f890b chore: prep v0.14.0 release 2023-11-16 00:04:19 +00:00
Sky
c3207e4d16 Custom ids (#144)
* Custom ids

- You can now set custom CSS ids for admonishment blocks with the `id` field.
- You can now customize the default CSS id prefix (default is `"admonition-"`).

Co-authored-by: Tom Milligan <tom.milligan@uipath.com>
2023-11-15 22:34:21 +00:00
Tom Milligan
ab63c90231 Merge pull request #154 from joshka/main
fix: use correct case for TL;DR and FAQ
2023-11-15 22:43:20 +01:00
Josh McKinney
d5bdde1f5c fix: use correct case for TL;DR and FAQ
Fixes: #153
2023-11-15 13:24:56 -08:00
Tom Milligan
52ca8fc831 Merge pull request #152 from tommilligan/print-pdf-render
fix: better rendering for pdf/print view
2023-11-13 17:09:38 +01:00
Tom Milligan
e1ea411e9a fix: better rendering for pdf/print view 2023-11-13 15:46:58 +00:00
Tom Milligan
31d5a27a6d Merge pull request #143 from tommilligan/prep-1.13.1
chore: prep 1.13.1 release
2023-10-17 09:59:48 +01:00
Tom Milligan
0f0e02702c chore: prep 1.13.1 release 2023-10-17 09:37:32 +01:00
Tom Milligan
7235d5f349 Merge pull request #142 from tommilligan/rust-version
ci: add msrv to cargo toml, update mdbook version
2023-10-15 13:26:11 +01:00
Tom Milligan
0304995dbb ci: add msrv to cargo toml, update mdbook version 2023-10-15 13:11:01 +01:00
Tom Milligan
197d9cd059 Merge pull request #140 from tommilligan/prep-1.13.0
chore: prep v0.13.0 release
2023-10-06 15:21:27 +01:00
Tom Milligan
04ff932f1f chore: prep v0.13.0 release 2023-10-06 14:52:13 +01:00
Tom Milligan
1526a5d814 Merge pull request #139 from tommilligan/pr-137
prefix directive class names with 'admonish-'
2023-10-06 14:16:45 +01:00
phoenixr-codes
eb21495797 prefix directive class names with 'admonish-'
This change exists to prevent conflicts with the newly added 'warning' class by mdBook. See also: https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#added
2023-10-06 13:43:54 +01:00
Tom Milligan
ebe6f7815c Merge pull request #138 from tommilligan/ci-prettier
ci: lint styles with prettier
2023-10-06 13:32:48 +01:00
Tom Milligan
c0c953c865 ci: lint styles with prettier 2023-10-06 13:15:45 +01:00
Tom Milligan
0fa34a66a0 Merge pull request #136 from tommilligan/deps-20231001
chore: deps 20231001
2023-10-02 08:50:53 +01:00
dependabot[bot]
dfc12c3652 chore(deps): bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 08:37:26 +01:00
dependabot[bot]
108edfffc5 chore(deps): bump JamesIves/github-pages-deploy-action
Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.4.1 to 4.4.3.
- [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases)
- [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.4.1...v4.4.3)

---
updated-dependencies:
- dependency-name: JamesIves/github-pages-deploy-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 08:37:26 +01:00
Tom Milligan
38f1933e8f chore: bump rust deps 2023-10-02 08:37:26 +01:00
Tom Milligan
a839038263 Merge pull request #128 from tommilligan/bug-127
markdown: fix panic when searching for indent
2023-09-19 13:02:43 +01:00
Tom Milligan
8501c812d9 chore: prep v1.12.1 2023-09-19 12:21:42 +01:00
Tom Milligan
933432afb2 markdown: fix panic when searching for indent 2023-09-19 12:21:42 +01:00
Tom Milligan
496e8f7c6d Merge pull request #126 from tommilligan/prep-1.12.0
chore: prep v1.12.0 release
2023-09-16 11:22:08 +01:00
Tom Milligan
1877fd1731 chore: upgrade internal dependencies 2023-09-16 10:58:17 +01:00
Tom Milligan
20286b3fae chore: prep v1.12.0 release 2023-09-16 10:55:53 +01:00
Tom Milligan
8e68cf919f Merge pull request #124 from tommilligan/bug-123
feat: support admonitions inside list items
2023-09-10 00:02:58 +01:00
Tom Milligan
02640dab1f feat: support admonitions inside list items 2023-09-09 23:44:58 +01:00
Tom Milligan
771e9c9fd8 Merge pull request #125 from tommilligan/prep-v1.11.1
chore: prepare v1.11.1 release
2023-09-09 23:43:48 +01:00
Tom Milligan
cce9343c47 chore: prepare v1.11.1 release 2023-09-09 23:32:10 +01:00
Tom Milligan
20b158966b Revert "chore: bump lockfile"
This reverts commit 39edc4d92a.
2023-09-09 23:24:26 +01:00
Tom Milligan
491f9cf341 Merge pull request #122 from tommilligan/fix-docs
docs: fix mdbook-toc build failure
2023-09-09 09:12:27 +01:00
Tom Milligan
6deaf1ea2b docs: fix mdbook-toc build failure 2023-09-09 09:12:07 +01:00
Tom Milligan
041e5a566f Merge pull request #121 from tommilligan/update-deps
chore: prep v1.11.0 release
2023-09-09 09:06:44 +01:00
Tom Milligan
99b5a235cf chore: prep v1.11.0 release 2023-09-09 09:05:49 +01:00
Tom Milligan
39edc4d92a chore: bump lockfile 2023-09-09 08:58:32 +01:00
Tom Milligan
7773213093 Merge pull request #118 from eitsupi/eitsupi-patch-1
ci(deploy): Use Ubuntu 20.04 for building linux gnu target binaries
2023-09-09 08:49:24 +01:00
eitsupi
e888fcd021 Use Ubuntu 20.04 for building linux gnu target binaries 2023-09-09 08:48:24 +01:00
Tom Milligan
95dc7582ad Merge pull request #119 from eitsupi/add-aarch64-musl
ci(deploy): deploy aarch64-unknown-linux-musl
2023-09-09 08:43:59 +01:00
eitsupi
b658eb6049 strip via Cargo 2023-09-09 08:31:25 +01:00
eitsupi
623291625a deploy aarch64-unknown-linux-musl 2023-09-09 08:31:25 +01:00
Tom Milligan
4dad5a86c8 chore: fix clippy 2023-09-09 08:28:21 +01:00
Tom Milligan
7e774f4655 chore: prep v1.10.2 release (#116) 2023-08-07 18:58:32 +01:00
Tom Milligan
823cefbcbc fix: unlink mdbook internal toml dependency from mdbook-admonish (#115)
* chore: bump dependencies

* fix: unlink mdbook internal toml dependency from mdbook-admonish
2023-08-07 18:55:02 +01:00
Tom Milligan
a6a2941821 chore: prep v1.10.1 release (#113) 2023-07-28 18:49:46 +01:00
Uriel
faf99a1b76 only modify summary with the admonition-title class (#112)
* only modify `summary` with the `admonition-title` class

* regenerate assets, update snapshot test, fix themes

---------

Co-authored-by: Tom Milligan <tom.milligan@uipath.com>
2023-07-28 18:44:05 +01:00
Jonas
afdc2b03d0 Improvement of links (#111) 2023-07-26 12:19:01 +01:00
Tom Milligan
e55df3e60b Merge pull request #110 from tommilligan/prep-1.10.0
chore: prep v1.10.0 release
2023-07-23 19:51:53 +01:00
Tom Milligan
f3d49b93de chore: prep v1.10.0 release 2023-07-23 19:47:37 +01:00
Tom Milligan
92caf95b34 chore: add notes for future v2 release 2023-07-23 19:38:24 +01:00
Tom Milligan
0742c6c1e8 Merge pull request #109 from tommilligan/run-doctests
feat: add support for test renderer, running doctests
2023-07-23 19:33:20 +01:00
37 changed files with 1825 additions and 1229 deletions

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Cache build files
uses: actions/cache@v3
with:
@@ -35,7 +35,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Cache build files
uses: actions/cache@v3
with:
@@ -51,6 +51,12 @@ jobs:
with:
toolchain: stable
override: true
- name: Install node toolchain
uses: actions/setup-node@v3
with:
node-version: "20"
cache: "yarn"
cache-dependency-path: compile_assets/yarn.lock
- name: Install additional test dependencies
env:
CARGO_TARGET_DIR: cargo_target
@@ -66,20 +72,24 @@ jobs:
matrix:
os:
- ubuntu-20.04
# - windows-2019
rust:
- stable
- beta
- 1.66.0
experimental:
- false
# Run a canary test on nightly that's allowed to fail
include:
# Run a canary test on nightly that's allowed to fail
- os: ubuntu-20.04
rust: nightly
experimental: true
# Don't bother retesting stable linux, we did it in the comprehensive test
# Test only stable on Windows, presume we'd get same result on other
# versions as Linux
- os: windows-2022
rust: stable
experimental: false
exclude:
# Don't bother retesting stable linux, we did it in the comprehensive test
- os: ubuntu-20.04
rust: stable
experimental: false
@@ -87,7 +97,7 @@ jobs:
continue-on-error: ${{ matrix.experimental }}
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Cache build files
uses: actions/cache@v3
with:

View File

@@ -16,14 +16,16 @@ jobs:
strategy:
fail-fast: false
matrix:
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- x86_64-apple-darwin
- x86_64-pc-windows-msvc
include:
- target: x86_64-unknown-linux-gnu
- target: aarch64-unknown-linux-musl
os: ubuntu-latest
name: aarch64-unknown-linux-musl.tar.gz
- target: x86_64-unknown-linux-gnu
# Deliberately pinned to the same version `mdbook` uses to build
# binaries, so we use the same glibc version
#
# ref: https://github.com/rust-lang/mdBook/pull/1955
os: ubuntu-20.04
name: x86_64-unknown-linux-gnu.tar.gz
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
@@ -37,7 +39,7 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: Setup | Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
# Cache files between builds
- name: Setup | Cache Cargo
@@ -56,17 +58,19 @@ jobs:
profile: minimal
target: ${{ matrix.target }}
- name: Setup | musl tools
if: matrix.target == 'x86_64-unknown-linux-musl'
run: sudo apt install -y musl-tools
- name: Setup | cross
if: endsWith(matrix.target, '-unknown-linux-musl')
uses: taiki-e/install-action@v2
with:
tool: cross
- name: Build | Build
if: matrix.target != 'x86_64-unknown-linux-musl'
if: ${{ !endsWith(matrix.target, '-unknown-linux-musl') }}
run: cargo build --release --target ${{ matrix.target }}
- name: Build | Build (musl)
if: matrix.target == 'x86_64-unknown-linux-musl'
run: cargo build --release --target ${{ matrix.target }}
if: endsWith(matrix.target, '-unknown-linux-musl')
run: cross build --release --target ${{ matrix.target }}
- name: Post Setup | Extract tag name
shell: bash
@@ -78,7 +82,6 @@ jobs:
run: |
mkdir target/stage
cd target/${{ matrix.target }}/release
strip ${{ env.CRATE_NAME }}.exe
7z a ../../stage/${{ env.CRATE_NAME }}-${{ steps.extract_tag.outputs.tag }}-${{ matrix.name }} ${{ env.CRATE_NAME }}.exe
cd -
- name: Post Setup | Prepare artifacts [-nix]
@@ -86,7 +89,6 @@ jobs:
run: |
mkdir target/stage
cd target/${{ matrix.target }}/release
strip ${{ env.CRATE_NAME }}
tar czvf ../../stage/${{ env.CRATE_NAME }}-${{ steps.extract_tag.outputs.tag }}-${{ matrix.name }} ${{ env.CRATE_NAME }}
cd -
- name: Post Setup | Upload artifacts
@@ -102,7 +104,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Setup | Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -131,7 +133,7 @@ jobs:
needs: github_release
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: |

View File

@@ -13,7 +13,7 @@ jobs:
publish:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: |
@@ -36,7 +36,7 @@ jobs:
- name: Build book
run: ./scripts/build-book
- name: Push docs
uses: JamesIves/github-pages-deploy-action@v4.4.1
uses: JamesIves/github-pages-deploy-action@v4.4.3
with:
branch: gh-pages
folder: book/book

View File

@@ -2,11 +2,115 @@
## Unreleased
### Changed
- `additional-css` _UNIX_ style path normalization ([#161](https://github.com/tommilligan/mdbook-admonish/issues/161))
### Fixed
- Typo from _prereprocessor_ to _preprocessor_
## 1.14.0
### Changed
- Styles version updated to `3.0.1`. Run `mdbook-admonish install` to update.
### Added
- You can now set custom CSS ids for admonition blocks with the `id` field. Thanks to [@Sky9x](https://github.com/Sky9x) for contributing this feature! ([#144](https://github.com/tommilligan/mdbook-admonish/pull/144))
- You can also now customize the CSS id prefix with the config option `default.css_id_prefix`
### Fixed
- Improve rendering of blocks in print/PDF view. Thanks to [@csk111165](https://github.com/csk111165) for the report ([#152](https://github.com/tommilligan/mdbook-admonish/issues/152))
- Fix the default titles for `tldr` and `faq` directives looking bad. They now render as `TL;DR` and `FAQ` by default. Thanks [@joshka](https://github.com/joshka) for fixing this! ([#154](https://github.com/tommilligan/mdbook-admonish/pull/154))
## 1.13.1
### Changed
- Bumped internal `mdbook` version to `0.4.35` ([#142](https://github.com/tommilligan/mdbook-admonish/pull/142))
### Fixed
- Relaxed `clap` dependency to fix compilation error when using other `mdbook-*` plugins. Thanks to [@joshka](https://github.com/joshka) for the [report](https://github.com/tommilligan/mdbook-admonish/pull/141)! ([#142](https://github.com/tommilligan/mdbook-admonish/pull/142))
## 1.13.0
### Changed
- Required styles version is now `^3.0.0` (release `1.13.0`). Run `mdbook-admonish install` to update.
- Internal CSS classnames for directives are now prefixed with `admonish-`, so `warning` is now `admonish-warning`. This avoids a conflict with upstream classnames introduced in `mdbook 0.4.35`. Thanks to [@phoenixr-codes](https://github.com/phoenixr-codes) for the report and fix! ([#139](https://github.com/tommilligan/mdbook-admonish/pull/139))
### Fixed
- Some minor inconsistencies in SCSS (and downstream CSS) styles were fixed by adopting Prettier linting ([#138](https://github.com/tommilligan/mdbook-admonish/pull/138))
## 1.12.1
### Fixed
- Panic when searching for an indent in non-ASCII content. Thanks to [@CoralPink](https://github.com/CoralPink) for the report! ([#128](https://github.com/tommilligan/mdbook-admonish/pull/128))
## 1.12.0
### Added
- Admonitions are now supported when indented inside other elements, such as a list. Thanks to [@mattburgess](https://github.com/mattburgess) for the report! ([#124](https://github.com/tommilligan/mdbook-admonish/pull/124))
## 1.11.1
### Fixed
- Reverted internal dependency upgrades that unintentionally increased MSRV from 1.66.0 in 1.11.0
## 1.11.0 (yanked)
**Note:** This release has been yanked.
It unintentionally increased the MSRV from 1.66.0
### Changed
- `gnu` prebuilt binaries are now built on `ubuntu-20.04` to match `mdbook` binaries. Thanks to [@eitsupi](https://github.com/eitsupi) for the fix! ([#118](https://github.com/tommilligan/mdbook-admonish/pull/118))
### Added
- `aarch64-unknown-linux-musl` prebuilt binary now available ([#119](https://github.com/tommilligan/mdbook-admonish/pull/119))
## 1.10.2
### Fixed
- Fixed `cargo install mdbook-admonish` failing due to an internal dependency mismatch with `mdbook` ([#115](https://github.com/tommilligan/mdbook-admonish/pull/115))
## 1.10.1
### Fixed
- Only restyle `summary` elements generated by `mdbook-admonish`. Thanks to [@ImUrX](https://github.com/ImUrX) for the report and fix! ([#112](https://github.com/tommilligan/mdbook-admonish/pull/112))
## 1.10.0
### Changed
- MSRV (minimum supported rust version) is now 1.66.0 for mdbook v0.4.32 ([#109](https://github.com/tommilligan/mdbook-admonish/pull/109))
### Added
- Support `mdbook test` running doctests inside admonish blocks. Opt-in to this by setting `renderer.test.action_mode = "strip"` ([#109](https://github.com/tommilligan/mdbook-admonish/pull/109))
- Log a warning when an invalid admonish block is encountered ([#109](https://github.com/tommilligan/mdbook-admonish/pull/109))
### Fixed
- Document all `book.toml` configuration options [in the reference](https://tommilligan.github.io/mdbook-admonish/reference.html), some of which were previously undocumened ([#109](https://github.com/tommilligan/mdbook-admonish/pull/109))
## 1.9.0
### Changed
- Styles updated to `^2.0.1`. Run `mdbook-admonish install` to update.
- Styles version updated to `2.0.1`. Run `mdbook-admonish install` to update.
- MSRV (minimum supported rust version) is now 1.64.0 for clap v4 ([#79](https://github.com/tommilligan/mdbook-admonish/pull/79))
- More verbose error messages for invalid TOML configurations ([#79](https://github.com/tommilligan/mdbook-admonish/pull/79))
@@ -109,7 +213,11 @@ This behaviour is [documented in the readme here](https://github.com/tommilligan
- Flattened indentation of generated HTML, otherwise it's styled as a markdown code block
- Fixed edge cases where the info string changes length when parsed, causing title/body to be incorrectly split
## 1.3.0
## 1.3.0 (yanked)
**Note:** This release has been yanked.
It unintentionally introduced a serious parsing bug.
### Added

840
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
[package]
name = "mdbook-admonish"
version = "1.9.0"
version = "1.14.0"
edition = "2021"
rust-version = "1.66.0"
authors = ["Tom Milligan <code@tommilligan.net>"]
description = "A preprocessor for mdbook to add Material Design admonishments."
@@ -17,27 +18,37 @@ name = "mdbook-admonish"
path = "src/bin/mdbook-admonish.rs"
required-features = ["cli"]
[profile.release]
strip = true
[lib]
name = "mdbook_admonish"
path = "src/lib.rs"
[dependencies]
anyhow = "1.0.65"
clap = { version = "4", default_features = false, features = ["std", "derive"], optional = true }
anyhow = "1.0.75"
# Note: clap 4.4 increases MSRV to 1.70.0 (2023-06-01)
# To use MSRV supported dependencies, install using the lockfile with
# `cargo install mdbook-admonish --locked`
clap = { version = "4.3", default_features = false, features = ["std", "derive"], optional = true }
env_logger = { version = "0.10", default_features = false, optional = true }
log = "0.4.17"
mdbook = "0.4.32"
once_cell = "1.15.0"
pulldown-cmark = "0.9.2"
regex = "1.6.0"
semver = "1.0.14"
serde = { version = "1.0.145", features = ["derive"] }
serde_json = "1.0.85"
toml = "0.7.3"
toml_edit = { version = "0.19.8", optional = true }
log = "0.4.20"
mdbook = "0.4.35"
once_cell = "1.18.0"
path-slash = "0.2.1"
pulldown-cmark = "0.9.3"
regex = "1.9.6"
semver = "1.0.19"
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.107"
# The version of toml that mdbook uses internally (and uses in it's public api)
# Only used for compatilibilty with the mdbook public api
toml_mdbook = { package = "toml", version = "0.5.11" }
toml = "0.8.1"
toml_edit = { version = "0.20.1", optional = true }
[dev-dependencies]
pretty_assertions = "1.3.0"
pretty_assertions = "1.4.0"
[features]
default = ["cli", "cli-install"]

View File

@@ -70,6 +70,9 @@ Install the tool:
```bash
cargo install mdbook-admonish
# If you get compilation/installation errors, try a locked installation
cargo install mdbook-admonish --locked
```
Then let `mdbook-admonish` add the required files and configuration:
@@ -101,6 +104,21 @@ Then, build your book as usual:
mdbook path/to/book
```
### Reproducible builds
For a reproducible build suitable for use in CI or scripts, please:
- Pin to a specific version
- Install with lockfile dependencies
- Always install the latest CSS assets
```bash
cargo install mdbook-admonish --vers "1.5.0" --locked
mdbook-admonish install path/to/your/book
```
The Minimum Supported Rust Version (MSRV) is documented in `Cargo.toml`, and noted in the `CHANGELOG.md`. We aims to support around six months of stable Rust.
### Updates
**Please note**, when updating your version of `mdbook-admonish`, updated styles will not be applied unless you rerun `mdbook-admonish install` to update the additional CSS files in your book.
@@ -117,12 +135,6 @@ ERROR:
If you want to update across minor versions without breakage, you should always run `mdbook-admonish install`.
Alternatively, pin to a specific version for a reproducible installation:
```bash
cargo install mdbook-admonish --vers "1.5.0" --locked
```
### Process included files
You can ensure that content inlined with `{{#include}}` is also processed by [setting the `after` option](https://rust-lang.github.io/mdBook/format/configuration/preprocessors.html#require-a-certain-order):
@@ -174,8 +186,6 @@ You must make the next `mdbook-admonish` crate version at least a **minor** vers
Github workflows are setup such that pushing a `vX.Y.Z` tag will trigger a release to be cut.
Once the release is created, copy and paste the relevant section of `CHANGELOG.md` manually to update the description.
## Thanks
This utility is heavily drawn from and inspired by other projects, namely:

View File

@@ -9,7 +9,7 @@ title = "The mdbook-admonish book"
[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "2.0.0" # do not edit: managed by `mdbook-admonish install`
assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install`
[preprocessor.toc]
command = "mdbook-toc"

View File

@@ -5,5 +5,5 @@ set -exuo pipefail
cd "$(dirname "$0")"/../..
if ! mdbook-toc --version; then
cargo install mdbook-toc --version 0.13.0 --force
cargo install mdbook-toc --version 0.14.1 --force
fi

View File

@@ -7,7 +7,7 @@
[![Latest version](https://img.shields.io/crates/v/mdbook-admonish.svg)](https://crates.io/crates/mdbook-admonish)
[![docs.rs](https://img.shields.io/docsrs/mdbook-admonish)](https://docs.rs/mdbook-admonish)
A preprocessor for [mdbook](https://github.com/rust-lang-nursery/mdBook) to add [Material Design](https://material.io/design) admonishments, based on the [mkdocs-material](https://squidfunk.github.io/mkdocs-material/reference/admonitions/) implementation.
A preprocessor for [mdbook](https://github.com/rust-lang/mdBook) to add [Material Design](https://material.io/design) admonishments, based on the [mkdocs-material](https://squidfunk.github.io/mkdocs-material/reference/admonitions/) implementation.
It turns this:
@@ -39,7 +39,7 @@ My example is the best!
My example is the best!
```
See the [list of directives](./reference.md) for a full list of supported admonitions. You'll find:
See the [list of directives](./reference.md#directives) for a full list of supported admonitions. You'll find:
- `info`
- `warning`
@@ -74,13 +74,13 @@ This block will error
This block will error
```
You can also configure the build to fail loudly, by setting `on_failure = "bail"` in `book.toml`. See the [configuration reference](./reference.md) for more details.
You can also configure the build to fail loudly, by setting `on_failure = "bail"` in `book.toml`. See the [configuration reference](./reference.md#booktoml-configuration) for more details.
### Additional Options
You can pass additional options to each block. The options are structured as TOML key-value pairs.
Note that some options can be passed globally, through the `default` section in `book.toml`. See the [configuration reference](./reference.md) for more details.
Note that some options can be passed globally, through the `default` section in `book.toml`. See the [configuration reference](./reference.md#booktoml-configuration) for more details.
#### Custom title
@@ -161,6 +161,23 @@ Will yield something like the following HTML, which you can then apply styles to
</div>
```
#### Custom CSS ID
If you want to customize the CSS `id` field, set `id="custom-id"`.
This will ignore [`default.css_id_prefix`](reference.md#default).
The default id is a normalized version of the admonishment's title,
prefixed with the `default.css_id_prefix`,
with an appended number if multiple blocks would have the same id.
Setting the `id` field will *ignore* all other ids and the duplicate counter.
````
```admonish info title="My Info" id="my-special-info"
Link to this block with `#my-special-info` instead of the default `#admonition-my-info`.
```
````
#### Collapsible
For a block to be initially collapsible, and then be openable, set `collapsible=true`:
@@ -176,3 +193,4 @@ Will yield something like the following HTML, which you can then apply styles to
```admonish collapsible=true
Content will be hidden initially.
```

View File

@@ -38,6 +38,7 @@ Subfields:
- `default.title` (optional): Title to use for blocks. Defaults to the directive used in titlecase.
- `default.collapsible` (optional, default: `false`): Make blocks collapsible by default when set to `true`.
- `default.css_id_prefix` (optional, default: `"admonition-"`): The default css id prefix to add to the id of all blocks. Ignored on blocks with an `id` field.
### `renderer`

6
book/v2.md Normal file
View File

@@ -0,0 +1,6 @@
# Notes for a v2 release
## Default behaviour changes
- `on_failure` default changed from `continue` to `bail`
- `preprocessor.admonish.renderer.test.render_mode` default changed from `preserve` to `strip`

View File

@@ -4,9 +4,14 @@
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "sass --no-source-map scss/mdbook-admonish.scss ../src/bin/assets/mdbook-admonish.css"
"build": "sass --no-source-map scss/mdbook-admonish.scss ../src/bin/assets/mdbook-admonish.css",
"lint": "prettier --check .",
"fix": "prettier --write ."
},
"dependencies": {
"sass": "^1.49.7"
},
"devDependencies": {
"prettier": "^3.0.3"
}
}

View File

@@ -30,29 +30,41 @@
/// Admonition flavours
$admonitions: (
// pencil
note: $clr-blue-a200 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>",
admonish-note: $clr-blue-a200
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>",
// clipboard-text
abstract summary tldr: $clr-light-blue-a400 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>",
admonish-abstract admonish-summary admonish-tldr: $clr-light-blue-a400
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>",
// information
info todo: $clr-cyan-a700 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>",
admonish-info admonish-todo: $clr-cyan-a700
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>",
// fire
tip hint important: $clr-teal-a700 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>",
admonish-tip admonish-hint admonish-important: $clr-teal-a700
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>",
// check-bold
success check done: $clr-green-a700 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>",
admonish-success admonish-check admonish-done: $clr-green-a700
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>",
// help-circle
question help faq: $clr-light-green-a700 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>",
admonish-question admonish-help admonish-faq: $clr-light-green-a700
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>",
// alert
warning caution attention: $clr-orange-a400 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>",
admonish-warning admonish-caution admonish-attention: $clr-orange-a400
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>",
// close-thick
failure fail missing: $clr-red-a200 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>",
admonish-failure admonish-fail admonish-missing: $clr-red-a200
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>",
// lighting-bold
danger error: $clr-red-a400 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>",
admonish-danger admonish-error: $clr-red-a400
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>",
// bug
bug: $clr-pink-a400 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>",
admonish-bug: $clr-pink-a400
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>",
// format-list-numbered
example: $clr-deep-purple-a200 "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>",
admonish-example: $clr-deep-purple-a200
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>",
// format-quote-close
quote cite: $clr-grey "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>",
admonish-quote admonish-cite: $clr-grey
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>"
) !default;
// ----------------------------------------------------------------------------
@@ -62,16 +74,13 @@ $admonitions: (
// Admonition variables
:root {
@each $names, $props in $admonitions {
--md-admonition-icon--#{nth($names, 1)}:
url("data:image/svg+xml;charset=utf-8,#{nth($props, 2)}");
--md-admonition-icon--#{nth($names, 1)}: url("data:image/svg+xml;charset=utf-8,#{nth($props, 2)}");
}
--md-details-icon:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>");
--md-details-icon: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>");
}
// ----------------------------------------------------------------------------
// Admonition
:is(.admonition) {
display: flow-root;
@@ -86,7 +95,9 @@ $admonitions: (
border: 0 solid black;
border-inline-start-width: 0.4rem;
border-radius: 0.2rem;
box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);;
box-shadow:
0 0.2rem 1rem rgba(0, 0, 0, 0.05),
0 0 0.1rem rgba(0, 0, 0, 0.1);
// [print]: Omit shadow as it may lead to rendering errors
@media print {
@@ -125,25 +136,27 @@ a.admonition-anchor-link {
position: absolute;
left: -1.2rem;
// Ensure we have enough padding, so that we can move the mouse to click on it
padding-right: 1.0rem;
padding-right: 1rem;
&:link, &:visited {
&:link,
&:visited {
// Don't make links colored (override to standard text color)
// variable provided downstream by mdbook
color: var(--fg);
}
&:link:hover, &:visited:hover {
&:link:hover,
&:visited:hover {
// No underline on hover
text-decoration: none;
}
&::before {
content: '§';
content: "§";
}
}
// Admonition title
:is(.admonition-title, summary) {
:is(.admonition-title, summary.admonition-title) {
position: relative;
min-height: 4rem;
margin-block: 0;
@@ -152,6 +165,9 @@ a.admonition-anchor-link {
padding-inline: 4.4rem 1.2rem;
font-weight: 700;
background-color: color.adjust($clr-blue-a200, $alpha: -0.9);
// Always print title bar tint
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
// Compatilility with rendering markdown inside the content
display: flex;
@@ -173,6 +189,9 @@ a.admonition-anchor-link {
width: 2rem;
height: 2rem;
background-color: $clr-blue-a200;
// Always print icon
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
-webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
mask-repeat: no-repeat;
@@ -182,17 +201,16 @@ a.admonition-anchor-link {
content: "";
}
// Show anchor link on hover over title
&:hover a.admonition-anchor-link {
display: initial
display: initial;
}
}
summary.admonition-title {
details.admonition > &::after {
position: absolute;
top: .625em;
top: 0.625em;
inset-inline-end: 1.6rem;
height: 2rem;
width: 2rem;
@@ -205,7 +223,7 @@ summary.admonition-title {
-webkit-mask-size: contain;
content: "";
transform: rotate(0deg);
transition: transform .25s;
transition: transform 0.25s;
}
details[open].admonition > &::after {
@@ -223,6 +241,7 @@ summary.admonition-title {
// Admonition flavour selectors
$flavours: ();
@each $name in $names {
$flavours: list.join($flavours, ".#{$name}", $separator: comma);
}
@@ -233,7 +252,7 @@ summary.admonition-title {
}
// Admonition flavour title
:is(#{$flavours}) > :is(.admonition-title, summary) {
:is(#{$flavours}) > :is(.admonition-title, summary.admonition-title) {
background-color: color.adjust($tint, $alpha: -0.9);
// Admonition icon
@@ -261,7 +280,8 @@ summary.admonition-title {
}
}
.ayu, .coal {
.ayu,
.coal {
& :is(.admonition) {
background-color: var(--theme-hover);
}
@@ -272,8 +292,10 @@ summary.admonition-title {
background-color: var(--sidebar-bg);
color: var(--sidebar-fg);
}
& .admonition-anchor-link {
&:link, &:visited {
&:link,
&:visited {
color: var(--sidebar-fg);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -95,6 +95,11 @@ picomatch@^2.0.4, picomatch@^2.2.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
prettier@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643"
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"

View File

@@ -9,7 +9,7 @@ title = "mdbook-admonish-integration"
[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install`
assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install`
after = ["links"]
[preprocessor.admonish.renderer.test]

View File

@@ -9,7 +9,7 @@ title = "mdbook-admonish-integration"
[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "2.0.1" # do not edit: managed by `mdbook-admonish install`
assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install`
after = ["links"]
[preprocessor.admonish.renderer.test]

View File

@@ -1,5 +1,5 @@
<h1 id="chapter-1"><a class="header" href="#chapter-1">Chapter 1</a></h1>
<div id="admonition-what-is-this" class="admonition abstract">
<div id="admonition-what-is-this" class="admonition admonish-abstract">
<div class="admonition-title">
<p>What <i>is</i> this?</p>
<p><a class="admonition-anchor-link" href="#admonition-what-is-this"></a></p>
@@ -9,7 +9,7 @@
<p>It verifies that <code>mdbook</code> post-processes our generated HTML in the way we expect.</p>
</div>
</div>
<div id="admonition-note" class="admonition note">
<div id="admonition-note" class="admonition admonish-note">
<div class="admonition-title">
<p>Note</p>
<p><a class="admonition-anchor-link" href="#admonition-note"></a></p>
@@ -18,12 +18,12 @@
<p>Simples</p>
</div>
</div>
<div id="admonition-default" class="admonition warning">
<div id="admonition-default" class="admonition admonish-warning">
<div>
<p>No title, only body</p>
</div>
</div>
<div id="admonition-error-rendering-admonishment" class="admonition bug">
<div id="admonition-error-rendering-admonishment" class="admonition admonish-bug">
<div class="admonition-title">
<p>Error rendering admonishment</p>
<p><a class="admonition-anchor-link" href="#admonition-error-rendering-admonishment"></a></p>
@@ -44,7 +44,7 @@ No title, only body
</code></pre>
</div>
</div>
<details id="admonition-note-1" class="admonition note">
<details id="admonition-note-1" class="admonition admonish-note">
<summary class="admonition-title">
<p>Note</p>
<p><a class="admonition-anchor-link" href="#admonition-note-1"></a></p>
@@ -53,7 +53,7 @@ No title, only body
<p>Hidden on load</p>
</div>
</details>
<div id="admonition-warning" class="admonition warning">
<div id="admonition-warning" class="admonition admonish-warning">
<div class="admonition-title">
<p>Warning</p>
<p><a class="admonition-anchor-link" href="#admonition-warning"></a></p>
@@ -62,7 +62,7 @@ No title, only body
<p>This is a commonly shared warning!</p>
</div>
</div>
<div id="admonition-note-2" class="admonition note">
<div id="admonition-note-2" class="admonition admonish-note">
<div class="admonition-title">
<p>Note</p>
<p><a class="admonition-anchor-link" href="#admonition-note-2"></a></p>
@@ -72,7 +72,7 @@ No title, only body
</code></pre>
</div>
</div>
<div id="admonition-note-3" class="admonition note">
<div id="admonition-note-3" class="admonition admonish-note">
<div class="admonition-title">
<p>Note</p>
<p><a class="admonition-anchor-link" href="#admonition-note-3"></a></p>
@@ -90,4 +90,29 @@ let x = 20;
<span class="boring">}</span></code></pre></pre>
</div>
</div>
<p>In a list:</p>
<ol>
<li>
<p>Thing one</p>
<pre><code class="language-sh">Thing one
</code></pre>
</li>
<li>
<p>Thing two</p>
<div id="admonition-note-4" class="admonition admonish-note">
<div class="admonition-title">
<p>Note</p>
<p><a class="admonition-anchor-link" href="#admonition-note-4"></a></p>
</div>
<div>
<p>Thing two</p>
</div>
</div>
</li>
<li>
<p>Thing three</p>
<pre><code class="language-sh">Thing three
</code></pre>
</li>
</ol>

View File

@@ -41,3 +41,23 @@ let x = 10;
let x = 20;
```
````
In a list:
1. Thing one
```sh
Thing one
```
1. Thing two
```admonish
Thing two
```
1. Thing three
```sh
Thing three
```

View File

@@ -8,6 +8,21 @@ function eprintln() {
>&2 echo "$1"
}
# Node things
pushd compile_assets > /dev/null
eprintln "Linting style sources"
yarn run lint
eprintln "Checking compiled styles up to date"
COMITTED_ASSETS="$(cat ../src/bin/assets/mdbook-admonish.css)"
yarn run build
RECOMPILED_ASSETS="$(cat ../src/bin/assets/mdbook-admonish.css)"
diff -u <(printf "%s" "$COMITTED_ASSETS") <(printf "%s" "$RECOMPILED_ASSETS")
popd > /dev/null
# Rust things
eprintln "Formatting sources"
cargo fmt -- --check
@@ -24,5 +39,6 @@ cargo test --no-default-features --features cli
eprintln "Building documentation"
cargo doc --no-deps --lib
# Integration test
eprintln "Running mdbook integration test"
./integration/scripts/check

View File

@@ -4,10 +4,21 @@
#
# Does not include offline node development stack (i.e. yarn)
set -exuo pipefail
set -euo pipefail
function eprintln() {
>&2 echo "$1"
}
cd "$(dirname "$0")"/..
eprintln "Installing additional Rust components"
rustup component add rustfmt clippy
eprintln "Installing mdbook"
./scripts/install-mdbook
eprintln "Installing node dependencies"
pushd compile_assets > /dev/null
yarn install --frozen-lockfile
popd > /dev/null

View File

@@ -1,9 +1,18 @@
#!/bin/bash
set -exuo pipefail
set -euo pipefail
cd "$(dirname "$0")"/..
if ! mdbook --version; then
cargo install mdbook --version 0.4.32 --force
function eprintln() {
>&2 echo "$1"
}
VERSION="0.4.35"
eprintln "Checking if mdbook $VERSION is installed"
if [[ "$(mdbook --version)" != "mdbook v$VERSION" ]]; then
eprintln "Installing mdbook $VERSION"
cargo install mdbook --version "$VERSION" --force
fi
eprintln "mdbook $VERSION is installed"

View File

@@ -1 +1 @@
^2.0.0
^3.0.0

View File

@@ -1 +1 @@
2.0.1
3.0.1

View File

@@ -1,31 +1,18 @@
@charset "UTF-8";
:root {
--md-admonition-icon--note:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>");
--md-admonition-icon--abstract:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>");
--md-admonition-icon--info:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>");
--md-admonition-icon--tip:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>");
--md-admonition-icon--success:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>");
--md-admonition-icon--question:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>");
--md-admonition-icon--warning:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>");
--md-admonition-icon--failure:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>");
--md-admonition-icon--danger:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>");
--md-admonition-icon--bug:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>");
--md-admonition-icon--example:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>");
--md-admonition-icon--quote:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>");
--md-details-icon:
url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>");
--md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>");
--md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>");
--md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>");
--md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>");
--md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>");
--md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>");
--md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>");
--md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>");
--md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>");
--md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>");
--md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>");
--md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>");
--md-details-icon: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>");
}
:is(.admonition) {
@@ -75,7 +62,7 @@ a.admonition-anchor-link::before {
content: "§";
}
:is(.admonition-title, summary) {
:is(.admonition-title, summary.admonition-title) {
position: relative;
min-height: 4rem;
margin-block: 0;
@@ -84,21 +71,25 @@ a.admonition-anchor-link::before {
padding-inline: 4.4rem 1.2rem;
font-weight: 700;
background-color: rgba(68, 138, 255, 0.1);
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
display: flex;
}
:is(.admonition-title, summary) p {
:is(.admonition-title, summary.admonition-title) p {
margin: 0;
}
html :is(.admonition-title, summary):last-child {
html :is(.admonition-title, summary.admonition-title):last-child {
margin-bottom: 0;
}
:is(.admonition-title, summary)::before {
:is(.admonition-title, summary.admonition-title)::before {
position: absolute;
top: 0.625em;
inset-inline-start: 1.6rem;
width: 2rem;
height: 2rem;
background-color: #448aff;
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
-webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
mask-repeat: no-repeat;
@@ -107,7 +98,7 @@ html :is(.admonition-title, summary):last-child {
-webkit-mask-size: contain;
content: "";
}
:is(.admonition-title, summary):hover a.admonition-anchor-link {
:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link {
display: initial;
}
@@ -132,204 +123,204 @@ details[open].admonition > summary.admonition-title::after {
transform: rotate(90deg);
}
:is(.admonition):is(.note) {
:is(.admonition):is(.admonish-note) {
border-color: #448aff;
}
:is(.note) > :is(.admonition-title, summary) {
:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(68, 138, 255, 0.1);
}
:is(.note) > :is(.admonition-title, summary)::before {
:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #448aff;
mask-image: var(--md-admonition-icon--note);
-webkit-mask-image: var(--md-admonition-icon--note);
mask-image: var(--md-admonition-icon--admonish-note);
-webkit-mask-image: var(--md-admonition-icon--admonish-note);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.abstract, .summary, .tldr) {
:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {
border-color: #00b0ff;
}
:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) {
:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(0, 176, 255, 0.1);
}
:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before {
:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #00b0ff;
mask-image: var(--md-admonition-icon--abstract);
-webkit-mask-image: var(--md-admonition-icon--abstract);
mask-image: var(--md-admonition-icon--admonish-abstract);
-webkit-mask-image: var(--md-admonition-icon--admonish-abstract);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.info, .todo) {
:is(.admonition):is(.admonish-info, .admonish-todo) {
border-color: #00b8d4;
}
:is(.info, .todo) > :is(.admonition-title, summary) {
:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(0, 184, 212, 0.1);
}
:is(.info, .todo) > :is(.admonition-title, summary)::before {
:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #00b8d4;
mask-image: var(--md-admonition-icon--info);
-webkit-mask-image: var(--md-admonition-icon--info);
mask-image: var(--md-admonition-icon--admonish-info);
-webkit-mask-image: var(--md-admonition-icon--admonish-info);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.tip, .hint, .important) {
:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {
border-color: #00bfa5;
}
:is(.tip, .hint, .important) > :is(.admonition-title, summary) {
:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(0, 191, 165, 0.1);
}
:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before {
:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #00bfa5;
mask-image: var(--md-admonition-icon--tip);
-webkit-mask-image: var(--md-admonition-icon--tip);
mask-image: var(--md-admonition-icon--admonish-tip);
-webkit-mask-image: var(--md-admonition-icon--admonish-tip);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.success, .check, .done) {
:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {
border-color: #00c853;
}
:is(.success, .check, .done) > :is(.admonition-title, summary) {
:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(0, 200, 83, 0.1);
}
:is(.success, .check, .done) > :is(.admonition-title, summary)::before {
:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #00c853;
mask-image: var(--md-admonition-icon--success);
-webkit-mask-image: var(--md-admonition-icon--success);
mask-image: var(--md-admonition-icon--admonish-success);
-webkit-mask-image: var(--md-admonition-icon--admonish-success);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.question, .help, .faq) {
:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {
border-color: #64dd17;
}
:is(.question, .help, .faq) > :is(.admonition-title, summary) {
:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(100, 221, 23, 0.1);
}
:is(.question, .help, .faq) > :is(.admonition-title, summary)::before {
:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #64dd17;
mask-image: var(--md-admonition-icon--question);
-webkit-mask-image: var(--md-admonition-icon--question);
mask-image: var(--md-admonition-icon--admonish-question);
-webkit-mask-image: var(--md-admonition-icon--admonish-question);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.warning, .caution, .attention) {
:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {
border-color: #ff9100;
}
:is(.warning, .caution, .attention) > :is(.admonition-title, summary) {
:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(255, 145, 0, 0.1);
}
:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before {
:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #ff9100;
mask-image: var(--md-admonition-icon--warning);
-webkit-mask-image: var(--md-admonition-icon--warning);
mask-image: var(--md-admonition-icon--admonish-warning);
-webkit-mask-image: var(--md-admonition-icon--admonish-warning);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.failure, .fail, .missing) {
:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {
border-color: #ff5252;
}
:is(.failure, .fail, .missing) > :is(.admonition-title, summary) {
:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(255, 82, 82, 0.1);
}
:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before {
:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #ff5252;
mask-image: var(--md-admonition-icon--failure);
-webkit-mask-image: var(--md-admonition-icon--failure);
mask-image: var(--md-admonition-icon--admonish-failure);
-webkit-mask-image: var(--md-admonition-icon--admonish-failure);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.danger, .error) {
:is(.admonition):is(.admonish-danger, .admonish-error) {
border-color: #ff1744;
}
:is(.danger, .error) > :is(.admonition-title, summary) {
:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(255, 23, 68, 0.1);
}
:is(.danger, .error) > :is(.admonition-title, summary)::before {
:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #ff1744;
mask-image: var(--md-admonition-icon--danger);
-webkit-mask-image: var(--md-admonition-icon--danger);
mask-image: var(--md-admonition-icon--admonish-danger);
-webkit-mask-image: var(--md-admonition-icon--admonish-danger);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.bug) {
:is(.admonition):is(.admonish-bug) {
border-color: #f50057;
}
:is(.bug) > :is(.admonition-title, summary) {
:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(245, 0, 87, 0.1);
}
:is(.bug) > :is(.admonition-title, summary)::before {
:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #f50057;
mask-image: var(--md-admonition-icon--bug);
-webkit-mask-image: var(--md-admonition-icon--bug);
mask-image: var(--md-admonition-icon--admonish-bug);
-webkit-mask-image: var(--md-admonition-icon--admonish-bug);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.example) {
:is(.admonition):is(.admonish-example) {
border-color: #7c4dff;
}
:is(.example) > :is(.admonition-title, summary) {
:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(124, 77, 255, 0.1);
}
:is(.example) > :is(.admonition-title, summary)::before {
:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #7c4dff;
mask-image: var(--md-admonition-icon--example);
-webkit-mask-image: var(--md-admonition-icon--example);
mask-image: var(--md-admonition-icon--admonish-example);
-webkit-mask-image: var(--md-admonition-icon--admonish-example);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
}
:is(.admonition):is(.quote, .cite) {
:is(.admonition):is(.admonish-quote, .admonish-cite) {
border-color: #9e9e9e;
}
:is(.quote, .cite) > :is(.admonition-title, summary) {
:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) {
background-color: rgba(158, 158, 158, 0.1);
}
:is(.quote, .cite) > :is(.admonition-title, summary)::before {
:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before {
background-color: #9e9e9e;
mask-image: var(--md-admonition-icon--quote);
-webkit-mask-image: var(--md-admonition-icon--quote);
mask-image: var(--md-admonition-icon--admonish-quote);
-webkit-mask-image: var(--md-admonition-icon--admonish-quote);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-size: contain;
@@ -340,7 +331,8 @@ details[open].admonition > summary.admonition-title::after {
background-color: var(--sidebar-bg);
}
.ayu :is(.admonition), .coal :is(.admonition) {
.ayu :is(.admonition),
.coal :is(.admonition) {
background-color: var(--theme-hover);
}

View File

@@ -97,6 +97,9 @@ fn handle_supports(renderer: String) -> ! {
#[cfg(feature = "cli-install")]
mod install {
use anyhow::{Context, Result};
use path_slash::PathExt;
use std::borrow::Cow;
use std::path::Path;
use std::{
fs::{self, File},
io::Write,
@@ -122,6 +125,16 @@ mod install {
}
}
// Normalize path to UNIX style.
// This avoids conflicts/rewriting files when projects are used under different
// operating systems (e.g. on Windows, after being used on Linux)
//
// https://github.com/tommilligan/mdbook-admonish/issues/161
fn normalize_config_file_path(path: &Path) -> Result<Cow<'_, str>> {
path.to_slash()
.context("UNIX style path normalization error")
}
pub fn handle_install(proj_dir: PathBuf, css_dir: PathBuf) -> Result<()> {
let config = proj_dir.join("book.toml");
log::info!("Reading configuration file '{}'", config.display());
@@ -139,7 +152,7 @@ mod install {
);
preprocessor["assets_version"] = value;
} else {
log::info!("Unexpected configuration, not updating prereprocessor configuration");
log::info!("Unexpected configuration, not updating preprocessor configuration");
};
let mut additional_css = additional_css(&mut doc);
@@ -148,12 +161,13 @@ mod install {
// Normalize path to remove no-op components
// https://github.com/tommilligan/mdbook-admonish/issues/47
let filepath: PathBuf = filepath.components().collect();
let filepath_str = filepath.to_str().context("non-utf8 filepath")?;
if let Ok(ref mut additional_css) = additional_css {
if !additional_css.contains_str(filepath_str) {
let filepath_str = normalize_config_file_path(&filepath)?;
if !additional_css.contains_str(&filepath_str) {
log::info!("Adding '{filepath_str}' to 'additional-css'");
additional_css.push(filepath_str);
additional_css.push(filepath_str.as_ref());
}
} else {
log::warn!("Unexpected configuration, not updating 'additional-css'");
@@ -227,4 +241,24 @@ A beautifully styled message.
item["command"] = toml_edit::value("mdbook-admonish");
Ok(item)
}
#[cfg(test)]
mod test {
use super::*;
/// This test seems redundant, but would fail on Windows.
///
/// We want to always convert to a fixed output string style, independant
/// of runtime platform, and forward slashes in relative paths are fine on
/// Windows.
#[test]
fn test_normalize_config_file_path() {
let input = PathBuf::from(".")
.join("css-dir")
.join("mdbook-admonish.css");
let expected = "./css-dir/mdbook-admonish.css";
let actual = normalize_config_file_path(&input).unwrap();
assert_eq!(actual.as_ref(), expected);
}
}
}

View File

@@ -5,15 +5,17 @@ use std::collections::HashMap;
use crate::types::AdmonitionDefaults;
/// Loads the plugin configuration from mdbook internals.
///
/// Roundtrips config to string, to avoid linking the plugin's internal version of toml
/// to the one publically exposed by the mdbook library.
pub(crate) fn admonish_config_from_context(ctx: &PreprocessorContext) -> Result<Config> {
let table: toml::Table = ctx
.config
.get_preprocessor("admonish")
.context("No configuration for mdbook-admonish in book.toml")?
.to_owned();
table
.try_into()
.context("Invalid mdbook-admonish configuration in book.toml")
let table: String = toml_mdbook::to_string(
ctx.config
.get_preprocessor("admonish")
.context("No configuration for mdbook-admonish in book.toml")?,
)?;
toml::from_str(&table).context("Invalid mdbook-admonish configuration in book.toml")
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]

View File

@@ -9,6 +9,7 @@ mod v2;
pub(crate) struct InstanceConfig {
pub(crate) directive: String,
pub(crate) title: Option<String>,
pub(crate) id: Option<String>,
pub(crate) additional_classnames: Vec<String>,
pub(crate) collapsible: Option<bool>,
}
@@ -69,18 +70,22 @@ mod test {
InstanceConfig {
directive: "note".to_owned(),
title: None,
id: None,
additional_classnames: vec!["additional-classname".to_owned()],
collapsible: None,
}
);
// v2 syntax is supported
assert_eq!(
InstanceConfig::from_info_string(r#"admonish title="Custom Title" type="question""#)
.unwrap()
.unwrap(),
InstanceConfig::from_info_string(
r#"admonish title="Custom Title" type="question" id="my-id""#
)
.unwrap()
.unwrap(),
InstanceConfig {
directive: "question".to_owned(),
title: Some("Custom Title".to_owned()),
id: Some("my-id".to_owned()),
additional_classnames: Vec::new(),
collapsible: None,
}

View File

@@ -52,6 +52,7 @@ pub(crate) fn from_config_string(config_string: &str) -> Result<InstanceConfig,
Ok(InstanceConfig {
directive: directive.to_owned(),
title,
id: None,
additional_classnames,
collapsible: None,
})
@@ -69,6 +70,7 @@ mod test {
InstanceConfig {
directive: "".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -78,6 +80,7 @@ mod test {
InstanceConfig {
directive: "".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -87,6 +90,7 @@ mod test {
InstanceConfig {
directive: "unknown".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -96,6 +100,7 @@ mod test {
InstanceConfig {
directive: "note".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -105,6 +110,7 @@ mod test {
InstanceConfig {
directive: "note".to_owned(),
title: None,
id: None,
additional_classnames: vec!["additional-classname".to_owned()],
collapsible: None,
}

View File

@@ -10,6 +10,8 @@ struct UserInput {
#[serde(default)]
title: Option<String>,
#[serde(default)]
id: Option<String>,
#[serde(default)]
class: Option<String>,
#[serde(default)]
collapsible: Option<bool>,
@@ -88,6 +90,7 @@ pub(crate) fn from_config_string(config_string: &str) -> Result<InstanceConfig,
Ok(InstanceConfig {
directive: config.r#type.unwrap_or_default(),
title: config.title,
id: config.id,
additional_classnames,
collapsible: config.collapsible,
})
@@ -105,6 +108,7 @@ mod test {
InstanceConfig {
directive: "".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -114,6 +118,7 @@ mod test {
InstanceConfig {
directive: "".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -126,6 +131,7 @@ mod test {
InstanceConfig {
directive: "note".to_owned(),
title: Some("Никита".to_owned()),
id: None,
additional_classnames: vec!["additional".to_owned(), "classname".to_owned()],
collapsible: Some(true),
}
@@ -136,6 +142,7 @@ mod test {
InstanceConfig {
directive: "".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -146,6 +153,7 @@ mod test {
InstanceConfig {
directive: "info".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
}
@@ -156,10 +164,22 @@ mod test {
InstanceConfig {
directive: "info".to_owned(),
title: Some("Information".to_owned()),
id: None,
additional_classnames: Vec::new(),
collapsible: Some(false),
}
);
// Test custom id
assert_eq!(
from_config_string(r#"info title="My Info" id="my-info-custom-id""#).unwrap(),
InstanceConfig {
directive: "info".to_owned(),
title: Some("My Info".to_owned()),
id: Some("my-info-custom-id".to_owned()),
additional_classnames: Vec::new(),
collapsible: None,
}
);
// Directive after toml config is an error
assert!(from_config_string(r#"title="Information" info"#).is_err());
}

View File

@@ -28,12 +28,15 @@ pub(crate) fn preprocess(
for (event, span) in events.into_offset_iter() {
if let Event::Start(Tag::CodeBlock(Fenced(info_string))) = event.clone() {
let span_content = &content[span.start..span.end];
const INDENT_SCAN_MAX: usize = 1024;
let indent = indent_of(content, span.start, INDENT_SCAN_MAX);
let admonition = match parse_admonition(
info_string.as_ref(),
admonition_defaults,
span_content,
on_failure,
indent,
) {
Some(admonition) => admonition,
None => continue,
@@ -44,7 +47,7 @@ pub(crate) fn preprocess(
// Once we've identitified admonition blocks, handle them differently
// depending on our render mode
let new_content = match render_text_mode {
RenderTextMode::Html => admonition.html_with_unique_ids(&mut id_counter),
RenderTextMode::Html => admonition.html(&mut id_counter),
RenderTextMode::Strip => admonition.strip(),
};
@@ -62,11 +65,73 @@ pub(crate) fn preprocess(
Ok(content)
}
/// Returns the indent of the given position.
///
/// Defined as the number of characters between the given `position` (where
/// position is a valid char boundary byte-index in `content`),
/// and the previous newline character `\n`.
///
/// `max` is the maximum number of characters to scan before assuming there is
/// no indent (will return zero if exceeded).
///
/// ## Panics
///
/// Will panic if `position` is not a valid utf-8 char boundary index of `content`.
fn indent_of(content: &str, position: usize, max: usize) -> usize {
// Scan for a line start before this span.
content[..position]
.chars()
.rev()
// For safety, only scan up to a fixed limit of the text
.take(max)
.position(|c| c == '\n')
// If we can't find a newline, assume no indent
.unwrap_or_default()
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn indent_of_samples() {
for (content, position, max, expected) in [
// Empty case
("", 0, 10, 0),
("no newline", 4, 10, 0),
// Newline at position 5, difference from 8 is 3
("with\nnewline", 8, 10, 3),
// If no newline in safety limit, return 0
("with\nnewline", 8, 2, 0),
// Safety limit is characters, not bytes
// Regression test for FIXME LINK
(
"例えばこれは",
// Position is generated by mdbook internals, should be valid char limit
// This mimics the second character starting the span
"".len(),
// Any arbitrary safetly limit should be valid
1,
// Should not panic
0,
),
(
"例え\n れは",
// Position is generated by mdbook internals, should be valid char limit
// This mimics the second character starting the span
"例え\n ".len(),
// Any arbitrary safetly limit should be valid
4,
// Should not panic
2,
),
] {
let actual = indent_of(content, position, max);
assert_eq!(actual, expected);
}
}
fn prep(content: &str) -> String {
preprocess(
content,
@@ -88,7 +153,7 @@ Text
let expected = r##"# Chapter
<div id="admonition-note" class="admonition note">
<div id="admonition-note" class="admonition admonish-note">
<div class="admonition-title">
Note
@@ -120,7 +185,7 @@ Text
let expected = r##"# Chapter
<div id="admonition-note" class="admonition note">
<div id="admonition-note" class="admonition admonish-note">
<div class="admonition-title">
Note
@@ -152,7 +217,7 @@ Text
let expected = r##"# Chapter
<div id="admonition-warning" class="admonition warning">
<div id="admonition-warning" class="admonition admonish-warning">
<div class="admonition-title">
Warning
@@ -182,7 +247,7 @@ Text
let expected = r##"# Chapter
<div id="admonition-caution" class="admonition warning">
<div id="admonition-caution" class="admonition admonish-warning">
<div class="admonition-title">
Caution
@@ -212,7 +277,7 @@ Text
let expected = r##"# Chapter
<div id="admonition-read-this" class="admonition warning">
<div id="admonition-read-this" class="admonition admonish-warning">
<div class="admonition-title">
Read **this**!
@@ -306,7 +371,7 @@ hello
let expected = r##"
<div id="admonition-and-in-the-title" class="admonition note">
<div id="admonition-and-in-the-title" class="admonition admonish-note">
<div class="admonition-title">
And "<i>in</i>" the title
@@ -336,7 +401,7 @@ hello
let expected = r##"
<div id="admonition-trademark" class="admonition warning">
<div id="admonition-trademark" class="admonition admonish-warning">
<div class="admonition-title">
Trademark™
@@ -365,7 +430,7 @@ Will have bonus classnames
let expected = r##"
<div id="admonition-tip" class="admonition tip my-style other-style">
<div id="admonition-tip" class="admonition admonish-tip my-style other-style">
<div class="admonition-title">
Tip
@@ -393,7 +458,7 @@ Will have bonus classnames
let expected = r##"
<div id="admonition-developers-dont-want-you-to-know-this-one-weird-tip" class="admonition tip my-style other-style">
<div id="admonition-developers-dont-want-you-to-know-this-one-weird-tip" class="admonition admonish-tip my-style other-style">
<div class="admonition-title">
Developers don't want you to know this one weird tip!
@@ -418,16 +483,16 @@ Will have bonus classnames
```
"#;
let expected = r##"
let expected = r#"
<div id="admonition-default" class="admonition note">
<div id="admonition-default" class="admonition admonish-note">
<div>
</div>
</div>
"##;
"#;
assert_eq!(expected, prep(content));
}
@@ -446,7 +511,7 @@ Content one.
let expected = r##"
<div id="admonition-my-note" class="admonition note">
<div id="admonition-my-note" class="admonition admonish-note">
<div class="admonition-title">
My Note
@@ -461,7 +526,7 @@ Content zero.
</div>
<div id="admonition-my-note-1" class="admonition note">
<div id="admonition-my-note-1" class="admonition admonish-note">
<div class="admonition-title">
My Note
@@ -489,7 +554,7 @@ Bonus content!
let expected = r##"
<div id="admonition-article-heading" class="admonition tip my other-style">
<div id="admonition-article-heading" class="admonition admonish-tip my other-style">
<div class="admonition-title">
Article Heading
@@ -517,7 +582,7 @@ Bonus content!
let expected = r##"
<div id="admonition-error-rendering-admonishment" class="admonition bug">
<div id="admonition-error-rendering-admonishment" class="admonition admonish-bug">
<div class="admonition-title">
Error rendering admonishment
@@ -617,7 +682,7 @@ Hidden
let expected = r##"
<details id="admonition-note" class="admonition note">
<details id="admonition-note" class="admonition admonish-note">
<summary class="admonition-title">
Note
@@ -646,7 +711,7 @@ Text
let expected = r##"# Chapter
<div id="admonition-admonish" class="admonition note">
<div id="admonition-admonish" class="admonition admonish-note">
<div class="admonition-title">
Admonish
@@ -667,6 +732,7 @@ Text
OnFailure::Continue,
&AdmonitionDefaults {
title: Some("Admonish".to_owned()),
css_id_prefix: None,
collapsible: false,
},
RenderTextMode::Html,
@@ -684,9 +750,9 @@ A simple admonition.
Text
"#;
let expected = r##"# Chapter
let expected = r#"# Chapter
<div id="admonition-default" class="admonition note">
<div id="admonition-default" class="admonition admonish-note">
<div>
A simple admonition.
@@ -694,13 +760,14 @@ A simple admonition.
</div>
</div>
Text
"##;
"#;
let preprocess_result = preprocess(
content,
OnFailure::Continue,
&AdmonitionDefaults {
title: Some("Admonish".to_owned()),
css_id_prefix: None,
collapsible: false,
},
RenderTextMode::Html,
@@ -716,11 +783,41 @@ Text
A simple admonition.
```
Text
"#;
let expected = r#"# Chapter
<div id="admonition-default" class="admonition admonish-note">
<div>
A simple admonition.
</div>
</div>
Text
"#;
assert_eq!(expected, prep(content));
}
#[test]
fn standard_custom_id() {
let content = r#"# Chapter
```admonish check id="yay-custom-id"
A simple admonition.
```
Text
"#;
let expected = r##"# Chapter
<div id="admonition-default" class="admonition note">
<div id="yay-custom-id" class="admonition admonish-success">
<div class="admonition-title">
Check
<a class="admonition-anchor-link" href="#yay-custom-id"></a>
</div>
<div>
A simple admonition.
@@ -732,4 +829,245 @@ Text
assert_eq!(expected, prep(content));
}
#[test]
fn no_custom_id_default_prefix() {
let content = r#"# Chapter
```admonish check
A simple admonition.
```
Text
"#;
let expected = r##"# Chapter
<div id="admonition-check" class="admonition admonish-success">
<div class="admonition-title">
Check
<a class="admonition-anchor-link" href="#admonition-check"></a>
</div>
<div>
A simple admonition.
</div>
</div>
Text
"##;
assert_eq!(expected, prep(content));
}
#[test]
fn no_custom_id_default_prefix_custom_title() {
let content = r#"# Chapter
```admonish check title="Check Mark"
A simple admonition.
```
Text
"#;
let expected = r##"# Chapter
<div id="admonition-check-mark" class="admonition admonish-success">
<div class="admonition-title">
Check Mark
<a class="admonition-anchor-link" href="#admonition-check-mark"></a>
</div>
<div>
A simple admonition.
</div>
</div>
Text
"##;
assert_eq!(expected, prep(content));
}
#[test]
fn empty_default_id_prefix() {
let content = r#"# Chapter
```admonish info
A simple admonition.
```
Text
"#;
let expected = r##"# Chapter
<div id="info" class="admonition admonish-info">
<div class="admonition-title">
Info
<a class="admonition-anchor-link" href="#info"></a>
</div>
<div>
A simple admonition.
</div>
</div>
Text
"##;
let preprocess_result = preprocess(
content,
OnFailure::Continue,
&AdmonitionDefaults {
title: Some("Info".to_owned()),
css_id_prefix: Some("".to_owned()),
collapsible: false,
},
RenderTextMode::Html,
)
.unwrap();
assert_eq!(expected, preprocess_result);
}
#[test]
fn custom_id_prefix_custom_title() {
let content = r#"# Chapter
```admonish info title="My Title"
A simple admonition.
```
Text
"#;
let expected = r##"# Chapter
<div id="prefix-my-title" class="admonition admonish-info">
<div class="admonition-title">
My Title
<a class="admonition-anchor-link" href="#prefix-my-title"></a>
</div>
<div>
A simple admonition.
</div>
</div>
Text
"##;
let preprocess_result = preprocess(
content,
OnFailure::Continue,
&AdmonitionDefaults {
title: Some("Info".to_owned()),
css_id_prefix: Some("prefix-".to_owned()),
collapsible: false,
},
RenderTextMode::Html,
)
.unwrap();
assert_eq!(expected, preprocess_result);
}
#[test]
fn custom_id_custom_title() {
let content = r#"# Chapter
```admonish info title="My Title" id="my-section-id"
A simple admonition.
```
Text
"#;
let expected = r##"# Chapter
<div id="my-section-id" class="admonition admonish-info">
<div class="admonition-title">
My Title
<a class="admonition-anchor-link" href="#my-section-id"></a>
</div>
<div>
A simple admonition.
</div>
</div>
Text
"##;
let preprocess_result = preprocess(
content,
OnFailure::Continue,
&AdmonitionDefaults {
title: Some("Info".to_owned()),
css_id_prefix: Some("ignored-prefix-".to_owned()),
collapsible: false,
},
RenderTextMode::Html,
)
.unwrap();
assert_eq!(expected, preprocess_result);
}
#[test]
fn list_embed() {
let content = r#"# Chapter
1. Thing one
```sh
Thing one
```
1. Thing two
```admonish
Thing two
```
1. Thing three
```sh
Thing three
```
"#;
let expected = r##"# Chapter
1. Thing one
```sh
Thing one
```
1. Thing two
<div id="admonition-note" class="admonition admonish-note">
<div class="admonition-title">
Note
<a class="admonition-anchor-link" href="#admonition-note"></a>
</div>
<div>
Thing two
</div>
</div>
1. Thing three
```sh
Thing three
```
"##;
assert_eq!(expected, prep(content));
}
}

View File

@@ -6,7 +6,7 @@ use crate::{
book_config::OnFailure,
render::Admonition,
resolve::AdmonitionMeta,
types::{AdmonitionDefaults, Directive},
types::{AdmonitionDefaults, CssId, Directive},
};
/// Given the content in the span of the code block, and the info string,
@@ -23,6 +23,7 @@ pub(crate) fn parse_admonition<'a>(
admonition_defaults: &'a AdmonitionDefaults,
content: &'a str,
on_failure: OnFailure,
indent: usize,
) -> Option<Result<Admonition<'a>>> {
// We need to know fence details anyway for error messages
let extracted = extract_admonish_body(content);
@@ -30,8 +31,6 @@ pub(crate) fn parse_admonition<'a>(
let info = AdmonitionMeta::from_info_string(info_string, admonition_defaults)?;
let info = match info {
Ok(info) => info,
// FIXME return error messages to break build if configured
// Err(message) => return Some(Err(content)),
Err(message) => {
// Construct a fence capable of enclosing whatever we wrote for the
// actual input block
@@ -47,6 +46,7 @@ pub(crate) fn parse_admonition<'a>(
Ok(Admonition {
directive: Directive::Bug,
title: "Error rendering admonishment".to_owned(),
css_id: CssId::Prefix("admonition-".to_owned()),
additional_classnames: Vec::new(),
collapsible: false,
content: Cow::Owned(format!(
@@ -63,6 +63,7 @@ Original markdown input:
{enclosing_fence}
"#
)),
indent,
})
}
OnFailure::Bail => Err(anyhow!("Error processing admonition, bailing:\n{content}")),
@@ -70,7 +71,24 @@ Original markdown input:
}
};
Some(Ok(Admonition::new(info, extracted.body)))
Some(Ok(Admonition::new(
info,
extracted.body,
// Note that this is a bit hacky - the fence information comes from the start
// of the block, and includes the whole line.
//
// This is more likely to be what we want, as ending indentation is unrelated
// according to the commonmark spec (ref https://spec.commonmark.org/0.12/#example-85)
//
// The main case we're worried about here is indenting enough to be inside list items,
// and in this case the starting code fence must be indented enough to be considered
// part of the list item.
//
// The hacky thing is that we're considering line indent in the document as a whole,
// not relative to the context of some containing item. But I think that's what we
// want for now, anyway.
indent,
)))
}
/// We can't trust the info string length to find the start of the body

View File

@@ -170,7 +170,7 @@ x = 20;
"#;
let expected_content = r##"
<div id="admonition-title" class="admonition note">
<div id="admonition-title" class="admonition admonish-note">
<div class="admonition-title">
Title
@@ -190,7 +190,7 @@ x = 20;
let ctx = mock_context(
&json!({
"assets_version": "2.0.0"
"assets_version": "3.0.0"
}),
"html",
);
@@ -212,7 +212,7 @@ x = 20;
"#;
let ctx = mock_context(
&json!({
"assets_version": "2.0.0"
"assets_version": "3.0.0"
}),
"test",
);
@@ -242,7 +242,7 @@ x = 20;
"#;
let ctx = mock_context(
&json!({
"assets_version": "2.0.0",
"assets_version": "3.0.0",
"renderer": {
"test": {
"render_mode": "strip",

View File

@@ -3,23 +3,26 @@ use std::borrow::Cow;
use std::collections::HashMap;
pub use crate::preprocessor::Admonish;
use crate::{resolve::AdmonitionMeta, types::Directive};
use crate::{
resolve::AdmonitionMeta,
types::{CssId, Directive},
};
impl Directive {
fn classname(&self) -> &'static str {
match self {
Directive::Note => "note",
Directive::Abstract => "abstract",
Directive::Info => "info",
Directive::Tip => "tip",
Directive::Success => "success",
Directive::Question => "question",
Directive::Warning => "warning",
Directive::Failure => "failure",
Directive::Danger => "danger",
Directive::Bug => "bug",
Directive::Example => "example",
Directive::Quote => "quote",
Directive::Note => "admonish-note",
Directive::Abstract => "admonish-abstract",
Directive::Info => "admonish-info",
Directive::Tip => "admonish-tip",
Directive::Success => "admonish-success",
Directive::Question => "admonish-question",
Directive::Warning => "admonish-warning",
Directive::Failure => "admonish-failure",
Directive::Danger => "admonish-danger",
Directive::Bug => "admonish-bug",
Directive::Example => "admonish-example",
Directive::Quote => "admonish-quote",
}
}
}
@@ -29,15 +32,18 @@ pub(crate) struct Admonition<'a> {
pub(crate) directive: Directive,
pub(crate) title: String,
pub(crate) content: Cow<'a, str>,
pub(crate) css_id: CssId,
pub(crate) additional_classnames: Vec<String>,
pub(crate) collapsible: bool,
pub(crate) indent: usize,
}
impl<'a> Admonition<'a> {
pub(crate) fn new(info: AdmonitionMeta, content: &'a str) -> Self {
pub(crate) fn new(info: AdmonitionMeta, content: &'a str, indent: usize) -> Self {
let AdmonitionMeta {
directive,
title,
css_id,
additional_classnames,
collapsible,
} = info;
@@ -45,38 +51,45 @@ impl<'a> Admonition<'a> {
directive,
title,
content: Cow::Borrowed(content),
css_id,
additional_classnames,
collapsible,
indent,
}
}
pub(crate) fn html_with_unique_ids(&self, id_counter: &mut HashMap<String, usize>) -> String {
let anchor_id = unique_id_from_content(
if !self.title.is_empty() {
&self.title
} else {
ANCHOR_ID_DEFAULT
},
id_counter,
);
self.html(&anchor_id)
}
pub(crate) fn html(&self, id_counter: &mut HashMap<String, usize>) -> String {
let anchor_id = match &self.css_id {
CssId::Verbatim(id) => Cow::Borrowed(id),
CssId::Prefix(prefix) => {
let id = unique_id_from_content(
if !self.title.is_empty() {
&self.title
} else {
ANCHOR_ID_DEFAULT
},
id_counter,
);
Cow::Owned(format!("{}{}", prefix, id))
}
};
fn html(&self, anchor_id: &str) -> String {
let mut additional_class = Cow::Borrowed(self.directive.classname());
let title = &self.title;
let content = &self.content;
let indent = " ".repeat(self.indent);
let title_block = if self.collapsible { "summary" } else { "div" };
let title_html = if !title.is_empty() {
Cow::Owned(format!(
r##"<{title_block} class="admonition-title">
{title}
<a class="admonition-anchor-link" href="#{ANCHOR_ID_PREFIX}-{anchor_id}"></a>
</{title_block}>
r##"{indent}<{title_block} class="admonition-title">
{indent}
{indent}{title}
{indent}
{indent}<a class="admonition-anchor-link" href="#{anchor_id}"></a>
{indent}</{title_block}>
"##
))
} else {
@@ -100,13 +113,13 @@ impl<'a> Admonition<'a> {
// rendered as markdown paragraphs.
format!(
r#"
<{admonition_block} id="{ANCHOR_ID_PREFIX}-{anchor_id}" class="admonition {additional_class}">
{title_html}<div>
{content}
</div>
</{admonition_block}>"#,
{indent}<{admonition_block} id="{anchor_id}" class="admonition {additional_class}">
{title_html}{indent}<div>
{indent}
{indent}{content}
{indent}
{indent}</div>
{indent}</{admonition_block}>"#,
)
}
@@ -118,5 +131,4 @@ impl<'a> Admonition<'a> {
}
}
const ANCHOR_ID_PREFIX: &str = "admonition";
const ANCHOR_ID_DEFAULT: &str = "default";

View File

@@ -1,5 +1,5 @@
use crate::config::InstanceConfig;
use crate::types::{AdmonitionDefaults, Directive};
use crate::types::{AdmonitionDefaults, CssId, Directive};
use std::str::FromStr;
/// All information required to render an admonition.
@@ -9,6 +9,7 @@ use std::str::FromStr;
pub(crate) struct AdmonitionMeta {
pub directive: Directive,
pub title: String,
pub css_id: CssId,
pub additional_classnames: Vec<String>,
pub collapsible: bool,
}
@@ -28,6 +29,7 @@ impl AdmonitionMeta {
let InstanceConfig {
directive: raw_directive,
title,
id,
additional_classnames,
collapsible,
} = raw;
@@ -38,25 +40,49 @@ impl AdmonitionMeta {
// Load the directive (and title, if one still not given)
let (directive, title) = match (Directive::from_str(&raw_directive), title) {
(Ok(directive), None) => (directive, ucfirst(&raw_directive)),
(Ok(directive), None) => (directive, format_directive_title(&raw_directive)),
(Err(_), None) => (Directive::Note, "Note".to_owned()),
(Ok(directive), Some(title)) => (directive, title),
(Err(_), Some(title)) => (Directive::Note, title),
};
let css_id = if let Some(verbatim) = id {
CssId::Verbatim(verbatim)
} else {
const DEFAULT_CSS_ID_PREFIX: &str = "admonition-";
CssId::Prefix(
defaults
.css_id_prefix
.clone()
.unwrap_or_else(|| DEFAULT_CSS_ID_PREFIX.to_owned()),
)
};
Self {
directive,
title,
css_id,
additional_classnames,
collapsible,
}
}
}
/// Make the first letter of `input` upppercase.
/// Format the title of an admonition directive
///
/// We special case a few words to make them look nicer (e.g. "tldr" -> "TL;DR" and "faq" -> "FAQ").
fn format_directive_title(input: &str) -> String {
match input {
"tldr" => "TL;DR".to_owned(),
"faq" => "FAQ".to_owned(),
_ => uppercase_first(input),
}
}
/// Make the first letter of `input` uppercase.
///
/// source: https://stackoverflow.com/a/38406885
fn ucfirst(input: &str) -> String {
fn uppercase_first(input: &str) -> String {
let mut chars = input.chars();
match chars.next() {
None => String::new(),
@@ -69,6 +95,18 @@ mod test {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_format_directive_title() {
assert_eq!(format_directive_title(""), "");
assert_eq!(format_directive_title("a"), "A");
assert_eq!(format_directive_title("tldr"), "TL;DR");
assert_eq!(format_directive_title("faq"), "FAQ");
assert_eq!(format_directive_title("note"), "Note");
assert_eq!(format_directive_title("abstract"), "Abstract");
// Unicode
assert_eq!(format_directive_title("🦀"), "🦀");
}
#[test]
fn test_admonition_info_from_raw() {
assert_eq!(
@@ -76,6 +114,7 @@ mod test {
InstanceConfig {
directive: " ".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
},
@@ -84,6 +123,7 @@ mod test {
AdmonitionMeta {
directive: Directive::Note,
title: "Note".to_owned(),
css_id: CssId::Prefix("admonition-".to_owned()),
additional_classnames: Vec::new(),
collapsible: false,
}
@@ -97,17 +137,47 @@ mod test {
InstanceConfig {
directive: " ".to_owned(),
title: None,
id: None,
additional_classnames: Vec::new(),
collapsible: None,
},
&AdmonitionDefaults {
title: Some("Important!!!".to_owned()),
css_id_prefix: Some("custom-prefix-".to_owned()),
collapsible: true,
},
),
AdmonitionMeta {
directive: Directive::Note,
title: "Important!!!".to_owned(),
css_id: CssId::Prefix("custom-prefix-".to_owned()),
additional_classnames: Vec::new(),
collapsible: true,
}
);
}
#[test]
fn test_admonition_info_from_raw_with_defaults_and_custom_id() {
assert_eq!(
AdmonitionMeta::resolve(
InstanceConfig {
directive: " ".to_owned(),
title: None,
id: Some("my-custom-id".to_owned()),
additional_classnames: Vec::new(),
collapsible: None,
},
&AdmonitionDefaults {
title: Some("Important!!!".to_owned()),
css_id_prefix: Some("ignored-custom-prefix-".to_owned()),
collapsible: true,
},
),
AdmonitionMeta {
directive: Directive::Note,
title: "Important!!!".to_owned(),
css_id: CssId::Verbatim("my-custom-id".to_owned()),
additional_classnames: Vec::new(),
collapsible: true,
}

View File

@@ -3,12 +3,16 @@ use std::str::FromStr;
/// Book wide defaults that may be provided by the user.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Default)]
#[serde(rename_all = "kebab-case")]
pub(crate) struct AdmonitionDefaults {
#[serde(default)]
pub(crate) title: Option<String>,
#[serde(default)]
pub(crate) collapsible: bool,
#[serde(default)]
pub(crate) css_id_prefix: Option<String>,
}
#[derive(Debug, PartialEq)]
@@ -54,3 +58,15 @@ pub(crate) enum RenderTextMode {
Strip,
Html,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum CssId {
/// id="my-id" in the admonishment
///
/// used directly for the id field
Verbatim(String),
/// the prefix from default.css_id_prefix (or "admonish-" if not specified)
///
/// will generate the rest of the id based on the title
Prefix(String),
}