diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8229d26..30499d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
### Added
- Additional classnames can be specified using `directive.classname` syntax
+- Support removing the title bar entirely
### Fixed
diff --git a/README.md b/README.md
index 8675ee2..df21535 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,7 @@
[](https://crates.io/crates/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-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.
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
Markdown and HTML can be used in the inner content, as you'd expect:
@@ -77,8 +86,7 @@ accomplished with the dereference operator,

-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):
+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):
````
~~~admonish bug
@@ -146,9 +154,7 @@ mdbook path/to/book
### 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.
+**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.
## Development
diff --git a/img/no-title-bar.png b/img/no-title-bar.png
new file mode 100644
index 0000000..5bb99a1
Binary files /dev/null and b/img/no-title-bar.png differ
diff --git a/integration/expected/chapter_1_main.html b/integration/expected/chapter_1_main.html
index d913b1d..c2681ff 100644
--- a/integration/expected/chapter_1_main.html
+++ b/integration/expected/chapter_1_main.html
@@ -16,4 +16,9 @@
Simples
+
diff --git a/integration/src/chapter_1.md b/integration/src/chapter_1.md
index 31fc2ac..79ae27b 100644
--- a/integration/src/chapter_1.md
+++ b/integration/src/chapter_1.md
@@ -9,3 +9,7 @@ It verifies that `mdbook` post-processes our generated HTML in the way we expect
```admonish
Simples
```
+
+```admonish warning ""
+No title, only body
+```
diff --git a/src/lib.rs b/src/lib.rs
index 728e404..c73bea8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -101,45 +101,37 @@ struct AdmonitionInfoRaw<'a> {
#[derive(Debug, PartialEq)]
struct AdmonitionInfo<'a> {
directive: Directive,
- title: Cow<'a, str>,
+ title: Option,
additional_classnames: Option>,
}
-impl<'a> Default for AdmonitionInfo<'a> {
- fn default() -> Self {
- Self {
- directive: Directive::Note,
- title: Cow::Borrowed("Note"),
- additional_classnames: None,
- }
- }
-}
-
-impl<'a> TryFrom> for AdmonitionInfo<'a> {
- type Error = ();
-
- fn try_from(other: AdmonitionInfoRaw<'a>) -> Result {
+impl<'a> From> for AdmonitionInfo<'a> {
+ fn from(other: AdmonitionInfoRaw<'a>) -> Self {
let AdmonitionInfoRaw {
- directive,
+ directive: raw_directive,
title,
additional_classnames,
} = other;
- let title = title
- .map(Cow::Owned)
- .unwrap_or_else(|| Cow::Owned(ucfirst(directive)));
- let directive = Directive::from_str(directive)?;
- Ok(Self {
+ let (directive, title) = match (Directive::from_str(raw_directive), title) {
+ (Ok(directive), None) => (directive, ucfirst(raw_directive)),
+ (Err(_), None) => (Directive::Note, "Note".to_owned()),
+ (Ok(directive), Some(title)) => (directive, title),
+ (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,
title,
additional_classnames,
- })
+ }
}
}
#[derive(Debug, PartialEq)]
struct Admonition<'a> {
directive: Directive,
- title: Cow<'a, str>,
+ title: Option,
content: &'a str,
additional_classnames: Option>,
}
@@ -164,6 +156,20 @@ impl<'a> Admonition<'a> {
let title = &self.title;
let content = &self.content;
+ let title_html = title
+ .as_ref()
+ .map(|title| {
+ Cow::Owned(format!(
+ r#"
+
+{title}
+
+
+"#
+ ))
+ })
+ .unwrap_or(Cow::Borrowed(""));
+
if let Some(additional_classnames) = &self.additional_classnames {
let mut buffer = additional_class.into_owned();
for additional_classname in additional_classnames {
@@ -180,12 +186,7 @@ impl<'a> Admonition<'a> {
// rendered as markdown paragraphs.
format!(
r#"
-
-
-{title}
-
-
-
+{title_html}
{content}
@@ -201,7 +202,7 @@ const ADMONISH_BLOCK_KEYWORD: &str = "admonish";
/// - `None` if this is not an `admonish` block.
/// - `Some(AdmonitionInfoRaw)` if this is an `admonish` block
fn parse_info_string(info_string: &str) -> Option
{
- // 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 {
""
} else {
@@ -230,7 +231,12 @@ fn parse_info_string(info_string: &str) -> Option {
None => (directive, None),
Some((directive, additional_classnames)) => (
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`.
fn parse_admonition<'a>(info_string: &'a str, content: &'a str) -> Option> {
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);
Some(Admonition::new(info, body))
}
@@ -629,6 +635,27 @@ Developers don't want you to know this one weird tip!
Will have bonus classnames
+
+
+"#;
+
+ assert_eq!(expected, preprocess(content).unwrap());
+ }
+
+ #[test]
+ fn block_with_empty_additional_classnames_title_content() {
+ let content = r#"
+```admonish .... ""
+```
+"#;
+
+ let expected = r#"
+
+
"#;