HTML templates literals in JavaScript that enable efficient, expressive HTML templating with incremental DOM updates
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Essential template creation and rendering functionality for building dynamic HTML interfaces with efficient incremental DOM updates.
Creates HTML templates from template literals with embedded expressions.
/**
* Interprets a template literal as an HTML template that can efficiently
* render to and update a container.
* @param strings - Template strings array
* @param values - Template expression values
* @returns Template result for rendering
*/
function html(strings: TemplateStringsArray, ...values: unknown[]): TemplateResult;Usage Examples:
import { html } from 'lit-html';
// Simple template
const greeting = html`<h1>Hello World!</h1>`;
// Template with expressions
const userCard = (name: string, age: number) => html`
<div class="card">
<h2>${name}</h2>
<p>Age: ${age}</p>
</div>
`;
// Conditional content with nothing
const maybeButton = (showButton: boolean) => html`
${showButton ? html`<button>Click me</button>` : nothing}
`;Creates SVG templates for vector graphics content within HTML templates.
/**
* Interprets a template literal as an SVG fragment that can efficiently render
* to and update a container.
* @param strings - Template strings array
* @param values - Template expression values
* @returns SVG template result for rendering
*/
function svg(strings: TemplateStringsArray, ...values: unknown[]): SVGTemplateResult;Usage Examples:
import { html, svg } from 'lit-html';
// SVG fragment for use inside HTML
const icon = (size: number) => svg`
<circle cx="50" cy="50" r="${size}" fill="blue"/>
<text x="50" y="55" text-anchor="middle">Icon</text>
`;
// Use SVG in HTML template
const iconButton = html`
<button>
<svg viewBox="0 0 100 100" width="24" height="24">
${icon(40)}
</svg>
Click me
</button>
`;Creates MathML templates for mathematical notation within HTML templates.
/**
* Interprets a template literal as MathML fragment that can efficiently render
* to and update a container.
* @param strings - Template strings array
* @param values - Template expression values
* @returns MathML template result for rendering
*/
function mathml(strings: TemplateStringsArray, ...values: unknown[]): MathMLTemplateResult;Usage Examples:
import { html, mathml } from 'lit-html';
// Mathematical equation
const quadraticFormula = mathml`
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mo>-</mo>
<mi>b</mi>
<mo>±</mo>
<msqrt>
<mrow>
<msup><mi>b</mi><mn>2</mn></msup>
<mo>-</mo>
<mn>4</mn>
<mi>a</mi>
<mi>c</mi>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mi>a</mi>
</mrow>
</mfrac>
</mrow>
`;
// Use MathML in HTML
const mathExample = html`
<div>
<h3>Quadratic Formula:</h3>
<math>
${quadraticFormula}
</math>
</div>
`;Renders template results to DOM containers with efficient incremental updates.
/**
* Renders a value, usually a lit-html TemplateResult, to the container.
* @param value - Any renderable value, typically a TemplateResult
* @param container - DOM container to render to
* @param options - Optional rendering configuration
* @returns RootPart for managing the rendered content
*/
function render(
value: unknown,
container: HTMLElement | DocumentFragment,
options?: RenderOptions
): RootPart;Usage Examples:
import { html, render } from 'lit-html';
// Basic rendering
const template = html`<h1>Hello World</h1>`;
render(template, document.body);
// Rendering with options
render(template, document.body, {
host: myComponent,
renderBefore: existingElement
});
// Managing the returned RootPart
const part = render(template, container);
part.setConnected(false); // Disconnect async directivesSpecial values for controlling template rendering behavior.
/**
* A sentinel value that signals a ChildPart to fully clear its content.
* Prefer using `nothing` over other falsy values for consistent behavior.
*/
const nothing: unique symbol;
/**
* A sentinel value that signals that a value was handled by a directive and
* should not be written to the DOM.
*/
const noChange: unique symbol;Usage Examples:
import { html, nothing, noChange } from 'lit-html';
// Using nothing for conditional content
const conditionalContent = (show: boolean) => html`
<div>
${show ? html`<p>Visible content</p>` : nothing}
</div>
`;
// Using noChange in custom directives
class MyDirective extends Directive {
render(value: string) {
if (value === this.previousValue) {
return noChange; // Skip update
}
this.previousValue = value;
return value;
}
}interface TemplateResult<T extends ResultType = ResultType> {
readonly strings: TemplateStringsArray;
readonly values: unknown[];
}
type HTMLTemplateResult = TemplateResult<typeof HTML_RESULT>;
type SVGTemplateResult = TemplateResult<typeof SVG_RESULT>;
type MathMLTemplateResult = TemplateResult<typeof MATHML_RESULT>;
interface RenderOptions {
/** An object to use as the `this` value for event listeners */
host?: object;
/** A DOM node before which to render content in the container */
renderBefore?: ChildNode | null;
/** Node used for cloning the template (controls ownerDocument) */
creationScope?: { importNode(node: Node, deep?: boolean): Node };
/** Initial connected state for the top-level part being rendered */
isConnected?: boolean;
}
interface RootPart extends ChildPart {
/** Sets the connection state for AsyncDirectives contained within this root */
setConnected(isConnected: boolean): void;
}Utility for detecting server environments in universal/isomorphic applications.
/**
* A boolean that will be `true` in server environments like Node, and `false`
* in browser environments. Note that your server environment or toolchain must
* support the "node" export condition for this to be `true`.
*/
const isServer: boolean;Usage Examples:
import { isServer } from 'lit-html/is-server.js';
// Conditional behavior based on environment
const template = html`
<div>
${isServer
? html`<p>Rendered on server</p>`
: html`<p>Rendered in browser</p>`
}
</div>
`;
// Skip browser-specific APIs on server
if (!isServer) {
// Safe to use browser APIs
element.focus();
}Security-related functions for controlling value sanitization and DOM safety.
/**
* A function which can sanitize values that will be written to a specific kind
* of DOM sink (property or attribute).
* @param value - The value to sanitize
* @returns The sanitized value to write to the DOM
*/
type ValueSanitizer = (value: unknown) => unknown;
/**
* Factory function that creates a sanitizer for a specific DOM context.
* @param node - The HTML node that is being written to
* @param name - The name of an attribute or property
* @param type - Whether the write is to a property or attribute
* @returns A function that will sanitize values for this context
*/
type SanitizerFactory = (
node: Node,
name: string,
type: 'property' | 'attribute'
) => ValueSanitizer;
/**
* Sets the global sanitizer factory for controlling value sanitization.
* Can only be called once - subsequent calls will throw an error.
* @param sanitizerFactory - Factory function for creating sanitizers
*/
render.setSanitizer = (sanitizerFactory: SanitizerFactory) => void;
/**
* Creates a sanitizer for a specific DOM context using the current global factory.
* @param node - The HTML node context
* @param name - The attribute or property name
* @param type - Whether this is for a property or attribute
* @returns ValueSanitizer function for this context
*/
render.createSanitizer = (
node: Node,
name: string,
type: 'property' | 'attribute'
) => ValueSanitizer;Usage Examples:
import { render } from 'lit-html';
// Set up a custom sanitizer factory
render.setSanitizer((node, name, type) => {
if (type === 'attribute' && name === 'src') {
// Custom sanitization for src attributes
return (value) => {
const url = String(value);
// Only allow https URLs
return url.startsWith('https://') ? url : '';
};
}
if (type === 'property' && name === 'innerHTML') {
// Sanitize innerHTML property
return (value) => {
// Remove script tags (basic example)
return String(value).replace(/<script[^>]*>.*?<\/script>/gi, '');
};
}
// Default: no sanitization
return (value) => value;
});
// Create a sanitizer for a specific context
const imgElement = document.createElement('img');
const srcSanitizer = render.createSanitizer(imgElement, 'src', 'attribute');
// Use the sanitizer
const safeUrl = srcSanitizer('https://example.com/image.jpg'); // Allowed
const blockedUrl = srcSanitizer('javascript:alert("xss")'); // Blocked
// Security policies example
render.setSanitizer((node, name, type) => {
// High-risk attributes that need sanitization
const highRiskAttrs = ['src', 'href', 'action', 'formaction'];
if (type === 'attribute' && highRiskAttrs.includes(name)) {
return (value) => {
const str = String(value);
// Block javascript: and data: URLs
if (str.match(/^(javascript|data):/i)) {
console.warn(`Blocked potentially unsafe ${name}: ${str}`);
return '';
}
return str;
};
}
return (value) => value;
});