From b25fa12b82e56b81bffb0e4fd294a2ee7da7de52 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sat, 3 May 2025 13:20:49 -0700 Subject: [PATCH] fix: allow interleaved spans and variables in footer --- src/ui/footer.rs | 54 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/src/ui/footer.rs b/src/ui/footer.rs index 332dbd3..49d18ac 100644 --- a/src/ui/footer.rs +++ b/src/ui/footer.rs @@ -178,10 +178,9 @@ impl FooterLine { palette: &ColorPalette, ) -> Result { use FooterTemplateChunk::*; - let mut line = Line::default(); let FooterVariables { current_slide, total_slides, author, title, sub_title, event, location, date } = vars; let arena = Arena::default(); - let parser = MarkdownParser::new(&arena); + let mut reassembled = String::new(); for chunk in template.0 { let raw_text = match chunk { CurrentSlide => Cow::Owned(current_slide.to_string()), @@ -199,20 +198,22 @@ impl FooterLine { if raw_text.lines().count() != 1 { return Err(InvalidFooterTemplateError::NoNewlines); } - let starting_length = raw_text.len(); - let raw_text = raw_text.trim_start(); - let left_whitespace = starting_length - raw_text.len(); - let raw_text = raw_text.trim_end(); - let right_whitespace = starting_length - raw_text.len() - left_whitespace; - let inlines = parser.parse_inlines(raw_text)?; - let mut contents = inlines.resolve(palette)?; - if left_whitespace != 0 { - contents.0.insert(0, " ".repeat(left_whitespace).into()); - } - if right_whitespace != 0 { - contents.0.push(" ".repeat(right_whitespace).into()); - } - line.0.extend(contents.0); + reassembled.push_str(&raw_text); + } + // Inline parsing loses leading/trailing whitespaces so re-add them ourselves + let starting_length = reassembled.len(); + let raw_text = reassembled.trim_start(); + let left_whitespace = starting_length - raw_text.len(); + let raw_text = raw_text.trim_end(); + let right_whitespace = starting_length - raw_text.len() - left_whitespace; + let parser = MarkdownParser::new(&arena); + let inlines = parser.parse_inlines(&reassembled)?; + let mut line = inlines.resolve(palette)?; + if left_whitespace != 0 { + line.0.insert(0, " ".repeat(left_whitespace).into()); + } + if right_whitespace != 0 { + line.0.push(" ".repeat(right_whitespace).into()); } line.apply_style(style); Ok(Self(line)) @@ -320,4 +321,25 @@ mod tests { let template = FooterTemplate(vec![chunk]); FooterLine::new(template, &Default::default(), &VARIABLES, &PALETTE).expect_err("render succeeded"); } + + #[test] + fn interleaved_spans() { + let chunks = vec![ + FooterTemplateChunk::Literal("".into()), + FooterTemplateChunk::CurrentSlide, + FooterTemplateChunk::Literal(" / ".into()), + FooterTemplateChunk::TotalSlides, + FooterTemplateChunk::Literal("".into()), + FooterTemplateChunk::Literal("".into()), + FooterTemplateChunk::Title, + FooterTemplateChunk::Literal("".into()), + ]; + let template = FooterTemplate(chunks); + let line = FooterLine::new(template, &Default::default(), &VARIABLES, &PALETTE).expect("render failed"); + let expected = &[ + Text::new("1 / 5", TextStyle::default().fg_color(Color::new(255, 0, 0))), + Text::new("hi", TextStyle::default().fg_color(Color::Green)), + ]; + assert_eq!(line.0.0, expected); + } }