text_view: Fix list item to merge inline paragraphs, and fix paragraphs margin. (#1036)
## Before <img width="1712" alt="image" src="https://github.com/user-attachments/assets/579385e6-a206-45e4-80a1-e1e2cdd6b164" /> ## After <img width="1712" alt="image" src="https://github.com/user-attachments/assets/2f551d22-5662-4c3c-a0e5-5ce9f26e1e66" />
This commit is contained in:
parent
9eb7e10a1d
commit
4075447c63
3 changed files with 91 additions and 57 deletions
|
|
@ -201,6 +201,25 @@ impl Paragraph {
|
||||||
Self::Image { .. } => 1,
|
Self::Image { .. } => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to merge two paragraphs, if they are both text elements.
|
||||||
|
///
|
||||||
|
/// - Returns `true` if other have merge into self.
|
||||||
|
/// - Returns `false` if not able to merge.
|
||||||
|
pub fn try_merge(&mut self, other: &Self) -> bool {
|
||||||
|
if let Self::Texts { children, .. } = self {
|
||||||
|
if let Self::Texts {
|
||||||
|
children: other_children,
|
||||||
|
..
|
||||||
|
} = other
|
||||||
|
{
|
||||||
|
children.extend(other_children.clone());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
@ -262,15 +281,10 @@ pub enum Node {
|
||||||
html: bool,
|
html: bool,
|
||||||
},
|
},
|
||||||
Divider,
|
Divider,
|
||||||
Ignore,
|
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
pub(super) fn is_ignore(&self) -> bool {
|
|
||||||
matches!(self, Self::Ignore)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn is_list_item(&self) -> bool {
|
pub(super) fn is_list_item(&self) -> bool {
|
||||||
matches!(self, Self::ListItem { .. })
|
matches!(self, Self::ListItem { .. })
|
||||||
}
|
}
|
||||||
|
|
@ -283,11 +297,7 @@ impl Node {
|
||||||
pub(super) fn compact(&self) -> Node {
|
pub(super) fn compact(&self) -> Node {
|
||||||
match self {
|
match self {
|
||||||
Self::Root { children } => {
|
Self::Root { children } => {
|
||||||
let children = children
|
let children = children.iter().map(|c| c.compact()).collect::<Vec<_>>();
|
||||||
.iter()
|
|
||||||
.map(|c| c.compact())
|
|
||||||
.filter(|c| !c.is_ignore())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
if children.len() == 1 {
|
if children.len() == 1 {
|
||||||
children.first().unwrap().compact()
|
children.first().unwrap().compact()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -310,7 +320,13 @@ impl RenderOnce for Paragraph {
|
||||||
|
|
||||||
for text_node in children.into_iter() {
|
for text_node in children.into_iter() {
|
||||||
let text_len = text_node.text.len();
|
let text_len = text_node.text.len();
|
||||||
text.push_str(&text_node.text);
|
let part = if text.len() == 0 {
|
||||||
|
// trim start for first text
|
||||||
|
text_node.text.trim_start()
|
||||||
|
} else {
|
||||||
|
text_node.text.as_str()
|
||||||
|
};
|
||||||
|
text.push_str(&part);
|
||||||
|
|
||||||
let mut node_highlights = vec![];
|
let mut node_highlights = vec![];
|
||||||
for (range, style) in text_node.marks {
|
for (range, style) in text_node.marks {
|
||||||
|
|
@ -421,6 +437,7 @@ impl Node {
|
||||||
ordered: state.ordered,
|
ordered: state.ordered,
|
||||||
todo: checked.is_some(),
|
todo: checked.is_some(),
|
||||||
}),
|
}),
|
||||||
|
false,
|
||||||
true,
|
true,
|
||||||
text_view_style,
|
text_view_style,
|
||||||
window,
|
window,
|
||||||
|
|
@ -485,6 +502,7 @@ impl Node {
|
||||||
todo: checked.is_some(),
|
todo: checked.is_some(),
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
text_view_style,
|
text_view_style,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
|
|
@ -607,6 +625,7 @@ impl Node {
|
||||||
pub(crate) fn render(
|
pub(crate) fn render(
|
||||||
self,
|
self,
|
||||||
list_state: Option<ListState>,
|
list_state: Option<ListState>,
|
||||||
|
is_root: bool,
|
||||||
is_last_child: bool,
|
is_last_child: bool,
|
||||||
style: &TextViewStyle,
|
style: &TextViewStyle,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
|
|
@ -624,8 +643,8 @@ impl Node {
|
||||||
.children({
|
.children({
|
||||||
let children_len = children.len();
|
let children_len = children.len();
|
||||||
children.into_iter().enumerate().map(move |(index, c)| {
|
children.into_iter().enumerate().map(move |(index, c)| {
|
||||||
let is_last_child = index == children_len - 1;
|
let is_last_child = is_root && index == children_len - 1;
|
||||||
c.render(None, is_last_child, style, window, cx)
|
c.render(None, false, is_last_child, style, window, cx)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
|
|
@ -699,10 +718,9 @@ impl Node {
|
||||||
.mb(mb)
|
.mb(mb)
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
Node::Break { .. } => div().into_any_element(),
|
Node::Break { .. } => div().into_any_element(),
|
||||||
Node::Ignore => div().into_any_element(),
|
|
||||||
_ => {
|
_ => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("Unknown implementation: {:?}", self);
|
tracing::warn!("unknown implementation: {:?}", self);
|
||||||
}
|
}
|
||||||
|
|
||||||
div().into_any_element()
|
div().into_any_element()
|
||||||
|
|
@ -869,7 +887,6 @@ impl Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Node::Divider => "---".to_string(),
|
Node::Divider => "---".to_string(),
|
||||||
Node::Ignore => "".to_string(),
|
|
||||||
Node::Unknown => "".to_string(),
|
Node::Unknown => "".to_string(),
|
||||||
}
|
}
|
||||||
.trim()
|
.trim()
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,8 @@ pub(super) fn parse_html(source: &str) -> Result<element::Node, SharedString> {
|
||||||
|
|
||||||
let mut paragraph = Paragraph::default();
|
let mut paragraph = Paragraph::default();
|
||||||
// NOTE: The outer paragraph is not used.
|
// NOTE: The outer paragraph is not used.
|
||||||
let node: element::Node = parse_node(&dom.document, &mut paragraph);
|
let node: element::Node =
|
||||||
|
parse_node(&dom.document, &mut paragraph).unwrap_or(element::Node::Unknown);
|
||||||
let node = node.compact();
|
let node = node.compact();
|
||||||
|
|
||||||
Ok(node)
|
Ok(node)
|
||||||
|
|
@ -173,7 +174,7 @@ impl Element for HtmlElement {
|
||||||
|
|
||||||
let mut el = div()
|
let mut el = div()
|
||||||
.map(|this| match root {
|
.map(|this| match root {
|
||||||
Ok(node) => this.child(node.render(None, true, &self.style, window, cx)),
|
Ok(node) => this.child(node.render(None, true, true, &self.style, window, cx)),
|
||||||
Err(err) => this.child(
|
Err(err) => this.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
|
|
@ -492,7 +493,7 @@ fn parse_paragraph(
|
||||||
local_name!("img") => {
|
local_name!("img") => {
|
||||||
let Some(src) = attr_value(attrs, local_name!("src")) else {
|
let Some(src) = attr_value(attrs, local_name!("src")) else {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("[html] Image node missing src attribute");
|
tracing::warn!("Image node missing src attribute");
|
||||||
}
|
}
|
||||||
return (text, marks);
|
return (text, marks);
|
||||||
};
|
};
|
||||||
|
|
@ -509,7 +510,6 @@ fn parse_paragraph(
|
||||||
title: title.map(Into::into),
|
title: title.map(Into::into),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
// All unknown tags to as text
|
// All unknown tags to as text
|
||||||
let mut child_paragraph = Paragraph::default();
|
let mut child_paragraph = Paragraph::default();
|
||||||
|
|
@ -539,7 +539,7 @@ fn parse_paragraph(
|
||||||
(text, marks)
|
(text, marks)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> Option<element::Node> {
|
||||||
match node.data {
|
match node.data {
|
||||||
NodeData::Text { ref contents } => {
|
NodeData::Text { ref contents } => {
|
||||||
let text = contents.borrow().to_string();
|
let text = contents.borrow().to_string();
|
||||||
|
|
@ -547,14 +547,14 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
paragraph.push_str(&text);
|
paragraph.push_str(&text);
|
||||||
}
|
}
|
||||||
|
|
||||||
element::Node::Ignore
|
None
|
||||||
}
|
}
|
||||||
NodeData::Element {
|
NodeData::Element {
|
||||||
ref name,
|
ref name,
|
||||||
ref attrs,
|
ref attrs,
|
||||||
..
|
..
|
||||||
} => match name.local {
|
} => match name.local {
|
||||||
local_name!("br") => element::Node::Break { html: true },
|
local_name!("br") => Some(element::Node::Break { html: true }),
|
||||||
local_name!("h1")
|
local_name!("h1")
|
||||||
| local_name!("h2")
|
| local_name!("h2")
|
||||||
| local_name!("h3")
|
| local_name!("h3")
|
||||||
|
|
@ -587,9 +587,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
if children.len() > 0 {
|
if children.len() > 0 {
|
||||||
children.push(heading);
|
children.push(heading);
|
||||||
|
|
||||||
element::Node::Root { children }
|
Some(element::Node::Root { children })
|
||||||
} else {
|
} else {
|
||||||
heading
|
Some(heading)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_name!("img") => {
|
local_name!("img") => {
|
||||||
|
|
@ -601,9 +601,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
|
|
||||||
let Some(src) = attr_value(attrs, local_name!("src")) else {
|
let Some(src) = attr_value(attrs, local_name!("src")) else {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("[html] Image node missing src attribute");
|
tracing::warn!("image node missing src attribute");
|
||||||
}
|
}
|
||||||
return element::Node::Ignore;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let alt = attr_value(&attrs, local_name!("alt"));
|
let alt = attr_value(&attrs, local_name!("alt"));
|
||||||
|
|
@ -623,9 +623,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
|
|
||||||
if children.len() > 0 {
|
if children.len() > 0 {
|
||||||
children.push(element::Node::Paragraph(image));
|
children.push(element::Node::Paragraph(image));
|
||||||
element::Node::Root { children }
|
Some(element::Node::Root { children })
|
||||||
} else {
|
} else {
|
||||||
element::Node::Paragraph(image)
|
Some(element::Node::Paragraph(image))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_name!("ul") | local_name!("ol") => {
|
local_name!("ul") | local_name!("ol") => {
|
||||||
|
|
@ -641,7 +641,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
|
|
||||||
for child in node.children.borrow().iter() {
|
for child in node.children.borrow().iter() {
|
||||||
let mut child_paragraph = Paragraph::default();
|
let mut child_paragraph = Paragraph::default();
|
||||||
list_children.push(parse_node(child, &mut child_paragraph));
|
if let Some(child_node) = parse_node(child, &mut child_paragraph) {
|
||||||
|
list_children.push(child_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let list = element::Node::List {
|
let list = element::Node::List {
|
||||||
|
|
@ -650,19 +652,30 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
};
|
};
|
||||||
if children.len() > 0 {
|
if children.len() > 0 {
|
||||||
children.push(list);
|
children.push(list);
|
||||||
element::Node::Root { children }
|
Some(element::Node::Root { children })
|
||||||
} else {
|
} else {
|
||||||
list
|
Some(list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_name!("li") => {
|
local_name!("li") => {
|
||||||
let mut children = vec![];
|
let mut children = vec![];
|
||||||
|
|
||||||
for child in node.children.borrow().iter() {
|
for child in node.children.borrow().iter() {
|
||||||
let mut child_paragraph = Paragraph::default();
|
let mut child_paragraph = Paragraph::default();
|
||||||
children.push(parse_node(child, &mut child_paragraph));
|
if let Some(child_node) = parse_node(child, &mut child_paragraph) {
|
||||||
|
children.push(child_node);
|
||||||
|
}
|
||||||
if child_paragraph.text_len() > 0 {
|
if child_paragraph.text_len() > 0 {
|
||||||
children.push(element::Node::Paragraph(child_paragraph.clone()));
|
// If last child is paragraph, merge child
|
||||||
child_paragraph.clear();
|
if let Some(last_child) = children.last_mut() {
|
||||||
|
if let element::Node::Paragraph(last_paragraph) = last_child {
|
||||||
|
if last_paragraph.try_merge(&child_paragraph) {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(element::Node::Paragraph(child_paragraph));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -671,11 +684,11 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
paragraph.clear();
|
paragraph.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
element::Node::ListItem {
|
Some(element::Node::ListItem {
|
||||||
children,
|
children,
|
||||||
spread: false,
|
spread: false,
|
||||||
checked: None,
|
checked: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
local_name!("table") => {
|
local_name!("table") => {
|
||||||
let mut children = vec![];
|
let mut children = vec![];
|
||||||
|
|
@ -704,9 +717,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
let table = element::Node::Table(table);
|
let table = element::Node::Table(table);
|
||||||
if children.len() > 0 {
|
if children.len() > 0 {
|
||||||
children.push(table);
|
children.push(table);
|
||||||
element::Node::Root { children }
|
Some(element::Node::Root { children })
|
||||||
} else {
|
} else {
|
||||||
table
|
Some(table)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_name!("blockquote") => {
|
local_name!("blockquote") => {
|
||||||
|
|
@ -725,9 +738,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
}
|
}
|
||||||
children.push(element::Node::Blockquote(blockquote));
|
children.push(element::Node::Blockquote(blockquote));
|
||||||
|
|
||||||
element::Node::Root { children: children }
|
Some(element::Node::Root { children: children })
|
||||||
}
|
}
|
||||||
local_name!("style") | local_name!("script") => element::Node::Ignore,
|
local_name!("style") | local_name!("script") => None,
|
||||||
_ => {
|
_ => {
|
||||||
if BLOCK_ELEMENTS.contains(&name.local.trim()) {
|
if BLOCK_ELEMENTS.contains(&name.local.trim()) {
|
||||||
let mut children: Vec<element::Node> = vec![];
|
let mut children: Vec<element::Node> = vec![];
|
||||||
|
|
@ -744,7 +757,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
|
|
||||||
// Inner of the block element -- The "Inner text of block element"
|
// Inner of the block element -- The "Inner text of block element"
|
||||||
for child in node.children.borrow().iter() {
|
for child in node.children.borrow().iter() {
|
||||||
children.push(parse_node(child, paragraph));
|
if let Some(child_node) = parse_node(child, paragraph) {
|
||||||
|
children.push(child_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if !paragraph.is_empty() {
|
// if !paragraph.is_empty() {
|
||||||
|
|
@ -753,9 +768,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if children.is_empty() {
|
if children.is_empty() {
|
||||||
element::Node::Ignore
|
None
|
||||||
} else {
|
} else {
|
||||||
element::Node::Root { children }
|
Some(element::Node::Root { children })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Others to as Inline
|
// Others to as Inline
|
||||||
|
|
@ -764,9 +779,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
if paragraph.is_image() {
|
if paragraph.is_image() {
|
||||||
let image = paragraph.clone();
|
let image = paragraph.clone();
|
||||||
paragraph.clear();
|
paragraph.clear();
|
||||||
element::Node::Paragraph(image)
|
Some(element::Node::Paragraph(image))
|
||||||
} else {
|
} else {
|
||||||
element::Node::Ignore
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -774,7 +789,9 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
NodeData::Document => {
|
NodeData::Document => {
|
||||||
let mut children = vec![];
|
let mut children = vec![];
|
||||||
for child in node.children.borrow().iter() {
|
for child in node.children.borrow().iter() {
|
||||||
children.push(parse_node(child, paragraph));
|
if let Some(child_node) = parse_node(child, paragraph) {
|
||||||
|
children.push(child_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !paragraph.is_empty() {
|
if !paragraph.is_empty() {
|
||||||
|
|
@ -782,11 +799,11 @@ fn parse_node(node: &Rc<Node>, paragraph: &mut Paragraph) -> element::Node {
|
||||||
paragraph.clear();
|
paragraph.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
element::Node::Root { children }
|
Some(element::Node::Root { children })
|
||||||
}
|
}
|
||||||
NodeData::Doctype { .. } => element::Node::Ignore,
|
NodeData::Doctype { .. }
|
||||||
NodeData::Comment { .. } => element::Node::Ignore,
|
| NodeData::Comment { .. }
|
||||||
NodeData::ProcessingInstruction { .. } => element::Node::Ignore,
|
| NodeData::ProcessingInstruction { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ impl Element for MarkdownElement {
|
||||||
|
|
||||||
let mut el = div()
|
let mut el = div()
|
||||||
.map(|this| match root {
|
.map(|this| match root {
|
||||||
Ok(node) => this.child(node.render(None, true, &self.style, window, cx)),
|
Ok(node) => this.child(node.render(None, true, true, &self.style, window, cx)),
|
||||||
Err(err) => this.child(
|
Err(err) => this.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
|
|
@ -341,13 +341,13 @@ fn parse_paragraph(paragraph: &mut Paragraph, node: &mdast::Node) -> String {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("[markdown] unsupported inline html tag: {:#?}", el);
|
tracing::warn!("unsupported inline html tag: {:#?}", el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("[markdown] error parsing html: {:#?}", err);
|
tracing::warn!("failed parsing html: {:#?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
text.push_str(&val.value);
|
text.push_str(&val.value);
|
||||||
|
|
@ -355,7 +355,7 @@ fn parse_paragraph(paragraph: &mut Paragraph, node: &mdast::Node) -> String {
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("[markdown] unsupported inline node: {:#?}", node);
|
tracing::warn!("unsupported inline node: {:#?}", node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -437,7 +437,7 @@ fn ast_to_node(value: mdast::Node, style: &TextViewStyle, cx: &mut App) -> eleme
|
||||||
Ok(el) => el,
|
Ok(el) => el,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("[markdown] error parsing html: {:#?}", err);
|
tracing::warn!("error parsing html: {:#?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
element::Node::Paragraph(val.value.into())
|
element::Node::Paragraph(val.value.into())
|
||||||
|
|
@ -494,7 +494,7 @@ fn ast_to_node(value: mdast::Node, style: &TextViewStyle, cx: &mut App) -> eleme
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("[markdown] unsupported node: {:#?}", value);
|
tracing::warn!("unsupported node: {:#?}", value);
|
||||||
}
|
}
|
||||||
element::Node::Unknown
|
element::Node::Unknown
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue