simple-html-tag
A simple, fast, and secure tagged template literal function for creating HTML strings with automatic XSS protection.
import { html } from "simple-html-tag";
const name = "World";
const greeting = html`Hello ${name}`;
console.log(greeting); // "Hello World"
Features
✨ Zero dependencies - Lightweight and fast
🔒 XSS protection - Automatic HTML escaping by default
🚀 TypeScript support - Full type safety and IntelliSense
⚡ High performance - Optimized for speed with pre-compiled regexes
🔄 Async support - Handle promises and async data seamlessly
📦 ESM/CommonJS - Works with modern bundlers and Node.js
Installation
npm install simple-html-tag
yarn add simple-html-tag
pnpm add simple-html-tag
bun add simple-html-tag
Quick Start
import { html, safe } from "simple-html-tag";
// Automatic XSS protection
const userInput = '<script>alert("xss")</script>';
const result = html`<div>Hello ${userInput}</div>`;
console.log(result); // <div>Hello <script>alert("xss")</script></div>
// Safe HTML when you trust the content
const trustedHtml = safe("<strong>Bold text</strong>");
const result2 = html`<div>${trustedHtml}</div>`;
console.log(result2); // <div><strong>Bold text</strong></div>
API Reference
html
- Tagged Template Literal
Creates HTML strings with automatic escaping of interpolated values.
import { html } from "simple-html-tag";
const name = '<script>alert("xss")</script>';
const age = 25;
const result = html`
<div class="user">
<h1>Hello ${name}</h1>
<p>Age: ${age}</p>
</div>
`;
// All variables are automatically escaped except those marked as safe
safe
- Mark Content as Safe
Marks a string as safe HTML that should not be escaped.
import { html, safe } from "simple-html-tag";
const trustedContent = safe("<em>This will not be escaped</em>");
const userContent = "<script>This will be escaped</script>";
const result = html`
<article>
${trustedContent}
<p>${userContent}</p>
</article>
`;
htmlAsync
- Async Template Literal
Handles promises and async data in template literals.
import { htmlAsync, safe } from "simple-html-tag";
async function renderUser(userId) {
const user = await fetchUser(userId);
const avatar = await fetchAvatar(userId);
return htmlAsync`
<div class="user">
<img src="${avatar.url}" alt="${user.name}">
<h1>${user.name}</h1>
<p>${user.bio}</p>
</div>
`;
}
Usage Examples
Basic HTML Generation
import { html } from "simple-html-tag";
function createButton(text, type = "button") {
return html`<button type="${type}" class="btn">${text}</button>`;
}
const submitBtn = createButton("Submit", "submit");
Working with Arrays
import { html } from "simple-html-tag";
const items = ["Apple", "Banana", "Cherry"];
const list = html`
<ul>
${items.map((item) => html`<li>${item}</li>`)}
</ul>
`;
Components with Safe HTML
import { html, safe } from "simple-html-tag";
function userCard(user) {
const avatar = user.avatar ? html`<img src="${user.avatar}" alt="${user.name}" />` : safe('<div class="avatar-placeholder"></div>');
return html`
<div class="user-card">
<div class="avatar">${avatar}</div>
<h3>${user.name}</h3>
<p>${user.email}</p>
</div>
`;
}
Async Data Loading
import { htmlAsync } from "simple-html-tag";
async function renderArticle(articleId) {
const article = fetchArticle(articleId);
const author = fetchAuthor(articleId);
return htmlAsync`
<article>
<h1>${article.title}</h1>
<p>By ${author.name}</p>
<div>${article.content}</div>
</article>
`;
}
Security
This library automatically escapes all interpolated values to prevent XSS attacks:
&
becomes&
<
becomes<
>
becomes>
"
becomes"
'
becomes'
/
becomes/
Only content explicitly marked with safe()
will bypass escaping.
Performance
- Pre-compiled regular expressions for fast escaping
- Minimal object creation and string concatenation
- Optimized for template literal performance
- Zero dependencies for maximum efficiency
TypeScript
Full TypeScript support with comprehensive type definitions:
import { html, safe, htmlAsync } from "simple-html-tag";
// Type-safe HTML generation
const result: string = html`<div>${"text"}</div>`;
// Safe HTML is properly typed
const safeHtml: string & { [Symbol]: true } = safe("<b>bold</b>");
// Async version returns Promise<string>
const asyncResult: Promise<string> = htmlAsync`<div>${Promise.resolve("text")}</div>`;
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Development
# Install dependencies
bun install
# Run tests
bun test
# Build package
bun run build
# Watch mode for tests
bun run watch
License
This project is licensed under the Unlicense - see the LICENSE file for details.
Credits
Created by Anthony Corcutt
Documented and enhanced by GitHub Copilot