Apart from running screaming in the opposite direction from tagged templates for security reasons, I think a more suitable approach (that fits current ECMAScript naming conventions / namespacing) might just be something like:
You can already effectively do this, though you'll have to decide for yourself if putting the following lines of code into a top-level module translates to "Writing your own framework":
import html from "MyModule"
const content = html`<h1 id=hello>Hello world!</h1>`; // No New API Needed
document.querySelector("#container").replaceChildren(content.childNodes)
You're losing the pretty printing in the console but there's options for that -- from tweaking the toString() prototype method to straight up creating a custom class that acts as an Element.
Worth noting too: you could cheat in the html function above and have it directly return content.childNodes, thus reducing the differences between the two examples to simply "patch" vs "replaceChildren".
In your example, are you envisioning that HTMLElement.patch() is doing something different than Element.replaceChildren() or Element.replaceWith()? That'd be one area that wouldn't be addressed with this.
Having it first-party would be lovely but it's already pretty doable.
All of what I'm talking about is doable through libraries today (or you can write it yourself). But making things available through DOM APIs create a new baseline where the very same tools are made available for anyone, no matter the framework (think: document.querySelector APIs).
Regarding patch, morphdom explains very well the difference between replacing and patching the DOM [1]:
> Replacing an entire DOM tree is fast but loses internal state (e.g., scroll positions, input carets, CSS transitions). Instead, we aim to transform the existing DOM tree to match the new one, minimizing changes and preserving state.
Also, there's the matter of performance. Diffing and patching as a single method call implemented natively should be a lot faster than using a bunch of JS code.
I agree on the point of first-party, as I already wrote.
I suspect there would be a lot of edge case footguns in trying to write something like patch() that tries to crawl the content as a diff and make only the minimal changes. Things like events being bound incorrectly to elements, what to do when the structures of the old and new don't match in some breaking way, etc.
Not saying it can't be done but I suspect it's more complexity than we think of typically when using a term like patch. Some of those items (such as transitions) can be pretty straightforward to deal with already.
> Also, there's the matter of performance. Diffing and patching as a single method call implemented natively should be a lot faster than using a bunch of JS code.
Performance and the DOM (especially as typically deployed in an SPA / the "modern" web) don't really go together already, so I'm not convinced that's a particularly compelling argument. Making it first-party on its own is already that compelling argument IMO.
Worth noting too: you could cheat in the html function above and have it directly return content.childNodes, thus reducing the differences between the two examples to simply "patch" vs "replaceChildren".
In your example, are you envisioning that HTMLElement.patch() is doing something different than Element.replaceChildren() or Element.replaceWith()? That'd be one area that wouldn't be addressed with this.
Having it first-party would be lovely but it's already pretty doable.