k2f_docx 0.2.2

K2F lock → DOCX exporter
Documentation
pub(crate) fn numbering_xml() -> String {
    let mut xml = String::from(
        r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
"#,
    );
    xml.push_str(&abstract_num(0, false));
    xml.push_str(&abstract_num(1, true));
    xml.push_str(
        r#"  <w:num w:numId="1">
    <w:abstractNumId w:val="0"/>
  </w:num>
  <w:num w:numId="2">
    <w:abstractNumId w:val="1"/>
  </w:num>
</w:numbering>
"#,
    );
    xml
}

fn abstract_num(id: u32, numbered: bool) -> String {
    let mut s = format!(
        r#"  <w:abstractNum w:abstractNumId="{id}">
    <w:nsid w:val="{nsid}"/>
    <w:multiLevelType w:val="hybridMultilevel"/>
"#,
        nsid = format!("{:08X}", 0x4B32_4630 + id),
    );
    for ilvl in 0..9u32 {
        if numbered {
            let lvl_text = format!("%{}.", ilvl + 1);
            s.push_str(&format!(
                r#"    <w:lvl w:ilvl="{ilvl}">
      <w:start w:val="1"/>
      <w:numFmt w:val="decimal"/>
      <w:lvlText w:val="{lvl_text}"/>
      <w:lvlJc w:val="left"/>
      <w:pPr>
        <w:ind w:left="0" w:hanging="0"/>
      </w:pPr>
      <w:rPr>
        <w:color w:val="000001"/>
      </w:rPr>
    </w:lvl>
"#
            ));
        } else {
            s.push_str(&format!(
                r#"    <w:lvl w:ilvl="{ilvl}">
      <w:start w:val="1"/>
      <w:numFmt w:val="bullet"/>
      <w:lvlText w:val="•"/>
      <w:lvlJc w:val="left"/>
      <w:pPr>
        <w:ind w:left="0" w:hanging="0"/>
      </w:pPr>
      <w:rPr>
        <w:color w:val="000001"/>
      </w:rPr>
    </w:lvl>
"#
            ));
        }
    }
    s.push_str("  </w:abstractNum>\n");
    s
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn numbering_pins_rgb_marker_color() {
        let xml = numbering_xml();
        assert!(
            xml.contains(r#"<w:color w:val="000001"/>"#),
            "list markers must not use Automatic color, got {xml}"
        );
        assert!(
            !xml.contains(r#"w:hanging="360""#),
            "default numbering indent would shrink lock text boxes, got {xml}"
        );
    }
}