#![allow(non_upper_case_globals)]
use dioxus_core::prelude::IntoAttributeValue;
use dioxus_core::HasAttributes;
use dioxus_html_internal_macro::impl_extension_attributes;
#[cfg(feature = "hot-reload-context")]
use dioxus_rsx::HotReloadingContext;
#[cfg(feature = "hot-reload-context")]
use crate::{map_global_attributes, map_svg_attributes};
pub type AttributeDescription = (&'static str, Option<&'static str>, bool);
macro_rules! impl_attribute {
(
$element:ident {
$(#[$attr_method:meta])*
$fil:ident: $vil:ident (DEFAULT),
}
) => {
$(#[$attr_method])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
#[doc = concat!("let ", stringify!($fil), " = \"value\";")]
///
/// rsx! {
/// // Attributes need to be under the element they modify
#[doc = concat!(" ", stringify!($element), " {")]
/// // Attributes are followed by a colon and then the value of the attribute
#[doc = concat!(" ", stringify!($fil), ": \"value\"")]
/// }
#[doc = concat!(" ", stringify!($element), " {")]
/// // Or you can use the shorthand syntax if you have a variable in scope that has the same name as the attribute
#[doc = concat!(" ", stringify!($fil), ",")]
/// }
/// };
/// ```
pub const $fil: AttributeDescription = (stringify!($fil), None, false);
};
(
$element:ident {
$(#[$attr_method:meta])*
$fil:ident: $vil:ident ($name:literal),
}
) => {
$(#[$attr_method])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
#[doc = concat!("let ", stringify!($fil), " = \"value\";")]
///
/// rsx! {
/// // Attributes need to be under the element they modify
#[doc = concat!(" ", stringify!($element), " {")]
/// // Attributes are followed by a colon and then the value of the attribute
#[doc = concat!(" ", stringify!($fil), ": \"value\"")]
/// }
#[doc = concat!(" ", stringify!($element), " {")]
/// // Or you can use the shorthand syntax if you have a variable in scope that has the same name as the attribute
#[doc = concat!(" ", stringify!($fil), ",")]
/// }
/// };
/// ```
pub const $fil: AttributeDescription = ($name, None, false);
};
(
$element:ident {
$(#[$attr_method:meta])*
$fil:ident: $vil:ident (volatile),
}
) => {
$(#[$attr_method])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
#[doc = concat!("let ", stringify!($fil), " = \"value\";")]
///
/// rsx! {
/// // Attributes need to be under the element they modify
#[doc = concat!(" ", stringify!($element), " {")]
/// // Attributes are followed by a colon and then the value of the attribute
#[doc = concat!(" ", stringify!($fil), ": \"value\"")]
/// }
#[doc = concat!(" ", stringify!($element), " {")]
/// // Or you can use the shorthand syntax if you have a variable in scope that has the same name as the attribute
#[doc = concat!(" ", stringify!($fil), ",")]
/// }
/// };
/// ```
pub const $fil: AttributeDescription = (stringify!($fil), None, true);
};
(
$element:ident {
$(#[$attr_method:meta])*
$fil:ident: $vil:ident (in $ns:literal),
}
) => {
$(#[$attr_method])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
#[doc = concat!("let ", stringify!($fil), " = \"value\";")]
///
/// rsx! {
/// // Attributes need to be under the element they modify
#[doc = concat!(" ", stringify!($element), " {")]
/// // Attributes are followed by a colon and then the value of the attribute
#[doc = concat!(" ", stringify!($fil), ": \"value\"")]
/// }
#[doc = concat!(" ", stringify!($element), " {")]
/// // Or you can use the shorthand syntax if you have a variable in scope that has the same name as the attribute
#[doc = concat!(" ", stringify!($fil), ",")]
/// }
/// };
/// ```
pub const $fil: AttributeDescription = (stringify!($fil), Some($ns), false)
};
(
$element:ident {
$(#[$attr_method:meta])*
$fil:ident: $vil:ident (in $ns:literal : volatile),
}
) => {
$(#[$attr_method])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
#[doc = concat!("let ", stringify!($fil), " = \"value\";")]
///
/// rsx! {
/// // Attributes need to be under the element they modify
#[doc = concat!(" ", stringify!($element), " {")]
/// // Attributes are followed by a colon and then the value of the attribute
#[doc = concat!(" ", stringify!($fil), ": \"value\"")]
/// }
#[doc = concat!(" ", stringify!($element), " {")]
/// // Or you can use the shorthand syntax if you have a variable in scope that has the same name as the attribute
#[doc = concat!(" ", stringify!($fil), ",")]
/// }
/// };
/// ```
pub const $fil: AttributeDescription = (stringify!($fil), Some($ns), true)
};
}
#[cfg(feature = "hot-reload-context")]
macro_rules! impl_attribute_match {
(
$attr:ident $fil:ident: $vil:ident (DEFAULT),
) => {
if $attr == stringify!($fil) {
return Some((stringify!($fil), None));
}
};
(
$attr:ident $fil:ident: $vil:ident (volatile),
) => {
if $attr == stringify!($fil) {
return Some((stringify!($fil), None));
}
};
(
$attr:ident $fil:ident: $vil:ident ($name:literal),
) => {
if $attr == stringify!($fil) {
return Some(($name, None));
}
};
(
$attr:ident $fil:ident: $vil:ident (in $ns:literal),
) => {
if $attr == stringify!($fil) {
return Some((stringify!(fil), Some($ns)));
}
};
}
#[cfg(feature = "html-to-rsx")]
macro_rules! impl_html_to_rsx_attribute_match {
(
$attr:ident $fil:ident $name:literal
) => {
if $attr == $name {
return Some(stringify!($fil));
}
};
(
$attr:ident $fil:ident $_:tt
) => {
if $attr == stringify!($fil) {
return Some(stringify!($fil));
}
};
}
macro_rules! impl_element {
(
$(#[$attr:meta])*
$name:ident None {
$(
$(#[$attr_method:meta])*
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
#[allow(non_camel_case_types)]
$(#[$attr])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
/// # let attributes = vec![];
/// # fn ChildComponent() -> Element { unimplemented!() }
/// # let raw_expression: Element = rsx! {};
/// rsx! {
/// // Elements are followed by braces that surround any attributes and children for that element
#[doc = concat!(" ", stringify!($name), " {")]
/// // Add any attributes first
/// class: "my-class",
/// "custom-attribute-name": "value",
/// // Then add any attributes you are spreading into this element
/// ..attributes,
/// // Then add any children elements, components, text nodes, or raw expressions
/// div {}
/// ChildComponent {}
/// "child text"
/// {raw_expression}
/// }
/// };
/// ```
pub mod $name {
#[allow(unused)]
use super::*;
pub use crate::attribute_groups::global_attributes::*;
pub const TAG_NAME: &'static str = stringify!($name);
pub const NAME_SPACE: Option<&'static str> = None;
$(
impl_attribute!(
$name {
$(#[$attr_method])*
$fil: $vil ($extra),
}
);
)*
}
};
(
$(#[$attr:meta])*
$name:ident $namespace:literal {
$(
$(#[$attr_method:meta])*
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
$(#[$attr])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
/// # let attributes = vec![];
/// # fn ChildComponent() -> Element { unimplemented!() }
/// # let raw_expression: Element = rsx! {};
/// rsx! {
/// // Elements are followed by braces that surround any attributes and children for that element
#[doc = concat!(" ", stringify!($name), " {")]
/// // Add any attributes first
/// color: "red",
/// "custom-attribute-name": "value",
/// // Then add any attributes you are spreading into this element
/// ..attributes,
/// // Then add any children elements, components, text nodes, or raw expressions
/// circle { cx: "10", cy: "10", r: "2", fill: "red" }
/// ChildComponent {}
/// "child text"
/// {raw_expression}
/// }
/// };
/// ```
pub mod $name {
#[allow(unused)]
use super::*;
pub use crate::attribute_groups::svg_attributes::*;
pub const TAG_NAME: &'static str = stringify!($name);
pub const NAME_SPACE: Option<&'static str> = Some($namespace);
$(
impl_attribute!(
$name {
$(#[$attr_method])*
$fil: $vil ($extra),
}
);
)*
}
};
(
$(#[$attr:meta])*
$element:ident [$name:literal, $namespace:tt] {
$(
$(#[$attr_method:meta])*
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
#[allow(non_camel_case_types)]
$(#[$attr])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
/// # let attributes = vec![];
/// # fn ChildComponent() -> Element { unimplemented!() }
/// # let raw_expression: Element = rsx! {};
/// rsx! {
/// // Elements are followed by braces that surround any attributes and children for that element
#[doc = concat!(" ", stringify!($element), " {")]
/// // Add any attributes first
/// color: "red",
/// "custom-attribute-name": "value",
/// // Then add any attributes you are spreading into this element
/// ..attributes,
/// // Then add any children elements, components, text nodes, or raw expressions
/// circle { cx: "10", cy: "10", r: "2", fill: "red" }
/// ChildComponent {}
/// "child text"
/// {raw_expression}
/// }
/// };
/// ```
pub mod $element {
#[allow(unused)]
use super::*;
pub use crate::attribute_groups::svg_attributes::*;
pub const TAG_NAME: &'static str = $name;
pub const NAME_SPACE: Option<&'static str> = Some($namespace);
$(
impl_attribute!(
$element {
$(#[$attr_method])*
$fil: $vil ($extra),
}
);
)*
}
}
}
#[cfg(feature = "hot-reload-context")]
macro_rules! impl_element_match {
(
$el:ident $name:ident None {
$(
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
if $el == stringify!($name) {
return Some((stringify!($name), None));
}
};
(
$el:ident $name:ident $namespace:literal {
$(
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
if $el == stringify!($name) {
return Some((stringify!($name), Some($namespace)));
}
};
(
$el:ident $name:ident [$_:literal, $namespace:tt] {
$(
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
if $el == stringify!($name) {
return Some((stringify!($name), Some($namespace)));
}
};
}
#[cfg(feature = "hot-reload-context")]
macro_rules! impl_element_match_attributes {
(
$el:ident $attr:ident $name:ident None {
$(
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
if $el == stringify!($name) {
$(
impl_attribute_match!(
$attr $fil: $vil ($extra),
);
)*
return impl_map_global_attributes!($el $attr $name None);
}
};
(
$el:ident $attr:ident $name:ident $namespace:tt {
$(
$fil:ident: $vil:ident $extra:tt,
)*
}
) => {
if $el == stringify!($name) {
$(
impl_attribute_match!(
$attr $fil: $vil ($extra),
);
)*
return impl_map_global_attributes!($el $attr $name $namespace);
}
}
}
#[cfg(feature = "hot-reload-context")]
macro_rules! impl_map_global_attributes {
(
$el:ident $attr:ident $element:ident None
) => {
map_global_attributes($attr)
};
(
$el:ident $attr:ident $element:ident $namespace:literal
) => {
if $namespace == "http://www.w3.org/2000/svg" {
map_svg_attributes($attr)
} else {
map_global_attributes($attr)
}
};
(
$el:ident $attr:ident $element:ident [$name:literal, $namespace:tt]
) => {
if $namespace == "http://www.w3.org/2000/svg" {
map_svg_attributes($attr)
} else {
map_global_attributes($attr)
}
};
}
macro_rules! builder_constructors {
(
$(
$(#[$attr:meta])*
$name:ident $namespace:tt {
$(
$(#[$attr_method:meta])*
$fil:ident: $vil:ident $extra:tt,
)*
};
)*
) => {
#[cfg(feature = "hot-reload-context")]
pub struct HtmlCtx;
#[cfg(feature = "hot-reload-context")]
impl HotReloadingContext for HtmlCtx {
fn map_attribute(element: &str, attribute: &str) -> Option<(&'static str, Option<&'static str>)> {
$(
impl_element_match_attributes!(
element attribute $name $namespace {
$(
$fil: $vil $extra,
)*
}
);
)*
None
}
fn map_element(element: &str) -> Option<(&'static str, Option<&'static str>)> {
$(
impl_element_match!(
element $name $namespace {
$(
$fil: $vil $extra,
)*
}
);
)*
None
}
}
#[cfg(feature = "html-to-rsx")]
pub fn map_html_attribute_to_rsx(html: &str) -> Option<&'static str> {
$(
$(
impl_html_to_rsx_attribute_match!(
html $fil $extra
);
)*
)*
if let Some(name) = crate::map_html_global_attributes_to_rsx(html) {
return Some(name);
}
if let Some(name) = crate::map_html_svg_attributes_to_rsx(html) {
return Some(name);
}
None
}
#[cfg(feature = "html-to-rsx")]
pub fn map_html_element_to_rsx(html: &str) -> Option<&'static str> {
$(
if html == stringify!($name) {
return Some(stringify!($name));
}
)*
None
}
$(
impl_element!(
$(#[$attr])*
$name $namespace {
$(
$(#[$attr_method])*
$fil: $vil $extra,
)*
}
);
)*
/// This module contains helpers for rust analyzer autocompletion
#[doc(hidden)]
pub mod completions {
/// This helper tells rust analyzer that it should autocomplete the element name with braces.
#[allow(non_camel_case_types)]
pub enum CompleteWithBraces {
$(
$(#[$attr])*
///
/// ## Usage in rsx
///
/// ```rust, no_run
/// # use dioxus::prelude::*;
/// # let attributes = vec![];
/// # fn ChildComponent() -> Element { unimplemented!() }
/// # let raw_expression: Element = rsx! {};
/// rsx! {
/// // Elements are followed by braces that surround any attributes and children for that element
#[doc = concat!(" ", stringify!($name), " {")]
/// // Add any attributes first
/// class: "my-class",
/// "custom-attribute-name": "value",
/// // Then add any attributes you are spreading into this element
/// ..attributes,
/// // Then add any children elements, components, text nodes, or raw expressions
/// div {}
/// ChildComponent {}
/// "child text"
/// {raw_expression}
/// }
/// };
/// ```
$name {}
),*
}
}
pub(crate) mod extensions {
use super::*;
$(
impl_extension_attributes![$name { $($fil,)* }];
)*
}
};
}
// Organized in the same order as
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
//
// Does not include obsolete elements.
//
// This namespace represents a collection of modern HTML-5 compatible elements.
//
// This list does not include obsolete, deprecated, experimental, or poorly supported elements.
builder_constructors! {
// Document metadata
/// Build a
/// [`