Merge pull request #2528 from iced-rs/feature/rich-text-strikethrough

Strikethrough support for `rich_text`
This commit is contained in:
Héctor Ramón 2024-07-28 18:01:23 +02:00 committed by GitHub
commit 7445b97df5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 73 additions and 28 deletions

View file

@ -247,6 +247,8 @@ pub struct Span<'a, Link = (), Font = crate::Font> {
pub padding: Padding, pub padding: Padding,
/// Whether the [`Span`] should be underlined or not. /// Whether the [`Span`] should be underlined or not.
pub underline: bool, pub underline: bool,
/// Whether the [`Span`] should be struck through or not.
pub strikethrough: bool,
} }
/// A text highlight. /// A text highlight.
@ -271,6 +273,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
link: None, link: None,
padding: Padding::ZERO, padding: Padding::ZERO,
underline: false, underline: false,
strikethrough: false,
} }
} }
@ -395,6 +398,12 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
self 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. /// Turns the [`Span`] into a static one.
pub fn to_static(self) -> Span<'static, Link, Font> { pub fn to_static(self) -> Span<'static, Link, Font> {
Span { Span {
@ -407,6 +416,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
highlight: self.highlight, highlight: self.highlight,
padding: self.padding, padding: self.padding,
underline: self.underline, underline: self.underline,
strikethrough: self.strikethrough,
} }
} }
} }

View file

@ -47,6 +47,7 @@ pub fn parse(
let mut spans = Vec::new(); let mut spans = Vec::new();
let mut strong = false; let mut strong = false;
let mut emphasis = false; let mut emphasis = false;
let mut strikethrough = false;
let mut metadata = false; let mut metadata = false;
let mut table = false; let mut table = false;
let mut link = None; let mut link = None;
@ -59,7 +60,8 @@ pub fn parse(
markdown, markdown,
pulldown_cmark::Options::ENABLE_YAML_STYLE_METADATA_BLOCKS pulldown_cmark::Options::ENABLE_YAML_STYLE_METADATA_BLOCKS
| pulldown_cmark::Options::ENABLE_PLUSES_DELIMITED_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<List>, item| { let produce = |lists: &mut Vec<List>, item| {
@ -90,6 +92,10 @@ pub fn parse(
emphasis = true; emphasis = true;
None None
} }
pulldown_cmark::Tag::Strikethrough if !metadata && !table => {
strikethrough = true;
None
}
pulldown_cmark::Tag::Link { dest_url, .. } pulldown_cmark::Tag::Link { dest_url, .. }
if !metadata && !table => if !metadata && !table =>
{ {
@ -155,12 +161,16 @@ pub fn parse(
Item::Heading(level, spans.drain(..).collect()), Item::Heading(level, spans.drain(..).collect()),
) )
} }
pulldown_cmark::TagEnd::Strong if !metadata && !table => {
strong = false;
None
}
pulldown_cmark::TagEnd::Emphasis if !metadata && !table => { pulldown_cmark::TagEnd::Emphasis if !metadata && !table => {
emphasis = false; emphasis = false;
None None
} }
pulldown_cmark::TagEnd::Strong if !metadata && !table => { pulldown_cmark::TagEnd::Strikethrough if !metadata && !table => {
strong = false; strikethrough = false;
None None
} }
pulldown_cmark::TagEnd::Link if !metadata && !table => { pulldown_cmark::TagEnd::Link if !metadata && !table => {
@ -227,7 +237,7 @@ pub fn parse(
return None; return None;
} }
let span = span(text.into_string()); let span = span(text.into_string()).strikethrough(strikethrough);
let span = if strong || emphasis { let span = if strong || emphasis {
span.font(Font { span.font(Font {
@ -263,7 +273,8 @@ pub fn parse(
.color(Color::WHITE) .color(Color::WHITE)
.background(color!(0x111111)) .background(color!(0x111111))
.border(border::rounded(2)) .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() { let span = if let Some(link) = link.as_ref() {
span.color(palette.primary).link(link.clone()) span.color(palette.primary).link(link.clone())
@ -275,7 +286,7 @@ pub fn parse(
None None
} }
pulldown_cmark::Event::SoftBreak if !metadata && !table => { pulldown_cmark::Event::SoftBreak if !metadata && !table => {
spans.push(span(" ")); spans.push(span(" ").strikethrough(strikethrough));
None None
} }
pulldown_cmark::Event::HardBreak if !metadata && !table => { pulldown_cmark::Event::HardBreak if !metadata && !table => {

View file

@ -254,7 +254,11 @@ where
let is_hovered_link = let is_hovered_link =
span.link.is_some() && Some(index) == hovered_span; 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 translation = layout.position() - Point::ORIGIN;
let regions = state.paragraph.span_bounds(index); 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 let size = span
.size .size
.or(self.size) .or(self.size)
@ -295,29 +299,49 @@ where
.unwrap_or(self.line_height) .unwrap_or(self.line_height)
.to_absolute(size); .to_absolute(size);
for bounds in regions { 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 &regions {
renderer.fill_quad( renderer.fill_quad(
renderer::Quad { renderer::Quad {
bounds: Rectangle::new( bounds: Rectangle::new(
bounds.position() bounds.position() + baseline
+ translation - Vector::new(0.0, size.0 * 0.08),
+ Vector::new(
0.0,
size.0
+ (line_height.0 - size.0)
/ 2.0
- size.0 * 0.08,
),
Size::new(bounds.width, 1.0), Size::new(bounds.width, 1.0),
), ),
..Default::default() ..Default::default()
}, },
span.color color,
.or(style.color)
.unwrap_or(defaults.text_color),
); );
} }
} }
if span.strikethrough {
for bounds in &regions {
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,
);
}
}
}
} }
} }