diff --git a/packages/sycamore-macro/src/view/codegen.rs b/packages/sycamore-macro/src/view/codegen.rs index 743f80cf8..be1118efd 100644 --- a/packages/sycamore-macro/src/view/codegen.rs +++ b/packages/sycamore-macro/src/view/codegen.rs @@ -72,9 +72,15 @@ impl Codegen { children, } = elem; - let tag = match tag { - ElementTag::Builtin(id) => id.to_string(), - ElementTag::Custom(s) => s.clone(), + let quote_tag = match tag { + ElementTag::Builtin(id) => quote! { + let __el = ::sycamore::generic_node::GenericNode::element( + <::sycamore::html::#id as ::sycamore::html::SycamoreElement>::TAG_NAME + ); + }, + ElementTag::Custom(tag_s) => quote! { + let __el = ::sycamore::generic_node::GenericNode::element(#tag_s); + }, }; let quote_attrs: TokenStream = attrs.iter().map(|attr| self.attribute(attr)).collect(); @@ -229,7 +235,7 @@ impl Codegen { }; quote! {{ - let __el = ::sycamore::generic_node::GenericNode::element(#tag); + #quote_tag #quote_attrs #quote_children __el diff --git a/packages/sycamore-macro/tests/view/element-fail.rs b/packages/sycamore-macro/tests/view/element-fail.rs index c0f2c7a2b..e981b075c 100644 --- a/packages/sycamore-macro/tests/view/element-fail.rs +++ b/packages/sycamore-macro/tests/view/element-fail.rs @@ -5,6 +5,7 @@ fn compile_fail() { let _: View = view! { ctx, button(disabled) }; let _: View = view! { ctx, button(on:click) }; let _: View = view! { ctx, button(unknown:directive="123") }; + let _: View = view! { ctx, unknownelement }; let _: View = view! { ctx, button(a.b.c="123") }; diff --git a/packages/sycamore-macro/tests/view/element-fail.stderr b/packages/sycamore-macro/tests/view/element-fail.stderr index d8f7619ef..dd71a3c19 100644 --- a/packages/sycamore-macro/tests/view/element-fail.stderr +++ b/packages/sycamore-macro/tests/view/element-fail.stderr @@ -17,20 +17,26 @@ error: unknown directive `unknown` | ^^^^^^^ error: expected `=` - --> tests/view/element-fail.rs:9:47 - | -9 | let _: View = view! { ctx, button(a.b.c="123") }; - | ^ + --> tests/view/element-fail.rs:10:47 + | +10 | let _: View = view! { ctx, button(a.b.c="123") }; + | ^ error: unexpected end of input, children and dangerously_set_inner_html cannot be both set - --> tests/view/element-fail.rs:11:26 + --> tests/view/element-fail.rs:12:26 | -11 | let _: View = view! { ctx, +12 | let _: View = view! { ctx, | __________________________^ -12 | | p(dangerously_set_inner_html="Test") { -13 | | "Error" -14 | | } -15 | | }; +13 | | p(dangerously_set_inner_html="Test") { +14 | | "Error" +15 | | } +16 | | }; | |_________^ | = note: this error originates in the macro `view` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `unknownelement` in module `sycamore::html` + --> tests/view/element-fail.rs:8:39 + | +8 | let _: View = view! { ctx, unknownelement }; + | ^^^^^^^^^^^^^^ not found in `sycamore::html` diff --git a/packages/sycamore/src/component.rs b/packages/sycamore/src/component.rs index 270b794b7..1b24b03d1 100644 --- a/packages/sycamore/src/component.rs +++ b/packages/sycamore/src/component.rs @@ -81,7 +81,10 @@ impl<'a, G: GenericNode> Children<'a, G> { } /// Create a new [`Children`] from a closure. - pub fn new(_ctx: ScopeRef<'a>, f: impl FnOnce(BoundedScopeRef<'_, 'a>) -> View + 'a) -> Self { + pub fn new( + _ctx: ScopeRef<'a>, + f: impl FnOnce(BoundedScopeRef<'_, 'a>) -> View + 'a, + ) -> Self { Self { f: Box::new(f) } } } diff --git a/packages/sycamore/src/html/mod.rs b/packages/sycamore/src/html/mod.rs new file mode 100644 index 000000000..56a213d29 --- /dev/null +++ b/packages/sycamore/src/html/mod.rs @@ -0,0 +1,196 @@ +//! HTML tag definitions. +//! +//! _Documentation sources: https://developer.mozilla.org/en-US/_ + +/// Represents an element. +pub trait SycamoreElement { + const TAG_NAME: &'static str; + const NAME_SPACE: Option<&'static str>; +} + +/// MBE for generating elements. +macro_rules! define_elements { + ( + $( + $(#[$attr:meta])* + $el:ident { + $( + $(#[$attr_method:meta])* + $at:ident: $ty:path, + )* + }, + )* + ) => { + $( + #[allow(non_camel_case_types)] + #[doc = concat!("Build a [`<", stringify!($el), ">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/", stringify!($el), ") element.")] + $(#[$attr])* + pub struct $el; + + impl SycamoreElement for $el { + const TAG_NAME: &'static str = stringify!($el); + const NAME_SPACE: Option<&'static str> = None; + } + )* + }; +} + +// A list of valid HTML5 elements (does not include removed or obsolete elements). +define_elements! { + /// The `` HTML element (or anchor element), with its `href` attribute, creates a hyperlink to web pages, files, email addresses, locations in the same page, or anything else a URL can address. + /// + /// Content within each `` should indicate the link's destination. If the `href` attribute is present, pressing the enter key while focused on the `` element will activate it. + a {}, + abbr {}, + address {}, + area {}, + article {}, + aside {}, + audio {}, + b {}, + base {}, + bdi {}, + bdo {}, + blockquote {}, + br {}, + /// The `