panache_parser/syntax/
block_quotes.rs1use super::ast::{AstChildren, support};
4use super::{AstNode, PanacheLanguage, SyntaxKind, SyntaxNode};
5
6pub struct BlockQuote(SyntaxNode);
7
8impl AstNode for BlockQuote {
9 type Language = PanacheLanguage;
10
11 fn can_cast(kind: SyntaxKind) -> bool {
12 kind == SyntaxKind::BLOCK_QUOTE
13 }
14
15 fn cast(syntax: SyntaxNode) -> Option<Self> {
16 if Self::can_cast(syntax.kind()) {
17 Some(Self(syntax))
18 } else {
19 None
20 }
21 }
22
23 fn syntax(&self) -> &SyntaxNode {
24 &self.0
25 }
26}
27
28impl BlockQuote {
29 pub fn blocks(&self) -> impl Iterator<Item = SyntaxNode> {
31 self.0.children().filter(|child| {
32 !matches!(
33 child.kind(),
34 SyntaxKind::BLOCK_QUOTE_MARKER | SyntaxKind::WHITESPACE
35 )
36 })
37 }
38
39 pub fn nested_blockquotes(&self) -> AstChildren<BlockQuote> {
41 support::children(&self.0)
42 }
43
44 pub fn contains_node(node: &SyntaxNode) -> bool {
46 node.ancestors()
47 .any(|ancestor| Self::can_cast(ancestor.kind()))
48 }
49
50 pub fn depth(&self) -> usize {
52 self.0
53 .ancestors()
54 .filter(|ancestor| Self::can_cast(ancestor.kind()))
55 .count()
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use crate::parse;
63
64 #[test]
65 fn blockquote_cast_and_blocks() {
66 let tree = parse("> Intro\n>\n> - Item\n>\n> Outro\n", None);
67
68 let bq = tree
69 .descendants()
70 .find_map(BlockQuote::cast)
71 .expect("blockquote");
72
73 let kinds: Vec<_> = bq.blocks().map(|n| n.kind()).collect();
74 assert!(kinds.contains(&SyntaxKind::PARAGRAPH));
75 assert!(kinds.contains(&SyntaxKind::LIST));
76 }
77
78 #[test]
79 fn blockquote_nested_blockquotes_iterator() {
80 let tree = parse("> outer\n>\n> > inner\n", None);
81
82 let outer = tree
83 .descendants()
84 .find_map(BlockQuote::cast)
85 .expect("outer blockquote");
86
87 assert!(outer.nested_blockquotes().next().is_some());
88 assert_eq!(outer.depth(), 1);
89 }
90
91 #[test]
92 fn blockquote_contains_node_detects_membership() {
93 let tree = parse("> quote\n", None);
94 let blockquote = tree
95 .descendants()
96 .find_map(BlockQuote::cast)
97 .expect("blockquote");
98 assert!(BlockQuote::contains_node(blockquote.syntax()));
99 }
100}