subscript_compiler/frontend/
query.rs

1//! Node transformations.
2use std::iter::FromIterator;
3use std::collections::{HashSet, HashMap};
4use std::rc::Rc;
5use std::borrow::Cow;
6use serde::{Serialize, Deserialize};
7use crate::frontend::data::{
8    Atom,
9    Text,
10    Enclosure,
11    EnclosureKind,
12    INLINE_MATH_TAG,
13    RewriteRule,
14};
15use crate::frontend::ast::{Node, Tag};
16
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum HeadingKind {
20    H1,
21    H2,
22    H3,
23    H4,
24    H5,
25    H6,
26}
27
28impl HeadingKind {
29    pub fn from_str(x: &str) -> Option<Self> {
30        match x {
31            "h1" => Some(HeadingKind::H1),
32            "h2" => Some(HeadingKind::H2),
33            "h3" => Some(HeadingKind::H3),
34            "h4" => Some(HeadingKind::H4),
35            "h5" => Some(HeadingKind::H5),
36            "h6" => Some(HeadingKind::H6),
37            _ => None
38        }
39    }
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct Heading {
44    kind: HeadingKind,
45    text: String,
46}
47
48pub fn query_heading_nodes<'a>(node: &Node<'a>) -> Vec<Heading> {
49    pub fn go<'a>(node: &Node<'a>) -> Vec<Tag<'a>> {
50        match node {
51            Node::Tag(tag) if tag.has_name("h1") => vec![tag.clone()],
52            Node::Tag(tag) if tag.has_name("h2") => vec![tag.clone()],
53            Node::Tag(tag) if tag.has_name("h3") => vec![tag.clone()],
54            Node::Tag(tag) if tag.has_name("h4") => vec![tag.clone()],
55            Node::Tag(tag) if tag.has_name("h5") => vec![tag.clone()],
56            Node::Tag(tag) if tag.has_name("h6") => vec![tag.clone()],
57            Node::Tag(node) => {
58                node.children
59                    .iter()
60                    .flat_map(go)
61                    .collect::<Vec<_>>()
62            }
63            Node::Enclosure(node) => {
64                node.data.children
65                    .iter()
66                    .flat_map(go)
67                    .collect::<Vec<_>>()
68            }
69            Node::Ident(..) => Vec::new(),
70            Node::String(..) => Vec::new(),
71            Node::InvalidToken(..) => Vec::new(),
72        }
73    }
74    go(node)
75        .into_iter()
76        .map(|tag| {
77            let kind = HeadingKind::from_str(tag.name()).unwrap();
78            let text = tag.children
79                .iter()
80                .map(Node::to_string)
81                .collect::<Vec<_>>()
82                .join(" ");
83            Heading{kind, text}
84        })
85        .collect::<Vec<_>>()
86}