So I have an incomplete PR for declarative shadow DOM support in parse5, there is now a new proposed API with implementation in Chrome beta for <template for> that similarly has behavior wherein the template gets removed and the contents get put somewhere else during parsing.
I do have interest in implementing support for some of these proposals still, but I would like to ask what the general approach that would be preferable for parse5 going forward with such proposals. In particular, should we implement the template behavior as spec-ed which mean whenever new parts of these proposals are added we have to keep changing the parse5 behavior.
Alternatively would it be preferable instead to just implement the necessary hooks for changing the insertion location (and adding additional children for serialization)? Whoever implements the tree adapter would be responsible for detecting such templates and changing the parsing behaviour themselves, but it does mean that there is no need to wait for parse5 to support future proposals to be able to implement them.
Or possibly some combination of the above? (e.g. Supporting declarative shadow roots directly, while also allowing general hooks for changing the insertion target)
cc @43081j
Just to show a difference, in my current incomplete PR, declarative shadow dom would be supported essentially just by providing the appropriate tree adapter methods:
class MyTreeAdapter {
// ...rest of tree adapter
// Called when a <template shadowrootmode=""> is encountered
createDeclarativeShadowRoot(
element: Element,
shadowRootInit: { ...other shadowroot attrs },
): ShadowRoot | null {}
// Called during serialization so that a <template shadowrootmode=""> can be created if appropriate
getShadowRoot(element: Element): ShadowRoot | null {}
// Called to check if shadow root mode is serializable
getShadowRootInit(shadowRoot: ShadowRoot): { serializable: boolean, ...other shadowroot attrs } {}
}
In the alternative approach, instead we would leave the tree adapter to read the attributes and deal with creating shadow roots / insertion targets themselves:
class TemplateElement extends Element {
_insertionTarget: ParentNode | null;
_insertionStartMarker: ChildNode | null;
_insertionEndMarker: ChildNode | null;
}
class MyTreeAdapter {
// Gets called after createElement, if the element has an insertion target then parse5 will insert
// nodes there instead
getInsertionTarget(template: TemplateElement): { target: ParentNode | null, startMarker: ChildNode | null, endMarker: ChildNode | null } | null {
// get targets from template
}
#createTemplateElement(attrs: Attr[], parentNode: ParentNode | null): TemplateElement {
const template = new TemplateElement();
if (attrs.some(attr => attr.name === "for")) {
// find relevant markers, and set _insertion{Target,StartMarker,
} else if (attrs.some(attr => attr.name === "shadowrootmode")) {
// if parentNode is an element, create a shadow root using other shadowroot attrs
// and set _insertionTarget to the shadow root
}
return template;
}
// We get a new parentNode argument to createElement so that we can get the element to attach
// declarative shadow roots to
createElement(elementName: string, namespace: NS, attrs: Attr[], parentNode: ParentNode | null) {
if (elementName === "template" && namespace === HTML_NS) {
return this.#createTemplateElement(attrs);
}
// create element normally
}
// Primarily for serializing declarative shadow roots
// but flexible if declarative templates or anything adds
// additional markers or the like
getExtraPrependedChildren(element: Element): ChildNode[] {
if (element._shadowRoot) {
const template = new TemplateElement();
template.setAttribute('shadowrootmode', element._shadowRoot.mode);
// ...other shadow root attrs;
return [template];
}
return [];
}
So I have an incomplete PR for declarative shadow DOM support in
parse5, there is now a new proposed API with implementation in Chrome beta for<template for>that similarly has behavior wherein the template gets removed and the contents get put somewhere else during parsing.I do have interest in implementing support for some of these proposals still, but I would like to ask what the general approach that would be preferable for
parse5going forward with such proposals. In particular, should we implement the template behavior as spec-ed which mean whenever new parts of these proposals are added we have to keep changing theparse5behavior.Alternatively would it be preferable instead to just implement the necessary hooks for changing the insertion location (and adding additional children for serialization)? Whoever implements the tree adapter would be responsible for detecting such templates and changing the parsing behaviour themselves, but it does mean that there is no need to wait for
parse5to support future proposals to be able to implement them.Or possibly some combination of the above? (e.g. Supporting declarative shadow roots directly, while also allowing general hooks for changing the insertion target)
cc @43081j
Just to show a difference, in my current incomplete PR, declarative shadow dom would be supported essentially just by providing the appropriate tree adapter methods:
In the alternative approach, instead we would leave the tree adapter to read the attributes and deal with creating shadow roots / insertion targets themselves: