whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
7.87k stars 2.58k forks source link

Syntax for <template> variables #4219

Open indolering opened 5 years ago

indolering commented 5 years ago

This is a bikeshed ticket to opine the best syntax for <template> variables.

Syntax Pros Cons Viable?
{} Simple, reuses JSX syntax. Breaks inline style tags: <template><style>x-foo {color: blue;}</style>.
{{}} Familiar syntax used by Mustache, Angular, etc. Requires escaping by Mustache and friends
${} Looks like variables used in JS! Would require escaping when creating HTML via JS template literals:
template.innerHTML = <div>\${foo}</div>
@{} Vague syntax similarity to JS decorators. Conflicts with CSS at-rules.
#{} Hash TAG identifier ... almost a pun! Syntax conflict with hash ID's in URLS: <a href=faq.html#{...}>
<% %> Familiar EJS syntax It's fat/ugly, conflicts with EJS, might cause problems in URLs w/ percent encoding
<% > Familiar to EJS users. It's fat/ugly, might conflict with EJS linters, etc ✔️
<< >> Prettier than <% %>, looks more HTML-esque Fat ... ? ✔️
<$ > JQuery's famous power symbol, pretty slim ? ✔️
<= > Resembles variable assignment! ? ✔️
<# > Hash TAG, good alternative for HTML escaping ? ✔️
<! > Comments that are removed form HTML markup... ?
<_ _> Removes whitespace from left/right/both side(s) of tag ?
<__ __> Removes newline from left/right/both side(s) of the tag ?
snuggs commented 5 years ago

@indolering IMHO I feel the {} example should be a ❓ . The use case I feel isn't real world. If i'm not mistaken <template> is to be reused in and of itself. When would one declare style x-foo multiple times or even have a dynamic selector declaration? Honest question.

Again I feel should be a ❓ not ❌ . Unless a better use case is used like the style="" attribute but even then I don't think there is a chance of {} CSS blocks as they are superfluous within that context. It's also easy to no-op bypass <style> element within <template>.content context. Can provide working examples if you like and have already been doing this in production for a couple years now under many use cases for <template>. Also is fairly easy to determine if token is alphanumeric name or a style. If i'm not mistaken there are no CSS rules without :. I would say ; as well but tailing rules have optional closing semicolons. I'd be willing to bet the bike shed and say there will always be a : between {} if CSS is there. And never a : if a template variable. This can easily be done by having an alphanumeric step validation for the token name. Similar to - requirement with custom element name.

Your thoughts?

snuggs commented 5 years ago

#{} will conflict with dynamic fragment identifiers. <a href=faq.html#{...}>

Not that anyone would write an element id or a fragment identifier in this way but the RFC for URI allows these characters i believe RFC3986.

And HTML5 allows any character to be used as identifier / fragment id as they can be pct-encoded.

Overall no real interpretational threat but does introduce possibility of navigational issues arising due to fragment identifiers.

indolering commented 5 years ago

When would one declare style x-foo multiple times or even have a dynamic selector declaration? Honest question.

Inline styling is a thing, when I was working on web components it was much easier to have the styles embedded within the component itself instead of in a separate document. AFAIK this syntax is already considered a mistake by the JSX community. Maintainers can override if they wish.

indolering commented 5 years ago

Overall no real interpretational threat but does introduce possibility of navigational issues arising due to fragment identifiers.

Escaping is a PITA, let's not do that!

indolering commented 5 years ago

I'm leaning towards having multiple tags to replicate EJS's control flow, escaping, and whitespace elimination features. I would be more partial to <= > for no escaping, <# > for HTML escaping, <! > for comments that are removed from the output, <=_ _> for whitespace removal, and <=__ __> for multi-line whitespace removal.

caridy commented 5 years ago

