use crate::Inline;
#[must_use]
pub fn definition_run_in_width(terms: &[Vec<Inline>]) -> Option<usize> {
let mut final_row = String::new();
let mut present = false;
for term in terms {
let mut row = String::new();
let mut term_present = false;
append(term, &mut row, &mut term_present);
if term_present {
final_row = row;
present = true;
}
}
(present && !final_row.is_empty()).then(|| super::text_width(&final_row))
}
fn append(nodes: &[Inline], row: &mut String, present: &mut bool) {
for node in nodes {
match node {
Inline::Text { value } | Inline::Code { value } => {
*present |= !value.is_empty();
if let Some((_, tail)) = value.rsplit_once('\n') {
row.clear();
row.push_str(tail);
} else {
row.push_str(value);
}
}
Inline::Strong { children }
| Inline::Emphasis { children }
| Inline::Link { children, .. } => append(children, row, present),
Inline::LineBreak => {
row.clear();
*present = true;
}
Inline::Anchor { .. } => {}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn text(value: &str) -> Inline {
Inline::Text {
value: value.into(),
}
}
#[test]
fn preceding_labels_and_hard_rows_do_not_measure_the_final_open_row() {
assert_eq!(
definition_run_in_width(&[vec![text("long-label")], vec![text("-b")]]),
Some(2)
);
assert_eq!(
definition_run_in_width(&[vec![text("long-label\n-b")]]),
Some(2)
);
assert_eq!(
definition_run_in_width(&[vec![text("-b")], vec![text("long-label")]]),
Some(10)
);
assert_eq!(definition_run_in_width(&[vec![text(" -b ")]]), Some(5));
}
#[test]
fn anchors_and_wrappers_do_not_reopen_a_closed_label_row() {
let anchor = Inline::anchor("target");
for boundary in [Inline::LineBreak, text("\n")] {
assert_eq!(
definition_run_in_width(&[vec![text("-b"), boundary, anchor.clone()]]),
None
);
}
assert_eq!(
definition_run_in_width(&[vec![text("-b")], vec![anchor]]),
Some(2)
);
assert_eq!(
definition_run_in_width(&[vec![Inline::Emphasis {
children: Vec::new()
}]]),
None
);
assert_eq!(
definition_run_in_width(&[vec![text("-b"), Inline::LineBreak, text("-c")]]),
Some(2)
);
}
#[test]
fn styled_link_fragments_share_unicode_cell_measurement() {
let terms = vec![vec![
text("long-label"),
Inline::LineBreak,
Inline::Strong {
children: vec![text("日")],
},
Inline::Link {
target: crate::LinkTarget::External {
uri: "https://example.org".into(),
},
title: None,
children: vec![text("本e")],
},
Inline::Emphasis {
children: vec![text("\u{301}")],
},
]];
assert_eq!(definition_run_in_width(&terms), Some(5));
}
}