Intro
Demo
jsx
functionMyComponent ({children }) {return ("<!DOCTYPE html>" +(<html lang ="en"><head ><title >My Website</title ></head ><Type '{ "hx-boost": true; "hx-ext": "sse"; }' is not assignable to type 'HtmlBodyTag'. Types of property '["hx-boost"]' are incompatible. Type 'true' is not assignable to type 'BoolStr | undefined'.2322Type '{ "hx-boost": true; "hx-ext": "sse"; }' is not assignable to type 'HtmlBodyTag'. Types of property '["hx-boost"]' are incompatible. Type 'true' is not assignable to type 'BoolStr | undefined'.body hx-boost hx-ext ="sse"><div id ="main">{children }<form hx-post ="/purchase"hx-swap ="outerHTML"hx-vals ={{foo : "bar" }}><button type ="submit">Buy Now</button ></form ></div ></body ></html >));}
jsx
functionMyComponent ({children }) {return ("<!DOCTYPE html>" +(<html lang ="en"><head ><title >My Website</title ></head ><Type '{ "hx-boost": true; "hx-ext": "sse"; }' is not assignable to type 'HtmlBodyTag'. Types of property '["hx-boost"]' are incompatible. Type 'true' is not assignable to type 'BoolStr | undefined'.2322Type '{ "hx-boost": true; "hx-ext": "sse"; }' is not assignable to type 'HtmlBodyTag'. Types of property '["hx-boost"]' are incompatible. Type 'true' is not assignable to type 'BoolStr | undefined'.body hx-boost hx-ext ="sse"><div id ="main">{children }<form hx-post ="/purchase"hx-swap ="outerHTML"hx-vals ={{foo : "bar" }}><button type ="submit">Buy Now</button ></form ></div ></body ></html >));}
Install
shell
npm i typed-htmx
shell
npm i typed-htmx
You can also install as a dev dependency if you're only using the type definitions.
Usage
You can configure typed-htmx either as pure type declarations, or as a JSX templating engine.
As type declarations
Configure your tsconfig.json
as follows:
jsonc
{"compilerOptions": {"jsx": "react","moduleResolution": "node16", // or "nodenext""types": ["typed-htmx" /** and any other types you need */]}}
jsonc
{"compilerOptions": {"jsx": "react","moduleResolution": "node16", // or "nodenext""types": ["typed-htmx" /** and any other types you need */]}}
An alternative is to include a triple-slash directive wherever you need completions for htmx attributes:
jsx
/// <reference types="typed-htmx" />functionMyComponent ({children }) {return <div hx-get ="/asd">{children }</div >;}
jsx
/// <reference types="typed-htmx" />functionMyComponent ({children }) {return <div hx-get ="/asd">{children }</div >;}
If your frontend library injects its own JSX types, you'll need to augment it. See the example project for a demo. typed-html and React are supported out of the box.
As a JSX templating engine
If you prefer to use JSX only for its templating capabilities in the vein of
typed-html, you can use typed-htmx/typed-html
which is included with this
library and optimized for htmx usage:
- Attributes such as
hx-vals
andhx-headers
may also accept an object literal, which will be stringified on demand. - Configurable options for sanitization, defaults to a no-op.
Configure your tsconfig.json
as follows:
jsonc
{"compilerOptions": {"jsx": "react-jsx","jsxImportSource": "typed-htmx/typed-html","moduleResolution": "node16" // or "nodenext"}}
jsonc
{"compilerOptions": {"jsx": "react-jsx","jsxImportSource": "typed-htmx/typed-html","moduleResolution": "node16" // or "nodenext"}}
Tips
Configuring the JSX runtime
If you don't have any other JSX runtimes like React or Preact set up, you can use
typed-htmx/typed-html
, which will convert JSX into strings at runtime.
You can configure the runtime using jsxConfig
:
js
import {jsxConfig } from "typed-htmx";// Set to true to allow all text and skip sanitizationjsxConfig .trusted = true;// Bring your own sanitizerjsxConfig .sanitize = (raw ,originalType ) => `..`;
js
import {jsxConfig } from "typed-htmx";// Set to true to allow all text and skip sanitizationjsxConfig .trusted = true;// Bring your own sanitizerjsxConfig .sanitize = (raw ,originalType ) => `..`;
Compiling JSX templates
JSX functions are fairly fast and will unlikely to be a bottleneck in your server.
However, it is possible to achieve higher performance via techniques such as code transformations à la Babel.
For example, you can use swc-plugin-static-jsx
which will transform the demo snippet into pure string interpolation:
ts
// Use typed-htmx's template functionimport {html } from "typed-htmx";// Or provide your ownfunctionmyHtml (raw :TemplateStringsArray , ...args : unknown[]): string {return `..`;}functionMyComponent ({children }) {return ("<!DOCTYPE html>" +html `<html lang="en"><head><title>My Website</title></head><body hx-boost hx-ext="sse"><div id="main">${{$$child :children }}<formhx-post="/purchase"hx-swap="outerHTML"${{ "hx-vals": {foo : "bar" } }}><button type="submit">Buy Now</button></form></div></body></html>`);}
ts
// Use typed-htmx's template functionimport {html } from "typed-htmx";// Or provide your ownfunctionmyHtml (raw :TemplateStringsArray , ...args : unknown[]): string {return `..`;}functionMyComponent ({children }) {return ("<!DOCTYPE html>" +html `<html lang="en"><head><title>My Website</title></head><body hx-boost hx-ext="sse"><div id="main">${{$$child :children }}<formhx-post="/purchase"hx-swap="outerHTML"${{ "hx-vals": {foo : "bar" } }}><button type="submit">Buy Now</button></form></div></body></html>`);}