{"version":3,"file":"yett.min.js","sources":["../../src/variables.js","../../src/checks.js","../../src/observer.js","../../src/monkey.js","../../src/unblock.js"],"sourcesContent":["export const TYPE_ATTRIBUTE = 'javascript/blocked'\n\nexport const patterns = {\n blacklist: window.YETT_BLACKLIST,\n whitelist: window.YETT_WHITELIST\n}\n\n// Backup list containing the original blacklisted script elements\nexport const backupScripts = {\n blacklisted: []\n}","import { patterns, TYPE_ATTRIBUTE } from './variables'\n\nexport const isOnBlacklist = (src, type) => (\n src &&\n (!type || type !== TYPE_ATTRIBUTE) &&\n (\n (!patterns.blacklist || patterns.blacklist.some(pattern => pattern.test(src))) &&\n (!patterns.whitelist || patterns.whitelist.every(pattern => !pattern.test(src)))\n )\n)\n\nexport const willBeUnblocked = function(script) {\n const src = script.getAttribute('src')\n return (\n patterns.blacklist && patterns.blacklist.every(entry => !entry.test(src)) ||\n patterns.whitelist && patterns.whitelist.some(entry => entry.test(src))\n )\n}","import { backupScripts, TYPE_ATTRIBUTE } from './variables'\nimport { isOnBlacklist } from './checks'\n\n// Setup a mutation observer to track DOM insertion\nexport const observer = new MutationObserver(mutations => {\n for (let i = 0; i < mutations.length; i++) {\n const { addedNodes } = mutations[i];\n for(let i = 0; i < addedNodes.length; i++) {\n const node = addedNodes[i]\n // For each added script tag\n if(node.nodeType === 1 && node.tagName === 'SCRIPT') {\n const src = node.src\n const type = node.type\n // If the src is inside the blacklist and is not inside the whitelist\n if(isOnBlacklist(src, type)) {\n // We backup a copy of the script node\n backupScripts.blacklisted.push(node.cloneNode())\n\n // Blocks inline script execution in Safari & Chrome\n node.type = TYPE_ATTRIBUTE\n\n // Firefox has this additional event which prevents scripts from beeing executed\n const beforeScriptExecuteListener = function (event) {\n // Prevent only marked scripts from executing\n if(node.getAttribute('type') === TYPE_ATTRIBUTE)\n event.preventDefault()\n node.removeEventListener('beforescriptexecute', beforeScriptExecuteListener)\n }\n node.addEventListener('beforescriptexecute', beforeScriptExecuteListener)\n\n // Remove the node from the DOM\n node.parentElement.removeChild(node)\n }\n }\n }\n }\n})\n\n// Starts the monitoring\nobserver.observe(document.documentElement, {\n childList: true,\n subtree: true\n})","import { TYPE_ATTRIBUTE } from './variables'\nimport { isOnBlacklist } from './checks'\n\nconst createElementBackup = document.createElement\n\n// Monkey patch the createElement method to prevent dynamic scripts from executing\ndocument.createElement = function(...args) {\n // If this is not a script tag, bypass\n if(args[0].toLowerCase() !== 'script')\n return createElementBackup.bind(document)(...args)\n\n const scriptElt = createElementBackup.bind(document)(...args)\n const originalSetAttribute = scriptElt.setAttribute.bind(scriptElt)\n\n // Define getters / setters to ensure that the script type is properly set\n Object.defineProperties(scriptElt, {\n 'src': {\n get() {\n return scriptElt.getAttribute('src')\n },\n set(value) {\n if(isOnBlacklist(value, scriptElt.type)) {\n originalSetAttribute('type', TYPE_ATTRIBUTE)\n }\n originalSetAttribute('src', value)\n return true\n }\n },\n 'type': {\n set(value) {\n const typeValue =\n isOnBlacklist(scriptElt.src, scriptElt.type) ?\n TYPE_ATTRIBUTE :\n value\n originalSetAttribute('type', typeValue)\n return true\n }\n }\n })\n\n // Monkey patch the setAttribute function so that the setter is called instead\n scriptElt.setAttribute = function(name, value) {\n if(name === 'type' || name === 'src')\n scriptElt[name] = value\n else\n HTMLScriptElement.prototype.setAttribute.call(scriptElt, name, value)\n }\n\n return scriptElt\n}","import {\n patterns,\n backupScripts,\n TYPE_ATTRIBUTE\n} from './variables'\n\nimport {\n willBeUnblocked\n} from './checks'\n\nimport {\n observer\n} from './observer'\n\nconst URL_REPLACER_REGEXP = new RegExp('[|\\\\{}()[\\\\]^$+*?.]', 'g')\n\n// Unblocks all (or a selection of) blacklisted scripts.\nexport const unblock = function(...scriptUrlsOrRegexes) {\n if(scriptUrlsOrRegexes.length < 1) {\n patterns.blacklist = []\n patterns.whitelist = []\n } else {\n if(patterns.blacklist) {\n patterns.blacklist = patterns.blacklist.filter(pattern => (\n scriptUrlsOrRegexes.every(urlOrRegexp => {\n if(typeof urlOrRegexp === 'string')\n return !pattern.test(urlOrRegexp)\n else if(urlOrRegexp instanceof RegExp)\n return pattern.toString() !== urlOrRegexp.toString()\n })\n ))\n }\n if(patterns.whitelist) {\n patterns.whitelist = [\n ...patterns.whitelist,\n ...scriptUrlsOrRegexes\n .map(urlOrRegexp => {\n if(typeof urlOrRegexp === 'string') {\n const escapedUrl = urlOrRegexp.replace(URL_REPLACER_REGEXP, '\\\\$&')\n const permissiveRegexp = '.*' + escapedUrl + '.*'\n if(patterns.whitelist.every(p => p.toString() !== permissiveRegexp.toString())) {\n return new RegExp(permissiveRegexp)\n }\n } else if(urlOrRegexp instanceof RegExp) {\n if(patterns.whitelist.every(p => p.toString() !== urlOrRegexp.toString())) {\n return urlOrRegexp\n }\n }\n return null\n })\n .filter(Boolean)\n ]\n }\n }\n\n\n // Parse existing script tags with a marked type\n const tags = document.querySelectorAll(`script[type=\"${TYPE_ATTRIBUTE}\"]`)\n for(let i = 0; i < tags.length; i++) {\n const script = tags[i]\n if(willBeUnblocked(script)) {\n script.type = 'application/javascript'\n backupScripts.blacklisted.push(script)\n script.parentElement.removeChild(script)\n }\n }\n\n // Exclude 'whitelisted' scripts from the blacklist and append them to \n let indexOffset = 0;\n [...backupScripts.blacklisted].forEach((script, index) => {\n if(willBeUnblocked(script)) {\n const scriptNode = document.createElement('script')\n scriptNode.setAttribute('src', script.src)\n scriptNode.setAttribute('type', 'application/javascript')\n document.head.appendChild(scriptNode)\n backupScripts.blacklisted.splice(index - indexOffset, 1)\n indexOffset++\n }\n })\n\n // Disconnect the observer if the blacklist is empty for performance reasons\n if(patterns.blacklist && patterns.blacklist.length < 1) {\n observer.disconnect()\n }\n}"],"names":["TYPE_ATTRIBUTE","patterns","blacklist","window","YETT_BLACKLIST","whitelist","YETT_WHITELIST","backupScripts","blacklisted","isOnBlacklist","src","type","some","pattern","test","every","willBeUnblocked","script","getAttribute","entry","observer","MutationObserver","mutations","i","length","addedNodes","node","nodeType","tagName","push","cloneNode","addEventListener","beforeScriptExecuteListener","event","preventDefault","removeEventListener","parentElement","removeChild","observe","document","documentElement","childList","subtree","createElementBackup","createElement","args","toLowerCase","bind","scriptElt","originalSetAttribute","setAttribute","Object","defineProperties","get","set","value","typeValue","name","HTMLScriptElement","prototype","call","URL_REPLACER_REGEXP","RegExp","scriptUrlsOrRegexes","filter","urlOrRegexp","toString","map","permissiveRegexp","replace","p","Boolean","tags","querySelectorAll","indexOffset","forEach","index","scriptNode","head","appendChild","splice","disconnect"],"mappings":"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"}