From deb984cdf81210d1aec7fe98b57e5f9b13ac6c03 Mon Sep 17 00:00:00 2001 From: Krystian Sienkiewicz Date: Wed, 29 Jul 2026 23:38:30 +0200 Subject: [PATCH 1/2] fix: mention attributes preserved when custom sanitizationConfig linkRegex is provided --- src/web/EnrichedTextInput.tsx | 4 ++-- src/web/__tests__/sanitization.test.ts | 12 ++++++++++++ src/web/normalization/tiptapHtmlNormalizer.ts | 3 ++- src/web/sanitization/htmlSanitizer.ts | 1 + src/web/useOnChangeHtml.ts | 6 +++--- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/web/EnrichedTextInput.tsx b/src/web/EnrichedTextInput.tsx index 87fa483b2..2f2c421a3 100644 --- a/src/web/EnrichedTextInput.tsx +++ b/src/web/EnrichedTextInput.tsx @@ -326,7 +326,7 @@ export const EnrichedTextInput = ({ ); useMentionEvents(editor, getMentionCallbacks); - useOnChangeHtml(editor, onChangeHtml, sanitizationConfig); + useOnChangeHtml(editor, () => sanitizationConfigRef.current, onChangeHtml); useOnChangeText(editor, onChangeText); useOnChangeState(editor, resolvedHtmlStyle, onChangeState); useOnLinkDetected(editor, linkEmitterRef); @@ -357,7 +357,7 @@ export const EnrichedTextInput = ({ Promise.resolve( normalizeHtmlFromTiptap( editor.getHTML(), - sanitizationConfigRef.current + () => sanitizationConfigRef.current ) ), toggleBold: () => runFocused(editor, (c) => c.toggleBold()), diff --git a/src/web/__tests__/sanitization.test.ts b/src/web/__tests__/sanitization.test.ts index 2814432c8..9cdb3c800 100644 --- a/src/web/__tests__/sanitization.test.ts +++ b/src/web/__tests__/sanitization.test.ts @@ -147,4 +147,16 @@ describe('sanitizeHtml with a custom linkRegex', () => { // eslint-disable-next-line no-script-url expect(out).not.toContain('javascript:'); }); + + it('keeps mention attributes when a custom config is provided', () => { + const out = sanitizeHtml( + '@Joe', + { + linkRegex, + } + ); + expect(out).toContain('text="Joe"'); + expect(out).toContain('indicator="@"'); + expect(out).toContain('data-user-id="42"'); + }); }); diff --git a/src/web/normalization/tiptapHtmlNormalizer.ts b/src/web/normalization/tiptapHtmlNormalizer.ts index 976e1d316..cadbda43a 100644 --- a/src/web/normalization/tiptapHtmlNormalizer.ts +++ b/src/web/normalization/tiptapHtmlNormalizer.ts @@ -22,8 +22,9 @@ export function prepareHtmlForTiptap( export function normalizeHtmlFromTiptap( html: string, - sanitizationConfig?: SanitizationConfig + getSanitizationConfig: () => SanitizationConfig | undefined ): string { + const sanitizationConfig = getSanitizationConfig(); html = sanitizeHtml(html, sanitizationConfig); html = checkboxHtmlFromTiptap(html); diff --git a/src/web/sanitization/htmlSanitizer.ts b/src/web/sanitization/htmlSanitizer.ts index a57a56aa0..6b8acf442 100644 --- a/src/web/sanitization/htmlSanitizer.ts +++ b/src/web/sanitization/htmlSanitizer.ts @@ -10,6 +10,7 @@ export function sanitizeHtml(html: string, config?: SanitizationConfig) { return DOMPurify.sanitize(html, { ADD_TAGS: ['mention', 'codeblock'], ADD_ATTR: MENTION_ATTRS, + ADD_URI_SAFE_ATTR: MENTION_ATTRS, // if not supplied, fall back to DOMPurify's built-in default. ...(config?.linkRegex ? { ALLOWED_URI_REGEXP: config.linkRegex } : {}), }); diff --git a/src/web/useOnChangeHtml.ts b/src/web/useOnChangeHtml.ts index a172d0655..f3cb0991b 100644 --- a/src/web/useOnChangeHtml.ts +++ b/src/web/useOnChangeHtml.ts @@ -6,10 +6,10 @@ import { normalizeHtmlFromTiptap } from './normalization/tiptapHtmlNormalizer'; export const useOnChangeHtml = ( editor: Editor, - onChangeHtml?: (e: NativeSyntheticEvent) => void, - sanitizationConfig?: SanitizationConfig + getSanitizationConfig: () => SanitizationConfig | undefined, + onChangeHtml?: (e: NativeSyntheticEvent) => void ) => { useOnEditorChange(editor, onChangeHtml, (e) => - normalizeHtmlFromTiptap(e.getHTML(), sanitizationConfig) + normalizeHtmlFromTiptap(e.getHTML(), getSanitizationConfig) ); }; From f38659a0e831069e9912eb2072237b934b084053 Mon Sep 17 00:00:00 2001 From: Krystian Sienkiewicz Date: Thu, 30 Jul 2026 00:06:26 +0200 Subject: [PATCH 2/2] docs: sanitization linkregex info tweak --- docs/WEB.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/WEB.md b/docs/WEB.md index d51b6908c..bc69f67fb 100644 --- a/docs/WEB.md +++ b/docs/WEB.md @@ -30,7 +30,7 @@ On web, HTML is sanitized automatically with [DOMPurify](https://github.com/cure By default, sanitization strips links with non-standard protocols (e.g. `custom://…`). Both `EnrichedText` and `EnrichedTextInput` accept a web-only `sanitizationConfig` prop whose `linkRegex` field lets you control which link URIs survive. -`linkRegex` maps directly to DOMPurify's [`ALLOWED_URI_REGEXP`](https://github.com/cure53/DOMPurify#can-i-configure-dompurify), so it **replaces** the default allow-list rather than extending it — remember to keep the standard protocols you still want to permit: +`linkRegex` maps directly to DOMPurify's [`ALLOWED_URI_REGEXP`](https://github.com/cure53/DOMPurify#can-i-configure-dompurify), so it **replaces** the default allow-list rather than extending it. Because this regex affects all URI-containing attributes (e.g. `src` in ``), remember to keep the standard protocols you still want to permit: ```tsx