Simple and unsafe HTML/XML templates for TypeScript, using tagged template literals.
This library should not be used with untrusted strings!
Tagged template literals in JavaScript start with a tag (html
or xml
for this library) and are enclosed in backticks (e.g. html`text goes here`
).
Values are inserted as JavaScript expressions enclosed in braces, prefixed by a dollar sign (e.g. html`<p>${value}</p>`
).
For literal-html, if the expression evaluates to an object with a single key, the key indicates the type of escaping that is required. For example, {attr: "&"}
is an object with attr
as its key and "&"
as its (string) value. This tells literal-html to escape the value as an attribute value. For example, html`<img alt="${{attr: "&"}}" />`
would be escaped as <img alt="&" />
.
Supported types and keys:
Format | Escapes | Notes |
---|---|---|
${...} |
&<>'" | Supports number in addition to string |
${{content: ...}} |
&<> | |
${{attr: ...}} |
&<>'" | |
${{scriptString: ...}} |
<"\ | Namely for use in JSON-LD |
${{param: ...}} |
encodeURIComponent() |
For URL query parameters |
${{verbatim: ...}} |
(none) | Only use with previously escaped strings |
import { html, xml } from "https://deno.land/x/literal_html/mod.ts";
const value = ...; // Some string to be inserted
// Strings are escaped conservatively by default:
const fragmentHTML = html`<p>${value}</p>`;
const fragmentXML = xml`<text>${value}</text>`;
// You can specify the type of escaping required using an object with a single key, e.g. {attr: ...} for an attribute`:
const fragment3 = html`<img alt="${{attr: value}}" />`;
// To eliminate escaping altogether use the "verbatim" key:
const fragment4 = html`<p>${{verbatim: "This will NOT be escaped at all!"}}</p>`;
Examples of each type of escape follow.
const value = "what's <this> do? this & \"that\"!";
const result = html`<html><body><p>${value}</p></body></html>`;
// Result: <html><body><p>what's <this> do? this & "that"!</p></body></html>
const value = "what's <this> do? this & \"that\"!";
const result = html`<html><body><p>${{content: value}}</p></body></html>`;
// Result: <html><body><p>what's <this> do? this & "that"!</p></body></html>
const value = "what's <this> do? this & \"that\"!";
const result = html`<html><body><img alt="${{attr: value}}" /></body></html>`;
// Result: <html><body><img alt="what's <this> do? this & "that"!" /></body></html>
const value = 'A < "B" \\ C';
const result = html`<script type="application/ld+json">{ "name": "${{scriptString: value}}" }</script>`;
// Result: <script type="application/ld+json">{ "name": "A \x3C \"B\" \\ C" }</script>
const value = "what's <this> do? 'this' & \"that\"!";
const result = html`<html><body><p><a href="https://www.bing.com/search?q=${{param: value}}">Link</a></p></body></html>`;
// Result: <html><body><p><a href="https://www.bing.com/search?q=what's%20%3Cthis%3E%20do%3F%20'this'%20%26%20%22that%22!">Link</a></p></body></html>
This should only be used with strings that have already been properly escaped.
const result = html`<p>${{verbatim: "Line 1<br/>Line 2<br/>"}}</p>`;
// Result: <p>Line 1<br/>Line 2<br/></p>
This is especially useful for conditional inclusion:
const alt = "An image";
const result = html`<img ${{verbatim: alt ? html`alt="${alt}"` : ""}}/>`;
// Result: <img alt="An image"/>
Or applying templates to arrays of values:
const listItems = ["<", ">", "&"];
const result = html`<ul>${{
verbatim: listItems
.map(x => html`<li>${x}</li>`)
.join("")
}}</ul>`;
// Result: <ul><li><</li><li>></li><li>&</li></ul>