diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5c7a23c0b..7fea88a23 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,6 +52,9 @@ jobs: - name: Install Playwright Browsers (chromium) run: pnpm exec playwright install chromium + - name: Start HTTP Server + run: pnpm serve:demo & + - name: Find Playwright Summary Comment (when exist) if: ${{ github.event.pull_request.number }} uses: peter-evans/find-comment@v2 diff --git a/demo/src/examples/example13.ts b/demo/src/examples/example13.ts index 56158ba5b..a97a12548 100644 --- a/demo/src/examples/example13.ts +++ b/demo/src/examples/example13.ts @@ -1,3 +1,4 @@ +import DOMPurify from 'dompurify'; import { multipleSelect, MultipleSelectInstance } from 'multiple-select-vanilla'; export default class Example { @@ -17,6 +18,7 @@ export default class Example { name: 'my-select', single: false, useSelectOptionLabelToHtml: true, + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), data: [ { text: ' January', diff --git a/demo/src/options/options27.ts b/demo/src/options/options27.ts index c763f4de9..bfec50452 100644 --- a/demo/src/options/options27.ts +++ b/demo/src/options/options27.ts @@ -1,3 +1,4 @@ +import DOMPurify from 'dompurify'; import { multipleSelect, MultipleSelectInstance, TextFilter } from 'multiple-select-vanilla'; export default class Example { @@ -20,6 +21,7 @@ export default class Example { divElm.innerHTML = text; return divElm.textContent?.includes(search) ?? true; }, + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), }) as MultipleSelectInstance; this.ms2 = multipleSelect('#from-data', { @@ -31,6 +33,7 @@ export default class Example { { value: `44'`, text: `44'` }, { value: `33`, text: `33` }, ], + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }) as unknown as string, }) as MultipleSelectInstance; this.btnEnableElm = document.querySelector('#enableRenderHtml') as HTMLButtonElement; diff --git a/demo/src/options/options28.ts b/demo/src/options/options28.ts index 933601e93..9b72e6378 100644 --- a/demo/src/options/options28.ts +++ b/demo/src/options/options28.ts @@ -1,3 +1,4 @@ +import DOMPurify from 'dompurify'; import { multipleSelect, MultipleSelectInstance } from 'multiple-select-vanilla'; export default class Example { @@ -9,6 +10,7 @@ export default class Example { labelTemplate: (el) => { return `${el.getAttribute('label')}`; }, + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), }) as MultipleSelectInstance; } diff --git a/demo/src/options/options30.ts b/demo/src/options/options30.ts index 46641f357..7a5afd5ae 100644 --- a/demo/src/options/options30.ts +++ b/demo/src/options/options30.ts @@ -1,3 +1,4 @@ +import DOMPurify from 'dompurify'; import { multipleSelect, MultipleSelectInstance } from 'multiple-select-vanilla'; export default class Example { @@ -12,18 +13,21 @@ export default class Example { autoAdjustDropHeight: true, position: 'top', showOkButton: true, + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), }) as MultipleSelectInstance; this.ms2 = multipleSelect('#select2', { autoAdjustDropHeight: true, position: 'top', showOkButton: true, + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), }) as MultipleSelectInstance; this.ms3 = multipleSelect('#select3', { autoAdjustDropHeight: true, filter: true, position: 'top', + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }) as unknown as string, }) as MultipleSelectInstance; this.ms4 = multipleSelect('#select4') as MultipleSelectInstance; diff --git a/demo/src/options/options31.ts b/demo/src/options/options31.ts index 09ae09baf..035419c78 100644 --- a/demo/src/options/options31.ts +++ b/demo/src/options/options31.ts @@ -1,3 +1,4 @@ +import DOMPurify from 'dompurify'; import { multipleSelect, MultipleSelectInstance } from 'multiple-select-vanilla'; export default class Example { @@ -11,6 +12,7 @@ export default class Example { this.ms2 = multipleSelect('#select2', { useSelectOptionLabelToHtml: true, + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), data: [ { text: ' January', diff --git a/demo/src/options/options32.ts b/demo/src/options/options32.ts index 1282ccbe0..d4b41bd42 100644 --- a/demo/src/options/options32.ts +++ b/demo/src/options/options32.ts @@ -13,7 +13,7 @@ export default class Example { : dirtyHtml, // or even better, use dedicated libraries like DOM Purify: https://github.com/cure53/DOMPurify - // sanitizer: (dirtyHtml) => DOMPurify.sanitize(dirtyHtml || '') + // sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), }) as MultipleSelectInstance; } diff --git a/lib/package.json b/lib/package.json index 217f33b4a..bdcb52e3e 100644 --- a/lib/package.json +++ b/lib/package.json @@ -67,6 +67,7 @@ "sass:copy": "cross-env copyfiles -u 2 src/styles/**/*.scss dist/styles/sass" }, "devDependencies": { + "@types/trusted-types": "^2.0.5", "autoprefixer": "^10.4.16", "copyfiles": "^2.4.1", "cross-env": "^7.0.3", diff --git a/lib/src/MultipleSelectInstance.ts b/lib/src/MultipleSelectInstance.ts index ec330013d..7e8c26e92 100644 --- a/lib/src/MultipleSelectInstance.ts +++ b/lib/src/MultipleSelectInstance.ts @@ -972,7 +972,7 @@ export class MultipleSelectInstance { */ protected renderAsTextOrHtmlWhenEnabled(elm: HTMLElement, value: string) { if (this.isRenderAsHtml) { - elm.innerHTML = this.options.sanitizer ? this.options.sanitizer(value) : value; + elm.innerHTML = (typeof this.options.sanitizer === 'function' ? this.options.sanitizer(value) : value) as unknown as string; } else { elm.textContent = value; } diff --git a/lib/src/interfaces/interfaces.ts b/lib/src/interfaces/interfaces.ts index 24acba759..34f38489b 100644 --- a/lib/src/interfaces/interfaces.ts +++ b/lib/src/interfaces/interfaces.ts @@ -27,7 +27,7 @@ export interface VirtualScrollOption { scrollEl: HTMLElement; contentEl: HTMLElement; callback: () => void; - sanitizer?: (dirtyHtml: string) => string; + sanitizer?: (html: string) => string | TrustedHTML; } export interface MultipleSelectLocale { diff --git a/lib/src/interfaces/multipleSelectOption.interface.ts b/lib/src/interfaces/multipleSelectOption.interface.ts index 68124fdd9..38d2b129f 100644 --- a/lib/src/interfaces/multipleSelectOption.interface.ts +++ b/lib/src/interfaces/multipleSelectOption.interface.ts @@ -255,5 +255,5 @@ export interface MultipleSelectOption extends MultipleSelectLocale { * Sanitizes HTML code, for example `