summaryrefslogtreecommitdiffstats
path: root/widget/src/markdown.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector@hecrj.dev>2024-07-21 17:18:53 +0200
committerLibravatar GitHub <noreply@github.com>2024-07-21 17:18:53 +0200
commit5443e4d8289873895587d856dbcf46f980bda6ab (patch)
tree4f0037c07349ba0f1ea3e3ace596d988d9c3d952 /widget/src/markdown.rs
parent4b44079f34aa9e01977a7974e5f49ae79ff6cd90 (diff)
parenta2943798a3cf79e15344063fbf4ea8c84d261d6f (diff)
downloadiced-5443e4d8289873895587d856dbcf46f980bda6ab.tar.gz
iced-5443e4d8289873895587d856dbcf46f980bda6ab.tar.bz2
iced-5443e4d8289873895587d856dbcf46f980bda6ab.zip
Merge pull request #2512 from iced-rs/feature/rich-text-links
Add `Link` support to `rich_text` widget
Diffstat (limited to 'widget/src/markdown.rs')
-rw-r--r--widget/src/markdown.rs68
1 files changed, 41 insertions, 27 deletions
diff --git a/widget/src/markdown.rs b/widget/src/markdown.rs
index de691a4d..ae4020bc 100644
--- a/widget/src/markdown.rs
+++ b/widget/src/markdown.rs
@@ -14,13 +14,13 @@ use crate::{column, container, rich_text, row, span, text};
#[derive(Debug, Clone)]
pub enum Item {
/// A heading.
- Heading(Vec<text::Span<'static>>),
+ Heading(Vec<text::Span<'static, String>>),
/// A paragraph.
- Paragraph(Vec<text::Span<'static>>),
+ Paragraph(Vec<text::Span<'static, String>>),
/// A code block.
///
/// You can enable the `highlighter` feature for syntax highligting.
- CodeBlock(Vec<text::Span<'static>>),
+ CodeBlock(Vec<text::Span<'static, String>>),
/// A list.
List {
/// The first number of the list, if it is ordered.
@@ -46,7 +46,7 @@ pub fn parse(
let mut emphasis = false;
let mut metadata = false;
let mut table = false;
- let mut link = false;
+ let mut link = None;
let mut lists = Vec::new();
#[cfg(feature = "highlighter")]
@@ -93,8 +93,10 @@ pub fn parse(
emphasis = true;
None
}
- pulldown_cmark::Tag::Link { .. } if !metadata && !table => {
- link = true;
+ pulldown_cmark::Tag::Link { dest_url, .. }
+ if !metadata && !table =>
+ {
+ link = Some(dest_url);
None
}
pulldown_cmark::Tag::List(first_item) if !metadata && !table => {
@@ -150,7 +152,7 @@ pub fn parse(
None
}
pulldown_cmark::TagEnd::Link if !metadata && !table => {
- link = false;
+ link = None;
None
}
pulldown_cmark::TagEnd::Paragraph if !metadata && !table => {
@@ -245,7 +247,11 @@ pub fn parse(
span
};
- let span = span.color_maybe(link.then_some(palette.primary));
+ let span = if let Some(link) = link.as_ref() {
+ span.color(palette.primary).link(link.to_string())
+ } else {
+ span
+ };
spans.push(span);
@@ -272,40 +278,48 @@ pub fn parse(
/// You can obtain the items with [`parse`].
pub fn view<'a, Message, Renderer>(
items: impl IntoIterator<Item = &'a Item>,
+ on_link: impl Fn(String) -> Message + Copy + 'a,
) -> Element<'a, Message, Theme, Renderer>
where
Message: 'a,
Renderer: core::text::Renderer<Font = Font> + 'a,
{
let blocks = items.into_iter().enumerate().map(|(i, item)| match item {
- Item::Heading(heading) => container(rich_text(heading))
- .padding(padding::top(if i > 0 { 8 } else { 0 }))
- .into(),
- Item::Paragraph(paragraph) => rich_text(paragraph).into(),
- Item::List { start: None, items } => column(
- items
- .iter()
- .map(|items| row!["•", view(items)].spacing(10).into()),
- )
- .spacing(10)
- .into(),
+ Item::Heading(heading) => {
+ container(rich_text(heading).on_link(on_link))
+ .padding(padding::top(if i > 0 { 8 } else { 0 }))
+ .into()
+ }
+ Item::Paragraph(paragraph) => {
+ rich_text(paragraph).on_link(on_link).into()
+ }
+ Item::List { start: None, items } => {
+ column(items.iter().map(|items| {
+ row!["•", view(items, on_link)].spacing(10).into()
+ }))
+ .spacing(10)
+ .into()
+ }
Item::List {
start: Some(start),
items,
} => column(items.iter().enumerate().map(|(i, items)| {
- row![text!("{}.", i as u64 + *start), view(items)]
+ row![text!("{}.", i as u64 + *start), view(items, on_link)]
.spacing(10)
.into()
}))
.spacing(10)
.into(),
- Item::CodeBlock(code) => {
- container(rich_text(code).font(Font::MONOSPACE).size(12))
- .width(Length::Fill)
- .padding(10)
- .style(container::rounded_box)
- .into()
- }
+ Item::CodeBlock(code) => container(
+ rich_text(code)
+ .font(Font::MONOSPACE)
+ .size(12)
+ .on_link(on_link),
+ )
+ .width(Length::Fill)
+ .padding(10)
+ .style(container::rounded_box)
+ .into(),
});
Element::new(column(blocks).width(Length::Fill).spacing(16))