npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@purestack/ts-html

v1.1.32

Published

Type-safe HTML builder for TypeScript. `ts-html` provides a mutable, chainable API for creating HTML trees, setting attributes, and serializing to HTML with optional Prettier formatting. It is framework-agnostic and can be used on the server or in build t

Downloads

4,613

Readme

@purestack/ts-html

Type-safe HTML builder for TypeScript. ts-html provides a mutable, chainable API for creating HTML trees, setting attributes, and serializing to HTML with optional Prettier formatting. It is framework-agnostic and can be used on the server or in build tools (no DOM required).

Why this package exists

  • Build HTML with TypeScript instead of template strings.
  • Get type-checked tags and attributes (including ARIA and event attrs).
  • Compose HTML with chainable builders.
  • Generate predictable HTML output that can be prettified.

Install

npm install @purestack/ts-html
yarn add @purestack/ts-html
pnpm add @purestack/ts-html

Quick Example

import { h } from '@purestack/ts-html'

const html = h('html').push(
  h('head').push(
    h('title').text('Hello'),
    h('meta').attr({ charset: 'utf-8' }),
  ),
  h('body').push(
    h('main').push(h('h1').text('Hello world')),
    h('script').raw('console.log("hello")'),
  ),
)

const out = await html.toPrettyHtml()
console.log(out)

Core Concepts

h(tag)

Creates a TSNode for the given tag. If tag is omitted or an empty string, it creates a fragment node (used for grouping).

const fragment = h('').text('a').raw('<b>b</b>')

Mutable, Chainable Nodes

Mutating methods change the current node and return it for chaining. Use fresh nodes for independent trees. clone() makes a shallow copy: it copies attributes and the children array but shares child nodes.

const base = h('input')
const typed = base.clone().attr({ type: 'text' })

base.toHtml() // <input/>
typed.toHtml() // <input type="text"/>

Text vs Raw HTML

  • text() escapes HTML special characters.
  • raw() injects HTML without escaping.
const safe = h('p').text('<b>safe</b>')
const raw = h('p').raw('<b>raw</b>')

Attributes

ts-html exposes multiple attribute helpers to help with type safety:

  • attr(...) for tag-specific attributes
  • attrAll(...) for all attributes
  • attrGlobal(...) for global HTML attributes
  • attrAria(...) for ARIA attributes
  • attrEvents(...) for event-handler attributes
const button = h('button')
  .attr({ type: 'button' })
  .attrAria({ 'aria-label': 'Close' })
  .attrEvents({ onclick: 'close()' })

Selecting and Replacing Nodes

Use select(tag, replacer) to find the first matching tag in the subtree and replace it.

const page = h('html')
  .push(h('body').push(h('main')))
  .select('main', (node) => node.attr({ id: 'app' }))

Serialization

  • toHtml() returns HTML as a string.
  • toPrettyHtml() formats output using Prettier with sensible defaults.
const html = h('div').push(h('span').text('hi'))
console.log(html.toHtml())

Head Helpers

ts-html includes a small head metadata layer that turns a high-level config into <head> content:

import { createHead, getHeadConfig, h } from '@purestack/ts-html'

const head = createHead(
  getHeadConfig({
    title: 'My Site',
    description: 'Example',
    canonicalUrl: 'https://example.com',
    openGraph: { title: 'My Site', url: 'https://example.com' },
  }),
)

const doc = h('html').push(head, h('body'))

Relevant types:

  • BasicHeadConfig (high-level SEO config)
  • HeadConfig (low-level, explicit head element lists)

Type Safety and Metadata

Attribute and tag unions are generated into src/html.d.ts from datasets in src/meta/data. This gives you type-checked attributes for standard tags while still allowing custom elements.

API Overview

  • h(tag?)
  • TSNode#text(text, replace?)
  • TSNode#raw(html, replace?)
  • TSNode#push(...children)
  • TSNode#attr(...), attrAll(...), attrGlobal(...), attrAria(...), attrEvents(...)
  • TSNode#id(...), TSNode#class(...)
  • TSNode#select(tag, replacer)
  • TSNode#toHtml(), TSNode#toPrettyHtml(options?)

Tests

yarn workspace @purestack/ts-html test

Related Packages

  • @purestack/ts-css for typed CSS generation
  • @purestack/ts-ssg for a minimal static-site composition layer

License

MIT