rocal_ui/enums/
html_element.rs

1use std::fmt;
2
3use syn::{
4    parse::{Parse, ParseStream},
5    Ident,
6};
7
8#[derive(Debug, Clone)]
9pub enum HtmlElement {
10    Html,
11    Base,
12    Head,
13    Link,
14    Meta,
15    Style,
16    Title,
17    Body,
18    Address,
19    Article,
20    Aside,
21    Footer,
22    Header,
23    H1,
24    H2,
25    H3,
26    H4,
27    H5,
28    H6,
29    Hgroup,
30    Main,
31    Nav,
32    Section,
33    Search,
34    Blockquote,
35    Dd,
36    Div,
37    Dl,
38    Dt,
39    Figcaption,
40    Figure,
41    Hr,
42    Li,
43    Menu,
44    Ol,
45    P,
46    Pre,
47    Ul,
48    A,
49    Abbr,
50    B,
51    Bdi,
52    Bdo,
53    Br,
54    Cite,
55    Code,
56    Data,
57    Dfn,
58    Em,
59    I,
60    Kbd,
61    Mark,
62    Q,
63    Rp,
64    Rt,
65    Ruby,
66    S,
67    Samp,
68    Small,
69    Span,
70    Strong,
71    Sub,
72    Sup,
73    Time,
74    U,
75    Var,
76    Wbr,
77    Area,
78    Audio,
79    Img,
80    Map,
81    Track,
82    Video,
83    Embed,
84    Fencedframe,
85    Iframe,
86    Object,
87    Picture,
88    Source,
89    Svg,
90    Path,
91    Math,
92    Canvas,
93    Noscript,
94    Script,
95    Del,
96    Ins,
97    Caption,
98    Col,
99    Colgroup,
100    Table,
101    Tbody,
102    Td,
103    Tfoot,
104    Th,
105    Thead,
106    Tr,
107    Button,
108    Datalist,
109    FieldSet,
110    Form,
111    Input,
112    Label,
113    Legend,
114    Meter,
115    Optgroup,
116    Option,
117    Output,
118    Progress,
119    Select,
120    Selectedcontent,
121    Textarea,
122    Details,
123    Dialog,
124    Summary,
125    Slot,
126    Template,
127    Fragment,
128}
129
130impl HtmlElement {
131    const VOID_ELEMENTS: [HtmlElement; 14] = [
132        HtmlElement::Area,
133        HtmlElement::Base,
134        HtmlElement::Br,
135        HtmlElement::Col,
136        HtmlElement::Embed,
137        HtmlElement::Hr,
138        HtmlElement::Img,
139        HtmlElement::Input,
140        HtmlElement::Link,
141        HtmlElement::Meta,
142        HtmlElement::Source,
143        HtmlElement::Track,
144        HtmlElement::Wbr,
145        HtmlElement::Path,
146    ];
147
148    #[allow(dead_code)]
149    const OPTIONAL_CLOSING_ELEMENTS: [HtmlElement; 15] = [
150        HtmlElement::Html,
151        HtmlElement::Head,
152        HtmlElement::Body,
153        HtmlElement::P,
154        HtmlElement::Li,
155        HtmlElement::Dt,
156        HtmlElement::Dd,
157        HtmlElement::Option,
158        HtmlElement::Thead,
159        HtmlElement::Th,
160        HtmlElement::Tbody,
161        HtmlElement::Tr,
162        HtmlElement::Td,
163        HtmlElement::Tfoot,
164        HtmlElement::Colgroup,
165    ];
166
167    pub fn is_void(&self) -> bool {
168        Self::VOID_ELEMENTS.contains(&self)
169    }
170}
171
172impl fmt::Display for HtmlElement {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        let tag = match self {
175            HtmlElement::Html => "html",
176            HtmlElement::Base => "base",
177            HtmlElement::Head => "head",
178            HtmlElement::Link => "link",
179            HtmlElement::Meta => "meta",
180            HtmlElement::Style => "style",
181            HtmlElement::Title => "title",
182            HtmlElement::Body => "body",
183            HtmlElement::Address => "address",
184            HtmlElement::Article => "article",
185            HtmlElement::Aside => "aside",
186            HtmlElement::Footer => "footer",
187            HtmlElement::Header => "header",
188            HtmlElement::H1 => "h1",
189            HtmlElement::H2 => "h2",
190            HtmlElement::H3 => "h3",
191            HtmlElement::H4 => "h4",
192            HtmlElement::H5 => "h5",
193            HtmlElement::H6 => "h6",
194            HtmlElement::Hgroup => "hgroup",
195            HtmlElement::Main => "main",
196            HtmlElement::Nav => "nav",
197            HtmlElement::Section => "section",
198            HtmlElement::Search => "search",
199            HtmlElement::Blockquote => "blockquote",
200            HtmlElement::Dd => "dd",
201            HtmlElement::Div => "div",
202            HtmlElement::Dl => "dl",
203            HtmlElement::Dt => "dt",
204            HtmlElement::Figcaption => "figcaption",
205            HtmlElement::Figure => "figure",
206            HtmlElement::Hr => "hr",
207            HtmlElement::Li => "li",
208            HtmlElement::Menu => "menu",
209            HtmlElement::Ol => "ol",
210            HtmlElement::P => "p",
211            HtmlElement::Pre => "pre",
212            HtmlElement::Ul => "ul",
213            HtmlElement::A => "a",
214            HtmlElement::Abbr => "abbr",
215            HtmlElement::B => "b",
216            HtmlElement::Bdi => "bdi",
217            HtmlElement::Bdo => "bdo",
218            HtmlElement::Br => "br",
219            HtmlElement::Cite => "cite",
220            HtmlElement::Code => "code",
221            HtmlElement::Data => "data",
222            HtmlElement::Dfn => "dfn",
223            HtmlElement::Em => "em",
224            HtmlElement::I => "i",
225            HtmlElement::Kbd => "kbd",
226            HtmlElement::Mark => "mark",
227            HtmlElement::Q => "q",
228            HtmlElement::Rp => "rp",
229            HtmlElement::Rt => "rt",
230            HtmlElement::Ruby => "ruby",
231            HtmlElement::S => "s",
232            HtmlElement::Samp => "samp",
233            HtmlElement::Small => "small",
234            HtmlElement::Span => "span",
235            HtmlElement::Strong => "strong",
236            HtmlElement::Sub => "sub",
237            HtmlElement::Sup => "sup",
238            HtmlElement::Time => "time",
239            HtmlElement::U => "u",
240            HtmlElement::Var => "var",
241            HtmlElement::Wbr => "wbr",
242            HtmlElement::Area => "area",
243            HtmlElement::Audio => "audio",
244            HtmlElement::Img => "img",
245            HtmlElement::Map => "map",
246            HtmlElement::Track => "track",
247            HtmlElement::Video => "video",
248            HtmlElement::Embed => "embed",
249            HtmlElement::Fencedframe => "fencedframe",
250            HtmlElement::Iframe => "iframe",
251            HtmlElement::Object => "object",
252            HtmlElement::Picture => "picture",
253            HtmlElement::Source => "source",
254            HtmlElement::Svg => "svg",
255            HtmlElement::Path => "path",
256            HtmlElement::Math => "math",
257            HtmlElement::Canvas => "canvas",
258            HtmlElement::Noscript => "noscript",
259            HtmlElement::Script => "script",
260            HtmlElement::Del => "del",
261            HtmlElement::Ins => "ins",
262            HtmlElement::Caption => "caption",
263            HtmlElement::Col => "col",
264            HtmlElement::Colgroup => "colgroup",
265            HtmlElement::Table => "table",
266            HtmlElement::Tbody => "tbody",
267            HtmlElement::Td => "td",
268            HtmlElement::Tfoot => "tfoot",
269            HtmlElement::Th => "th",
270            HtmlElement::Thead => "thead",
271            HtmlElement::Tr => "tr",
272            HtmlElement::Button => "button",
273            HtmlElement::Datalist => "datalist",
274            HtmlElement::FieldSet => "fieldset",
275            HtmlElement::Form => "form",
276            HtmlElement::Input => "input",
277            HtmlElement::Label => "label",
278            HtmlElement::Legend => "legend",
279            HtmlElement::Meter => "meter",
280            HtmlElement::Optgroup => "optgroup",
281            HtmlElement::Option => "option",
282            HtmlElement::Output => "output",
283            HtmlElement::Progress => "progress",
284            HtmlElement::Select => "select",
285            HtmlElement::Selectedcontent => "selectedcontent",
286            HtmlElement::Textarea => "textarea",
287            HtmlElement::Details => "details",
288            HtmlElement::Dialog => "dialog",
289            HtmlElement::Summary => "summary",
290            HtmlElement::Slot => "slot",
291            HtmlElement::Template => "template",
292            HtmlElement::Fragment => "",
293        };
294
295        write!(f, "{tag}")
296    }
297}
298
299impl HtmlElement {
300    pub fn from_str(s: &str) -> Option<Self> {
301        use HtmlElement::*;
302        match s {
303            "html" => Some(Html),
304            "base" => Some(Base),
305            "head" => Some(Head),
306            "link" => Some(Link),
307            "meta" => Some(Meta),
308            "style" => Some(Style),
309            "title" => Some(Title),
310            "body" => Some(Body),
311            "address" => Some(Address),
312            "article" => Some(Article),
313            "aside" => Some(Aside),
314            "footer" => Some(Footer),
315            "header" => Some(Header),
316            "h1" => Some(H1),
317            "h2" => Some(H2),
318            "h3" => Some(H3),
319            "h4" => Some(H4),
320            "h5" => Some(H5),
321            "h6" => Some(H6),
322            "hgroup" => Some(Hgroup),
323            "main" => Some(Main),
324            "nav" => Some(Nav),
325            "section" => Some(Section),
326            "search" => Some(Search),
327            "blockquote" => Some(Blockquote),
328            "dd" => Some(Dd),
329            "div" => Some(Div),
330            "dl" => Some(Dl),
331            "dt" => Some(Dt),
332            "figcaption" => Some(Figcaption),
333            "figure" => Some(Figure),
334            "hr" => Some(Hr),
335            "li" => Some(Li),
336            "menu" => Some(Menu),
337            "ol" => Some(Ol),
338            "p" => Some(P),
339            "pre" => Some(Pre),
340            "ul" => Some(Ul),
341            "a" => Some(A),
342            "abbr" => Some(Abbr),
343            "b" => Some(B),
344            "bdi" => Some(Bdi),
345            "bdo" => Some(Bdo),
346            "br" => Some(Br),
347            "cite" => Some(Cite),
348            "code" => Some(Code),
349            "data" => Some(Data),
350            "dfn" => Some(Dfn),
351            "em" => Some(Em),
352            "i" => Some(I),
353            "kbd" => Some(Kbd),
354            "mark" => Some(Mark),
355            "q" => Some(Q),
356            "rp" => Some(Rp),
357            "rt" => Some(Rt),
358            "ruby" => Some(Ruby),
359            "s" => Some(S),
360            "samp" => Some(Samp),
361            "small" => Some(Small),
362            "span" => Some(Span),
363            "strong" => Some(Strong),
364            "sub" => Some(Sub),
365            "sup" => Some(Sup),
366            "time" => Some(Time),
367            "u" => Some(U),
368            "var" => Some(Var),
369            "wbr" => Some(Wbr),
370            "area" => Some(Area),
371            "audio" => Some(Audio),
372            "img" => Some(Img),
373            "map" => Some(Map),
374            "track" => Some(Track),
375            "video" => Some(Video),
376            "embed" => Some(Embed),
377            "fencedframe" => Some(Fencedframe),
378            "iframe" => Some(Iframe),
379            "object" => Some(Object),
380            "picture" => Some(Picture),
381            "source" => Some(Source),
382            "svg" => Some(Svg),
383            "path" => Some(Path),
384            "math" => Some(Math),
385            "canvas" => Some(Canvas),
386            "noscript" => Some(Noscript),
387            "script" => Some(Script),
388            "del" => Some(Del),
389            "ins" => Some(Ins),
390            "caption" => Some(Caption),
391            "col" => Some(Col),
392            "colgroup" => Some(Colgroup),
393            "table" => Some(Table),
394            "tbody" => Some(Tbody),
395            "td" => Some(Td),
396            "tfoot" => Some(Tfoot),
397            "th" => Some(Th),
398            "thead" => Some(Thead),
399            "tr" => Some(Tr),
400            "button" => Some(Button),
401            "datalist" => Some(Datalist),
402            "fieldset" => Some(FieldSet),
403            "form" => Some(Form),
404            "input" => Some(Input),
405            "label" => Some(Label),
406            "legend" => Some(Legend),
407            "meter" => Some(Meter),
408            "optgroup" => Some(Optgroup),
409            "option" => Some(Option),
410            "output" => Some(Output),
411            "progress" => Some(Progress),
412            "select" => Some(Select),
413            "selectedcontent" => Some(Selectedcontent),
414            "textarea" => Some(Textarea),
415            "details" => Some(Details),
416            "dialog" => Some(Dialog),
417            "summary" => Some(Summary),
418            "slot" => Some(Slot),
419            "template" => Some(Template),
420            "fragment" => Some(Fragment),
421            _ => None,
422        }
423    }
424}
425
426impl PartialEq for HtmlElement {
427    fn eq(&self, other: &Self) -> bool {
428        self.to_string() == other.to_string()
429    }
430}
431
432impl Parse for HtmlElement {
433    fn parse(input: ParseStream) -> Result<Self, syn::Error> {
434        let element: Ident = input.parse()?;
435        let element = HtmlElement::from_str(&element.to_string())
436            .ok_or(HtmlElement::Fragment)
437            .map_err(|_| syn::Error::new(input.span(), "The element is unavailable in HTML5"))?;
438        Ok(element)
439    }
440}