latexml_core/document/
helpers.rs1use libxml::tree::Node;
2
3use super::{Document, get_node_qname};
4use crate::common::{error::*, xml::XML_NS};
5
6pub fn preceding_para_sibling(node: &Node) -> bool {
13 match node.get_prev_element_sibling() {
14 None => false,
15 Some(prev) => {
16 if prev.get_name() == "_spilled_" {
17 prev.get_attribute("last").as_deref() == Some("ltx:para")
21 } else {
22 get_node_qname(&prev) == crate::pin!("ltx:para")
23 }
24 },
25 }
26}
27
28pub fn prune_empty_para(document: &mut Document, node: &mut Node) -> Result<()> {
31 let children = node.get_child_elements();
32 if children.is_empty() {
33 let prev_is_para = preceding_para_sibling(node);
34 if !prev_is_para {
35 document.add_class(&mut node.get_parent().unwrap(), "ltx_pruned_first")?;
37 }
38 if let Some(id) = node.get_attribute_ns("id", XML_NS) {
41 if let Some(pos) = id.rfind('.') {
43 let suffix = &id[pos + 1..];
44 let prefix: String = suffix.chars().take_while(|c| !c.is_ascii_digit()).collect();
45 let ctrkey = if prefix.is_empty() {
48 "_ID_counter_".to_string()
49 } else {
50 format!("_ID_counter_{}_", prefix)
51 };
52 if let Some(mut ancestor) = node.get_parent()
53 && let Some(ctr_str) = ancestor.get_attribute(&ctrkey)
54 && let Ok(ctr) = ctr_str.parse::<u32>()
55 && ctr > 0
56 {
57 ancestor.set_attribute(&ctrkey, &(ctr - 1).to_string())?;
58 }
59 } else {
60 let prefix: String = id.chars().take_while(|c| !c.is_ascii_digit()).collect();
62 let ctrkey = if prefix.is_empty() {
65 "_ID_counter_".to_string()
66 } else {
67 format!("_ID_counter_{}_", prefix)
68 };
69 if let Some(root) = document.get_document().get_root_element() {
71 let mut root = root;
72 if let Some(ctr_str) = root.get_attribute(&ctrkey)
73 && let Ok(ctr) = ctr_str.parse::<u32>()
74 && ctr > 0
75 {
76 root.set_attribute(&ctrkey, &(ctr - 1).to_string())?;
77 }
78 }
79 }
80 document.unrecord_id(&id);
81 }
82 node.unlink();
83 }
84 Ok(())
85}