From 987ae0c77c4bb649e5a2b9b1f0cb976e1cb306aa Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 3 May 2025 14:56:08 -0700 Subject: [PATCH 1/6] Move admonition code to a separate file This is intended to help clean things up and isolate the admonition support in a distinct place. --- docs/authoring.md | 2 +- mdbook-spec/src/admonitions.rs | 80 ++++++++++++++++++++++++++++++++++ mdbook-spec/src/lib.rs | 77 +------------------------------- theme/reference.css | 2 +- 4 files changed, 84 insertions(+), 77 deletions(-) create mode 100644 mdbook-spec/src/admonitions.rs diff --git a/docs/authoring.md b/docs/authoring.md index a465309c8..68665e35e 100644 --- a/docs/authoring.md +++ b/docs/authoring.md @@ -182,7 +182,7 @@ Admonitions use a style similar to GitHub-flavored markdown, where the style nam > This is a note. ``` -The color and styling is defined in [`theme/reference.css`](https://github.com/rust-lang/reference/blob/master/theme/reference.css) and the transformation and icons are in [`mdbook-spec/src/lib.rs`](https://github.com/rust-lang/reference/blob/HEAD/mdbook-spec/src/lib.rs). +The color and styling is defined in [`theme/reference.css`](https://github.com/rust-lang/reference/blob/master/theme/reference.css) and the transformation and icons are in [`mdbook-spec/src/admonitions.rs`](https://github.com/rust-lang/reference/blob/HEAD/mdbook-spec/src/admonitions.rs). ## Style diff --git a/mdbook-spec/src/admonitions.rs b/mdbook-spec/src/admonitions.rs new file mode 100644 index 000000000..01624c154 --- /dev/null +++ b/mdbook-spec/src/admonitions.rs @@ -0,0 +1,80 @@ +//! Support for admonitions using markdown blockquotes. + +use crate::{Diagnostics, warn_or_err}; +use mdbook::book::Chapter; +use regex::{Captures, Regex}; +use std::sync::LazyLock; + +/// The Regex for the syntax for blockquotes that have a specific CSS class, +/// like `> [!WARNING]`. +static ADMONITION_RE: LazyLock = LazyLock::new(|| { + Regex::new(r"(?m)^ *> \[!(?[^]]+)\]\n(?
(?: *>.*\n)+)").unwrap() +}); + +/// Converts blockquotes with special headers into admonitions. +/// +/// The blockquote should look something like: +/// +/// ```markdown +/// > [!WARNING] +/// > ... +/// ``` +/// +/// This will add a `
` around the +/// blockquote so that it can be styled differently, and injects an icon. +/// The actual styling needs to be added in the `reference.css` CSS file. +pub fn admonitions(chapter: &Chapter, diag: &mut Diagnostics) -> String { + ADMONITION_RE + .replace_all(&chapter.content, |caps: &Captures<'_>| { + let lower = caps["admon"].to_lowercase(); + let term = to_initial_case(&caps["admon"]); + let blockquote = &caps["blockquote"]; + let initial_spaces = blockquote.chars().position(|ch| ch != ' ').unwrap_or(0); + let space = &blockquote[..initial_spaces]; + if lower.starts_with("edition-") { + let edition = &lower[8..]; + return format!("{space}
\n\ + \n\ + {space}>

\ + {edition} Edition differences

\n\ + {space} >\n\ + {blockquote}\n\ + \n\ + {space}
\n"); + } + + // These icons are from GitHub, MIT License, see https://github.com/primer/octicons + let svg = match lower.as_str() { + "note" => "", + "warning" => "", + _ => { + warn_or_err!( + diag, + "admonition `{lower}` in {:?} is incorrect or not yet supported", + chapter.path.as_ref().unwrap() + ); + "" + } + }; + format!( + "{space}
\n\ + \n\ + {space}>

\ + \ + {svg}\ + {term}

\n\ + {space} >\n\ + {blockquote}\n\ + \n\ + {space}
\n", + ) + }) + .to_string() +} + +fn to_initial_case(s: &str) -> String { + let mut chars = s.chars(); + let first = chars.next().expect("not empty").to_uppercase(); + let rest = chars.as_str().to_lowercase(); + format!("{first}{rest}") +} diff --git a/mdbook-spec/src/lib.rs b/mdbook-spec/src/lib.rs index 0f14819fc..f5799ae0f 100644 --- a/mdbook-spec/src/lib.rs +++ b/mdbook-spec/src/lib.rs @@ -14,17 +14,12 @@ use std::io; use std::ops::Range; use std::path::PathBuf; +mod admonitions; pub mod grammar; mod rules; mod std_links; mod test_links; -/// The Regex for the syntax for blockquotes that have a specific CSS class, -/// like `> [!WARNING]`. -static ADMONITION_RE: Lazy = Lazy::new(|| { - Regex::new(r"(?m)^ *> \[!(?[^]]+)\]\n(?
(?: *>.*\n)+)").unwrap() -}); - /// A primitive regex to find link reference definitions. static MD_LINK_REFERENCE_DEFINITION: Lazy = Lazy::new(|| Regex::new(r"(?m)^\[(?