use std::collections::HashMap;
use encoding_rs::Encoding;
use super::scan;
const MAX_LEVEL: u8 = 6;
pub type HeadingStyles = HashMap<i32, u8>;
pub fn parse(bytes: &[u8], enc: &'static Encoding) -> HeadingStyles {
let mut out = HeadingStyles::new();
scan::for_each_entry(bytes, b"{\\stylesheet", |def| {
if let Some((num, level)) = parse_style(def, enc) {
out.insert(num, level);
}
});
out
}
fn parse_style(def: &[u8], enc: &'static Encoding) -> Option<(i32, u8)> {
let rest = def.strip_prefix(b"{\\s")?;
let digits: Vec<u8> = rest.iter().copied().take_while(u8::is_ascii_digit).collect();
if digits.is_empty() {
return None;
}
let num: i32 = std::str::from_utf8(&digits).ok()?.parse().ok()?;
if let Some(level) = outline_level(def) {
return Some((num, level));
}
let name = scan::read_trailing_name(def, enc)?;
heading_level_from_name(&name).map(|level| (num, level))
}
fn outline_level(def: &[u8]) -> Option<u8> {
let n = scan::read_param(def, b"\\outlinelevel")?;
if n >= 9 {
return None;
}
Some(((n + 1) as u8).min(MAX_LEVEL))
}
fn heading_level_from_name(name: &str) -> Option<u8> {
let lower = name.trim().to_lowercase();
const HEADING_WORDS: [&str; 14] = [
"heading",
"überschrift",
"uberschrift",
"titre",
"título",
"titulo",
"titolo",
"kop",
"overskrift",
"rubrik",
"otsikko",
"заголовок",
"標題",
"見出し",
];
let word = HEADING_WORDS.iter().find(|w| lower.starts_with(*w))?;
let rest = lower[word.len()..].trim_start_matches([' ', '-', '_']).trim();
if rest.is_empty() {
return Some(1);
}
let level: u32 = rest.parse().ok()?;
if level == 0 {
return None;
}
Some((level as u8).min(MAX_LEVEL))
}