Skip to content

Commit 9c649cb

Browse files
committed
feat: html sanitization
1 parent 53970ec commit 9c649cb

9 files changed

Lines changed: 49 additions & 9 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@
105105
"@tiptap/extension-underline": "3.20.4",
106106
"@tiptap/extensions": "3.20.4",
107107
"@tiptap/pm": "3.20.4",
108-
"@tiptap/react": "3.20.4"
108+
"@tiptap/react": "3.20.4",
109+
"dompurify": "^3.4.11"
109110
},
110111
"devDependencies": {
111112
"@commitlint/config-conventional": "^19.6.0",

src/web/EnrichedText.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@ import type { EnrichedTextProps } from '../types';
33
import './EnrichedText.css';
44
import { enrichedTextStyleToCSSProperties } from './styleConversion/enrichedTextStyleToCSSProperties';
55
import { htmlStyleToCSSVariables } from './styleConversion/htmlStyleToCSSVariables';
6-
import { ENRICHED_TEXT_CLASSNAME } from './consts/classNames';
6+
import { ENRICHED_TEXT_CLASSNAME } from './constants/classNames';
77
import { enrichedInputThemingToCSSProperties } from './styleConversion/enrichedInputThemingToCSSProperties';
88
import { buildMentionRulesCSS } from './styleConversion/buildMentionRulesCSS';
9-
import { checkboxHtmlToWeb } from './checkboxHtmlToWeb';
9+
import { sanitizeHtml } from './sanitization/htmlSanitizer';
10+
import { prepareHtmlForWeb } from './normalization/prepareHtmlForWeb';
1011

1112
export const EnrichedText = ({
1213
children,
1314
htmlStyle,
1415
style,
1516
selectionColor,
1617
}: EnrichedTextProps) => {
17-
const html = useMemo(() => checkboxHtmlToWeb(children), [children]);
18+
const sanitizedHtml = useMemo(() => sanitizeHtml(children), [children]);
19+
20+
const finalHtml = useMemo(
21+
() => prepareHtmlForWeb(sanitizedHtml),
22+
[sanitizedHtml]
23+
);
1824

1925
const textStyle: CSSProperties = useMemo(
2026
() => enrichedTextStyleToCSSProperties(style ?? {}),
@@ -47,7 +53,7 @@ export const EnrichedText = ({
4753
<div
4854
style={finalStyle}
4955
className={ENRICHED_TEXT_CLASSNAME}
50-
dangerouslySetInnerHTML={{ __html: html }}
56+
dangerouslySetInnerHTML={{ __html: finalHtml }}
5157
/>
5258
</>
5359
);

src/web/EnrichedTextInput.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ import {
7474
import { StripMarksOnImagePlugin } from './pmPlugins/StripMarksOnImagePlugin';
7575
import { ShortcutPlugin } from './pmPlugins/ShortcutPlugin';
7676
import { returnKeyTypeToEnterKeyHint } from './returnKeyTypeToEnterKeyHint';
77-
import { ENRICHED_TEXT_INPUT_CLASSNAME } from './consts/classNames';
77+
import { ENRICHED_TEXT_INPUT_CLASSNAME } from './constants/classNames';
78+
7879
function runFocused(
7980
editor: Editor,
8081
apply: (chain: ChainedCommands) => ChainedCommands

src/web/checkboxHtmlToWeb.ts renamed to src/web/normalization/prepareHtmlForWeb.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
export function prepareHtmlForWeb(html: string) {
2+
return checkboxHtmlToWeb(html);
3+
}
4+
15
/*
26
* Native checkbox format (as produced by the editor):
37
* <ul data-type="checkbox">
@@ -17,7 +21,7 @@
1721
* </li>
1822
* </ul>
1923
*/
20-
export function checkboxHtmlToWeb(html: string): string {
24+
function checkboxHtmlToWeb(html: string): string {
2125
const parser = new DOMParser();
2226
const doc = parser.parseFromString(html, 'text/html');
2327

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import DOMPurify from 'dompurify';
2+
3+
export function sanitizeHtml(html: string) {
4+
return DOMPurify.sanitize(html, {
5+
ADD_TAGS: ['mention'],
6+
ADD_ATTR: ['text', 'indicator'],
7+
});
8+
}

src/web/styleConversion/__tests__/buildMentionRulesCSS.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { buildMentionRulesCSS } from '../buildMentionRulesCSS';
33
import {
44
ENRICHED_TEXT_CLASSNAME,
55
ENRICHED_TEXT_INPUT_CLASSNAME,
6-
} from '../../consts/classNames';
6+
} from '../../constants/classNames';
77

88
describe('buildMentionRulesCSS', () => {
99
it.each([

src/web/styleConversion/buildMentionRulesCSS.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { isMentionStyleRecord } from '../../utils/isMentionStyleRecord';
33
import {
44
ENRICHED_TEXT_CLASSNAME,
55
ENRICHED_TEXT_INPUT_CLASSNAME,
6-
} from '../consts/classNames';
6+
} from '../constants/classNames';
77
import { ET_MENTION_CSS_VARS } from './htmlStyleToCSSVariables';
88
import { MENTION_STYLE_DEFAULT_KEY } from './mentionIndicatorCssKey';
99

yarn.lock

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4548,6 +4548,13 @@ __metadata:
45484548
languageName: node
45494549
linkType: hard
45504550

4551+
"@types/trusted-types@npm:^2.0.7":
4552+
version: 2.0.7
4553+
resolution: "@types/trusted-types@npm:2.0.7"
4554+
checksum: 10c0/4c4855f10de7c6c135e0d32ce462419d8abbbc33713b31d294596c0cc34ae1fa6112a2f9da729c8f7a20707782b0d69da3b1f8df6645b0366d08825ca1522e0c
4555+
languageName: node
4556+
linkType: hard
4557+
45514558
"@types/use-sync-external-store@npm:^0.0.6":
45524559
version: 0.0.6
45534560
resolution: "@types/use-sync-external-store@npm:0.0.6"
@@ -6909,6 +6916,18 @@ __metadata:
69096916
languageName: node
69106917
linkType: hard
69116918

6919+
"dompurify@npm:^3.4.11":
6920+
version: 3.4.11
6921+
resolution: "dompurify@npm:3.4.11"
6922+
dependencies:
6923+
"@types/trusted-types": "npm:^2.0.7"
6924+
dependenciesMeta:
6925+
"@types/trusted-types":
6926+
optional: true
6927+
checksum: 10c0/31439481c7e8fc3805d40c376936fd66936620fb1b1a31a2ec097f6165412c37f2d868e082c9ceba62bb37661c1ea132a5db4d5213434317e30df68d4aca9cc9
6928+
languageName: node
6929+
linkType: hard
6930+
69126931
"dot-prop@npm:^5.1.0":
69136932
version: 5.3.0
69146933
resolution: "dot-prop@npm:5.3.0"
@@ -12881,6 +12900,7 @@ __metadata:
1288112900
clang-format: "npm:^1.8.0"
1288212901
commitlint: "npm:^19.6.1"
1288312902
del-cli: "npm:^5.1.0"
12903+
dompurify: "npm:^3.4.11"
1288412904
eslint: "npm:^9.22.0"
1288512905
eslint-config-prettier: "npm:^10.1.1"
1288612906
eslint-plugin-prettier: "npm:^5.2.3"

0 commit comments

Comments
 (0)