UNPKG

amuchina

Version:

A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebWorker like neither of those.

86 lines (85 loc) 2.58 kB
/* IMPORT */ import { FUNKY_TAG_NAMES } from './constants.js'; /* MAIN */ const cloneDeep = (value) => { return JSON.parse(JSON.stringify(value)); }; const isElement = (value) => { return (value.nodeType === 1); }; const isElementFunky = (value) => { return FUNKY_TAG_NAMES.has(value.tagName); }; const isElementAction = (value) => { return ('action' in value); }; const isElementIframe = (value) => { return (value.tagName === 'IFRAME'); }; const isElementFormAction = (value) => { return ('formAction' in value); }; const isElementHyperlink = (value) => { return ('protocol' in value); }; const isScriptOrDataUrl = (() => { const re = /^(?:\w+script|data):/i; return (url) => { return re.test(url); }; })(); const isScriptOrDataUrlLoose = (() => { const re = /(?:script|data):/i; return (url) => { return re.test(url); }; })(); const mergeMaps = (maps) => { const merged = {}; for (let i = 0, l = maps.length; i < l; i++) { const map = maps[i]; for (const key in map) { if (!merged[key]) { merged[key] = map[key]; } else { merged[key] = merged[key].concat(map[key]); } } } return merged; }; const traverseElementsBasic = (parent, callback) => { let current = parent.firstChild; while (current) { const next = current.nextSibling; if (isElement(current)) { callback(current, parent); if (current.parentNode) { // Still connected, so recurse traverseElementsBasic(current, callback); } } current = next; } }; const traverseElementsIterator = (parent, callback) => { const iterator = document.createNodeIterator(parent, NodeFilter.SHOW_ELEMENT); let current; while (current = iterator.nextNode()) { const parent = current.parentNode; if (!parent) continue; callback(current, parent); //TSC } }; const traverseElements = (parent, callback) => { const hasIterator = !!globalThis.document && !!globalThis.document.createNodeIterator; // For better WebWorker support if (hasIterator) { return traverseElementsIterator(parent, callback); } else { return traverseElementsBasic(parent, callback); } }; /* EXPORT */ export { cloneDeep, isElement, isElementFunky, isElementAction, isElementIframe, isElementFormAction, isElementHyperlink, isScriptOrDataUrl, isScriptOrDataUrlLoose, mergeMaps, traverseElements };