diff --git a/core/src/text.rs b/core/src/text.rs index 68c586f17a..436fee9ac7 100644 --- a/core/src/text.rs +++ b/core/src/text.rs @@ -247,6 +247,8 @@ pub struct Span<'a, Link = (), Font = crate::Font> { pub padding: Padding, /// Whether the [`Span`] should be underlined or not. pub underline: bool, + /// Whether the [`Span`] should be struck through or not. + pub strikethrough: bool, } /// A text highlight. @@ -271,6 +273,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> { link: None, padding: Padding::ZERO, underline: false, + strikethrough: false, } } @@ -395,6 +398,12 @@ impl<'a, Link, Font> Span<'a, Link, Font> { self } + /// Sets whether the [`Span`] shoud be struck through or not. + pub fn strikethrough(mut self, strikethrough: bool) -> Self { + self.strikethrough = strikethrough; + self + } + /// Turns the [`Span`] into a static one. pub fn to_static(self) -> Span<'static, Link, Font> { Span { @@ -407,6 +416,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> { highlight: self.highlight, padding: self.padding, underline: self.underline, + strikethrough: self.strikethrough, } } } diff --git a/widget/src/markdown.rs b/widget/src/markdown.rs index 9cd4a62ff6..23e3643532 100644 --- a/widget/src/markdown.rs +++ b/widget/src/markdown.rs @@ -47,6 +47,7 @@ pub fn parse( let mut spans = Vec::new(); let mut strong = false; let mut emphasis = false; + let mut strikethrough = false; let mut metadata = false; let mut table = false; let mut link = None; @@ -59,7 +60,8 @@ pub fn parse( markdown, pulldown_cmark::Options::ENABLE_YAML_STYLE_METADATA_BLOCKS | pulldown_cmark::Options::ENABLE_PLUSES_DELIMITED_METADATA_BLOCKS - | pulldown_cmark::Options::ENABLE_TABLES, + | pulldown_cmark::Options::ENABLE_TABLES + | pulldown_cmark::Options::ENABLE_STRIKETHROUGH, ); let produce = |lists: &mut Vec, item| { @@ -90,6 +92,10 @@ pub fn parse( emphasis = true; None } + pulldown_cmark::Tag::Strikethrough if !metadata && !table => { + strikethrough = true; + None + } pulldown_cmark::Tag::Link { dest_url, .. } if !metadata && !table => { @@ -155,12 +161,16 @@ pub fn parse( Item::Heading(level, spans.drain(..).collect()), ) } + pulldown_cmark::TagEnd::Strong if !metadata && !table => { + strong = false; + None + } pulldown_cmark::TagEnd::Emphasis if !metadata && !table => { emphasis = false; None } - pulldown_cmark::TagEnd::Strong if !metadata && !table => { - strong = false; + pulldown_cmark::TagEnd::Strikethrough if !metadata && !table => { + strikethrough = false; None } pulldown_cmark::TagEnd::Link if !metadata && !table => { @@ -227,7 +237,7 @@ pub fn parse( return None; } - let span = span(text.into_string()); + let span = span(text.into_string()).strikethrough(strikethrough); let span = if strong || emphasis { span.font(Font { @@ -263,7 +273,8 @@ pub fn parse( .color(Color::WHITE) .background(color!(0x111111)) .border(border::rounded(2)) - .padding(padding::left(2).right(2)); + .padding(padding::left(2).right(2)) + .strikethrough(strikethrough); let span = if let Some(link) = link.as_ref() { span.color(palette.primary).link(link.clone()) @@ -275,7 +286,7 @@ pub fn parse( None } pulldown_cmark::Event::SoftBreak if !metadata && !table => { - spans.push(span(" ")); + spans.push(span(" ").strikethrough(strikethrough)); None } pulldown_cmark::Event::HardBreak if !metadata && !table => { diff --git a/widget/src/text/rich.rs b/widget/src/text/rich.rs index 096056d43a..c6aa1e1449 100644 --- a/widget/src/text/rich.rs +++ b/widget/src/text/rich.rs @@ -254,7 +254,11 @@ where let is_hovered_link = span.link.is_some() && Some(index) == hovered_span; - if span.highlight.is_some() || span.underline || is_hovered_link { + if span.highlight.is_some() + || span.underline + || span.strikethrough + || is_hovered_link + { let translation = layout.position() - Point::ORIGIN; let regions = state.paragraph.span_bounds(index); @@ -284,7 +288,7 @@ where } } - if span.underline || is_hovered_link { + if span.underline || span.strikethrough || is_hovered_link { let size = span .size .or(self.size) @@ -295,27 +299,47 @@ where .unwrap_or(self.line_height) .to_absolute(size); - for bounds in regions { - renderer.fill_quad( - renderer::Quad { - bounds: Rectangle::new( - bounds.position() - + translation - + Vector::new( - 0.0, - size.0 - + (line_height.0 - size.0) - / 2.0 - - size.0 * 0.08, - ), - Size::new(bounds.width, 1.0), - ), - ..Default::default() - }, - span.color - .or(style.color) - .unwrap_or(defaults.text_color), + let color = span + .color + .or(style.color) + .unwrap_or(defaults.text_color); + + let baseline = translation + + Vector::new( + 0.0, + size.0 + (line_height.0 - size.0) / 2.0, ); + + if span.underline || is_hovered_link { + for bounds in ®ions { + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle::new( + bounds.position() + baseline + - Vector::new(0.0, size.0 * 0.08), + Size::new(bounds.width, 1.0), + ), + ..Default::default() + }, + color, + ); + } + } + + if span.strikethrough { + for bounds in ®ions { + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle::new( + bounds.position() + baseline + - Vector::new(0.0, size.0 / 2.0), + Size::new(bounds.width, 1.0), + ), + ..Default::default() + }, + color, + ); + } } } }