From 4d357442af2f4e05d5d0afbe6b1e8003c0638e04 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 12 Jul 2024 15:41:11 -0600 Subject: [PATCH] infra: support non-numbered and no-caption listings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When I originally built this, I thought *all* “listings” had numbers and captions, but it turns out that there are a number of places in the book where having the overall `figure`-driven output, i.e. with a file name, is desirable even though there is no number or caption. A potential enhancement later would be to require a caption if a number is present, since that seems to be what the book actually does. --- packages/mdbook-trpl-listing/src/lib.rs | 108 +++++++++--------- packages/mdbook-trpl-listing/src/tests/mod.rs | 27 +++++ 2 files changed, 79 insertions(+), 56 deletions(-) diff --git a/packages/mdbook-trpl-listing/src/lib.rs b/packages/mdbook-trpl-listing/src/lib.rs index 8f203645bc..3d8eabcf49 100644 --- a/packages/mdbook-trpl-listing/src/lib.rs +++ b/packages/mdbook-trpl-listing/src/lib.rs @@ -155,7 +155,7 @@ fn rewrite_listing(src: &str, mode: Mode) -> Result { match ev { Event::Html(tag) => { if tag.starts_with(" Result { }) .build(); - match listing_result { - Ok(listing) => { - let opening_event = match mode { - Mode::Default => { - let opening_html = - listing.opening_html(); - Event::Html(opening_html.into()) - } - Mode::Simple => { - let opening_text = - listing.opening_text(); - Event::Text(opening_text.into()) - } - }; - - state.current_listing = Some(listing); - state.events.push(Ok(opening_event)); + let opening_event = match mode { + Mode::Default => { + let opening_html = listing.opening_html(); + Event::Html(opening_html.into()) } - Err(reason) => state.events.push(Err(reason)), - } + Mode::Simple => { + let opening_text = listing.opening_text(); + Event::Text(opening_text.into()) + } + }; + + state.current_listing = Some(listing); + state.events.push(Ok(opening_event)); } else if tag.starts_with("") { let trailing = if !tag.ends_with('>') { tag.replace("", "") @@ -259,8 +252,8 @@ fn rewrite_listing(src: &str, mode: Mode) -> Result { #[derive(Debug)] struct Listing { - number: String, - caption: String, + number: Option, + caption: Option, file_name: Option, } @@ -277,12 +270,21 @@ impl Listing { } fn closing_html(&self, trailing: &str) -> String { - format!( - r#"
Listing {number}: {caption}
-{trailing}"#, - number = self.number, - caption = self.caption - ) + match (&self.number, &self.caption) { + (Some(number), Some(caption)) => format!( + r#"
Listing {number}: {caption}
+{trailing}"# + ), + (None, Some(caption)) => format!( + r#"
{caption}
+{trailing}"# + ), + (Some(number), None) => format!( + r#"
Listing {number}
+{trailing}"# + ), + (None, None) => format!("{trailing}"), + } } fn opening_text(&self) -> String { @@ -293,11 +295,14 @@ impl Listing { } fn closing_text(&self, trailing: &str) -> String { - format!( - "Listing {number}: {caption}{trailing}", - number = self.number, - caption = self.caption, - ) + match (&self.number, &self.caption) { + (Some(number), Some(caption)) => { + format!("Listing {number}: {caption}{trailing}") + } + (None, Some(caption)) => format!("{caption}{trailing}"), + (Some(number), None) => format!("Listing {number}{trailing}"), + (None, None) => trailing.into(), + } } } @@ -331,32 +336,23 @@ impl<'a> ListingBuilder<'a> { self } - fn build(self) -> Result { - let number = self - .number - .ok_or_else(|| String::from("Missing number"))? - .to_owned(); - - let caption = self - .caption - .map(|caption_source| { - let events = new_cmark_parser(caption_source, true); - let mut buf = String::with_capacity(caption_source.len() * 2); - html::push_html(&mut buf, events); - - // This is not particularly principled, but since the only - // place it is used is here, for caption source handling, it - // is “fine”. - buf.replace("

", "").replace("

", "").replace('\n', "") - }) - .ok_or_else(|| String::from("Missing caption"))? - .to_owned(); + fn build(self) -> Listing { + let caption = self.caption.map(|caption_source| { + let events = new_cmark_parser(caption_source, true); + let mut buf = String::with_capacity(caption_source.len() * 2); + html::push_html(&mut buf, events); - Ok(Listing { - number, + // This is not particularly principled, but since the only + // place it is used is here, for caption source handling, it + // is “fine”. + buf.replace("

", "").replace("

", "").replace('\n', "") + }); + + Listing { + number: self.number.map(String::from), caption, file_name: self.file_name.map(String::from), - }) + } } } diff --git a/packages/mdbook-trpl-listing/src/tests/mod.rs b/packages/mdbook-trpl-listing/src/tests/mod.rs index 1e1240e855..71407581b7 100644 --- a/packages/mdbook-trpl-listing/src/tests/mod.rs +++ b/packages/mdbook-trpl-listing/src/tests/mod.rs @@ -131,5 +131,32 @@ This is the closing."# ); } +#[test] +fn without_number() { + let result = rewrite_listing( + r#"+ +```rust +fn main() {} +``` + +"#, + Mode::Default, + ); + + assert!(result.is_ok()); + assert_eq!( + result.unwrap(), + r#"
+Filename: src/main.rs + +````rust +fn main() {} +```` + +
"# + ); +} + #[cfg(test)] mod config;