lit-html
Advanced tools
Comparing version 0.2.2 to 0.2.3
@@ -53,3 +53,5 @@ /** | ||
export declare abstract class Part { | ||
instance: TemplateInstance; | ||
size?: number; | ||
constructor(instance: TemplateInstance); | ||
abstract setValue(value: any): void; | ||
@@ -62,3 +64,3 @@ protected _getValue(value: any): any; | ||
strings: string[]; | ||
constructor(element: Element, name: string, strings: string[]); | ||
constructor(instance: TemplateInstance, element: Element, name: string, strings: string[]); | ||
setValue(values: any[]): void; | ||
@@ -71,3 +73,3 @@ readonly size: number; | ||
private _previousValue; | ||
constructor(startNode: Node, endNode: Node); | ||
constructor(instance: TemplateInstance, startNode: Node, endNode: Node); | ||
setValue(value: any): void; | ||
@@ -85,12 +87,9 @@ clear(): void; | ||
_createPart(templatePart: TemplatePart, node: Node): Part; | ||
_createInstance(template: Template): TemplateInstance; | ||
} | ||
declare global { | ||
interface Node { | ||
__templateInstance?: { | ||
startNode: Node; | ||
endNode: Node; | ||
}; | ||
__startMarker?: Node; | ||
__templateInstance?: TemplateInstance; | ||
} | ||
} | ||
export {}; |
@@ -160,2 +160,5 @@ /** | ||
export class Part { | ||
constructor(instance) { | ||
this.instance = instance; | ||
} | ||
_getValue(value) { | ||
@@ -179,4 +182,4 @@ if (typeof value === 'function') { | ||
export class AttributePart extends Part { | ||
constructor(element, name, strings) { | ||
super(); | ||
constructor(instance, element, name, strings) { | ||
super(instance); | ||
console.assert(element.nodeType === Node.ELEMENT_NODE); | ||
@@ -212,4 +215,4 @@ this.element = element; | ||
export class NodePart extends Part { | ||
constructor(startNode, endNode) { | ||
super(); | ||
constructor(instance, startNode, endNode) { | ||
super(instance); | ||
this.startNode = startNode; | ||
@@ -232,3 +235,3 @@ this.endNode = endNode; | ||
this.clear(); | ||
instance = new TemplateInstance(value.template); | ||
instance = this.instance._createInstance(value.template); | ||
node = instance._clone(); | ||
@@ -281,3 +284,3 @@ } | ||
} | ||
itemPart = new NodePart(itemStart, itemEnd); | ||
itemPart = new NodePart(this.instance, itemStart, itemEnd); | ||
} | ||
@@ -350,6 +353,6 @@ itemPart.setValue(current.value); | ||
if (templatePart.type === 'attribute') { | ||
return new AttributePart(node, templatePart.name, templatePart.strings); | ||
return new AttributePart(this, node, templatePart.name, templatePart.strings); | ||
} | ||
else if (templatePart.type === 'node') { | ||
return new NodePart(node, node.nextSibling); | ||
return new NodePart(this, node, node.nextSibling); | ||
} | ||
@@ -360,3 +363,6 @@ else { | ||
} | ||
_createInstance(template) { | ||
return new TemplateInstance(template); | ||
} | ||
} | ||
//# sourceMappingURL=lit-html.js.map |
@@ -24,3 +24,3 @@ /** | ||
} | ||
return function (part) { | ||
return (part) => { | ||
let state = stateCache.get(part); | ||
@@ -64,3 +64,3 @@ if (state === undefined) { | ||
container.insertBefore(endNode, currentMarker.nextSibling); | ||
itemPart = new NodePart(currentMarker, endNode); | ||
itemPart = new NodePart(part.instance, currentMarker, endNode); | ||
if (key !== undefined && keyMap !== undefined) { | ||
@@ -67,0 +67,0 @@ keyMap.set(key, itemPart); |
@@ -288,38 +288,41 @@ /** | ||
suite('extensibility', () => { | ||
test('can replace parts with custom types', () => { | ||
// This test demonstrates how a flavored layer on top of lit-html could | ||
// modify the parsed Template to implement different behavior, like setting | ||
// properties instead of attributes. | ||
// Note that because the template parse phase captures the pre-parsed | ||
// attribute names from the template strings, we can retreive the original | ||
// case of the names! | ||
class PropertySettingTemplateInstance extends TemplateInstance { | ||
_createPart(templatePart, node) { | ||
if (templatePart.type === 'attribute') { | ||
return new PropertyPart(node, templatePart.rawName, templatePart.strings); | ||
} | ||
return super._createPart(templatePart, node); | ||
// These tests demonstrate how a flavored layer on top of lit-html could | ||
// modify the parsed Template to implement different behavior, like setting | ||
// properties instead of attributes. | ||
// Note that because the template parse phase captures the pre-parsed | ||
// attribute names from the template strings, we can retreive the original | ||
// case of the names! | ||
class PropertySettingTemplateInstance extends TemplateInstance { | ||
_createPart(templatePart, node) { | ||
if (templatePart.type === 'attribute') { | ||
return new PropertyPart(this, node, templatePart.rawName, templatePart.strings); | ||
} | ||
return super._createPart(templatePart, node); | ||
} | ||
class PropertyPart extends AttributePart { | ||
setValue(values) { | ||
const s = this.strings; | ||
if (s.length === 2 && s[0] === '' && s[s.length - 1] === '') { | ||
// An expression that occupies the whole attribute value will leave | ||
// leading and trailing empty strings. | ||
this.element[this.name] = values[0]; | ||
} | ||
else { | ||
// Interpolation, so interpolate | ||
let text = ''; | ||
for (let i = 0; i < s.length; i++) { | ||
text += s[i]; | ||
if (i < s.length - 1) { | ||
text += values[i]; | ||
} | ||
_createInstance(template) { | ||
return new PropertySettingTemplateInstance(template); | ||
} | ||
} | ||
class PropertyPart extends AttributePart { | ||
setValue(values) { | ||
const s = this.strings; | ||
if (s.length === 2 && s[0] === '' && s[s.length - 1] === '') { | ||
// An expression that occupies the whole attribute value will leave | ||
// leading and trailing empty strings. | ||
this.element[this.name] = values[0]; | ||
} | ||
else { | ||
// Interpolation, so interpolate | ||
let text = ''; | ||
for (let i = 0; i < s.length; i++) { | ||
text += s[i]; | ||
if (i < s.length - 1) { | ||
text += values[i]; | ||
} | ||
this.element[this.name] = text; | ||
} | ||
this.element[this.name] = text; | ||
} | ||
} | ||
} | ||
test('can replace parts with custom types', () => { | ||
const container = document.createElement('div'); | ||
@@ -334,2 +337,12 @@ const t = html `<div someProp="${123}"></div>`; | ||
}); | ||
test('works with nested tempaltes', () => { | ||
const container = document.createElement('div'); | ||
const t = html `${html `<div someProp="${123}"></div>`}`; | ||
const instance = new PropertySettingTemplateInstance(t.template); | ||
const fragment = instance._clone(); | ||
instance.update(t.values); | ||
container.appendChild(fragment); | ||
assert.equal(container.innerHTML, '<div></div>'); | ||
assert.strictEqual(container.firstElementChild.someProp, 123); | ||
}); | ||
}); | ||
@@ -348,3 +361,4 @@ }); | ||
container.appendChild(endNode); | ||
part = new NodePart(startNode, endNode); | ||
const instance = new TemplateInstance(html ``.template); | ||
part = new NodePart(instance, startNode, endNode); | ||
}); | ||
@@ -392,2 +406,9 @@ suite('setValue', () => { | ||
}); | ||
test('accepts nested arrays', () => { | ||
part.setValue([1, [2], 3]); | ||
assert.equal(container.innerHTML, '123'); | ||
assert.deepEqual(['', '1', '', '2', '', '3', ''], Array.from(container.childNodes).map((n) => n.nodeValue)); | ||
assert.strictEqual(container.firstChild, startNode); | ||
assert.strictEqual(container.lastChild, endNode); | ||
}); | ||
test('accepts nested templates', () => { | ||
@@ -422,4 +443,2 @@ part.setValue(html `<h1>${'foo'}</h1>`); | ||
assert.strictEqual(container.lastChild, endNode); | ||
const n2 = container.childNodes.item(2); | ||
const n4 = container.childNodes.item(4); | ||
part.setValue([]); | ||
@@ -453,2 +472,14 @@ assert.equal(container.innerHTML, ''); | ||
}); | ||
test('updates nested arrays', () => { | ||
part.setValue([1, [2], 3]); | ||
assert.equal(container.innerHTML, '123'); | ||
assert.deepEqual(['', '1', '', '2', '', '3', ''], Array.from(container.childNodes).map((n) => n.nodeValue)); | ||
assert.strictEqual(container.firstChild, startNode); | ||
assert.strictEqual(container.lastChild, endNode); | ||
part.setValue([[1], 2, 3]); | ||
assert.equal(container.innerHTML, '123'); | ||
assert.deepEqual(['', '1', '', '2', '', '3', ''], Array.from(container.childNodes).map((n) => n.nodeValue)); | ||
assert.strictEqual(container.firstChild, startNode); | ||
assert.strictEqual(container.lastChild, endNode); | ||
}); | ||
test('updates are stable when called multiple times with templates', () => { | ||
@@ -455,0 +486,0 @@ let value = 'foo'; |
@@ -16,3 +16,3 @@ /** | ||
/// <reference path="../../node_modules/@types/chai/index.d.ts" /> | ||
import { html, NodePart } from '../lit-html.js'; | ||
import { html, NodePart, TemplateInstance } from '../lit-html.js'; | ||
import { repeat } from '../repeat.js'; | ||
@@ -31,6 +31,7 @@ const assert = chai.assert; | ||
container.appendChild(endNode); | ||
part = new NodePart(startNode, endNode); | ||
const instance = new TemplateInstance(html ``.template); | ||
part = new NodePart(instance, startNode, endNode); | ||
}); | ||
suite('keyed', () => { | ||
test('renderes list', () => { | ||
test('renders a list', () => { | ||
const r = repeat([1, 2, 3], (i) => i, (i) => html ` | ||
@@ -37,0 +38,0 @@ <li>item: ${i}</li>`); |
{ | ||
"name": "lit-html", | ||
"version": "0.2.2", | ||
"version": "0.2.3", | ||
"description": "HTML template literals in JavaScript", | ||
@@ -5,0 +5,0 @@ "license": "BSD-3-Clause", |
@@ -178,4 +178,9 @@ /** | ||
export abstract class Part { | ||
instance: TemplateInstance | ||
size?: number; | ||
constructor(instance: TemplateInstance) { | ||
this.instance = instance; | ||
} | ||
abstract setValue(value: any): void; | ||
@@ -205,4 +210,4 @@ | ||
constructor(element: Element, name: string, strings: string[]) { | ||
super(); | ||
constructor(instance: TemplateInstance, element: Element, name: string, strings: string[]) { | ||
super(instance); | ||
console.assert(element.nodeType === Node.ELEMENT_NODE); | ||
@@ -246,4 +251,4 @@ this.element = element; | ||
constructor(startNode: Node, endNode: Node) { | ||
super(); | ||
constructor(instance: TemplateInstance, startNode: Node, endNode: Node) { | ||
super(instance); | ||
this.startNode = startNode; | ||
@@ -267,3 +272,3 @@ this.endNode = endNode; | ||
this.clear(); | ||
instance = new TemplateInstance(value.template); | ||
instance = this.instance._createInstance(value.template); | ||
node = instance._clone(); | ||
@@ -317,3 +322,3 @@ } | ||
} | ||
itemPart = new NodePart(itemStart, itemEnd); | ||
itemPart = new NodePart(this.instance, itemStart, itemEnd); | ||
} | ||
@@ -398,5 +403,5 @@ | ||
if (templatePart.type === 'attribute') { | ||
return new AttributePart(node as Element, templatePart.name!, templatePart.strings!); | ||
return new AttributePart(this, node as Element, templatePart.name!, templatePart.strings!); | ||
} else if (templatePart.type === 'node') { | ||
return new NodePart(node, node.nextSibling!); | ||
return new NodePart(this, node, node.nextSibling!); | ||
} else { | ||
@@ -407,2 +412,6 @@ throw new Error(`unknown part type: ${templatePart.type}`); | ||
_createInstance(template: Template) { | ||
return new TemplateInstance(template); | ||
} | ||
} | ||
@@ -412,8 +421,4 @@ | ||
interface Node { | ||
__templateInstance?: { | ||
startNode: Node; | ||
endNode: Node; | ||
}; | ||
__startMarker?: Node; | ||
__templateInstance?: TemplateInstance; | ||
} | ||
} |
@@ -38,3 +38,3 @@ /** | ||
return function (part: NodePart): any { | ||
return (part: NodePart): any => { | ||
let state = stateCache.get(part); | ||
@@ -81,3 +81,3 @@ if (state === undefined) { | ||
container.insertBefore(endNode, currentMarker.nextSibling); | ||
itemPart = new NodePart(currentMarker, endNode); | ||
itemPart = new NodePart(part.instance, currentMarker, endNode); | ||
if (key !== undefined && keyMap !== undefined) { | ||
@@ -84,0 +84,0 @@ keyMap.set(key, itemPart!); |
@@ -18,3 +18,3 @@ /** | ||
import {html, TemplateResult, TemplatePart, TemplateInstance, NodePart, Part, AttributePart} from '../lit-html.js'; | ||
import {html, TemplateResult, TemplatePart, TemplateInstance, NodePart, Part, AttributePart, Template} from '../lit-html.js'; | ||
@@ -353,44 +353,46 @@ const assert = chai.assert; | ||
test('can replace parts with custom types', () => { | ||
// This test demonstrates how a flavored layer on top of lit-html could | ||
// modify the parsed Template to implement different behavior, like setting | ||
// properties instead of attributes. | ||
// These tests demonstrate how a flavored layer on top of lit-html could | ||
// modify the parsed Template to implement different behavior, like setting | ||
// properties instead of attributes. | ||
// Note that because the template parse phase captures the pre-parsed | ||
// attribute names from the template strings, we can retreive the original | ||
// case of the names! | ||
// Note that because the template parse phase captures the pre-parsed | ||
// attribute names from the template strings, we can retreive the original | ||
// case of the names! | ||
class PropertySettingTemplateInstance extends TemplateInstance { | ||
_createPart(templatePart: TemplatePart, node: Node): Part { | ||
if (templatePart.type === 'attribute') { | ||
return new PropertyPart(node as Element, templatePart.rawName!, templatePart.strings!); | ||
} | ||
return super._createPart(templatePart, node); | ||
class PropertySettingTemplateInstance extends TemplateInstance { | ||
_createPart(templatePart: TemplatePart, node: Node): Part { | ||
if (templatePart.type === 'attribute') { | ||
return new PropertyPart(this, node as Element, templatePart.rawName!, templatePart.strings!); | ||
} | ||
return super._createPart(templatePart, node); | ||
} | ||
_createInstance(template: Template) { | ||
return new PropertySettingTemplateInstance(template); | ||
} | ||
} | ||
class PropertyPart extends AttributePart { | ||
class PropertyPart extends AttributePart { | ||
setValue(values: any[]): void { | ||
const s = this.strings; | ||
if (s.length === 2 && s[0] === '' && s[s.length - 1] === '') { | ||
// An expression that occupies the whole attribute value will leave | ||
// leading and trailing empty strings. | ||
(this.element as any)[this.name] = values[0]; | ||
} else { | ||
// Interpolation, so interpolate | ||
let text = ''; | ||
for (let i = 0; i < s.length; i++) { | ||
text += s[i]; | ||
if (i < s.length - 1) { | ||
text += values[i]; | ||
} | ||
setValue(values: any[]): void { | ||
const s = this.strings; | ||
if (s.length === 2 && s[0] === '' && s[s.length - 1] === '') { | ||
// An expression that occupies the whole attribute value will leave | ||
// leading and trailing empty strings. | ||
(this.element as any)[this.name] = values[0]; | ||
} else { | ||
// Interpolation, so interpolate | ||
let text = ''; | ||
for (let i = 0; i < s.length; i++) { | ||
text += s[i]; | ||
if (i < s.length - 1) { | ||
text += values[i]; | ||
} | ||
(this.element as any)[this.name] = text; | ||
} | ||
(this.element as any)[this.name] = text; | ||
} | ||
} | ||
} | ||
test('can replace parts with custom types', () => { | ||
const container = document.createElement('div'); | ||
@@ -406,2 +408,13 @@ const t = html`<div someProp="${123}"></div>`; | ||
test('works with nested tempaltes', () => { | ||
const container = document.createElement('div'); | ||
const t = html`${html`<div someProp="${123}"></div>`}`; | ||
const instance = new PropertySettingTemplateInstance(t.template); | ||
const fragment = instance._clone(); | ||
instance.update(t.values); | ||
container.appendChild(fragment); | ||
assert.equal(container.innerHTML, '<div></div>'); | ||
assert.strictEqual((container.firstElementChild as any).someProp, 123); | ||
}); | ||
}); | ||
@@ -424,3 +437,4 @@ | ||
container.appendChild(endNode); | ||
part = new NodePart(startNode, endNode); | ||
const instance = new TemplateInstance(html``.template); | ||
part = new NodePart(instance, startNode, endNode); | ||
}); | ||
@@ -479,2 +493,10 @@ | ||
test('accepts nested arrays', () => { | ||
part.setValue([1,[2],3]); | ||
assert.equal(container.innerHTML, '123'); | ||
assert.deepEqual(['', '1', '', '2', '', '3', ''], Array.from(container.childNodes).map((n) => n.nodeValue)); | ||
assert.strictEqual(container.firstChild, startNode); | ||
assert.strictEqual(container.lastChild, endNode); | ||
}); | ||
test('accepts nested templates', () => { | ||
@@ -513,4 +535,2 @@ part.setValue(html`<h1>${'foo'}</h1>`); | ||
assert.strictEqual(container.lastChild, endNode); | ||
const n2 = container.childNodes.item(2); | ||
const n4 = container.childNodes.item(4); | ||
@@ -550,2 +570,17 @@ part.setValue([]); | ||
test('updates nested arrays', () => { | ||
part.setValue([1,[2],3]); | ||
assert.equal(container.innerHTML, '123'); | ||
assert.deepEqual(['', '1', '', '2', '', '3', ''], Array.from(container.childNodes).map((n) => n.nodeValue)); | ||
assert.strictEqual(container.firstChild, startNode); | ||
assert.strictEqual(container.lastChild, endNode); | ||
part.setValue([[1],2,3]); | ||
assert.equal(container.innerHTML, '123'); | ||
assert.deepEqual(['', '1', '', '2', '', '3', ''], Array.from(container.childNodes).map((n) => n.nodeValue)); | ||
assert.strictEqual(container.firstChild, startNode); | ||
assert.strictEqual(container.lastChild, endNode); | ||
}); | ||
test('updates are stable when called multiple times with templates', () => { | ||
@@ -552,0 +587,0 @@ let value = 'foo'; |
@@ -18,3 +18,3 @@ /** | ||
import {html, NodePart} from '../lit-html.js'; | ||
import {html, NodePart, TemplateInstance} from '../lit-html.js'; | ||
import {repeat} from '../repeat.js'; | ||
@@ -37,3 +37,4 @@ | ||
container.appendChild(endNode); | ||
part = new NodePart(startNode, endNode); | ||
const instance = new TemplateInstance(html``.template); | ||
part = new NodePart(instance, startNode, endNode); | ||
}); | ||
@@ -43,3 +44,3 @@ | ||
test('renderes list', () => { | ||
test('renders a list', () => { | ||
const r = repeat([1, 2, 3], (i) => i, (i: number) => html` | ||
@@ -46,0 +47,0 @@ <li>item: ${i}</li>`); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
170477
2553