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

Syntax for <template> variables #4219

Open
indolering opened this issue Nov 29, 2018 · 14 comments
Open

Syntax for <template> variables #4219

indolering opened this issue Nov 29, 2018 · 14 comments

Comments

@indolering
Copy link

indolering commented Nov 29, 2018

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
Copy link
Member

snuggs commented Dec 4, 2018

@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
Copy link
Member

snuggs commented Dec 4, 2018

#{} 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
Copy link
Author

indolering commented Dec 20, 2018

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
Copy link
Author

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
Copy link
Author

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
Copy link

caridy commented Dec 21, 2018

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
Copy link
Member

snuggs commented Dec 21, 2018

@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
Copy link
Author

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
Copy link

caridy commented Dec 29, 2018

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

@snuggs
Copy link
Member

snuggs commented Apr 14, 2020

@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
Copy link
Member

snuggs commented Apr 14, 2020

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
Copy link

jurca commented Nov 20, 2022

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).

@snuggs
Copy link
Member

snuggs commented Jan 6, 2025

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.

@jurca Wouldn't this break HTML validation?
IIRC only the id and XML namespace attributes can have :. Unless there would be a bind XML namespacing. Could be wrong. Been a while since i've been over to that side of the specs.

@jurca
Copy link

jurca commented Jan 6, 2025

@snuggs

I think it would - the introduction of a new element would already do it, I think. At least the W3 validator rejects the following input:

<!DOCTYPE html>
<html lang="en">
<head><title>Title</title></head>
<body>
<bind var="variableName"/>
</body>
</html>

The standard would need to be extended, and validators updated - but that would be the case for any syntax using the < character.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants