Skip to main content

marco_core/intelligence/markdown/
ast.rs

1//! Canonical markdown AST re-exports for intelligence subsystems.
2
3pub use crate::parser::{Document, Node, NodeKind, Position, Span};
4
5/// Alias types used by the intelligence boundary.
6pub type MarkdownDocument = Document;
7pub type MarkdownNode = Node;
8pub type MarkdownNodeKind = NodeKind;
9
10/// Return this node's span if available.
11pub fn node_span(node: &Node) -> Option<Span> {
12    node.span
13}
14
15/// True when the node kind is considered block-level.
16pub fn is_block_kind(kind: &NodeKind) -> bool {
17    matches!(
18        kind,
19        NodeKind::Heading { .. }
20            | NodeKind::Paragraph
21            | NodeKind::CodeBlock { .. }
22            | NodeKind::ThematicBreak
23            | NodeKind::List { .. }
24            | NodeKind::ListItem
25            | NodeKind::DefinitionList
26            | NodeKind::DefinitionTerm
27            | NodeKind::DefinitionDescription
28            | NodeKind::TaskCheckbox { .. }
29            | NodeKind::Blockquote
30            | NodeKind::Admonition { .. }
31            | NodeKind::TabGroup
32            | NodeKind::TabItem { .. }
33            | NodeKind::SliderDeck { .. }
34            | NodeKind::Slide { .. }
35            | NodeKind::Table { .. }
36            | NodeKind::TableRow { .. }
37            | NodeKind::TableCell { .. }
38            | NodeKind::HtmlBlock { .. }
39            | NodeKind::FootnoteDefinition { .. }
40            | NodeKind::MermaidDiagram { .. }
41    )
42}
43
44/// True when the node kind is considered inline-level.
45pub fn is_inline_kind(kind: &NodeKind) -> bool {
46    matches!(
47        kind,
48        NodeKind::Text(_)
49            | NodeKind::TaskCheckboxInline { .. }
50            | NodeKind::Emphasis
51            | NodeKind::Strong
52            | NodeKind::StrongEmphasis
53            | NodeKind::Strikethrough
54            | NodeKind::Mark
55            | NodeKind::Superscript
56            | NodeKind::Subscript
57            | NodeKind::Link { .. }
58            | NodeKind::LinkReference { .. }
59            | NodeKind::FootnoteReference { .. }
60            | NodeKind::Image { .. }
61            | NodeKind::CodeSpan(_)
62            | NodeKind::InlineHtml(_)
63            | NodeKind::HardBreak
64            | NodeKind::SoftBreak
65            | NodeKind::PlatformMention { .. }
66            | NodeKind::InlineMath { .. }
67            | NodeKind::DisplayMath { .. }
68    )
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn smoke_test_block_and_inline_classification() {
77        assert!(is_block_kind(&NodeKind::Paragraph));
78        assert!(is_block_kind(&NodeKind::CodeBlock {
79            language: None,
80            code: "x".to_string()
81        }));
82        assert!(!is_block_kind(&NodeKind::Text("x".to_string())));
83
84        assert!(is_inline_kind(&NodeKind::Text("x".to_string())));
85        assert!(is_inline_kind(&NodeKind::Link {
86            url: "https://example.com".to_string(),
87            title: None
88        }));
89        assert!(!is_inline_kind(&NodeKind::Paragraph));
90    }
91}