1/** 2 * HTML Sanitization Utilities 3 * Wraps DOMPurify for consistent sanitization across the site 4 */ 5 6const SanitizeUtils = { 7 /** 8 * Sanitize HTML string for safe innerHTML insertion 9 * @param {string} html - The HTML string to sanitize 10 * @param {Object} options - Optional DOMPurify configuration 11 * @returns {string} - Sanitized HTML 12 */ 13 sanitizeHTML(html, options = {}) { 14 if (typeof DOMPurify === 'undefined') { 15 console.error('DOMPurify is not loaded. Returning empty string for safety.'); 16 return ''; 17 } 18 19 // Default safe configuration 20 const defaultConfig = { 21 ALLOWED_TAGS: [ 22 'p', 'br', 'strong', 'em', 'u', 'a', 'span', 'div', 23 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 24 'ul', 'ol', 'li', 25 'img', 'figure', 'figcaption', 26 'blockquote', 'code', 'pre', 27 'table', 'thead', 'tbody', 'tr', 'th', 'td', 28 'svg', 'path', 'circle', 'rect', 'line', 'polyline', 'polygon', 29 'button', 'audio' 30 ], 31 ALLOWED_ATTR: [ 32 'href', 'target', 'rel', 'class', 'id', 'style', 33 'src', 'alt', 'title', 'width', 'height', 'loading', 'decoding', 34 'data-*', 'aria-*', 35 'viewBox', 'xmlns', 'd', 'fill', 'stroke', 'stroke-width', 36 'type', 'disabled', 'preload', 'controls' 37 ], 38 ALLOW_DATA_ATTR: true, 39 ALLOW_ARIA_ATTR: true 40 }; 41 42 const config = { ...defaultConfig, ...options }; 43 return DOMPurify.sanitize(html, config); 44 }, 45 46 /** 47 * Sanitize HTML with iframe support (for video embeds) 48 * @param {string} html - The HTML string to sanitize 49 * @returns {string} - Sanitized HTML with iframes allowed 50 */ 51 sanitizeWithIframes(html) { 52 return this.sanitizeHTML(html, { 53 ADD_TAGS: ['iframe'], 54 ADD_ATTR: ['allow', 'allowfullscreen', 'frameborder', 'src'] 55 }); 56 }, 57 58 /** 59 * Sanitize simple text content (loading states, errors) 60 * @param {string} html - The HTML string to sanitize 61 * @returns {string} - Sanitized HTML (very restrictive) 62 */ 63 sanitizeSimple(html) { 64 return this.sanitizeHTML(html, { 65 ALLOWED_TAGS: ['div', 'p', 'span', 'strong', 'em'], 66 ALLOWED_ATTR: ['class', 'style'] 67 }); 68 }, 69 70 /** 71 * Escape HTML for use in attributes or plain text 72 * @param {string} text - Text to escape 73 * @returns {string} - Escaped text 74 */ 75 escapeHTML(text) { 76 if (!text) return ''; 77 const div = document.createElement('div'); 78 div.textContent = text; 79 return div.innerHTML; 80 } 81}; 82 83// Export for use in other scripts 84if (typeof window !== 'undefined') { 85 window.SanitizeUtils = SanitizeUtils; 86} 87 88if (typeof module !== 'undefined' && module.exports) { 89 module.exports = SanitizeUtils; 90}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.