-
Notifications
You must be signed in to change notification settings - Fork 378
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
[templates] Template proposal essentials (shave the mustache) #739
Comments
You can use {{}} with nothing inside it if you don't want to give your template parts descriptive names. It'll then work exactly as you're describing. |
Sure, it could be any placeholder, the point is - we don't need to introduce any logic or syntax and the only thing that should be added to spec is ability to transform array of strings (same array that you will get from template string) into DocumentFragment and parts. |
I'm saying the proposed spec already covers your needs. |
I'm saying it covers much more then we all need. It introduces new syntax and some logic in temlpates that is not enough to write descriptive templates and can be moved to js template strings. This issue propose to introduce less significant changes to a spec: Transform array of strings into a document fragment and parts, nothing more (no mustache, no template changes) This is the only things that we really need the rest is already there because of template strings. |
OK. You can use the subset of the spec that you're interested in though; we'll continue exploring the rest of the spec for other peoples' use cases which go beyond your own. |
I'm not talking about my personal needs, I'm talking about not to implement something that you and other developers do not need, because it is already there. |
I will schedule a call to @rniwa, may be he will understand my point better. I will repeat it once again - logic can be moved from the template itself to a template string, the only thing that specification is missing is ability to transform array of strings into a DocumentFragment and parts. The rest is already there or could be implemented with zero efforts. |
First off, I'd much prefer discussion this over Github or email threads. I understand what you're saying but this approach tends to break down when if you have nested templates. There, you need to be able to recognize inner templates as separate entities while parsing |
Let's discuss this part here. It would not break down with nesting templates or logic. Symbol We won't have simple string replacement, rather we will have a mechanism (based on build in HTML parser) that turn that array of strings into DocumentFragment and Parts object. So if you ask where all the logic and nesting should go then? The answer is to javascript through template strings e.g. const template = html`
<div>
<h1>${name}</h1>
${name ? html`<h2>Wellcome ${name}!</h2>` : ''}
</div>
` As you see we have nesting template and More specifically the inner template will receive plain (string) name value as a part value, while the outer template will receive inner template as a part value. So there is no issues when we are substituting string or DocumentFragment into a template (very naive implementation could use innerHTML as in example of the original post, smarter - will take care of context, but it is still very native to substitute DocumentFragment into another DocumentFragment). This way we might have very descriptive templates with all familiar js syntax, while keeping proposal small. As a result we will be able to write templates in js (with template strings) and html (developer will introduce a preferred separator and have only plain template that he will split into array of strings, more complex template logic and composition should be done in js part through the template strings) |
Moreover, let's say that <div>
<h1>$$</h1>
$$
</div> and <h2>Wellcome $$!</h2> We can compose them into complex template with logic this way const SEPARATOR = '$$';
const template = html(tpl1.split(SEPARATOR), name, name ? html(tpl2.split(SEPARATOR), name) : ''); Well it is working but does not look quite good, but there is a better way to say the same, we can define a template like this <div>
<h1>${name}</h1>
${name ? html`<h2>Wellcome ${name}!</h2>` : ''}
</div> And then instantiate it this way (it is dirty, but having scoped eval and native implementation will work better) const template = eval('html`' + tpl + '`'); |
Nesting template literal within template literal like that is too cumbersome for many use cases. Also, we certainly don't want to be encouraging the use of |
Well it is the matter of preferences, you can always wrap it to a function and hide nesting complexity. The good part - it is well known, flexible and valid JavaScript, you need to change very little in spec and you will get full power of templates vs you will add a lot and got mustache templates. Eval was example of very quick and dirty polyfill. It is not required and you can parse the same expression without using eval or entroduce better native way to construct template strings from regular strings. |
Well, one of the requirements for this template API is that it needs to work for declarative custom elements. I don't think what you're proposing would be able to satisfy that use case. |
Why? The example above is declarative. |
What example? I don't see any example which doesn't involve scripts here. See https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Declarative-Custom-Elements-Strawman.md for how the current proposal does this. What you're proposing would require ordering of properties to substitute $$ or whatever delimiter is, and doesn't allow name-based referencing. This alone is a show stopper in declarative custom elements since you'd have to remember which argument corresponds to which part based on ordering. In the world where a template is defined away from where it's used having to remember what n-th argument means in the template poses a serious if not fatal developer ergonomics issue. |
I’m talking about the example above that does include template strings (sorry, I am far from computer to copy it). Instantiation with scoped eval or other parser might be internal mechanism. So you just put template strings with html tag into your html template. |
My point is, having basic mechanism that turn array of strings into a DOM and Parts e.g.
and from this point we can move to declarative templates
|
That is not decralative. We can't have evaluation of a string literal in the middle of a template. |
We don't need to have immediate evaluation. Evaluation can be delayed until actual instantiation. |
No, that won't work because we can't execute arbitrary scripts like that from template at least in v1. That would either not run under CSP's eval restriction, or we'd need to invent a new CSP option. I feel like we're not going anywhere on this. All I can say at this point is that we've already considers what you're proposing here, and it doesn't satisfy all the requirements we have. |
Do we really need the mustache syntax?
Having a template string in JavaScript allow us to inject values into specific parts of a string:
`word1 ${executedValue1} word2 ${executedValue2} ...`
It appears that the essence of html templates are very similar.
A mustache syntax is powerful, yet it is not descriptive enough (people already mentioned that in other issues e.g. #704). So the question is, should we have a template syntax at all? Taking into account that we can use function results in mustache templates as well as nested templates, means that we can avoid using any template syntax and just have a placeholder like we do in template string (the logic can be moved inside a function)
Which can be rewritten:
The placeholder (
$$
) can be anything, but the point is that we don't have any logic in the template at all, and we can transform this template (string) into something very familiar:The result is exactly the same as in tagged template string. It is native, performant, straightforward and we don't need anything new (no new syntax, no parser, nor anything else). But now, there are some parts that should be improved (and this is the only part that should be added to the spec), i.e. we need to turn this array of strings into a DocumentFragment and an object that holds the array of context for the dynamic parts (values).
DocumentFragment representation:
and
Where
nodeContext1
andnodeContext2
are placeholders that hold the values and have an update method that updates an appropriate part of the DocumentFragment.Having a regular DocumentFragment and Parts object, it is possible to update Fragment with a new data:
Moreover, we can add complex logic inside javascript template strings like below:
Libraries like
lit-html
uses similar mechanism under the hood as well.This way, we do not introduce any new syntax and solve the basic issue that can fit both html templates and template strings. Template logic can go to the template strings rather than the template itself (instead of {{#loop}} we can use native js). Having this bare minimum native implementation of templates, allows us to extend the power of templates with 3rd party libraries later.
The text was updated successfully, but these errors were encountered: