#![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}; use crate::{GlobalAttributes, SvgAttributes}; pub type AttributeDiscription = (&'static str, Option<&'static str>, bool); macro_rules! impl_attribute { ( $(#[$attr_method:meta])* $fil:ident: $vil:ident (DEFAULT), ) => { pub const $fil: AttributeDiscription = (stringify!($fil), None, false); }; ( $(#[$attr_method:meta])* $fil:ident: $vil:ident ($name:literal), ) => { pub const $fil: AttributeDiscription = ($name, None, false); }; ( $(#[$attr_method:meta])* $fil:ident: $vil:ident (volatile), ) => { pub const $fil: AttributeDiscription = (stringify!($fil), None, true); }; ( $(#[$attr_method:meta])* $fil:ident: $vil:ident (in $ns:literal), ) => { pub const $fil: AttributeDiscription = (stringify!($fil), Some($ns), false) }; ( $(#[$attr_method:meta])* $fil:ident: $vil:ident (in $ns:literal : volatile), ) => { pub const $fil: AttributeDiscription = (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])* pub struct $name; impl $name { pub const TAG_NAME: &'static str = stringify!($name); pub const NAME_SPACE: Option<&'static str> = None; $( impl_attribute!( $(#[$attr_method])* $fil: $vil ($extra), ); )* } impl GlobalAttributes for $name {} }; ( $(#[$attr:meta])* $name:ident $namespace:literal { $( $(#[$attr_method:meta])* $fil:ident: $vil:ident $extra:tt, )* } ) => { #[allow(non_camel_case_types)] $(#[$attr])* pub struct $name; impl SvgAttributes for $name {} impl $name { pub const TAG_NAME: &'static str = stringify!($name); pub const NAME_SPACE: Option<&'static str> = Some($namespace); $( impl_attribute!( $(#[$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])* pub struct $element; impl SvgAttributes for $element {} impl $element { pub const TAG_NAME: &'static str = $name; pub const NAME_SPACE: Option<&'static str> = Some($namespace); $( impl_attribute!( $(#[$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, )* } ); )* pub(crate) mod extensions { use super::*; $( impl_extension_attributes![ELEMENT $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 compatiable elements. // // This list does not include obsolete, deprecated, experimental, or poorly supported elements. builder_constructors! { // Document metadata /// Build a /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) /// element. /// base None { href: Uri DEFAULT, target: Target DEFAULT, }; /// Build a /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head) /// element. head None {}; /// Build a /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link) /// element. link None { // as: Mime, crossorigin: CrossOrigin DEFAULT, href: Uri DEFAULT, hreflang: LanguageTag DEFAULT, media: String DEFAULT, // FIXME media query rel: LinkType DEFAULT, sizes: String DEFAULT, // FIXME title: String DEFAULT, // FIXME r#type: Mime "type", integrity: String DEFAULT, }; /// Build a /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta) /// element. meta None { charset: String DEFAULT, // FIXME IANA standard names content: String DEFAULT, http_equiv: String "http-equiv", name: Metadata DEFAULT, }; /// Build a /// [`