Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elements as attribute values #14

Open
gbj opened this issue May 19, 2023 · 3 comments
Open

Elements as attribute values #14

gbj opened this issue May 19, 2023 · 3 comments
Labels
enhancement New feature or request syn Related to syn library

Comments

@gbj
Copy link

gbj commented May 19, 2023

leptos-rs/leptos#766 makes an interesting proposal for shortening much Leptos boilerplate.

If KeyedAttributeValue could itself be a Node, then

<Routes>
  <Route path="/" view=|cx| view! { cx, <Home/> }/>
  <Route path="/other" view=|cx| view! { cx, <Other>"children"</Other> }/>
  <Route path="/*any" view=|cx| view! { cx, "just text" }/>
</Routes>

could be shortened to

<Routes>
  <Route path="/" view=<Home/>/>
  <Route path="/other" view=<Other>"children"</Other>/>
  <Route path="/*any" view=<>"just text"</>/>
</Routes>

i.e., the framework could choose to expand any key={fragment or element} to |cx| {that fragment or element}

@vldm
Copy link
Collaborator

vldm commented May 21, 2023

Technically it's not that simple. Array of attributes is parsing using parse_tokens_with_ending, which limit parsing context to one that ends with > (end of open tag).
This is copied from original syn-rsx. And the main reason for that, i think, is to avoid ambiguity during parsing rust expressions. <div checked=x>2 >.

Parsing attribute value as `syn::Expr` already violate html5 spec, which expects no spaces inside unquoted attribute values.

html5 spec

Unquoted attribute value syntax
The attribute name, followed by zero or more space characters, followed by a single U+003D EQUALS SIGN character, followed by zero or more space characters, followed by the attribute value, which, in addition to the requirements given above for attribute values, must not contain any literal space characters, any U+0022 QUOTATION MARK characters ("), U+0027 APOSTROPHE characters ('), U+003D EQUALS SIGN characters (=), U+003C LESS-THAN SIGN characters (<), U+003E GREATER-THAN SIGN characters (>), or U+0060 GRAVE ACCENT characters (`), and must not be the empty string.

I think we can violate it further, but it should not obscure end-users. In order to do it we should reduce amount of mixing parsing context, not increasing it (or at-least try to mark mixed context, like templating syntax in js).
(Currently user expect html, only inside html tags, and rust code only in curly brackets, and attribute values).

For original issue, i understand that nobody likes writing more boilerplate code, but i also think there is second problem with using view inside attribute - its a problem of mixing parsing context, so it can obscure the end-user.
And this problem looks more framework related, i have written an comment, with idea, how it can be done in leptos leptos-rs/leptos#766 (comment)

@gbj
Copy link
Author

gbj commented May 21, 2023

Technically it's not that simple. Array of attributes is parsing using parse_tokens_with_ending, which limit parsing context to one that ends with > (end of open tag). This is copied from original syn-rsx. And the main reason for that, i think, is to avoid ambiguity during parsing rust expressions. <div checked=x>2 >.

Makes sense as a way of avoiding ambiguity. I guess I'd say... any attribute value that starts with < seems to me that it would have to be a fragment or element, because I don't think it's possible to have a valid Rust expression that starts with < (for example, <2;)

But I'm sure you know much more than I do about the actual parsing here.

Parsing attribute value as syn::Expr already violate html5 spec, which expects no spaces inside unquoted attribute values.
I think we can violate it further, but it should not obscure end-users. In order to do it we should reduce amount of mixing parsing context, not increasing it (or at-least try to mark mixed context, like templating syntax in js). (Currently user expect html, only inside html tags, and rust code only in curly brackets, and attribute values).

I see JSX as the thing to compare to here: something like <MyComponent view={<span>Hello</span>}/> is valid JSX but invalid HTML, of course. I guess in our case the difference is that there's always a macro invocation, not JSX syntax mixed into ordinary code, and that example is actually two separate JSX "invocations", the equivalent of rsx! { <MyComponent view=rsx! { <span>Hello</span> } /> }

It would be nice from my end to have the flexibility but I understand if it's not possible or would be too much added complexity!

@vldm vldm added the syn Related to syn library label May 21, 2023
@vldm
Copy link
Collaborator

vldm commented May 21, 2023

I see JSX as the thing to compare to here: something like <MyComponent view={<span>Hello</span>}/> is valid JSX but invalid HTML, of course. I guess in our case the difference is that there's always a macro invocation, not JSX syntax mixed into ordinary code, and that example is actually two separate JSX "invocations", the equivalent of rsx! { <MyComponent view=rsx! { <span>Hello</span> } /> }

Yes, that what i meant when said "at-least to mark mixed context" - it would be easier for user to find it, and for parser to understand.

I guess I'd say... any attribute value that starts with < seems to me that it would have to be a fragment or element, because I don't think it's possible to have a valid Rust expression that starts with < (for example, <2;)

Good point. But in that quote i was talking more about > - currently parser just searching for first occurence.
But if we would expect that attribute could contain valid html element - this should be changed.

And if that would change, we also should change syn::Expr::parse in order to prevent it eat > at end of the tag (in that example <div checked=x>).

Maybe someone can figure out easier way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request syn Related to syn library
Projects
None yet
Development

No branches or pull requests

2 participants