1use std::{convert, fmt};
4
5use atoms::{tokens, FragmentClose, FragmentOpen};
6use proc_macro2::{Ident, TokenStream};
7use quote::ToTokens;
8use syn::{parse::ParseStream, ExprPath, LitStr, Token};
9
10pub mod atoms;
11mod attribute;
12mod node_name;
13mod node_value;
14pub mod parse;
15mod parser_ext;
16mod raw_text;
17
18pub use attribute::{
19 AttributeValueExpr, FnBinding, KVAttributeValue, KeyedAttribute, KeyedAttributeValue,
20 NodeAttribute,
21};
22pub use node_name::{NodeName, NodeNameFragment};
23pub use node_value::{InvalidBlock, NodeBlock};
24
25pub use self::raw_text::RawText;
26use crate::recoverable::{ParseRecoverable, RecoverableContext};
27
28#[derive(Debug, Clone, PartialEq, Eq)]
30pub enum NodeType {
31 Element,
32 Text,
33 Comment,
34 Doctype,
35 Block,
36 Fragment,
37 RawText,
38 Custom,
39}
40
41impl fmt::Display for NodeType {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(
44 f,
45 "{}",
46 match self {
47 Self::Element => "NodeType::Element",
48 Self::Text => "NodeType::Text",
49 Self::RawText => "NodeType::RawText",
50 Self::Comment => "NodeType::Comment",
51 Self::Doctype => "NodeType::Doctype",
52 Self::Block => "NodeType::Block",
53 Self::Fragment => "NodeType::Fragment",
54 Self::Custom => "NodeType::Custom",
55 }
56 )
57 }
58}
59
60#[derive(Clone, Debug)]
62pub enum Node<C = Infallible> {
63 Comment(NodeComment),
64 Doctype(NodeDoctype),
65 Fragment(NodeFragment<C>),
66 Element(NodeElement<C>),
67 Block(NodeBlock),
68 Text(NodeText),
69 RawText(RawText<C>),
70 Custom(C),
71}
72impl<C: CustomNode> ToTokens for Node<C> {
74 fn to_tokens(&self, tokens: &mut TokenStream) {
75 match self {
76 Self::Comment(comment) => comment.to_tokens(tokens),
77 Self::Doctype(doctype) => doctype.to_tokens(tokens),
78 Self::Fragment(fragment) => fragment.to_tokens(tokens),
79 Self::Element(element) => element.to_tokens(tokens),
80 Self::Block(block) => block.to_tokens(tokens),
81 Self::Text(text) => text.to_tokens(tokens),
82 Self::RawText(raw_text) => raw_text.to_tokens(tokens),
83 Self::Custom(custom) => custom.to_tokens(tokens),
84 }
85 }
86}
87
88impl<C: CustomNode> Node<C> {
89 pub fn flatten(mut self) -> Vec<Self> {
90 let children = self
91 .children_mut()
92 .map(|children| children.drain(..))
93 .into_iter()
94 .flatten()
95 .collect::<Vec<_>>();
96
97 std::iter::once(self)
98 .chain(children.into_iter().flat_map(Self::flatten))
99 .collect()
100 }
101 pub fn r#type(&self) -> NodeType {
103 match &self {
104 Self::Element(_) => NodeType::Element,
105 Self::Text(_) => NodeType::Text,
106 Self::Comment(_) => NodeType::Comment,
107 Self::Doctype(_) => NodeType::Element,
108 Self::Block(_) => NodeType::Block,
109 Self::Fragment(_) => NodeType::Fragment,
110 Self::RawText(_) => NodeType::RawText,
111 Self::Custom(_) => NodeType::Custom,
112 }
113 }
114
115 pub fn children(&self) -> Option<&Vec<Self>> {
117 match self {
118 Self::Fragment(NodeFragment { children, .. })
119 | Self::Element(NodeElement { children, .. }) => Some(children),
120 _ => None,
121 }
122 }
123
124 pub fn children_mut(&mut self) -> Option<&mut Vec<Self>> {
126 match self {
127 Self::Fragment(NodeFragment { children, .. })
128 | Self::Element(NodeElement { children, .. }) => Some(children),
129 _ => None,
130 }
131 }
132}
133
134#[derive(Clone, Debug)]
139pub struct NodeElement<C> {
140 pub open_tag: atoms::OpenTag,
141 pub children: Vec<Node<C>>,
142 pub close_tag: Option<atoms::CloseTag>,
143}
144impl<C: CustomNode> ToTokens for NodeElement<C> {
146 fn to_tokens(&self, tokens: &mut TokenStream) {
147 self.open_tag.to_tokens(tokens);
148 for child in &self.children {
149 child.to_tokens(tokens);
150 }
151 if let Some(close_tag) = &self.close_tag {
152 close_tag.to_tokens(tokens);
153 }
154 }
155}
156
157impl<C: CustomNode> NodeElement<C> {
158 pub fn name(&self) -> &NodeName {
159 &self.open_tag.name
160 }
161 pub fn attributes(&self) -> &[NodeAttribute] {
162 &self.open_tag.attributes
163 }
164 pub fn attributes_mut(&mut self) -> &mut Vec<NodeAttribute> {
165 &mut self.open_tag.attributes
166 }
167 pub fn chidlren(&self) -> &[Node<C>] {
168 &self.children
169 }
170 pub fn children_mut(&mut self) -> &mut Vec<Node<C>> {
171 &mut self.children
172 }
173}
174
175#[derive(Clone, Debug, syn_derive::Parse, syn_derive::ToTokens)]
179pub struct NodeText {
180 pub value: LitStr,
182}
183
184impl NodeText {
185 pub fn value_string(&self) -> String {
187 self.value.value()
188 }
189}
190
191#[derive(Clone, Debug, syn_derive::Parse, syn_derive::ToTokens)]
196pub struct NodeComment {
197 pub token_start: tokens::ComStart,
198 pub value: LitStr,
200 pub token_end: tokens::ComEnd,
201}
202#[derive(Clone, Debug, syn_derive::ToTokens)]
210pub struct NodeDoctype {
211 pub token_start: tokens::DocStart,
212 pub token_doctype: Ident,
214 pub value: RawText,
216 pub token_end: Token![>],
217}
218
219#[derive(Clone, Debug)]
223pub struct NodeFragment<C> {
224 pub tag_open: FragmentOpen,
226 pub children: Vec<Node<C>>,
228 pub tag_close: Option<FragmentClose>,
230}
231impl<C: CustomNode> ToTokens for NodeFragment<C> {
233 fn to_tokens(&self, tokens: &mut TokenStream) {
234 self.tag_open.to_tokens(tokens);
235 for child in &self.children {
236 child.to_tokens(tokens);
237 }
238 if let Some(close_tag) = &self.tag_close {
239 close_tag.to_tokens(tokens);
240 }
241 }
242}
243
244impl<C> NodeFragment<C> {
245 pub fn children(&self) -> &[Node<C>] {
246 &self.children
247 }
248 pub fn children_mut(&mut self) -> &mut Vec<Node<C>> {
249 &mut self.children
250 }
251}
252
253fn path_to_string(expr: &ExprPath) -> String {
254 expr.path
255 .segments
256 .iter()
257 .map(|segment| segment.ident.to_string())
258 .collect::<Vec<String>>()
259 .join("::")
260}
261
262pub trait CustomNode: ParseRecoverable + ToTokens {
263 fn peek_element(input: ParseStream) -> bool;
269}
270
271#[derive(Clone, Copy, Debug, Eq, PartialEq)]
274pub struct Infallible(convert::Infallible);
275
276impl From<convert::Infallible> for Infallible {
277 fn from(s: convert::Infallible) -> Self {
278 match s {}
279 }
280}
281impl ToTokens for Infallible {
282 fn to_tokens(&self, _tokens: &mut TokenStream) {
283 match self.0 {}
284 }
285}
286impl ParseRecoverable for Infallible {
287 fn parse_recoverable(_: &mut RecoverableContext, _: ParseStream) -> Option<Self> {
288 unreachable!("Infallible::peek_element returns false")
289 }
290}
291impl CustomNode for Infallible {
292 fn peek_element(_: ParseStream) -> bool {
293 false
294 }
295}