use ox_content_ast::Node;
pub(super) fn collect_heading_text(nodes: &[Node<'_>]) -> String {
let mut text = String::new();
collect_heading_text_into(nodes, &mut text);
text
}
pub(super) fn collect_heading_text_into(nodes: &[Node<'_>], text: &mut String) {
for node in nodes {
collect_node_text(node, text);
}
}
fn collect_node_text(node: &Node<'_>, text: &mut String) {
match node {
Node::Text(value) => text.push_str(value.value),
Node::InlineCode(value) => text.push_str(value.value),
Node::Emphasis(value) => {
for child in &value.children {
collect_node_text(child, text);
}
}
Node::Strong(value) => {
for child in &value.children {
collect_node_text(child, text);
}
}
Node::Delete(value) => {
for child in &value.children {
collect_node_text(child, text);
}
}
Node::Link(value) => {
for child in &value.children {
collect_node_text(child, text);
}
}
_ => {}
}
}
pub(super) fn slugify_heading(text: &str) -> String {
let mut out = String::with_capacity(text.len());
slugify_heading_into(text, &mut out);
out
}
pub(super) fn slugify_heading_into(text: &str, out: &mut String) {
let bytes = text.as_bytes();
out.reserve(text.len());
let start_len = out.len();
let mut last_was_separator = true;
let mut i = 0;
while i < bytes.len() {
let b = bytes[i];
if b < 0x80 {
if b.is_ascii_alphanumeric() {
let lower = if b.is_ascii_uppercase() { b + 32 } else { b };
out.push(lower as char);
last_was_separator = false;
} else if !last_was_separator {
out.push('-');
last_was_separator = true;
}
i += 1;
} else {
let mut j = i + 1;
while j < bytes.len() && bytes[j] >= 0x80 {
j += 1;
}
for ch in text[i..j].chars() {
for lower in ch.to_lowercase() {
if lower.is_alphanumeric() {
out.push(lower);
last_was_separator = false;
} else if !last_was_separator {
out.push('-');
last_was_separator = true;
}
}
}
i = j;
}
}
while out.len() > start_len && out.ends_with('-') {
out.pop();
}
if out.len() == start_len {
out.push_str("section");
}
}