refactor(builder): use shared escaper everywhere, drop 26 local copies

Replace divergent, buggy local esc/escapeHtml helpers across 26 files with
imports from src/utils/escape (escapeHtml/escapeAttr). Attribute call sites use
escapeAttr, text-content sites use escapeHtml. Several toHtml outputs now
correctly escape & where old local escapers omitted it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 11:49:10 -07:00
parent cce984508f
commit fad1882117
26 changed files with 101 additions and 119 deletions
+4 -4
View File
@@ -2,6 +2,7 @@ import React, { CSSProperties, useState } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { AnchorIdField } from '../../ui/AnchorIdField';
import { escapeHtml, escapeAttr } from '../../utils/escape';
interface AccordionItem {
title: string;
@@ -299,12 +300,11 @@ Accordion.craft = {
/* ---------- HTML export ---------- */
(Accordion as any).toHtml = (props: AccordionProps, _childrenHtml: string) => {
const esc = (s: any) => String(s ?? "").replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
const sectionStyle = cssPropsToString({
padding: '60px 20px',
...props.style,
});
const idAttr = props.anchorId ? ` id="${esc(props.anchorId)}"` : '';
const idAttr = props.anchorId ? ` id="${escapeAttr(props.anchorId)}"` : '';
const headerBg = props.headerBg || '#f8fafc';
const headerColor = props.headerColor || '#18181b';
const contentBg = props.contentBg || '#ffffff';
@@ -318,10 +318,10 @@ Accordion.craft = {
const borderBottom = i === items.length - 1 ? `border:1px solid ${borderColor};` : `border:1px solid ${borderColor};border-bottom:none;`;
return `<details${openAttr} style="${borderBottom}${topRadius}${bottomRadius}">
<summary style="padding:16px 20px;background-color:${headerBg};color:${headerColor};cursor:pointer;font-weight:600;font-size:16px;list-style:none;display:flex;justify-content:space-between;align-items:center">
${esc(item.title)}
${escapeHtml(item.title)}
</summary>
<div style="padding:16px 20px;background-color:${contentBg};color:#4b5563;font-size:14px;line-height:1.6;border-top:1px solid ${borderColor}">
${esc(item.content)}
${escapeHtml(item.content)}
</div>
</details>`;
}).join('\n ');