diff --git a/source b/source index 2d7effe1d68..e6a51869a59 100644 --- a/source +++ b/source @@ -13894,6 +13894,7 @@ https://software.hixie.ch/utilities/js/live-dom-viewer/?%3C%21DOCTYPE%20HTML%3E%
  • autocorrect
  • autofocus
  • contenteditable
  • +
  • contentname
  • dir
  • draggable
  • enterkeyhint
  • @@ -67863,6 +67864,7 @@ not-slash = %x0000-002E / %x0030-10FFFF
    Nothing (for clarification, see example).
    Content attributes:
    Global attributes
    +
    contentmethod
    shadowrootmode
    shadowrootdelegatesfocus
    shadowrootclonable
    @@ -67879,6 +67881,7 @@ interface HTMLTemplateElement : HTMLElement { [HTMLConstructor] constructor(); readonly attribute DocumentFragment content; + [CEReactions] attribute DOMString contentMethod; [CEReactions] attribute DOMString shadowRootMode; [CEReactions, Reflect] attribute boolean shadowRootDelegatesFocus; [CEReactions, Reflect] attribute boolean shadowRootClonable; @@ -67894,6 +67897,60 @@ interface HTMLTemplateElement : HTMLElement {

    In a rendering, the template element represents nothing.

    +

    The contentmethod content attribute is an + enumerated attribute with the following keywords and states:

    + + + + + + + + + +
    Keyword + State + Brief description +
    replace + Replace + Replace the target element itself. +
    replace-children + Replace Children + Replace the child nodes of the target element. +
    append + Append + Append child nodes to the target element. +
    prepend + Prepend + Prepend child nodes to the target element. +
    + +

    The contentmethod attribute's invalid value default and missing value default are both the None state.

    + +

    The contentname + attribute value points to the target for template contentmethod, like an ID attribute.

    + + +

    If specified, the contentname attribute value must equal + the contentname of another element in the same + tree.

    + + +

    Each element has an associated element-or-null content target, which is initially + null.

    + +

    Each element has an associated node-or-null content target first child, which is + initially null.

    + +

    The content target element is used to adjust the parser's insertion + point based on the contentmethod attribute. + The content target first child is used only for the + Prepend state.

    +

    The shadowrootmode content attribute is an enumerated attribute with the following keywords and states:

    @@ -68075,6 +68132,13 @@ interface HTMLTemplateElement : HTMLElement { not a ShadowRoot node; otherwise null.

    +
    +

    The contentMethod IDL attribute must + reflect the contentmethod content + attribute, limited to only known values.

    +
    +

    The shadowRootMode IDL attribute must @@ -68159,6 +68223,62 @@ interface HTMLTemplateElement : HTMLElement {

    +
    + +

    In this example, a template element with a contentmethod 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.

    + +
    <!DOCTYPE html>
    +<html lang="en">
    + <head>
    +  <title>Async recommendation engine</title>
    +  <style>
    +   aside {
    +    /* position the aside where it can grow without causing layout shift or obscuring other content */
    +   }
    +   aside.wireframe {
    +    /* style the wireframe content */
    +   }
    +  </style>
    + </head>
    + <body>
    +  <h1>How to train your cat</h1>
    +  <p>Set realistic goals and don't expect your cat to make a perfect cup of tea
    +  on the first try.</p>
    +  <aside contentname="recommended" class="wireframe">
    +    <p>Recommended reading:</p>
    +    <ul>
    +      <li>...</li>
    +      <li>...</li>
    +      <li>...</li>
    +    </ul>
    +  </aside>
    +  <p>...</p>
    +  <p>Now sit back and enjoy your tea with your cat.</p>
    +
    +  <!-- The server has a potentially long delay at this point. -->
    +
    +  <template contentmethod="replace">
    +   <aside contentname="recommended">
    +    <p>Recommended reading:</p>
    +    <ul>
    +      <li>Cat or butler, which is right for you?</li>
    +      <li>Rewarding good cat behavior</li>
    +      <li>Kettles considered harmful</li>
    +    </ul>
    +   </aside>
    +  </template>
    + </body>
    +</html>
    + +

    The aside element inside the template replaces the original + aside, and since class="wireframe" is not repeated, + the initial wireframe styling is removed when the final content is loaded.

    +
    + +
    @@ -139261,9 +139381,28 @@ dictionary StorageEventInit : EventInit {
  • -

    If the adjusted insertion location is inside a template - element, let it instead be inside the template element's template - contents, after its last child (if any).

    +

    If adjusted insertion location is inside an element whose content + target is non-null:

    + +
      +
    1. Let target be that element's content target.

    2. + +
    3. Let target first child be that element's content target first + child.

    4. + +
    5. +

      If target first child is a node whose parent is target, set + adjusted insertion location to inside target, before target first + child.

      + +

      If target's first child was moved or removed, the element will be + appended to target below. Should the node be dropped instead, or should we update + content target first child and keep inserting before it?

      +
    6. + +
    7. Otherwise, set adjusted insertion location to inside target, after + its last child (if any).

    8. +
  • @@ -139413,6 +139552,86 @@ dictionary StorageEventInit : EventInit { algorithm, then push a new element queue onto element's relevant agent's custom element reactions stack.

  • +
  • +

    If element has a contentname attribute + set to a non-empty value and adjusted insertion location is inside a + template element whose contentmethod attribute is not in the None state:

    + +
      +
    1. Let template be that template element.

    2. + +
    3. +

      Let scope be the second-to-bottommost element on the stack of open + elements.

      + +

      The bottommost node (the current node) is template and + the node above is what would have been template's parent if it was inserted.

      + +

      In the fragment case, scope can be the root + html element of the temporary document. This makes it possible for contentmethod and contentname to modify already-parsed content in the + fragment.

      +
    4. + +
    5. +

      If scope is the body element of its node document, + set scope to its parent.

      + +

      This is to support targeting head and body with a + template inside body.

      + +

      Patching head from within head is not possible + but could easily be supported.

      +
    6. + +
    7. Let target be the first descendant of scope in + tree order with a contentname attribute + value equal to that of element, or null if there is no such element.

    8. + +
    9. +

      If target is an element with the same local name and namespace as + element:

      + +
        +
      1. Let state be the state that template's + contentmethod attribute is in.

      2. + +
      3. +

        If state is Replace:

        + +
          +
        1. Set adjusted insertion location to inside target's parent, + after target.

        2. + +
        3. Remove target from its parent.

        4. +
        +
      4. + +
      5. +

        Otherwise:

        + +
          +
        1. Set element's content target to target.

        2. + +
        3. If state is Replace Children, + remove target's children from target.

        4. + +
        5. If state is Prepend, + set element's content target first child to target's + first child.

        6. +
        + +

        The Append state is + not explicitly handled here, as appending is the default parser behavior.

        +
      6. +
      +
    10. +
    +
  • +
  • Insert element at the adjusted insertion location.

  • If the parser was not created as part of the HTML fragment parsing @@ -140196,9 +140415,13 @@ document.body.appendChild(text);

    If any of the following are false:

    -

    then insert an HTML element for the token.

    +

    then insert an HTML element for the token and return.

  • -

    Otherwise:

    +

    If templateStartTag's shadowrootmode is not in the None state:

    1. Let declarativeShadowHostElement be adjusted current @@ -140289,6 +140514,17 @@ document.body.appendChild(text);

  • + +
  • +

    Otherwise, if templateStartTag's contentmethod is not in the None state:

    + +
      +
    1. Insert a foreign element for templateStartTag, with HTML + namespace and true.

    2. +
    +
  • @@ -152714,6 +152950,19 @@ interface External { Whether the element is editable "true"; "plaintext-only"; "false" + + contentmethod + template + Enables out-of-order streaming + "replace"; + "replace-children"; + "append"; + "prepend" + + contentname + HTML elements + Unique string to target what contentmethod affects + Text* controls audio;