simple_rsx/
lib.rs

1//! Simple RSX - A lightweight JSX-like library for Rust
2//!
3//! This crate provides a simple way to write HTML-like components in Rust using JSX-style syntax.
4//! It's perfect for building user interfaces or generating HTML content with a familiar, component-based approach.
5//!
6//! # Quick Start
7//!
8//! ```rust
9//! use simple_rsx::*;
10//!
11//! // Create a simple component
12//! let greeting = rsx!(
13//!     <div class="greeting">
14//!         <h1>Hello, World!</h1>
15//!         <p>Welcome to Simple RSX</p>
16//!     </div>
17//! );
18//!
19//! // Convert to HTML string
20//! println!("{}", greeting); // Outputs the HTML
21//! ```
22//!
23//! # Features
24//!
25//! - JSX-like syntax with the `rsx!` macro
26//! - Component-based architecture
27//! - Type-safe attributes and children
28//! - Easy conversion to HTML strings
29//! - Support for custom components
30//!
31//! # Custom Components
32//!
33//! ```rust
34//! use simple_rsx::*;
35//!
36//! #[derive(Default)]
37//! struct ButtonProps {
38//!     text: String,
39//!     children: Vec<Node>,
40//! }
41//!
42//! #[component]
43//! fn Button(props: ButtonProps) -> Node {
44//!     rsx!(
45//!         <button class="btn">
46//!             {props.text}
47//!             {props.children}
48//!         </button>
49//!     )
50//! }
51//! ```
52
53use indexmap::IndexMap;
54pub use simple_rsx_macros::{component, either, rsx};
55use std::fmt::Display;
56
57/// A trait for converting values into HTML attribute strings.
58///
59/// This trait is automatically implemented for any type that implements `ToString`,
60/// making it easy to use various types as attribute values.
61///
62/// # Example
63///
64/// ```rust
65/// use simple_rsx::*;
66///
67/// let element = rsx!(<div id="my-id" hidden={true} />);
68/// ```
69pub trait Attribute {
70    fn value(&self) -> String;
71}
72
73/// A trait for handling optional attribute values.
74///
75/// This trait is automatically implemented for `Option<T>` where T implements `ToString`.
76/// It allows for graceful handling of optional attributes, rendering them as empty strings when None.
77///
78/// # Example
79///
80/// ```rust
81/// use simple_rsx::*;
82///
83/// let maybe_title = Some("Hello".to_string());
84/// let element = rsx!(<div title={maybe_title} />);
85/// ```
86pub trait OptionAttribute {
87    fn value(&self) -> String;
88}
89
90impl<T: ToString> Attribute for T {
91    fn value(&self) -> String {
92        self.to_string()
93    }
94}
95
96impl<T: ToString> OptionAttribute for Option<T> {
97    fn value(&self) -> String {
98        match self {
99            Some(t) => t.to_string(),
100            None => String::new(),
101        }
102    }
103}
104
105/// Represents an HTML element with its tag name, attributes, and children.
106///
107/// Elements are the building blocks of the RSX tree structure. Each element
108/// can have attributes (like class, id, etc.) and can contain other elements
109/// or text nodes as children.
110///
111/// You typically won't create Elements directly, but rather use the `rsx!` macro:
112///
113/// ```rust
114/// use simple_rsx::*;
115///
116/// let element = rsx!(
117///     <div class="container">
118///         <p>Hello world!</p>
119///     </div>
120/// );
121/// ```
122#[derive(Clone)]
123pub struct Element {
124    tag: String,
125    attributes: IndexMap<String, String>,
126    children: Vec<Node>,
127}
128
129impl Element {
130    /// Creates a new Element node with the specified tag name.
131    ///
132    /// # Example
133    ///
134    /// ```rust
135    /// use simple_rsx::*;
136    ///
137    /// let element = Element::new("div");
138    /// assert!(matches!(element, Node::Element(_)));
139    /// ```
140    pub fn new(tag: &str) -> Node {
141        Node::Element(Element {
142            tag: tag.to_string(),
143            attributes: IndexMap::new(),
144            children: Vec::new(),
145        })
146    }
147
148    /// Sets an attribute on the element.
149    ///
150    /// # Example
151    ///
152    /// ```rust
153    /// use simple_rsx::*;
154    ///
155    /// let mut node = Element::new("div");
156    /// let mut element = node.as_element_mut().unwrap();
157    /// element.set_attribute("class", "container");
158    /// ```
159    pub fn set_attribute(&mut self, name: &str, value: impl Attribute) {
160        self.attributes.insert(name.to_string(), value.value());
161    }
162
163    /// Adds a child node to this element.
164    ///
165    /// # Example
166    ///
167    /// ```rust
168    /// use simple_rsx::*;
169    ///
170    /// let mut parent_node = Element::new("div");
171    /// let mut parent = parent_node.as_element_mut().unwrap();
172    /// parent.append_child(Element::new("p"));
173    /// ```
174    pub fn append_child(&mut self, node: Node) {
175        self.children.push(node);
176    }
177}
178
179impl Node {
180    /// Attempts to get a mutable reference to the underlying Element if this node is an Element.
181    ///
182    /// Returns None if the node is not an Element (e.g., if it's Text or Fragment).
183    pub fn as_element_mut(&mut self) -> Option<&mut Element> {
184        match self {
185            Node::Element(el) => Some(el),
186            _ => None,
187        }
188    }
189
190    /// Adds a child node if this node is an Element.
191    ///
192    /// This method has no effect if the node is not an Element.
193    pub fn append_child(&mut self, node: Node) {
194        if let Node::Element(el) = self {
195            el.children.push(node);
196        }
197    }
198}
199
200/// A trait for creating reusable components.
201///
202/// Components are the heart of RSX's reusability model. They allow you to create
203/// custom elements with their own logic and state.
204///
205/// # Example
206///
207/// ```rust
208/// use simple_rsx::*;
209///
210/// struct Card;
211/// #[derive(Default)]
212/// struct CardProps {
213///     title: String,
214///     children: Vec<Node>,
215/// }
216///
217/// impl Component for Card {
218///     type Props = CardProps;
219///     fn render(&mut self, props: Self::Props) -> Node {
220///         rsx!(
221///             <div class="card">
222///                 <h2>{props.title}</h2>
223///                 <div class="card-content">{props.children}</div>
224///             </div>
225///         )
226///     }
227/// }
228/// ```
229pub trait Component {
230    /// The type of props this component accepts
231    type Props;
232
233    /// Renders the component with the given props
234    fn render(props: Self::Props) -> Node;
235}
236
237/// Represents a node in the RSX tree.
238///
239/// Nodes are the fundamental building blocks of RSX. They can be:
240/// - Elements (like `<div>` or `<p>`)
241/// - Text content
242/// - Fragments (groups of nodes)
243/// - Comments
244///
245/// # Example
246///
247/// ```rust
248/// use simple_rsx::*;
249///
250/// let text_node = Node::Text("Hello".to_string());
251/// let element_node = Element::new("div");
252/// let fragment = Node::Fragment(vec![text_node, element_node]);
253/// ```
254#[derive(Clone)]
255pub enum Node {
256    /// An HTML element with a tag name, attributes, and children
257    Element(Element),
258    /// Plain text content
259    Text(String),
260    /// A group of nodes without a wrapper element
261    Fragment(Vec<Node>),
262    /// An HTML comment
263    Comment(String),
264}
265
266impl From<String> for Node {
267    fn from(value: String) -> Self {
268        Node::Text(value)
269    }
270}
271
272impl From<&String> for Node {
273    fn from(value: &String) -> Self {
274        Node::Text(value.to_string())
275    }
276}
277
278impl From<&str> for Node {
279    fn from(value: &str) -> Self {
280        Node::Text(value.to_string())
281    }
282}
283
284impl From<&&str> for Node {
285    fn from(value: &&str) -> Self {
286        Node::Text(value.to_string())
287    }
288}
289
290impl<T: ToString> From<Vec<T>> for Node {
291    fn from(value: Vec<T>) -> Self {
292        Node::Fragment(
293            value
294                .into_iter()
295                .map(|t| Node::Text(t.to_string()))
296                .collect(),
297        )
298    }
299}
300
301impl<T: ToString> From<Option<T>> for Node {
302    fn from(value: Option<T>) -> Self {
303        match value {
304            Some(t) => Node::Text(t.to_string()),
305            None => Node::Text("".to_string()),
306        }
307    }
308}
309
310impl From<&Vec<String>> for Node {
311    fn from(value: &Vec<String>) -> Self {
312        Node::Fragment(
313            value
314                .iter()
315                .map(|item| Node::Text(item.to_string()))
316                .collect(),
317        )
318    }
319}
320
321impl From<i32> for Node {
322    fn from(value: i32) -> Self {
323        Node::Text(value.to_string())
324    }
325}
326
327impl From<u32> for Node {
328    fn from(value: u32) -> Self {
329        Node::Text(value.to_string())
330    }
331}
332
333impl From<u64> for Node {
334    fn from(value: u64) -> Self {
335        Node::Text(value.to_string())
336    }
337}
338
339impl FromIterator<u32> for Node {
340    fn from_iter<T: IntoIterator<Item = u32>>(iter: T) -> Self {
341        let mut result = Vec::new();
342        for item in iter {
343            result.push(Node::Text(item.to_string()));
344        }
345        Node::Fragment(result)
346    }
347}
348
349impl FromIterator<u64> for Node {
350    fn from_iter<T: IntoIterator<Item = u64>>(iter: T) -> Self {
351        let mut result = Vec::new();
352        for item in iter {
353            result.push(Node::Text(item.to_string()));
354        }
355        Node::Fragment(result)
356    }
357}
358
359impl FromIterator<i32> for Node {
360    fn from_iter<T: IntoIterator<Item = i32>>(iter: T) -> Self {
361        let mut result = Vec::new();
362        for item in iter {
363            result.push(Node::Text(item.to_string()));
364        }
365        Node::Fragment(result)
366    }
367}
368
369impl From<f32> for Node {
370    fn from(value: f32) -> Self {
371        Node::Text(value.to_string())
372    }
373}
374
375impl From<bool> for Node {
376    fn from(value: bool) -> Self {
377        Node::Text(value.to_string())
378    }
379}
380
381impl<I, F, R> From<std::iter::Map<I, F>> for Node
382where
383    I: Iterator,
384    F: FnMut(I::Item) -> R,
385    R: Into<Node>,
386    Vec<Node>: FromIterator<R>,
387{
388    fn from(iter: std::iter::Map<I, F>) -> Self {
389        let nodes: Vec<Node> = iter.collect();
390        Node::from(nodes)
391    }
392}
393
394impl Display for Node {
395    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
396        match self {
397            Node::Element(el) => {
398                write!(f, "<{}", el.tag)?;
399                for (key, value) in &el.attributes {
400                    write!(f, " {}=\"{}\"", key, value)?;
401                }
402                write!(f, ">")?;
403                for child in &el.children {
404                    write!(f, "{}", child)?;
405                }
406                write!(f, "</{}>", el.tag)?;
407                Ok(())
408            }
409            Node::Text(text) => {
410                write!(f, "{}", text)?;
411                Ok(())
412            }
413            Node::Fragment(nodes) => {
414                for node in nodes {
415                    write!(f, "{}", node)?;
416                }
417                Ok(())
418            }
419            Node::Comment(comment) => {
420                write!(f, "<!--{}-->", comment)?;
421                Ok(())
422            }
423        }
424    }
425}
426
427macro_rules! derive_elements {
428    (
429        $(
430            $(#[$tag_meta:meta])*
431            $tag:ident {
432                $(
433                    $(#[$attr_meta:meta])*
434                    $attr_name:ident : $attr_value:ty
435                ),* $(,)?
436            }
437        )*
438    ) => {
439        $(
440            #[allow(non_camel_case_types)]
441            $(#[$tag_meta])*
442            pub struct $tag;
443
444            paste::paste! {
445                #[derive(Default)]
446                #[allow(non_snake_case)]
447                pub struct [<HTML $tag:camel Element Props>] {
448                    // Global HTML attributes
449
450                    /// The child nodes of the element
451                    pub children: Vec<Node>,
452
453                    /// The id attribute specifies a unique id for an HTML element
454                    pub id: String,
455
456                    /// A unique key to identify the element
457                    pub key: String,
458
459                    /// The class attribute specifies one or more class names for an HTML element
460                    pub class: String,
461
462                    /// The style attribute specifies an inline CSS style for an element
463                    pub style: String,
464
465                    /// The title attribute specifies extra information about an element (displayed as a tooltip)
466                    pub title: Option<String>,
467                    /// The width attribute specifies the width of the image
468                    pub width: Option<String>,
469                    /// The height attribute specifies the height of the image
470                    pub height: Option<String>,
471
472                    /// Specifies whether an element is draggable or not
473                    pub draggable: bool,
474
475                    /// Specifies visibility of an element (hidden or visible)
476                    pub hidden: bool,
477
478                    /// Specifies a shortcut key to activate/focus an element
479                    pub accesskey: String,
480
481                    /// Specifies whether the content of an element is editable or not
482                    pub contenteditable: bool,
483
484                    /// Specifies the text direction for the content in an element
485                    pub dir: String,
486
487                    /// Specifies the tabbing order of an element (when the tab button is used)
488                    pub tabindex: Option<i32>,
489
490                    /// Specifies whether the element is to have its spelling and grammar checked
491                    pub spellcheck: bool,
492
493                    /// Specifies the language of the element's content
494                    pub lang: String,
495
496                    /// Specifies whether an element is translateable or not
497                    pub translate: bool,
498
499                    /// Controls whether and how text input is automatically capitalized
500                    pub autocapitalize: String,
501
502                    /// Specifies an inline CSS style for an element
503                    pub role: String,
504
505                    // ARIA Accessibility attributes
506
507                    /// Identifies the current element within a set
508                    pub aria_current: String,
509
510                    /// Defines a string value that labels the current element
511                    pub aria_label: Option<String>,
512
513                    /// Identifies the element that labels the current element
514                    pub aria_labelledby: Option<String>,
515
516                    /// Identifies the element that describes the current element
517                    pub aria_describedby: Option<String>,
518
519                    /// Indicates whether an element is expanded or collapsed
520                    pub aria_expanded: bool,
521
522                    /// Indicates the element that represents the current item within a container or set
523                    pub aria_selected: bool,
524
525                    /// Indicates whether the element is checked, unchecked, or represents mixed mode
526                    pub aria_checked: String,
527
528                    /// Indicates whether an element and its subtree are hidden
529                    pub aria_hidden: bool,
530
531                    /// Indicates the availability and type of interactive popup element
532                    pub aria_haspopup: String,
533
534                    /// Defines an element's role
535                    pub aria_role: String,
536
537                    // Element specific attributes
538                    $(
539                        pub $attr_name: $attr_value,
540                    )*
541                }
542
543                impl [<HTML $tag:camel Element Props>] {
544                    fn to_attributes(&self) -> IndexMap<String, String> {
545                        #[allow(unused_mut)]
546                        let mut attributes = IndexMap::new();
547                        $(
548                            if !self.$attr_name.value().is_empty() {
549                                let mut key = stringify!($attr_name);
550                                if let Some(last_char) = key.chars().last() {
551                                    if last_char == '_' {
552                                        key = &key[..key.len() - 1];
553                                    }
554                                }
555                                attributes.insert(key.replace('_', "-"), self.$attr_name.value());
556                            }
557                        )*
558                        if !self.id.value().is_empty() {
559                            attributes.insert("id".to_string(), self.id.value());
560                        }
561                        if !self.class.value().is_empty() {
562                            attributes.insert("class".to_string(), self.class.value());
563                        }
564                        if !self.style.value().is_empty() {
565                            attributes.insert("style".to_string(), self.style.value());
566                        }
567                        if !self.title.value().is_empty() {
568                            attributes.insert("title".to_string(), self.title.value());
569                        }
570                        if self.draggable {
571                            attributes.insert("draggable".to_string(), "true".to_string());
572                        }
573                        if self.hidden {
574                            attributes.insert("hidden".to_string(), "true".to_string());
575                        }
576                        if !self.accesskey.value().is_empty() {
577                            attributes.insert("accesskey".to_string(), self.accesskey.value());
578                        }
579                        if self.contenteditable {
580                            attributes.insert("contenteditable".to_string(), "true".to_string());
581                        }
582                        if !self.dir.value().is_empty() {
583                            attributes.insert("dir".to_string(), self.dir.value());
584                        }
585                        if let Some(tabindex) = self.tabindex {
586                            attributes.insert("tabindex".to_string(), tabindex.to_string());
587                        }
588                        if self.spellcheck {
589                            attributes.insert("spellcheck".to_string(), "true".to_string());
590                        }
591                        if !self.lang.value().is_empty() {
592                            attributes.insert("lang".to_string(), self.lang.value());
593                        }
594                        if self.translate {
595                            attributes.insert("translate".to_string(), "true".to_string());
596                        }
597                        if !self.autocapitalize.value().is_empty() {
598                            attributes.insert("autocapitalize".to_string(), self.autocapitalize.value());
599                        }
600                        if !self.role.value().is_empty() {
601                            attributes.insert("role".to_string(), self.role.value());
602                        }
603                        if !self.aria_current.value().is_empty() {
604                            attributes.insert("aria-current".to_string(), self.aria_current.value());
605                        }
606                        if !self.aria_label.value().is_empty() {
607                            attributes.insert("aria-label".to_string(), self.aria_label.value());
608                        }
609                        if !self.aria_labelledby.value().is_empty() {
610                            attributes.insert("aria-labelledby".to_string(), self.aria_labelledby.value());
611                        }
612                        if !self.aria_describedby.value().is_empty() {
613                            attributes.insert("aria-describedby".to_string(), self.aria_describedby.value());
614                        }
615                        if self.aria_expanded {
616                            attributes.insert("aria-expanded".to_string(), "true".to_string());
617                        }
618                        if self.aria_selected {
619                            attributes.insert("aria-selected".to_string(), "true".to_string());
620                        }
621                        if !self.aria_checked.value().is_empty() {
622                            attributes.insert("aria-checked".to_string(), self.aria_checked.value());
623                        }
624                        if self.aria_hidden {
625                            attributes.insert("aria-hidden".to_string(), "true".to_string());
626                        }
627                        if !self.aria_haspopup.value().is_empty() {
628                            attributes.insert("aria-haspopup".to_string(), self.aria_haspopup.value());
629                        }
630                        if !self.aria_role.value().is_empty() {
631                            attributes.insert("aria-role".to_string(), self.aria_role.value());
632                        }
633
634                        attributes
635                    }
636                }
637
638                impl Component for $tag {
639                    type Props = [<HTML $tag:camel Element Props>];
640
641                    fn render(props: Self::Props) -> Node {
642                        Node::Element(Element {
643                            tag: stringify!($tag).to_string(),
644                            attributes: props.to_attributes(),
645                            children: props.children,
646                        })
647                    }
648                }
649            }
650        )*
651    };
652}
653
654pub mod elements {
655    use super::*;
656    derive_elements! {
657        /// HTML `<html>` element - Root element of an HTML document
658        html {
659        }
660        /// HTML `<body>` element - Represents the content of an HTML document
661        ///
662        /// Example:
663        ///
664        /// ```<body>Content goes here</body>```
665        body {
666        }
667        /// HTML `<head>` element - Contains metadata about the document
668        ///
669        /// Example:
670        ///
671        /// ```<head><title>Document Title</title></head>```
672        head {
673        }
674        /// HTML `<title>` element - Defines the title of the document
675        ///
676        /// Example:
677        ///
678        /// ```<title>Document Title</title>```
679        title {
680        }
681        /// HTML `<meta` element - Provides metadata about the document
682        ///
683        /// Example:
684        ///
685        /// ```<meta charset="UTF-8">```
686        meta {
687            /// The character encoding of the document
688            charset: String,
689            /// The HTTP response status code
690            http_equiv: String,
691            /// The content of the document
692            content: String,
693            /// The name of the metadata
694            name: String,
695            /// The property of the metadata
696            property: String,
697        }
698        /// HTML `<style>` element - Defines style information for a document
699        ///
700        /// Example:
701        ///
702        /// ```<style>body { background-color: #f0f0f0; }</style>```
703        style {
704        }
705        /// HTML `<script>` element - Embeds executable code or data
706        ///
707        /// Example:
708        ///
709        /// ```<script src="script.js"></script>```
710        script {
711            /// The URL of the external script file
712            src: String,
713            /// The type of the script
714            type_: String,
715            /// The language of the script
716            language: String,
717            /// The character encoding of the script
718            charset: String,
719            /// The defer attribute specifies that the script will be executed after the document is finished parsing
720            defer: bool,
721            /// The async attribute specifies that the script will be executed asynchronously
722            async_: bool,
723        }
724        /// HTML `<link>` element - Specifies relationships between the current document and an external resource
725        ///
726        /// Example:
727        ///
728        /// ```<link rel="stylesheet" href="style.css">```
729        link {
730            /// The relationship between the current document and the linked resource
731            rel: String,
732            /// The URL of the linked resource
733            href: String,
734            /// The type of the linked resource
735            type_: String,
736            /// The character encoding of the linked resource
737            charset: String,
738            /// crossorigin attribute specifies that the element will request a cross-origin Isolation of its browsing context
739            crossorigin: String,
740            /// The referrerpolicy attribute specifies the referrer policy for the linked resource
741            referrerpolicy: String,
742        }
743        /// HTML `<div>` element - Container element for grouping and styling content
744        ///
745        /// Example:
746        ///
747        /// ```<div class="container">Content goes here</div>```
748        div {
749        }
750
751        /// HTML `<p>` element - Represents a paragraph of text
752        ///
753        /// Example:
754        ///
755        /// ```<p>This is a paragraph of text.</p>```
756        p {
757        }
758
759        /// HTML `<span>` element - Inline container for targeting text with styles
760        ///
761        /// Example:
762        ///
763        /// ```<span class="highlight">Highlighted text</span>```
764        span {
765        }
766
767        /// HTML `<a>` element - Creates a hyperlink to other web pages or resources
768        ///
769        /// Example:
770        ///
771        /// ```<a href="https://example.com" target="_blank">Visit Example</a>```
772        a {
773            /// The href attribute specifies the URL of the page the link goes to
774            /// Example: href="https://example.com"
775            href: String,
776            /// The target attribute specifies where to open the linked document
777            /// Example: target="_blank" (opens in new tab)
778            target: String,
779            /// The rel attribute specifies the relationship between the current document and the linked document
780            /// Example: rel="nofollow" (tells search engines not to follow this link)
781            rel: String,
782            /// The download attribute indicates the browser to download the URL instead of navigating
783            /// Example: download="filename.pdf"
784            download: String,
785            /// The hreflang attribute specifies the language of the linked document
786            /// Example: hreflang="en" (English)
787            hreflang: String,
788            /// The type attribute specifies the media type of the linked document
789            /// Example: type="text/html"
790            type_: String,
791            /// The media attribute specifies what media/device the linked document is optimized for
792            /// Example: media="print" (for print stylesheets)
793            media: String,
794            /// The referrerpolicy attribute specifies which referrer information to send
795            /// Example: referrerpolicy="no-referrer"
796            referrerpolicy: String,
797            /// The ping attribute specifies URLs to be notified when the link is followed
798            /// Example: ping="https://example.com/track"
799            ping: String,
800        }
801
802        /// HTML <h1> element - First level heading (most important)
803        ///
804        /// Example:
805        ///
806        /// ```<h1>Main Page Title</h1>```
807        h1 {
808        }
809
810        /// HTML <h2> element - Second level heading
811        ///
812        /// Example:
813        ///
814        /// ```<h2>Section Heading</h2>```
815        h2 {
816        }
817
818        /// HTML <h3> element - Third level heading
819        ///
820        /// Example:
821        ///
822        /// ```<h3>Subsection Heading</h3>```
823        h3 {
824        }
825
826        /// HTML <h4> element - Fourth level heading
827        ///
828        /// Example:
829        ///
830        /// ```<h4>Sub-subsection Heading</h4>```
831        h4 {
832        }
833
834        /// HTML <h5> element - Fifth level heading
835        ///
836        /// Example:
837        ///
838        /// ```<h5>Minor Heading</h5>```
839        h5 {
840        }
841
842        /// HTML <h6> element - Sixth level heading (least important)
843        ///
844        /// Example:
845        ///
846        /// ```<h6>Fine Detail Heading</h6>```
847        h6 {
848        }
849
850        /// HTML `<img>` element - Embeds an image into the document
851        ///
852        /// Example:
853        ///
854        /// ```<img src="image.jpg" alt="Description of image">```
855        img {
856            /// The src attribute specifies the URL/path to the image
857            /// Example: src="images/logo.png"
858            src: String,
859            /// The alt attribute provides alternative text for screen readers and if image fails to load
860            /// Example: alt="Company Logo"
861            alt: String,
862            /// The loading attribute indicates how the browser should load the image
863            /// Example: loading="lazy" (defers loading until it's near viewport)
864            loading: String,
865        }
866
867        /// HTML `<br>` element - Produces a line break in text
868        ///
869        /// Example:
870        ///
871        /// ```<br>```
872        br {}
873
874        /// HTML `<hr>` element - Creates a horizontal rule (divider)
875        ///
876        /// Example:
877        ///
878        /// ```<hr>```
879        hr {
880        }
881
882        /// HTML `<ul>` element - Unordered list with bullet points
883        ///
884        /// Example:
885        ///
886        /// ```<ul><li>Item 1</li><li>Item 2</li></ul>```
887        ul {
888            /// The type attribute specifies the bullet style (disc, circle, square)
889            /// Example: type="square"
890            type_: String,
891        }
892
893        /// HTML `<li>` element - List item within ordered or unordered lists
894        ///
895        /// Example:
896        ///
897        /// ```<li>List item content</li>```
898        li {
899            /// The value attribute specifies the start value of the list item (for ol)
900            /// Example: value="3" (starts this item at number 3)
901            value: Option<i32>,
902        }
903
904        /// HTML `<ol>` element - Ordered (numbered) list
905        ///
906        /// Example:
907        ///
908        /// ```<ol start="5" type="A"><li>Item E</li><li>Item F</li></ol>```
909        ol {
910            /// The type attribute specifies the numbering type (1, A, a, I, i)
911            /// Example: type="A" (uses capital letters)
912            type_: String,
913            /// The start attribute specifies the start value of the list
914            /// Example: start="5" (starts counting from 5)
915            start: i32,
916            /// The reversed attribute specifies that list should be in descending order
917            /// Example: reversed (counts down instead of up)
918            reversed: bool,
919        }
920
921        /// HTML `<table>` element - Creates a data table with rows and columns
922        ///
923        /// Example:
924        ///
925        /// ```<table border="1"><tr><th>Header</th></tr><tr><td>Data</td></tr></table>```
926        table {
927            /// The border attribute specifies the width of the border around the table
928            /// Example: border="1" (1 pixel border)
929            border: i32,
930            /// The cellpadding attribute specifies the space between cell content and borders
931            /// Example: cellpadding="5" (5 pixels of padding)
932            cellpadding: i32,
933            /// The cellspacing attribute specifies the space between cells
934            /// Example: cellspacing="2" (2 pixels between cells)
935            cellspacing: i32,
936        }
937
938        /// HTML `<tr>` element - Table row container
939        ///
940        /// Example:
941        ///
942        /// ```<tr><td>Cell 1</td><td>Cell 2</td></tr>```
943        tr {
944        }
945
946        /// HTML `<td>` element - Table data cell
947        ///
948        /// Example:
949        ///
950        /// ```<td colspan="2">This cell spans two columns</td>```
951        td {
952            /// The colspan attribute specifies how many columns a cell should span
953            /// Example: colspan="3" (cell spans 3 columns)
954            colspan: i32,
955            /// The rowspan attribute specifies how many rows a cell should span
956            /// Example: rowspan="2" (cell spans 2 rows)
957            rowspan: i32,
958            /// The headers attribute associates data cells with header cells
959            /// Example: headers="col1 row1" (associates with those header IDs)
960            headers: String,
961            /// The scope attribute specifies whether header cells are for rows or columns
962            /// Example: scope="col" (header applies to whole column)
963            scope: String,
964        }
965
966        /// HTML `<th>` element - Table header cell
967        ///
968        /// Example:
969        ///
970        /// ```<th scope="col">Column Header</th>```
971        th {
972            /// The colspan attribute specifies how many columns a cell should span
973            /// Example: colspan="3" (header spans 3 columns)
974            colspan: i32,
975            /// The rowspan attribute specifies how many rows a cell should span
976            /// Example: rowspan="2" (header spans 2 rows)
977            rowspan: i32,
978            /// The headers attribute associates data cells with header cells
979            /// Example: headers="col1 row1" (associates with those header IDs)
980            headers: String,
981            /// The scope attribute specifies whether the header cell is for a row, column, etc.
982            /// Example: scope="row" (header applies to whole row)
983            scope: String,
984        }
985
986        /// HTML `<tbody>` element - Groups body content in a table
987        ///
988        /// Example:
989        ///
990        /// ```<table><tbody><tr><td>Data</td></tr></tbody></table>```
991        tbody {
992        }
993
994        /// HTML `<thead>` element - Groups header content in a table
995        ///
996        /// Example:
997        ///
998        /// ```<table><thead><tr><th>Header</th></tr></thead><tbody>...</tbody></table>```
999        thead {
1000        }
1001
1002        /// HTML `<tfoot>` element - Groups footer content in a table
1003        ///
1004        /// Example:
1005        ///
1006        /// ```<table><thead>...</thead><tbody>...</tbody><tfoot><tr><td>Summary</td></tr></tfoot></table>```
1007        tfoot {
1008        }
1009
1010        /// HTML `<form>` element - Container for interactive inputs to collect user data
1011        ///
1012        /// Example:
1013        ///
1014        /// ```<form action="/submit" method="post"><input type="text"><button type="submit">Submit</button></form>```
1015        form {
1016            /// The action attribute specifies where to send form data when submitted
1017            ///
1018            /// Example: action="/process-form.php"
1019            action: String,
1020            /// The method attribute specifies HTTP method for sending data (GET/POST)
1021            ///
1022            /// Example: method="post" (sends data in request body)
1023            method: String,
1024            /// The target attribute specifies where to display the response
1025            ///
1026            /// Example: target="_blank" (opens response in new tab)
1027            target: String,
1028            /// The enctype attribute specifies how form data should be encoded
1029            ///
1030            /// Example: enctype="multipart/form-data" (needed for file uploads)
1031            enctype: String,
1032            /// The novalidate attribute disables browser's built-in form validation
1033            ///
1034            /// Example: novalidate (skips validation)
1035            novalidate: bool,
1036            /// The autocomplete attribute controls browser autofill behavior
1037            ///
1038            /// Example: autocomplete="off" (disables autofill)
1039            autocomplete: String,
1040            /// The accept attribute specifies file types the server accepts (for file inputs)
1041            ///
1042            /// Example: accept=".jpg,.png" (accepts only those image formats)
1043            accept: String,
1044            /// Example: name="contact-form"
1045            name: String,
1046        }
1047
1048        /// HTML `<input>` element - Creates interactive controls for forms
1049        ///
1050        /// Example:
1051        ///
1052        /// ```<input type="text" placeholder="Enter your name" required>```
1053        input {
1054            /// The type attribute specifies the input type (text, password, email, etc.)
1055            ///
1056            /// Example: type="email" (validates as email address)
1057            type_: String,
1058            /// The placeholder attribute shows hint text when field is empty
1059            ///
1060            /// Example: placeholder="Enter your email"
1061            placeholder: String,
1062            /// The required attribute makes the field mandatory
1063            ///
1064            /// Example: required (field must be filled)
1065            required: bool,
1066            /// The value attribute specifies the default/current value
1067            ///
1068            /// Example: value="Default text"
1069            value: String,
1070            /// The name attribute specifies the name of the input (for form submission)
1071            ///
1072            /// Example: name="email"
1073            name: String,
1074            /// The disabled attribute disables the input
1075            ///
1076            /// Example: disabled (user cannot interact with input)
1077            disabled: bool,
1078            /// The readonly attribute makes the input read-only
1079            ///
1080            /// Example: readonly (user cannot modify but can focus/select)
1081            readonly: bool,
1082            /// The min attribute specifies minimum value for number/date inputs
1083            ///
1084            /// Example: min="1" (number input minimum value)
1085            min: String,
1086            /// The max attribute specifies maximum value for number/date inputs
1087            ///
1088            /// Example: max="100" (number input maximum value)
1089            max: String,
1090            /// The pattern attribute specifies a regex pattern for validation
1091            ///
1092            /// Example: pattern="[0-9]{3}" (requires exactly 3 digits)
1093            pattern: String,
1094            /// The autocomplete attribute controls browser autofill for this field
1095            ///
1096            /// Example: autocomplete="current-password"
1097            autocomplete: String,
1098        }
1099
1100        /// HTML `<textarea>` element - Multi-line text input control
1101        ///
1102        /// Example:
1103        ///
1104        /// ```<textarea rows="4" cols="50" placeholder="Your message here"></textarea>```
1105        textarea {
1106            /// The placeholder attribute shows hint text when field is empty
1107            /// Example: placeholder="Enter your comments"
1108            placeholder: String,
1109            /// The required attribute makes the field mandatory
1110            /// Example: required (must be filled before submission)
1111            required: bool,
1112            /// The value attribute specifies the default/current text content
1113            /// Example: value="Default text in the textarea"
1114            value: String,
1115            /// The rows attribute specifies visible number of text lines
1116            /// Example: rows="10" (shows 10 lines of text)
1117            rows: i32,
1118            /// The cols attribute specifies visible width in average characters
1119            /// Example: cols="40" (about 40 characters wide)
1120            cols: i32,
1121            /// The name attribute specifies the name of the textarea (for form submission)
1122            /// Example: name="comments"
1123            name: String,
1124            /// The disabled attribute disables the textarea
1125            /// Example: disabled (user cannot interact)
1126            disabled: bool,
1127            /// The readonly attribute makes the textarea read-only
1128            /// Example: readonly (user cannot modify but can focus/select)
1129            readonly: bool,
1130            /// The maxlength attribute specifies maximum character count
1131            /// Example: maxlength="500" (limits to 500 characters)
1132            maxlength: i32,
1133        }
1134
1135        /// HTML `<button>` element - Clickable button control
1136        ///
1137        /// Example:
1138        ///
1139        /// ```<button type="submit">Click Me</button>```
1140        button {
1141            /// The type attribute specifies button function (submit, reset, button)
1142            /// Example: type="submit" (submits the form)
1143            type_: String,
1144            /// The value attribute specifies the value associated with the button
1145            /// Example: value="btn1" (for form processing)
1146            value: String,
1147            /// The disabled attribute disables the button
1148            /// Example: disabled (button cannot be clicked)
1149            disabled: bool,
1150            /// The name attribute specifies the name of the button (for form submission)
1151            /// Example: name="submit-button"
1152            name: String,
1153            /// The formaction attribute overrides form's action for this button
1154            /// Example: formaction="/alternative-submit"
1155            formaction: String,
1156            /// The formmethod attribute overrides form's method for this button
1157            /// Example: formmethod="get"
1158            formmethod: String,
1159        }
1160
1161        /// HTML `<select>` element - Dropdown selection list
1162        ///
1163        /// Example:
1164        ///
1165        /// ```<select><option value="1">Option 1</option><option value="2">Option 2</option></select>```
1166        select {
1167            /// The multiple attribute allows selecting multiple options
1168            /// Example: multiple (user can select multiple items)
1169            multiple: bool,
1170            /// The disabled attribute disables the dropdown
1171            /// Example: disabled (user cannot interact)
1172            disabled: bool,
1173            /// The value attribute specifies the selected value
1174            /// Example: value="option2" (preselects this option)
1175            value: String,
1176            /// The name attribute specifies the name of the select (for form submission)
1177            /// Example: name="country"
1178            name: String,
1179            /// The size attribute specifies number of visible options
1180            /// Example: size="5" (shows 5 options at once)
1181            size: i32,
1182            /// The required attribute makes selection mandatory
1183            /// Example: required (user must select an option)
1184            required: bool,
1185        }
1186
1187        /// HTML `<option>` element - Defines option in a select dropdown
1188        ///
1189        /// Example:
1190        ///
1191        /// ```<option value="blue" selected>Blue</option>```
1192        option {
1193            /// The value attribute specifies the value to be sent to server
1194            /// Example: value="NY" (value sent when this option is selected)
1195            value: String,
1196            /// The selected attribute preselects this option when page loads
1197            /// Example: selected (this option is selected by default)
1198            selected: bool,
1199            /// The disabled attribute makes this option unselectable
1200            /// Example: disabled (cannot be chosen)
1201            disabled: bool,
1202        }
1203
1204        /// HTML `<label>` element - Caption for a form control
1205        ///
1206        /// Example:
1207        ///
1208        /// ```<label for="username">Username:</label><input id="username">```
1209        label {
1210            /// The for attribute connects the label to a form control by ID
1211            /// Example: for="email" (associates with input having id="email")
1212            for_: String,
1213        }
1214
1215        /// HTML `<iframe>` element - Embeds another document within the current HTML document
1216        ///
1217        /// Example:
1218        ///
1219        /// ```<iframe src="https://example.com" title="Example Site"></iframe>```
1220        iframe {
1221            /// The src attribute specifies the URL of the embedded document
1222            /// Example: src="https://maps.google.com"
1223            src: String,
1224            /// The frameborder attribute specifies whether to display a border
1225            /// Example: frameborder="0" (no border)
1226            frameborder: String,
1227            /// The allow attribute specifies features allowed in the iframe
1228            /// Example: allow="camera; microphone" (permits access to these devices)
1229            allow: String,
1230            /// The allowfullscreen attribute allows iframe content to go fullscreen
1231            /// Example: allowfullscreen (allows fullscreen mode)
1232            allowfullscreen: bool,
1233            /// The sandbox attribute restricts iframe capabilities for security
1234            /// Example: sandbox="allow-scripts" (only allows scripts to run)
1235            sandbox: String,
1236        }
1237
1238        /// HTML `<video>` element - Embeds video content in the document
1239        ///
1240        /// Example:
1241        ///
1242        /// ```<video src="movie.mp4" controls width="500">Video not supported</video>```
1243        video {
1244            /// The src attribute specifies URL/path of the video
1245            /// Example: src="videos/intro.mp4"
1246            src: String,
1247            /// The controls attribute displays video playback controls
1248            /// Example: controls (shows play/pause/volume controls)
1249            controls: bool,
1250            /// The autoplay attribute starts playing video automatically
1251            /// Example: autoplay (video plays when page loads)
1252            autoplay: bool,
1253            /// The loop attribute makes the video replay when finished
1254            /// Example: loop (continuously replays)
1255            loop_: bool,
1256            /// The poster attribute specifies an image shown before video plays
1257            /// Example: poster="thumbnail.jpg"
1258            poster: String,
1259            /// The muted attribute mutes the audio by default
1260            /// Example: muted (starts with no sound)
1261            muted: bool,
1262            /// The preload attribute hints how to preload the video
1263            /// Example: preload="auto" (preload entire video)
1264            preload: String,
1265            /// The playsinline attribute plays inline on iOS (instead of fullscreen)
1266            /// Example: playsinline (important for iPhone users)
1267            playsinline: bool,
1268        }
1269
1270        /// HTML `<audio>` element - Embeds sound content in the document
1271        ///
1272        /// Example:
1273        ///
1274        /// ```<audio src="song.mp3" controls>Audio not supported</audio>```
1275        audio {
1276            /// The src attribute specifies URL/path of the audio file
1277            /// Example: src="audio/background-music.mp3"
1278            src: String,
1279            /// The controls attribute displays audio playback controls
1280            /// Example: controls (shows play/pause/volume controls)
1281            controls: bool,
1282            /// The autoplay attribute starts playing audio automatically
1283            /// Example: autoplay (audio plays when page loads)
1284            autoplay: bool,
1285            /// The loop attribute makes the audio replay when finished
1286            /// Example: loop (continuously replays)
1287            loop_: bool,
1288            /// The muted attribute mutes the audio by default
1289            /// Example: muted (starts with no sound)
1290            muted: bool,
1291            /// The preload attribute hints how to preload the audio
1292            /// Example: preload="none" (doesn't preload)
1293            preload: String,
1294        }
1295
1296        /// HTML `<source>` element - Defines media resources for video/audio elements
1297        ///
1298        /// Example:
1299        ///
1300        /// ```<video><source src="movie.mp4" type="video/mp4"><source src="movie.webm" type="video/webm"></video>```
1301        source {
1302            /// The src attribute specifies URL/path of the media resource
1303            /// Example: src="audio/song.ogg"
1304            src: String,
1305            /// The type attribute specifies the MIME type of the resource
1306            /// Example: type="video/webm" (defines file format)
1307            type_: String,
1308            /// The media attribute specifies for which media the resource is intended
1309            /// Example: media="(min-width: 600px)" (responsive resources)
1310            media: String,
1311        }
1312
1313        /// HTML `<canvas>` element - Container for graphics rendered with JavaScript
1314        ///
1315        /// Example:
1316        ///
1317        /// ```<canvas id="myCanvas" width="200" height="100">Your browser does not support canvas</canvas>```
1318        canvas {
1319        }
1320
1321        /// HTML `<svg>` element - Container for SVG graphics
1322        ///
1323        /// Example:
1324        ///
1325        /// ```<svg viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="red" /></svg>```
1326        svg {
1327            /// The viewBox attribute defines coordinate system and aspect ratio
1328            /// Example: viewBox="0 0 800 600" (x, y, width, height)
1329            viewBox: String,
1330            /// The preserveAspectRatio attribute controls scaling behavior
1331            /// Example: preserveAspectRatio="xMidYMid meet" (center and scale)
1332            preserve_aspect_ratio: String,
1333            /// The xmlns attribute defines the XML namespace (required for standalone SVG)
1334            /// Example: xmlns="http://www.w3.org/2000/svg"
1335            xmlns: String,
1336            /// The fill attribute specifies the fill color
1337            /// Example: fill="#3498db" (blue fill)
1338            fill: String,
1339            /// The stroke attribute specifies the outline color
1340            /// Example: stroke="#e74c3c" (red outline)
1341            stroke: String,
1342            /// The stroke-width attribute specifies the width of the outline
1343            /// Example: stroke-width="3" (3 units thick)
1344            stroke_width: String,
1345            /// The stroke-linecap attribute specifies line end style
1346            /// Example: stroke-linecap="round" (rounded ends)
1347            stroke_linecap: String,
1348            /// The stroke-linejoin attribute specifies how line joins are rendered
1349            /// Example: stroke-linejoin="miter" (pointed corners)
1350            stroke_linejoin: String,
1351            /// The stroke-miterlimit attribute limits the length of miters
1352            /// Example: stroke-miterlimit="4" (limits pointy corners)
1353            stroke_miterlimit: String,
1354            /// The stroke-dasharray attribute creates dashed lines
1355            /// Example: stroke-dasharray="5,5" (5 units on, 5 units off)
1356            stroke_dasharray: String,
1357            /// The stroke-dashoffset attribute adjusts dash pattern start
1358            /// Example: stroke-dashoffset="10" (starts 10 units into pattern)
1359            stroke_dashoffset: String,
1360            /// The stroke-opacity attribute sets stroke transparency
1361            /// Example: stroke-opacity="0.5" (50% transparent)
1362            stroke_opacity: String,
1363            /// The fill-opacity attribute sets fill transparency
1364            /// Example: fill-opacity="0.7" (70% opaque)
1365            fill_opacity: String,
1366        }
1367
1368        /// HTML `<path>` element - Defines a path in SVG graphics
1369        ///
1370        /// Example:
1371        ///
1372        /// ```<path d="M10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black" />```
1373        path {
1374            /// The d attribute defines the path to be drawn
1375            /// Example: d="M20,20 L80,20 L80,80 L20,80 Z" (square path)
1376            d: String,
1377            /// The fill attribute specifies the fill color
1378            /// Example: fill="#3498db" (blue fill)
1379            fill: String,
1380            /// The stroke attribute specifies the outline color
1381            /// Example: stroke="#e74c3c" (red outline)
1382            stroke: String,
1383            /// The stroke-width attribute specifies the width of the outline
1384            /// Example: stroke-width="3" (3 units thick)
1385            stroke_width: String,
1386            /// The stroke-linecap attribute specifies line end style
1387            /// Example: stroke-linecap="round" (rounded ends)
1388            stroke_linecap: String,
1389            /// The stroke-linejoin attribute specifies how line joins are rendered
1390            /// Example: stroke-linejoin="miter" (pointed corners)
1391            stroke_linejoin: String,
1392            /// The stroke-miterlimit attribute limits the length of miters
1393            /// Example: stroke-miterlimit="4" (limits pointy corners)
1394            stroke_miterlimit: String,
1395            /// The stroke-dasharray attribute creates dashed lines
1396            /// Example: stroke-dasharray="5,5" (5 units on, 5 units off)
1397            stroke_dasharray: String,
1398            /// The stroke-dashoffset attribute adjusts dash pattern start
1399            /// Example: stroke-dashoffset="10" (starts 10 units into pattern)
1400            stroke_dashoffset: String,
1401            /// The stroke-opacity attribute sets stroke transparency
1402            /// Example: stroke-opacity="0.5" (50% transparent)
1403            stroke_opacity: String,
1404            /// The fill-opacity attribute sets fill transparency
1405            /// Example: fill-opacity="0.7" (70% opaque)
1406            fill_opacity: String,
1407        }
1408
1409        /// HTML `<rect>` element - Draws a rectangle in SVG
1410        ///
1411        /// Example:
1412        ///
1413        /// ```<rect x="10" y="10" width="100" height="50" fill="blue" />```
1414        rect {
1415            /// The x attribute specifies the x-coordinate of the rectangle
1416            /// Example: x="25" (25 units from the left)
1417            x: String,
1418            /// The y attribute specifies the y-coordinate of the rectangle
1419            /// Example: y="50" (50 units from the top)
1420            y: String,
1421            /// The rx attribute specifies the horizontal corner radius
1422            /// Example: rx="10" (rounded corners)
1423            rx: String,
1424            /// The ry attribute specifies the vertical corner radius
1425            /// Example: ry="10" (rounded corners)
1426            ry: String,
1427            /// The fill attribute specifies the fill color
1428            /// Example: fill="#2ecc71" (green fill)
1429            fill: String,
1430            /// The stroke attribute specifies the outline color
1431            /// Example: stroke="#27ae60" (darker green outline)
1432            stroke: String,
1433            /// The stroke-width attribute specifies the width of the outline
1434            /// Example: stroke-width="2" (2 units thick)
1435            stroke_width: String,
1436        }
1437
1438        /// HTML `<circle>` element - Draws a circle in SVG
1439        ///
1440        /// Example:
1441        ///
1442        /// ```<circle cx="50" cy="50" r="40" fill="red" />```
1443        circle {
1444            /// The cx attribute specifies the x-coordinate of the center
1445            /// Example: cx="100" (center x at 100 units)
1446            cx: String,
1447            /// The cy attribute specifies the y-coordinate of the center
1448            /// Example: cy="100" (center y at 100 units)
1449            cy: String,
1450            /// The r attribute specifies the radius of the circle
1451            /// Example: r="75" (75 units radius)
1452            r: String,
1453            /// The fill attribute specifies the fill color
1454            /// Example: fill="#9b59b6" (purple fill)
1455            fill: String,
1456            /// The stroke attribute specifies the outline color
1457            /// Example: stroke="#8e44ad" (darker purple outline)
1458            stroke: String,
1459            /// The stroke-width attribute specifies the width of the outline
1460            /// Example: stroke-width="3" (3 units thick)
1461            stroke_width: String,
1462        }
1463
1464        /// HTML `<ellipse>` element - Draws an ellipse in SVG
1465        ///
1466        /// Example:
1467        ///
1468        /// ```<ellipse cx="100" cy="50" rx="100" ry="50" fill="yellow" />```
1469        ellipse {
1470            /// The cx attribute specifies the x-coordinate of the center
1471            /// Example: cx="150" (center x at 150 units)
1472            cx: String,
1473            /// The cy attribute specifies the y-coordinate of the center
1474            /// Example: cy="75" (center y at 75 units)
1475            cy: String,
1476            /// The rx attribute specifies the horizontal radius
1477            /// Example: rx="100" (100 units horizontal radius)
1478            rx: String,
1479            /// The ry attribute specifies the vertical radius
1480            /// Example: ry="50" (50 units vertical radius)
1481            ry: String,
1482            /// The fill attribute specifies the fill color
1483            /// Example: fill="#f1c40f" (yellow fill)
1484            fill: String,
1485            /// The stroke attribute specifies the outline color
1486            /// Example: stroke="#f39c12" (darker yellow outline)
1487            stroke: String,
1488            /// The stroke-width attribute specifies the width of the outline
1489            /// Example: stroke-width="2" (2 units thick)
1490            stroke_width: String,
1491        }
1492
1493        /// HTML `<line>` element - Draws a line in SVG
1494        ///
1495        /// Example:
1496        ///
1497        /// ```<line x1="0" y1="0" x2="100" y2="100" stroke="black" />```
1498        line {
1499            /// The x1 attribute specifies the x-coordinate of the start point
1500            /// Example: x1="10" (starts 10 units from left)
1501            x1: String,
1502            /// The y1 attribute specifies the y-coordinate of the start point
1503            /// Example: y1="10" (starts 10 units from top)
1504            y1: String,
1505            /// The x2 attribute specifies the x-coordinate of the end point
1506            /// Example: x2="200" (ends 200 units from left)
1507            x2: String,
1508            /// The y2 attribute specifies the y-coordinate of the end point
1509            /// Example: y2="200" (ends 200 units from top)
1510            y2: String,
1511            /// The stroke attribute specifies the line color
1512            /// Example: stroke="#34495e" (dark blue line)
1513            stroke: String,
1514            /// The stroke-width attribute specifies the width of the line
1515            /// Example: stroke-width="5" (5 units thick)
1516            stroke_width: String,
1517            /// The stroke-linecap attribute specifies line end style
1518            /// Example: stroke-linecap="round" (rounded ends)
1519            stroke_linecap: String,
1520            /// The stroke-dasharray attribute creates dashed lines
1521            /// Example: stroke-dasharray="10,5" (10 units on, 5 units off)
1522            stroke_dasharray: String,
1523        }
1524
1525        /// HTML `<polyline>` element - Draws connected straight lines in SVG
1526        ///
1527        /// Example:
1528        ///
1529        /// ```<polyline points="20,20 40,25 60,40 80,120 120,140 200,180" stroke="orange" fill="none" />```
1530        polyline {
1531            /// The points attribute specifies coordinates for each point
1532            /// Example: points="0,0 50,50 100,25" (series of x,y pairs)
1533            points: String,
1534            /// The fill attribute specifies the fill color between lines
1535            /// Example: fill="none" (transparent fill)
1536            fill: String,
1537            /// The stroke attribute specifies the line color
1538            /// Example: stroke="#e67e22" (orange line)
1539            stroke: String,
1540            /// The stroke-width attribute specifies the width of the lines
1541            /// Example: stroke-width="3" (3 units thick)
1542            stroke_width: String,
1543            /// The stroke-linejoin attribute specifies how lines are joined
1544            /// Example: stroke-linejoin="round" (rounded corners)
1545            stroke_linejoin: String,
1546        }
1547
1548        /// HTML `<polygon>` element - Draws a closed shape with straight lines in SVG
1549        ///
1550        /// Example:
1551        ///
1552        /// ```<polygon points="200,10 250,190 160,210" fill="green" />```
1553        polygon {
1554            /// The points attribute specifies coordinates for each point
1555            /// Example: points="50,50 150,50 100,150" (triangle coordinates)
1556            points: String,
1557            /// The fill attribute specifies the fill color of the shape
1558            /// Example: fill="#1abc9c" (teal fill)
1559            fill: String,
1560            /// The stroke attribute specifies the outline color
1561            /// Example: stroke="#16a085" (darker teal outline)
1562            stroke: String,
1563            /// The stroke-width attribute specifies the width of the outline
1564            /// Example: stroke-width="2" (2 units thick)
1565            stroke_width: String,
1566            /// The fill-rule attribute specifies how to fill shapes with holes
1567            /// Example: fill-rule="evenodd" (alternates fill for nested shapes)
1568            fill_rule: String,
1569        }
1570
1571        /// HTML `<g>` element - Groups SVG elements together
1572        ///
1573        /// Example:
1574        ///
1575        /// ```<g transform="rotate(45 50 50)"><rect x="20" y="20" width="60" height="60" /></g>```
1576        g {
1577            /// The transform attribute applies transformations to the group
1578            /// Example: transform="translate(100,50) scale(2)" (moves and scales)
1579            transform: String,
1580            /// The fill attribute specifies the fill color for all elements in the group
1581            /// Example: fill="#3498db" (blue fill for all children)
1582            fill: String,
1583            /// The stroke attribute specifies the outline color for all elements in the group
1584            /// Example: stroke="#2980b9" (darker blue outline for all children)
1585            stroke: String,
1586        }
1587
1588        /// HTML `<use>` element - Reuses an SVG element defined elsewhere
1589        ///
1590        /// Example:
1591        ///
1592        /// ```<r#use href="#myCircle" x="10" y="10" fill="blue" />```
1593        r#use {
1594            /// The href attribute specifies which element to reuse
1595            /// Example: href="#icon-star" (references element with id="icon-star")
1596            href: String,
1597            /// The x attribute specifies the x-coordinate where to place the reused element
1598            /// Example: x="100" (100 units from left)
1599            x: String,
1600            /// The y attribute specifies the y-coordinate where to place the reused element
1601            /// Example: y="50" (50 units from top)
1602            y: String,
1603        }
1604
1605        /// HTML <foreignObject> element - Includes non-SVG elements inside SVG
1606        ///
1607        /// Example:
1608        ///
1609        /// ```<foreignObject x="20" y="20" width="160" height="160"><div>HTML content inside SVG</div></foreignObject>```
1610        foreignObject {
1611            /// The x attribute specifies the x-coordinate of the foreign object
1612            /// Example: x="25" (25 units from left)
1613            x: String,
1614            /// The y attribute specifies the y-coordinate of the foreign object
1615            /// Example: y="25" (25 units from top)
1616            y: String,
1617        }
1618
1619        /// HTML `<defs>` element - Container for reusable SVG elements
1620        ///
1621        /// Example:
1622        ///
1623        /// ```<defs><circle id="myCircle" cx="5" cy="5" r="4" /></defs>```
1624        defs {
1625        }
1626
1627        /// HTML <linearGradient> element - Defines a linear gradient for SVG fills
1628        ///
1629        /// Example:
1630        ///
1631        /// ```<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" style="stop-color:rgb(255,255,0)" /></linearGradient>```
1632        linearGradient {
1633            /// The x1 attribute defines the start point of the gradient (x-coordinate)
1634            /// Example: x1="0%" (starts at left edge)
1635            x1: String,
1636            /// The y1 attribute defines the start point of the gradient (y-coordinate)
1637            /// Example: y1="0%" (starts at top edge)
1638            y1: String,
1639            /// The x2 attribute defines the end point of the gradient (x-coordinate)
1640            /// Example: x2="100%" (ends at right edge)
1641            x2: String,
1642            /// The y2 attribute defines the end point of the gradient (y-coordinate)
1643            /// Example: y2="100%" (ends at bottom edge)
1644            y2: String,
1645            /// The gradientUnits attribute defines the coordinate system for the gradient
1646            /// Example: gradientUnits="userSpaceOnUse" (uses absolute coordinates)
1647            gradientUnits: String,
1648            /// The spreadMethod attribute defines how the gradient fills beyond its bounds
1649            /// Example: spreadMethod="reflect" (gradient reflects at boundaries)
1650            spreadMethod: String,
1651        }
1652
1653        /// HTML `<stop>` element - Defines color transitions in gradients
1654        ///
1655        /// Example:
1656        ///
1657        /// ```<stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1" />```
1658        stop {
1659            /// The offset attribute defines where along the gradient this color appears
1660            /// Example: offset="50%" (color positioned halfway through gradient)
1661            offset: String,
1662            /// The stop-color attribute defines the color at this stop
1663            /// Example: stop-color="#3498db" (blue color)
1664            stop_color: String,
1665            /// The stop-opacity attribute defines the opacity at this stop
1666            /// Example: stop-opacity="0.5" (50% transparent)
1667            stop_opacity: String,
1668        }
1669
1670        /// HTML <radialGradient> element - Defines a radial gradient for SVG fills
1671        ///
1672        /// Example:
1673        ///
1674        /// ```<radialGradient id="grad2" cx="50%" cy="50%" r="50%"><stop offset="0%" style="stop-color:red" /></radialGradient>```
1675        radialGradient {
1676            /// The cx attribute defines the x-coordinate of the center point
1677            /// Example: cx="50%" (center of the area horizontally)
1678            cx: String,
1679            /// The cy attribute defines the y-coordinate of the center point
1680            /// Example: cy="50%" (center of the area vertically)
1681            cy: String,
1682            /// The r attribute defines the radius of the gradient
1683            /// Example: r="75%" (extends to 75% of the reference area)
1684            r: String,
1685            /// The fx attribute defines the x-coordinate of the focal point
1686            /// Example: fx="60%" (focal point slightly right of center)
1687            fx: String,
1688            /// The fy attribute defines the y-coordinate of the focal point
1689            /// Example: fy="40%" (focal point slightly above center)
1690            fy: String,
1691            /// The fr attribute defines the radius of the focal point
1692            /// Example: fr="5%" (small focal point)
1693            fr: String,
1694            /// The gradientUnits attribute defines the coordinate system for the gradient
1695            /// Example: gradientUnits="objectBoundingBox" (relative to object)
1696            gradientUnits: String,
1697            /// The spreadMethod attribute defines how the gradient fills beyond its bounds
1698            /// Example: spreadMethod="pad" (uses edge color beyond boundaries)
1699            spreadMethod: String,
1700        }
1701
1702        /// HTML `<mask>` element - Defines an area where SVG elements are partially or fully hidden
1703        ///
1704        /// Example:
1705        ///
1706        /// ```<mask id="myMask"><rect width="100%" height="100%" fill="white" opacity="0.5" /></mask>```
1707        mask {
1708            /// The maskUnits attribute specifies the coordinate system for mask positioning
1709            /// Example: maskUnits="userSpaceOnUse" (absolute coordinates)
1710            mask_units: String,
1711            /// The maskContentUnits attribute specifies the coordinate system for mask content
1712            /// Example: maskContentUnits="objectBoundingBox" (relative to object)
1713            mask_content_units: String,
1714            /// The x attribute specifies the x-coordinate of the mask
1715            /// Example: x="0" (starts at left edge)
1716            x: String,
1717            /// The y attribute specifies the y-coordinate of the mask
1718            /// Example: y="0" (starts at top edge)
1719            y: String,
1720        }
1721        /// HTML `<article>` element - Defines an independent, self-contained content
1722        ///
1723        /// Example:
1724        ///
1725        /// ```<article><h1>Article Title</h1><p>Article content goes here...</p></article>```
1726        article {
1727        }
1728
1729        /// HTML `<aside>` element - Defines content aside from the page content
1730        ///
1731        /// Example:
1732        ///
1733        /// ```<aside><p>Sidebar content goes here...</p></aside>```
1734        aside {
1735        }
1736
1737        /// HTML `<details>` element - Defines additional details that the user can view or hide
1738        ///
1739        /// Example:
1740        ///
1741        /// ```<details><summary>Click to view details</summary><p>Details content goes here...</p></details>```
1742        details {
1743        }
1744
1745        /// HTML `<figcaption>` element - Defines a caption for a `<figure>` element
1746        ///
1747        /// Example:
1748        ///
1749        /// ```<figure><img src="image.jpg" alt="Image description" /><figcaption>Caption goes here...</figcaption></figure>```
1750        figcaption {
1751        }
1752
1753        /// HTML `<figure>` element - Specifies self-contained content, like illustrations, diagrams, photos, code listings, etc.
1754        ///
1755        /// Example:
1756        ///
1757        /// ```<figure><img src="image.jpg" alt="Image description" /><figcaption>Caption goes here...</figcaption></figure>```
1758        figure {
1759        }
1760
1761        /// HTML `<footer>` element - Defines a footer for a document or section
1762        ///
1763        /// Example:
1764        ///
1765        /// ```<footer><p>Footer content goes here...</p></footer>```
1766        footer {
1767        }
1768
1769        /// HTML `<header>` element - Defines a container for introductory content or a set of navigational links
1770        ///
1771        /// Example:
1772        ///
1773        /// ```<header><h1>Header content goes here...</h1></header>```
1774        header {
1775        }
1776
1777        /// HTML `<main>` element - Specifies the main content of a document
1778        ///
1779        /// Example:
1780        ///
1781        /// ```<main><p>Main content goes here...</p></main>```
1782        main {
1783        }
1784
1785        /// HTML `<mark>` element - Defines marked/highlighted text
1786        ///
1787        /// Example:
1788        ///
1789        /// ```<p>Some <mark>marked</mark> text.</p>```
1790        mark {
1791        }
1792
1793        /// HTML `<nav>` element - Defines navigation links
1794        ///
1795        /// Example:
1796        ///
1797        /// ```<nav><a href="#home">Home</a> <a href="#about">About</a> <a href="#contact">Contact</a></nav>```
1798        nav {
1799        }
1800
1801        /// HTML `<section>` element - Defines a section in a document
1802        ///
1803        /// Example:
1804        ///
1805        /// ```<section><h2>Section Title</h2><p>Section content goes here...</p></section>```
1806        section {
1807        }
1808
1809        /// HTML `<summary>` element - Defines a visible heading for a `<details>` element
1810        ///
1811        /// Example:
1812        ///
1813        /// ```<details><summary>Click to view details</summary><p>Details content goes here...</p></details>```
1814        summary {
1815        }
1816
1817        /// HTML `<time>` element - Defines a date/time
1818        ///
1819        /// Example:
1820        ///
1821        /// ```<p>Published on <time datetime="2023-08-01">August 1, 2023</time></p>```
1822        time {
1823            /// The datetime attribute specifies the date/time
1824            /// Example: datetime="2023-08-01" (August 1, 2023)
1825            datetime: String,
1826            /// The pubdate attribute specifies that the content is published
1827            /// Example: pubdate="pubdate" (content is published)
1828            pubdate: String,
1829        }
1830
1831        /// HTML `<wbr>` element - Inserts a line break opportunity
1832        ///
1833        /// Example:
1834        ///
1835        /// ```<p>Here is a long word:<wbr>supercalifragilisticexpialidocious</p>```
1836        wbr {
1837        }
1838
1839        /// HTML `<address>` element - Defines contact information for the author/owner of a document
1840        ///
1841        /// Example:
1842        ///
1843        /// ```<address>Contact us at <a href="mailto:="mail="mailto:EMAIL"EMAILample.com</a></address>```
1844        address {
1845        }
1846
1847        /// HTML `<bdi>` element - Defines a term/name within a description list
1848        ///
1849        /// Example:
1850        ///
1851        /// ```<dl><dt><bdi>Name</bdi></dt><dd>John Doe</dd></dl>```
1852        bdi {
1853        }
1854
1855        /// HTML `<bdo>` element - Overrides the current text direction
1856        ///
1857        /// Example:
1858        ///
1859        /// ```<p><bdo dir="rtl">This text is written from right to left</bdo></p>```
1860        bdo {
1861        }
1862
1863        /// HTML `<cite>` element - Defines the title of a work
1864        ///
1865        /// Example:
1866        ///
1867        /// ```<p>To learn more about <cite>HTML</cite>, visit <a href="```<p>To learn more about <cite>HTML</cite>, visit <a href="URL_ADDRESS.w3.org/TR/html52/">W3C</a>.</p>```
1868        cite {
1869        }
1870
1871        /// HTML `<dfn>` element - Defines a definition
1872        ///
1873        /// Example:
1874        ///
1875        /// ```<p>The <dfn>HTML</dfn> element is used to define a section in a document.</p>```
1876        dfn {
1877        }
1878
1879        /// HTML `<em>` element - Defines emphasized text
1880        ///
1881        /// Example:
1882        ///
1883        /// ```<p>He is <em>very</em> angry.</p>```
1884        em {
1885        }
1886
1887        /// HTML `<i>` element - Defines a part of text in an alternate voice or mood
1888        ///
1889        /// Example:
1890        ///
1891        /// ```<p><i>This text is in italics.</i></p>```
1892        i {
1893        }
1894
1895        /// HTML `<kbd>` element - Defines keyboard input
1896        ///
1897        /// Example:
1898        ///
1899        /// ```<p>Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy.</p>```
1900        kbd {
1901        }
1902
1903        /// HTML `<meter>` element - Defines a scalar measurement within a known range (a gauge)
1904        ///
1905        /// Example:
1906        ///
1907        /// ```<meter value="75" min="0" max="100"></meter>```
1908        meter {
1909            /// The value attribute specifies the current value
1910            /// Example: value="75" (current value is 75)
1911            value: String,
1912            /// The min attribute specifies the minimum value
1913            /// Example: min="0" (minimum value is 0)
1914            min: String,
1915            /// The max attribute specifies the maximum value
1916            /// Example: max="100" (maximum value is 100)
1917            max: String,
1918            /// The low attribute specifies the low value
1919            /// Example: low="33" (low value is 33)
1920            low: String,
1921            /// The high attribute specifies the high value
1922            /// Example: high="66" (high value is 66)
1923            high: String,
1924            /// The optimum attribute specifies the optimum value
1925            /// Example: optimum="50" (optimum value is 50)
1926            optimum: String,
1927        }
1928
1929        /// HTML `<output>` element - Defines the result of a calculation
1930        ///
1931        /// Example:
1932        ///
1933        /// ```<form><input type="number" id="num1" /><input type="number" id="num2" /><button onclick="calculate()">Calculate</button><output id="result"></output></form>```
1934        output {
1935        }
1936
1937        /// HTML `<progress>` element - Defines the progress of a task
1938        ///
1939        /// Example:
1940        ///
1941        /// ```<progress value="75" max="100"></progress>```
1942        progress {
1943            /// The value attribute specifies the current value
1944            /// Example: value="75" (current value is 75)
1945            value: String,
1946            /// The max attribute specifies the maximum value
1947            /// Example: max="100" (maximum value is 100)
1948            max: String,
1949        }
1950
1951        /// HTML `<q>` element - Defines a short inline quotation
1952        ///
1953        /// Example:
1954        ///
1955        /// ```<p><q>We are the so-called "Vikings" from the north.</q></p>```
1956        q {
1957        }
1958
1959        /// HTML `<rp>` element - Defines a parenthesis for browsers that do not support `<ruby>`
1960        ///
1961        /// Example:
1962        ///
1963        /// ```<ruby><rb>漢</rb><rp>(</rp><rt>han</rt><rp>)</rp></ruby>```
1964        rp {
1965        }
1966
1967        /// HTML `<rt>` element - Defines a ruby text
1968        ///
1969        /// Example:
1970        ///
1971        /// ```<ruby><rb>漢</rb><rt>han</rt></ruby>```
1972        rt {
1973        }
1974
1975        /// HTML `<ruby>` element - Defines a ruby annotation (for East Asian typography)
1976        ///
1977        /// Example:
1978        ///
1979        /// ```<ruby><rb>漢</rb><rt>han</rt></ruby>```
1980        ruby {
1981        }
1982
1983        /// HTML `<s>` element - Defines strikethrough text
1984        ///
1985        /// Example:
1986        ///
1987        /// ```<p>Price: <s>$100</s> $50</p>```
1988        s {
1989        }
1990
1991        /// HTML `<samp>` element - Defines sample output from a computer program
1992        ///
1993        /// Example:
1994        ///
1995        /// ```<samp>Hello, World!</samp>```
1996        samp {
1997        }
1998
1999        /// HTML `<small>` element - Defines smaller text
2000        ///
2001        /// Example:
2002        ///
2003        /// ```<p><small>This is some smaller text.</small></p>```
2004        small {
2005        }
2006
2007        /// HTML `<strong>` element - Defines important text
2008        ///
2009        /// Example:
2010        ///
2011        /// ```<p><strong>This is important!</strong></p>```
2012        strong {
2013        }
2014
2015        /// HTML `<sub>` element - Defines subscript text
2016        ///
2017        /// Example:
2018        ///
2019        /// ```<p>H<sub>2</sub>O</p>```
2020        sub {
2021        }
2022
2023        /// HTML `<sup>` element - Defines superscript text
2024        ///
2025        /// Example:
2026        ///
2027        /// ```<p>X<sup>2</sup></p>```
2028        sup {
2029        }
2030
2031        /// HTML `<var>` element - Defines a variable
2032        ///
2033        /// Example:
2034        ///
2035        /// ```<p>The area is <var>x</var> times <var>y</var>.</p>```
2036        var {
2037        }
2038
2039        /// HTML `<template>` element - Defines a container for content that is not to be rendered when a page is loaded
2040        ///
2041        /// Example:
2042        ///
2043        /// ```<template><p>This content will not be rendered.</p></template>```
2044        template {
2045        }
2046
2047        /// HTML `<u>` element - Defines text that should be rendered as underlined
2048        ///
2049        /// Example:
2050        ///
2051        /// ```<p><u>This text is underlined.</u></p>```
2052        u {
2053        }
2054
2055        /// HTML `<noscript>` element - Defines content that is displayed to users with disabled scripts
2056        ///
2057        /// Example:
2058        ///
2059        /// ```<noscript><p>JavaScript is disabled.</p></noscript>```
2060        noscript {
2061        }
2062
2063        /// HTML `<legend>` element - Defines a caption for a `<fieldset>` element
2064        ///
2065        /// Example:
2066        ///
2067        /// ```<fieldset><legend>Personal Information</legend><input type="text" name="name" /><input type="email" name="email" /></fieldset>```
2068        legend {
2069        }
2070
2071        /// HTML `<optgroup>` element - Defines a group of related `<option>` elements in a `<select>` element
2072        ///
2073        /// Example:
2074        ///
2075        /// ```<select><optgroup label="Fruits"><option value="apple">Apple</option><option value="banana">Banana</option></optgroup><optgroup label="Vegetables"><option value="carrot">Carrot</option><option value="potato">Potato</option></optgroup></select>```
2076        optgroup {
2077            /// The label attribute specifies a label for the group
2078            /// Example: label="Fruits" (label for the group is "Fruits")
2079            label: String,
2080        }
2081
2082        /// HTML `<dialog>` element - Defines a dialog box or other interactive component
2083        ///
2084        /// Example:
2085        ///
2086        /// ```<dialog><p>Dialog content goes here...</p><button onclick="closeDialog()">Close</button></dialog>```
2087        dialog {
2088            /// The open attribute specifies whether the dialog is open or closed
2089            /// Example: open="open" (dialog is open)
2090            open: String,
2091        }
2092
2093        /// HTML `<blockquote>` element - Defines a section that is quoted from another source
2094        ///
2095        /// Example:
2096        ///
2097        /// ```<blockquote><p>This is a quote.</p><footer>- John Doe</footer></blockquote>```
2098        blockquote {
2099        }
2100
2101        /// HTML `<dd>` element - Defines a description/value pair within a `<dl>` element
2102        ///
2103        /// Example:
2104        ///
2105        /// ```<dl><dt>Coffee</dt><dd>Black hot drink</dd><dt>Milk</dt><dd>White cold drink</dd></dl>```
2106        dd {
2107        }
2108
2109        /// HTML `<dl>` element - Defines a description list
2110        ///
2111        /// Example:
2112        ///
2113        /// ```<dl><dt>Coffee</dt><dd>Black hot drink</dd><dt>Milk</dt><dd>White cold drink</dd></dl>```
2114        dl {
2115        }
2116
2117        /// HTML `<dt>` element - Defines a term/name in a description list
2118        ///
2119        /// Example:
2120        ///
2121        /// ```<dl><dt>Coffee</dt><dd>Black hot drink</dd><dt>Milk</dt><dd>White cold drink</dd></dl>```
2122        dt {
2123        }
2124
2125        /// HTML `<base>` element - Specifies the base URL/target for all relative URLs in a document
2126        ///
2127        /// Example:
2128        ///
2129        /// ```<base href="```<base href="URL_ADDRESS.example.com/" target="_blank">```
2130        base {
2131            /// The href attribute specifies the base URL
2132            /// ```<base href="URL_ADDR```<base href="URL_ADDRESS.example.com/" target="_blank">```
2133            href: String,
2134            /// The target attribute specifies the target for all relative URLs
2135            /// ```<base href="URL_ADDRESS.example.com/" target="_blank">```
2136            target: String,
2137        }
2138    }
2139}