Skip to content

Commit

Permalink
Merge pull request #393 from yue4u/feat/skip-dom-purify-for-trusted-c…
Browse files Browse the repository at this point in the history
…ontent

feat!(@charcoal-ui/icons): skip dom purify for trusted content
  • Loading branch information
yue4u authored Oct 24, 2024
2 parents db17dd4 + 4eb112c commit 42cca0b
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 18 deletions.
29 changes: 18 additions & 11 deletions packages/icons/src/PixivIcon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import warning from 'warning'
import { KnownIconFile } from './charcoalIconFiles'
import { getIcon, addCustomIcon } from './loaders'
import { __SERVER__ } from './ssr'
import DOMPurify from 'dompurify'

const attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const

Expand Down Expand Up @@ -179,8 +178,11 @@ export class PixivIcon extends HTMLElement {
render() {
const size = this.forceResizedSize ?? this.scaledSize

const style = DOMPurify.sanitize(
`<style>
if (!Number.isFinite(size)) {
throw new TypeError(`icon size must not be NaN`)
}

const style = `<style>
:host {
display: inline-flex;
--size: ${size}px;
Expand All @@ -190,23 +192,28 @@ export class PixivIcon extends HTMLElement {
width: var(--size);
height: var(--size);
}
</style>`,
{ ALLOWED_TAGS: ['style'], FORCE_BODY: true }
)
</style>`

const svg = DOMPurify.sanitize(
const svg =
this.svgContent !== undefined
? this.svgContent
: `<svg viewBox="0 0 ${size} ${size}"></svg>`,
{ USE_PROFILES: { svg: true, svgFilters: true } }
)
: `<svg viewBox="0 0 ${size} ${size}"></svg>`

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.shadowRoot!.innerHTML = style + svg
}

private async loadSvg(name: string) {
this.svgContent = await getIcon(name)
const iconResult = await getIcon(name)

if (iconResult.trusted) {
this.svgContent = iconResult.svgContent
} else {
const { default: DOMPurify } = await import('dompurify')
this.svgContent = DOMPurify.sanitize(iconResult.svgContent, {
USE_PROFILES: { svg: true, svgFilters: true },
})
}
this.render()
}

Expand Down
4 changes: 4 additions & 0 deletions packages/icons/src/loaders/CharcoalIconFilesLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export class CharcoalIconFilesLoader implements Loadable {
this._name = name
}

get trusted() {
return true
}

get importIconFile() {
return charcoalIconFiles[this._name]
}
Expand Down
4 changes: 4 additions & 0 deletions packages/icons/src/loaders/CustomIconLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export class CustomIconLoader implements Loadable {
this._filePathOrUrl = filePathOrUrl
}

get trusted() {
return false
}

async fetch(): Promise<string> {
if (this._resultSvg !== undefined) {
return this._resultSvg
Expand Down
1 change: 1 addition & 0 deletions packages/icons/src/loaders/Loadable.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export interface Loadable {
readonly trusted: boolean
fetch(): Promise<string>
}
17 changes: 10 additions & 7 deletions packages/icons/src/loaders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ export async function getIcon(name: string) {
throw new PixivIconLoadError(name, 'Loader was not found')
}

return loader.fetch().catch((e) => {
if (e instanceof PixivIconLoadError) {
throw e
}

throw new PixivIconLoadError(name, e)
})
return loader
.fetch()
.then((svgContent) => ({ trusted: loader.trusted, svgContent }))
.catch((e) => {
if (e instanceof PixivIconLoadError) {
throw e
}

throw new PixivIconLoadError(name, e)
})
}

function resolveIconLoader(name: string) {
Expand Down

0 comments on commit 42cca0b

Please sign in to comment.