or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-usage.mdcore-htm.mdindex.mdpreact-integration.mdreact-integration.md
tile.json

core-htm.mddocs/

Core HTM API

The core HTM library provides the fundamental tagged template functionality that can be bound to any hyperscript-compatible function.

Primary API

htm.bind()

function bind<HResult>(
  h: (type: any, props: Record<string, any>, ...children: any[]) => HResult
): (strings: TemplateStringsArray, ...values: any[]) => HResult | HResult[];

Binds HTM to a hyperscript function and returns a tagged template function.

Parameters:

  • h
    - Hyperscript function following the pattern
    h(type, props, ...children)
    • type
      : Element type (string for HTML elements, function/class for components)
    • props
      : Object containing element properties/attributes, or
      null
    • children
      : Variable number of child elements

Returns:

  • Tagged template function that converts HTML-like syntax to hyperscript calls
  • Single element for one root, array for multiple roots

Usage Examples:

import htm from "htm";

// Custom hyperscript function
const h = (tag, props, ...children) => ({ tag, props, children });
const html = htm.bind(h);

// Basic element
const element = html`<div>Hello World</div>`;
// Result: { tag: 'div', props: null, children: ['Hello World'] }

// Element with props
const button = html`<button class="primary" onclick=${handleClick}>Click</button>`;
// Result: { tag: 'button', props: { class: 'primary', onclick: handleClick }, children: ['Click'] }

// Component usage
const MyComponent = ({ name }) => html`<span>Hello ${name}</span>`;
const app = html`<${MyComponent} name="Alice" />`;
// Result: { tag: MyComponent, props: { name: 'Alice' }, children: [] }

Template Syntax

Basic Elements

// Self-closing
html`<div />`
html`<img src="photo.jpg" />`

// With content
html`<div>Content here</div>`
html`<h1>Title</h1>`

// Nested elements
html`
  <div>
    <h1>Title</h1>
    <p>Paragraph</p>
  </div>
`

Dynamic Values

const className = "container";
const content = "Hello World";
const isVisible = true;

// Dynamic attributes
html`<div class=${className}>Content</div>`

// Dynamic content
html`<div>${content}</div>`

// Boolean attributes
html`<input disabled=${isVisible} />`

// Mixed static and dynamic
html`<div class="base ${className}">Content</div>`

Component Integration

const MyComponent = ({ title, children }) => html`
  <div class="component">
    <h2>${title}</h2>
    <div class="content">${children}</div>
  </div>
`;

// Component usage
html`<${MyComponent} title="Welcome">
  <p>Child content</p>
</${MyComponent}>`;

// Self-closing component
html`<${MyComponent} title="Welcome" />`;

Prop Spreading

const props = { class: "button", disabled: true };
const extraProps = { "data-test": "my-button" };

// Spread props
html`<button ...${props} onclick=${handleClick}>Click</button>`;

// Multiple spreads
html`<button ...${props} ...${extraProps}>Click</button>`;

// Mix spread and direct props
html`<button ...${props} id="special">Click</button>`;

Multiple Root Elements

// Returns array when multiple roots
const items = html`
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
`;
// Result: [{ tag: 'li', ... }, { tag: 'li', ... }, { tag: 'li', ... }]

// Fragment syntax
const fragment = html`<>
  <h1>Title</h1>
  <p>Content</p>
</>`;

Special Syntax Features

// HTML comments (ignored in output)
html`<!-- This is a comment --><div>Content</div>`;

// Implicit closing tags
html`<div>Content</>`;  // Equivalent to <div>Content</div>

// Component end tags with explicit closing
html`<${Component} prop="value">
  Child content
</${Component}>`;

Performance Features

Template Caching

HTM automatically caches compiled templates for performance:

const html = htm.bind(h);

// First call compiles and caches
const element1 = html`<div class=${class1}>Content</div>`;

// Second call with same template reuses cached version
const element2 = html`<div class=${class2}>Content</div>`;

The caching system:

  • Uses a
    WeakMap
    keyed by the hyperscript function
  • Caches compiled operation lists per template string array
  • Provides significant performance benefits for repeated template usage

Static vs Dynamic Optimization

HTM optimizes templates by distinguishing static and dynamic parts:

// Mostly static - highly optimized
html`<div class="static">Static content</div>`;

// Dynamic parts tracked separately
html`<div class=${dynamic}>Content: ${content}</div>`;

Advanced Usage

Custom Hyperscript Functions

// Virtual DOM builder
const vdom = (tag, props, ...children) => ({ tag, props, children });
const htmlVdom = htm.bind(vdom);

// HTML string builder  
const htmlString = (tag, props, ...children) => {
  const attrs = props ? Object.entries(props)
    .map(([k, v]) => ` ${k}="${v}"`).join('') : '';
  const content = children.join('');
  return `<${tag}${attrs}>${content}</${tag}>`;
};
const htmlStr = htm.bind(htmlString);

// Custom renderer with logging
const loggingH = (tag, props, ...children) => {
  console.log('Creating element:', tag, props, children);
  return { tag, props, children };
};
const htmlLog = htm.bind(loggingH);

Type Safety with TypeScript

// Define your hyperscript return type
interface VNode {
  tag: string | Function;
  props: Record<string, any> | null;
  children: any[];
}

// Type-safe hyperscript function
const h = (tag: any, props: Record<string, any> | null, ...children: any[]): VNode => ({
  tag, props, children
});

// Bind with proper typing
const html = htm.bind(h);

// TypeScript will infer VNode | VNode[] return type
const element = html`<div>Typed content</div>`;

Types

// Main HTM interface
interface HTM {
  bind<HResult>(
    h: HyperscriptFunction<HResult>
  ): TemplateFunction<HResult>;
}

// Hyperscript function type
type HyperscriptFunction<T> = (
  type: any,
  props: Record<string, any> | null,
  ...children: any[]
) => T;

// Template function type
type TemplateFunction<T> = (
  strings: TemplateStringsArray,
  ...values: any[]
) => T | T[];

// Internal caching types
interface TemplateCache extends Map<TemplateStringsArray, any> {}
interface GlobalCache extends Map<HyperscriptFunction<any>, TemplateCache> {}