pub fn parse_list_end_of_line(state: &mut crate::State) {
let item_end_position = state.skip_whitespace_backwards(state.scan_position);
state.flush(item_end_position);
state.scan_position += 1;
let mut level = 0;
for open_node in &state.stack {
match open_node.type_ {
crate::OpenNodeType::Table { .. } | crate::OpenNodeType::Tag { .. } => level += 1,
_ => break,
}
}
let start_level = level;
let mut term_level = None;
while level < state.stack.len() {
match (
&state.stack[level].type_,
state.get_byte(state.scan_position),
) {
(crate::OpenNodeType::DefinitionList { .. }, Some(b':'))
| (crate::OpenNodeType::OrderedList { .. }, Some(b'#'))
| (crate::OpenNodeType::UnorderedList { .. }, Some(b'*')) => {
level += 1;
state.scan_position += 1;
}
(crate::OpenNodeType::DefinitionList { .. }, Some(b';')) => {
if term_level.is_none() {
term_level = Some(level);
}
level += 1;
state.scan_position += 1;
}
_ => break,
}
}
if let Some(term_level) = term_level {
if level < state.stack.len()
|| match state.get_byte(state.scan_position) {
Some(b'#') | Some(b'*') | Some(b':') | Some(b';') => true,
_ => false,
}
{
state.scan_position -= level - term_level;
level = term_level;
state.warnings.push(crate::Warning {
end: state.scan_position,
message: crate::WarningMessage::DefinitionTermContinuation,
start: state.scan_position - 1,
});
}
}
while level < state.stack.len() {
let open_node = state.stack.pop().unwrap();
let node = match open_node.type_ {
crate::OpenNodeType::DefinitionList { mut items } => {
{
let item_index = items.len() - 1;
let last_item = &mut items[item_index];
last_item.end = item_end_position;
last_item.nodes = std::mem::replace(&mut state.nodes, open_node.nodes);
}
crate::Node::DefinitionList {
end: item_end_position,
items,
start: open_node.start,
}
}
crate::OpenNodeType::OrderedList { mut items } => {
{
let item_index = items.len() - 1;
let last_item = &mut items[item_index];
last_item.end = item_end_position;
last_item.nodes = std::mem::replace(&mut state.nodes, open_node.nodes);
}
crate::Node::OrderedList {
end: item_end_position,
items,
start: open_node.start,
}
}
crate::OpenNodeType::UnorderedList { mut items } => {
{
let item_index = items.len() - 1;
let last_item = &mut items[item_index];
last_item.end = item_end_position;
last_item.nodes = std::mem::replace(&mut state.nodes, open_node.nodes);
}
crate::Node::UnorderedList {
end: item_end_position,
items,
start: open_node.start,
}
}
_ => unreachable!(),
};
state.nodes.push(node);
}
state.flushed_position = state.scan_position;
if parse_list_item_start(state) {
while parse_list_item_start(state) {}
skip_spaces(state);
} else if level > start_level {
match state.stack.get_mut(level - 1) {
Some(crate::OpenNode {
type_: crate::OpenNodeType::DefinitionList { items },
..
}) => {
{
let item_index = items.len() - 1;
let last_item = &mut items[item_index];
last_item.end = item_end_position;
last_item.nodes = std::mem::replace(&mut state.nodes, vec![]);
}
items.push(crate::DefinitionListItem {
end: 0,
nodes: vec![],
start: state.scan_position - 1,
type_: if state
.wiki_text
.as_bytes()
.get(state.scan_position - 1)
.cloned()
== Some(b';')
{
crate::DefinitionListItemType::Term
} else {
crate::DefinitionListItemType::Details
},
});
}
Some(crate::OpenNode {
type_: crate::OpenNodeType::OrderedList { items },
..
}) => {
{
let item_index = items.len() - 1;
let last_item = &mut items[item_index];
last_item.end = item_end_position;
last_item.nodes = std::mem::replace(&mut state.nodes, vec![]);
};
items.push(crate::ListItem {
end: 0,
nodes: vec![],
start: state.scan_position - 1,
});
}
Some(crate::OpenNode {
type_: crate::OpenNodeType::UnorderedList { items },
..
}) => {
{
let item_index = items.len() - 1;
let last_item = &mut items[item_index];
last_item.end = item_end_position;
last_item.nodes = std::mem::replace(&mut state.nodes, vec![]);
};
items.push(crate::ListItem {
end: 0,
nodes: vec![],
start: state.scan_position - 1,
});
}
_ => unreachable!(),
}
skip_spaces(state);
} else {
state.skip_empty_lines();
}
}
pub fn parse_list_item_start(state: &mut crate::State) -> bool {
let open_node_type = match state.get_byte(state.scan_position) {
Some(b'#') => crate::OpenNodeType::OrderedList {
items: vec![crate::ListItem {
end: 0,
nodes: vec![],
start: state.scan_position + 1,
}],
},
Some(b'*') => crate::OpenNodeType::UnorderedList {
items: vec![crate::ListItem {
end: 0,
nodes: vec![],
start: state.scan_position + 1,
}],
},
Some(b':') => crate::OpenNodeType::DefinitionList {
items: vec![crate::DefinitionListItem {
end: 0,
nodes: vec![],
start: state.scan_position + 1,
type_: crate::DefinitionListItemType::Details,
}],
},
Some(b';') => crate::OpenNodeType::DefinitionList {
items: vec![crate::DefinitionListItem {
end: 0,
nodes: vec![],
start: state.scan_position + 1,
type_: crate::DefinitionListItemType::Term,
}],
},
_ => return false,
};
let position = state.scan_position + 1;
state.push_open_node(open_node_type, position);
true
}
pub fn skip_spaces(state: &mut crate::State) {
while match state.get_byte(state.scan_position) {
Some(b'\t') | Some(b' ') => true,
_ => false,
} {
state.scan_position += 1;
}
state.flushed_position = state.scan_position;
}