@remix-run/html-template
v0.3.0
Published
HTML template tag with auto-escaping for JavaScript
Downloads
1,521
Readme
html-template
Safe HTML template tag with auto-escaping for JavaScript.
html-template provides a tagged template literal for safely constructing HTML strings with automatic escaping of interpolated values to prevent XSS vulnerabilities.
Features
- Automatic HTML escaping - All interpolated values are escaped by default
- Explicit raw HTML - Use
html.rawwhen you need unescaped HTML from trusted sources - Composable - SafeHtml values can be nested without double-escaping
- Type-safe - Full TypeScript support with branded types
- Zero dependencies - Lightweight and self-contained
- Runtime agnostic - Works in Node.js, Bun, Deno, browsers, and edge runtimes
Installation
Install from npm:
npm install @remix-run/html-templateUsage
import { html } from '@remix-run/html-template'
let userInput = '<script>alert("XSS")</script>'
let greeting = html`<h1>Hello ${userInput}!</h1>`
console.log(String(greeting))
// Output: <h1>Hello <script>alert("XSS")</script>!</h1>By default, all interpolated values are automatically escaped to prevent XSS attacks.
If you have trusted HTML that should not be escaped, use html.raw:
import { html } from '@remix-run/html-template'
let trustedIcon = '<svg>...</svg>'
let button = html.raw`<button>${trustedIcon} Click me</button>`
console.log(String(button))
// => <button><svg>...</svg> Click me</button>Warning: Only use html.raw with content you trust. Never use it with user input.
Composing HTML Fragments
SafeHtml values can be nested without double-escaping:
import { html } from '@remix-run/html-template'
let title = html`<h1>My Title</h1>`
let content = html`<p>Some content with ${userInput}</p>`
let page = html`
<!doctype html>
<html>
<body>
${title} ${content}
</body>
</html>
`Working with Arrays
You can interpolate arrays of values, which will be flattened and joined:
import { html } from '@remix-run/html-template'
let items = ['Apple', 'Banana', 'Cherry']
let list = html`
<ul>
${items.map((item) => html`<li>${item}</li>`)}
</ul>
`Conditional Rendering
Use null or undefined to render nothing:
import { html } from '@remix-run/html-template'
let showError = false
let errorMessage = 'Something went wrong'
let page = html`<div>${showError ? html`<div class="error">${errorMessage}</div>` : null}</div>`Related Packages
@remix-run/fetch-router- HTTP router that works great with html-template
License
See LICENSE
