lira/
html5.rs

1use crate::core::{CanAddChildren, CanAddText, HasAttributes, Node, Open, Void};
2
3// attributes
4
5/// Global HTML attributes that can be used on almost any element.
6/// Based on: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes
7pub trait HasGlobalAttributes: HasAttributes + Sized {
8    /// Provides a hint for generating a keyboard shortcut for the current element.
9    /// Space-separated list of characters.
10    fn accesskey(self, value: impl AsRef<str>) -> Self {
11        let key = "accesskey";
12        self.attr(key, value)
13    }
14
15    /// Space-separated list of CSS classes.
16    fn class(self, value: impl AsRef<str>) -> Self {
17        let key = "class";
18        self.attr(key, value)
19    }
20
21    /// Unique identifier for the element, must be unique in the document.
22    fn id(self, value: impl AsRef<str>) -> Self {
23        let key = "id";
24        self.attr(key, value)
25    }
26
27    /// Specifies the language of the element's content (BCP 47 tag).
28    fn lang(self, value: impl AsRef<str>) -> Self {
29        let key = "lang";
30        self.attr(key, value)
31    }
32
33    /// Advisory information, usually shown as a tooltip.
34    fn title(self, value: impl AsRef<str>) -> Self {
35        let key = "title";
36        self.attr(key, value)
37    }
38
39    /// Makes the element draggable via the Drag and Drop API.
40    fn draggable(self) -> Self {
41        self.flag("draggable")
42    }
43
44    /// Enables or disables spell checking on the element.
45    fn spellcheck(self) -> Self {
46        self.flag("spellcheck")
47    }
48
49    /// Automatically focus this element when the page or dialog loads.
50    fn autofocus(self) -> Self {
51        self.flag("autofocus")
52    }
53
54    /// Allows editing of the element's content by the user.
55    fn contenteditable(self) -> Self {
56        self.flag("contenteditable")
57    }
58
59    /// Provides an explicit tab order for the element.
60    fn tabindex(self, value: i32) -> Self {
61        self.attr("tabindex", value.to_string())
62    }
63
64    /// Hides the element from the page.
65    fn hidden(self) -> Self {
66        self.flag("hidden")
67    }
68
69    /// Sets automatic capitalization behavior for user input.
70    fn autocapitalize(self, value: impl AsRef<str>) -> Self {
71        self.attr("autocapitalize", value)
72    }
73
74    /// Forms a class of attributes, called custom data attributes, that allow proprietary information to be exchanged
75    /// between the HTML and its DOM representation that may be used by scripts. All such custom data are available
76    /// via the HTMLElement interface of the element the attribute is set on. The HTMLElement.dataset property gives
77    /// access to them.
78    fn data(self, key: &'static str, value: impl AsRef<str>) -> Self
79    where
80        Self: Sized + HasAttributes,
81    {
82        self.attr(format!("data-{}", key).as_str(), value)
83    }
84}
85
86impl<Tag> HasGlobalAttributes for Node<Tag, Open> {}
87impl<Tag> HasGlobalAttributes for Node<Tag, Void> {}
88
89pub trait HasHref: HasAttributes + Sized {
90    /// The URL of the linked resource (absolute or relative).
91    fn href(self, value: impl AsRef<str>) -> Self {
92        self.attr("href", value)
93    }
94}
95
96#[derive(Clone, Copy, PartialEq, Eq)]
97pub enum Rel {
98    /// Alternate representations of the current document.
99    Alternate,
100
101    /// Author of the current document or article.
102    Author,
103
104    /// Permalink for the nearest ancestor section.
105    Bookmark,
106
107    /// Preferred URL for the current document.
108    Canonical,
109
110    /// Tells the browser to preemptively perform DNS resolution for the target resource's origin.
111    DnsPrefetch,
112
113    /// The referenced document is not part of the same site as the current document.
114    External,
115
116    /// Link to context-sensitive help.
117    Help,
118
119    /// An icon representing the current document.
120    Icon,
121
122    /// Indicates that the main content of the current document is covered by the copyright license described l
123    /// by the referenced document.
124    License,
125
126    /// Web app manifest.
127    Manifest,
128
129    /// Indicates that the current document is a part of a series and that the next document in the series is the
130    /// referenced document.
131    Next,
132
133    /// Indicates that the current document's original author or publisher does not endorse the referenced document.
134    NoFollow,
135
136    /// Creates a top-level browsing context that is not an auxiliary browsing context if the hyperlink would create
137    /// either of those, to begin with (i.e., has an appropriate target attribute value).
138    NoOpener,
139
140    /// No Referer header will be included. Additionally, has the same effect as noopener.
141    NoReferrer,
142
143    /// Creates an auxiliary browsing context if the hyperlink would otherwise create a top-level browsing context
144    /// that is not an auxiliary browsing context (i.e., has "_blank" as target attribute value).
145    Opener,
146
147    /// Specifies that the user agent should preemptively fetch and cache the target resource as it is likely to
148    /// be required for a followup navigation.
149    Prefetch,
150
151    /// Specifies that the user agent must preemptively fetch and cache the target resource for current navigation
152    /// according to the potential destination given by the as attribute (and the priority associated with the
153    /// corresponding destination).
154    Preload,
155
156    /// Indicates that the current document is a part of a series and that the previous document in the series
157    /// is the referenced document.
158    Prev,
159
160    /// Gives a link to a resource that can be used to search through the current document and its related pages.
161    Search,
162
163    /// Imports a style sheet.
164    Stylesheet,
165
166    /// Gives a tag (identified by the given address) that applies to the current document.
167    Tag,
168}
169
170pub trait HasRel: HasAttributes + Sized {
171    fn rel(self, rel: Rel) -> Self {
172        let value = match rel {
173            Rel::Alternate => "alternate",
174            Rel::Author => "author",
175            Rel::Bookmark => "bookmark",
176            Rel::Canonical => "canonical",
177            Rel::DnsPrefetch => "dns-prefetch",
178            Rel::External => "external",
179            Rel::Help => "help",
180            Rel::Icon => "icon",
181            Rel::License => "license",
182            Rel::Manifest => "manifest",
183            Rel::Next => "next",
184            Rel::NoFollow => "nofollow",
185            Rel::NoOpener => "noopener",
186            Rel::NoReferrer => "noreferrer",
187            Rel::Opener => "opener",
188            Rel::Prefetch => "prefetch",
189            Rel::Preload => "preload",
190            Rel::Prev => "prev",
191            Rel::Search => "search",
192            Rel::Stylesheet => "stylesheet",
193            Rel::Tag => "tag",
194        };
195        self.attr("rel", value)
196    }
197}
198
199pub trait HasSrc: HasAttributes + Sized {
200    /// URL of the embeddable content (image, script, iframe, etc.).
201    fn src(self, value: impl AsRef<str>) -> Self {
202        self.attr("src", value)
203    }
204}
205
206pub enum InputType {
207    Text,
208    Password,
209    Checkbox,
210    Radio,
211    File,
212    Submit,
213    Reset,
214    Button,
215    Hidden,
216    Email,
217    Number,
218    Date,
219}
220
221pub trait HasInputType: HasAttributes + Sized {
222    fn input_type(self, value: impl Into<InputType>) -> Self {
223        let value = match value.into() {
224            InputType::Text => "text",
225            InputType::Password => "password",
226            InputType::Checkbox => "checkbox",
227            InputType::Radio => "radio",
228            InputType::File => "file",
229            InputType::Submit => "submit",
230            InputType::Reset => "reset",
231            InputType::Button => "button",
232            InputType::Hidden => "hidden",
233            InputType::Email => "email",
234            InputType::Number => "number",
235            InputType::Date => "date",
236        };
237        self.attr("type", value)
238    }
239}
240
241pub enum Target {
242    Self_,
243    Blank,
244    Parent,
245    Top,
246}
247
248pub trait HasTarget: HasAttributes + Sized {
249    fn target(self, target: Target) -> Self {
250        let value = match target {
251            Target::Self_ => "_self",
252            Target::Blank => "_blank",
253            Target::Parent => "_parent",
254            Target::Top => "_top",
255        };
256        self.attr("target", value)
257    }
258}
259
260pub enum FormMethod {
261    Get,
262    Post,
263    Dialog,
264}
265
266// HTML elements
267
268// <html> element
269
270// <html>
271pub struct Html;
272
273/// Root element of an HTML document. All other elements must be descendants of this.
274pub fn html() -> Node<Html, Open> {
275    // since this will be used for an entire page, make it big
276    let mut buf = Vec::with_capacity(2048);
277    buf.extend_from_slice(b"<!DOCTYPE html>");
278    Node::with_buffer("html", buf)
279}
280
281impl CanAddChildren for Html {}
282
283// <head>
284pub struct Head;
285
286/// Contains metadata about the document (title, links, meta, etc.).
287pub fn head() -> Node<Head, Open> {
288    Node::new("head")
289}
290
291impl CanAddChildren for Head {}
292
293// <link> — void element
294pub struct Link;
295
296/// Specifies relationships between the current document and external resources (e.g. CSS, icons).
297pub fn link() -> Node<Link, Void> {
298    Node::new_self_closing("link")
299}
300
301impl HasHref for Node<Link, Void> {}
302impl HasRel for Node<Link, Void> {}
303
304impl Node<Link, Void> {
305    /// Specifies a Subresource Integrity value that allows browsers to verify what they fetch.
306    pub fn integrity(self, value: impl AsRef<str>) -> Self {
307        self.attr("integrity", value)
308    }
309}
310
311// <meta> — void element
312pub struct Meta;
313
314/// Represents metadata not covered by other elements.
315pub fn meta() -> Node<Meta, Void> {
316    Node::new_self_closing("meta")
317}
318
319impl Node<Meta, Void> {
320    pub fn charset(self, value: impl AsRef<str>) -> Self {
321        self.attr("charset", value)
322    }
323    pub fn content(self, value: impl AsRef<str>) -> Self {
324        self.attr("content", value)
325    }
326    pub fn http_equiv(self, value: impl AsRef<str>) -> Self {
327        self.attr("http-equiv", value)
328    }
329    pub fn media(self, value: impl AsRef<str>) -> Self {
330        self.attr("media", value)
331    }
332    pub fn name(self, value: impl AsRef<str>) -> Self {
333        self.attr("name", value)
334    }
335}
336
337// <style>
338pub struct Style;
339
340/// Contains CSS styling rules for the document.
341pub fn style() -> Node<Style, Open> {
342    Node::new("style")
343}
344
345impl CanAddText for Style {}
346impl CanAddChildren for Style {}
347
348// <title>
349pub struct Title;
350
351/// Defines the document title shown in browser tab/title bar.
352pub fn title() -> Node<Title, Open> {
353    Node::new("title")
354}
355
356impl CanAddText for Title {}
357
358// <body>
359pub struct Body;
360
361/// Represents the main content of the HTML document.
362pub fn body() -> Node<Body, Open> {
363    Node::new("body")
364}
365
366impl CanAddChildren for Body {}
367
368// <div>
369pub struct Div;
370
371/// Generic block-level container for grouping content.
372pub fn div() -> Node<Div, Open> {
373    Node::new("div")
374}
375
376impl CanAddChildren for Div {}
377impl CanAddText for Div {}
378
379// <span>
380pub struct Span;
381
382/// Generic inline container for phrasing content.
383pub fn span() -> Node<Span, Open> {
384    Node::new("span")
385}
386
387impl CanAddChildren for Span {}
388impl CanAddText for Span {}
389
390// <h1>
391pub struct H1;
392
393pub fn h1() -> Node<H1, Open> {
394    Node::new("h1")
395}
396
397impl CanAddChildren for H1 {}
398impl CanAddText for H1 {}
399
400// <h2>
401pub struct H2;
402
403pub fn h2() -> Node<H2, Open> {
404    Node::new("h2")
405}
406
407impl CanAddChildren for H2 {}
408impl CanAddText for H2 {}
409
410// <h3>
411pub struct H3;
412
413pub fn h3() -> Node<H3, Open> {
414    Node::new("h3")
415}
416
417impl CanAddChildren for H3 {}
418impl CanAddText for H3 {}
419
420// <h4>
421pub struct H4;
422
423pub fn h4() -> Node<H4, Open> {
424    Node::new("h4")
425}
426
427impl CanAddChildren for H4 {}
428impl CanAddText for H4 {}
429
430// <h5>
431pub struct H5;
432
433pub fn h5() -> Node<H5, Open> {
434    Node::new("h5")
435}
436
437impl CanAddChildren for H5 {}
438impl CanAddText for H5 {}
439
440// <h6>
441pub struct H6;
442
443pub fn h6() -> Node<H6, Open> {
444    Node::new("h6")
445}
446
447impl CanAddChildren for H6 {}
448impl CanAddText for H6 {}
449
450// <p>
451pub struct Paragraph;
452
453/// Represents a paragraph of text.
454pub fn p() -> Node<Paragraph, Open> {
455    Node::new("p")
456}
457
458impl CanAddChildren for Paragraph {}
459impl CanAddText for Paragraph {}
460
461// <img>
462pub struct Img;
463
464/// Embeds an image into the document.
465pub fn img() -> Node<Img, Void> {
466    Node::new_self_closing("img")
467}
468
469impl HasSrc for Node<Img, Void> {}
470
471impl Node<Img, Void> {
472    /// Text description of the image, shown if image fails to load.
473    pub fn alt(self, value: impl AsRef<str>) -> Self {
474        self.attr("alt", value)
475    }
476
477    /// Intrinsic width of the image in pixels.
478    pub fn width(self, value: i32) -> Self {
479        self.attr("width", value.to_string())
480    }
481
482    /// Intrinsic height of the image in pixels.
483    pub fn height(self, value: i32) -> Self {
484        self.attr("height", value.to_string())
485    }
486}
487
488// <form>
489pub struct Form;
490
491/// Represents a form, used to collect user input.
492pub fn form() -> Node<Form, Open> {
493    Node::new("form")
494}
495
496impl CanAddChildren for Form {}
497
498impl Node<Form, Open> {
499    /// URL to which the form data is submitted.
500    pub fn action(self, value: impl AsRef<str>) -> Self {
501        self.attr("action", value)
502    }
503
504    /// HTTP method to submit the form (Get, Post, Dialog).
505    pub fn method(self, method: FormMethod) -> Self {
506        self.attr(
507            "method",
508            match method {
509                FormMethod::Get => "GET",
510                FormMethod::Post => "POST",
511                FormMethod::Dialog => "dialog",
512            },
513        )
514    }
515
516    /// Name of the character encodings the server accepts.
517    pub fn accept_charset(self, value: impl AsRef<str>) -> Self {
518        self.attr("accept-charset", value)
519    }
520
521    /// Toggles browser autocomplete for the form fields.
522    pub fn autocomplete(self, value: bool) -> Self {
523        self.attr("autocomplete", if value { "on" } else { "off" })
524    }
525}
526
527// <input>
528pub struct Input;
529
530/// Represents an input field where users can enter data.
531pub fn input() -> Node<Input, Void> {
532    Node::new_self_closing("input")
533}
534
535impl HasInputType for Node<Input, Void> {}
536
537impl Node<Input, Void> {
538    /// Name of the input control.
539    pub fn name(self, value: impl AsRef<str>) -> Self {
540        self.attr("name", value)
541    }
542
543    /// Default value of the input.
544    pub fn value(self, value: impl AsRef<str>) -> Self {
545        self.attr("value", value)
546    }
547
548    /// Indicates that the input should be checked by default (for checkboxes/radios).
549    pub fn checked(self) -> Self {
550        self.flag("checked")
551    }
552
553    /// Specifies accepted file types for file input.
554    pub fn accept(self, value: impl AsRef<str>) -> Self {
555        self.attr("accept", value)
556    }
557
558    /// Enables capturing a new file via camera or microphone.
559    pub fn capture(self) -> Self {
560        self.flag("capture")
561    }
562
563    /// Enables browser autocomplete for the input.
564    pub fn autocomplete(self, value: bool) -> Self {
565        self.attr("autocomplete", if value { "on" } else { "off" })
566    }
567}
568
569// <button>
570pub struct Button;
571
572/// Represents a clickable button.
573pub fn button() -> Node<Button, Open> {
574    Node::new("button")
575}
576
577impl CanAddChildren for Button {}
578impl CanAddText for Button {}
579
580impl Node<Button, Open> {
581    /// Type of button: "button", "submit", or "reset".
582    pub fn type_(self, value: impl AsRef<str>) -> Self {
583        self.attr("type", value)
584    }
585
586    /// Name of the button.
587    pub fn name(self, value: impl AsRef<str>) -> Self {
588        self.attr("name", value)
589    }
590
591    /// Default value of the button.
592    pub fn value(self, value: impl AsRef<str>) -> Self {
593        self.attr("value", value)
594    }
595
596    /// Disables the button.
597    pub fn disabled(self) -> Self {
598        self.flag("disabled")
599    }
600}
601
602// <textarea>
603pub struct Textarea;
604
605/// Represents a multi-line text input.
606pub fn textarea() -> Node<Textarea, Open> {
607    Node::new("textarea")
608}
609
610impl CanAddText for Textarea {}
611
612impl Node<Textarea, Open> {
613    /// Name of the textarea.
614    pub fn name(self, value: impl AsRef<str>) -> Self {
615        self.attr("name", value)
616    }
617
618    /// Default value inside the textarea.
619    pub fn value(self, value: impl AsRef<str>) -> Self {
620        self.attr("value", value)
621    }
622
623    /// Number of visible rows.
624    pub fn rows(self, value: i32) -> Self {
625        self.attr("rows", value.to_string())
626    }
627
628    /// Number of visible columns.
629    pub fn cols(self, value: i32) -> Self {
630        self.attr("cols", value.to_string())
631    }
632
633    /// Disables the textarea.
634    pub fn disabled(self) -> Self {
635        self.flag("disabled")
636    }
637
638    /// Enables browser autocomplete.
639    pub fn autocomplete(self, value: bool) -> Self {
640        self.attr("autocomplete", if value { "on" } else { "off" })
641    }
642}
643
644// <select>
645pub struct Select;
646
647/// Represents a drop-down list of options.
648pub fn select() -> Node<Select, Open> {
649    Node::new("select")
650}
651
652impl CanAddChildren for Select {}
653
654impl Node<Select, Open> {
655    /// Name of the select element.
656    pub fn name(self, value: impl AsRef<str>) -> Self {
657        self.attr("name", value)
658    }
659
660    /// Disables the select element.
661    pub fn disabled(self) -> Self {
662        self.flag("disabled")
663    }
664
665    /// Enables multiple selection.
666    pub fn multiple(self) -> Self {
667        self.flag("multiple")
668    }
669
670    /// Enables browser autocomplete.
671    pub fn autocomplete(self, value: bool) -> Self {
672        self.attr("autocomplete", if value { "on" } else { "off" })
673    }
674}
675
676// <option>
677pub struct OptionElement;
678
679/// Represents a single option inside a <select>.
680pub fn option() -> Node<OptionElement, Open> {
681    Node::new("option")
682}
683
684impl CanAddText for OptionElement {}
685
686impl Node<OptionElement, Open> {
687    /// Value of the option when submitted.
688    pub fn value(self, value: impl AsRef<str>) -> Self {
689        self.attr("value", value)
690    }
691
692    /// Marks the option as selected.
693    pub fn selected(self) -> Self {
694        self.flag("selected")
695    }
696
697    /// Disables the option.
698    pub fn disabled(self) -> Self {
699        self.flag("disabled")
700    }
701}
702
703// <header>
704pub struct Header;
705
706/// Represents introductory content or a set of navigational links.
707pub fn header() -> Node<Header, Open> {
708    Node::new("header")
709}
710
711impl CanAddChildren for Header {}
712impl CanAddText for Header {}
713
714// <footer>
715pub struct Footer;
716
717/// Represents footer content for its nearest sectioning content.
718pub fn footer() -> Node<Footer, Open> {
719    Node::new("footer")
720}
721
722impl CanAddChildren for Footer {}
723impl CanAddText for Footer {}
724
725// <nav>
726pub struct Nav;
727
728/// Represents a section of navigation links.
729pub fn nav() -> Node<Nav, Open> {
730    Node::new("nav")
731}
732
733impl CanAddChildren for Nav {}
734impl CanAddText for Nav {}
735
736// <section>
737pub struct Section;
738
739/// Represents a generic section of content.
740pub fn section() -> Node<Section, Open> {
741    Node::new("section")
742}
743
744impl CanAddChildren for Section {}
745impl CanAddText for Section {}
746
747// <article>
748pub struct Article;
749
750/// Represents a self-contained composition, such as a blog post or news article.
751pub fn article() -> Node<Article, Open> {
752    Node::new("article")
753}
754
755impl CanAddChildren for Article {}
756impl CanAddText for Article {}
757
758// <aside>
759pub struct Aside;
760
761/// Represents content indirectly related to the main content (sidebar).
762pub fn aside() -> Node<Aside, Open> {
763    Node::new("aside")
764}
765
766impl CanAddChildren for Aside {}
767impl CanAddText for Aside {}
768
769// <main>
770pub struct Main;
771
772/// Represents the dominant content of the <body> of a document.
773pub fn main() -> Node<Main, Open> {
774    Node::new("main")
775}
776
777impl CanAddChildren for Main {}
778impl CanAddText for Main {}
779
780// <code>
781pub struct Code;
782
783/// Represents a fragment of computer code.
784pub fn code() -> Node<Code, Open> {
785    Node::new("code")
786}
787
788impl CanAddChildren for Code {}
789impl CanAddText for Code {}
790
791// <pre>
792pub struct Pre;
793
794/// Represents preformatted text.
795pub fn pre() -> Node<Pre, Open> {
796    Node::new("pre")
797}
798
799impl CanAddChildren for Pre {}
800impl CanAddText for Pre {}
801
802// <a>
803pub struct A;
804
805/// Together with its href attribute, creates a hyperlink to web pages, files, email addresses, locations within the
806/// current page, or anything else a URL can address.
807pub fn a() -> Node<A, Open> {
808    Node::new("a")
809}
810
811impl CanAddChildren for A {}
812impl CanAddText for A {}
813impl HasHref for Node<A, Open> {}
814
815impl Node<A, Open> {
816    /// Indicates that the hyperlink is to be used for downloading a resource.
817    pub fn download(self) -> Self {
818        self.flag("download")
819    }
820}
821
822// <b>
823pub struct B;
824
825/// Represents text with bold importance.
826pub fn b() -> Node<B, Open> {
827    Node::new("b")
828}
829
830impl CanAddChildren for B {}
831impl CanAddText for B {}
832
833// <i>
834pub struct I;
835
836/// Represents text in italics, usually for emphasis or stylistic purposes.
837pub fn i() -> Node<I, Open> {
838    Node::new("i")
839}
840
841impl CanAddChildren for I {}
842impl CanAddText for I {}
843
844// <u>
845pub struct U;
846
847/// Represents text that should be stylistically underlined.
848pub fn u() -> Node<U, Open> {
849    Node::new("u")
850}
851
852impl CanAddChildren for U {}
853impl CanAddText for U {}
854
855// <strong>
856pub struct Strong;
857
858/// Represents text with strong importance.
859pub fn strong() -> Node<Strong, Open> {
860    Node::new("strong")
861}
862
863impl CanAddChildren for Strong {}
864impl CanAddText for Strong {}
865
866// <small>
867pub struct Small;
868
869/// Represents smaller print text.
870pub fn small() -> Node<Small, Open> {
871    Node::new("small")
872}
873
874impl CanAddChildren for Small {}
875impl CanAddText for Small {}
876
877// <label>
878pub struct Label;
879
880/// Represents a label for a form control.
881pub fn label() -> Node<Label, Open> {
882    Node::new("label")
883}
884
885impl CanAddChildren for Label {}
886impl CanAddText for Label {}
887
888impl Node<Label, Open> {
889    /// Associates the label with a form control by its ID.
890    pub fn for_(self, value: impl AsRef<str>) -> Self {
891        self.attr("for", value)
892    }
893}
894
895// <details>
896pub struct Details;
897
898/// Represents a disclosure widget that users can open or close.
899pub fn details() -> Node<Details, Open> {
900    Node::new("details")
901}
902
903impl CanAddChildren for Details {}
904impl CanAddText for Details {}
905
906impl Node<Details, Open> {
907    /// Indicates whether the details should be open by default.
908    pub fn open(self) -> Self {
909        self.flag("open")
910    }
911}
912
913// <summary>
914pub struct Summary;
915
916/// Represents a summary, visible in a <details> element.
917pub fn summary() -> Node<Summary, Open> {
918    Node::new("summary")
919}
920
921impl CanAddChildren for Summary {}
922impl CanAddText for Summary {}
923
924// <dialog>
925pub struct Dialog;
926
927/// Represents a dialog box or interactive window.
928pub fn dialog() -> Node<Dialog, Open> {
929    Node::new("dialog")
930}
931
932impl CanAddChildren for Dialog {}
933impl CanAddText for Dialog {}
934
935impl Node<Dialog, Open> {
936    /// Indicates that the dialog is open.
937    pub fn open(self) -> Self {
938        self.flag("open")
939    }
940}
941
942// <hr>
943pub struct Hr;
944
945/// Represents a thematic break (horizontal rule).
946pub fn hr() -> Node<Hr, Void> {
947    Node::new_self_closing("hr")
948}
949
950// <base>
951pub struct Base;
952
953/// Specifies the base URL and target for relative URLs.
954pub fn base() -> Node<Base, Void> {
955    Node::new_self_closing("base")
956}
957
958impl HasHref for Node<Base, Void> {}
959impl HasTarget for Node<Base, Void> {}
960
961// <script>
962pub struct Script;
963
964pub fn script() -> Node<Script, Open> {
965    Node::new("script")
966}
967
968impl CanAddText for Script {}
969impl HasSrc for Node<Script, Open> {}
970
971impl Node<Script, Open> {
972    /// Executes the script asynchronously.
973    pub fn async_(self) -> Self {
974        self.flag("async")
975    }
976
977    /// Indicates that the script should be executed after the page has been parsed.
978    pub fn defer(self) -> Self {
979        self.flag("defer")
980    }
981
982    /// Specifies a Subresource Integrity value that allows browsers to verify what they fetch.
983    pub fn integrity(self, value: impl AsRef<str>) -> Self {
984        self.attr("integrity", value)
985    }
986
987    /// Type of script: "importmap", "module", ...
988    pub fn type_(self, value: impl AsRef<str>) -> Self {
989        self.attr("type", value)
990    }
991}
992
993// <ul>
994pub struct Ul;
995
996pub fn ul() -> Node<Ul, Open> {
997    Node::new("ul")
998}
999
1000impl CanAddChildren for Ul {}
1001
1002// <ol>
1003pub struct Ol;
1004
1005pub fn ol() -> Node<Ol, Open> {
1006    Node::new("ol")
1007}
1008
1009impl CanAddChildren for Ol {}
1010
1011// <li>
1012pub struct Li;
1013
1014pub fn li() -> Node<Li, Open> {
1015    Node::new("li")
1016}
1017
1018impl CanAddChildren for Li {}
1019impl CanAddText for Li {}
1020
1021// <table>
1022pub struct Table;
1023
1024pub fn table() -> Node<Table, Open> {
1025    Node::new("table")
1026}
1027
1028impl CanAddChildren for Table {}
1029
1030// <thead>
1031pub struct THead;
1032
1033pub fn thead() -> Node<THead, Open> {
1034    Node::new("thead")
1035}
1036
1037impl CanAddChildren for THead {}
1038
1039// <tbody>
1040pub struct TBody;
1041
1042pub fn tbody() -> Node<TBody, Open> {
1043    Node::new("tbody")
1044}
1045
1046impl CanAddChildren for TBody {}
1047
1048// <tfoot>
1049pub struct TFoot;
1050
1051pub fn tfoot() -> Node<TFoot, Open> {
1052    Node::new("tfoot")
1053}
1054
1055impl CanAddChildren for TFoot {}
1056
1057// <tr>
1058pub struct Tr;
1059
1060pub fn tr() -> Node<Tr, Open> {
1061    Node::new("tr")
1062}
1063
1064impl CanAddChildren for Tr {}
1065
1066// <th>
1067pub struct Th;
1068
1069pub fn th() -> Node<Th, Open> {
1070    Node::new("th")
1071}
1072
1073impl CanAddChildren for Th {}
1074impl CanAddText for Th {}
1075
1076// <td>
1077pub struct Td;
1078
1079pub fn td() -> Node<Td, Open> {
1080    Node::new("td")
1081}
1082
1083impl CanAddChildren for Td {}
1084impl CanAddText for Td {}