asciidork_parser/tasks/
heading_level.rs

1use crate::internal::*;
2
3impl<'arena> Parser<'arena> {
4  pub fn line_heading_level(&self, line: &Line) -> Option<u8> {
5    let unadjusted = line.unadjusted_heading_level()?;
6    Some(adjusted_leveloffset(
7      self
8        .lexer
9        .leveloffset(line.first_loc().unwrap().include_depth),
10      adjusted_leveloffset(self.ctx.leveloffset, unadjusted),
11    ))
12  }
13
14  pub fn section_start_level(
15    &self,
16    lines: &ContiguousLines<'arena>,
17    meta: &ChunkMeta<'arena>,
18  ) -> Option<u8> {
19    for line in lines.iter() {
20      if line.is_block_attr_list() || line.is_chunk_title() || line.is_comment() {
21        continue;
22      } else if let Some(level) = self.line_heading_level(line) {
23        return match meta.attrs.has_str_positional("discrete")
24          || meta.attrs.has_str_positional("float")
25        {
26          true => None,
27          false => Some(level),
28        };
29      } else {
30        return None;
31      }
32    }
33    None
34  }
35
36  pub fn adjust_leveloffset(leveloffset: &mut i8, value: &AttrValue) {
37    match value {
38      AttrValue::String(s) => {
39        if let Some(add) = s.strip_prefix('+') {
40          *leveloffset += add.parse::<i8>().unwrap_or(0);
41        } else if let Some(sub) = s.strip_prefix('-') {
42          *leveloffset -= sub.parse::<i8>().unwrap_or(0);
43        } else {
44          *leveloffset = s.parse::<i8>().unwrap_or(*leveloffset);
45        }
46      }
47      AttrValue::Bool(false) => *leveloffset = 0,
48      AttrValue::Bool(true) => {}
49    }
50  }
51}
52
53const fn adjusted_leveloffset(leveloffset: i8, heading_level: u8) -> u8 {
54  if leveloffset == 0 {
55    return heading_level;
56  }
57  let new_level = (heading_level as i8) + leveloffset;
58  if new_level < 0 {
59    0
60  } else {
61    new_level as u8
62  }
63}