I agree with @snuggs, {} should be ❓at least. We have been using that in our html templates for quite some time for the Lightning Web Components platform, and we have encounter only one issue so far (consider that we currently have +1k developers using this platform and a lot more currently ramping up, creating from very simple web components to very complex ones. The only issue that we have faced is confusing about what goes inside, folks sometimes asume that it is a JS expression of some sort, which is not (I think ${} will be a lot more confusing on this regard, but in general that will be an issue with everything on this table).

Note: we do not allow variables inside the style tag, they have few ways to deal with this.

snuggs commented 5 years ago

@caridy we just barf on anything non-alphanumeric (inclusive of : & ;). Sounds a bit aggressive but what's between { and } should literally be just a placeholder token. I concur with ${...} confusion but would understand if that was a viable candidate. However this would for certain break the POLA principal. The majority of blood sweat and tears with templating systems from author's perspective usually wraps around wanting (not necessarily needing) evaluation. K.I.S.S. is the fastest path to ship IMHO. And the edge cases thought of with the evaluation have usually been circumvented by keeping the logic elsewhere in a well defined name. That way the token is just that...a token.

We came up with an implementation a while ago and has been working smoothly aligning to most (not all) needs for the past couple of years. I just love when can actually write HTML in the browser. (Not a permutation of XML in JavaScript...that needs endless packages to get to a screen 😳. Which is why we are all here 😄 )

indolering commented 5 years ago

Note: we do not allow variables inside the style tag, they have few ways to deal with this.

Do you mean your specific templating system or the template proposal?

caridy commented 5 years ago

@indolering our abstraction layer on top of the template proposal, which adds a bunch of restrictions for various reasons.

snuggs commented 4 years ago

@caridy just had an epiphany dealing with the <...> formats... In the HTML spec there is no enforcement of quotes around attributes (only if whitespace).

<foo-bar baz=<...> and that's when hope flies out the window....Methinks too much overhead in the HTML parser to deal with this. Works great for TEXT_NODE children. Attributes (IIRC) would require far too much from the parser. Already a pain in the neck converting Attr back to being an object descendant of node.

Like I said before a few years ago we skipped over <style> & <script> tags for parsing templates. And haven't even run into an edge case. And truth be told....Similar to your team we just set up some anti-patterns.....Placing <style> in a repeatable template would be one of these anti-patterns YAGNI. I'm still in support of {token}. Been using it for YEARS now with custom elements and works smashingly. Your thoughts...

snuggs commented 4 years ago

Inline styling is a thing, ... @indolering

TRUE...However even after a couple years i've still yet to see an "inline style" (via style="..." attribute) that contained {}. Unless you meant nested <style> within Template. And as said before we just bypass this when traversing <template> children. IIRC the platform has separate parser for styles and JS so this should overlap in template implementation. (Or at least the "do nothing" has worked in our case)

Perhaps this is the "JSX is broken" you were speaking of. I do recall some curlybrace style in JSX attributes but I've refused to use JSX for years now as it will probably deprecate itself before the platform does. It's not HTML, nor CSS, nor JS no matter how many backticks and parenthesis are used. And for that reason cues should be taken from JSX but should bend to the platform and not the inverse IMHO. /cc @caridy

jurca commented 1 year ago

An idea for an HTML-esque approach: use an element for node slots and attribute namespace for attribute slots.

Let's say the name for the element and attribute namespace would be bind (Note that both var and slot elements already exist in HTML, so a different name might be preferable).

Example usage:

<form bind:action="variableName=/default-value" method="post">
  <bind var="variableName"/>
  <input type="text" name="fullname" bind:placeholder="variableName">
  <input type="email" name="email" bind:placeholder="variableName=Default placeholder value">
  <button>
    <bind var="variableName">Default content</bind>
  </button>
</form>

The obvious downsides of this are verbosity, no support for setting only a part of attribute's value without introducing another interpolation syntax and that it's unclear if <bind> should work inside comments. The upside is that this requires no modifications to the HTML parser, as the template can be instantiated by manipulating the parsed DOM.

I'm not saying this a great idea, just something that might work safely and be viable, so I thought I might share it here.

Edit: Some, but slight, changes to the HTML parser would be needed, that is allowing <bind> element to appear inside any element (for example it currently gets removed from the <select> element's children).