Comparing version 0.11.0-dev.2 to 0.11.0-dev.3
@@ -14,20 +14,5 @@ /** | ||
*/ | ||
import { DirectiveFn, NodePart } from '../core.js'; | ||
/** | ||
* A directive that renders the items of an async iterable[1], appending new | ||
* values after previous values, similar to the built-in support for iterables. | ||
* | ||
* Async iterables are objects with a [Symbol.asyncIterator] method, which | ||
* returns an iterator who's `next()` method returns a Promise. When a new | ||
* value is available, the Promise resolves and the value is appended to the | ||
* Part controlled by the directive. If another value other than this | ||
* directive has been set on the Part, the iterable will no longer be listened | ||
* to and new values won't be written to the Part. | ||
* | ||
* [1]: https://github.com/tc39/proposal-async-iteration | ||
* | ||
* @param value An async iterable | ||
* @param mapper An optional function that maps from (value, index) to another | ||
* value. Useful for generating templates for each item in the iterable. | ||
* @deprecated import /directives/async-append.js instead | ||
*/ | ||
export declare const asyncAppend: <T>(value: AsyncIterable<T>, mapper?: ((v: T, index?: number | undefined) => any) | undefined) => DirectiveFn<NodePart>; | ||
export * from '../directives/async-append.js'; |
@@ -14,91 +14,6 @@ /** | ||
*/ | ||
var __asyncValues = (this && this.__asyncValues) || function (o) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var m = o[Symbol.asyncIterator], i; | ||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); | ||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } | ||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } | ||
}; | ||
import { directive, NodePart } from '../core.js'; | ||
/** | ||
* A directive that renders the items of an async iterable[1], appending new | ||
* values after previous values, similar to the built-in support for iterables. | ||
* | ||
* Async iterables are objects with a [Symbol.asyncIterator] method, which | ||
* returns an iterator who's `next()` method returns a Promise. When a new | ||
* value is available, the Promise resolves and the value is appended to the | ||
* Part controlled by the directive. If another value other than this | ||
* directive has been set on the Part, the iterable will no longer be listened | ||
* to and new values won't be written to the Part. | ||
* | ||
* [1]: https://github.com/tc39/proposal-async-iteration | ||
* | ||
* @param value An async iterable | ||
* @param mapper An optional function that maps from (value, index) to another | ||
* value. Useful for generating templates for each item in the iterable. | ||
* @deprecated import /directives/async-append.js instead | ||
*/ | ||
export const asyncAppend = (value, mapper) => directive(async (part) => { | ||
var e_1, _a; | ||
// If we've already set up this particular iterable, we don't need | ||
// to do anything. | ||
if (value === part._value) { | ||
return; | ||
} | ||
part._value = value; | ||
// We keep track of item Parts across iterations, so that we can | ||
// share marker nodes between consecutive Parts. | ||
let itemPart; | ||
let i = 0; | ||
try { | ||
for (var value_1 = __asyncValues(value), value_1_1; value_1_1 = await value_1.next(), !value_1_1.done;) { | ||
let v = value_1_1.value; | ||
// When we get the first value, clear the part. This lets the previous | ||
// value display until we can replace it. | ||
if (i === 0) { | ||
part.clear(); | ||
} | ||
// Check to make sure that value is the still the current value of | ||
// the part, and if not bail because a new value owns this part | ||
if (part._value !== value) { | ||
break; | ||
} | ||
// As a convenience, because functional-programming-style | ||
// transforms of iterables and async iterables requires a library, | ||
// we accept a mapper function. This is especially convenient for | ||
// rendering a template for each item. | ||
if (mapper !== undefined) { | ||
v = mapper(v, i); | ||
} | ||
// Like with sync iterables, each item induces a Part, so we need | ||
// to keep track of start and end nodes for the Part. | ||
// Note: Because these Parts are not updatable like with a sync | ||
// iterable (if we render a new value, we always clear), it may | ||
// be possible to optimize away the Parts and just re-use the | ||
// Part.setValue() logic. | ||
let itemStartNode = part.startNode; | ||
// Check to see if we have a previous item and Part | ||
if (itemPart !== undefined) { | ||
// Create a new node to separate the previous and next Parts | ||
itemStartNode = document.createComment(''); | ||
// itemPart is currently the Part for the previous item. Set | ||
// it's endNode to the node we'll use for the next Part's | ||
// startNode. | ||
itemPart.endNode = itemStartNode; | ||
part.endNode.parentNode.insertBefore(itemStartNode, part.endNode); | ||
} | ||
itemPart = new NodePart(part.templateFactory); | ||
itemPart.insertAfterNode(itemStartNode); | ||
itemPart.setValue(v); | ||
itemPart.commit(); | ||
i++; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (value_1_1 && !value_1_1.done && (_a = value_1.return)) await _a.call(value_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
}); | ||
export * from '../directives/async-append.js'; | ||
//# sourceMappingURL=async-append.js.map |
@@ -14,21 +14,5 @@ /** | ||
*/ | ||
import { DirectiveFn, NodePart } from '../core.js'; | ||
/** | ||
* A directive that renders the items of an async iterable[1], replacing | ||
* previous values with new values, so that only one value is ever rendered | ||
* at a time. | ||
* | ||
* Async iterables are objects with a [Symbol.asyncIterator] method, which | ||
* returns an iterator who's `next()` method returns a Promise. When a new | ||
* value is available, the Promise resolves and the value is rendered to the | ||
* Part controlled by the directive. If another value other than this | ||
* directive has been set on the Part, the iterable will no longer be listened | ||
* to and new values won't be written to the Part. | ||
* | ||
* [1]: https://github.com/tc39/proposal-async-iteration | ||
* | ||
* @param value An async iterable | ||
* @param mapper An optional function that maps from (value, index) to another | ||
* value. Useful for generating templates for each item in the iterable. | ||
* @deprecated import /directives/async-replace.js instead | ||
*/ | ||
export declare const asyncReplace: <T>(value: AsyncIterable<T>, mapper?: ((v: T, index?: number | undefined) => any) | undefined) => DirectiveFn<NodePart>; | ||
export * from '../directives/async-replace.js'; |
@@ -14,74 +14,6 @@ /** | ||
*/ | ||
var __asyncValues = (this && this.__asyncValues) || function (o) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var m = o[Symbol.asyncIterator], i; | ||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); | ||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } | ||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } | ||
}; | ||
import { directive, NodePart } from '../core.js'; | ||
/** | ||
* A directive that renders the items of an async iterable[1], replacing | ||
* previous values with new values, so that only one value is ever rendered | ||
* at a time. | ||
* | ||
* Async iterables are objects with a [Symbol.asyncIterator] method, which | ||
* returns an iterator who's `next()` method returns a Promise. When a new | ||
* value is available, the Promise resolves and the value is rendered to the | ||
* Part controlled by the directive. If another value other than this | ||
* directive has been set on the Part, the iterable will no longer be listened | ||
* to and new values won't be written to the Part. | ||
* | ||
* [1]: https://github.com/tc39/proposal-async-iteration | ||
* | ||
* @param value An async iterable | ||
* @param mapper An optional function that maps from (value, index) to another | ||
* value. Useful for generating templates for each item in the iterable. | ||
* @deprecated import /directives/async-replace.js instead | ||
*/ | ||
export const asyncReplace = (value, mapper) => directive(async (part) => { | ||
var e_1, _a; | ||
// If we've already set up this particular iterable, we don't need | ||
// to do anything. | ||
if (value === part._value) { | ||
return; | ||
} | ||
// We nest a new part to keep track of previous item values separately | ||
// of the iterable as a value itself. | ||
const itemPart = new NodePart(part.templateFactory); | ||
part._value = itemPart; | ||
let i = 0; | ||
try { | ||
for (var value_1 = __asyncValues(value), value_1_1; value_1_1 = await value_1.next(), !value_1_1.done;) { | ||
let v = value_1_1.value; | ||
// When we get the first value, clear the part. This let's the | ||
// previous value display until we can replace it. | ||
if (i === 0) { | ||
part.clear(); | ||
itemPart.appendIntoPart(part); | ||
} | ||
// Check to make sure that value is the still the current value of | ||
// the part, and if not bail because a new value owns this part | ||
if (part._value !== itemPart) { | ||
break; | ||
} | ||
// As a convenience, because functional-programming-style | ||
// transforms of iterables and async iterables requires a library, | ||
// we accept a mapper function. This is especially convenient for | ||
// rendering a template for each item. | ||
if (mapper !== undefined) { | ||
v = mapper(v, i); | ||
} | ||
itemPart.setValue(v); | ||
itemPart.commit(); | ||
i++; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (value_1_1 && !value_1_1.done && (_a = value_1.return)) await _a.call(value_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
}); | ||
export * from '../directives/async-replace.js'; | ||
//# sourceMappingURL=async-replace.js.map |
@@ -14,5 +14,7 @@ /** | ||
*/ | ||
import { Part, SVGTemplateResult, TemplateProcessor, TemplateResult } from '../core.js'; | ||
export { render } from '../core.js'; | ||
export { BooleanAttributePart, EventPart } from '../lit-html.js'; | ||
import { Part } from './parts.js'; | ||
import { TemplateProcessor } from './template-processor.js'; | ||
import { SVGTemplateResult, TemplateResult } from './template-result.js'; | ||
export { BooleanAttributePart, EventPart } from './parts.js'; | ||
export { render } from './render.js'; | ||
/** | ||
@@ -19,0 +21,0 @@ * Interprets a template literal as a lit-extended HTML template. |
@@ -14,6 +14,7 @@ /** | ||
*/ | ||
import { AttributeCommitter, SVGTemplateResult, TemplateProcessor, TemplateResult } from '../core.js'; | ||
import { BooleanAttributePart, EventPart, PropertyCommitter } from '../lit-html.js'; | ||
export { render } from '../core.js'; | ||
export { BooleanAttributePart, EventPart } from '../lit-html.js'; | ||
import { AttributeCommitter, BooleanAttributePart, EventPart, PropertyCommitter } from './parts.js'; | ||
import { TemplateProcessor } from './template-processor.js'; | ||
import { SVGTemplateResult, TemplateResult } from './template-result.js'; | ||
export { BooleanAttributePart, EventPart } from './parts.js'; | ||
export { render } from './render.js'; | ||
/** | ||
@@ -20,0 +21,0 @@ * Interprets a template literal as a lit-extended HTML template. |
@@ -14,3 +14,3 @@ /** | ||
*/ | ||
import { Template } from '../core.js'; | ||
import { Template } from './template.js'; | ||
/** | ||
@@ -17,0 +17,0 @@ * Removes the list of nodes from a Template safely. In addition to removing |
@@ -14,3 +14,3 @@ /** | ||
*/ | ||
import { isTemplatePartActive } from '../core.js'; | ||
import { isTemplatePartActive } from './template.js'; | ||
const walkerNodeFilter = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT; | ||
@@ -17,0 +17,0 @@ /** |
@@ -14,6 +14,5 @@ /** | ||
*/ | ||
import { DirectiveFn, NodePart } from '../core.js'; | ||
export declare type KeyFn<T> = (item: T) => any; | ||
export declare type ItemTemplate<T> = (item: T, index: number) => any; | ||
export declare function repeat<T>(items: T[], keyFn: KeyFn<T>, template: ItemTemplate<T>): DirectiveFn<NodePart>; | ||
export declare function repeat<T>(items: T[], template: ItemTemplate<T>): DirectiveFn<NodePart>; | ||
/** | ||
* @deprecated import /directives/repeat.js instead | ||
*/ | ||
export * from '../directives/repeat.js'; |
@@ -14,79 +14,6 @@ /** | ||
*/ | ||
import { directive, NodePart, removeNodes, reparentNodes } from '../core.js'; | ||
const keyMapCache = new WeakMap(); | ||
function cleanMap(part, key, map) { | ||
if (!part.startNode.parentNode) { | ||
map.delete(key); | ||
} | ||
} | ||
export function repeat(items, keyFnOrTemplate, template) { | ||
let keyFn; | ||
if (arguments.length === 2) { | ||
template = keyFnOrTemplate; | ||
} | ||
else if (arguments.length === 3) { | ||
keyFn = keyFnOrTemplate; | ||
} | ||
return directive((part) => { | ||
let keyMap = keyMapCache.get(part); | ||
if (keyMap === undefined) { | ||
keyMap = new Map(); | ||
keyMapCache.set(part, keyMap); | ||
} | ||
const container = part.startNode.parentNode; | ||
let index = -1; | ||
let currentMarker = part.startNode.nextSibling; | ||
for (const item of items) { | ||
let result; | ||
let key; | ||
try { | ||
++index; | ||
result = template(item, index); | ||
key = keyFn ? keyFn(item) : index; | ||
} | ||
catch (e) { | ||
console.error(e); | ||
continue; | ||
} | ||
// Try to reuse a part | ||
let itemPart = keyMap.get(key); | ||
if (itemPart === undefined) { | ||
// TODO(justinfagnani): We really want to avoid manual marker creation | ||
// here and instead use something like part.insertBeforePart(). This | ||
// requires a little refactoring, like iterating through values and | ||
// existing parts like NodePart#_setIterable does. We can also remove | ||
// keyMapCache and use part._value instead. | ||
// But... repeat() is badly in need of rewriting, so we'll do this for | ||
// now and revisit soon. | ||
const marker = document.createComment(''); | ||
const endNode = document.createComment(''); | ||
container.insertBefore(marker, currentMarker); | ||
container.insertBefore(endNode, currentMarker); | ||
itemPart = new NodePart(part.templateFactory); | ||
itemPart.insertAfterNode(marker); | ||
if (key !== undefined) { | ||
keyMap.set(key, itemPart); | ||
} | ||
} | ||
else if (currentMarker !== itemPart.startNode) { | ||
// Existing part in the wrong position | ||
const end = itemPart.endNode.nextSibling; | ||
if (currentMarker !== end) { | ||
reparentNodes(container, itemPart.startNode, end, currentMarker); | ||
} | ||
} | ||
else { | ||
// else part is in the correct position already | ||
currentMarker = itemPart.endNode.nextSibling; | ||
} | ||
itemPart.setValue(result); | ||
itemPart.commit(); | ||
} | ||
// Cleanup | ||
if (currentMarker !== part.endNode) { | ||
removeNodes(container, currentMarker, part.endNode); | ||
keyMap.forEach(cleanMap); | ||
} | ||
}); | ||
} | ||
/** | ||
* @deprecated import /directives/repeat.js instead | ||
*/ | ||
export * from '../directives/repeat.js'; | ||
//# sourceMappingURL=repeat.js.map |
@@ -14,4 +14,4 @@ /** | ||
*/ | ||
import { TemplateResult } from '../core.js'; | ||
export { html, svg, TemplateResult } from '../core.js'; | ||
import { TemplateResult } from './template-result.js'; | ||
export { html, svg, TemplateResult } from '../lit-html.js'; | ||
declare global { | ||
@@ -18,0 +18,0 @@ interface Window { |
@@ -14,5 +14,8 @@ /** | ||
*/ | ||
import { removeNodes, Template, templateCaches, TemplateInstance } from '../core.js'; | ||
import { removeNodes } from './dom.js'; | ||
import { insertNodeIntoTemplate, removeNodesFromTemplate } from './modify-template.js'; | ||
export { html, svg, TemplateResult } from '../core.js'; | ||
import { templateCaches } from './template-factory.js'; | ||
import { TemplateInstance } from './template-instance.js'; | ||
import { Template } from './template.js'; | ||
export { html, svg, TemplateResult } from '../lit-html.js'; | ||
// Get a key to lookup in `templateCaches`. | ||
@@ -19,0 +22,0 @@ const getTemplateCacheKey = (type, scopeName) => `${type}--${scopeName}`; |
@@ -14,3 +14,5 @@ /** | ||
*/ | ||
import { DirectiveFn, NodePart } from '../core.js'; | ||
export declare const unsafeHTML: (value: any) => DirectiveFn<NodePart>; | ||
/** | ||
* @deprecated import /directives/unsafe-html.js instead | ||
*/ | ||
export * from '../directives/unsafe-html.js'; |
@@ -14,23 +14,6 @@ /** | ||
*/ | ||
import { _isPrimitiveValue, directive } from '../core.js'; | ||
/** | ||
* Renders the result as HTML, rather than text. | ||
* | ||
* Note, this is unsafe to use with any user-provided input that hasn't been | ||
* sanitized or escaped, as it may lead to cross-site-scripting | ||
* vulnerabilities. | ||
* @deprecated import /directives/unsafe-html.js instead | ||
*/ | ||
const previousValues = new WeakMap(); | ||
export const unsafeHTML = (value) => directive((part) => { | ||
// Dirty check primitive values | ||
const previousValue = previousValues.get(part); | ||
if (previousValue === value && _isPrimitiveValue(value)) { | ||
return; | ||
} | ||
// Use a <template> to parse HTML into Nodes | ||
const tmp = document.createElement('template'); | ||
tmp.innerHTML = value; | ||
part.setValue(document.importNode(tmp.content, true)); | ||
previousValues.set(part, value); | ||
}); | ||
export * from '../directives/unsafe-html.js'; | ||
//# sourceMappingURL=unsafe-html.js.map |
@@ -14,6 +14,5 @@ /** | ||
*/ | ||
import { DirectiveFn, NodePart } from '../core.js'; | ||
/** | ||
* Display `defaultContent` until `promise` resolves. | ||
* @deprecated import /directives/until.js instead | ||
*/ | ||
export declare const until: (promise: Promise<any>, defaultContent: any) => DirectiveFn<NodePart>; | ||
export * from '../directives/until.js'; |
@@ -14,11 +14,6 @@ /** | ||
*/ | ||
import { directive } from '../core.js'; | ||
/** | ||
* Display `defaultContent` until `promise` resolves. | ||
* @deprecated import /directives/until.js instead | ||
*/ | ||
export const until = (promise, defaultContent) => directive((part) => { | ||
part.setValue(defaultContent); | ||
part.commit(); | ||
part.setValue(promise); | ||
}); | ||
export * from '../directives/until.js'; | ||
//# sourceMappingURL=until.js.map |
@@ -14,88 +14,21 @@ /** | ||
*/ | ||
import { AttributeCommitter, AttributePart, Part, SVGTemplateResult, TemplateProcessor, TemplateResult } from './core.js'; | ||
export * from './core.js'; | ||
import { SVGTemplateResult, TemplateResult } from './lib/template-result.js'; | ||
export * from './lib/template-result.js'; | ||
export * from './lib/template.js'; | ||
export * from './lib/template-processor.js'; | ||
export * from './lib/template-instance.js'; | ||
export * from './lib/parts.js'; | ||
export * from './lib/dom.js'; | ||
export * from './lib/directive.js'; | ||
export * from './lib/render.js'; | ||
export * from './lib/template-factory.js'; | ||
/** | ||
* Interprets a template literal as a lit-html HTML template. | ||
* Interprets a template literal as an HTML template that can efficiently | ||
* render to and update a container. | ||
*/ | ||
export declare const html: (strings: TemplateStringsArray, ...values: any[]) => TemplateResult; | ||
/** | ||
* Interprets a template literal as a lit-html SVG template. | ||
* Interprets a template literal as an SVG template that can efficiently | ||
* render to and update a container. | ||
*/ | ||
export declare const svg: (strings: TemplateStringsArray, ...values: any[]) => SVGTemplateResult; | ||
/** | ||
* A PartCallback which allows templates to set properties, declarative | ||
* event handlers, and boolean attributes. | ||
* | ||
* Properties are set by prefixing an attribute name with `.`. | ||
* | ||
* Attribute names in lit-html templates preserve case, so properties are case | ||
* sensitive. If an expression takes up an entire attribute value, then the | ||
* property is set to that value. If an expression is interpolated with a string | ||
* or other expressions then the property is set to the string result of the | ||
* interpolation. | ||
* | ||
* Example: | ||
* | ||
* html`<input .value=${value}>` | ||
* | ||
* Event handlers are set by prefixing an attribute name with `@`. | ||
* | ||
* Example: | ||
* | ||
* html`<button @click=${(e)=> this.onClickHandler(e)}>Buy Now</button>` | ||
* | ||
* Boolean attributes are set by prepending `?` to an attribute name. | ||
* | ||
* Example: | ||
* | ||
* html`<input type="checkbox" ?checked=${value}>` | ||
*/ | ||
export declare class LitTemplateProcessor extends TemplateProcessor { | ||
handleAttributeExpressions(element: Element, name: string, strings: string[]): Part[]; | ||
} | ||
export declare const templateProcessor: LitTemplateProcessor; | ||
/** | ||
* Implements a boolean attribute, roughly as defined in the HTML | ||
* specification. | ||
* | ||
* If the value is truthy, then the attribute is present with a value of | ||
* ''. If the value is falsey, the attribute is removed. | ||
*/ | ||
export declare class BooleanAttributePart implements Part { | ||
element: Element; | ||
name: string; | ||
strings: string[]; | ||
_value: any; | ||
_pendingValue: any; | ||
constructor(element: Element, name: string, strings: string[]); | ||
setValue(value: any): void; | ||
commit(): void; | ||
} | ||
/** | ||
* Sets attribute values for PropertyParts, so that the value is only set once | ||
* even if there are multiple parts for a property. | ||
* | ||
* If an expression controls the whole property value, then the value is simply | ||
* assigned to the property under control. If there are string literals or | ||
* multiple expressions, then the strings are expressions are interpolated into | ||
* a string first. | ||
*/ | ||
export declare class PropertyCommitter extends AttributeCommitter { | ||
single: boolean; | ||
constructor(element: Element, name: string, strings: string[]); | ||
protected _createPart(): PropertyPart; | ||
_getValue(): any; | ||
commit(): void; | ||
} | ||
export declare class PropertyPart extends AttributePart { | ||
} | ||
export declare class EventPart implements Part { | ||
element: Element; | ||
eventName: string; | ||
_value: any; | ||
_pendingValue: any; | ||
constructor(element: Element, eventName: string); | ||
setValue(value: any): void; | ||
commit(): void; | ||
handleEvent(event: Event): void; | ||
} |
182
lit-html.js
@@ -14,172 +14,22 @@ /** | ||
*/ | ||
import { AttributeCommitter, AttributePart, isDirective, noChange, SVGTemplateResult, TemplateProcessor, TemplateResult } from './core.js'; | ||
export * from './core.js'; | ||
import { SVGTemplateResult, TemplateResult } from './lib/template-result.js'; | ||
export * from './lib/template-result.js'; | ||
export * from './lib/template.js'; | ||
export * from './lib/template-processor.js'; | ||
export * from './lib/template-instance.js'; | ||
export * from './lib/parts.js'; | ||
export * from './lib/dom.js'; | ||
export * from './lib/directive.js'; | ||
export * from './lib/render.js'; | ||
export * from './lib/template-factory.js'; | ||
/** | ||
* Interprets a template literal as a lit-html HTML template. | ||
* Interprets a template literal as an HTML template that can efficiently | ||
* render to and update a container. | ||
*/ | ||
export const html = (strings, ...values) => new TemplateResult(strings, values, 'html', templateProcessor); | ||
export const html = (strings, ...values) => new TemplateResult(strings, values, 'html'); | ||
/** | ||
* Interprets a template literal as a lit-html SVG template. | ||
* Interprets a template literal as an SVG template that can efficiently | ||
* render to and update a container. | ||
*/ | ||
export const svg = (strings, ...values) => new SVGTemplateResult(strings, values, 'svg', templateProcessor); | ||
/** | ||
* A PartCallback which allows templates to set properties, declarative | ||
* event handlers, and boolean attributes. | ||
* | ||
* Properties are set by prefixing an attribute name with `.`. | ||
* | ||
* Attribute names in lit-html templates preserve case, so properties are case | ||
* sensitive. If an expression takes up an entire attribute value, then the | ||
* property is set to that value. If an expression is interpolated with a string | ||
* or other expressions then the property is set to the string result of the | ||
* interpolation. | ||
* | ||
* Example: | ||
* | ||
* html`<input .value=${value}>` | ||
* | ||
* Event handlers are set by prefixing an attribute name with `@`. | ||
* | ||
* Example: | ||
* | ||
* html`<button @click=${(e)=> this.onClickHandler(e)}>Buy Now</button>` | ||
* | ||
* Boolean attributes are set by prepending `?` to an attribute name. | ||
* | ||
* Example: | ||
* | ||
* html`<input type="checkbox" ?checked=${value}>` | ||
*/ | ||
export class LitTemplateProcessor extends TemplateProcessor { | ||
handleAttributeExpressions(element, name, strings) { | ||
const prefix = name[0]; | ||
if (prefix === '.') { | ||
const comitter = new PropertyCommitter(element, name.slice(1), strings); | ||
return comitter.parts; | ||
} | ||
if (prefix === '@') { | ||
return [new EventPart(element, name.slice(1))]; | ||
} | ||
if (prefix === '?') { | ||
return [new BooleanAttributePart(element, name.slice(1), strings)]; | ||
} | ||
return super.handleAttributeExpressions(element, name, strings); | ||
} | ||
} | ||
export const templateProcessor = new LitTemplateProcessor(); | ||
/** | ||
* Implements a boolean attribute, roughly as defined in the HTML | ||
* specification. | ||
* | ||
* If the value is truthy, then the attribute is present with a value of | ||
* ''. If the value is falsey, the attribute is removed. | ||
*/ | ||
export class BooleanAttributePart { | ||
constructor(element, name, strings) { | ||
this._value = undefined; | ||
this._pendingValue = undefined; | ||
if (strings.length !== 2 || strings[0] !== '' || strings[1] !== '') { | ||
throw new Error('Boolean attributes can only contain a single expression'); | ||
} | ||
this.element = element; | ||
this.name = name; | ||
this.strings = strings; | ||
} | ||
setValue(value) { | ||
this._pendingValue = value; | ||
} | ||
commit() { | ||
while (isDirective(this._pendingValue)) { | ||
const directive = this._pendingValue; | ||
this._pendingValue = noChange; | ||
directive(this); | ||
} | ||
if (this._pendingValue === noChange) { | ||
return; | ||
} | ||
const value = !!this._pendingValue; | ||
if (this._value !== value) { | ||
if (value) { | ||
this.element.setAttribute(this.name, ''); | ||
} | ||
else { | ||
this.element.removeAttribute(this.name); | ||
} | ||
} | ||
this._value = value; | ||
this._pendingValue = noChange; | ||
} | ||
} | ||
/** | ||
* Sets attribute values for PropertyParts, so that the value is only set once | ||
* even if there are multiple parts for a property. | ||
* | ||
* If an expression controls the whole property value, then the value is simply | ||
* assigned to the property under control. If there are string literals or | ||
* multiple expressions, then the strings are expressions are interpolated into | ||
* a string first. | ||
*/ | ||
export class PropertyCommitter extends AttributeCommitter { | ||
constructor(element, name, strings) { | ||
super(element, name, strings); | ||
this.single = | ||
(strings.length === 2 && strings[0] === '' && strings[1] === ''); | ||
} | ||
_createPart() { | ||
return new PropertyPart(this); | ||
} | ||
_getValue() { | ||
if (this.single) { | ||
return this.parts[0]._value; | ||
} | ||
return super._getValue(); | ||
} | ||
commit() { | ||
if (this.dirty) { | ||
this.dirty = false; | ||
this.element[this.name] = this._getValue(); | ||
} | ||
} | ||
} | ||
export class PropertyPart extends AttributePart { | ||
} | ||
export class EventPart { | ||
constructor(element, eventName) { | ||
this._value = undefined; | ||
this._pendingValue = undefined; | ||
this.element = element; | ||
this.eventName = eventName; | ||
} | ||
setValue(value) { | ||
this._pendingValue = value; | ||
} | ||
commit() { | ||
while (isDirective(this._pendingValue)) { | ||
const directive = this._pendingValue; | ||
this._pendingValue = noChange; | ||
directive(this); | ||
} | ||
if (this._pendingValue === noChange) { | ||
return; | ||
} | ||
if ((this._pendingValue == null) !== (this._value == null)) { | ||
if (this._pendingValue == null) { | ||
this.element.removeEventListener(this.eventName, this); | ||
} | ||
else { | ||
this.element.addEventListener(this.eventName, this); | ||
} | ||
} | ||
this._value = this._pendingValue; | ||
this._pendingValue = noChange; | ||
} | ||
handleEvent(event) { | ||
if (typeof this._value === 'function') { | ||
this._value.call(this.element, event); | ||
} | ||
else if (typeof this._value.handleEvent === 'function') { | ||
this._value.handleEvent(event); | ||
} | ||
} | ||
} | ||
export const svg = (strings, ...values) => new SVGTemplateResult(strings, values, 'svg'); | ||
//# sourceMappingURL=lit-html.js.map |
{ | ||
"name": "lit-html", | ||
"version": "0.11.0-dev.2", | ||
"version": "0.11.0-dev.3", | ||
"description": "HTML template literals in JavaScript", | ||
@@ -16,6 +16,4 @@ "license": "BSD-3-Clause", | ||
"/lit-html.d.ts", | ||
"/core.js", | ||
"/core.js.map", | ||
"/core.d.ts", | ||
"/lib/", | ||
"/directives/", | ||
"/src/", | ||
@@ -26,7 +24,6 @@ "!/src/test/" | ||
"build": "tsc", | ||
"checksize": "rollup -c ; rm lit-html.bundled.js", | ||
"gen-docs": "typedoc --readme none --mode modules --excludeNotExported --excludePrivate --exclude **/*_test.ts --out ./docs/api ./src", | ||
"test": "npm run build && npm run lint && wct --npm", | ||
"quicktest": "wct -l chrome -p --npm", | ||
"checksize": "uglifyjs core.js -mc --toplevel | gzip -9 | wc -c", | ||
"min": "uglifyjs core.js -mc --toplevel", | ||
"format": "find src test | grep '\\.js$\\|\\.ts$' | xargs clang-format --style=file -i", | ||
@@ -43,2 +40,5 @@ "lint": "tslint --project ./", | ||
"mocha": "^5.2.0", | ||
"rollup": "^0.64.1", | ||
"rollup-plugin-filesize": "^4.0.1", | ||
"rollup-plugin-terser": "^1.0.1", | ||
"tslint": "^5.9.1", | ||
@@ -49,3 +49,3 @@ "typedoc": "^0.11.1", | ||
"wct-browser-legacy": "^1.0.1", | ||
"web-component-tester": "^6.6.0" | ||
"web-component-tester": "^6.8.0" | ||
}, | ||
@@ -52,0 +52,0 @@ "typings": "lit-html.d.ts", |
@@ -15,3 +15,3 @@ /** | ||
import {isTemplatePartActive, Template, TemplatePart} from '../core.js'; | ||
import {isTemplatePartActive, Template, TemplatePart} from './template.js'; | ||
@@ -18,0 +18,0 @@ const walkerNodeFilter = |
@@ -15,7 +15,11 @@ /** | ||
import {removeNodes, Template, templateCaches, TemplateContainer, TemplateInstance, TemplateResult} from '../core.js'; | ||
import {removeNodes} from './dom.js'; | ||
import {insertNodeIntoTemplate, removeNodesFromTemplate} from './modify-template.js'; | ||
import {TemplateContainer} from './render.js'; | ||
import {templateCaches} from './template-factory.js'; | ||
import {TemplateInstance} from './template-instance.js'; | ||
import {TemplateResult} from './template-result.js'; | ||
import {Template} from './template.js'; | ||
export {html, svg, TemplateResult} from '../core.js'; | ||
export {html, svg, TemplateResult} from '../lit-html.js'; | ||
@@ -22,0 +26,0 @@ declare global { |
@@ -15,197 +15,26 @@ /** | ||
import {AttributeCommitter, AttributePart, isDirective, noChange, Part, SVGTemplateResult, TemplateProcessor, TemplateResult} from './core.js'; | ||
import {SVGTemplateResult, TemplateResult} from './lib/template-result.js'; | ||
export * from './core.js'; | ||
export * from './lib/template-result.js'; | ||
export * from './lib/template.js'; | ||
export * from './lib/template-processor.js'; | ||
export * from './lib/template-instance.js'; | ||
export * from './lib/parts.js'; | ||
export * from './lib/dom.js'; | ||
export * from './lib/directive.js'; | ||
export * from './lib/render.js'; | ||
export * from './lib/template-factory.js'; | ||
/** | ||
* Interprets a template literal as a lit-html HTML template. | ||
* Interprets a template literal as an HTML template that can efficiently | ||
* render to and update a container. | ||
*/ | ||
export const html = (strings: TemplateStringsArray, ...values: any[]) => | ||
new TemplateResult(strings, values, 'html', templateProcessor); | ||
new TemplateResult(strings, values, 'html'); | ||
/** | ||
* Interprets a template literal as a lit-html SVG template. | ||
* Interprets a template literal as an SVG template that can efficiently | ||
* render to and update a container. | ||
*/ | ||
export const svg = (strings: TemplateStringsArray, ...values: any[]) => | ||
new SVGTemplateResult(strings, values, 'svg', templateProcessor); | ||
/** | ||
* A PartCallback which allows templates to set properties, declarative | ||
* event handlers, and boolean attributes. | ||
* | ||
* Properties are set by prefixing an attribute name with `.`. | ||
* | ||
* Attribute names in lit-html templates preserve case, so properties are case | ||
* sensitive. If an expression takes up an entire attribute value, then the | ||
* property is set to that value. If an expression is interpolated with a string | ||
* or other expressions then the property is set to the string result of the | ||
* interpolation. | ||
* | ||
* Example: | ||
* | ||
* html`<input .value=${value}>` | ||
* | ||
* Event handlers are set by prefixing an attribute name with `@`. | ||
* | ||
* Example: | ||
* | ||
* html`<button @click=${(e)=> this.onClickHandler(e)}>Buy Now</button>` | ||
* | ||
* Boolean attributes are set by prepending `?` to an attribute name. | ||
* | ||
* Example: | ||
* | ||
* html`<input type="checkbox" ?checked=${value}>` | ||
*/ | ||
export class LitTemplateProcessor extends TemplateProcessor { | ||
handleAttributeExpressions(element: Element, name: string, strings: string[]): | ||
Part[] { | ||
const prefix = name[0]; | ||
if (prefix === '.') { | ||
const comitter = new PropertyCommitter(element, name.slice(1), strings); | ||
return comitter.parts; | ||
} | ||
if (prefix === '@') { | ||
return [new EventPart(element, name.slice(1))]; | ||
} | ||
if (prefix === '?') { | ||
return [new BooleanAttributePart(element, name.slice(1), strings)]; | ||
} | ||
return super.handleAttributeExpressions(element, name, strings); | ||
} | ||
} | ||
export const templateProcessor = new LitTemplateProcessor(); | ||
/** | ||
* Implements a boolean attribute, roughly as defined in the HTML | ||
* specification. | ||
* | ||
* If the value is truthy, then the attribute is present with a value of | ||
* ''. If the value is falsey, the attribute is removed. | ||
*/ | ||
export class BooleanAttributePart implements Part { | ||
element: Element; | ||
name: string; | ||
strings: string[]; | ||
_value: any = undefined; | ||
_pendingValue: any = undefined; | ||
constructor(element: Element, name: string, strings: string[]) { | ||
if (strings.length !== 2 || strings[0] !== '' || strings[1] !== '') { | ||
throw new Error( | ||
'Boolean attributes can only contain a single expression'); | ||
} | ||
this.element = element; | ||
this.name = name; | ||
this.strings = strings; | ||
} | ||
setValue(value: any): void { | ||
this._pendingValue = value; | ||
} | ||
commit() { | ||
while (isDirective(this._pendingValue)) { | ||
const directive = this._pendingValue; | ||
this._pendingValue = noChange; | ||
directive(this); | ||
} | ||
if (this._pendingValue === noChange) { | ||
return; | ||
} | ||
const value = !!this._pendingValue; | ||
if (this._value !== value) { | ||
if (value) { | ||
this.element.setAttribute(this.name, ''); | ||
} else { | ||
this.element.removeAttribute(this.name); | ||
} | ||
} | ||
this._value = value; | ||
this._pendingValue = noChange; | ||
} | ||
} | ||
/** | ||
* Sets attribute values for PropertyParts, so that the value is only set once | ||
* even if there are multiple parts for a property. | ||
* | ||
* If an expression controls the whole property value, then the value is simply | ||
* assigned to the property under control. If there are string literals or | ||
* multiple expressions, then the strings are expressions are interpolated into | ||
* a string first. | ||
*/ | ||
export class PropertyCommitter extends AttributeCommitter { | ||
single: boolean; | ||
constructor(element: Element, name: string, strings: string[]) { | ||
super(element, name, strings); | ||
this.single = | ||
(strings.length === 2 && strings[0] === '' && strings[1] === ''); | ||
} | ||
protected _createPart(): PropertyPart { | ||
return new PropertyPart(this); | ||
} | ||
_getValue() { | ||
if (this.single) { | ||
return this.parts[0]._value; | ||
} | ||
return super._getValue(); | ||
} | ||
commit(): void { | ||
if (this.dirty) { | ||
this.dirty = false; | ||
(this.element as any)[this.name] = this._getValue(); | ||
} | ||
} | ||
} | ||
export class PropertyPart extends AttributePart {} | ||
export class EventPart implements Part { | ||
element: Element; | ||
eventName: string; | ||
_value: any = undefined; | ||
_pendingValue: any = undefined; | ||
constructor(element: Element, eventName: string) { | ||
this.element = element; | ||
this.eventName = eventName; | ||
} | ||
setValue(value: any): void { | ||
this._pendingValue = value; | ||
} | ||
commit() { | ||
while (isDirective(this._pendingValue)) { | ||
const directive = this._pendingValue; | ||
this._pendingValue = noChange; | ||
directive(this); | ||
} | ||
if (this._pendingValue === noChange) { | ||
return; | ||
} | ||
if ((this._pendingValue == null) !== (this._value == null)) { | ||
if (this._pendingValue == null) { | ||
this.element.removeEventListener(this.eventName, this); | ||
} else { | ||
this.element.addEventListener(this.eventName, this); | ||
} | ||
} | ||
this._value = this._pendingValue; | ||
this._pendingValue = noChange; | ||
} | ||
handleEvent(event: Event) { | ||
if (typeof this._value === 'function') { | ||
this._value.call(this.element, event); | ||
} else if (typeof this._value.handleEvent === 'function') { | ||
this._value.handleEvent(event); | ||
} | ||
} | ||
} | ||
new SVGTemplateResult(strings, values, 'svg'); |
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
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
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
322419
102
4707
14
1