Readme
Create valimport { html } from "https://esm.town/v/postpostscript/html"
const unsafeInput = "<script>alert(1)</script>"
console.log(html`Value: ${unsafeInput}`)
// Value: <script>alert(1)</script>
These can be combined -- HTML marked as safe (instance is RawHTML
) will be directly inserted:
Create valconst scripts = html`<script>alert(1)</script>`
console.log(html`<head>
${scripts}
</head>`.toString())
// <head>
// <script>alert(1)</script>
// </head>
To easily create HTTP Response outputs like @stevekrouse/html, use the htmlResponse
utility:
Create valimport { html, htmlResponse } from "https://esm.town/v/postpostscript/html";
export default function(req: Request) {
return htmlResponse`
Request URL: ${decodeURIComponent(req.url)}
`;
}
Tests: @postpostscript/htmlTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { hybridTaggedTemplateMethod } from "https://esm.town/v/postpostscript/hybridTaggedTemplateMethod";
import { html as createHTMLResponse } from "https://esm.town/v/stevekrouse/html";
export class RawHTML extends String {
constructor(value: unknown) {
if (value instanceof RawHTML) {
super(value);
} else {
super(coerceString(value));
}
}
trim() {
return new RawHTML(this.toString().trim());
}
}
export function htmlEscape(text: string | RawHTML | unknown) {
if (text instanceof RawHTML) {
return text;
}
return new RawHTML(
coerceString(text)
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">"),
);
}
export function coerceString(value: unknown) {
if (typeof value === "string") {
return value;
} else if (typeof value === "number" || typeof value === "boolean") {
return value.toString();
} else if (value === undefined) {
return "";
}
return JSON.stringify(value) || "";
}
export const html = hybridTaggedTemplateMethod({
transformReplacement(replacement) {
return replacement instanceof Array
? replacement.map(part => htmlEscape(part)).join("")
: htmlEscape(replacement);
},
transformResult(result) {
return new RawHTML(result);
},
});
export const rawHtml = hybridTaggedTemplateMethod({
transformReplacement(replacement) {
return replacement instanceof Array
? replacement.join("")
: replacement;
},
transformResult(result) {
return new RawHTML(result);
},
});
export const htmlResponse = hybridTaggedTemplateMethod({
transformReplacement(replacement) {
return replacement instanceof Array
? replacement.map(part => htmlEscape(part)).join("")
: htmlEscape(replacement);
},
transformResult(result) {
return createHTMLResponse(result);
},
});
👆 This is a val. Vals are TypeScript snippets of code, written in the browser and run on our servers. Create scheduled functions, email yourself, and persist small pieces of data — all from the browser.