rtml/
tags.rs

1use crate::*;
2
3pub trait Tag: std::fmt::Display + 'static {}
4
5pub trait TagValue: ToString {
6    fn render(&self) -> String {
7        return self.to_string();
8    }
9}
10
11macro_rules! tagit {
12    ($tag:ident, $trait:ident $(,$attr:ident)*) => {
13        #[allow(unused_variables)]
14        impl $tag {
15            pub fn type_check(&self, attr: &dyn $trait){}
16        }
17        #[warn(unused_variables)]
18        pub trait $trait {}
19        impl Tag for $tag {}
20
21        $(impl $trait for $attr {})*
22    };
23}
24
25tagit! {ATag, ACompat, download, href, hreflang, media, ping, referrerpolicy, rel, target }
26tagit! {AbbrTag, AbbrCompat}
27tagit! {AddressTag, AddressCompat}
28tagit! {AreaTag, AreaCompat, alt, coords, download, href, hreflang, media, rel, shape, target }
29tagit! {ArticleTag, ArticleCompat}
30tagit! {AsideTag, AsideCompat}
31tagit! {AudioTag, AudioCompat, autoplay, controls, _loop, muted, preload, src }
32tagit! {BTag, BCompat}
33tagit! {BaseTag, BaseCompat, href, target }
34tagit! {BdiTag, BdiCompat}
35tagit! {BdoTag, BdoCompat}
36tagit! {BlockquoteTag, BlockquoteCompat, cite }
37tagit! {BodyTag, BodyCompat}
38tagit! {BrTag, BrCompat}
39tagit! {ButtonTag, ButtonCompat, autofocus, disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, name, _type, value }
40tagit! {CanvasTag, CanvasCompat, height, width }
41tagit! {CaptionTag, CaptionCompat}
42tagit! {CiteTag, CiteCompat}
43tagit! {CodeTag, CodeCompat}
44tagit! {ColTag, ColCompat, span }
45tagit! {ColgroupTag, ColgroupCompat, span }
46tagit! {DataTag, DataCompat, value }
47tagit! {DatalistTag, DatalistCompat}
48tagit! {DdTag, DdCompat}
49tagit! {DelTag, DelCompat, cite, datetime }
50tagit! {DetailsTag, DetailsCompat, open }
51tagit! {DfnTag, DfnCompat}
52tagit! {DialogTag, DialogCompat, open }
53tagit! {DivTag, DivCompat}
54tagit! {DlTag, DlCompat}
55tagit! {DtTag, DtCompat}
56tagit! {EmTag, EmCompat}
57tagit! {EmbedTag, EmbedCompat, height, src, _type, width }
58tagit! {FieldsetTag, FieldsetCompat, disabled, form, name }
59tagit! {FigcaptionTag, FigcaptionCompat}
60tagit! {FigureTag, FigureCompat}
61tagit! {FooterTag, FooterCompat}
62tagit! {FormTag, FormCompat, accept_charset, action, autocomplete, enctype, method, name, novalidate, target }
63tagit! {H1Tag, H1Compat}
64tagit! {H2Tag, H2Compat}
65tagit! {H3Tag, H3Compat}
66tagit! {H4Tag, H4Compat}
67tagit! {H5Tag, H5Compat}
68tagit! {H6Tag, H6Compat}
69tagit! {HeadTag, HeadCompat}
70tagit! {HeaderTag, HeaderCompat}
71tagit! {HrTag, HrCompat}
72tagit! {HtmlTag, HtmlCompat}
73tagit! {ITag, ICompat}
74tagit! {IframeTag, IframeCompat, allow, allowfullscreen, height, name, referrerpolicy, sandbox, src, srcdoc, width }
75tagit! {ImgTag, ImgCompat, alt, crossorigin, decoding, height, referrerpolicy, sizes, src, srcset, usemap, width }
76tagit! {InputTag, InputCompat, accept, alt, autocomplete, autofocus, checked, disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, height, list, max, maxlength, min, minlength, multiple, name, pattern, placeholder, readonly, required, size, src, step, _type, value, width }
77tagit! {InsTag, InsCompat, cite, datetime }
78tagit! {KbdTag, KbdCompat}
79tagit! {LabelTag, LabelCompat, form }
80tagit! {LegendTag, LegendCompat}
81tagit! {LiTag, LiCompat, value }
82tagit! {LinkTag, LinkCompat, _as, crossorigin, href, hreflang, media, rel, sizes, _type }
83tagit! {MainTag, MainCompat}
84tagit! {MapTag, MapCompat, name }
85tagit! {MarkTag, MarkCompat}
86tagit! {MenuTag, MenuCompat, _type }
87tagit! {MetaTag, MetaCompat, charset, content, http_equiv, name }
88tagit! {MeterTag, MeterCompat, high, low, max, min, optimum, value }
89tagit! {NavTag, NavCompat}
90tagit! {NoscriptTag, NoscriptCompat}
91tagit! {ObjectTag, ObjectCompat, data, form, height, name, _type, width }
92tagit! {OlTag, OlCompat, reversed, start }
93tagit! {OptgroupTag, OptgroupCompat, disabled, label }
94tagit! {OptionTag, OptionCompat, disabled, label, selected, value }
95tagit! {OutputTag, OutputCompat, _for, form, name }
96tagit! {PTag, PCompat}
97tagit! {PictureTag, PictureCompat}
98tagit! {PreTag, PreCompat}
99tagit! {ProgressTag, ProgressCompat, max, value }
100tagit! {QTag, QCompat, cite }
101tagit! {RpTag, RpCompat}
102tagit! {RtTag, RtCompat}
103tagit! {RubyTag, RubyCompat}
104tagit! {STag, SCompat}
105tagit! {SampTag, SampCompat}
106tagit! {ScriptTag, ScriptCompat, _async, crossorigin, defer, integrity, nomodule, src, _type }
107tagit! {SectionTag, SectionCompat}
108tagit! {SelectTag, SelectCompat, autocomplete, autofocus, disabled, form, multiple, name, required, size }
109tagit! {SmallTag, SmallCompat}
110tagit! {SourceTag, SourceCompat, muted, media, sizes, src, srcset, _type }
111tagit! {SpanTag, SpanCompat}
112tagit! {StrongTag, StrongCompat}
113tagit! {StyleTag, StyleCompat, media, nonce, _type }
114tagit! {SubTag, SubCompat}
115tagit! {SummaryTag, SummaryCompat}
116tagit! {SupTag, SupCompat}
117tagit! {TableTag, TableCompat}
118tagit! {TbodyTag, TbodyCompat}
119tagit! {TdTag, TdCompat, colspan, headers, rowspan, scope }
120tagit! {TemplateTag, TemplateCompat}
121tagit! {TextareaTag, TextareaCompat, autocomplete, autofocus, cols, disabled, form, maxlength, minlength, name, placeholder, readonly, required, rows, wrap }
122tagit! {TfootTag, TfootCompat}
123tagit! {ThTag, ThCompat, colspan, headers, rowspan, scope }
124tagit! {TheadTag, TheadCompat}
125tagit! {TimeTag, TimeCompat, datetime }
126tagit! {TitleTag, TitleCompat}
127tagit! {TrTag, TrCompat}
128tagit! {TrackTag, TrackCompat, default, _kind, label, src, srclang }
129tagit! {UTag, UCompat}
130tagit! {UlTag, UlCompat}
131tagit! {VarTag, VarCompat}
132tagit! {VideoTag, VideoCompat, autoplay, controls, crossorigin, height, _loop, muted, playsinline, poster, preload, src, width }
133tagit! {WbrTag, WbrCompat}
134
135/// # Example
136/// ```
137/// # #[macro_use] extern crate rtml;
138/// # fn main() {
139/// use rtml::*;
140///
141/// assert_eq!(
142///     a![.href="https://www.example.com", "Link text"].render(),
143///     "<a href=\"https://www.example.com\">Link text</a>"
144/// );
145///
146/// assert_eq!(
147///     a![.href="/path/to/page", "Click here"].render(),
148///     "<a href=\"/path/to/page\">Click here</a>"
149/// );
150/// assert_eq!(
151///     a![.href="mailto:user@example.com", "Send email"].render(),
152///     "<a href=\"mailto:user@example.com\">Send email</a>"
153/// );
154///
155/// # }
156/// ```
157#[macro_export]
158macro_rules! a {
159    ($($all:tt)*) => {parse_double_tag!(ATag, $($all)*) };
160}
161
162/// # Example
163/// ```
164/// # #[macro_use] extern crate rtml;
165/// # fn main() {
166/// use rtml::*;
167///
168/// assert_eq!(
169///     abbr![.title="Hypertext Markup Language", "HTML"].render(),
170///     "<abbr title=\"Hypertext Markup Language\">HTML</abbr>"
171/// );
172///
173/// assert_eq!(
174///     abbr![.title="Scalable Vector Graphics", "SVG"].render(),
175///     "<abbr title=\"Scalable Vector Graphics\">SVG</abbr>"
176/// );
177/// # }
178/// ```
179#[macro_export]
180macro_rules! abbr {
181    ($($all:tt)*) => {parse_double_tag!(AbbrTag, $($all)*) };
182}
183
184/// # Example
185/// ```
186/// # #[macro_use] extern crate rtml;
187/// # fn main() {
188/// use rtml::*;
189///
190/// assert_eq!(
191///     address!["P. Sherman", br![], "42 Wallaby way", br![], "Sydney, Australia"].render(),
192///     "<address>P. Sherman<br>42 Wallaby way<br>Sydney, Australia</address>"
193/// );
194///
195/// # }
196/// ```
197#[macro_export]
198macro_rules! address {
199    ($($all:tt)*) => {parse_double_tag!(AddressTag, $($all)*) };
200}
201
202/// # Example
203/// ```
204/// # #[macro_use] extern crate rtml;
205/// # fn main() {
206/// use rtml::*;
207///
208/// assert_eq!(
209///     area![.shape="rect", .coords="0,0,100,100", .href="example.com"].render(),
210///     "<area shape=\"rect\" coords=\"0,0,100,100\" href=\"example.com\">"
211/// );
212///
213/// # }
214/// ```
215#[macro_export]
216macro_rules! area {
217    ($($all:tt)*) => {parse_single_tag!(AreaTag, $($all)*) };
218}
219
220/// # Example
221/// ```
222/// # #[macro_use] extern crate rtml;
223/// # fn main() {
224/// use rtml::*;
225///
226/// assert_eq!(
227///     article!["This is an article."].render(),
228///     "<article>This is an article.</article>"
229/// );
230///
231/// assert_eq!(
232///     article!["This is an article with a ", b!["bold"], " word."].render(),
233///     "<article>This is an article with a <b>bold</b> word.</article>"
234/// );
235/// # }
236/// ```
237#[macro_export]
238macro_rules! article {
239    ($($all:tt)*) => {parse_double_tag!(ArticleTag, $($all)*) };
240}
241
242/// # Example
243/// ```
244/// # #[macro_use] extern crate rtml;
245/// # fn main() {
246/// use rtml::*;
247///
248/// assert_eq!(
249///     aside!["This is an aside."].render(),
250///     "<aside>This is an aside.</aside>"
251/// );
252/// # }
253/// ```
254#[macro_export]
255macro_rules! aside {
256    ($($all:tt)*) => {parse_double_tag!(AsideTag, $($all)*) };
257}
258
259/// # Example
260/// ```
261/// # #[macro_use] extern crate rtml;
262/// # fn main() {
263/// use rtml::*;
264///
265/// assert_eq!(
266///     audio![.src="example.mp3"].render(),
267///     "<audio src=\"example.mp3\">"
268/// );
269///
270/// assert_eq!(
271///     audio![.src="example.mp3", .controls = "true"].render(),
272///     "<audio src=\"example.mp3\" controls=\"true\">"
273/// );
274/// # }
275/// ```
276#[macro_export]
277macro_rules! audio {
278    ($($all:tt)*) => {parse_single_tag!(AudioTag, $($all)*) };
279}
280
281/// # Example
282/// ```
283/// # #[macro_use] extern crate rtml;
284/// # fn main() {
285/// use rtml::*;
286///
287/// assert_eq!(
288///     b!["This is bold text"].render(),
289///     "<b>This is bold text</b>"
290/// );
291/// # }
292/// ```
293#[macro_export]
294macro_rules! b {
295    ($($all:tt)*) => {parse_double_tag!(BTag, $($all)*) };
296}
297
298/// # Example
299/// ```
300/// # #[macro_use] extern crate rtml;
301/// # fn main() {
302/// use rtml::*;
303///
304/// assert_eq!(
305///     base![.href="https://example.com"].render(),
306///     "<base href=\"https://example.com\">"
307/// );
308/// # }
309/// ```
310#[macro_export]
311macro_rules! base {
312    ($($all:tt)*) => {parse_single_tag!(BaseTag, $($all)*) };
313}
314
315/// # Example
316/// ```
317/// # #[macro_use] extern crate rtml;
318/// # fn main() {
319/// use rtml::*;
320///
321/// assert_eq!(
322///     bdi!["This text will be displayed in a different direction"].render(),
323///     "<bdi>This text will be displayed in a different direction</bdi>"
324/// );
325/// # }
326/// ```
327#[macro_export]
328macro_rules! bdi {
329    ($($all:tt)*) => {parse_double_tag!(BdiTag, $($all)*) };
330}
331
332/// # Example
333/// ```
334/// # #[macro_use] extern crate rtml;
335/// # fn main() {
336/// use rtml::*;
337///
338/// assert_eq!(
339///     bdo![.dir="rtl", "This text will be displayed in a right-to-left direction"].render(),
340///     "<bdo dir=\"rtl\">This text will be displayed in a right-to-left direction</bdo>"
341/// );
342/// # }
343/// ```
344#[macro_export]
345macro_rules! bdo {
346    ($($all:tt)*) => {parse_double_tag!(BdoTag, $($all)*) };
347}
348
349/// # Example
350/// ```
351/// # #[macro_use] extern crate rtml;
352/// # fn main() {
353/// use rtml::*;
354///
355/// assert_eq!(
356///     blockquote!["This is a blockquote."].render(),
357///     "<blockquote>This is a blockquote.</blockquote>"
358/// );
359///
360/// assert_eq!(
361///     blockquote![.cite="https://example.com","This is a blockquote with citation"].render(),
362///     "<blockquote cite=\"https://example.com\">This is a blockquote with citation</blockquote>"
363/// );
364/// # }
365/// ```
366#[macro_export]
367macro_rules! blockquote {
368    ($($all:tt)*) => {parse_double_tag!(BlockquoteTag, $($all)*) };
369}
370
371/// # Example
372/// ```
373/// # #[macro_use] extern crate rtml;
374/// # fn main() {
375/// use rtml::*;
376///
377/// assert_eq!(
378///     body!["This is the body"].render(),
379///     "<body>This is the body</body>"
380/// );
381/// # }
382/// ```
383#[macro_export]
384macro_rules! body {
385    ($($all:tt)*) => {parse_double_tag!(BodyTag, $($all)*) };
386}
387
388/// # Example
389/// ```
390/// # #[macro_use] extern crate rtml;
391/// # fn main() {
392/// use rtml::*;
393///
394/// assert_eq!(
395///     br![].render(),
396///     "<br>"
397/// );
398/// # }
399/// ```
400#[macro_export]
401macro_rules! br {
402    ($($all:tt)*) => {parse_single_tag!(BrTag, $($all)*) };
403}
404
405/// # Example
406/// ```
407/// # #[macro_use] extern crate rtml;
408/// # fn main() {
409/// use rtml::*;
410///
411/// assert_eq!(
412///     button!["Click me"].render(),
413///     "<button>Click me</button>"
414/// );
415///
416/// # }
417/// ```
418
419#[macro_export]
420macro_rules! button {
421    ($($all:tt)*) => {parse_double_tag!(ButtonTag, $($all)*) };
422}
423
424/// # Example
425/// ```
426/// # #[macro_use] extern crate rtml;
427/// # fn main() {
428/// use rtml::*;
429///
430/// assert_eq!(
431///     canvas![].render(),
432///     "<canvas></canvas>"
433/// );
434///
435/// assert_eq!(
436///     canvas![.width="300", .height="150"].render(),
437///     "<canvas width=\"300\" height=\"150\"></canvas>"
438/// );
439/// # }
440/// ```
441#[macro_export]
442macro_rules! canvas {
443    ($($all:tt)*) => {parse_double_tag!(CanvasTag, $($all)*) };
444}
445
446/// # Example
447/// ```
448/// # #[macro_use] extern crate rtml;
449/// # fn main() {
450/// use rtml::*;
451///
452/// assert_eq!(
453///     caption!["This is a caption"].render(),
454///     "<caption>This is a caption</caption>"
455/// );
456/// # }
457/// ```
458#[macro_export]
459macro_rules! caption {
460    ($($all:tt)*) => {parse_double_tag!(CaptionTag, $($all)*) };
461}
462
463/// # Example
464/// ```
465/// # #[macro_use] extern crate rtml;
466/// # fn main() {
467/// use rtml::*;
468///
469/// assert_eq!(
470///     cite!["This is a citation"].render(),
471///     "<cite>This is a citation</cite>"
472/// );
473/// # }
474/// ```
475#[macro_export]
476macro_rules! cite {
477    ($($all:tt)*) => {parse_double_tag!(CiteTag, $($all)*) };
478}
479
480/// # Example
481/// ```
482/// # #[macro_use] extern crate rtml;
483/// # fn main() {
484/// use rtml::*;
485///
486/// assert_eq!(
487///     code![ "h1![\"This is awesome!\"]" ].render(),
488///     "<code>h1![\"This is awesome!\"]</code>"
489/// );
490/// # }
491/// ```
492#[macro_export]
493macro_rules! code {
494    ($($all:tt)*) => {parse_double_tag!(CodeTag, $($all)*) };
495}
496
497/// # Example
498/// ```
499/// # #[macro_use] extern crate rtml;
500/// # fn main() {
501/// use rtml::*;
502///
503/// assert_eq!(
504///     col![.span="2", .style="background-color:red"].render(),
505///     "<col span=\"2\" style=\"background-color:red\">"
506/// );
507/// # }
508/// ```
509#[macro_export]
510macro_rules! col {
511    ($($all:tt)*) => {parse_single_tag!(ColTag, $($all)*) };
512}
513
514/// # Example
515/// ```
516/// # #[macro_use] extern crate rtml;
517/// # fn main() {
518/// use rtml::*;
519///
520/// assert_eq!(
521///     colgroup![col![], col![]].render(),
522///     "<colgroup><col><col></colgroup>"
523/// );
524///
525/// # }
526/// ```
527#[macro_export]
528macro_rules! colgroup {
529    ($($all:tt)*) => {parse_double_tag!(ColgroupTag, $($all)*) };
530}
531
532/// # Example
533/// ```
534/// # #[macro_use] extern crate rtml;
535/// # fn main() {
536/// use rtml::*;
537///
538/// assert_eq!(
539///     data!["123"].render(),
540///     "<data>123</data>"
541/// );
542///
543/// assert_eq!(
544///     data![.value = "456", "Data Value"].render(),
545///     "<data value=\"456\">Data Value</data>"
546/// );
547/// # }
548/// ```
549#[macro_export]
550macro_rules! data {
551    ($($all:tt)*) => {parse_double_tag!(DataTag, $($all)*) };
552}
553
554/// # Example
555/// ```
556/// # #[macro_use] extern crate rtml;
557/// # fn main() {
558/// use rtml::*;
559///
560/// assert_eq!(
561///     datalist![option!["option1"], option!["option2"], option!["option3"]].render(),
562///     "<datalist><option>option1</option><option>option2</option><option>option3</option></datalist>"
563/// );
564/// # }
565/// ```
566#[macro_export]
567macro_rules! datalist {
568    ($($all:tt)*) => {parse_double_tag!(DatalistTag, $($all)*) };
569}
570
571/// # Example
572/// ```
573/// # #[macro_use] extern crate rtml;
574/// # fn main() {
575/// use rtml::*;
576///
577/// assert_eq!(
578///     dd!["This is a definition"].render(),
579///     "<dd>This is a definition</dd>"
580/// );
581/// # }
582/// ```
583#[macro_export]
584macro_rules! dd {
585    ($($all:tt)*) => {parse_double_tag!(DdTag, $($all)*) };
586}
587
588/// # Example
589/// ```
590/// # #[macro_use] extern crate rtml;
591/// # fn main() {
592/// use rtml::*;
593///
594/// assert_eq!(
595///     del!["This text is deleted"].render(),
596///     "<del>This text is deleted</del>"
597/// );
598/// # }
599/// ```
600#[macro_export]
601macro_rules! del {
602    ($($all:tt)*) => {parse_double_tag!(DelTag, $($all)*) };
603}
604
605/// # Example
606/// ```
607/// # #[macro_use] extern crate rtml;
608/// # fn main() {
609/// use rtml::*;
610///
611/// assert_eq!(
612///     details![summary!["Details"], "This is the details content"].render(),
613///     "<details><summary>Details</summary>This is the details content</details>"
614/// );
615///
616/// # }
617#[macro_export]
618macro_rules! details {
619    ($($all:tt)*) => {parse_double_tag!(DetailsTag, $($all)*) };
620}
621
622/// # Example
623/// ```
624/// # #[macro_use] extern crate rtml;
625/// # fn main() {
626/// use rtml::*;
627///
628/// assert_eq!(
629///     dialog!["This is a dialog"].render(),
630///     "<dialog>This is a dialog</dialog>"
631/// );
632/// # }
633/// ```
634#[macro_export]
635macro_rules! dialog {
636    ($($all:tt)*) => {parse_double_tag!(DialogTag, $($all)*) };
637}
638
639/// # Example
640/// ```
641/// # #[macro_use] extern crate rtml;
642/// # fn main() {
643/// use rtml::*;
644///
645/// assert_eq!(
646///     div!{ "This is a div\"s inner text!" }.render(),
647///     "<div>This is a div\"s inner text!</div>"
648/// );
649/// # }
650/// ```
651#[macro_export]
652macro_rules! div {
653    ($($all:tt)*) => {parse_double_tag!(DivTag, $($all)*) };
654}
655
656/// # Example
657/// ```
658/// # #[macro_use] extern crate rtml;
659/// # fn main() {
660/// use rtml::*;
661///
662/// assert_eq!(
663///     dl![dt!["Term 1"], dd!["Definition 1"], dt!["Term 2"], dd!["Definition 2"]].render(),
664///     "<dl><dt>Term 1</dt><dd>Definition 1</dd><dt>Term 2</dt><dd>Definition 2</dd></dl>"
665/// );
666/// # }
667/// ```
668#[macro_export]
669macro_rules! dl {
670    ($($all:tt)*) => {parse_double_tag!(DlTag, $($all)*) };
671}
672
673/// # Example
674/// ```
675/// # #[macro_use] extern crate rtml;
676/// # fn main() {
677/// use rtml::*;
678///
679/// assert_eq!(
680///     dl![dt!["Term 1"], dd!["Definition 1"], dt!["Term 2"], dd!["Definition 2"]].render(),
681///     "<dl><dt>Term 1</dt><dd>Definition 1</dd><dt>Term 2</dt><dd>Definition 2</dd></dl>"
682/// );
683/// # }
684/// ```
685#[macro_export]
686macro_rules! dt {
687    ($($all:tt)*) => {parse_double_tag!(DtTag, $($all)*) };
688}
689
690/// # Example
691/// ```
692/// # #[macro_use] extern crate rtml;
693/// # fn main() {
694/// use rtml::*;
695///
696/// assert_eq!(
697///     em!["This is emphasized text"].render(),
698///     "<em>This is emphasized text</em>"
699/// );
700/// # }
701/// ```
702#[macro_export]
703macro_rules! em {
704    ($($all:tt)*) => {parse_double_tag!(EmTag, $($all)*) };
705}
706
707/// # Example
708/// ```
709/// # #[macro_use] extern crate rtml;
710/// # fn main() {
711/// use rtml::*;
712///
713/// assert_eq!(
714///     embed![.src="example.swf"].render(),
715///     "<embed src=\"example.swf\">"
716/// );
717///
718/// assert_eq!(
719///     embed![.src="example.swf", ._type="application/x-shockwave-flash", .width="400", .height="300"].render(),
720///     "<embed src=\"example.swf\" type=\"application/x-shockwave-flash\" width=\"400\" height=\"300\">"
721/// );
722/// # }
723/// ```
724#[macro_export]
725macro_rules! embed {
726    ($($all:tt)*) => {parse_single_tag!(EmbedTag, $($all)*) };
727}
728
729/// # Example
730/// ```
731/// # #[macro_use] extern crate rtml;
732/// # fn main() {
733/// use rtml::*;
734///
735/// assert_eq!(
736///     fieldset![legend!["This is a fieldset"], "This is the fieldset content"].render(),
737///     "<fieldset><legend>This is a fieldset</legend>This is the fieldset content</fieldset>"
738/// );
739/// # }
740/// ```
741#[macro_export]
742macro_rules! fieldset {
743    ($($all:tt)*) => {parse_double_tag!(FieldsetTag, $($all)*) };
744}
745
746/// # Example
747/// ```
748/// # #[macro_use] extern crate rtml;
749/// # fn main() {
750/// use rtml::*;
751///
752/// assert_eq!(
753///     figcaption!["This is a caption"].render(),
754///     "<figcaption>This is a caption</figcaption>"
755/// );
756/// # }
757/// ```
758#[macro_export]
759macro_rules! figcaption {
760    ($($all:tt)*) => {parse_double_tag!(FigcaptionTag, $($all)*) };
761}
762
763/// # Example
764/// ```
765/// # #[macro_use] extern crate rtml;
766/// # fn main() {
767/// use rtml::*;
768///
769/// assert_eq!(
770///     figure![img![.src="example.jpg"], figcaption!["This is a caption"]].render(),
771///     "<figure><img src=\"example.jpg\"><figcaption>This is a caption</figcaption></figure>"
772/// );
773/// # }
774/// ```
775#[macro_export]
776macro_rules! figure {
777    ($($all:tt)*) => {parse_double_tag!(FigureTag, $($all)*) };
778}
779
780/// # Example
781/// ```
782/// # #[macro_use] extern crate rtml;
783/// # fn main() {
784/// use rtml::*;
785///
786/// assert_eq!(
787///     footer!["This is a footer"].render(),
788///     "<footer>This is a footer</footer>"
789/// );
790/// # }
791/// ```
792#[macro_export]
793macro_rules! footer {
794    ($($all:tt)*) => {parse_double_tag!(FooterTag, $($all)*) };
795}
796
797/// # Example
798/// ```
799/// # #[macro_use] extern crate rtml;
800/// # fn main() {
801/// use rtml::*;
802///
803/// assert_eq!(
804///     form![.action="https://www.example.com", .method="post", "This is a form"].render(),
805///     "<form action=\"https://www.example.com\" method=\"post\">This is a form</form>"
806/// );
807/// # }
808/// ```
809#[macro_export]
810macro_rules! form {
811    ($($all:tt)*) => {parse_double_tag!(FormTag, $($all)*) };
812}
813
814/// # Example
815/// ```
816/// # #[macro_use] extern crate rtml;
817/// # fn main() {
818/// use rtml::*;
819///
820/// assert_eq!(
821///     h1!["This is a heading"].render(),
822///     "<h1>This is a heading</h1>"
823/// );
824/// # }
825/// ```
826#[macro_export]
827macro_rules! h1 {
828    ($($all:tt)*) => {parse_double_tag!(H1Tag, $($all)*) };
829}
830
831/// # Example
832/// ```
833/// # #[macro_use] extern crate rtml;
834/// # fn main() {
835/// use rtml::*;
836///
837/// assert_eq!(
838///     h2!["This is a heading"].render(),
839///     "<h2>This is a heading</h2>"
840/// );
841/// # }
842/// ```
843#[macro_export]
844macro_rules! h2 {
845    ($($all:tt)*) => {parse_double_tag!(H2Tag, $($all)*) };
846}
847
848/// # Example
849/// ```
850/// # #[macro_use] extern crate rtml;
851/// # fn main() {
852/// use rtml::*;
853///
854/// assert_eq!(
855///     h3!["This is a heading"].render(),
856///     "<h3>This is a heading</h3>"
857/// );
858/// # }
859/// ```
860#[macro_export]
861macro_rules! h3 {
862    ($($all:tt)*) => {parse_double_tag!(H3Tag, $($all)*) };
863}
864
865/// # Example
866/// ```
867/// # #[macro_use] extern crate rtml;
868/// # fn main() {
869/// use rtml::*;
870///
871/// assert_eq!(
872///     h4!["This is a heading"].render(),
873///     "<h4>This is a heading</h4>"
874/// );
875/// # }
876/// ```
877#[macro_export]
878macro_rules! h4 {
879    ($($all:tt)*) => {parse_double_tag!(H4Tag, $($all)*) };
880}
881
882/// # Example
883/// ```
884/// # #[macro_use] extern crate rtml;
885/// # fn main() {
886/// use rtml::*;
887///
888/// assert_eq!(
889///     h5!["This is a heading"].render(),
890///     "<h5>This is a heading</h5>"
891/// );
892/// # }
893/// ```
894#[macro_export]
895macro_rules! h5 {
896    ($($all:tt)*) => {parse_double_tag!(H5Tag, $($all)*) };
897}
898
899/// # Example
900/// ```
901/// # #[macro_use] extern crate rtml;
902/// # fn main() {
903/// use rtml::*;
904///
905/// assert_eq!(
906///     h6!["This is a heading"].render(),
907///     "<h6>This is a heading</h6>"
908/// );
909/// # }
910/// ```
911#[macro_export]
912macro_rules! h6 {
913    ($($all:tt)*) => {parse_double_tag!(H6Tag, $($all)*) };
914}
915
916/// # Example
917/// ```
918/// # #[macro_use] extern crate rtml;
919/// # fn main() {
920/// use rtml::*;
921///
922/// assert_eq!(
923///     head![title!["This is a title"], link![.rel="stylesheet", .href="example.css"]].render(),
924///     "<head><title>This is a title</title><link rel=\"stylesheet\" href=\"example.css\"></head>"
925/// );
926/// # }
927/// ```
928#[macro_export]
929macro_rules! head {
930    ($($all:tt)*) => {parse_double_tag!(HeadTag, $($all)*) };
931}
932
933/// # Example
934/// ```
935/// # #[macro_use] extern crate rtml;
936/// # fn main() {
937/// use rtml::*;
938///
939/// assert_eq!(
940///     header!["This is a header"].render(),
941///     "<header>This is a header</header>"
942/// );
943/// # }
944/// ```
945#[macro_export]
946macro_rules! header {
947    ($($all:tt)*) => {parse_double_tag!(HeaderTag, $($all)*) };
948}
949
950/// # Example
951/// ```
952/// # #[macro_use] extern crate rtml;
953/// # fn main() {
954/// use rtml::*;
955///
956/// assert_eq!(
957///     hr![].render(),
958///     "<hr>"
959/// );
960/// # }
961/// ```
962#[macro_export]
963macro_rules! hr {
964    ($($all:tt)*) => {parse_single_tag!(HrTag, $($all)*) };
965}
966
967/// # Example
968/// ```
969/// # #[macro_use] extern crate rtml;
970/// # fn main() {
971/// use rtml::*;
972///
973/// let result = html! {
974///  .lang = "en",
975///      head!{
976///          title!{
977///              "Title of the document"
978///          }
979///      },
980///      body!{
981///              div!{
982///                  "text",
983///                  h1!{
984///                      "This is a heading"
985///                  },
986///                  p!{
987///                      "This is a paragraph"
988///                  }
989///              }
990///      }
991/// }.render();
992///
993/// println!("{}", result);
994///
995/// assert_eq!(
996///     html![head![title!["This is a title"]], body!["This is the body"]].render(),
997///     "<html><head><title>This is a title</title></head><body>This is the body</body></html>"
998/// );
999/// # }
1000/// ```
1001#[macro_export]
1002macro_rules! html {
1003    ($($all:tt)*) => {parse_double_tag!(HtmlTag, $($all)*) };
1004}
1005
1006/// # Example
1007/// ```
1008/// # #[macro_use] extern crate rtml;
1009/// # fn main() {
1010/// use rtml::*;
1011///
1012/// assert_eq!(
1013///     i!["This is in italic"].render(),
1014///     "<i>This is in italic</i>"
1015/// );
1016/// # }
1017/// ```
1018#[macro_export]
1019macro_rules! i {
1020    ($($all:tt)*) => {parse_double_tag!(ITag, $($all)*) };
1021}
1022
1023/// # Example
1024/// ```
1025/// # #[macro_use] extern crate rtml;
1026/// # fn main() {
1027/// use rtml::*;
1028///
1029/// assert_eq!(
1030///     iframe![.src="example.html"].render(),
1031///     "<iframe src=\"example.html\"></iframe>"
1032/// );
1033///
1034/// assert_eq!(
1035///     iframe![.src="example.html", .width="400", .height="300"].render(),
1036///     "<iframe src=\"example.html\" width=\"400\" height=\"300\"></iframe>"
1037/// );
1038/// # }
1039/// ```
1040#[macro_export]
1041macro_rules! iframe {
1042    ($($all:tt)*) => {parse_double_tag!(IframeTag, $($all)*) };
1043}
1044
1045/// # Example
1046/// ```
1047/// # #[macro_use] extern crate rtml;
1048/// # fn main() {
1049/// use rtml::*;
1050///
1051/// assert_eq!(
1052///     img![.src="example.jpg"].render(),
1053///     "<img src=\"example.jpg\">"
1054/// );
1055/// # }
1056/// ```
1057#[macro_export]
1058macro_rules! img {
1059    ($($all:tt)*) => {parse_single_tag!(ImgTag, $($all)*) };
1060}
1061
1062/// # Example
1063/// ```
1064/// # #[macro_use] extern crate rtml;
1065/// # fn main() {
1066/// use rtml::*;
1067///
1068/// assert_eq!(
1069///     input![._type="text", .name="name"].render(),
1070///     "<input type=\"text\" name=\"name\">"
1071/// );
1072///
1073/// assert_eq!(
1074///     input![._type="submit", .value="submit"].render(),
1075///     "<input type=\"submit\" value=\"submit\">"
1076/// );
1077/// # }
1078/// ```
1079#[macro_export]
1080macro_rules! input {
1081    ($($all:tt)*) => {parse_single_tag!(InputTag, $($all)*) };
1082}
1083
1084/// # Example
1085/// ```
1086/// # #[macro_use] extern crate rtml;
1087/// # fn main() {
1088/// use rtml::*;
1089///
1090/// assert_eq!(
1091///     ins![.datetime="2022-01-01", "This is inserted text"].render(),
1092///     "<ins datetime=\"2022-01-01\">This is inserted text</ins>"
1093/// );
1094/// # }
1095/// ```
1096#[macro_export]
1097macro_rules! ins {
1098    ($($all:tt)*) => {parse_double_tag!(InsTag, $($all)*) };
1099}
1100
1101/// # Example
1102/// ```
1103/// # #[macro_use] extern crate rtml;
1104/// # fn main() {
1105/// use rtml::*;
1106///
1107/// assert_eq!(
1108///     kbd!["This is keyboard input"].render(),
1109///     "<kbd>This is keyboard input</kbd>"
1110/// );
1111/// # }
1112/// ```
1113#[macro_export]
1114macro_rules! kbd {
1115    ($($all:tt)*) => {parse_double_tag!(KbdTag, $($all)*) };
1116}
1117
1118/// # Example
1119/// ```
1120/// # #[macro_use] extern crate rtml;
1121/// # fn main() {
1122/// use rtml::*;
1123///
1124/// assert_eq!(
1125///     label!["Name:"].render(),
1126///     "<label>Name:</label>"
1127/// );
1128/// # }
1129/// ```
1130#[macro_export]
1131macro_rules! label {
1132    ($($all:tt)*) => {parse_double_tag!(LabelTag, $($all)*) };
1133}
1134
1135/// # Example
1136/// ```
1137/// # #[macro_use] extern crate rtml;
1138/// # fn main() {
1139/// use rtml::*;
1140///
1141/// assert_eq!(
1142///     fieldset![legend!["This is a fieldset"], "This is the fieldset content"].render(),
1143///     "<fieldset><legend>This is a fieldset</legend>This is the fieldset content</fieldset>"
1144/// );
1145/// # }
1146/// ```
1147#[macro_export]
1148macro_rules! legend {
1149    ($($all:tt)*) => {parse_double_tag!(LegendTag, $($all)*) };
1150}
1151
1152/// # Example
1153/// ```
1154/// # #[macro_use] extern crate rtml;
1155/// # fn main() {
1156/// use rtml::*;
1157///
1158/// assert_eq!(
1159///     li!["Item 1"].render(),
1160///     "<li>Item 1</li>"
1161/// );
1162///
1163/// assert_eq!(
1164///     li![.value=5, "Item 5"].render(),
1165///     "<li value=\"5\">Item 5</li>"
1166/// );
1167/// # }
1168/// ```
1169#[macro_export]
1170macro_rules! li {
1171    ($($all:tt)*) => {parse_double_tag!(LiTag, $($all)*) };
1172}
1173
1174/// # Example
1175/// ```
1176/// # #[macro_use] extern crate rtml;
1177/// # fn main() {
1178/// use rtml::*;
1179///
1180/// assert_eq!(
1181///     link![.rel="stylesheet", .href="example.css"].render(),
1182///     "<link rel=\"stylesheet\" href=\"example.css\">"
1183/// );
1184/// # }
1185/// ```
1186#[macro_export]
1187macro_rules! link {
1188    ($($all:tt)*) => {parse_single_tag!(LinkTag, $($all)*) };
1189}
1190
1191/// # Example
1192/// ```
1193/// # #[macro_use] extern crate rtml;
1194/// # fn main() {
1195/// use rtml::*;
1196///
1197/// assert_eq!(
1198///     main!["This is the main content"].render(),
1199///     "<main>This is the main content</main>"
1200/// );
1201/// # }
1202/// ```
1203#[macro_export]
1204macro_rules! main {
1205    ($($all:tt)*) => {parse_double_tag!(MainTag, $($all)*) };
1206}
1207
1208/// # Example
1209/// ```
1210/// # #[macro_use] extern crate rtml;
1211/// # fn main() {
1212/// use rtml::*;
1213///
1214/// assert_eq!(
1215///     map![.name="example", area![.shape="rect", .coords="0,0,100,100", .href="example.html"]].render(),
1216///     "<map name=\"example\"><area shape=\"rect\" coords=\"0,0,100,100\" href=\"example.html\"></map>"
1217/// );
1218/// # }
1219#[macro_export]
1220macro_rules! map {
1221    ($($all:tt)*) => {parse_double_tag!(MapTag, $($all)*) };
1222}
1223
1224/// # Example
1225/// ```
1226/// # #[macro_use] extern crate rtml;
1227/// # fn main() {
1228/// use rtml::*;
1229///
1230/// assert_eq!(
1231///     mark!["This is marked text"].render(),
1232///     "<mark>This is marked text</mark>"
1233/// );
1234/// # }
1235/// ```
1236#[macro_export]
1237macro_rules! mark {
1238    ($($all:tt)*) => {parse_double_tag!(MarkTag, $($all)*) };
1239}
1240
1241/// # Example
1242/// ```
1243/// # #[macro_use] extern crate rtml;
1244/// # fn main() {
1245/// use rtml::*;
1246///
1247/// assert_eq!(
1248///     menu![li!["Item 1"], li!["Item 2"]].render(),
1249///     "<menu><li>Item 1</li><li>Item 2</li></menu>"
1250/// );
1251/// # }
1252/// ```
1253#[macro_export]
1254macro_rules! menu {
1255    ($($all:tt)*) => {parse_double_tag!(MenuTag, $($all)*) };
1256}
1257
1258/// # Example
1259/// ```
1260/// # #[macro_use] extern crate rtml;
1261/// # fn main() {
1262/// use rtml::*;
1263///
1264/// assert_eq!(
1265///     meta![.name="viewport", .content="width=device-width, initial-scale=1"].render(),
1266///     "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
1267/// );
1268/// # }
1269/// ```
1270#[macro_export]
1271macro_rules! meta {
1272    ($($all:tt)*) => {parse_single_tag!(MetaTag, $($all)*) };
1273}
1274
1275/// # Example
1276/// ```
1277/// # #[macro_use] extern crate rtml;
1278/// # fn main() {
1279/// use rtml::*;
1280///
1281/// assert_eq!(
1282///     meter![.value=2, .min=0, .max=5, "2 out of 5"].render(),
1283///     "<meter value=\"2\" min=\"0\" max=\"5\">2 out of 5</meter>"
1284/// );
1285/// # }
1286/// ```
1287#[macro_export]
1288macro_rules! meter {
1289    ($($all:tt)*) => {parse_double_tag!(MeterTag, $($all)*) };
1290}
1291
1292/// # Example
1293/// ```
1294/// # #[macro_use] extern crate rtml;
1295/// # fn main() {
1296/// use rtml::*;
1297///
1298/// assert_eq!(
1299///     nav![a![.href="home.html", "Home"], a![.href="about.html", "About"], a![.href="contact.html", "Contact"]].render(),
1300///     "<nav><a href=\"home.html\">Home</a><a href=\"about.html\">About</a><a href=\"contact.html\">Contact</a></nav>"
1301/// );
1302/// # }
1303/// ```
1304#[macro_export]
1305macro_rules! nav {
1306    ($($all:tt)*) => {parse_double_tag!(NavTag, $($all)*) };
1307}
1308
1309/// # Example
1310/// ```
1311/// # #[macro_use] extern crate rtml;
1312/// # fn main() {
1313/// use rtml::*;
1314///
1315/// assert_eq!(
1316///     noscript!["JavaScript is disabled."].render(),
1317///     "<noscript>JavaScript is disabled.</noscript>"
1318/// );
1319/// # }
1320/// ```
1321#[macro_export]
1322macro_rules! noscript {
1323    ($($all:tt)*) => {parse_double_tag!(NoscriptTag, $($all)*) };
1324}
1325
1326/// # Example
1327/// ```
1328/// # #[macro_use] extern crate rtml;
1329/// # fn main() {
1330/// use rtml::*;
1331///
1332/// assert_eq!(
1333///     ol![li!["Item 1"], li!["Item 2"]].render(),
1334///     "<ol><li>Item 1</li><li>Item 2</li></ol>"
1335/// );
1336/// # }
1337/// ```
1338#[macro_export]
1339macro_rules! ol {
1340    ($($all:tt)*) => {parse_double_tag!(OlTag, $($all)*) };
1341}
1342
1343/// # Example
1344/// ```
1345/// # #[macro_use] extern crate rtml;
1346/// # fn main() {
1347/// use rtml::*;
1348///
1349/// assert_eq!(
1350///     optgroup![.label="Fruits", option!["Apple"], option!["Banana"], option!["Cherry"]].render(),
1351///     "<optgroup label=\"Fruits\"><option>Apple</option><option>Banana</option><option>Cherry</option></optgroup>"
1352/// );
1353/// # }
1354/// ```
1355#[macro_export]
1356macro_rules! optgroup {
1357    ($($all:tt)*) => {parse_double_tag!(OptgroupTag, $($all)*) };
1358}
1359
1360/// # Example
1361/// ```
1362/// # #[macro_use] extern crate rtml;
1363/// # fn main() {
1364/// use rtml::*;
1365///
1366/// assert_eq!(
1367///     option!["Apple"].render(),
1368///     "<option>Apple</option>"
1369/// );
1370///
1371/// assert_eq!(
1372///     option![.value="a", "Apple"].render(),
1373///     "<option value=\"a\">Apple</option>"
1374/// );
1375/// # }
1376/// ```
1377#[macro_export]
1378macro_rules! option {
1379    ($($all:tt)*) => {parse_double_tag!(OptionTag, $($all)*) };
1380}
1381
1382/// # Example
1383/// ```
1384/// # #[macro_use] extern crate rtml;
1385/// # fn main() {
1386/// use rtml::*;
1387///
1388/// assert_eq!(
1389///     output!["10"].render(),
1390///     "<output>10</output>"
1391/// );
1392/// # }
1393/// ```
1394#[macro_export]
1395macro_rules! output {
1396    ($($all:tt)*) => {parse_double_tag!(OutputTag, $($all)*) };
1397}
1398
1399/// # Example
1400/// ```
1401/// # #[macro_use] extern crate rtml;
1402/// # fn main() {
1403/// use rtml::*;
1404///
1405/// assert_eq!(
1406///     p!["This is a paragraph"].render(),
1407///     "<p>This is a paragraph</p>"
1408/// );
1409/// # }
1410/// ```
1411#[macro_export]
1412macro_rules! p {
1413    ($($all:tt)*) => {parse_double_tag!(PTag, $($all)*) };
1414}
1415
1416#[macro_export]
1417macro_rules! picture {
1418    ($($all:tt)*) => {parse_double_tag!(PictureTag, $($all)*) };
1419}
1420
1421/// # Example
1422/// ```
1423/// # #[macro_use] extern crate rtml;
1424/// # fn main() {
1425/// use rtml::*;
1426///
1427/// assert_eq!(
1428///     pre!["    var x = 5;\n    var y = 10;\n    var z = x + y;\n"].render(),
1429///     "<pre>    var x = 5;\n    var y = 10;\n    var z = x + y;\n</pre>"
1430/// );
1431/// # }
1432/// ```
1433#[macro_export]
1434macro_rules! pre {
1435    ($($all:tt)*) => {parse_double_tag!(PreTag, $($all)*) };
1436}
1437
1438/// # Example
1439/// ```
1440/// # #[macro_use] extern crate rtml;
1441/// # fn main() {
1442/// use rtml::*;
1443///
1444/// assert_eq!(
1445///     progress![.value=50, .max=100, "50%"].render(),
1446///     "<progress value=\"50\" max=\"100\">50%</progress>"
1447/// );
1448/// # }
1449/// ```
1450#[macro_export]
1451macro_rules! progress {
1452    ($($all:tt)*) => {parse_double_tag!(ProgressTag, $($all)*) };
1453}
1454
1455/// # Example
1456/// ```
1457/// # #[macro_use] extern crate rtml;
1458/// # fn main() {
1459/// use rtml::*;
1460///
1461/// assert_eq!(
1462///     q!["This is a short quote."].render(),
1463///     "<q>This is a short quote.</q>"
1464/// );
1465///
1466/// assert_eq!(
1467///     q![.cite="https://www.example.com", "This is a short quote."].render(),
1468///     "<q cite=\"https://www.example.com\">This is a short quote.</q>"
1469/// );
1470/// # }
1471/// ```
1472#[macro_export]
1473macro_rules! q {
1474    ($($all:tt)*) => {parse_double_tag!(QTag, $($all)*) };
1475}
1476
1477/// # Example
1478/// ```
1479/// # #[macro_use] extern crate rtml;
1480/// # fn main() {
1481/// use rtml::*;
1482///
1483/// assert_eq!(
1484///     rp!["」"].render(),
1485///     "<rp>」</rp>"
1486/// );
1487/// # }
1488/// ```
1489#[macro_export]
1490macro_rules! rp {
1491    ($($all:tt)*) => {parse_double_tag!(RpTag, $($all)*) };
1492}
1493
1494/// # Example
1495/// ```
1496/// # #[macro_use] extern crate rtml;
1497/// # fn main() {
1498/// use rtml::*;
1499///
1500/// assert_eq!(
1501///     ruby![ "漢", rt!["ㄏㄢˋ"] ].render(),
1502///     "<ruby>漢<rt>ㄏㄢˋ</rt></ruby>"
1503/// );
1504/// # }
1505/// ```
1506#[macro_export]
1507macro_rules! rt {
1508    ($($all:tt)*) => {parse_double_tag!(RtTag, $($all)*) };
1509}
1510
1511/// # Example
1512/// ```
1513/// # #[macro_use] extern crate rtml;
1514/// # fn main() {
1515/// use rtml::*;
1516///
1517/// assert_eq!(
1518///     ruby![ "漢", rt!["ㄏㄢˋ"] ].render(),
1519///     "<ruby>漢<rt>ㄏㄢˋ</rt></ruby>"
1520/// );
1521/// # }
1522/// ```
1523#[macro_export]
1524macro_rules! ruby {
1525    ($($all:tt)*) => {parse_double_tag!(RubyTag, $($all)*) };
1526}
1527
1528/// # Example
1529/// ```
1530/// # #[macro_use] extern crate rtml;
1531/// # fn main() {
1532/// use rtml::*;
1533///
1534/// assert_eq!(
1535///     s!["This text is no longer accurate"].render(),
1536///     "<s>This text is no longer accurate</s>"
1537/// );
1538/// # }
1539/// ```
1540#[macro_export]
1541macro_rules! s {
1542    ($($all:tt)*) => {parse_double_tag!(STag, $($all)*) };
1543}
1544
1545/// # Example
1546/// ```
1547/// # #[macro_use] extern crate rtml;
1548/// # fn main() {
1549/// use rtml::*;
1550///
1551/// assert_eq!(
1552///     samp!["Sample output from a computer program"].render(),
1553///     "<samp>Sample output from a computer program</samp>"
1554/// );
1555/// # }
1556/// ```
1557#[macro_export]
1558macro_rules! samp {
1559    ($($all:tt)*) => {parse_double_tag!(SampTag, $($all)*) };
1560}
1561
1562/// # Example
1563/// ```
1564/// # #[macro_use] extern crate rtml;
1565/// # fn main() {
1566/// use rtml::*;
1567///
1568/// assert_eq!(
1569///     script![.src="script.js", ._type="text/javascript"].render(),
1570///     "<script src=\"script.js\" type=\"text/javascript\"></script>"
1571/// );
1572/// # }
1573/// ```
1574#[macro_export]
1575macro_rules! script {
1576    ($($all:tt)*) => {parse_double_tag!(ScriptTag, $($all)*) };
1577}
1578
1579/// # Example
1580/// ```
1581/// # #[macro_use] extern crate rtml;
1582/// # fn main() {
1583/// use rtml::*;
1584///
1585/// assert_eq!(
1586///     section![h1!["Section Title"], "Section content."].render(),
1587///     "<section><h1>Section Title</h1>Section content.</section>"
1588/// );
1589/// # }
1590/// ```
1591#[macro_export]
1592macro_rules! section {
1593    ($($all:tt)*) => {parse_double_tag!(SectionTag, $($all)*) };
1594}
1595
1596/// # Example
1597/// ```
1598/// # #[macro_use] extern crate rtml;
1599/// # fn main() {
1600/// use rtml::*;
1601///
1602/// assert_eq!(
1603///     select![
1604///         option!["Option 1"],
1605///         option!["Option 2"],
1606///         option!["Option 3"]
1607///     ].render(),
1608///     "<select><option>Option 1</option><option>Option 2</option><option>Option 3</option></select>"
1609/// );
1610/// # }
1611/// ```
1612#[macro_export]
1613macro_rules! select {
1614    ($($all:tt)*) => {parse_double_tag!(SelectTag, $($all)*) };
1615}
1616
1617/// # Example
1618/// ```
1619/// # #[macro_use] extern crate rtml;
1620/// # fn main() {
1621/// use rtml::*;
1622///
1623/// assert_eq!(
1624///     small!["This text is small"].render(),
1625///     "<small>This text is small</small>"
1626/// );
1627/// # }
1628/// ```
1629#[macro_export]
1630macro_rules! small {
1631    ($($all:tt)*) => {parse_double_tag!(SmallTag, $($all)*) };
1632}
1633
1634/// # Example
1635/// ```
1636/// # #[macro_use] extern crate rtml;
1637/// # fn main() {
1638/// use rtml::*;
1639///
1640/// assert_eq!(
1641///     source![.src="audio.ogg", ._type="audio/ogg"].render(),
1642///     "<source src=\"audio.ogg\" type=\"audio/ogg\">"
1643/// );
1644/// # }
1645/// ```
1646#[macro_export]
1647macro_rules! source {
1648    ($($all:tt)*) => {parse_single_tag!(SourceTag, $($all)*) };
1649}
1650
1651/// # Example
1652/// ```
1653/// # #[macro_use] extern crate rtml;
1654/// # fn main() {
1655/// use rtml::*;
1656///
1657/// assert_eq!(
1658///     span![.class="highlight", "This text is highlighted"].render(),
1659///     "<span class=\"highlight\">This text is highlighted</span>"
1660/// );
1661/// # }
1662/// ```
1663#[macro_export]
1664macro_rules! span {
1665    ($($all:tt)*) => {parse_double_tag!(SpanTag, $($all)*) };
1666}
1667
1668/// # Example
1669/// ```
1670/// # #[macro_use] extern crate rtml;
1671/// # fn main() {
1672/// use rtml::*;
1673///
1674/// assert_eq!(
1675///     strong!["This text is important"].render(),
1676///     "<strong>This text is important</strong>"
1677/// );
1678/// # }
1679/// ```
1680#[macro_export]
1681macro_rules! strong {
1682    ($($all:tt)*) => {parse_double_tag!(StrongTag, $($all)*) };
1683}
1684
1685/// # Example
1686/// ```
1687/// # #[macro_use] extern crate rtml;
1688/// # fn main() {
1689/// use rtml::*;
1690///
1691/// assert_eq!(
1692///     style![._type="text/css", "body {background-color: black;} h1 {color: white;}"].render(),
1693///     "<style type=\"text/css\">body {background-color: black;} h1 {color: white;}</style>"
1694/// );
1695/// # }
1696/// ```
1697#[macro_export]
1698macro_rules! style {
1699    ($($all:tt)*) => {parse_double_tag!(StyleTag, $($all)*) };
1700}
1701
1702/// # Example
1703/// ```
1704/// # #[macro_use] extern crate rtml;
1705/// # fn main() {
1706/// use rtml::*;
1707///
1708/// assert_eq!(
1709///     sub!["This text is a subscript"].render(),
1710///     "<sub>This text is a subscript</sub>"
1711/// );
1712/// # }
1713/// ```
1714#[macro_export]
1715macro_rules! sub {
1716    ($($all:tt)*) => {parse_double_tag!(SubTag, $($all)*) };
1717}
1718
1719/// # Example
1720/// ```
1721/// # #[macro_use] extern crate rtml;
1722/// # fn main() {
1723/// use rtml::*;
1724///
1725/// assert_eq!(
1726///     summary!["This is a summary"].render(),
1727///     "<summary>This is a summary</summary>"
1728/// );
1729/// # }
1730/// ```
1731#[macro_export]
1732macro_rules! summary {
1733    ($($all:tt)*) => {parse_double_tag!(SummaryTag, $($all)*) };
1734}
1735
1736/// # Example
1737/// ```
1738/// # #[macro_use] extern crate rtml;
1739/// # fn main() {
1740/// use rtml::*;
1741///
1742/// assert_eq!(
1743///     sup!["This text is a superscript"].render(),
1744///     "<sup>This text is a superscript</sup>"
1745/// );
1746/// # }
1747/// ```
1748#[macro_export]
1749macro_rules! sup {
1750    ($($all:tt)*) => {parse_double_tag!(SupTag, $($all)*) };
1751}
1752
1753/// # Example
1754/// ```
1755/// # #[macro_use] extern crate rtml;
1756/// # fn main() {
1757/// use rtml::*;
1758///
1759/// assert_eq!(
1760///     table![
1761///         tr![
1762///             td!["Cell 1,1"],
1763///             td!["Cell 1,2"]
1764///         ],
1765///         tr![
1766///             td!["Cell 2,1"],
1767///             td!["Cell 2,2"]
1768///         ]
1769///     ].render(),
1770///     "<table><tr><td>Cell 1,1</td><td>Cell 1,2</td></tr><tr><td>Cell 2,1</td><td>Cell 2,2</td></tr></table>"
1771/// );
1772/// # }
1773/// ```
1774#[macro_export]
1775macro_rules! table {
1776    ($($all:tt)*) => {parse_double_tag!(TableTag, $($all)*) };
1777}
1778
1779/// # Example
1780/// ```
1781/// # #[macro_use] extern crate rtml;
1782/// # fn main() {
1783/// use rtml::*;
1784///
1785/// assert_eq!(
1786///     tbody![
1787///         tr![
1788///             td!["Cell 1,1"],
1789///             td!["Cell 1,2"]
1790///         ],
1791///         tr![
1792///             td!["Cell 2,1"],
1793///             td!["Cell 2,2"]
1794///         ]
1795///     ].render(),
1796///     "<tbody><tr><td>Cell 1,1</td><td>Cell 1,2</td></tr><tr><td>Cell 2,1</td><td>Cell 2,2</td></tr></tbody>"
1797/// );
1798/// # }
1799/// ```
1800#[macro_export]
1801macro_rules! tbody {
1802    ($($all:tt)*) => {parse_double_tag!(TbodyTag, $($all)*) };
1803}
1804
1805/// # Example
1806/// ```
1807/// # #[macro_use] extern crate rtml;
1808/// # fn main() {
1809/// use rtml::*;
1810///
1811/// assert_eq!(
1812///     td!["Cell 1,1"].render(),
1813///     "<td>Cell 1,1</td>"
1814/// );
1815/// # }
1816/// ```
1817#[macro_export]
1818macro_rules! td {
1819    ($($all:tt)*) => {parse_double_tag!(TdTag, $($all)*) };
1820}
1821
1822/// # Example
1823/// ```
1824/// # #[macro_use] extern crate rtml;
1825/// # fn main() {
1826/// use rtml::*;
1827///
1828/// assert_eq!(
1829///     template![
1830///         h1!["Title"],
1831///         p!["Description"]
1832///     ].render(),
1833///     "<template><h1>Title</h1><p>Description</p></template>"
1834/// );
1835/// # }
1836/// ```
1837#[macro_export]
1838macro_rules! template {
1839    ($($all:tt)*) => {parse_double_tag!(TemplateTag, $($all)*) };
1840}
1841
1842/// # Example
1843/// ```
1844/// # #[macro_use] extern crate rtml;
1845/// # fn main() {
1846/// use rtml::*;
1847///
1848/// assert_eq!(
1849///     textarea![.name="message", "Default text"].render(),
1850///     "<textarea name=\"message\">Default text</textarea>"
1851/// );
1852/// # }
1853/// ```
1854#[macro_export]
1855macro_rules! textarea {
1856    ($($all:tt)*) => {parse_double_tag!(TextareaTag, $($all)*) };
1857}
1858
1859/// # Example
1860/// ```
1861/// # #[macro_use] extern crate rtml;
1862/// # fn main() {
1863/// use rtml::*;
1864///
1865/// assert_eq!(
1866///     table![
1867///         tr![
1868///             td!["Cell 1,1"]
1869///         ],
1870///         tfoot![
1871///             tr![
1872///                 td!["Footer 1"]
1873///             ]
1874///         ]
1875///     ].render(),
1876///     "<table><tr><td>Cell 1,1</td></tr><tfoot><tr><td>Footer 1</td></tr></tfoot></table>"
1877/// );
1878/// # }
1879/// ```
1880#[macro_export]
1881macro_rules! tfoot {
1882    ($($all:tt)*) => {parse_double_tag!(TfootTag, $($all)*) };
1883}
1884
1885/// # Example
1886/// ```
1887/// # #[macro_use] extern crate rtml;
1888/// # fn main() {
1889/// use rtml::*;
1890///
1891/// assert_eq!(
1892///     table![
1893///         thead![
1894///             tr![
1895///                 th!["Header 1"]
1896///             ]
1897///         ],
1898///         tbody![
1899///             tr![
1900///                 td!["Cell 1,1"]
1901///             ]
1902///         ],
1903///         tfoot![
1904///             tr![
1905///                 td!["Footer 1"]
1906///             ]
1907///         ]
1908///     ].render(),
1909///     "<table><thead><tr><th>Header 1</th></tr></thead><tbody><tr><td>Cell 1,1</td></tr></tbody><tfoot><tr><td>Footer 1</td></tr></tfoot></table>"
1910/// );
1911/// # }
1912/// ```
1913#[macro_export]
1914macro_rules! th {
1915    ($($all:tt)*) => {parse_double_tag!(ThTag, $($all)*) };
1916}
1917
1918/// # Example
1919/// ```
1920/// # #[macro_use] extern crate rtml;
1921/// # fn main() {
1922/// use rtml::*;
1923///
1924/// assert_eq!(
1925///     table![
1926///         thead![
1927///             tr![
1928///                 th!["Header 1"]
1929///             ]
1930///         ],
1931///         tbody![
1932///             tr![
1933///                 td!["Cell 1,1"]
1934///             ]
1935///         ],
1936///         tfoot![
1937///             tr![
1938///                 td!["Footer 1"]
1939///             ]
1940///         ]
1941///     ].render(),
1942///     "<table><thead><tr><th>Header 1</th></tr></thead><tbody><tr><td>Cell 1,1</td></tr></tbody><tfoot><tr><td>Footer 1</td></tr></tfoot></table>"
1943/// );
1944/// # }
1945/// ```
1946#[macro_export]
1947macro_rules! thead {
1948    ($($all:tt)*) => {parse_double_tag!(TheadTag, $($all)*) };
1949}
1950
1951/// # Example
1952/// ```
1953/// # #[macro_use] extern crate rtml;
1954/// # fn main() {
1955/// use rtml::*;
1956///
1957/// assert_eq!(
1958///     time![
1959///         .datetime="2022-07-05T18:00:00Z",
1960///         "July 5th, 2022 6:00 PM"
1961///     ].render(),
1962///     "<time datetime=\"2022-07-05T18:00:00Z\">July 5th, 2022 6:00 PM</time>"
1963///     );
1964/// # }
1965/// ```
1966#[macro_export]
1967macro_rules! time {
1968    ($($all:tt)*) => {parse_double_tag!(TimeTag, $($all)*) };
1969}
1970
1971/// # Example
1972/// ```
1973/// # #[macro_use] extern crate rtml;
1974/// # fn main() {
1975/// use rtml::*;
1976///
1977/// assert_eq!(
1978///     title![
1979///         "Page Title"
1980///     ].render(),
1981///     "<title>Page Title</title>"
1982///     );
1983/// # }
1984/// ```
1985#[macro_export]
1986macro_rules! title {
1987    ($($all:tt)*) => {parse_double_tag!(TitleTag, $($all)*) };
1988}
1989
1990/// # Example
1991/// ```
1992/// # #[macro_use] extern crate rtml;
1993/// # fn main() {
1994/// use rtml::*;
1995///
1996/// assert_eq!(
1997///     table![
1998///         tr![
1999///             td!["Cell 1,1"]
2000///         ],
2001///         tfoot![
2002///             tr![
2003///                 td!["Footer 1"]
2004///             ]
2005///         ]
2006///     ].render(),
2007///     "<table><tr><td>Cell 1,1</td></tr><tfoot><tr><td>Footer 1</td></tr></tfoot></table>"
2008/// );
2009/// # }
2010/// ```
2011#[macro_export]
2012macro_rules! tr {
2013    ($($all:tt)*) => {parse_double_tag!(TrTag, $($all)*) };
2014}
2015
2016/// # Example
2017/// ```
2018/// # #[macro_use] extern crate rtml;
2019/// # fn main() {
2020/// use rtml::*;
2021///
2022/// assert_eq!(
2023///     track![
2024///         ._kind="captions",
2025///         .src="https://example.com/captions.vtt",
2026///         .srclang="en",
2027///         .label="English Captions"
2028///     ].render(),
2029///     "<track kind=\"captions\" src=\"https://example.com/captions.vtt\" srclang=\"en\" label=\"English Captions\"></track>"
2030/// );
2031/// # }
2032/// ```
2033#[macro_export]
2034macro_rules! track {
2035    ($($all:tt)*) => {parse_double_tag!(TrackTag, $($all)*) };
2036}
2037
2038/// # Example
2039/// ```
2040/// # #[macro_use] extern crate rtml;
2041/// # fn main() {
2042/// use rtml::*;
2043///
2044/// assert_eq!(
2045///     u![
2046///         "Underlined text"
2047///     ].render(),
2048///     "<u>Underlined text</u>"
2049///     );
2050/// # }
2051/// ```
2052#[macro_export]
2053macro_rules! u {
2054    ($($all:tt)*) => {parse_double_tag!(UTag, $($all)*) };
2055}
2056
2057/// # Example
2058/// ```
2059/// # #[macro_use] extern crate rtml;
2060/// # fn main() {
2061/// use rtml::*;
2062///
2063/// assert_eq!(
2064///     ul![
2065///         li!["Item 1"],
2066///         li!["Item 2"],
2067///         li!["Item 3"]
2068///     ].render(),
2069///     "<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>"
2070///     );
2071/// # }
2072/// ```
2073#[macro_export]
2074macro_rules! ul {
2075    ($($all:tt)*) => {parse_double_tag!(UlTag, $($all)*) };
2076}
2077
2078/// # Example
2079/// ```
2080/// # #[macro_use] extern crate rtml;
2081/// # fn main() {
2082/// use rtml::*;
2083///
2084/// assert_eq!(
2085///     var![ "math" ].render(),
2086///     "<var>math</var>"
2087///     );
2088/// # }
2089/// ```
2090#[macro_export]
2091macro_rules! var {
2092    ($($all:tt)*) => {parse_double_tag!(VarTag, $($all)*) };
2093}
2094
2095/// # Example
2096/// ```
2097/// # #[macro_use] extern crate rtml;
2098/// # fn main() {
2099/// use rtml::*;
2100///
2101/// assert_eq!(
2102///     video![
2103///         .src="https://example.com/video.mp4",
2104///         .width="720",
2105///         .height="480",
2106///         .controls="true"
2107///     ].render(),
2108///     "<video src=\"https://example.com/video.mp4\" width=\"720\" height=\"480\" controls=\"true\"></video>"
2109///     );
2110/// # }
2111/// ```
2112#[macro_export]
2113macro_rules! video {
2114    ($($all:tt)*) => {parse_double_tag!(VideoTag, $($all)*) };
2115}
2116
2117/// # Example
2118/// ```
2119/// # #[macro_use] extern crate rtml;
2120/// # fn main() {
2121/// use rtml::*;
2122///
2123/// assert_eq!(
2124///    wbr![].render(),
2125///    "<wbr>"
2126///    );
2127/// # }
2128/// ```
2129#[macro_export]
2130macro_rules! wbr {
2131    ($($all:tt)*) => {parse_single_tag!(WbrTag, $($all)*) };
2132}
2133
2134#[macro_export]
2135macro_rules! parse_double_tag {
2136    () => {
2137        ""
2138    };
2139    (,$inner_left:expr $(,$inner:expr)*) => {
2140        render_fn!("{}{}", $inner_left, parse_double_tag!($(,$inner)*))
2141    };
2142    ($tag:ident,) => {
2143        render_fn!("<{}></{}>", $tag, $tag)
2144    };
2145    ($tag:ident $(,$inner:expr)*) => {
2146        render_fn!("<{}>{}</{}>", $tag, parse_double_tag!($(,$inner)*), $tag)
2147    };
2148    ($tag:ident $(,.$attr:ident = $value:expr)* $(,$inner:expr)*) => {
2149        render_fn!("<{}{}>{}</{}>", $tag, parse_attr!($tag $(,.$attr = $value)*), parse_double_tag!($(,$inner)*), $tag)
2150    };
2151}
2152
2153#[macro_export]
2154macro_rules! parse_single_tag {
2155    ($tag:ident,) => {
2156        render_fn!("<{}>", $tag)
2157    };
2158    ($tag:ident $(,.$attr:ident = $value:expr)*) => {
2159        render_fn!("<{}{}>", $tag, parse_attr!($tag $(,.$attr = $value)*))
2160    };
2161}
2162
2163#[macro_export]
2164macro_rules! parse_attr {
2165    () => { "" };
2166    ($tag:ident) => {
2167        ""
2168    };
2169    ($tag:ident, .$attr:ident = $value:expr $(,.$right_attr:ident$(-$nexts:ident)* = $right_expr:expr)*) => {{
2170        let ident = $attr;
2171        $tag.type_check(&ident);
2172        render_fn!(" {}{}{}", ident, parse_val!($value), parse_attr!($tag $(,.$right_attr = $right_expr)*))
2173    }};
2174}
2175
2176#[macro_export]
2177macro_rules! parse_val {
2178    () => {
2179        ""
2180    };
2181    ($val:expr) => {
2182        render_fn!("=\"{}\"", $val)
2183    };
2184}