use panache_parser::parse;
use panache_parser::syntax::{
AstNode, Citation, FootnoteDefinition, GridTable, List, MultilineTable, ReferenceDefinition,
SimpleTable, TableCaption,
};
#[test]
fn grid_table_caption_and_rows() {
let input = r#"+---------+---------+
| Header1 | Header2 |
+=========+=========+
| Cell1 | Cell2 |
+---------+---------+
| Cell3 | Cell4 |
+---------+---------+
Table: Grid table caption"#;
let tree = parse(input, None);
let grid = tree
.descendants()
.find_map(GridTable::cast)
.expect("Should find GridTable");
let caption = grid.caption().expect("Should have caption");
let caption_text = caption.text();
assert!(caption_text.contains("Grid table caption"));
assert_eq!(grid.rows().count(), 2, "Should have 2 data rows");
}
#[test]
fn simple_table_caption_and_rows() {
let input = r#" Header1 Header2
-------- --------
Cell1 Cell2
Cell3 Cell4
Table: Simple table caption"#;
let tree = parse(input, None);
let simple = tree
.descendants()
.find_map(SimpleTable::cast)
.expect("Should find SimpleTable");
let caption = simple.caption();
assert!(caption.is_some(), "Should have caption");
assert!(simple.rows().next().is_some(), "Should have rows");
}
#[test]
fn multiline_table_caption_and_rows() {
let input = r#"-------------------
Header1 Header2
-------- --------
Cell1 Cell2
Cell3 Cell4
-------------------
Table: Multiline table caption"#;
let tree = parse(input, None);
let multiline = tree
.descendants()
.find_map(MultilineTable::cast)
.expect("Should find MultilineTable");
let caption = multiline.caption();
assert!(caption.is_some(), "Should have caption");
assert!(multiline.rows().next().is_some(), "Should have rows");
}
#[test]
fn table_caption_without_nested_emphasis() {
let input = r#"| A | B |
|---|---|
| 1 | 2 |
Table: Plain caption text"#;
let tree = parse(input, None);
let caption = tree
.descendants()
.find_map(TableCaption::cast)
.expect("Should find TableCaption");
let text = caption.text();
assert_eq!(text, "Plain caption text");
}
#[test]
fn list_item_is_loose() {
let input = "- First item\n\n- Second item\n";
let tree = parse(input, None);
let list = tree
.descendants()
.find_map(List::cast)
.expect("Should find List");
assert!(list.is_loose(), "List should be loose");
assert!(!list.is_compact(), "List should not be compact");
assert_eq!(list.items().count(), 2);
}
#[test]
fn list_item_is_compact() {
let input = "- First\n- Second\n- Third\n";
let tree = parse(input, None);
let list = tree
.descendants()
.find_map(List::cast)
.expect("Should find List");
assert!(list.is_compact(), "List should be compact");
let item = list.items().next().expect("Should have list item");
assert!(item.is_compact(), "Item in compact list should be compact");
assert!(!item.is_loose(), "Item in compact list should not be loose");
}
#[test]
fn reference_definition_label() {
let input = "[ref]: https://example.com \"Title\"\n\nSee [reference][ref].";
let tree = parse(input, None);
let ref_def = tree
.descendants()
.find_map(ReferenceDefinition::cast)
.expect("Should find ReferenceDefinition");
let label = ref_def.label();
assert_eq!(label, "ref");
}
#[test]
fn reference_definition_link() {
let input = "[label]: https://example.com\n";
let tree = parse(input, None);
let ref_def = tree
.descendants()
.find_map(ReferenceDefinition::cast)
.expect("Should find ReferenceDefinition");
let link = ref_def.link();
assert!(link.is_some(), "Should have link child");
}
#[test]
fn citation_key_texts() {
let input = "Some text [@doe2020; @smith2021] more text.";
let tree = parse(input, None);
let citation = tree
.descendants()
.find_map(Citation::cast)
.expect("Should find Citation");
let key_texts = citation.key_texts();
assert_eq!(key_texts.len(), 2);
assert!(key_texts.contains(&"doe2020".to_string()));
assert!(key_texts.contains(&"smith2021".to_string()));
}
#[test]
fn citation_keys() {
let input = "Text with [@key1; @key2; @key3] citation.";
let tree = parse(input, None);
let citation = tree
.descendants()
.find_map(Citation::cast)
.expect("Should find Citation");
let keys = citation.keys();
assert_eq!(keys.len(), 3);
let key_texts: Vec<_> = keys.iter().map(|k| k.text()).collect();
assert!(key_texts.contains(&"key1".to_string()));
assert!(key_texts.contains(&"key2".to_string()));
assert!(key_texts.contains(&"key3".to_string()));
}
#[test]
fn citation_with_single_key() {
let input = "Text with [@singlekey] citation.";
let tree = parse(input, None);
let citation = tree
.descendants()
.find_map(Citation::cast)
.expect("Should find Citation");
let keys = citation.keys();
assert_eq!(keys.len(), 1);
assert_eq!(keys[0].text(), "singlekey");
}
#[test]
fn empty_list_items() {
let input = "- \n- \n";
let tree = parse(input, None);
let list = tree
.descendants()
.find_map(List::cast)
.expect("Should find List");
assert_eq!(list.items().count(), 2, "Should have 2 items even if empty");
}
#[test]
fn footnote_definition_is_simple_with_continuation() {
let input = "[^1]: First line of text\n that continues here.";
let tree = parse(input, None);
let def = tree
.descendants()
.find_map(FootnoteDefinition::cast)
.expect("Should find FootnoteDefinition");
assert!(
def.is_simple(),
"Footnote with continuation should be simple"
);
}
#[test]
fn footnote_definition_is_not_simple_with_blank_line() {
let input = "[^1]: First paragraph.\n\n Second paragraph.";
let tree = parse(input, None);
let def = tree
.descendants()
.find_map(FootnoteDefinition::cast)
.expect("Should find FootnoteDefinition");
assert!(
!def.is_simple(),
"Multi-paragraph footnote should not be simple"
);
}