diff --git a/backend/src/main/resources/html-sanitization-config.json b/backend/src/main/resources/html-sanitization-config.json
index b6779d6..f1bd063 100644
--- a/backend/src/main/resources/html-sanitization-config.json
+++ b/backend/src/main/resources/html-sanitization-config.json
@@ -5,7 +5,8 @@
"sup", "sub", "small", "big", "mark", "pre", "code", "kbd", "samp", "var",
"ul", "ol", "li", "dl", "dt", "dd",
"a", "table", "thead", "tbody", "tfoot", "tr", "th", "td", "caption", "colgroup", "col",
- "blockquote", "cite", "q", "hr", "details", "summary"
+ "blockquote", "cite", "q", "hr", "details", "summary",
+ "section", "article", "font", "center", "abbr", "dfn", "tt"
],
"allowedAttributes": {
"p": ["class", "style"],
@@ -32,12 +33,44 @@
"pre": ["class", "style"],
"code": ["class", "style"],
"details": ["class", "style"],
- "summary": ["class", "style"]
+ "summary": ["class", "style"],
+ "section": ["class", "style"],
+ "article": ["class", "style"],
+ "font": ["class", "style", "color", "size", "face"],
+ "center": ["class", "style"],
+ "abbr": ["class", "style", "title"],
+ "dfn": ["class", "style"],
+ "tt": ["class", "style"],
+ "b": ["class", "style"],
+ "strong": ["class", "style"],
+ "i": ["class", "style"],
+ "em": ["class", "style"],
+ "u": ["class", "style"],
+ "s": ["class", "style"],
+ "small": ["class", "style"],
+ "big": ["class", "style"],
+ "mark": ["class", "style"],
+ "sup": ["class", "style"],
+ "sub": ["class", "style"],
+ "del": ["class", "style"],
+ "ins": ["class", "style"],
+ "strike": ["class", "style"],
+ "kbd": ["class", "style"],
+ "samp": ["class", "style"],
+ "var": ["class", "style"]
},
"allowedCssProperties": [
"color", "background-color", "font-size", "font-weight",
"font-style", "text-align", "text-decoration", "margin",
- "padding", "text-indent", "line-height"
+ "padding", "text-indent", "line-height",
+ "border", "border-color", "border-width", "border-style",
+ "font-family", "font-variant", "font-variant-ligatures",
+ "font-variant-caps", "font-variant-numeric", "font-variant-east-asian",
+ "font-variant-alternates", "font-variant-position", "font-variant-emoji",
+ "font-stretch", "letter-spacing", "word-spacing",
+ "text-transform", "text-shadow", "white-space",
+ "vertical-align", "display", "float", "clear",
+ "width", "height", "min-width", "min-height", "max-width", "max-height"
],
"removedAttributes": {
"a": ["href", "target"]
diff --git a/frontend/src/components/stories/RichTextEditor.tsx b/frontend/src/components/stories/RichTextEditor.tsx
index 62fda84..7935f35 100644
--- a/frontend/src/components/stories/RichTextEditor.tsx
+++ b/frontend/src/components/stories/RichTextEditor.tsx
@@ -3,7 +3,7 @@
import { useState, useRef, useEffect } from 'react';
import { Textarea } from '../ui/Input';
import Button from '../ui/Button';
-import { sanitizeHtmlSync, preloadSanitizationConfig } from '../../lib/sanitization';
+import { sanitizeHtmlSync } from '../../lib/sanitization';
interface RichTextEditorProps {
value: string;
@@ -25,7 +25,11 @@ export default function RichTextEditor({
// Preload sanitization config
useEffect(() => {
- preloadSanitizationConfig().catch(console.error);
+ // Clear cache and reload config to get latest sanitization rules
+ import('../../lib/sanitization').then(({ clearSanitizationCache, preloadSanitizationConfig }) => {
+ clearSanitizationCache();
+ preloadSanitizationConfig().catch(console.error);
+ });
}, []);
const handleVisualChange = (e: React.ChangeEvent) => {
@@ -109,7 +113,15 @@ export default function RichTextEditor({
console.log('Raw HTML:', htmlContent.substring(0, 500));
const sanitizedHtml = sanitizeHtmlSync(htmlContent);
- console.log('Sanitized HTML:', sanitizedHtml.substring(0, 500));
+ console.log('Sanitized HTML length:', sanitizedHtml.length);
+ console.log('Sanitized HTML preview:', sanitizedHtml.substring(0, 500));
+
+ // Check if sanitization removed too much content
+ const ratio = sanitizedHtml.length / htmlContent.length;
+ console.log('Sanitization ratio (kept/original):', ratio.toFixed(3));
+ if (ratio < 0.1) {
+ console.warn('Sanitization removed >90% of content - this might be too aggressive');
+ }
// Insert at cursor position instead of just appending
const textarea = visualTextareaRef.current;