I would expect to use something more like namespaces, where the default would be shorthand `on:`, `attr:`, `prop:`, `propOrAttr:` (maybe this is the default?) but where an explicit namespace declaration could move them if you for whatever reason needed to support XHTML 5.1 and your document already used the `on:` namespace for something else (not that _that_ is a thing right now, but why not be prepared?)
I personally think the sigils are easier to read and write than perfixes, and these particular sigils have popped up independently in multiple libraries like Vue, Lit, and LighterHTML.
But this API could use prefixes, or like Vue, it could support both.
Seriously browsers just need to adopt XSLT 3.0 and stop all this wheel reinvention already.
[0] https://github.com/Paligo/xee/issues/32#issuecomment-2762343...
```
static/
js/
css/
log/
my-post.xml
my-post.xsl
index.html
```Caddyfile:
```
:8080
try_files {path}.xml {path}.html
file_server {
index index.xml index.html
root static
}```
XSLT work is all based off of a repository someone wrote with a grug brain explainer:
https://github.com/pacocoursey/xslt
The next step is to generate all of the `static` dir from markdown files and probably a new markdown-like format for registering templates to generate xsl/xml files for special html blocks and template parts or generating blog listing pages.
<div>
{#each colors as color, i}
<button
style="background: {color}"
aria-label={color}
aria-current={selected === color}
onclick={() => selected = color}
>
{i + 1}
</button>
{/each}
</div>
<div x-data="{ open: false }">
<button @click="open = true">Expand</button>
<span x-show="open">
Content...
</span>
</div>
Nobody wants to express complex conditions all around the UI when derived state can be handled in a single store.
The code came directly from Svelte's official tutorials. Looks like I accidentally copied the problem instead of the solution!
These PHP style template ideas I have never understood. I thought we all agreed 30 years ago that while exceptionally functional for a "quick and dirty" approach they are horrible for long term product or application development.
You have a DOM. Use it as such.
What is "enough" here? It is good enough for the unified community. I know npmtrends.com isn't the best metric, but unified is popular. Unified has made it trivial to move between HTML, MDX, MD, JSX and even combinations of the above. I'm learning it's an opinion, but hyperscript and hast are HTML enough being that they're models of HTML
Hooking into a tagged template is a challenge. Functions will receive a list of unparsed html strings and already evaluated expressions to zipper up themselves before forwarding to the downstream template API.
https://stackoverflow.com/questions/39971088/evaluating-temp...
Unlike an expression or tag, a developer can hack on any AST or hyper script provided by a library. Im not sure proxies or reflection are useful working with string primitive and they're unergonomic.
This was something I mentioned on the other post so I appreciate seeing it called out clearly in the reply. (Not to assume I inspired the mention.) Thank you for sharing.
Frameworks and rendering libraries that don't have a markup-based template syntax are just very rare.
And I think for understandable reasons: Markup-based templates look like the output, and web developers know HTML, so the templates are easier to read and write.
That StackOverflow question seems unrelated because it's asking about untagged template literals. With tagged template literals, depending on the return type, you can absolutely get to the underlying values.
The first answer reinvents tagged templates and the second suggests them. I thought it was a good example to show the complexity of hacking in this approach. I'll add more context in the future.
I'm agreed that the average developer would hate working with an an AST -- JSX covers 99.9% use-case and React codebases are full of functional programming escape hatches -- but it is the foundation. An HAST is an interoperable, extendable representation we can move between any framework or tooling.
I'm likely projecting too much on the proposal. Templating is the top priority but it's the ancillary bits you mention that excite me most.
> Markup-based templates look like the output
I made the mistake of drinking functional programming laced koolaid, so in my mind they really do translate well, but I respect that you have a broader perspective.
Thanks for taking the time to reply. I'm a smidge honored that you'd even review my feedback!
Instead, what's hinted at in this article (using a plain HTML string) works great. Add in a little abstraction for the sake of structure and simplicity and you've got a surprisingly robust UI framework without a ton of complexity.
[1] https://cheatcode.co/joystick (a full-stack JS framework that has its own components API)
The component method in the framework is inspired by React v1 (really just that it's a function you call—my approach to everything else is different), but all of the routing is on the server-side (a light abstraction that maps back to Express.js routes).
The API is secure because it separates static developer controlled strings from dynamic and possibly user-controlled values by JavaScript syntax. Values from text bindings are written to the DOM by setting TextNode.data, which escapes the value first.
Since it "caches" the rendered parts, I haven't had performance issues just re-rendering everything on state changes (with some basic scheduling). I find it easier to reason about than React since I can use Vanilla JS everywhere, and components are just functions using the `html` tagged template, which can be composed.
I did many of my own experiments with templates that are native JS with no compile step, and reached basically the same conclusion as this post. Use tagged templates and keep it simple. My angle was server-focused, with async bits in a template doing automatic streaming while server rendering with them. Works super well and it takes so little code to achieve. Check it out if you're interested: https://www.hyperspan.dev/ or the CodeSandbox demo: https://7lpdpl.csb.app/
The templates look basically identical. html-tagged template literals that support streaming and async values and automatically escape values.
What Koa does will allowing strings by be returned with a default HTML mimetype is security malpractice, IMO. It's way to easy to just interpolate user-controlled values.
I even have a lot of those things planned, just not enough time!
I didn't do anything that required client-side JS yet, but the first things on that list are out-of-order rendering; watch mode (page reload); and hot module replacement.
But modern signal-based frameworks tend to work on the basis that doing these of rendering for each change is unnecessary, and so you should only update the relevant part of the DOM. This means rendering as seldom as often, in particular when handling conditionals and lists. This is why both SolidJS and Vue Vapor both have helpers for rendering lists and conditional elements, because if you just use `.map` and the ternary operator, things aren't going to work as you'd expect. Svelte has its own syntax but in principle works very similarly.
This proposal feels like it's very oriented around the React/Lit VDOM mechanism, with a handful of Preact-like concessions to signals where they are relatively easy to retrofit into a VDOM-like system. The problem is that these sorts of frameworks are heavyweight, slow, cumbersome things, because they're doing so much extra work. Codifying that sort of inefficiency directly into the browser seems like a terrible idea.
My second biggest criticism of this proposal is that I'm really struggling to see the benefit of it, i.e. who it's for. It can't be for framework compatibility, because it's not addressing any of the issues that actually make frameworks incompatible with each other (different state/context mechanisms, different lifecycles, etc). It can't be to codify common rendering idioms and optimise them by letting the browser implement them natively, because, as discussed, the proposal doesn't leave a lot of room for well-optimised frameworks. So I guess the idea is to ensure that the browser has a built-in web framework to make it easier for people to build complex web applications without needing to import lots of dependencies.
But if you're building a complex web application, the sort that needs specialised rendering like this, the overhead of a web framework is probably pretty minimal anyway. And if you're building simpler sites with minor interactivity, this sort of rendering system is complete overkill. You'd be better if writing a wrapper around document.createElement and going from there.
Haven't these tagged template libraries coalesced around the html`<${SomeComponent}><//>` syntax for custom components (including control flow components like Solid's `For` component)? The readme for Ryan Carniato's Lit DOM Expressions library includes this example for instance [1]:
const view = html`
<table class="table table-hover table-striped test-data">
<tbody>
<${For} each=${() => state.data}
>${row => html`
<tr>
<td class="col-md-1" textContent=${row.id} />
<td class="col-md-4">
<a onClick=${[select, row.id]}>${() => row.label}</a>
</td>
<td class="col-md-1">
<a onClick=${[remove, row.id]}
><span class="glyphicon glyphicon-remove"
/></a>
</td>
<td class="col-md-6" />
</tr>
`}<//
>
</tbody>
</table>
`;
The author of the article mentions this very briefly, where he writes "For JSX-style references you would need to use binding syntax like <${MyComponent}>". The Preact author's htm tagged template library uses this convention as well [2].[1] https://github.com/ryansolid/dom-expressions/tree/7fd9f86f1b...
My claim, having done that, is that template re-rendering and fine-grained reactivity are entirely compatible, and neither takes away from the other.
Template re-rendering is incredibly cheap, and not at all like React/vdom. It does a few simple checks: 1) that the new template is the same as the last, 2) it runs through the linear list of values and compares them to the last, writing them if they changed. This isn't like VDOM which has to traverse two fine-grained vdom trees comparing for differences. Many huge web applications like Photoshop, Reddit, and parts of YouTube use template re-rendering.
And signals work great with this. If your template is "signal pure" then it never needs to re-render. If it's partially signals and partially non-signal data, then it only needs to re-render when non-signal data changes.
Signals are great, but signal-only systems require that all data be wrapped in them. And I have seen large apps have problems with the memory overhead of the automatic dependency tracking and change detection at each composed signal in the graph. Memory pressure and GC could be problematic for the TC39 signals proposal (though hopefully not).
To answer your next point about who this is for: lots of different audiences.
First is plain web devs. I've seen in multiple large dev orgs moves to standardize all DOM creation outside of frameworks on lit-html or something similar, mainly out of security concerns. But templated DOM creation is so common, that it's really a big whole in the web platform that it's not built in. The only reason it's not is that platform maintainers are afraid of stepping on the toes of frameworks. I don't think that's a good reason.
Second is frameworks. Whether or not the exact set of current frameworks migrate to this, a framework created for a platform with templating built-in would have a high probably of just using it instead of rolling their own. You can easily imagine a React-alike built on top of this API, as I've seen people do with lit-html. That reduces code size and increases perform for libraries and users.
Third is web components authors. Many reach for something like Lit main for the templating. I don't think they should have to, even as the maintainer of Lit. Vanilla web components + native templating takes care of a large amount of component concerns for those developers.
Fourth is the platform itself. Part of my reason for working on this proposal now as opposed to my usual "I'll get to that one day" tasks is because I've seen so many people ask for an HTML-based templating solution, ie a better `<template>`. I support that, but I don't think we can easily get there all at once. This is an attempt to build the story and capabilities for the subset of features that an JS API needs first so that the infrastructure can be used for HTML templates. If the JS API gets in, then the HTML API can reuse it, adding the expressions, scopes, control flow, etc., that HTML needs and JS doesn't.
rictic•6h ago