Skip to content
This repository was archived by the owner on Jan 9, 2025. It is now read-only.

Commit eef927f

Browse files
authored
Merge pull request #13 from github/feat-add-unsafe-html
feat: add unsafe-html directive
2 parents 8c50314 + 0370a67 commit eef927f

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export {TemplateResult, html, render} from './html'
22
export {isDirective, directive} from './directive'
33
export {until} from './until'
4+
export {unsafeHTML} from './unsafe-html'

src/unsafe-html.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {directive} from './directive'
2+
import {NodeTemplatePart} from '@github/template-parts'
3+
import type {TemplatePart} from '@github/template-parts'
4+
5+
export const unsafeHTML = directive((value: string) => (part: TemplatePart) => {
6+
if (!(part instanceof NodeTemplatePart)) return
7+
const template = document.createElement('template')
8+
template.innerHTML = value
9+
const fragment = document.importNode(template.content, true)
10+
part.replace(...fragment.childNodes)
11+
})

test/unsafe-html.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {html, render, unsafeHTML} from '..'
2+
3+
describe('unsafeHTML', () => {
4+
it('renders basic text', async () => {
5+
const surface = document.createElement('section')
6+
render(html`<div>${unsafeHTML('Hello World')}</div>`, surface)
7+
expect(surface.innerHTML).to.equal('<div>Hello World</div>')
8+
})
9+
it('disallows use inside of an attribute', () => {
10+
const surface = document.createElement('section')
11+
render(html`<div style="${unsafeHTML('Hello World')}"></div>`, surface)
12+
expect(surface.innerHTML).to.equal('<div style=""></div>')
13+
})
14+
it('renders the given value as HTML', async () => {
15+
const surface = document.createElement('section')
16+
render(html`<div>${unsafeHTML('<span>Hello World</span>')}</div>`, surface)
17+
expect(surface.innerHTML).to.equal('<div><span>Hello World</span></div>')
18+
})
19+
it('renders multiple children', async () => {
20+
const surface = document.createElement('section')
21+
render(html`<div>${unsafeHTML('<span>Hello</span><span>World</span>')}</div>`, surface)
22+
expect(surface.innerHTML).to.equal('<div><span>Hello</span><span>World</span></div>')
23+
})
24+
it('updates correctly', async () => {
25+
const surface = document.createElement('section')
26+
const fn = name => html`<div>${unsafeHTML(`<span>Hello</span><span>${name}</span>`)}</div>`
27+
render(fn('World'), surface)
28+
expect(surface.innerHTML).to.equal('<div><span>Hello</span><span>World</span></div>')
29+
render(fn('Universe'), surface)
30+
render(fn('<a href="">Universe</a>'), surface)
31+
expect(surface.innerHTML).to.equal('<div><span>Hello</span><span><a href="">Universe</a></span></div>')
32+
})
33+
})

0 commit comments

Comments
 (0)