asciidork_parser/tasks/
heading_level.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crate::internal::*;

impl<'arena> Parser<'arena> {
  pub fn line_heading_level(&self, line: &Line) -> Option<u8> {
    let unadjusted = line.unadjusted_heading_level()?;
    Some(adjusted_leveloffset(
      self.lexer.leveloffset(line.loc().unwrap().include_depth),
      adjusted_leveloffset(self.ctx.leveloffset, unadjusted),
    ))
  }

  pub fn section_start_level(
    &self,
    lines: &ContiguousLines<'arena>,
    meta: &ChunkMeta<'arena>,
  ) -> Option<u8> {
    for line in lines.iter() {
      if line.is_block_attr_list() || line.is_chunk_title() || line.is_comment() {
        continue;
      } else if let Some(level) = self.line_heading_level(line) {
        return match meta.attrs.has_str_positional("discrete")
          || meta.attrs.has_str_positional("float")
        {
          true => None,
          false => Some(level),
        };
      } else {
        return None;
      }
    }
    None
  }

  pub fn adjust_leveloffset(leveloffset: &mut i8, value: &AttrValue) {
    match value {
      AttrValue::String(s) => {
        if let Some(add) = s.strip_prefix('+') {
          *leveloffset += add.parse::<i8>().unwrap_or(0);
        } else if let Some(sub) = s.strip_prefix('-') {
          *leveloffset -= sub.parse::<i8>().unwrap_or(0);
        } else {
          *leveloffset = s.parse::<i8>().unwrap_or(*leveloffset);
        }
      }
      AttrValue::Bool(false) => *leveloffset = 0,
      AttrValue::Bool(true) => {}
    }
  }
}

const fn adjusted_leveloffset(leveloffset: i8, heading_level: u8) -> u8 {
  if leveloffset == 0 {
    return heading_level;
  }
  let new_level = (heading_level as i8) + leveloffset;
  if new_level < 0 {
    0
  } else {
    new_level as u8
  }
}