use mant_ir::Inline;
pub(crate) fn plain_text(nodes: &[Inline]) -> String {
let mut output = String::new();
for node in nodes {
match node {
Inline::Text { value } | Inline::Code { value } => output.push_str(value),
Inline::Strong { children }
| Inline::Emphasis { children }
| Inline::Link { children, .. } => output.push_str(&plain_text(children)),
Inline::Anchor { .. } => {}
Inline::LineBreak => output.push('\n'),
}
}
output
}
pub(crate) fn first_visible_character(nodes: &[Inline]) -> Option<char> {
nodes.iter().find_map(first_character)
}
pub(crate) fn last_visible_character(nodes: &[Inline]) -> Option<char> {
nodes.iter().rev().find_map(last_character)
}
pub(crate) fn has_printable_character(nodes: &[Inline]) -> bool {
nodes.iter().any(|node| match node {
Inline::Text { value } | Inline::Code { value } => {
value.chars().any(|character| character != '\n')
}
Inline::Strong { children }
| Inline::Emphasis { children }
| Inline::Link { children, .. } => has_printable_character(children),
Inline::Anchor { .. } | Inline::LineBreak => false,
})
}
fn first_character(node: &Inline) -> Option<char> {
match node {
Inline::Text { value } | Inline::Code { value } => value.chars().next(),
Inline::Strong { children }
| Inline::Emphasis { children }
| Inline::Link { children, .. } => first_visible_character(children),
Inline::Anchor { .. } => None,
Inline::LineBreak => Some('\n'),
}
}
fn last_character(node: &Inline) -> Option<char> {
match node {
Inline::Text { value } | Inline::Code { value } => value.chars().next_back(),
Inline::Strong { children }
| Inline::Emphasis { children }
| Inline::Link { children, .. } => last_visible_character(children),
Inline::Anchor { .. } => None,
Inline::LineBreak => Some('\n'),
}
}
pub(crate) const DEFAULT_INLINE_TERM_MAX_WIDTH: usize = 6;
pub(crate) fn terms_fit_inline(terms: &[Vec<Inline>], max_width: usize) -> bool {
let width = terms
.iter()
.map(|term| plain_text(term))
.collect::<Vec<_>>()
.join(", ")
.trim()
.chars()
.count();
(1..=max_width).contains(&width)
}