Skip to content

Commit 1bb4386

Browse files
committed
trusted types?
1 parent 7de9022 commit 1bb4386

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<link rel="icon" type="image/svg+xml" href="data:" />
77
<link rel="stylesheet" href="reset.css" />
8+
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'">
89
<title>dhtml</title>
910
<script type="module">
1011
import { html } from './dist/index.js'

src/client/compiler.ts

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,42 @@ const DYNAMIC_GLOBAL = /dyn-\$(\d+)\$/g
2323
const FORCE_ATTRIBUTES = /-|^class$|^for$/i
2424
const NEEDS_UPPERCASING = /\$./g
2525

26+
function createPolicy<T extends { createHTML(input: string, ...args: unknown[]): string }>(_name: string, rules: T): T {
27+
return rules
28+
}
29+
30+
declare var trustedTypes: { createPolicy: typeof createPolicy }
31+
32+
const policy = (typeof trustedTypes === 'undefined' ? createPolicy : trustedTypes.createPolicy.bind(trustedTypes))(
33+
'dhtml',
34+
{
35+
createHTML: (_text, statics: TemplateStringsArray) => {
36+
let i = 0
37+
return [...lexer.lex(statics)]
38+
.map(([char, state]) => {
39+
if (char === '\0') {
40+
if (state === lexer.DATA) return `<!--dyn-$${i++}$-->`
41+
else return `dyn-$${i++}$`
42+
}
43+
if (state === lexer.ATTR_NAME && char.toLowerCase() !== char) {
44+
return `$${char}`
45+
}
46+
return char
47+
})
48+
.join('')
49+
},
50+
},
51+
)
52+
2653
const templates: WeakMap<TemplateStringsArray, CompiledTemplate> = new WeakMap()
2754
export function compile_template(statics: TemplateStringsArray): CompiledTemplate {
2855
const cached = templates.get(statics)
2956
if (cached) return cached
3057

3158
const template_element = document.createElement('template')
32-
let next_part = 0
33-
template_element.innerHTML = [...lexer.lex(statics)]
34-
.map(([char, state]) => {
35-
if (char === '\0') {
36-
if (state === lexer.DATA) return `<!--dyn-$${next_part++}$-->`
37-
else return `dyn-$${next_part++}$`
38-
}
39-
if (state === lexer.ATTR_NAME && char.toLowerCase() !== char) {
40-
return `$${char}`
41-
}
42-
return char
43-
})
44-
.join('')
45-
46-
next_part = 0
59+
template_element.innerHTML = policy.createHTML('', statics)
4760

61+
let next_part = 0
4862
const compiled: CompiledTemplate = {
4963
_content: template_element.content,
5064
_parts: Array(statics.length - 1),

0 commit comments

Comments
 (0)