Implement Quote support in markdown widget
This commit is contained in:
parent
5ad08acd97
commit
ca1bf717b3
3 changed files with 91 additions and 17 deletions
|
|
@ -400,9 +400,9 @@ where
|
|||
Renderer: core::Renderer + 'a,
|
||||
{
|
||||
fn from(
|
||||
column: Container<'a, Message, Theme, Renderer>,
|
||||
container: Container<'a, Message, Theme, Renderer>,
|
||||
) -> Element<'a, Message, Theme, Renderer> {
|
||||
Element::new(column)
|
||||
Element::new(container)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,10 @@ use crate::core::theme;
|
|||
use crate::core::{
|
||||
self, Color, Element, Length, Padding, Pixels, Theme, color,
|
||||
};
|
||||
use crate::{column, container, rich_text, row, scrollable, span, text};
|
||||
use crate::{
|
||||
column, container, rich_text, row, rule, scrollable, span, text,
|
||||
vertical_rule,
|
||||
};
|
||||
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
|
@ -208,6 +211,8 @@ pub enum Item {
|
|||
/// The alternative text of the image.
|
||||
alt: Text,
|
||||
},
|
||||
/// A quote.
|
||||
Quote(Vec<Item>),
|
||||
}
|
||||
|
||||
/// A bunch of parsed Markdown text.
|
||||
|
|
@ -454,6 +459,7 @@ fn parse_with<'a>(
|
|||
) -> impl Iterator<Item = (Item, &'a str, HashSet<String>)> + 'a {
|
||||
enum Scope {
|
||||
List(List),
|
||||
Quote(Vec<Item>),
|
||||
}
|
||||
|
||||
struct List {
|
||||
|
|
@ -524,6 +530,9 @@ fn parse_with<'a>(
|
|||
Scope::List(list) => {
|
||||
list.items.last_mut().expect("item context").push(item);
|
||||
}
|
||||
Scope::Quote(items) => {
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
|
|
@ -605,6 +614,22 @@ fn parse_with<'a>(
|
|||
|
||||
None
|
||||
}
|
||||
pulldown_cmark::Tag::BlockQuote(_kind) if !metadata && !table => {
|
||||
let prev = if spans.is_empty() {
|
||||
None
|
||||
} else {
|
||||
produce(
|
||||
state.borrow_mut(),
|
||||
&mut stack,
|
||||
Item::Paragraph(Text::new(spans.drain(..).collect())),
|
||||
source,
|
||||
)
|
||||
};
|
||||
|
||||
stack.push(Scope::Quote(Vec::new()));
|
||||
|
||||
prev
|
||||
}
|
||||
pulldown_cmark::Tag::CodeBlock(
|
||||
pulldown_cmark::CodeBlockKind::Fenced(language),
|
||||
) if !metadata && !table => {
|
||||
|
|
@ -703,7 +728,9 @@ fn parse_with<'a>(
|
|||
pulldown_cmark::TagEnd::List(_) if !metadata && !table => {
|
||||
let scope = stack.pop()?;
|
||||
|
||||
let Scope::List(list) = scope;
|
||||
let Scope::List(list) = scope else {
|
||||
return None;
|
||||
};
|
||||
|
||||
produce(
|
||||
state.borrow_mut(),
|
||||
|
|
@ -715,6 +742,22 @@ fn parse_with<'a>(
|
|||
source,
|
||||
)
|
||||
}
|
||||
pulldown_cmark::TagEnd::BlockQuote(_kind)
|
||||
if !metadata && !table =>
|
||||
{
|
||||
let scope = stack.pop()?;
|
||||
|
||||
let Scope::Quote(quote) = scope else {
|
||||
return None;
|
||||
};
|
||||
|
||||
produce(
|
||||
state.borrow_mut(),
|
||||
&mut stack,
|
||||
Item::Quote(quote),
|
||||
source,
|
||||
)
|
||||
}
|
||||
pulldown_cmark::TagEnd::Image if !metadata && !table => {
|
||||
let (url, title) = image.take()?;
|
||||
let alt = Text::new(spans.drain(..).collect());
|
||||
|
|
@ -1063,6 +1106,7 @@ where
|
|||
start: Some(start),
|
||||
items,
|
||||
} => viewer.ordered_list(settings, *start, items),
|
||||
Item::Quote(quote) => viewer.quote(settings, quote),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1226,7 +1270,33 @@ where
|
|||
.into()
|
||||
}
|
||||
|
||||
/// A view strategy to display a Markdown [`Item`].j
|
||||
/// Displays a quote using the default look.
|
||||
pub fn quote<'a, Message, Theme, Renderer>(
|
||||
viewer: &impl Viewer<'a, Message, Theme, Renderer>,
|
||||
settings: Settings,
|
||||
contents: &'a [Item],
|
||||
) -> Element<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Message: 'a,
|
||||
Theme: Catalog + 'a,
|
||||
Renderer: core::text::Renderer<Font = Font> + 'a,
|
||||
{
|
||||
row![
|
||||
vertical_rule(4),
|
||||
column(
|
||||
contents
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, content)| item(viewer, settings, content, i)),
|
||||
)
|
||||
.spacing(settings.spacing.0),
|
||||
]
|
||||
.height(Length::Shrink)
|
||||
.spacing(settings.spacing.0)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// A view strategy to display a Markdown [`Item`].
|
||||
pub trait Viewer<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer>
|
||||
where
|
||||
Self: Sized + 'a,
|
||||
|
|
@ -1321,6 +1391,17 @@ where
|
|||
) -> Element<'a, Message, Theme, Renderer> {
|
||||
ordered_list(self, settings, start, items)
|
||||
}
|
||||
|
||||
/// Displays a quote.
|
||||
///
|
||||
/// By default, it call [`quote`].
|
||||
fn quote(
|
||||
&self,
|
||||
settings: Settings,
|
||||
contents: &'a [Item],
|
||||
) -> Element<'a, Message, Theme, Renderer> {
|
||||
quote(self, settings, contents)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -1338,7 +1419,7 @@ where
|
|||
|
||||
/// The theme catalog of Markdown items.
|
||||
pub trait Catalog:
|
||||
container::Catalog + scrollable::Catalog + text::Catalog
|
||||
container::Catalog + scrollable::Catalog + rule::Catalog + text::Catalog
|
||||
{
|
||||
/// The styling class of a Markdown code block.
|
||||
fn code_block<'a>() -> <Self as container::Catalog>::Class<'a>;
|
||||
|
|
|
|||
|
|
@ -134,9 +134,7 @@ where
|
|||
let style = theme.style(&self.class);
|
||||
|
||||
let bounds = if self.is_horizontal {
|
||||
let line_y = (bounds.y + (bounds.height / 2.0)
|
||||
- (style.width as f32 / 2.0))
|
||||
.round();
|
||||
let line_y = (bounds.y + (bounds.height / 2.0)).round();
|
||||
|
||||
let (offset, line_width) = style.fill_mode.fill(bounds.width);
|
||||
let line_x = bounds.x + offset;
|
||||
|
|
@ -145,12 +143,10 @@ where
|
|||
x: line_x,
|
||||
y: line_y,
|
||||
width: line_width,
|
||||
height: style.width as f32,
|
||||
height: bounds.height,
|
||||
}
|
||||
} else {
|
||||
let line_x = (bounds.x + (bounds.width / 2.0)
|
||||
- (style.width as f32 / 2.0))
|
||||
.round();
|
||||
let line_x = (bounds.x + (bounds.width / 2.0)).round();
|
||||
|
||||
let (offset, line_height) = style.fill_mode.fill(bounds.height);
|
||||
let line_y = bounds.y + offset;
|
||||
|
|
@ -158,7 +154,7 @@ where
|
|||
Rectangle {
|
||||
x: line_x,
|
||||
y: line_y,
|
||||
width: style.width as f32,
|
||||
width: bounds.width,
|
||||
height: line_height,
|
||||
}
|
||||
};
|
||||
|
|
@ -192,8 +188,6 @@ where
|
|||
pub struct Style {
|
||||
/// The color of the rule.
|
||||
pub color: Color,
|
||||
/// The width (thickness) of the rule line.
|
||||
pub width: u16,
|
||||
/// The radius of the line corners.
|
||||
pub radius: border::Radius,
|
||||
/// The [`FillMode`] of the rule.
|
||||
|
|
@ -301,7 +295,6 @@ pub fn default(theme: &Theme) -> Style {
|
|||
|
||||
Style {
|
||||
color: palette.background.strong.color,
|
||||
width: 1,
|
||||
radius: 0.0.into(),
|
||||
fill_mode: FillMode::Full,
|
||||
snap: true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue