Skip to content

Commit 39a148f

Browse files
authored
Merge pull request #2851 from ehuss/admonitions
Add support for admonitions
2 parents 604d4dd + 873e4fe commit 39a148f

File tree

16 files changed

+314
-36
lines changed

16 files changed

+314
-36
lines changed

crates/mdbook-core/src/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ pub struct HtmlConfig {
436436
pub smart_punctuation: bool,
437437
/// Support for definition lists.
438438
pub definition_lists: bool,
439+
/// Support for admonitions.
440+
pub admonitions: bool,
439441
/// Should mathjax be enabled?
440442
pub mathjax_support: bool,
441443
/// Additional CSS stylesheets to include in the rendered page's `<head>`.
@@ -504,6 +506,7 @@ impl Default for HtmlConfig {
504506
preferred_dark_theme: None,
505507
smart_punctuation: true,
506508
definition_lists: true,
509+
admonitions: true,
507510
mathjax_support: false,
508511
additional_css: Vec::new(),
509512
additional_js: Vec::new(),

crates/mdbook-html/front-end/css/general.css

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ blockquote {
156156
border-block-end: .1em solid var(--quote-border);
157157
}
158158

159+
/* TODO: Remove .warning in a future version of mdbook, it is replaced by
160+
blockquote tags. */
159161
.warning {
160162
margin: 20px;
161163
padding: 0 20px;
@@ -324,3 +326,83 @@ dd > p {
324326
space before the definition. */
325327
margin-top: 0;
326328
}
329+
330+
/* Remove some excess space from the bottom. */
331+
.blockquote-tag p:last-child {
332+
margin-bottom: 2px;
333+
}
334+
335+
.blockquote-tag {
336+
/* Add some padding to make the vertical bar a little taller than the text.*/
337+
padding: 2px 0px 2px 20px;
338+
/* Add a solid color bar on the left side. */
339+
border-inline-start-style: solid;
340+
border-inline-start-width: 4px;
341+
/* Disable the background color from normal blockquotes . */
342+
background-color: inherit;
343+
/* Disable border blocks from blockquotes. */
344+
border-block-start: none;
345+
border-block-end: none;
346+
}
347+
348+
.blockquote-tag-title svg {
349+
fill: currentColor;
350+
/* Add space between the icon and the title. */
351+
margin-right: 8px;
352+
}
353+
354+
.blockquote-tag-note {
355+
border-inline-start-color: var(--blockquote-note-color);
356+
}
357+
358+
.blockquote-tag-tip {
359+
border-inline-start-color: var(--blockquote-tip-color);
360+
}
361+
362+
.blockquote-tag-important {
363+
border-inline-start-color: var(--blockquote-important-color);
364+
}
365+
366+
.blockquote-tag-warning {
367+
border-inline-start-color: var(--blockquote-warning-color);
368+
}
369+
370+
.blockquote-tag-caution {
371+
border-inline-start-color: var(--blockquote-caution-color);
372+
}
373+
374+
.blockquote-tag-note .blockquote-tag-title {
375+
color: var(--blockquote-note-color);
376+
}
377+
378+
.blockquote-tag-tip .blockquote-tag-title {
379+
color: var(--blockquote-tip-color);
380+
}
381+
382+
.blockquote-tag-important .blockquote-tag-title {
383+
color: var(--blockquote-important-color);
384+
}
385+
386+
.blockquote-tag-warning .blockquote-tag-title {
387+
color: var(--blockquote-warning-color);
388+
}
389+
390+
.blockquote-tag-caution .blockquote-tag-title {
391+
color: var(--blockquote-caution-color);
392+
}
393+
394+
.blockquote-tag-title {
395+
/* Slightly increase the weight for more emphasis. */
396+
font-weight: 600;
397+
/* Vertically center the icon with the text. */
398+
display: flex;
399+
align-items: center;
400+
/* Remove default large margins for a more compact display. */
401+
margin: 2px 0 8px 0;
402+
}
403+
404+
.blockquote-tag-title .fa-svg {
405+
fill: currentColor;
406+
/* Add some space between the icon and the text. */
407+
margin-right: 8px;
408+
}

crates/mdbook-html/front-end/css/variables.css

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@
6767
--footnote-highlight: #2668a6;
6868

6969
--overlay-bg: rgba(33, 40, 48, 0.4);
70+
71+
--blockquote-note-color: #74b9ff;
72+
--blockquote-tip-color: #09ca09;
73+
--blockquote-important-color: #d3abff;
74+
--blockquote-warning-color: #f0b72f;
75+
--blockquote-caution-color: #f21424;
7076
}
7177

7278
.coal {
@@ -120,6 +126,12 @@
120126
--footnote-highlight: #4079ae;
121127

122128
--overlay-bg: rgba(33, 40, 48, 0.4);
129+
130+
--blockquote-note-color: #4493f8;
131+
--blockquote-tip-color: #08ae08;
132+
--blockquote-important-color: #ab7df8;
133+
--blockquote-warning-color: #d29922;
134+
--blockquote-caution-color: #d91b29;
123135
}
124136

125137
.light, html:not(.js) {
@@ -173,6 +185,12 @@
173185
--footnote-highlight: #7e7eff;
174186

175187
--overlay-bg: rgba(200, 200, 205, 0.4);
188+
189+
--blockquote-note-color: #0969da;
190+
--blockquote-tip-color: #008000;
191+
--blockquote-important-color: #8250df;
192+
--blockquote-warning-color: #9a6700;
193+
--blockquote-caution-color: #b52731;
176194
}
177195

178196
.navy {
@@ -226,6 +244,12 @@
226244
--footnote-highlight: #4079ae;
227245

228246
--overlay-bg: rgba(33, 40, 48, 0.4);
247+
248+
--blockquote-note-color: #4493f8;
249+
--blockquote-tip-color: #09ca09;
250+
--blockquote-important-color: #ab7df8;
251+
--blockquote-warning-color: #d29922;
252+
--blockquote-caution-color: #f21424;
229253
}
230254

231255
.rust {
@@ -277,6 +301,12 @@
277301
--footnote-highlight: #d3a17a;
278302

279303
--overlay-bg: rgba(150, 150, 150, 0.25);
304+
305+
--blockquote-note-color: #023b95;
306+
--blockquote-tip-color: #007700;
307+
--blockquote-important-color: #8250df;
308+
--blockquote-warning-color: #603700;
309+
--blockquote-caution-color: #aa1721;
280310
}
281311

282312
@media (prefers-color-scheme: dark) {
@@ -331,5 +361,11 @@
331361
--footnote-highlight: #4079ae;
332362

333363
--overlay-bg: rgba(33, 40, 48, 0.4);
364+
365+
--blockquote-note-color: #4493f8;
366+
--blockquote-tip-color: #08ae08;
367+
--blockquote-important-color: #ab7df8;
368+
--blockquote-warning-color: #d29922;
369+
--blockquote-caution-color: #d91b29;
334370
}
335371
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use pulldown_cmark::BlockQuoteKind;
2+
3+
// This icon is from GitHub, MIT License, see https://github.com/primer/octicons
4+
const ICON_NOTE: &str = r#"<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path>"#;
5+
6+
// This icon is from GitHub, MIT License, see https://github.com/primer/octicons
7+
const ICON_TIP: &str = r#"<path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"></path>"#;
8+
9+
// This icon is from GitHub, MIT License, see https://github.com/primer/octicons
10+
const ICON_IMPORTANT: &str = r#"<path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>"#;
11+
12+
// This icon is from GitHub, MIT License, see https://github.com/primer/octicons
13+
const ICON_WARNING: &str = r#"<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>"#;
14+
15+
// This icon is from GitHub, MIT License, see https://github.com/primer/octicons
16+
const ICON_CAUTION: &str = r#"<path d="M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path>"#;
17+
18+
pub(crate) fn select_tag(kind: BlockQuoteKind) -> (&'static str, &'static str, &'static str) {
19+
match kind {
20+
BlockQuoteKind::Note => ("note", ICON_NOTE, "Note"),
21+
BlockQuoteKind::Tip => ("tip", ICON_TIP, "Tip"),
22+
BlockQuoteKind::Important => ("important", ICON_IMPORTANT, "Important"),
23+
BlockQuoteKind::Warning => ("warning", ICON_WARNING, "Warning"),
24+
BlockQuoteKind::Caution => ("caution", ICON_CAUTION, "Caution"),
25+
}
26+
}

crates/mdbook-html/src/html/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use mdbook_core::config::{HtmlConfig, RustEdition};
1616
use mdbook_markdown::{MarkdownOptions, new_cmark_parser};
1717
use std::path::{Path, PathBuf};
1818

19+
mod admonitions;
1920
mod hide_lines;
2021
mod print;
2122
mod serialize;
@@ -51,6 +52,7 @@ impl<'a> HtmlRenderOptions<'a> {
5152
let mut markdown_options = MarkdownOptions::default();
5253
markdown_options.smart_punctuation = config.smart_punctuation;
5354
markdown_options.definition_lists = config.definition_lists;
55+
markdown_options.admonitions = config.admonitions;
5456
HtmlRenderOptions {
5557
markdown_options,
5658
path,

crates/mdbook-html/src/html/tree.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ use html5ever::{LocalName, QualName};
1515
use indexmap::IndexMap;
1616
use mdbook_core::config::RustEdition;
1717
use mdbook_core::static_regex;
18-
use pulldown_cmark::{
19-
Alignment, BlockQuoteKind, CodeBlockKind, CowStr, Event, LinkType, Tag, TagEnd,
20-
};
18+
use pulldown_cmark::{Alignment, CodeBlockKind, CowStr, Event, LinkType, Tag, TagEnd};
2119
use std::borrow::Cow;
2220
use std::collections::{HashMap, HashSet};
2321
use std::ops::Deref;
@@ -407,14 +405,27 @@ where
407405
Tag::BlockQuote(kind) => {
408406
let mut b = Element::new("blockquote");
409407
if let Some(kind) = kind {
410-
let class = match kind {
411-
BlockQuoteKind::Note => "markdown-alert-note",
412-
BlockQuoteKind::Tip => "markdown-alert-tip",
413-
BlockQuoteKind::Important => "markdown-alert-important",
414-
BlockQuoteKind::Warning => "markdown-alert-warning",
415-
BlockQuoteKind::Caution => "markdown-alert-caution",
416-
};
408+
let (class_kind, icon, text) = super::admonitions::select_tag(kind);
409+
let class = format!("blockquote-tag blockquote-tag-{class_kind}");
417410
b.insert_attr("class", class.into());
411+
self.push(Node::Element(b));
412+
413+
let mut title = Element::new("p");
414+
title.insert_attr("class", "blockquote-tag-title".into());
415+
self.push(Node::Element(title));
416+
417+
let mut svg = Element::new("svg");
418+
svg.insert_attr("viewbox", "0 0 16 16".into());
419+
svg.insert_attr("width", "18".into());
420+
svg.insert_attr("height", "18".into());
421+
self.push(Node::Element(svg));
422+
self.append_html(icon);
423+
self.pop();
424+
425+
self.append(Node::Text(text.into()));
426+
427+
self.pop();
428+
return;
418429
}
419430
b
420431
}

crates/mdbook-markdown/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,18 @@ pub struct MarkdownOptions {
2828
///
2929
/// This is `true` by default.
3030
pub definition_lists: bool,
31+
/// Enables admonitions.
32+
///
33+
/// This is `true` by default.
34+
pub admonitions: bool,
3135
}
3236

3337
impl Default for MarkdownOptions {
3438
fn default() -> MarkdownOptions {
3539
MarkdownOptions {
3640
smart_punctuation: true,
3741
definition_lists: true,
42+
admonitions: true,
3843
}
3944
}
4045
}
@@ -53,5 +58,8 @@ pub fn new_cmark_parser<'text>(text: &'text str, options: &MarkdownOptions) -> P
5358
if options.definition_lists {
5459
opts.insert(Options::ENABLE_DEFINITION_LIST);
5560
}
61+
if options.admonitions {
62+
opts.insert(Options::ENABLE_GFM);
63+
}
5664
Parser::new_ext(text, opts)
5765
}

guide/src/format/configuration/renderers.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ default-theme = "light"
9999
preferred-dark-theme = "navy"
100100
smart-punctuation = true
101101
definition-lists = true
102+
admonitions = true
102103
mathjax-support = false
103104
additional-css = ["custom.css", "custom2.css"]
104105
additional-js = ["custom.js"]
@@ -127,6 +128,7 @@ The following configuration options are available:
127128
See [Smart Punctuation](../markdown.md#smart-punctuation).
128129
Defaults to `true`.
129130
- **definition-lists:** Enables [definition lists](../markdown.md#definition-lists). Defaults to `true`.
131+
- **admonitions:** Enables [admonitions](../markdown.md#admonitions). Defaults to `true`.
130132
- **mathjax-support:** Adds support for [MathJax](../mathjax.md). Defaults to
131133
`false`.
132134
- **additional-css:** If you need to slightly change the appearance of your book

guide/src/format/markdown.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,46 @@ term B
270270
Terms are clickable just like headers, which will set the browser's URL to point directly to that term.
271271

272272
See the [definition lists spec](https://github.com/pulldown-cmark/pulldown-cmark/blob/HEAD/pulldown-cmark/specs/definition_lists.txt) for more information on the specifics of the syntax. See the [Wikipedia guidelines for glossaries](https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Glossaries#General_guidelines_for_writing_glossaries) for some guidelines on how to write a glossary.
273+
274+
### Admonitions
275+
276+
An admonition is a special type of callout or notice block used to highlight important information. It is written as a blockquote with a special tag on the first line.
277+
278+
```md
279+
> [!NOTE]
280+
> General information or additional context.
281+
282+
> [!TIP]
283+
> A helpful suggestion or best practice.
284+
285+
> [!IMPORTANT]
286+
> Key information that shouldn't be missed.
287+
288+
> [!WARNING]
289+
> Critical information that highlights a potential risk.
290+
291+
> [!CAUTION]
292+
> Information about potential issues that require caution.
293+
```
294+
295+
These will render as:
296+
297+
> [!NOTE]
298+
> General information or additional context.
299+
300+
> [!TIP]
301+
> A helpful suggestion or best practice.
302+
303+
> [!IMPORTANT]
304+
> Key information that shouldn't be missed.
305+
306+
> [!WARNING]
307+
> Critical information that highlights a potential risk.
308+
309+
> [!CAUTION]
310+
> Information about potential issues that require caution.
311+
312+
This feature is enabled by default.
313+
To disable it, see the [`output.html.admonitions`] config option.
314+
315+
[`output.html.admonitions`]: configuration/renderers.md#html-renderer-options

guide/src/format/mdbook.md

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -338,32 +338,6 @@ HTML tags with class `hidden` will not be shown.
338338

339339
<div class="hidden">This will not be seen.</div>
340340

341-
### `class="warning"`
342-
343-
To make a warning or similar note stand out, wrap it in a warning div.
344-
345-
```html
346-
<div class="warning">
347-
348-
This is a bad thing that you should pay attention to.
349-
350-
Warning blocks should be used sparingly in documentation, to avoid "warning
351-
fatigue," where people are trained to ignore them because they usually don't
352-
matter for what they're doing.
353-
354-
</div>
355-
```
356-
357-
<div class="warning">
358-
359-
This is a bad thing that you should pay attention to.
360-
361-
Warning blocks should be used sparingly in documentation, to avoid "warning
362-
fatigue," where people are trained to ignore them because they usually don't
363-
matter for what they're doing.
364-
365-
</div>
366-
367341
## Font-Awesome icons
368342

369343
mdBook includes a copy of [Font Awesome Free's](https://fontawesome.com)

0 commit comments

Comments
 (0)