import sanitizeHtml from "sanitize-html"; import { readLiveSchema } from "../functions/live-schema"; import getSanitizeHtmlOptions from "./sanitize-html-options"; function grabTableFields(tableName) { const dbSchema = global.DB_SCHEMA || readLiveSchema(); const tableSchema = dbSchema?.tables?.find((t) => t.tableName === tableName); return tableSchema?.fields || []; } /** * Only fields with an explicit `html: true` flag are sanitized. * Missing / falsy / non-true values are never sanitized. */ function isExplicitHtmlField(field) { return field?.html === true; } function sanitizeValue(value, config) { if (typeof value !== "string") { return value; } return sanitizeHtml(value, getSanitizeHtmlOptions(config)); } /** * Sanitize string values ONLY for schema fields with explicit `html: true`. * Other fields (including plain text that happens to contain HTML) are left untouched. */ export default function sanitizeHtmlFields({ table, data, config, }) { const fields = grabTableFields(table); if (fields.length === 0) { return data; } const htmlFieldNames = new Set(fields .filter(isExplicitHtmlField) .map((f) => f.fieldName) .filter((name) => Boolean(name))); // No explicitly marked html fields on this table — skip entirely if (htmlFieldNames.size === 0) { return data; } const sanitized = { ...data }; const resolvedConfig = config || global.CONFIG; for (const key of Object.keys(sanitized)) { // Only sanitize keys that map to fields with html: true if (!htmlFieldNames.has(key)) continue; sanitized[key] = sanitizeValue(sanitized[key], resolvedConfig); } return sanitized; } /** * Sanitize an array of row objects for insert. */ export function sanitizeHtmlFieldsBatch({ table, data, config, }) { return data.map((row) => sanitizeHtmlFields({ table, data: row, config })); }