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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
// Copyright 2019 Fredrik Portström <https://portstrom.com>
// This is free software distributed under the terms specified in
// the file LICENSE at the top-level directory of this distribution.
pub fn parse_heading_end(state: &mut crate::State) {
let mut end_position = state.scan_position;
loop {
match state.get_byte(end_position - 1) {
Some(b'\t') | Some(b' ') => end_position -= 1,
_ => break,
}
}
let open_node = state.stack.pop().unwrap();
if state.get_byte(end_position - 1) != Some(b'=') || end_position < open_node.start + 3 {
state.warnings.push(crate::Warning {
end: end_position,
message: crate::WarningMessage::InvalidHeadingSyntaxRewinding,
start: open_node.start,
});
state.rewind(open_node.nodes, open_node.start);
return;
}
let start_level = match open_node.type_ {
crate::OpenNodeType::Heading { level } => level,
_ => unreachable!(),
};
let mut end_level: u8 = 1;
while end_level < start_level
&& end_position - end_level as usize > open_node.start + end_level as usize + 2
&& state.get_byte(end_position - end_level as usize - 1) == Some(b'=')
{
end_level += 1;
}
let position = state.skip_whitespace_backwards(end_position - end_level as usize);
if end_level < start_level {
state.warnings.push(crate::Warning {
end: end_position,
message: crate::WarningMessage::UnexpectedHeadingLevelCorrecting,
start: open_node.start,
});
let inner_start_position = open_node.start + end_level as usize;
if match state.nodes.get_mut(0) {
None => {
state.flushed_position = inner_start_position;
false
}
Some(crate::Node::Text { end, start, value }) => {
*start = inner_start_position;
*value = &state.wiki_text[inner_start_position..*end];
false
}
Some(_) => true,
} {
let end = state.skip_whitespace_forwards(open_node.start + start_level as usize);
state.nodes.insert(
0,
crate::Node::Text {
end,
start: inner_start_position,
value: &state.wiki_text[inner_start_position..end],
},
);
}
}
state.flush(position);
let nodes = std::mem::replace(&mut state.nodes, open_node.nodes);
state.nodes.push(crate::Node::Heading {
end: end_position,
level: end_level,
nodes,
start: open_node.start,
});
state.scan_position += 1;
state.skip_empty_lines();
}
pub fn parse_heading_start(state: &mut crate::State) {
let mut level = 1;
while state.get_byte(state.scan_position + level) == Some(b'=') && level < 6 {
level += 1;
}
let position = state.skip_whitespace_forwards(state.scan_position + level);
state.flushed_position = position;
state.push_open_node(
crate::OpenNodeType::Heading { level: level as u8 },
position,
);
}
|