Extract table logic
This commit is contained in:
parent
bebceb6581
commit
b32311ae65
|
@ -78,22 +78,44 @@ impl MdToken {
|
||||||
|
|
||||||
pub fn from(content: &str) -> Vec<MdToken> {
|
pub fn from(content: &str) -> Vec<MdToken> {
|
||||||
// to prevent infinite loops
|
// to prevent infinite loops
|
||||||
let mut max_iterations = 10000;
|
let mut max_iterator_checker = MaxIteratorChecker::default();
|
||||||
let mut decrease_max_iterations = || {
|
|
||||||
max_iterations -= 1;
|
|
||||||
if max_iterations <= 0 {
|
|
||||||
panic!("Max iterations reached, missing termination?");
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut output = Vec::new();
|
let mut output = Vec::new();
|
||||||
|
|
||||||
let mut iter = content.lines().peekable();
|
let mut iter = content.lines().peekable();
|
||||||
while let Some(line) = iter.next() {
|
|
||||||
decrease_max_iterations();
|
|
||||||
|
|
||||||
// assume this is a table
|
while let Some(line) = iter.next() {
|
||||||
|
max_iterator_checker.decrease();
|
||||||
|
|
||||||
|
// assume that lines starting with "|" are tables
|
||||||
if line.contains('|') {
|
if line.contains('|') {
|
||||||
|
let table = TableParser::new(&mut max_iterator_checker, &mut iter).parse(line);
|
||||||
|
output.push(MdToken::Content(table));
|
||||||
|
} else {
|
||||||
|
output.push(MdToken::parse_token(line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TableParser<'a, 'b> {
|
||||||
|
max_iterator_checker: &'a mut MaxIteratorChecker,
|
||||||
|
iter: &'a mut std::iter::Peekable<std::str::Lines<'b>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> TableParser<'a, 'b> {
|
||||||
|
fn new(
|
||||||
|
max_iterator_checker: &'a mut MaxIteratorChecker,
|
||||||
|
iter: &'a mut std::iter::Peekable<std::str::Lines<'b>>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
max_iterator_checker,
|
||||||
|
iter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(&mut self, line: &str) -> MdContent {
|
||||||
let to_columns = |column_line: &str| {
|
let to_columns = |column_line: &str| {
|
||||||
column_line
|
column_line
|
||||||
.replace('`', "")
|
.replace('`', "")
|
||||||
|
@ -106,35 +128,50 @@ impl MdToken {
|
||||||
raw: line.into(),
|
raw: line.into(),
|
||||||
columns: to_columns(line),
|
columns: to_columns(line),
|
||||||
};
|
};
|
||||||
let table_split = iter.next().unwrap();
|
|
||||||
|
let table_split = self.iter.next().unwrap();
|
||||||
let mut table_rows = Vec::new();
|
let mut table_rows = Vec::new();
|
||||||
while let Some(peeked_row_line) = iter.peek() {
|
while let Some(peeked_row_line) = self.iter.peek() {
|
||||||
decrease_max_iterations();
|
self.max_iterator_checker.decrease();
|
||||||
|
|
||||||
if !peeked_row_line.contains('|') {
|
if !peeked_row_line.contains('|') {
|
||||||
// we've reached the end of the table, let's go back one step
|
// we've reached the end of the table, let's go back one step
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_row_line = iter.next().unwrap();
|
let next_row_line = self.iter.next().unwrap();
|
||||||
let table_row = TableRow {
|
table_rows.push(TableRow {
|
||||||
raw: next_row_line.to_string(),
|
raw: next_row_line.to_string(),
|
||||||
columns: to_columns(next_row_line),
|
columns: to_columns(next_row_line),
|
||||||
};
|
});
|
||||||
|
|
||||||
table_rows.push(table_row);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output.push(MdToken::Content(MdContent::Table(Table {
|
MdContent::Table(Table {
|
||||||
header: table_header,
|
header: table_header,
|
||||||
split: table_split.to_string(),
|
split: table_split.to_string(),
|
||||||
rows: table_rows,
|
rows: table_rows,
|
||||||
})));
|
})
|
||||||
} else {
|
|
||||||
output.push(MdToken::parse_token(line));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
#[derive(Debug)]
|
||||||
|
struct MaxIteratorChecker {
|
||||||
|
max_iterations: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MaxIteratorChecker {
|
||||||
|
fn decrease(&mut self) {
|
||||||
|
self.max_iterations -= 1;
|
||||||
|
if self.max_iterations <= 0 {
|
||||||
|
panic!("Max iterations reached, missing termination?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MaxIteratorChecker {
|
||||||
|
fn default() -> Self {
|
||||||
|
MaxIteratorChecker {
|
||||||
|
max_iterations: 10000,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user