Skip to content

Commit 79b4ee6

Browse files
committed
Change NodeTemplatePart.replace type signature
Replace `ChildNode` with `Node` in `NodeTemplatePart.replace(...nodes)` signature. According to the [3.2. Template Parts and Custom Template Process Callback][] section of the specification, the `NodeTemplatePart` interface declares `replace(...nodes: Array<string | Node>)`: ```typescript interface NodeTemplatePart : TemplatePart { readonly attribute ContainerNode parentNode; readonly attribute Node? previousSibling; readonly attribute Node? nextSibling; [NewObject] readonly NodeList replacementNodes; void replace((Node or DOMString)... nodes); void replaceHTML(DOMString html); } ``` This commit changes the type signature and adds coverage for replacing a `NodeTemplatePart` with a `DocumentFragment` instance. [3.2. Template Parts and Custom Template Process Callback]: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Template-Instantiation.md#32-template-parts-and-custom-template-process-callback
1 parent 0678eb7 commit 79b4ee6

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

src/node-template-part.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {TemplatePart} from './types.js'
22

3-
const parts = new WeakMap<NodeTemplatePart, ChildNode[]>()
3+
const parts = new WeakMap<NodeTemplatePart, Node[]>()
44
export class NodeTemplatePart implements TemplatePart {
55
constructor(
6-
node: ChildNode,
6+
node: Node,
77
public expression: string,
88
) {
99
parts.set(this, [node])
@@ -29,14 +29,15 @@ export class NodeTemplatePart implements TemplatePart {
2929
return parts.get(this)![parts.get(this)!.length - 1].nextSibling
3030
}
3131

32-
replace(...nodes: Array<string | ChildNode>): void {
33-
const normalisedNodes: ChildNode[] = nodes.map(node => {
32+
replace(...nodes: Array<string | Node>): void {
33+
const normalisedNodes: Node[] = nodes.map(node => {
3434
if (typeof node === 'string') return new Text(node)
3535
return node
3636
})
3737
if (!normalisedNodes.length) normalisedNodes.push(new Text(''))
38-
parts.get(this)![0].before(...normalisedNodes)
39-
for (const part of parts.get(this)!) part.remove()
38+
const node = parts.get(this)![0]
39+
for (const normalisedNode of normalisedNodes) node.parentNode?.insertBefore(normalisedNode, node)
40+
for (const part of parts.get(this)!) part.parentNode?.removeChild(part)
4041
parts.set(this, normalisedNodes)
4142
}
4243
}

test/template-instance.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {expect} from '@open-wc/testing'
22
import {TemplateInstance} from '../src/template-instance'
3-
import type {NodeTemplatePart} from '../src/node-template-part'
3+
import {NodeTemplatePart} from '../src/node-template-part'
44
import {propertyIdentityOrBooleanAttribute, createProcessor} from '../src/processors'
55

66
describe('template-instance', () => {
@@ -238,6 +238,25 @@ describe('template-instance', () => {
238238

239239
describe('edge cases', () => {
240240
describe('NodeTemplatePart', () => {
241+
it('replace supports a DocumentFragment Node that is not a ChildNode', () => {
242+
const template = Object.assign(document.createElement('template'), {
243+
innerHTML: '<div>{{a}}</div>',
244+
})
245+
const {content} = Object.assign(document.createElement('template'), {
246+
innerHTML: 'after',
247+
})
248+
const instance = new TemplateInstance(
249+
template,
250+
{a: 'before'},
251+
createProcessor(part => {
252+
if (part instanceof NodeTemplatePart) part.replace(content)
253+
}),
254+
)
255+
const root = document.createElement('div')
256+
root.appendChild(instance)
257+
expect(root.innerHTML).to.equal('<div>after</div>')
258+
})
259+
241260
it('replaces an empty replace() call with an empty text node', () => {
242261
const template = document.createElement('template')
243262
template.innerHTML = `<div>{{a}}</div>`

0 commit comments

Comments
 (0)