diff --git a/src/processors.ts b/src/processors.ts index 9146b54..60ab25c 100644 --- a/src/processors.ts +++ b/src/processors.ts @@ -1,5 +1,6 @@ import type {TemplatePart, TemplateTypeInit} from './types.js' -import type {TemplateInstance} from './template-instance.js' +import {TemplateInstance} from './template-instance.js' +import {InnerTemplatePart} from './inner-template-part.js' import {AttributeTemplatePart} from './attribute-template-part.js' type PartProcessor = (part: TemplatePart, value: unknown, state: unknown) => void @@ -9,7 +10,9 @@ export function createProcessor(processPart: PartProcessor): TemplateTypeInit { processCallback(_: TemplateInstance, parts: Iterable, state: unknown): void { if (typeof state !== 'object' || !state) return for (const part of parts) { - if (part.expression in state) { + if (part instanceof InnerTemplatePart) { + processPart(part, part.expression, state) + } else if (part.expression in state) { const value = (state as Record)[part.expression] ?? '' processPart(part, value, state) } @@ -18,12 +21,22 @@ export function createProcessor(processPart: PartProcessor): TemplateTypeInit { } } -export function processPropertyIdentity(part: TemplatePart, value: unknown): void { - part.value = value instanceof Node ? value : String(value) +export function processPropertyIdentity(part: TemplatePart, value: unknown, state?: unknown): void { + if (part instanceof InnerTemplatePart) { + const instance = new TemplateInstance(part.template, state) + part.template.content.replaceChildren(instance) + } else { + part.value = value instanceof Node ? value : String(value) + } } -export function processBooleanAttribute(part: TemplatePart, value: unknown): boolean { - if ( +export function processBooleanAttribute(part: TemplatePart, value: unknown, state?: unknown): boolean { + if (part instanceof InnerTemplatePart) { + const instance = new TemplateInstance(part.template, state, propertyIdentityOrBooleanAttribute) + part.template.content.replaceChildren(instance) + + return true + } else if ( typeof value === 'boolean' && part instanceof AttributeTemplatePart && typeof part.element[part.attributeName as keyof Element] === 'boolean' @@ -35,8 +48,10 @@ export function processBooleanAttribute(part: TemplatePart, value: unknown): boo } export const propertyIdentity = createProcessor(processPropertyIdentity) -export const propertyIdentityOrBooleanAttribute = createProcessor((part: TemplatePart, value: unknown) => { - if (!processBooleanAttribute(part, value)) { - processPropertyIdentity(part, value) - } -}) +export const propertyIdentityOrBooleanAttribute = createProcessor( + (part: TemplatePart, value: unknown, state: unknown) => { + if (!processBooleanAttribute(part, value, state)) { + processPropertyIdentity(part, value, state) + } + }, +) diff --git a/src/template-instance.ts b/src/template-instance.ts index a10cc20..28aeffd 100644 --- a/src/template-instance.ts +++ b/src/template-instance.ts @@ -10,13 +10,7 @@ function* collectParts(el: DocumentFragment): Generator { let node while ((node = walker.nextNode())) { if (node instanceof HTMLTemplateElement) { - if (node.hasAttribute('directive')) { - yield new InnerTemplatePart(node) - } else { - for (const part of collectParts(node.content)) { - yield part - } - } + yield new InnerTemplatePart(node) } else if (node instanceof Element && node.hasAttributes()) { for (let i = 0; i < node.attributes.length; i += 1) { const attr = node.attributes.item(i) diff --git a/test/template-instance.ts b/test/template-instance.ts index ad41273..2d203a0 100644 --- a/test/template-instance.ts +++ b/test/template-instance.ts @@ -402,6 +402,24 @@ describe('template-instance', () => { root.replaceChildren(new TemplateInstance(template, {x: 'x', y: false}, processor)) expect(root.innerHTML).to.equal('x') }) + + it('makes outer state available to InnerTemplatePart elements without attributes with default propertyIdentity processing', () => { + let callCount = 0 + const processor = createProcessor((part, value) => { + if (part instanceof InnerTemplatePart && value === part.expression) { + callCount += 1 + processPropertyIdentity(part, value) + } + }) + const template = Object.assign(document.createElement('template'), { + innerHTML: '', + }) + + const root = document.createElement('div') + root.appendChild(new TemplateInstance(template, {x: 'Hello world'}, processor)) + expect(callCount).to.equal(1) + expect(root.innerHTML).to.equal('') + }) }) }) })