subscript_compiler/frontend/
query.rs1use 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}