Skip to main content

katana_markdown_engine/document/
impls.rs

1use super::types::{KmeDocument, KmeNode, KmeNodeId, KmeNodeKind};
2use crate::TextFingerprint;
3
4impl KmeDocument {
5    pub fn nodes_by_kind(&self, predicate: impl Fn(&KmeNodeKind) -> bool) -> Vec<&KmeNode> {
6        self.nodes
7            .iter()
8            .filter(|node| predicate(&node.kind))
9            .collect()
10    }
11
12    pub fn node_by_id(&self, id: &KmeNodeId) -> Option<&KmeNode> {
13        self.nodes.iter().find(|node| &node.id == id)
14    }
15}
16
17impl KmeNode {
18    pub(crate) fn new(
19        kind: KmeNodeKind,
20        raw: &str,
21        ordinal: usize,
22        source: crate::SourceSpan,
23    ) -> Self {
24        Self {
25            id: KmeNodeId::from_parts(&kind, raw, ordinal),
26            kind,
27            source,
28            children: Vec::new(),
29        }
30    }
31}
32
33impl KmeNodeId {
34    pub(crate) fn from_parts(kind: &KmeNodeKind, raw: &str, ordinal: usize) -> Self {
35        let seed = format!("{}\0{}\0{}", kind.label(), raw, ordinal);
36        Self(format!("kme-{}", TextFingerprint::for_text(&seed).value))
37    }
38}
39
40impl KmeNodeKind {
41    pub fn label(&self) -> &'static str {
42        match self {
43            Self::Heading(_) => "heading",
44            Self::Paragraph => "paragraph",
45            Self::Emoji(_) => "emoji",
46            Self::HtmlBlock(_) => "html-block",
47            Self::List(_) => "list",
48            Self::CodeBlock(_) => "code-block",
49            Self::Table(_) => "table",
50            Self::BlockQuote => "blockquote",
51            Self::Alert { .. } => "alert",
52            Self::DescriptionList { .. } => "description-list",
53            Self::ThematicBreak => "thematic-break",
54            Self::RawBlock { .. } => "raw-block",
55        }
56    }
57}