diff options
author | 2024-07-21 12:45:05 +0200 | |
---|---|---|
committer | 2024-07-21 12:45:05 +0200 | |
commit | 9bfaf2840cffe35d689bd115a308d21961ab082a (patch) | |
tree | c9a7b4fc04607c3315dabe3ad2527251b0a3dff8 /widget/src/markdown.rs | |
parent | 4b44079f34aa9e01977a7974e5f49ae79ff6cd90 (diff) | |
download | iced-9bfaf2840cffe35d689bd115a308d21961ab082a.tar.gz iced-9bfaf2840cffe35d689bd115a308d21961ab082a.tar.bz2 iced-9bfaf2840cffe35d689bd115a308d21961ab082a.zip |
Add `Link` support to `rich_text` widget
Diffstat (limited to 'widget/src/markdown.rs')
-rw-r--r-- | widget/src/markdown.rs | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/widget/src/markdown.rs b/widget/src/markdown.rs index de691a4d..dc207a34 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_click: 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_click(on_link_click)) + .padding(padding::top(if i > 0 { 8 } else { 0 })) + .into() + } + Item::Paragraph(paragraph) => { + rich_text(paragraph).on_link_click(on_link_click).into() + } + Item::List { start: None, items } => { + column(items.iter().map(|items| { + row!["•", view(items, on_link_click)].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_click)] .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_click(on_link_click), + ) + .width(Length::Fill) + .padding(10) + .style(container::rounded_box) + .into(), }); Element::new(column(blocks).width(Length::Fill).spacing(16)) |