Skip to content
261 changes: 255 additions & 6 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -13894,6 +13894,7 @@ https://software.hixie.ch/utilities/js/live-dom-viewer/?%3C%21DOCTYPE%20HTML%3E%
<li><code data-x="attr-autocorrect">autocorrect</code></li>
<li><code data-x="attr-fe-autofocus">autofocus</code></li>
<li><code data-x="attr-contenteditable">contenteditable</code></li>
<li><code data-x="attr-contentname">contentname</code></li>
<li><code data-x="attr-dir">dir</code></li>
<li><code data-x="attr-draggable">draggable</code></li>
<li><code data-x="attr-enterkeyhint">enterkeyhint</code></li>
Expand Down Expand Up @@ -67863,6 +67864,7 @@ not-slash = %x0000-002E / %x0030-10FFFF
<dd><span data-x="concept-content-nothing">Nothing</span> (for clarification, <a href="#template-example">see example</a>).</dd>
<dt><span data-x="concept-element-attributes">Content attributes</span>:</dt>
<dd><span>Global attributes</span></dd>
<dd><code data-x="attr-template-contentmethod">contentmethod</code></dd>
<dd><code data-x="attr-template-shadowrootmode">shadowrootmode</code></dd>
<dd><code data-x="attr-template-shadowrootdelegatesfocus">shadowrootdelegatesfocus</code></dd>
<dd><code data-x="attr-template-shadowrootclonable">shadowrootclonable</code></dd>
Expand All @@ -67879,6 +67881,7 @@ interface <dfn interface>HTMLTemplateElement</dfn> : <span>HTMLElement</span> {
[<span>HTMLConstructor</span>] constructor();

readonly attribute <span>DocumentFragment</span> <span data-x="dom-template-content">content</span>;
[<span>CEReactions</span>] attribute DOMString <span data-x="dom-template-contentmethod">contentMethod</span>;
[<span>CEReactions</span>] attribute DOMString <span data-x="dom-template-shadowrootmode">shadowRootMode</span>;
[<span>CEReactions</span>, <span data-x="xattr-Reflect">Reflect</span>] attribute boolean <dfn attribute for="HTMLTemplateElement" data-x="dom-template-shadowrootdelegatesfocus">shadowRootDelegatesFocus</dfn>;
[<span>CEReactions</span>, <span data-x="xattr-Reflect">Reflect</span>] attribute boolean <dfn attribute for="HTMLTemplateElement" data-x="dom-template-shadowrootclonable">shadowRootClonable</dfn>;
Expand All @@ -67894,6 +67897,60 @@ interface <dfn interface>HTMLTemplateElement</dfn> : <span>HTMLElement</span> {

<p>In a rendering, the <code>template</code> element <span>represents</span> nothing.</p>

<p>The <dfn element-attr for="template"><code
data-x="attr-template-contentmethod">contentmethod</code></dfn> content attribute is an
<span>enumerated attribute</span> with the following keywords and states:</p>

<table>
<thead>
<tr>
<th>Keyword
<th>State
<th>Brief description
<tbody>
<tr>
<td><dfn attr-value for="template/contentmethod"><code data-x="attr-contentmethod-replace">replace</code></dfn>
<td><dfn data-x="attr-contentmethod-replace-state">Replace</dfn>
<td>Replace the target element itself.
<tr>
<td><dfn attr-value for="template/contentmethod"><code data-x="attr-contentmethod-replace-children">replace-children</code></dfn>
<td><dfn data-x="attr-contentmethod-replace-children-state">Replace Children</dfn>
<td>Replace the child nodes of the target element.
<tr>
<td><dfn attr-value for="template/contentmethod"><code data-x="attr-contentmethod-append">append</code></dfn>
<td><dfn data-x="attr-contentmethod-append-state">Append</dfn>
<td>Append child nodes to the target element.
<tr>
<td><dfn attr-value for="template/contentmethod"><code data-x="attr-contentmethod-prepend">prepend</code></dfn>
<td><dfn data-x="attr-contentmethod-prepend-state">Prepend</dfn>
<td>Prepend child nodes to the target element.
</table>

<p>The <code data-x="attr-template-contentmethod">contentmethod</code> attribute's <i
data-x="invalid value default">invalid value default</i> and <i data-x="missing value
default">missing value default</i> are both the <dfn
data-x="attr-contentmethod-none-state">None</dfn> state.</p>

<p>The <dfn element-attr for="htmlsvg-global"><code data-x="attr-contentname">contentname</code></dfn>
attribute value points to the target for template contentmethod, like an ID attribute.</p>
<!-- TODO better words, and should this be in another section since it's not for <template>? -->

<p>If specified, the <code data-x="attr-contentname">contentname</code> attribute value must equal
the <code data-x="attr-contentname">contentname</code> of another element in the same
<span>tree</span>.</p>
<!-- TODO: make this non-symmetrical and matching the processing model -->

<p>Each element has an associated element-or-null <dfn>content target</dfn>, which is initially
null.</p>

<p>Each element has an associated node-or-null <dfn>content target first child</dfn>, which is
initially null.</p>

<p class="note">The <span>content target</span> element is used to adjust the parser's insertion
point based on the <code data-x="attr-template-contentmethod">contentmethod</code> attribute.
The <span>content target first child</span> is used only for the
<span data-x="attr-contentmethod-prepend-state">Prepend</span> state.</p>

<p>The <dfn element-attr for="template"><code
data-x="attr-template-shadowrootmode">shadowrootmode</code></dfn> content attribute is an
<span>enumerated attribute</span> with the following keywords and states:</p>
Expand Down Expand Up @@ -68075,6 +68132,13 @@ interface <dfn interface>HTMLTemplateElement</dfn> : <span>HTMLElement</span> {
not a <code>ShadowRoot</code> node; otherwise null.</p>
</div>

<div algorithm>
<p>The <dfn attribute for="HTMLTemplateElement"><code
data-x="dom-template-contentmethod">contentMethod</code></dfn> IDL attribute must
<span>reflect</span> the <code data-x="attr-template-contentmethod">contentmethod</code> content
attribute, <span>limited to only known values</span>.</p>
</div>

<div algorithm>
<p>The <dfn attribute for="HTMLTemplateElement"><code
data-x="dom-template-shadowrootmode">shadowRootMode</code></dfn> IDL attribute must
Expand Down Expand Up @@ -68159,6 +68223,62 @@ interface <dfn interface>HTMLTemplateElement</dfn> : <span>HTMLElement</span> {
</div>


<div class="example">

<p>In this example, a <code>template</code> element with a <code
data-x="attr-template-contentmethod">contentmethod</code> attribute is used to stream a docuemnt
out-of-order, sending fast static content first and recommendations computed async as they become
available on the server.</p>

<pre><code class="html">&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;head>
&lt;title>Async recommendation engine&lt;/title>
&lt;style>
aside {
/* position the aside where it can grow without causing layout shift or obscuring other content */
}
aside.wireframe {
/* style the wireframe content */
}
&lt;/style>
&lt;/head>
&lt;body>
&lt;h1>How to train your cat&lt;/h1>
&lt;p>Set realistic goals and don't expect your cat to make a perfect cup of tea
on the first try.&lt;/p>
&lt;aside contentname="recommended" class="wireframe">
&lt;p>Recommended reading:&lt;/p>
&lt;ul>
&lt;li>...&lt;/li>
&lt;li>...&lt;/li>
&lt;li>...&lt;/li>
&lt;/ul>
&lt;/aside>
&lt;p>...&lt;/p>
&lt;p>Now sit back and enjoy your tea with your cat.&lt;/p>

&lt;!-- The server has a potentially long delay at this point. --&gt;

&lt;template contentmethod="replace">
&lt;aside contentname="recommended">
&lt;p>Recommended reading:&lt;/p>
&lt;ul>
&lt;li>Cat or butler, which is right for you?&lt;/li>
&lt;li>Rewarding good cat behavior&lt;/li>
&lt;li>Kettles considered harmful&lt;/li>
&lt;/ul>
&lt;/aside>
&lt;/template>
&lt;/body>
&lt;/html></code></pre>

<p>The <code>aside</code> element inside the <code>template</code> replaces the original
<code>aside</code>, and since <code data-x="">class="wireframe"</code> is not repeated,
the initial wireframe styling is removed when the final content is loaded.</p>
</div>



<div w-nodev>

Expand Down Expand Up @@ -139261,9 +139381,28 @@ dictionary <dfn dictionary>StorageEventInit</dfn> : <span>EventInit</span> {
</li>

<li>
<p>If the <var>adjusted insertion location</var> is inside a <code>template</code>
element, let it instead be inside the <code>template</code> element's <span>template
contents</span>, after its last child (if any).</p>
<p>If <var>adjusted insertion location</var> is inside an element whose <span>content
target</span> is non-null:</p>

<ol>
<li><p>Let <var>target</var> be that element's <span>content target</span>.</p></li>

<li><p>Let <var>target first child</var> be that element's <span>content target first
child</span>.</p></li>

<li>
<p>If <var>target first child</var> is a node whose parent is <var>target</var>, set
<var>adjusted insertion location</var> to inside <var>target</var>, before <var>target first
child</var>.</p>

<p class="XXX">If <var>target</var>'s first child was moved or removed, the element will be
appended to <var>target</var> below. Should the node be dropped instead, or should we update
<span>content target first child</span> and keep inserting before it?</p>
</li>

<li><p>Otherwise, set <var>adjusted insertion location</var> to inside <var>target</var>, after
its last child (if any).</p></li>
</ol>
</li>

<li>
Expand Down Expand Up @@ -139413,6 +139552,86 @@ dictionary <dfn dictionary>StorageEventInit</dfn> : <span>EventInit</span> {
algorithm</span>, then push a new <span>element queue</span> onto <var>element</var>'s
<span>relevant agent</span>'s <span>custom element reactions stack</span>.</p></li>

<li>
<p>If <var>element</var> has a <code data-x="attr-contentname">contentname</code> attribute
set to a non-empty value and <var>adjusted insertion location</var> is inside a
<code>template</code> element whose <code
data-x="attr-template-contentmethod">contentmethod</code> attribute is not in the <span
data-x="attr-contentmethod-none-state">None</span> state:</p>

<ol>
<li><p>Let <var>template</var> be that <code>template</code> element.</p></li>

<li>
<p>Let <var>scope</var> be the second-to-bottommost element on the <span>stack of open
elements</span>.</p>

<p class="note">The bottommost node (the <span>current node</span>) is <var>template</var> and
the node above is what would have been <var>template</var>'s parent if it was inserted.</p>

<p class="note">In the <span>fragment case</span>, <var>scope</var> can be the root
<code>html</code> element of the temporary document. This makes it possible for <code
data-x="attr-template-contentmethod">contentmethod</code> and <code
data-x="attr-contentname">contentname</code> to modify already-parsed content in the
fragment.</p>
</li>

<li>
<p>If <var>scope</var> is <span>the body element</span> of its <span>node document</span>,
set <var>scope</var> to its parent.</p>

<p class="note">This is to support targeting <code>head</code> and <code>body</code> with a
<code>template</code> inside <code>body</code>.</p>

<p class="XXX">Patching <code>head</code> from within <code>head</code> is not possible
but could easily be supported.</p>
</li>

<li><p>Let <var>target</var> be the first <span>descendant</span> of <var>scope</var> in
<span>tree order</span> with a <code data-x="attr-contentname">contentname</code> attribute
value equal to that of <var>element</var>, or null if there is no such element.</p></li>

<li>
<p>If <var>target</var> is an element with the same local name and namespace as
<var>element</var>:</p>

<ol>
<li><p>Let <var>state</var> be the state that <var>template</var>'s
<code data-x="attr-template-contentmethod">contentmethod</code> attribute is in.</p></li>

<li>
<p>If <var>state</var> is <span data-x="attr-contentmethod-replace-state">Replace</span>:</p>

<ol>
<li><p>Set <var>adjusted insertion location</var> to inside <var>target</var>'s parent,
after <var>target</var>.</p></li>

<li><p>Remove <var>target</var> from its parent.</p></li>
</ol>
</li>

<li>
<p>Otherwise:</p>

<ol>
<li><p>Set <var>element</var>'s <span>content target</span> to <var>target</var>.</p></li>

<li><p>If <var>state</var> is <span data-x="attr-contentmethod-replace-children-state">Replace Children</span>,
remove <var>target</var>'s children from <var>target</var>.</p></li>

<li><p>If <var>state</var> is <span data-x="attr-contentmethod-prepend-state">Prepend</span>,
set <var>element</var>'s <span>content target first child</span> to <var>target</var>'s
<span>first child</span>.</p></li>
</ol>

<p class="note">The <span data-x="attr-contentmethod-append-state">Append</span> state is
not explicitly handled here, as appending is the default parser behavior.</p>
</li>
</ol>
</li>
</ol>
</li>

<li><p>Insert <var>element</var> at the <var>adjusted insertion location</var>.</p></li>

<li><p>If the parser was not created as part of the <span>HTML fragment parsing
Expand Down Expand Up @@ -140196,9 +140415,13 @@ document.body.appendChild(text);
<p>If any of the following are false:</p>

<ul>
<li><var>templateStartTag</var>'s <code
data-x="attr-template-contentmethod">contentmethod</code> is not in the <span
data-x="attr-contentmethod-none-state">None</span> state; or</li>

<li><var>templateStartTag</var>'s <code
data-x="attr-template-shadowrootmode">shadowrootmode</code> is not in the <span
data-x="attr-shadowrootmode-none-state">None</span> state;</li>
data-x="attr-shadowrootmode-none-state">None</span> state; or</li>

<li><var>document</var>'s <span
data-x="concept-document-allow-declarative-shadow-roots">allow declarative shadow
Expand All @@ -140208,11 +140431,13 @@ document.body.appendChild(text);
open elements</span>,</li>
</ul>

<p>then <span>insert an HTML element</span> for the token.</p>
<p>then <span>insert an HTML element</span> for the token and return.</p>
</li>

<li>
<p>Otherwise:</p>
<p>If <var>templateStartTag</var>'s <code
data-x="attr-template-shadowrootmode">shadowrootmode</code> is not in the <span
data-x="attr-shadowrootmode-none-state">None</span> state:</p>

<ol>
<li><p>Let <var>declarativeShadowHostElement</var> be <span>adjusted current
Expand Down Expand Up @@ -140289,6 +140514,17 @@ document.body.appendChild(text);
</li>
</ol>
</li>

<li>
<p>Otherwise, if <var>templateStartTag</var>'s <code
data-x="attr-template-contentmethod">contentmethod</code> is not in the <span
data-x="attr-contentmethod-none-state">None</span> state:</p>

<ol>
<li><p><span>Insert a foreign element</span> for <var>templateStartTag</var>, with <span>HTML
namespace</span> and true.</p></li>
</ol>
</li>
</ol>
</dd>

Expand Down Expand Up @@ -152714,6 +152950,19 @@ interface <dfn interface>External</dfn> {
<td> Whether the element is editable
<td> "<code data-x="">true</code>"; "<code data-x="">plaintext-only</code>";
"<code data-x="">false</code>"
<tr>
<th> <code data-x="">contentmethod</code>
<td> <code data-x="attr-template-contentmethod">template</code>
<td> Enables out-of-order streaming <!-- TODO better words -->
<td> "<code data-x="attr-contentmethod-replace">replace</code>";
"<code data-x="attr-contentmethod-replace-children">replace-children</code>";
"<code data-x="attr-contentmethod-append">append</code>";
"<code data-x="attr-contentmethod-prepend">prepend</code>"
<tr>
<th> <code data-x="">contentname</code>
<td> <span data-x="attr-contentname">HTML elements</span>
<td> Unique string to target what contentmethod affects <!-- TODO better words -->
<td> <a href="#attribute-text">Text</a>*
<tr>
<th> <code data-x="">controls</code>
<td> <code data-x="attr-media-controls">audio</code>;
Expand Down