UNPKG

@networkpro/web

Version:

Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro Strategies

75 lines (63 loc) 2.1 kB
/* ========================================================================== src/lib/utils/purify.js Copyright © 2025 Network Pro Strategies (Network Pro™) SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later This file is part of Network Pro. ========================================================================== */ /** * @file purify.js * @description Universal DOMPurify instance for SSR + client with safe build support. * Secures untrusted HTML before injecting it into the DOM. * @module src/lib/utils * @author SunDevil311 * @updated 2025-06-01 */ import createDOMPurify from 'dompurify'; /** * @typedef {ReturnType<import('dompurify').default>} DOMPurifyInstance */ /** @type {import('dompurify').DOMPurify | null} */ let DOMPurifyInstance = null; /** @type {import('jsdom').JSDOM['window'] | null} */ let jsdomWindow = null; /** * SSR-safe + Vite-compatible init of DOMPurify. * * Caches DOMPurify across multiple calls to improve performance in tests or SSR environments. * * @returns {Promise<DOMPurifyInstance>} */ export async function getDOMPurify() { if (DOMPurifyInstance) return DOMPurifyInstance; if (typeof window !== 'undefined') { // ✅ Client-side: use native window DOMPurifyInstance = createDOMPurify(window); } else { // ✅ SSR: dynamically import jsdom to avoid bundling const { JSDOM } = await import('jsdom'); jsdomWindow = jsdomWindow || new JSDOM('').window; DOMPurifyInstance = createDOMPurify(jsdomWindow); } return DOMPurifyInstance; } /** * Sanitizes HTML content to prevent XSS. * * @param {string} dirtyHtml * @returns {Promise<string>} - A Promise resolving to sanitized HTML */ export async function sanitizeHtml(dirtyHtml) { const DOMPurify = await getDOMPurify(); return DOMPurify.sanitize(dirtyHtml, { USE_PROFILES: { html: true }, ALLOW_DATA_ATTR: false, ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto):)/i, }); } /** * Optional helper to reset cache (for test isolation). */ export function resetDOMPurifyCache() { DOMPurifyInstance = null; jsdomWindow = null; }