dev #38

Merged
JoeKung merged 9 commits from dev into main 2026-03-11 11:05:13 +01:00
2 changed files with 43 additions and 13 deletions
Showing only changes of commit 78b719d3c2 - Show all commits

View File

@@ -1836,17 +1836,18 @@ export class AdminShopComponent implements OnInit, OnDestroy {
if (!editor) { if (!editor) {
return; return;
} }
const currentHtml = this.serializeNodeChildren(editor);
const currentLanguage = this.activeContentLanguage; const currentLanguage = this.activeContentLanguage;
if (sanitize) { if (sanitize) {
const normalized = this.normalizeRichTextStorageValue(editor.innerHTML); const normalized = this.normalizeRichTextStorageValue(currentHtml);
const safeHtml = normalized ?? ''; const safeHtml = normalized ?? '';
this.productForm.descriptions[currentLanguage] = safeHtml; this.productForm.descriptions[currentLanguage] = safeHtml;
if (editor.innerHTML !== safeHtml) { if (currentHtml !== safeHtml) {
editor.innerHTML = safeHtml; this.replaceElementContentFromHtml(editor, safeHtml);
} }
return; return;
} }
this.productForm.descriptions[currentLanguage] = editor.innerHTML; this.productForm.descriptions[currentLanguage] = currentHtml;
} }
private renderActiveDescriptionInEditor(): void { private renderActiveDescriptionInEditor(): void {
@@ -1856,8 +1857,8 @@ export class AdminShopComponent implements OnInit, OnDestroy {
} }
const html = const html =
this.productForm.descriptions[this.activeContentLanguage] ?? ''; this.productForm.descriptions[this.activeContentLanguage] ?? '';
if (editor.innerHTML !== html) { if (this.serializeNodeChildren(editor) !== html) {
editor.innerHTML = html; this.replaceElementContentFromHtml(editor, html);
} }
} }
@@ -1926,7 +1927,7 @@ export class AdminShopComponent implements OnInit, OnDestroy {
} }
} }
return outputBody.innerHTML; return this.serializeNodeChildren(outputBody);
} }
private sanitizeRichTextNode( private sanitizeRichTextNode(
@@ -2016,9 +2017,35 @@ export class AdminShopComponent implements OnInit, OnDestroy {
} }
private extractTextFromHtml(value: string): string { private extractTextFromHtml(value: string): string {
const container = document.createElement('div'); const parser = new DOMParser();
container.innerHTML = value; const parsed = parser.parseFromString(`<body>${value}</body>`, 'text/html');
return container.textContent ?? ''; return parsed.body.textContent ?? '';
}
private serializeNodeChildren(node: Node): string {
const serializer = new XMLSerializer();
let html = '';
for (const child of Array.from(node.childNodes)) {
html += serializer.serializeToString(child);
}
return html;
}
private replaceElementContentFromHtml(
element: HTMLElement,
html: string,
): void {
if (!html) {
element.replaceChildren();
return;
}
const parser = new DOMParser();
const parsed = parser.parseFromString(`<body>${html}</body>`, 'text/html');
const nodes = Array.from(parsed.body.childNodes).map((child) =>
document.importNode(child, true),
);
element.replaceChildren(...nodes);
} }
private escapeHtml(value: string): string { private escapeHtml(value: string): string {

View File

@@ -671,9 +671,12 @@ export class ProductDetailComponent {
if (!this.containsHtmlMarkup(normalized)) { if (!this.containsHtmlMarkup(normalized)) {
return normalized; return normalized;
} }
const container = document.createElement('div'); const parser = new DOMParser();
container.innerHTML = normalized; const parsed = parser.parseFromString(
const text = (container.textContent ?? '').replace(/\u00a0/g, ' ').trim(); `<body>${normalized}</body>`,
'text/html',
);
const text = (parsed.body.textContent ?? '').replace(/\u00a0/g, ' ').trim();
return text || null; return text || null;
} }