Fix table parsing

This commit is contained in:
Joel Wachsler 2022-07-14 13:00:39 +00:00
parent 391ed560a6
commit f1c3656e6e
5 changed files with 149 additions and 7 deletions

View File

@ -77,10 +77,21 @@ impl MdToken {
} }
pub fn from(content: &str) -> Vec<MdToken> { pub fn from(content: &str) -> Vec<MdToken> {
// to prevent infinite loops
let mut max_iterations = 10000;
let mut decreate_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(); let mut iter = content.lines().peekable();
while let Some(line) = iter.next() { while let Some(line) = iter.next() {
decreate_max_iterations();
// assume this is a table // assume this is a table
if line.contains('|') { if line.contains('|') {
let to_columns = |column_line: &str| { let to_columns = |column_line: &str| {
@ -97,16 +108,18 @@ impl MdToken {
}; };
let table_split = iter.next().unwrap(); let table_split = iter.next().unwrap();
let mut table_rows = Vec::new(); let mut table_rows = Vec::new();
while let Some(row_line) = iter.next() { while let Some(peeked_row_line) = iter.peek() {
if !row_line.contains('|') { decreate_max_iterations();
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
iter.next_back();
break; break;
} }
let next_row_line = iter.next().unwrap();
let table_row = TableRow { let table_row = TableRow {
raw: row_line.into(), raw: next_row_line.to_string(),
columns: to_columns(row_line), columns: to_columns(next_row_line),
}; };
table_rows.push(table_row); table_rows.push(table_row);

View File

@ -96,11 +96,19 @@ mod tests {
macro_rules! update_test { macro_rules! update_test {
($test_file:expr) => { ($test_file:expr) => {
use std::fs; use std::fs;
use std::path::Path;
let input = include_str!(concat!("token_tree_factory_tests/", $test_file, ".md")); let input = include_str!(concat!("token_tree_factory_tests/", $test_file, ".md"));
let tree = TokenTreeFactory::create(input); let tree = TokenTreeFactory::create(input);
let tree_as_str = format!("{tree:#?}"); let tree_as_str = format!("{tree:#?}");
fs::write(concat!($test_file, ".check"), tree_as_str).unwrap(); let file = concat!("src/md_parser/token_tree_factory_tests/", $test_file, ".check");
// prevent user from accidentially leaving the current macro in a test
if Path::new(file).exists() {
panic!("Test case already exists: {file}");
}
fs::write(file, tree_as_str).unwrap();
}; };
} }
@ -128,4 +136,9 @@ mod tests {
fn log() { fn log() {
run_test!("log"); run_test!("log");
} }
#[test]
fn multi_table() {
run_test!("multi_table");
}
} }

View File

@ -93,6 +93,9 @@ TokenTree {
], ],
}, },
), ),
Text(
"",
),
Text( Text(
"Example:", "Example:",
), ),
@ -138,6 +141,9 @@ TokenTree {
], ],
}, },
), ),
Text(
"",
),
Text( Text(
"The response is a JSON array in which each element is an entry of the log.", "The response is a JSON array in which each element is an entry of the log.",
), ),
@ -197,6 +203,9 @@ TokenTree {
], ],
}, },
), ),
Text(
"",
),
Text( Text(
"Example:", "Example:",
), ),
@ -494,6 +503,15 @@ TokenTree {
Text( Text(
" \"type\":2", " \"type\":2",
), ),
Text(
" }",
),
Text(
"]",
),
Text(
"```",
),
], ],
children: [], children: [],
}, },

View File

@ -0,0 +1,86 @@
TokenTree {
title: None,
content: [],
children: [
TokenTree {
title: Some(
"Foo",
),
content: [
Text(
"",
),
],
children: [
TokenTree {
title: Some(
"Bar",
),
content: [
Table(
Table {
header: TableRow {
raw: "Parameter | Type | Description",
columns: [
"Parameter",
"Type",
"Description",
],
},
split: "----------------|---------|------------",
rows: [
TableRow {
raw: "`normal` | bool | Include normal messages (default: `true`)",
columns: [
"normal",
"bool",
"Include normal messages (default: true)",
],
},
],
},
),
Text(
"",
),
],
children: [],
},
TokenTree {
title: Some(
"Baz",
),
content: [
Table(
Table {
header: TableRow {
raw: "Parameter | Type | Description",
columns: [
"Parameter",
"Type",
"Description",
],
},
split: "----------------|---------|------------",
rows: [
TableRow {
raw: "`last_known_id` | integer | Exclude messages with \"message id\" <= `last_known_id` (default: `-1`)",
columns: [
"last_known_id",
"integer",
"Exclude messages with \"message id\" <= last_known_id (default: -1)",
],
},
],
},
),
Text(
"",
),
],
children: [],
},
],
},
],
}

View File

@ -0,0 +1,12 @@
# Foo
## Bar
Parameter | Type | Description
----------------|---------|------------
`normal` | bool | Include normal messages (default: `true`)
## Baz
Parameter | Type | Description
----------------|---------|------------
`last_known_id` | integer | Exclude messages with "message id" <= `last_known_id` (default: `-1`)