feat: Implement multi-image product display with fading and hover effects, and introduce lazy-loaded HTML sanitization.

This commit is contained in:
sebseb7
2026-03-10 11:27:15 +01:00
parent fb6c1159fe
commit 65a676de46
6 changed files with 403 additions and 205 deletions

View File

@@ -8,8 +8,7 @@ import EmailIcon from "@mui/icons-material/Email";
import LinkIcon from "@mui/icons-material/Link";
import CodeIcon from "@mui/icons-material/Code";
import { Link } from "react-router-dom";
import parse from "html-react-parser";
import sanitizeHtml from "sanitize-html";
import LazySanitizedHtml from "../utils/LazySanitizedHtml.js";
import AddToCartButton from "./AddToCartButton.js";
import ProductImage from "./ProductImage.js";
import Product from "./Product.js";
@@ -1624,10 +1623,10 @@ class ProductDetailPage extends Component {
"& strong": { fontWeight: 600 },
}}
>
{product.description ? (() => {
try {
// Sanitize HTML to remove invalid tags, but preserve style attributes and <product> tags
const sanitized = sanitizeHtml(product.description, {
{product.description ? (
<LazySanitizedHtml
html={product.description}
sanitizeOptions={(sanitizeHtml) => ({
allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img', 'product']),
allowedAttributes: {
'*': ['class', 'style'],
@@ -1636,26 +1635,20 @@ class ProductDetailPage extends Component {
'product': ['articlenr']
},
disallowedTagsMode: 'discard'
});
// Parse with custom replace function to handle <product> tags
return parse(sanitized, {
})}
parseOptions={{
replace: (domNode) => {
if (domNode.type === 'tag' && domNode.name === 'product') {
const articleNr = domNode.attribs && domNode.attribs['articlenr'];
if (articleNr) {
// Render embedded product component
return this.renderEmbeddedProduct(articleNr);
}
}
}
});
} catch (error) {
console.warn('Failed to parse product description HTML:', error);
// Fallback to rendering as plain text if HTML parsing fails
return <span>{product.description}</span>;
}
})() : upgrading ? (
}}
fallback={<span>{product.description}</span>}
/>
) : upgrading ? (
<Box sx={{ textAlign: "center", py: 2 }}>
<Typography variant="body1" color="text.secondary">
{this.props.t ? this.props.t('product.loadingDescription') : 'Produktbeschreibung wird geladen...'}