From 0b50fd68bae479873f6aa7a815fef3edea16eade Mon Sep 17 00:00:00 2001 From: Tom Milligan Date: Mon, 21 Feb 2022 18:26:33 +0000 Subject: [PATCH] feat: remove title bar if title empty --- CHANGELOG.md | 1 + README.md | 20 +++-- img/no-title-bar.png | Bin 0 -> 6832 bytes integration/expected/chapter_1_main.html | 5 ++ integration/src/chapter_1.md | 4 + src/lib.rs | 91 +++++++++++++++-------- 6 files changed, 82 insertions(+), 39 deletions(-) create mode 100644 img/no-title-bar.png 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 @@ [![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-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. ![Data Loss](img/data-loss.png) +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. +``` +```` + +![No Title Bar](img/no-title-bar.png) + #### 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, ![Complex Message](img/complex-message.png) -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 0000000000000000000000000000000000000000..5bb99a112152b227c80b8df7ddf1893e27a22a28 GIT binary patch literal 6832 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

?gRVcFMkq1`2<{v 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 literal 0 HcmV?d00001 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

+
+
+

No title, only body

+
+
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#" + +
+
+ + +
"#;