mirror of
https://github.com/tommilligan/mdbook-admonish.git
synced 2025-12-27 10:01:43 -05:00
feat: remove title bar if title empty
This commit is contained in:
committed by
Tom Milligan
parent
d851076cbc
commit
0b50fd68ba
@@ -5,6 +5,7 @@
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Additional classnames can be specified using `directive.classname` syntax
|
- Additional classnames can be specified using `directive.classname` syntax
|
||||||
|
- Support removing the title bar entirely
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -3,8 +3,7 @@
|
|||||||
[](https://crates.io/crates/mdbook-admonish)
|
[](https://crates.io/crates/mdbook-admonish)
|
||||||
[](https://docs.rs/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,
|
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.
|
||||||
based on the [mkdocs-material](https://squidfunk.github.io/mkdocs-material/reference/admonitions/) implementation.
|
|
||||||
|
|
||||||
It turns this:
|
It turns this:
|
||||||
|
|
||||||
@@ -64,6 +63,16 @@ The following steps can lead to irrecoverable data corruption.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
You can also remove the title bar entirely, by specifying the empty string:
|
||||||
|
|
||||||
|
````
|
||||||
|
```admonish success ""
|
||||||
|
This will take a while, go and grab a drink of water.
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
#### Nested Markdown/HTML
|
#### Nested Markdown/HTML
|
||||||
|
|
||||||
Markdown and HTML can be used in the inner content, as you'd expect:
|
Markdown and HTML can be used in the inner content, as you'd expect:
|
||||||
@@ -77,8 +86,7 @@ accomplished with the <span style="color: hotpink">dereference operator</span>,
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
If you have code blocks you want to include in the content,
|
If you have code blocks you want to include in the content, use [tildes for the outer code fence](https://spec.commonmark.org/0.30/#fenced-code-blocks):
|
||||||
use [tildes for the outer code fence](https://spec.commonmark.org/0.30/#fenced-code-blocks):
|
|
||||||
|
|
||||||
````
|
````
|
||||||
~~~admonish bug
|
~~~admonish bug
|
||||||
@@ -146,9 +154,7 @@ mdbook path/to/book
|
|||||||
|
|
||||||
### Updates
|
### Updates
|
||||||
|
|
||||||
**Please note**, when updating your version of `mdbook-admonish`, updated styles
|
**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.
|
||||||
will not be applied unless you rerun `mdbook-admonish install` to update the additional
|
|
||||||
CSS files in your book.
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|||||||
BIN
img/no-title-bar.png
Normal file
BIN
img/no-title-bar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -16,4 +16,9 @@
|
|||||||
<p>Simples</p>
|
<p>Simples</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="admonition warning">
|
||||||
|
<div>
|
||||||
|
<p>No title, only body</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -9,3 +9,7 @@ It verifies that `mdbook` post-processes our generated HTML in the way we expect
|
|||||||
```admonish
|
```admonish
|
||||||
Simples
|
Simples
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```admonish warning ""
|
||||||
|
No title, only body
|
||||||
|
```
|
||||||
|
|||||||
91
src/lib.rs
91
src/lib.rs
@@ -101,45 +101,37 @@ struct AdmonitionInfoRaw<'a> {
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct AdmonitionInfo<'a> {
|
struct AdmonitionInfo<'a> {
|
||||||
directive: Directive,
|
directive: Directive,
|
||||||
title: Cow<'a, str>,
|
title: Option<String>,
|
||||||
additional_classnames: Option<Vec<&'a str>>,
|
additional_classnames: Option<Vec<&'a str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Default for AdmonitionInfo<'a> {
|
impl<'a> From<AdmonitionInfoRaw<'a>> for AdmonitionInfo<'a> {
|
||||||
fn default() -> Self {
|
fn from(other: AdmonitionInfoRaw<'a>) -> Self {
|
||||||
Self {
|
|
||||||
directive: Directive::Note,
|
|
||||||
title: Cow::Borrowed("Note"),
|
|
||||||
additional_classnames: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TryFrom<AdmonitionInfoRaw<'a>> for AdmonitionInfo<'a> {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(other: AdmonitionInfoRaw<'a>) -> Result<Self, ()> {
|
|
||||||
let AdmonitionInfoRaw {
|
let AdmonitionInfoRaw {
|
||||||
directive,
|
directive: raw_directive,
|
||||||
title,
|
title,
|
||||||
additional_classnames,
|
additional_classnames,
|
||||||
} = other;
|
} = other;
|
||||||
let title = title
|
let (directive, title) = match (Directive::from_str(raw_directive), title) {
|
||||||
.map(Cow::Owned)
|
(Ok(directive), None) => (directive, ucfirst(raw_directive)),
|
||||||
.unwrap_or_else(|| Cow::Owned(ucfirst(directive)));
|
(Err(_), None) => (Directive::Note, "Note".to_owned()),
|
||||||
let directive = Directive::from_str(directive)?;
|
(Ok(directive), Some(title)) => (directive, title),
|
||||||
Ok(Self {
|
(Err(_), Some(title)) => (Directive::Note, title),
|
||||||
|
};
|
||||||
|
// If the user explicitly gave no title, then disable the title bar
|
||||||
|
let title = if title.is_empty() { None } else { Some(title) };
|
||||||
|
Self {
|
||||||
directive,
|
directive,
|
||||||
title,
|
title,
|
||||||
additional_classnames,
|
additional_classnames,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct Admonition<'a> {
|
struct Admonition<'a> {
|
||||||
directive: Directive,
|
directive: Directive,
|
||||||
title: Cow<'a, str>,
|
title: Option<String>,
|
||||||
content: &'a str,
|
content: &'a str,
|
||||||
additional_classnames: Option<Vec<&'a str>>,
|
additional_classnames: Option<Vec<&'a str>>,
|
||||||
}
|
}
|
||||||
@@ -164,6 +156,20 @@ impl<'a> Admonition<'a> {
|
|||||||
let title = &self.title;
|
let title = &self.title;
|
||||||
let content = &self.content;
|
let content = &self.content;
|
||||||
|
|
||||||
|
let title_html = title
|
||||||
|
.as_ref()
|
||||||
|
.map(|title| {
|
||||||
|
Cow::Owned(format!(
|
||||||
|
r#"<div class="admonition-title">
|
||||||
|
|
||||||
|
{title}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
"#
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.unwrap_or(Cow::Borrowed(""));
|
||||||
|
|
||||||
if let Some(additional_classnames) = &self.additional_classnames {
|
if let Some(additional_classnames) = &self.additional_classnames {
|
||||||
let mut buffer = additional_class.into_owned();
|
let mut buffer = additional_class.into_owned();
|
||||||
for additional_classname in additional_classnames {
|
for additional_classname in additional_classnames {
|
||||||
@@ -180,12 +186,7 @@ impl<'a> Admonition<'a> {
|
|||||||
// rendered as markdown paragraphs.
|
// rendered as markdown paragraphs.
|
||||||
format!(
|
format!(
|
||||||
r#"<div class="admonition {additional_class}">
|
r#"<div class="admonition {additional_class}">
|
||||||
<div class="admonition-title">
|
{title_html}<div>
|
||||||
|
|
||||||
{title}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
|
|
||||||
{content}
|
{content}
|
||||||
|
|
||||||
@@ -201,7 +202,7 @@ const ADMONISH_BLOCK_KEYWORD: &str = "admonish";
|
|||||||
/// - `None` if this is not an `admonish` block.
|
/// - `None` if this is not an `admonish` block.
|
||||||
/// - `Some(AdmonitionInfoRaw)` if this is an `admonish` block
|
/// - `Some(AdmonitionInfoRaw)` if this is an `admonish` block
|
||||||
fn parse_info_string(info_string: &str) -> Option<AdmonitionInfoRaw> {
|
fn parse_info_string(info_string: &str) -> Option<AdmonitionInfoRaw> {
|
||||||
// Get the rest of the info string if this is an admonitionment
|
// Get the rest of the info string if this is an admonition
|
||||||
let directive_title = if info_string == ADMONISH_BLOCK_KEYWORD {
|
let directive_title = if info_string == ADMONISH_BLOCK_KEYWORD {
|
||||||
""
|
""
|
||||||
} else {
|
} else {
|
||||||
@@ -230,7 +231,12 @@ fn parse_info_string(info_string: &str) -> Option<AdmonitionInfoRaw> {
|
|||||||
None => (directive, None),
|
None => (directive, None),
|
||||||
Some((directive, additional_classnames)) => (
|
Some((directive, additional_classnames)) => (
|
||||||
directive,
|
directive,
|
||||||
Some(additional_classnames.split(CLASSNAME_SEPARATOR).collect()),
|
Some(
|
||||||
|
additional_classnames
|
||||||
|
.split(CLASSNAME_SEPARATOR)
|
||||||
|
.filter(|additional_classname| !additional_classname.is_empty())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -280,7 +286,7 @@ fn extract_admonish_body(content: &str) -> &str {
|
|||||||
/// If the code block is not an admonition, return `None`.
|
/// If the code block is not an admonition, return `None`.
|
||||||
fn parse_admonition<'a>(info_string: &'a str, content: &'a str) -> Option<Admonition<'a>> {
|
fn parse_admonition<'a>(info_string: &'a str, content: &'a str) -> Option<Admonition<'a>> {
|
||||||
let info = parse_info_string(info_string)?;
|
let info = parse_info_string(info_string)?;
|
||||||
let info = AdmonitionInfo::try_from(info).unwrap_or_default();
|
let info = AdmonitionInfo::from(info);
|
||||||
let body = extract_admonish_body(content);
|
let body = extract_admonish_body(content);
|
||||||
Some(Admonition::new(info, body))
|
Some(Admonition::new(info, body))
|
||||||
}
|
}
|
||||||
@@ -629,6 +635,27 @@ Developers don't want you to know this one weird tip!
|
|||||||
|
|
||||||
Will have bonus classnames
|
Will have bonus classnames
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert_eq!(expected, preprocess(content).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_with_empty_additional_classnames_title_content() {
|
||||||
|
let content = r#"
|
||||||
|
```admonish .... ""
|
||||||
|
```
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let expected = r#"
|
||||||
|
|
||||||
|
<div class="admonition note">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"#;
|
"#;
|
||||||
|
|||||||
Reference in New Issue
Block a user