fix(catalog): decode and strip stray markup from product descriptions

P0-5: some catalog listings (live backend data, proxied third-party
marketplace via novo.market) carry HTML-entity-encoded markup in
their description field, e.g. '<attention>...</attention>'
and '"AppStops"' — rendered verbatim as visible text on
search-result cards and the PDP description tab.

Added a pure cleanDescription() util (item.utils.ts) that decodes
the common HTML entities and strips any resulting tag-like markup,
then wired it into ProductCardComponent (covers Home/Catalog/Search/
Wishlist/Compare/PDP-similar) and ProductDescriptionComponent (PDP
description tab). Output stays a plain string rendered via text
interpolation (never innerHTML), so this only cleans up display —
it introduces no HTML-rendering/XSS surface.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-19 22:56:12 +04:00
parent 374774901e
commit a39b3429ba
5 changed files with 32 additions and 4 deletions

View File

@@ -39,7 +39,7 @@
<h3 class="product-name">{{ title || item.name }}</h3>
@if (showDescription && description) {
<p class="product-description">{{ description }}</p>
<p class="product-description">{{ cleanDescription(description) }}</p>
}
@if (showRating) {

View File

@@ -4,7 +4,7 @@ import { RouterLink } from '@angular/router';
import { Product } from '../../core/products/models/product-domain.model';
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
import { TranslatePipe } from '../../i18n/translate.pipe';
import { getBadgeClass, getDiscountedPrice, getMainImage } from '../../utils/item.utils';
import { cleanDescription, getBadgeClass, getDiscountedPrice, getMainImage } from '../../utils/item.utils';
const STOCK_LABEL_KEYS: Record<string, string> = {
high: 'catalog.stockHigh',
@@ -55,6 +55,7 @@ export class ProductCardComponent {
readonly getMainImage = getMainImage;
readonly getDiscountedPrice = getDiscountedPrice;
readonly getBadgeClass = getBadgeClass;
readonly cleanDescription = cleanDescription;
onAddToCart(event: Event): void {
this.addToCart.emit({ itemID: this.item.itemID, event });