dashboard_widget.js
2 years ago
dashboard_widget.js.map
2 years ago
download.js
2 years ago
download.js.map
2 years ago
index.es.aa861507.js
2 years ago
index.es.aa861507.js.map
2 years ago
index.js
2 years ago
index.js.map
2 years ago
layout.js
2 years ago
layout.js.map
2 years ago
purify.2550ab20.js
2 years ago
purify.2550ab20.js.map
2 years ago
settings.js
2 years ago
settings.js.map
2 years ago
purify.2550ab20.js
1843 lines
| 1 | // modules are defined as an array |
| 2 | // [ module function, map of requires ] |
| 3 | // |
| 4 | // map of requires is short require name -> numeric require |
| 5 | // |
| 6 | // anything defined in a previous bundle is accessed via the |
| 7 | // orig method which is the require for previous bundles |
| 8 | |
| 9 | (function (modules, entry, mainEntry, parcelRequireName, globalName) { |
| 10 | /* eslint-disable no-undef */ |
| 11 | var globalObject = |
| 12 | typeof globalThis !== 'undefined' |
| 13 | ? globalThis |
| 14 | : typeof self !== 'undefined' |
| 15 | ? self |
| 16 | : typeof window !== 'undefined' |
| 17 | ? window |
| 18 | : typeof global !== 'undefined' |
| 19 | ? global |
| 20 | : {}; |
| 21 | /* eslint-enable no-undef */ |
| 22 | |
| 23 | // Save the require from previous bundle to this closure if any |
| 24 | var previousRequire = |
| 25 | typeof globalObject[parcelRequireName] === 'function' && |
| 26 | globalObject[parcelRequireName]; |
| 27 | |
| 28 | var cache = previousRequire.cache || {}; |
| 29 | // Do not use `require` to prevent Webpack from trying to bundle this call |
| 30 | var nodeRequire = |
| 31 | typeof module !== 'undefined' && |
| 32 | typeof module.require === 'function' && |
| 33 | module.require.bind(module); |
| 34 | |
| 35 | function newRequire(name, jumped) { |
| 36 | if (!cache[name]) { |
| 37 | if (!modules[name]) { |
| 38 | // if we cannot find the module within our internal map or |
| 39 | // cache jump to the current global require ie. the last bundle |
| 40 | // that was added to the page. |
| 41 | var currentRequire = |
| 42 | typeof globalObject[parcelRequireName] === 'function' && |
| 43 | globalObject[parcelRequireName]; |
| 44 | if (!jumped && currentRequire) { |
| 45 | return currentRequire(name, true); |
| 46 | } |
| 47 | |
| 48 | // If there are other bundles on this page the require from the |
| 49 | // previous one is saved to 'previousRequire'. Repeat this as |
| 50 | // many times as there are bundles until the module is found or |
| 51 | // we exhaust the require chain. |
| 52 | if (previousRequire) { |
| 53 | return previousRequire(name, true); |
| 54 | } |
| 55 | |
| 56 | // Try the node require function if it exists. |
| 57 | if (nodeRequire && typeof name === 'string') { |
| 58 | return nodeRequire(name); |
| 59 | } |
| 60 | |
| 61 | var err = new Error("Cannot find module '" + name + "'"); |
| 62 | err.code = 'MODULE_NOT_FOUND'; |
| 63 | throw err; |
| 64 | } |
| 65 | |
| 66 | localRequire.resolve = resolve; |
| 67 | localRequire.cache = {}; |
| 68 | |
| 69 | var module = (cache[name] = new newRequire.Module(name)); |
| 70 | |
| 71 | modules[name][0].call( |
| 72 | module.exports, |
| 73 | localRequire, |
| 74 | module, |
| 75 | module.exports, |
| 76 | this |
| 77 | ); |
| 78 | } |
| 79 | |
| 80 | return cache[name].exports; |
| 81 | |
| 82 | function localRequire(x) { |
| 83 | var res = localRequire.resolve(x); |
| 84 | return res === false ? {} : newRequire(res); |
| 85 | } |
| 86 | |
| 87 | function resolve(x) { |
| 88 | var id = modules[name][1][x]; |
| 89 | return id != null ? id : x; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | function Module(moduleName) { |
| 94 | this.id = moduleName; |
| 95 | this.bundle = newRequire; |
| 96 | this.exports = {}; |
| 97 | } |
| 98 | |
| 99 | newRequire.isParcelRequire = true; |
| 100 | newRequire.Module = Module; |
| 101 | newRequire.modules = modules; |
| 102 | newRequire.cache = cache; |
| 103 | newRequire.parent = previousRequire; |
| 104 | newRequire.register = function (id, exports) { |
| 105 | modules[id] = [ |
| 106 | function (require, module) { |
| 107 | module.exports = exports; |
| 108 | }, |
| 109 | {}, |
| 110 | ]; |
| 111 | }; |
| 112 | |
| 113 | Object.defineProperty(newRequire, 'root', { |
| 114 | get: function () { |
| 115 | return globalObject[parcelRequireName]; |
| 116 | }, |
| 117 | }); |
| 118 | |
| 119 | globalObject[parcelRequireName] = newRequire; |
| 120 | |
| 121 | for (var i = 0; i < entry.length; i++) { |
| 122 | newRequire(entry[i]); |
| 123 | } |
| 124 | |
| 125 | if (mainEntry) { |
| 126 | // Expose entry point to Node, AMD or browser globals |
| 127 | // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js |
| 128 | var mainExports = newRequire(mainEntry); |
| 129 | |
| 130 | // CommonJS |
| 131 | if (typeof exports === 'object' && typeof module !== 'undefined') { |
| 132 | module.exports = mainExports; |
| 133 | |
| 134 | // RequireJS |
| 135 | } else if (typeof define === 'function' && define.amd) { |
| 136 | define(function () { |
| 137 | return mainExports; |
| 138 | }); |
| 139 | |
| 140 | // <script> |
| 141 | } else if (globalName) { |
| 142 | this[globalName] = mainExports; |
| 143 | } |
| 144 | } |
| 145 | })({"6VJva":[function(require,module,exports) { |
| 146 | /*! @license DOMPurify 2.4.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.7/LICENSE */ (function(global, factory) { |
| 147 | module.exports = factory(); |
| 148 | })(this, function() { |
| 149 | "use strict"; |
| 150 | function _typeof(obj1) { |
| 151 | "@babel/helpers - typeof"; |
| 152 | return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) { |
| 153 | return typeof obj; |
| 154 | } : function(obj) { |
| 155 | return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; |
| 156 | }, _typeof(obj1); |
| 157 | } |
| 158 | function _setPrototypeOf(o1, p1) { |
| 159 | _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { |
| 160 | o.__proto__ = p; |
| 161 | return o; |
| 162 | }; |
| 163 | return _setPrototypeOf(o1, p1); |
| 164 | } |
| 165 | function _isNativeReflectConstruct() { |
| 166 | if (typeof Reflect === "undefined" || !Reflect.construct) return false; |
| 167 | if (Reflect.construct.sham) return false; |
| 168 | if (typeof Proxy === "function") return true; |
| 169 | try { |
| 170 | Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {})); |
| 171 | return true; |
| 172 | } catch (e) { |
| 173 | return false; |
| 174 | } |
| 175 | } |
| 176 | function _construct(Parent1, args1, Class1) { |
| 177 | if (_isNativeReflectConstruct()) _construct = Reflect.construct; |
| 178 | else _construct = function _construct(Parent, args, Class) { |
| 179 | var a = [ |
| 180 | null |
| 181 | ]; |
| 182 | a.push.apply(a, args); |
| 183 | var Constructor = Function.bind.apply(Parent, a); |
| 184 | var instance = new Constructor(); |
| 185 | if (Class) _setPrototypeOf(instance, Class.prototype); |
| 186 | return instance; |
| 187 | }; |
| 188 | return _construct.apply(null, arguments); |
| 189 | } |
| 190 | function _toConsumableArray(arr) { |
| 191 | return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); |
| 192 | } |
| 193 | function _arrayWithoutHoles(arr) { |
| 194 | if (Array.isArray(arr)) return _arrayLikeToArray(arr); |
| 195 | } |
| 196 | function _iterableToArray(iter) { |
| 197 | if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); |
| 198 | } |
| 199 | function _unsupportedIterableToArray(o, minLen) { |
| 200 | if (!o) return; |
| 201 | if (typeof o === "string") return _arrayLikeToArray(o, minLen); |
| 202 | var n = Object.prototype.toString.call(o).slice(8, -1); |
| 203 | if (n === "Object" && o.constructor) n = o.constructor.name; |
| 204 | if (n === "Map" || n === "Set") return Array.from(o); |
| 205 | if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); |
| 206 | } |
| 207 | function _arrayLikeToArray(arr, len) { |
| 208 | if (len == null || len > arr.length) len = arr.length; |
| 209 | for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; |
| 210 | return arr2; |
| 211 | } |
| 212 | function _nonIterableSpread() { |
| 213 | throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); |
| 214 | } |
| 215 | var hasOwnProperty = Object.hasOwnProperty, setPrototypeOf = Object.setPrototypeOf, isFrozen = Object.isFrozen, getPrototypeOf = Object.getPrototypeOf, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
| 216 | var freeze = Object.freeze, seal = Object.seal, create = Object.create; // eslint-disable-line import/no-mutable-exports |
| 217 | var _ref = typeof Reflect !== "undefined" && Reflect, apply = _ref.apply, construct = _ref.construct; |
| 218 | if (!apply) apply = function apply(fun, thisValue, args) { |
| 219 | return fun.apply(thisValue, args); |
| 220 | }; |
| 221 | if (!freeze) freeze = function freeze(x) { |
| 222 | return x; |
| 223 | }; |
| 224 | if (!seal) seal = function seal(x) { |
| 225 | return x; |
| 226 | }; |
| 227 | if (!construct) construct = function construct(Func, args) { |
| 228 | return _construct(Func, _toConsumableArray(args)); |
| 229 | }; |
| 230 | var arrayForEach = unapply(Array.prototype.forEach); |
| 231 | var arrayPop = unapply(Array.prototype.pop); |
| 232 | var arrayPush = unapply(Array.prototype.push); |
| 233 | var stringToLowerCase = unapply(String.prototype.toLowerCase); |
| 234 | var stringToString = unapply(String.prototype.toString); |
| 235 | var stringMatch = unapply(String.prototype.match); |
| 236 | var stringReplace = unapply(String.prototype.replace); |
| 237 | var stringIndexOf = unapply(String.prototype.indexOf); |
| 238 | var stringTrim = unapply(String.prototype.trim); |
| 239 | var regExpTest = unapply(RegExp.prototype.test); |
| 240 | var typeErrorCreate = unconstruct(TypeError); |
| 241 | function unapply(func) { |
| 242 | return function(thisArg) { |
| 243 | for(var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++)args[_key - 1] = arguments[_key]; |
| 244 | return apply(func, thisArg, args); |
| 245 | }; |
| 246 | } |
| 247 | function unconstruct(func) { |
| 248 | return function() { |
| 249 | for(var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++)args[_key2] = arguments[_key2]; |
| 250 | return construct(func, args); |
| 251 | }; |
| 252 | } |
| 253 | /* Add properties to a lookup table */ function addToSet(set, array, transformCaseFunc) { |
| 254 | var _transformCaseFunc; |
| 255 | transformCaseFunc = (_transformCaseFunc = transformCaseFunc) !== null && _transformCaseFunc !== void 0 ? _transformCaseFunc : stringToLowerCase; |
| 256 | if (setPrototypeOf) // Make 'in' and truthy checks like Boolean(set.constructor) |
| 257 | // independent of any properties defined on Object.prototype. |
| 258 | // Prevent prototype setters from intercepting set as a this value. |
| 259 | setPrototypeOf(set, null); |
| 260 | var l = array.length; |
| 261 | while(l--){ |
| 262 | var element = array[l]; |
| 263 | if (typeof element === "string") { |
| 264 | var lcElement = transformCaseFunc(element); |
| 265 | if (lcElement !== element) { |
| 266 | // Config presets (e.g. tags.js, attrs.js) are immutable. |
| 267 | if (!isFrozen(array)) array[l] = lcElement; |
| 268 | element = lcElement; |
| 269 | } |
| 270 | } |
| 271 | set[element] = true; |
| 272 | } |
| 273 | return set; |
| 274 | } |
| 275 | /* Shallow clone an object */ function clone(object) { |
| 276 | var newObject = create(null); |
| 277 | var property; |
| 278 | for(property in object)if (apply(hasOwnProperty, object, [ |
| 279 | property |
| 280 | ]) === true) newObject[property] = object[property]; |
| 281 | return newObject; |
| 282 | } |
| 283 | /* IE10 doesn't support __lookupGetter__ so lets' |
| 284 | * simulate it. It also automatically checks |
| 285 | * if the prop is function or getter and behaves |
| 286 | * accordingly. */ function lookupGetter(object, prop) { |
| 287 | while(object !== null){ |
| 288 | var desc = getOwnPropertyDescriptor(object, prop); |
| 289 | if (desc) { |
| 290 | if (desc.get) return unapply(desc.get); |
| 291 | if (typeof desc.value === "function") return unapply(desc.value); |
| 292 | } |
| 293 | object = getPrototypeOf(object); |
| 294 | } |
| 295 | function fallbackValue(element) { |
| 296 | console.warn("fallback value for", element); |
| 297 | return null; |
| 298 | } |
| 299 | return fallbackValue; |
| 300 | } |
| 301 | var html$1 = freeze([ |
| 302 | "a", |
| 303 | "abbr", |
| 304 | "acronym", |
| 305 | "address", |
| 306 | "area", |
| 307 | "article", |
| 308 | "aside", |
| 309 | "audio", |
| 310 | "b", |
| 311 | "bdi", |
| 312 | "bdo", |
| 313 | "big", |
| 314 | "blink", |
| 315 | "blockquote", |
| 316 | "body", |
| 317 | "br", |
| 318 | "button", |
| 319 | "canvas", |
| 320 | "caption", |
| 321 | "center", |
| 322 | "cite", |
| 323 | "code", |
| 324 | "col", |
| 325 | "colgroup", |
| 326 | "content", |
| 327 | "data", |
| 328 | "datalist", |
| 329 | "dd", |
| 330 | "decorator", |
| 331 | "del", |
| 332 | "details", |
| 333 | "dfn", |
| 334 | "dialog", |
| 335 | "dir", |
| 336 | "div", |
| 337 | "dl", |
| 338 | "dt", |
| 339 | "element", |
| 340 | "em", |
| 341 | "fieldset", |
| 342 | "figcaption", |
| 343 | "figure", |
| 344 | "font", |
| 345 | "footer", |
| 346 | "form", |
| 347 | "h1", |
| 348 | "h2", |
| 349 | "h3", |
| 350 | "h4", |
| 351 | "h5", |
| 352 | "h6", |
| 353 | "head", |
| 354 | "header", |
| 355 | "hgroup", |
| 356 | "hr", |
| 357 | "html", |
| 358 | "i", |
| 359 | "img", |
| 360 | "input", |
| 361 | "ins", |
| 362 | "kbd", |
| 363 | "label", |
| 364 | "legend", |
| 365 | "li", |
| 366 | "main", |
| 367 | "map", |
| 368 | "mark", |
| 369 | "marquee", |
| 370 | "menu", |
| 371 | "menuitem", |
| 372 | "meter", |
| 373 | "nav", |
| 374 | "nobr", |
| 375 | "ol", |
| 376 | "optgroup", |
| 377 | "option", |
| 378 | "output", |
| 379 | "p", |
| 380 | "picture", |
| 381 | "pre", |
| 382 | "progress", |
| 383 | "q", |
| 384 | "rp", |
| 385 | "rt", |
| 386 | "ruby", |
| 387 | "s", |
| 388 | "samp", |
| 389 | "section", |
| 390 | "select", |
| 391 | "shadow", |
| 392 | "small", |
| 393 | "source", |
| 394 | "spacer", |
| 395 | "span", |
| 396 | "strike", |
| 397 | "strong", |
| 398 | "style", |
| 399 | "sub", |
| 400 | "summary", |
| 401 | "sup", |
| 402 | "table", |
| 403 | "tbody", |
| 404 | "td", |
| 405 | "template", |
| 406 | "textarea", |
| 407 | "tfoot", |
| 408 | "th", |
| 409 | "thead", |
| 410 | "time", |
| 411 | "tr", |
| 412 | "track", |
| 413 | "tt", |
| 414 | "u", |
| 415 | "ul", |
| 416 | "var", |
| 417 | "video", |
| 418 | "wbr" |
| 419 | ]); // SVG |
| 420 | var svg$1 = freeze([ |
| 421 | "svg", |
| 422 | "a", |
| 423 | "altglyph", |
| 424 | "altglyphdef", |
| 425 | "altglyphitem", |
| 426 | "animatecolor", |
| 427 | "animatemotion", |
| 428 | "animatetransform", |
| 429 | "circle", |
| 430 | "clippath", |
| 431 | "defs", |
| 432 | "desc", |
| 433 | "ellipse", |
| 434 | "filter", |
| 435 | "font", |
| 436 | "g", |
| 437 | "glyph", |
| 438 | "glyphref", |
| 439 | "hkern", |
| 440 | "image", |
| 441 | "line", |
| 442 | "lineargradient", |
| 443 | "marker", |
| 444 | "mask", |
| 445 | "metadata", |
| 446 | "mpath", |
| 447 | "path", |
| 448 | "pattern", |
| 449 | "polygon", |
| 450 | "polyline", |
| 451 | "radialgradient", |
| 452 | "rect", |
| 453 | "stop", |
| 454 | "style", |
| 455 | "switch", |
| 456 | "symbol", |
| 457 | "text", |
| 458 | "textpath", |
| 459 | "title", |
| 460 | "tref", |
| 461 | "tspan", |
| 462 | "view", |
| 463 | "vkern" |
| 464 | ]); |
| 465 | var svgFilters = freeze([ |
| 466 | "feBlend", |
| 467 | "feColorMatrix", |
| 468 | "feComponentTransfer", |
| 469 | "feComposite", |
| 470 | "feConvolveMatrix", |
| 471 | "feDiffuseLighting", |
| 472 | "feDisplacementMap", |
| 473 | "feDistantLight", |
| 474 | "feFlood", |
| 475 | "feFuncA", |
| 476 | "feFuncB", |
| 477 | "feFuncG", |
| 478 | "feFuncR", |
| 479 | "feGaussianBlur", |
| 480 | "feImage", |
| 481 | "feMerge", |
| 482 | "feMergeNode", |
| 483 | "feMorphology", |
| 484 | "feOffset", |
| 485 | "fePointLight", |
| 486 | "feSpecularLighting", |
| 487 | "feSpotLight", |
| 488 | "feTile", |
| 489 | "feTurbulence" |
| 490 | ]); // List of SVG elements that are disallowed by default. |
| 491 | // We still need to know them so that we can do namespace |
| 492 | // checks properly in case one wants to add them to |
| 493 | // allow-list. |
| 494 | var svgDisallowed = freeze([ |
| 495 | "animate", |
| 496 | "color-profile", |
| 497 | "cursor", |
| 498 | "discard", |
| 499 | "fedropshadow", |
| 500 | "font-face", |
| 501 | "font-face-format", |
| 502 | "font-face-name", |
| 503 | "font-face-src", |
| 504 | "font-face-uri", |
| 505 | "foreignobject", |
| 506 | "hatch", |
| 507 | "hatchpath", |
| 508 | "mesh", |
| 509 | "meshgradient", |
| 510 | "meshpatch", |
| 511 | "meshrow", |
| 512 | "missing-glyph", |
| 513 | "script", |
| 514 | "set", |
| 515 | "solidcolor", |
| 516 | "unknown", |
| 517 | "use" |
| 518 | ]); |
| 519 | var mathMl$1 = freeze([ |
| 520 | "math", |
| 521 | "menclose", |
| 522 | "merror", |
| 523 | "mfenced", |
| 524 | "mfrac", |
| 525 | "mglyph", |
| 526 | "mi", |
| 527 | "mlabeledtr", |
| 528 | "mmultiscripts", |
| 529 | "mn", |
| 530 | "mo", |
| 531 | "mover", |
| 532 | "mpadded", |
| 533 | "mphantom", |
| 534 | "mroot", |
| 535 | "mrow", |
| 536 | "ms", |
| 537 | "mspace", |
| 538 | "msqrt", |
| 539 | "mstyle", |
| 540 | "msub", |
| 541 | "msup", |
| 542 | "msubsup", |
| 543 | "mtable", |
| 544 | "mtd", |
| 545 | "mtext", |
| 546 | "mtr", |
| 547 | "munder", |
| 548 | "munderover" |
| 549 | ]); // Similarly to SVG, we want to know all MathML elements, |
| 550 | // even those that we disallow by default. |
| 551 | var mathMlDisallowed = freeze([ |
| 552 | "maction", |
| 553 | "maligngroup", |
| 554 | "malignmark", |
| 555 | "mlongdiv", |
| 556 | "mscarries", |
| 557 | "mscarry", |
| 558 | "msgroup", |
| 559 | "mstack", |
| 560 | "msline", |
| 561 | "msrow", |
| 562 | "semantics", |
| 563 | "annotation", |
| 564 | "annotation-xml", |
| 565 | "mprescripts", |
| 566 | "none" |
| 567 | ]); |
| 568 | var text = freeze([ |
| 569 | "#text" |
| 570 | ]); |
| 571 | var html1 = freeze([ |
| 572 | "accept", |
| 573 | "action", |
| 574 | "align", |
| 575 | "alt", |
| 576 | "autocapitalize", |
| 577 | "autocomplete", |
| 578 | "autopictureinpicture", |
| 579 | "autoplay", |
| 580 | "background", |
| 581 | "bgcolor", |
| 582 | "border", |
| 583 | "capture", |
| 584 | "cellpadding", |
| 585 | "cellspacing", |
| 586 | "checked", |
| 587 | "cite", |
| 588 | "class", |
| 589 | "clear", |
| 590 | "color", |
| 591 | "cols", |
| 592 | "colspan", |
| 593 | "controls", |
| 594 | "controlslist", |
| 595 | "coords", |
| 596 | "crossorigin", |
| 597 | "datetime", |
| 598 | "decoding", |
| 599 | "default", |
| 600 | "dir", |
| 601 | "disabled", |
| 602 | "disablepictureinpicture", |
| 603 | "disableremoteplayback", |
| 604 | "download", |
| 605 | "draggable", |
| 606 | "enctype", |
| 607 | "enterkeyhint", |
| 608 | "face", |
| 609 | "for", |
| 610 | "headers", |
| 611 | "height", |
| 612 | "hidden", |
| 613 | "high", |
| 614 | "href", |
| 615 | "hreflang", |
| 616 | "id", |
| 617 | "inputmode", |
| 618 | "integrity", |
| 619 | "ismap", |
| 620 | "kind", |
| 621 | "label", |
| 622 | "lang", |
| 623 | "list", |
| 624 | "loading", |
| 625 | "loop", |
| 626 | "low", |
| 627 | "max", |
| 628 | "maxlength", |
| 629 | "media", |
| 630 | "method", |
| 631 | "min", |
| 632 | "minlength", |
| 633 | "multiple", |
| 634 | "muted", |
| 635 | "name", |
| 636 | "nonce", |
| 637 | "noshade", |
| 638 | "novalidate", |
| 639 | "nowrap", |
| 640 | "open", |
| 641 | "optimum", |
| 642 | "pattern", |
| 643 | "placeholder", |
| 644 | "playsinline", |
| 645 | "poster", |
| 646 | "preload", |
| 647 | "pubdate", |
| 648 | "radiogroup", |
| 649 | "readonly", |
| 650 | "rel", |
| 651 | "required", |
| 652 | "rev", |
| 653 | "reversed", |
| 654 | "role", |
| 655 | "rows", |
| 656 | "rowspan", |
| 657 | "spellcheck", |
| 658 | "scope", |
| 659 | "selected", |
| 660 | "shape", |
| 661 | "size", |
| 662 | "sizes", |
| 663 | "span", |
| 664 | "srclang", |
| 665 | "start", |
| 666 | "src", |
| 667 | "srcset", |
| 668 | "step", |
| 669 | "style", |
| 670 | "summary", |
| 671 | "tabindex", |
| 672 | "title", |
| 673 | "translate", |
| 674 | "type", |
| 675 | "usemap", |
| 676 | "valign", |
| 677 | "value", |
| 678 | "width", |
| 679 | "xmlns", |
| 680 | "slot" |
| 681 | ]); |
| 682 | var svg = freeze([ |
| 683 | "accent-height", |
| 684 | "accumulate", |
| 685 | "additive", |
| 686 | "alignment-baseline", |
| 687 | "ascent", |
| 688 | "attributename", |
| 689 | "attributetype", |
| 690 | "azimuth", |
| 691 | "basefrequency", |
| 692 | "baseline-shift", |
| 693 | "begin", |
| 694 | "bias", |
| 695 | "by", |
| 696 | "class", |
| 697 | "clip", |
| 698 | "clippathunits", |
| 699 | "clip-path", |
| 700 | "clip-rule", |
| 701 | "color", |
| 702 | "color-interpolation", |
| 703 | "color-interpolation-filters", |
| 704 | "color-profile", |
| 705 | "color-rendering", |
| 706 | "cx", |
| 707 | "cy", |
| 708 | "d", |
| 709 | "dx", |
| 710 | "dy", |
| 711 | "diffuseconstant", |
| 712 | "direction", |
| 713 | "display", |
| 714 | "divisor", |
| 715 | "dur", |
| 716 | "edgemode", |
| 717 | "elevation", |
| 718 | "end", |
| 719 | "fill", |
| 720 | "fill-opacity", |
| 721 | "fill-rule", |
| 722 | "filter", |
| 723 | "filterunits", |
| 724 | "flood-color", |
| 725 | "flood-opacity", |
| 726 | "font-family", |
| 727 | "font-size", |
| 728 | "font-size-adjust", |
| 729 | "font-stretch", |
| 730 | "font-style", |
| 731 | "font-variant", |
| 732 | "font-weight", |
| 733 | "fx", |
| 734 | "fy", |
| 735 | "g1", |
| 736 | "g2", |
| 737 | "glyph-name", |
| 738 | "glyphref", |
| 739 | "gradientunits", |
| 740 | "gradienttransform", |
| 741 | "height", |
| 742 | "href", |
| 743 | "id", |
| 744 | "image-rendering", |
| 745 | "in", |
| 746 | "in2", |
| 747 | "k", |
| 748 | "k1", |
| 749 | "k2", |
| 750 | "k3", |
| 751 | "k4", |
| 752 | "kerning", |
| 753 | "keypoints", |
| 754 | "keysplines", |
| 755 | "keytimes", |
| 756 | "lang", |
| 757 | "lengthadjust", |
| 758 | "letter-spacing", |
| 759 | "kernelmatrix", |
| 760 | "kernelunitlength", |
| 761 | "lighting-color", |
| 762 | "local", |
| 763 | "marker-end", |
| 764 | "marker-mid", |
| 765 | "marker-start", |
| 766 | "markerheight", |
| 767 | "markerunits", |
| 768 | "markerwidth", |
| 769 | "maskcontentunits", |
| 770 | "maskunits", |
| 771 | "max", |
| 772 | "mask", |
| 773 | "media", |
| 774 | "method", |
| 775 | "mode", |
| 776 | "min", |
| 777 | "name", |
| 778 | "numoctaves", |
| 779 | "offset", |
| 780 | "operator", |
| 781 | "opacity", |
| 782 | "order", |
| 783 | "orient", |
| 784 | "orientation", |
| 785 | "origin", |
| 786 | "overflow", |
| 787 | "paint-order", |
| 788 | "path", |
| 789 | "pathlength", |
| 790 | "patterncontentunits", |
| 791 | "patterntransform", |
| 792 | "patternunits", |
| 793 | "points", |
| 794 | "preservealpha", |
| 795 | "preserveaspectratio", |
| 796 | "primitiveunits", |
| 797 | "r", |
| 798 | "rx", |
| 799 | "ry", |
| 800 | "radius", |
| 801 | "refx", |
| 802 | "refy", |
| 803 | "repeatcount", |
| 804 | "repeatdur", |
| 805 | "restart", |
| 806 | "result", |
| 807 | "rotate", |
| 808 | "scale", |
| 809 | "seed", |
| 810 | "shape-rendering", |
| 811 | "specularconstant", |
| 812 | "specularexponent", |
| 813 | "spreadmethod", |
| 814 | "startoffset", |
| 815 | "stddeviation", |
| 816 | "stitchtiles", |
| 817 | "stop-color", |
| 818 | "stop-opacity", |
| 819 | "stroke-dasharray", |
| 820 | "stroke-dashoffset", |
| 821 | "stroke-linecap", |
| 822 | "stroke-linejoin", |
| 823 | "stroke-miterlimit", |
| 824 | "stroke-opacity", |
| 825 | "stroke", |
| 826 | "stroke-width", |
| 827 | "style", |
| 828 | "surfacescale", |
| 829 | "systemlanguage", |
| 830 | "tabindex", |
| 831 | "targetx", |
| 832 | "targety", |
| 833 | "transform", |
| 834 | "transform-origin", |
| 835 | "text-anchor", |
| 836 | "text-decoration", |
| 837 | "text-rendering", |
| 838 | "textlength", |
| 839 | "type", |
| 840 | "u1", |
| 841 | "u2", |
| 842 | "unicode", |
| 843 | "values", |
| 844 | "viewbox", |
| 845 | "visibility", |
| 846 | "version", |
| 847 | "vert-adv-y", |
| 848 | "vert-origin-x", |
| 849 | "vert-origin-y", |
| 850 | "width", |
| 851 | "word-spacing", |
| 852 | "wrap", |
| 853 | "writing-mode", |
| 854 | "xchannelselector", |
| 855 | "ychannelselector", |
| 856 | "x", |
| 857 | "x1", |
| 858 | "x2", |
| 859 | "xmlns", |
| 860 | "y", |
| 861 | "y1", |
| 862 | "y2", |
| 863 | "z", |
| 864 | "zoomandpan" |
| 865 | ]); |
| 866 | var mathMl = freeze([ |
| 867 | "accent", |
| 868 | "accentunder", |
| 869 | "align", |
| 870 | "bevelled", |
| 871 | "close", |
| 872 | "columnsalign", |
| 873 | "columnlines", |
| 874 | "columnspan", |
| 875 | "denomalign", |
| 876 | "depth", |
| 877 | "dir", |
| 878 | "display", |
| 879 | "displaystyle", |
| 880 | "encoding", |
| 881 | "fence", |
| 882 | "frame", |
| 883 | "height", |
| 884 | "href", |
| 885 | "id", |
| 886 | "largeop", |
| 887 | "length", |
| 888 | "linethickness", |
| 889 | "lspace", |
| 890 | "lquote", |
| 891 | "mathbackground", |
| 892 | "mathcolor", |
| 893 | "mathsize", |
| 894 | "mathvariant", |
| 895 | "maxsize", |
| 896 | "minsize", |
| 897 | "movablelimits", |
| 898 | "notation", |
| 899 | "numalign", |
| 900 | "open", |
| 901 | "rowalign", |
| 902 | "rowlines", |
| 903 | "rowspacing", |
| 904 | "rowspan", |
| 905 | "rspace", |
| 906 | "rquote", |
| 907 | "scriptlevel", |
| 908 | "scriptminsize", |
| 909 | "scriptsizemultiplier", |
| 910 | "selection", |
| 911 | "separator", |
| 912 | "separators", |
| 913 | "stretchy", |
| 914 | "subscriptshift", |
| 915 | "supscriptshift", |
| 916 | "symmetric", |
| 917 | "voffset", |
| 918 | "width", |
| 919 | "xmlns" |
| 920 | ]); |
| 921 | var xml = freeze([ |
| 922 | "xlink:href", |
| 923 | "xml:id", |
| 924 | "xlink:title", |
| 925 | "xml:space", |
| 926 | "xmlns:xlink" |
| 927 | ]); |
| 928 | var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode |
| 929 | var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm); |
| 930 | var TMPLIT_EXPR = seal(/\${[\w\W]*}/gm); |
| 931 | var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape |
| 932 | var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape |
| 933 | var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape |
| 934 | ); |
| 935 | var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); |
| 936 | var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex |
| 937 | ); |
| 938 | var DOCTYPE_NAME = seal(/^html$/i); |
| 939 | var getGlobal = function getGlobal() { |
| 940 | return typeof window === "undefined" ? null : window; |
| 941 | }; |
| 942 | /** |
| 943 | * Creates a no-op policy for internal use only. |
| 944 | * Don't export this function outside this module! |
| 945 | * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory. |
| 946 | * @param {Document} document The document object (to determine policy name suffix) |
| 947 | * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types |
| 948 | * are not supported). |
| 949 | */ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) { |
| 950 | if (_typeof(trustedTypes) !== "object" || typeof trustedTypes.createPolicy !== "function") return null; |
| 951 | // Allow the callers to control the unique policy name |
| 952 | // by adding a data-tt-policy-suffix to the script element with the DOMPurify. |
| 953 | // Policy creation with duplicate names throws in Trusted Types. |
| 954 | var suffix = null; |
| 955 | var ATTR_NAME = "data-tt-policy-suffix"; |
| 956 | if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) suffix = document.currentScript.getAttribute(ATTR_NAME); |
| 957 | var policyName = "dompurify" + (suffix ? "#" + suffix : ""); |
| 958 | try { |
| 959 | return trustedTypes.createPolicy(policyName, { |
| 960 | createHTML: function createHTML(html) { |
| 961 | return html; |
| 962 | }, |
| 963 | createScriptURL: function createScriptURL(scriptUrl) { |
| 964 | return scriptUrl; |
| 965 | } |
| 966 | }); |
| 967 | } catch (_) { |
| 968 | // Policy creation failed (most likely another DOMPurify script has |
| 969 | // already run). Skip creating the policy, as this will only cause errors |
| 970 | // if TT are enforced. |
| 971 | console.warn("TrustedTypes policy " + policyName + " could not be created."); |
| 972 | return null; |
| 973 | } |
| 974 | }; |
| 975 | function createDOMPurify() { |
| 976 | var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal(); |
| 977 | var DOMPurify = function DOMPurify(root) { |
| 978 | return createDOMPurify(root); |
| 979 | }; |
| 980 | /** |
| 981 | * Version label, exposed for easier checks |
| 982 | * if DOMPurify is up to date or not |
| 983 | */ DOMPurify.version = "2.4.7"; |
| 984 | /** |
| 985 | * Array of elements that DOMPurify removed during sanitation. |
| 986 | * Empty if nothing was removed. |
| 987 | */ DOMPurify.removed = []; |
| 988 | if (!window || !window.document || window.document.nodeType !== 9) { |
| 989 | // Not running in a browser, provide a factory function |
| 990 | // so that you can pass your own Window |
| 991 | DOMPurify.isSupported = false; |
| 992 | return DOMPurify; |
| 993 | } |
| 994 | var originalDocument = window.document; |
| 995 | var document = window.document; |
| 996 | var DocumentFragment = window.DocumentFragment, HTMLTemplateElement = window.HTMLTemplateElement, Node = window.Node, Element = window.Element, NodeFilter = window.NodeFilter, _window$NamedNodeMap = window.NamedNodeMap, NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap, HTMLFormElement = window.HTMLFormElement, DOMParser = window.DOMParser, trustedTypes = window.trustedTypes; |
| 997 | var ElementPrototype = Element.prototype; |
| 998 | var cloneNode = lookupGetter(ElementPrototype, "cloneNode"); |
| 999 | var getNextSibling = lookupGetter(ElementPrototype, "nextSibling"); |
| 1000 | var getChildNodes = lookupGetter(ElementPrototype, "childNodes"); |
| 1001 | var getParentNode = lookupGetter(ElementPrototype, "parentNode"); // As per issue #47, the web-components registry is inherited by a |
| 1002 | // new document created via createHTMLDocument. As per the spec |
| 1003 | // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries) |
| 1004 | // a new empty registry is used when creating a template contents owner |
| 1005 | // document, so we use that as our parent document to ensure nothing |
| 1006 | // is inherited. |
| 1007 | if (typeof HTMLTemplateElement === "function") { |
| 1008 | var template = document.createElement("template"); |
| 1009 | if (template.content && template.content.ownerDocument) document = template.content.ownerDocument; |
| 1010 | } |
| 1011 | var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument); |
| 1012 | var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML("") : ""; |
| 1013 | var _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName; |
| 1014 | var importNode = originalDocument.importNode; |
| 1015 | var documentMode = {}; |
| 1016 | try { |
| 1017 | documentMode = clone(document).documentMode ? document.documentMode : {}; |
| 1018 | } catch (_) {} |
| 1019 | var hooks = {}; |
| 1020 | /** |
| 1021 | * Expose whether this browser supports running the full DOMPurify. |
| 1022 | */ DOMPurify.isSupported = typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== undefined && documentMode !== 9; |
| 1023 | var MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, TMPLIT_EXPR$1 = TMPLIT_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE; |
| 1024 | var IS_ALLOWED_URI$1 = IS_ALLOWED_URI; |
| 1025 | /** |
| 1026 | * We consider the elements and attributes below to be safe. Ideally |
| 1027 | * don't add any new ones but feel free to remove unwanted ones. |
| 1028 | */ /* allowed element names */ var ALLOWED_TAGS = null; |
| 1029 | var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text))); |
| 1030 | /* Allowed attribute names */ var ALLOWED_ATTR = null; |
| 1031 | var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html1), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml))); |
| 1032 | /* |
| 1033 | * Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements. |
| 1034 | * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements) |
| 1035 | * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list) |
| 1036 | * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`. |
| 1037 | */ var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, { |
| 1038 | tagNameCheck: { |
| 1039 | writable: true, |
| 1040 | configurable: false, |
| 1041 | enumerable: true, |
| 1042 | value: null |
| 1043 | }, |
| 1044 | attributeNameCheck: { |
| 1045 | writable: true, |
| 1046 | configurable: false, |
| 1047 | enumerable: true, |
| 1048 | value: null |
| 1049 | }, |
| 1050 | allowCustomizedBuiltInElements: { |
| 1051 | writable: true, |
| 1052 | configurable: false, |
| 1053 | enumerable: true, |
| 1054 | value: false |
| 1055 | } |
| 1056 | })); |
| 1057 | /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */ var FORBID_TAGS = null; |
| 1058 | /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */ var FORBID_ATTR = null; |
| 1059 | /* Decide if ARIA attributes are okay */ var ALLOW_ARIA_ATTR = true; |
| 1060 | /* Decide if custom data attributes are okay */ var ALLOW_DATA_ATTR = true; |
| 1061 | /* Decide if unknown protocols are okay */ var ALLOW_UNKNOWN_PROTOCOLS = false; |
| 1062 | /* Decide if self-closing tags in attributes are allowed. |
| 1063 | * Usually removed due to a mXSS issue in jQuery 3.0 */ var ALLOW_SELF_CLOSE_IN_ATTR = true; |
| 1064 | /* Output should be safe for common template engines. |
| 1065 | * This means, DOMPurify removes data attributes, mustaches and ERB |
| 1066 | */ var SAFE_FOR_TEMPLATES = false; |
| 1067 | /* Decide if document with <html>... should be returned */ var WHOLE_DOCUMENT = false; |
| 1068 | /* Track whether config is already set on this instance of DOMPurify. */ var SET_CONFIG = false; |
| 1069 | /* Decide if all elements (e.g. style, script) must be children of |
| 1070 | * document.body. By default, browsers might move them to document.head */ var FORCE_BODY = false; |
| 1071 | /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html |
| 1072 | * string (or a TrustedHTML object if Trusted Types are supported). |
| 1073 | * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead |
| 1074 | */ var RETURN_DOM = false; |
| 1075 | /* Decide if a DOM `DocumentFragment` should be returned, instead of a html |
| 1076 | * string (or a TrustedHTML object if Trusted Types are supported) */ var RETURN_DOM_FRAGMENT = false; |
| 1077 | /* Try to return a Trusted Type object instead of a string, return a string in |
| 1078 | * case Trusted Types are not supported */ var RETURN_TRUSTED_TYPE = false; |
| 1079 | /* Output should be free from DOM clobbering attacks? |
| 1080 | * This sanitizes markups named with colliding, clobberable built-in DOM APIs. |
| 1081 | */ var SANITIZE_DOM = true; |
| 1082 | /* Achieve full DOM Clobbering protection by isolating the namespace of named |
| 1083 | * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules. |
| 1084 | * |
| 1085 | * HTML/DOM spec rules that enable DOM Clobbering: |
| 1086 | * - Named Access on Window (§7.3.3) |
| 1087 | * - DOM Tree Accessors (§3.1.5) |
| 1088 | * - Form Element Parent-Child Relations (§4.10.3) |
| 1089 | * - Iframe srcdoc / Nested WindowProxies (§4.8.5) |
| 1090 | * - HTMLCollection (§4.2.10.2) |
| 1091 | * |
| 1092 | * Namespace isolation is implemented by prefixing `id` and `name` attributes |
| 1093 | * with a constant string, i.e., `user-content-` |
| 1094 | */ var SANITIZE_NAMED_PROPS = false; |
| 1095 | var SANITIZE_NAMED_PROPS_PREFIX = "user-content-"; |
| 1096 | /* Keep element content when removing element? */ var KEEP_CONTENT = true; |
| 1097 | /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead |
| 1098 | * of importing it into a new Document and returning a sanitized copy */ var IN_PLACE = false; |
| 1099 | /* Allow usage of profiles like html, svg and mathMl */ var USE_PROFILES = {}; |
| 1100 | /* Tags to ignore content of when KEEP_CONTENT is true */ var FORBID_CONTENTS = null; |
| 1101 | var DEFAULT_FORBID_CONTENTS = addToSet({}, [ |
| 1102 | "annotation-xml", |
| 1103 | "audio", |
| 1104 | "colgroup", |
| 1105 | "desc", |
| 1106 | "foreignobject", |
| 1107 | "head", |
| 1108 | "iframe", |
| 1109 | "math", |
| 1110 | "mi", |
| 1111 | "mn", |
| 1112 | "mo", |
| 1113 | "ms", |
| 1114 | "mtext", |
| 1115 | "noembed", |
| 1116 | "noframes", |
| 1117 | "noscript", |
| 1118 | "plaintext", |
| 1119 | "script", |
| 1120 | "style", |
| 1121 | "svg", |
| 1122 | "template", |
| 1123 | "thead", |
| 1124 | "title", |
| 1125 | "video", |
| 1126 | "xmp" |
| 1127 | ]); |
| 1128 | /* Tags that are safe for data: URIs */ var DATA_URI_TAGS = null; |
| 1129 | var DEFAULT_DATA_URI_TAGS = addToSet({}, [ |
| 1130 | "audio", |
| 1131 | "video", |
| 1132 | "img", |
| 1133 | "source", |
| 1134 | "image", |
| 1135 | "track" |
| 1136 | ]); |
| 1137 | /* Attributes safe for values like "javascript:" */ var URI_SAFE_ATTRIBUTES = null; |
| 1138 | var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [ |
| 1139 | "alt", |
| 1140 | "class", |
| 1141 | "for", |
| 1142 | "id", |
| 1143 | "label", |
| 1144 | "name", |
| 1145 | "pattern", |
| 1146 | "placeholder", |
| 1147 | "role", |
| 1148 | "summary", |
| 1149 | "title", |
| 1150 | "value", |
| 1151 | "style", |
| 1152 | "xmlns" |
| 1153 | ]); |
| 1154 | var MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML"; |
| 1155 | var SVG_NAMESPACE = "http://www.w3.org/2000/svg"; |
| 1156 | var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; |
| 1157 | /* Document namespace */ var NAMESPACE = HTML_NAMESPACE; |
| 1158 | var IS_EMPTY_INPUT = false; |
| 1159 | /* Allowed XHTML+XML namespaces */ var ALLOWED_NAMESPACES = null; |
| 1160 | var DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [ |
| 1161 | MATHML_NAMESPACE, |
| 1162 | SVG_NAMESPACE, |
| 1163 | HTML_NAMESPACE |
| 1164 | ], stringToString); |
| 1165 | /* Parsing of strict XHTML documents */ var PARSER_MEDIA_TYPE; |
| 1166 | var SUPPORTED_PARSER_MEDIA_TYPES = [ |
| 1167 | "application/xhtml+xml", |
| 1168 | "text/html" |
| 1169 | ]; |
| 1170 | var DEFAULT_PARSER_MEDIA_TYPE = "text/html"; |
| 1171 | var transformCaseFunc; |
| 1172 | /* Keep a reference to config to pass to hooks */ var CONFIG = null; |
| 1173 | /* Ideally, do not touch anything below this line */ /* ______________________________________________ */ var formElement = document.createElement("form"); |
| 1174 | var isRegexOrFunction = function isRegexOrFunction(testValue) { |
| 1175 | return testValue instanceof RegExp || testValue instanceof Function; |
| 1176 | }; |
| 1177 | /** |
| 1178 | * _parseConfig |
| 1179 | * |
| 1180 | * @param {Object} cfg optional config literal |
| 1181 | */ // eslint-disable-next-line complexity |
| 1182 | var _parseConfig = function _parseConfig(cfg) { |
| 1183 | if (CONFIG && CONFIG === cfg) return; |
| 1184 | /* Shield configuration object from tampering */ if (!cfg || _typeof(cfg) !== "object") cfg = {}; |
| 1185 | /* Shield configuration object from prototype pollution */ cfg = clone(cfg); |
| 1186 | PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE; // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is. |
| 1187 | transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase; |
| 1188 | /* Set configuration parameters */ ALLOWED_TAGS = "ALLOWED_TAGS" in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS; |
| 1189 | ALLOWED_ATTR = "ALLOWED_ATTR" in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR; |
| 1190 | ALLOWED_NAMESPACES = "ALLOWED_NAMESPACES" in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES; |
| 1191 | URI_SAFE_ATTRIBUTES = "ADD_URI_SAFE_ATTR" in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc // eslint-disable-line indent |
| 1192 | ) // eslint-disable-line indent |
| 1193 | : DEFAULT_URI_SAFE_ATTRIBUTES; |
| 1194 | DATA_URI_TAGS = "ADD_DATA_URI_TAGS" in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc // eslint-disable-line indent |
| 1195 | ) // eslint-disable-line indent |
| 1196 | : DEFAULT_DATA_URI_TAGS; |
| 1197 | FORBID_CONTENTS = "FORBID_CONTENTS" in cfg ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS; |
| 1198 | FORBID_TAGS = "FORBID_TAGS" in cfg ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {}; |
| 1199 | FORBID_ATTR = "FORBID_ATTR" in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {}; |
| 1200 | USE_PROFILES = "USE_PROFILES" in cfg ? cfg.USE_PROFILES : false; |
| 1201 | ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true |
| 1202 | ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true |
| 1203 | ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false |
| 1204 | ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true |
| 1205 | SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false |
| 1206 | WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false |
| 1207 | RETURN_DOM = cfg.RETURN_DOM || false; // Default false |
| 1208 | RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false |
| 1209 | RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false |
| 1210 | FORCE_BODY = cfg.FORCE_BODY || false; // Default false |
| 1211 | SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true |
| 1212 | SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false |
| 1213 | KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true |
| 1214 | IN_PLACE = cfg.IN_PLACE || false; // Default false |
| 1215 | IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1; |
| 1216 | NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE; |
| 1217 | CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {}; |
| 1218 | if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck; |
| 1219 | if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck; |
| 1220 | if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === "boolean") CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements; |
| 1221 | if (SAFE_FOR_TEMPLATES) ALLOW_DATA_ATTR = false; |
| 1222 | if (RETURN_DOM_FRAGMENT) RETURN_DOM = true; |
| 1223 | /* Parse profile info */ if (USE_PROFILES) { |
| 1224 | ALLOWED_TAGS = addToSet({}, _toConsumableArray(text)); |
| 1225 | ALLOWED_ATTR = []; |
| 1226 | if (USE_PROFILES.html === true) { |
| 1227 | addToSet(ALLOWED_TAGS, html$1); |
| 1228 | addToSet(ALLOWED_ATTR, html1); |
| 1229 | } |
| 1230 | if (USE_PROFILES.svg === true) { |
| 1231 | addToSet(ALLOWED_TAGS, svg$1); |
| 1232 | addToSet(ALLOWED_ATTR, svg); |
| 1233 | addToSet(ALLOWED_ATTR, xml); |
| 1234 | } |
| 1235 | if (USE_PROFILES.svgFilters === true) { |
| 1236 | addToSet(ALLOWED_TAGS, svgFilters); |
| 1237 | addToSet(ALLOWED_ATTR, svg); |
| 1238 | addToSet(ALLOWED_ATTR, xml); |
| 1239 | } |
| 1240 | if (USE_PROFILES.mathMl === true) { |
| 1241 | addToSet(ALLOWED_TAGS, mathMl$1); |
| 1242 | addToSet(ALLOWED_ATTR, mathMl); |
| 1243 | addToSet(ALLOWED_ATTR, xml); |
| 1244 | } |
| 1245 | } |
| 1246 | /* Merge configuration parameters */ if (cfg.ADD_TAGS) { |
| 1247 | if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) ALLOWED_TAGS = clone(ALLOWED_TAGS); |
| 1248 | addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); |
| 1249 | } |
| 1250 | if (cfg.ADD_ATTR) { |
| 1251 | if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) ALLOWED_ATTR = clone(ALLOWED_ATTR); |
| 1252 | addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); |
| 1253 | } |
| 1254 | if (cfg.ADD_URI_SAFE_ATTR) addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc); |
| 1255 | if (cfg.FORBID_CONTENTS) { |
| 1256 | if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS); |
| 1257 | addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc); |
| 1258 | } |
| 1259 | /* Add #text in case KEEP_CONTENT is set to true */ if (KEEP_CONTENT) ALLOWED_TAGS["#text"] = true; |
| 1260 | /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */ if (WHOLE_DOCUMENT) addToSet(ALLOWED_TAGS, [ |
| 1261 | "html", |
| 1262 | "head", |
| 1263 | "body" |
| 1264 | ]); |
| 1265 | /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */ if (ALLOWED_TAGS.table) { |
| 1266 | addToSet(ALLOWED_TAGS, [ |
| 1267 | "tbody" |
| 1268 | ]); |
| 1269 | delete FORBID_TAGS.tbody; |
| 1270 | } // Prevent further manipulation of configuration. |
| 1271 | // Not available in IE8, Safari 5, etc. |
| 1272 | if (freeze) freeze(cfg); |
| 1273 | CONFIG = cfg; |
| 1274 | }; |
| 1275 | var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [ |
| 1276 | "mi", |
| 1277 | "mo", |
| 1278 | "mn", |
| 1279 | "ms", |
| 1280 | "mtext" |
| 1281 | ]); |
| 1282 | var HTML_INTEGRATION_POINTS = addToSet({}, [ |
| 1283 | "foreignobject", |
| 1284 | "desc", |
| 1285 | "title", |
| 1286 | "annotation-xml" |
| 1287 | ]); // Certain elements are allowed in both SVG and HTML |
| 1288 | // namespace. We need to specify them explicitly |
| 1289 | // so that they don't get erroneously deleted from |
| 1290 | // HTML namespace. |
| 1291 | var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [ |
| 1292 | "title", |
| 1293 | "style", |
| 1294 | "font", |
| 1295 | "a", |
| 1296 | "script" |
| 1297 | ]); |
| 1298 | /* Keep track of all possible SVG and MathML tags |
| 1299 | * so that we can perform the namespace checks |
| 1300 | * correctly. */ var ALL_SVG_TAGS = addToSet({}, svg$1); |
| 1301 | addToSet(ALL_SVG_TAGS, svgFilters); |
| 1302 | addToSet(ALL_SVG_TAGS, svgDisallowed); |
| 1303 | var ALL_MATHML_TAGS = addToSet({}, mathMl$1); |
| 1304 | addToSet(ALL_MATHML_TAGS, mathMlDisallowed); |
| 1305 | /** |
| 1306 | * |
| 1307 | * |
| 1308 | * @param {Element} element a DOM element whose namespace is being checked |
| 1309 | * @returns {boolean} Return false if the element has a |
| 1310 | * namespace that a spec-compliant parser would never |
| 1311 | * return. Return true otherwise. |
| 1312 | */ var _checkValidNamespace = function _checkValidNamespace(element) { |
| 1313 | var parent = getParentNode(element); // In JSDOM, if we're inside shadow DOM, then parentNode |
| 1314 | // can be null. We just simulate parent in this case. |
| 1315 | if (!parent || !parent.tagName) parent = { |
| 1316 | namespaceURI: NAMESPACE, |
| 1317 | tagName: "template" |
| 1318 | }; |
| 1319 | var tagName = stringToLowerCase(element.tagName); |
| 1320 | var parentTagName = stringToLowerCase(parent.tagName); |
| 1321 | if (!ALLOWED_NAMESPACES[element.namespaceURI]) return false; |
| 1322 | if (element.namespaceURI === SVG_NAMESPACE) { |
| 1323 | // The only way to switch from HTML namespace to SVG |
| 1324 | // is via <svg>. If it happens via any other tag, then |
| 1325 | // it should be killed. |
| 1326 | if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "svg"; |
| 1327 | // The only way to switch from MathML to SVG is via` |
| 1328 | // svg if parent is either <annotation-xml> or MathML |
| 1329 | // text integration points. |
| 1330 | if (parent.namespaceURI === MATHML_NAMESPACE) return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); |
| 1331 | // We only allow elements that are defined in SVG |
| 1332 | // spec. All others are disallowed in SVG namespace. |
| 1333 | return Boolean(ALL_SVG_TAGS[tagName]); |
| 1334 | } |
| 1335 | if (element.namespaceURI === MATHML_NAMESPACE) { |
| 1336 | // The only way to switch from HTML namespace to MathML |
| 1337 | // is via <math>. If it happens via any other tag, then |
| 1338 | // it should be killed. |
| 1339 | if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "math"; |
| 1340 | // The only way to switch from SVG to MathML is via |
| 1341 | // <math> and HTML integration points |
| 1342 | if (parent.namespaceURI === SVG_NAMESPACE) return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName]; |
| 1343 | // We only allow elements that are defined in MathML |
| 1344 | // spec. All others are disallowed in MathML namespace. |
| 1345 | return Boolean(ALL_MATHML_TAGS[tagName]); |
| 1346 | } |
| 1347 | if (element.namespaceURI === HTML_NAMESPACE) { |
| 1348 | // The only way to switch from SVG to HTML is via |
| 1349 | // HTML integration points, and from MathML to HTML |
| 1350 | // is via MathML text integration points |
| 1351 | if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) return false; |
| 1352 | if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) return false; |
| 1353 | // We disallow tags that are specific for MathML |
| 1354 | // or SVG and should never appear in HTML namespace |
| 1355 | return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); |
| 1356 | } // For XHTML and XML documents that support custom namespaces |
| 1357 | if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) return true; |
| 1358 | // The code should never reach this place (this means |
| 1359 | // that the element somehow got namespace that is not |
| 1360 | // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES). |
| 1361 | // Return false just in case. |
| 1362 | return false; |
| 1363 | }; |
| 1364 | /** |
| 1365 | * _forceRemove |
| 1366 | * |
| 1367 | * @param {Node} node a DOM node |
| 1368 | */ var _forceRemove = function _forceRemove(node) { |
| 1369 | arrayPush(DOMPurify.removed, { |
| 1370 | element: node |
| 1371 | }); |
| 1372 | try { |
| 1373 | // eslint-disable-next-line unicorn/prefer-dom-node-remove |
| 1374 | node.parentNode.removeChild(node); |
| 1375 | } catch (_) { |
| 1376 | try { |
| 1377 | node.outerHTML = emptyHTML; |
| 1378 | } catch (_) { |
| 1379 | node.remove(); |
| 1380 | } |
| 1381 | } |
| 1382 | }; |
| 1383 | /** |
| 1384 | * _removeAttribute |
| 1385 | * |
| 1386 | * @param {String} name an Attribute name |
| 1387 | * @param {Node} node a DOM node |
| 1388 | */ var _removeAttribute = function _removeAttribute(name, node) { |
| 1389 | try { |
| 1390 | arrayPush(DOMPurify.removed, { |
| 1391 | attribute: node.getAttributeNode(name), |
| 1392 | from: node |
| 1393 | }); |
| 1394 | } catch (_) { |
| 1395 | arrayPush(DOMPurify.removed, { |
| 1396 | attribute: null, |
| 1397 | from: node |
| 1398 | }); |
| 1399 | } |
| 1400 | node.removeAttribute(name); // We void attribute values for unremovable "is"" attributes |
| 1401 | if (name === "is" && !ALLOWED_ATTR[name]) { |
| 1402 | if (RETURN_DOM || RETURN_DOM_FRAGMENT) try { |
| 1403 | _forceRemove(node); |
| 1404 | } catch (_) {} |
| 1405 | else try { |
| 1406 | node.setAttribute(name, ""); |
| 1407 | } catch (_1) {} |
| 1408 | } |
| 1409 | }; |
| 1410 | /** |
| 1411 | * _initDocument |
| 1412 | * |
| 1413 | * @param {String} dirty a string of dirty markup |
| 1414 | * @return {Document} a DOM, filled with the dirty markup |
| 1415 | */ var _initDocument = function _initDocument(dirty) { |
| 1416 | /* Create a HTML document */ var doc; |
| 1417 | var leadingWhitespace; |
| 1418 | if (FORCE_BODY) dirty = "<remove></remove>" + dirty; |
| 1419 | else { |
| 1420 | /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */ var matches = stringMatch(dirty, /^[\r\n\t ]+/); |
| 1421 | leadingWhitespace = matches && matches[0]; |
| 1422 | } |
| 1423 | if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict) |
| 1424 | dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + "</body></html>"; |
| 1425 | var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty; |
| 1426 | /* |
| 1427 | * Use the DOMParser API by default, fallback later if needs be |
| 1428 | * DOMParser not work for svg when has multiple root element. |
| 1429 | */ if (NAMESPACE === HTML_NAMESPACE) try { |
| 1430 | doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE); |
| 1431 | } catch (_) {} |
| 1432 | /* Use createHTMLDocument in case DOMParser is not available */ if (!doc || !doc.documentElement) { |
| 1433 | doc = implementation.createDocument(NAMESPACE, "template", null); |
| 1434 | try { |
| 1435 | doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload; |
| 1436 | } catch (_) {} |
| 1437 | } |
| 1438 | var body = doc.body || doc.documentElement; |
| 1439 | if (dirty && leadingWhitespace) body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null); |
| 1440 | /* Work on whole document or just its body */ if (NAMESPACE === HTML_NAMESPACE) return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0]; |
| 1441 | return WHOLE_DOCUMENT ? doc.documentElement : body; |
| 1442 | }; |
| 1443 | /** |
| 1444 | * _createIterator |
| 1445 | * |
| 1446 | * @param {Document} root document/fragment to create iterator for |
| 1447 | * @return {Iterator} iterator instance |
| 1448 | */ var _createIterator = function _createIterator(root) { |
| 1449 | return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false); |
| 1450 | }; |
| 1451 | /** |
| 1452 | * _isClobbered |
| 1453 | * |
| 1454 | * @param {Node} elm element to check for clobbering attacks |
| 1455 | * @return {Boolean} true if clobbered, false if safe |
| 1456 | */ var _isClobbered = function _isClobbered(elm) { |
| 1457 | return elm instanceof HTMLFormElement && (typeof elm.nodeName !== "string" || typeof elm.textContent !== "string" || typeof elm.removeChild !== "function" || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== "function" || typeof elm.setAttribute !== "function" || typeof elm.namespaceURI !== "string" || typeof elm.insertBefore !== "function" || typeof elm.hasChildNodes !== "function"); |
| 1458 | }; |
| 1459 | /** |
| 1460 | * _isNode |
| 1461 | * |
| 1462 | * @param {Node} obj object to check whether it's a DOM node |
| 1463 | * @return {Boolean} true is object is a DOM node |
| 1464 | */ var _isNode = function _isNode(object) { |
| 1465 | return _typeof(Node) === "object" ? object instanceof Node : object && _typeof(object) === "object" && typeof object.nodeType === "number" && typeof object.nodeName === "string"; |
| 1466 | }; |
| 1467 | /** |
| 1468 | * _executeHook |
| 1469 | * Execute user configurable hooks |
| 1470 | * |
| 1471 | * @param {String} entryPoint Name of the hook's entry point |
| 1472 | * @param {Node} currentNode node to work on with the hook |
| 1473 | * @param {Object} data additional hook parameters |
| 1474 | */ var _executeHook = function _executeHook(entryPoint, currentNode, data) { |
| 1475 | if (!hooks[entryPoint]) return; |
| 1476 | arrayForEach(hooks[entryPoint], function(hook) { |
| 1477 | hook.call(DOMPurify, currentNode, data, CONFIG); |
| 1478 | }); |
| 1479 | }; |
| 1480 | /** |
| 1481 | * _sanitizeElements |
| 1482 | * |
| 1483 | * @protect nodeName |
| 1484 | * @protect textContent |
| 1485 | * @protect removeChild |
| 1486 | * |
| 1487 | * @param {Node} currentNode to check for permission to exist |
| 1488 | * @return {Boolean} true if node was killed, false if left alive |
| 1489 | */ var _sanitizeElements = function _sanitizeElements(currentNode) { |
| 1490 | var content; |
| 1491 | /* Execute a hook if present */ _executeHook("beforeSanitizeElements", currentNode, null); |
| 1492 | /* Check if element is clobbered or can clobber */ if (_isClobbered(currentNode)) { |
| 1493 | _forceRemove(currentNode); |
| 1494 | return true; |
| 1495 | } |
| 1496 | /* Check if tagname contains Unicode */ if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) { |
| 1497 | _forceRemove(currentNode); |
| 1498 | return true; |
| 1499 | } |
| 1500 | /* Now let's check the element's type and name */ var tagName = transformCaseFunc(currentNode.nodeName); |
| 1501 | /* Execute a hook if present */ _executeHook("uponSanitizeElement", currentNode, { |
| 1502 | tagName: tagName, |
| 1503 | allowedTags: ALLOWED_TAGS |
| 1504 | }); |
| 1505 | /* Detect mXSS attempts abusing namespace confusion */ if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) { |
| 1506 | _forceRemove(currentNode); |
| 1507 | return true; |
| 1508 | } |
| 1509 | /* Mitigate a problem with templates inside select */ if (tagName === "select" && regExpTest(/<template/i, currentNode.innerHTML)) { |
| 1510 | _forceRemove(currentNode); |
| 1511 | return true; |
| 1512 | } |
| 1513 | /* Remove element if anything forbids its presence */ if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { |
| 1514 | /* Check if we have a custom element to handle */ if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) { |
| 1515 | if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false; |
| 1516 | if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false; |
| 1517 | } |
| 1518 | /* Keep content except for bad-listed elements */ if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) { |
| 1519 | var parentNode = getParentNode(currentNode) || currentNode.parentNode; |
| 1520 | var childNodes = getChildNodes(currentNode) || currentNode.childNodes; |
| 1521 | if (childNodes && parentNode) { |
| 1522 | var childCount = childNodes.length; |
| 1523 | for(var i = childCount - 1; i >= 0; --i)parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode)); |
| 1524 | } |
| 1525 | } |
| 1526 | _forceRemove(currentNode); |
| 1527 | return true; |
| 1528 | } |
| 1529 | /* Check whether element has a valid namespace */ if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) { |
| 1530 | _forceRemove(currentNode); |
| 1531 | return true; |
| 1532 | } |
| 1533 | /* Make sure that older browsers don't get fallback-tag mXSS */ if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) { |
| 1534 | _forceRemove(currentNode); |
| 1535 | return true; |
| 1536 | } |
| 1537 | /* Sanitize element content to be template-safe */ if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) { |
| 1538 | /* Get the element's text content */ content = currentNode.textContent; |
| 1539 | content = stringReplace(content, MUSTACHE_EXPR$1, " "); |
| 1540 | content = stringReplace(content, ERB_EXPR$1, " "); |
| 1541 | content = stringReplace(content, TMPLIT_EXPR$1, " "); |
| 1542 | if (currentNode.textContent !== content) { |
| 1543 | arrayPush(DOMPurify.removed, { |
| 1544 | element: currentNode.cloneNode() |
| 1545 | }); |
| 1546 | currentNode.textContent = content; |
| 1547 | } |
| 1548 | } |
| 1549 | /* Execute a hook if present */ _executeHook("afterSanitizeElements", currentNode, null); |
| 1550 | return false; |
| 1551 | }; |
| 1552 | /** |
| 1553 | * _isValidAttribute |
| 1554 | * |
| 1555 | * @param {string} lcTag Lowercase tag name of containing element. |
| 1556 | * @param {string} lcName Lowercase attribute name. |
| 1557 | * @param {string} value Attribute value. |
| 1558 | * @return {Boolean} Returns true if `value` is valid, otherwise false. |
| 1559 | */ // eslint-disable-next-line complexity |
| 1560 | var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) { |
| 1561 | /* Make sure attribute cannot clobber */ if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document || value in formElement)) return false; |
| 1562 | /* Allow valid data-* attributes: At least one character after "-" |
| 1563 | (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes) |
| 1564 | XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) |
| 1565 | We don't need to check the value; it's always URI safe. */ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ; |
| 1566 | else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ; |
| 1567 | else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) { |
| 1568 | if (// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck |
| 1569 | // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck |
| 1570 | _basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck |
| 1571 | lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; |
| 1572 | else return false; |
| 1573 | /* Check value is safe. First, is attr inert? If so, is safe */ } else if (URI_SAFE_ATTRIBUTES[lcName]) ; |
| 1574 | else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ; |
| 1575 | else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) ; |
| 1576 | else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ; |
| 1577 | else if (value) return false; |
| 1578 | return true; |
| 1579 | }; |
| 1580 | /** |
| 1581 | * _basicCustomElementCheck |
| 1582 | * checks if at least one dash is included in tagName, and it's not the first char |
| 1583 | * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name |
| 1584 | * @param {string} tagName name of the tag of the node to sanitize |
| 1585 | */ var _basicCustomElementTest = function _basicCustomElementTest(tagName) { |
| 1586 | return tagName.indexOf("-") > 0; |
| 1587 | }; |
| 1588 | /** |
| 1589 | * _sanitizeAttributes |
| 1590 | * |
| 1591 | * @protect attributes |
| 1592 | * @protect nodeName |
| 1593 | * @protect removeAttribute |
| 1594 | * @protect setAttribute |
| 1595 | * |
| 1596 | * @param {Node} currentNode to sanitize |
| 1597 | */ var _sanitizeAttributes = function _sanitizeAttributes(currentNode) { |
| 1598 | var attr; |
| 1599 | var value; |
| 1600 | var lcName; |
| 1601 | var l; |
| 1602 | /* Execute a hook if present */ _executeHook("beforeSanitizeAttributes", currentNode, null); |
| 1603 | var attributes = currentNode.attributes; |
| 1604 | /* Check if we have attributes; if not we might have a text node */ if (!attributes) return; |
| 1605 | var hookEvent = { |
| 1606 | attrName: "", |
| 1607 | attrValue: "", |
| 1608 | keepAttr: true, |
| 1609 | allowedAttributes: ALLOWED_ATTR |
| 1610 | }; |
| 1611 | l = attributes.length; |
| 1612 | /* Go backwards over all attributes; safely remove bad ones */ while(l--){ |
| 1613 | attr = attributes[l]; |
| 1614 | var _attr = attr, name = _attr.name, namespaceURI = _attr.namespaceURI; |
| 1615 | value = name === "value" ? attr.value : stringTrim(attr.value); |
| 1616 | lcName = transformCaseFunc(name); |
| 1617 | /* Execute a hook if present */ hookEvent.attrName = lcName; |
| 1618 | hookEvent.attrValue = value; |
| 1619 | hookEvent.keepAttr = true; |
| 1620 | hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set |
| 1621 | _executeHook("uponSanitizeAttribute", currentNode, hookEvent); |
| 1622 | value = hookEvent.attrValue; |
| 1623 | /* Did the hooks approve of the attribute? */ if (hookEvent.forceKeepAttr) continue; |
| 1624 | /* Remove attribute */ _removeAttribute(name, currentNode); |
| 1625 | /* Did the hooks approve of the attribute? */ if (!hookEvent.keepAttr) continue; |
| 1626 | /* Work around a security issue in jQuery 3.0 */ if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) { |
| 1627 | _removeAttribute(name, currentNode); |
| 1628 | continue; |
| 1629 | } |
| 1630 | /* Sanitize attribute content to be template-safe */ if (SAFE_FOR_TEMPLATES) { |
| 1631 | value = stringReplace(value, MUSTACHE_EXPR$1, " "); |
| 1632 | value = stringReplace(value, ERB_EXPR$1, " "); |
| 1633 | value = stringReplace(value, TMPLIT_EXPR$1, " "); |
| 1634 | } |
| 1635 | /* Is `value` valid for this attribute? */ var lcTag = transformCaseFunc(currentNode.nodeName); |
| 1636 | if (!_isValidAttribute(lcTag, lcName, value)) continue; |
| 1637 | /* Full DOM Clobbering protection via namespace isolation, |
| 1638 | * Prefix id and name attributes with `user-content-` |
| 1639 | */ if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name")) { |
| 1640 | // Remove the attribute with this value |
| 1641 | _removeAttribute(name, currentNode); // Prefix the value and later re-create the attribute with the sanitized value |
| 1642 | value = SANITIZE_NAMED_PROPS_PREFIX + value; |
| 1643 | } |
| 1644 | /* Handle attributes that require Trusted Types */ if (trustedTypesPolicy && _typeof(trustedTypes) === "object" && typeof trustedTypes.getAttributeType === "function") { |
| 1645 | if (namespaceURI) ; |
| 1646 | else switch(trustedTypes.getAttributeType(lcTag, lcName)){ |
| 1647 | case "TrustedHTML": |
| 1648 | value = trustedTypesPolicy.createHTML(value); |
| 1649 | break; |
| 1650 | case "TrustedScriptURL": |
| 1651 | value = trustedTypesPolicy.createScriptURL(value); |
| 1652 | break; |
| 1653 | } |
| 1654 | } |
| 1655 | /* Handle invalid data-* attribute set by try-catching it */ try { |
| 1656 | if (namespaceURI) currentNode.setAttributeNS(namespaceURI, name, value); |
| 1657 | else /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */ currentNode.setAttribute(name, value); |
| 1658 | arrayPop(DOMPurify.removed); |
| 1659 | } catch (_) {} |
| 1660 | } |
| 1661 | /* Execute a hook if present */ _executeHook("afterSanitizeAttributes", currentNode, null); |
| 1662 | }; |
| 1663 | /** |
| 1664 | * _sanitizeShadowDOM |
| 1665 | * |
| 1666 | * @param {DocumentFragment} fragment to iterate over recursively |
| 1667 | */ var _sanitizeShadowDOM1 = function _sanitizeShadowDOM(fragment) { |
| 1668 | var shadowNode; |
| 1669 | var shadowIterator = _createIterator(fragment); |
| 1670 | /* Execute a hook if present */ _executeHook("beforeSanitizeShadowDOM", fragment, null); |
| 1671 | while(shadowNode = shadowIterator.nextNode()){ |
| 1672 | /* Execute a hook if present */ _executeHook("uponSanitizeShadowNode", shadowNode, null); |
| 1673 | /* Sanitize tags and elements */ if (_sanitizeElements(shadowNode)) continue; |
| 1674 | /* Deep shadow DOM detected */ if (shadowNode.content instanceof DocumentFragment) _sanitizeShadowDOM(shadowNode.content); |
| 1675 | /* Check attributes, sanitize if necessary */ _sanitizeAttributes(shadowNode); |
| 1676 | } |
| 1677 | /* Execute a hook if present */ _executeHook("afterSanitizeShadowDOM", fragment, null); |
| 1678 | }; |
| 1679 | /** |
| 1680 | * Sanitize |
| 1681 | * Public method providing core sanitation functionality |
| 1682 | * |
| 1683 | * @param {String|Node} dirty string or DOM node |
| 1684 | * @param {Object} configuration object |
| 1685 | */ // eslint-disable-next-line complexity |
| 1686 | DOMPurify.sanitize = function(dirty) { |
| 1687 | var cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; |
| 1688 | var body; |
| 1689 | var importedNode; |
| 1690 | var currentNode; |
| 1691 | var oldNode; |
| 1692 | var returnNode; |
| 1693 | /* Make sure we have a string to sanitize. |
| 1694 | DO NOT return early, as this will return the wrong type if |
| 1695 | the user has requested a DOM object rather than a string */ IS_EMPTY_INPUT = !dirty; |
| 1696 | if (IS_EMPTY_INPUT) dirty = "<!-->"; |
| 1697 | /* Stringify, in case dirty is an object */ if (typeof dirty !== "string" && !_isNode(dirty)) { |
| 1698 | if (typeof dirty.toString === "function") { |
| 1699 | dirty = dirty.toString(); |
| 1700 | if (typeof dirty !== "string") throw typeErrorCreate("dirty is not a string, aborting"); |
| 1701 | } else throw typeErrorCreate("toString is not a function"); |
| 1702 | } |
| 1703 | /* Check we can run. Otherwise fall back or ignore */ if (!DOMPurify.isSupported) { |
| 1704 | if (_typeof(window.toStaticHTML) === "object" || typeof window.toStaticHTML === "function") { |
| 1705 | if (typeof dirty === "string") return window.toStaticHTML(dirty); |
| 1706 | if (_isNode(dirty)) return window.toStaticHTML(dirty.outerHTML); |
| 1707 | } |
| 1708 | return dirty; |
| 1709 | } |
| 1710 | /* Assign config vars */ if (!SET_CONFIG) _parseConfig(cfg); |
| 1711 | /* Clean up removed elements */ DOMPurify.removed = []; |
| 1712 | /* Check if dirty is correctly typed for IN_PLACE */ if (typeof dirty === "string") IN_PLACE = false; |
| 1713 | if (IN_PLACE) /* Do some early pre-sanitization to avoid unsafe root nodes */ { |
| 1714 | if (dirty.nodeName) { |
| 1715 | var tagName = transformCaseFunc(dirty.nodeName); |
| 1716 | if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place"); |
| 1717 | } |
| 1718 | } else if (dirty instanceof Node) { |
| 1719 | /* If dirty is a DOM element, append to an empty document to avoid |
| 1720 | elements being stripped by the parser */ body = _initDocument("<!---->"); |
| 1721 | importedNode = body.ownerDocument.importNode(dirty, true); |
| 1722 | if (importedNode.nodeType === 1 && importedNode.nodeName === "BODY") /* Node is already a body, use as is */ body = importedNode; |
| 1723 | else if (importedNode.nodeName === "HTML") body = importedNode; |
| 1724 | else // eslint-disable-next-line unicorn/prefer-dom-node-append |
| 1725 | body.appendChild(importedNode); |
| 1726 | } else { |
| 1727 | /* Exit directly if we have nothing to do */ if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf("<") === -1) return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty; |
| 1728 | /* Initialize the document to work on */ body = _initDocument(dirty); |
| 1729 | /* Check we have a DOM node from the data */ if (!body) return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : ""; |
| 1730 | } |
| 1731 | /* Remove first element node (ours) if FORCE_BODY is set */ if (body && FORCE_BODY) _forceRemove(body.firstChild); |
| 1732 | /* Get node iterator */ var nodeIterator = _createIterator(IN_PLACE ? dirty : body); |
| 1733 | /* Now start iterating over the created document */ while(currentNode = nodeIterator.nextNode()){ |
| 1734 | /* Fix IE's strange behavior with manipulated textNodes #89 */ if (currentNode.nodeType === 3 && currentNode === oldNode) continue; |
| 1735 | /* Sanitize tags and elements */ if (_sanitizeElements(currentNode)) continue; |
| 1736 | /* Shadow DOM detected, sanitize it */ if (currentNode.content instanceof DocumentFragment) _sanitizeShadowDOM1(currentNode.content); |
| 1737 | /* Check attributes, sanitize if necessary */ _sanitizeAttributes(currentNode); |
| 1738 | oldNode = currentNode; |
| 1739 | } |
| 1740 | oldNode = null; |
| 1741 | /* If we sanitized `dirty` in-place, return it. */ if (IN_PLACE) return dirty; |
| 1742 | /* Return sanitized string or DOM */ if (RETURN_DOM) { |
| 1743 | if (RETURN_DOM_FRAGMENT) { |
| 1744 | returnNode = createDocumentFragment.call(body.ownerDocument); |
| 1745 | while(body.firstChild)// eslint-disable-next-line unicorn/prefer-dom-node-append |
| 1746 | returnNode.appendChild(body.firstChild); |
| 1747 | } else returnNode = body; |
| 1748 | if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmod) /* |
| 1749 | AdoptNode() is not used because internal state is not reset |
| 1750 | (e.g. the past names map of a HTMLFormElement), this is safe |
| 1751 | in theory but we would rather not risk another attack vector. |
| 1752 | The state that is cloned by importNode() is explicitly defined |
| 1753 | by the specs. |
| 1754 | */ returnNode = importNode.call(originalDocument, returnNode, true); |
| 1755 | return returnNode; |
| 1756 | } |
| 1757 | var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; |
| 1758 | /* Serialize doctype if allowed */ if (WHOLE_DOCUMENT && ALLOWED_TAGS["!doctype"] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML; |
| 1759 | /* Sanitize final string template-safe */ if (SAFE_FOR_TEMPLATES) { |
| 1760 | serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, " "); |
| 1761 | serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, " "); |
| 1762 | serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR$1, " "); |
| 1763 | } |
| 1764 | return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML; |
| 1765 | }; |
| 1766 | /** |
| 1767 | * Public method to set the configuration once |
| 1768 | * setConfig |
| 1769 | * |
| 1770 | * @param {Object} cfg configuration object |
| 1771 | */ DOMPurify.setConfig = function(cfg) { |
| 1772 | _parseConfig(cfg); |
| 1773 | SET_CONFIG = true; |
| 1774 | }; |
| 1775 | /** |
| 1776 | * Public method to remove the configuration |
| 1777 | * clearConfig |
| 1778 | * |
| 1779 | */ DOMPurify.clearConfig = function() { |
| 1780 | CONFIG = null; |
| 1781 | SET_CONFIG = false; |
| 1782 | }; |
| 1783 | /** |
| 1784 | * Public method to check if an attribute value is valid. |
| 1785 | * Uses last set config, if any. Otherwise, uses config defaults. |
| 1786 | * isValidAttribute |
| 1787 | * |
| 1788 | * @param {string} tag Tag name of containing element. |
| 1789 | * @param {string} attr Attribute name. |
| 1790 | * @param {string} value Attribute value. |
| 1791 | * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false. |
| 1792 | */ DOMPurify.isValidAttribute = function(tag, attr, value) { |
| 1793 | /* Initialize shared config vars if necessary. */ if (!CONFIG) _parseConfig({}); |
| 1794 | var lcTag = transformCaseFunc(tag); |
| 1795 | var lcName = transformCaseFunc(attr); |
| 1796 | return _isValidAttribute(lcTag, lcName, value); |
| 1797 | }; |
| 1798 | /** |
| 1799 | * AddHook |
| 1800 | * Public method to add DOMPurify hooks |
| 1801 | * |
| 1802 | * @param {String} entryPoint entry point for the hook to add |
| 1803 | * @param {Function} hookFunction function to execute |
| 1804 | */ DOMPurify.addHook = function(entryPoint, hookFunction) { |
| 1805 | if (typeof hookFunction !== "function") return; |
| 1806 | hooks[entryPoint] = hooks[entryPoint] || []; |
| 1807 | arrayPush(hooks[entryPoint], hookFunction); |
| 1808 | }; |
| 1809 | /** |
| 1810 | * RemoveHook |
| 1811 | * Public method to remove a DOMPurify hook at a given entryPoint |
| 1812 | * (pops it from the stack of hooks if more are present) |
| 1813 | * |
| 1814 | * @param {String} entryPoint entry point for the hook to remove |
| 1815 | * @return {Function} removed(popped) hook |
| 1816 | */ DOMPurify.removeHook = function(entryPoint) { |
| 1817 | if (hooks[entryPoint]) return arrayPop(hooks[entryPoint]); |
| 1818 | }; |
| 1819 | /** |
| 1820 | * RemoveHooks |
| 1821 | * Public method to remove all DOMPurify hooks at a given entryPoint |
| 1822 | * |
| 1823 | * @param {String} entryPoint entry point for the hooks to remove |
| 1824 | */ DOMPurify.removeHooks = function(entryPoint) { |
| 1825 | if (hooks[entryPoint]) hooks[entryPoint] = []; |
| 1826 | }; |
| 1827 | /** |
| 1828 | * RemoveAllHooks |
| 1829 | * Public method to remove all DOMPurify hooks |
| 1830 | * |
| 1831 | */ DOMPurify.removeAllHooks = function() { |
| 1832 | hooks = {}; |
| 1833 | }; |
| 1834 | return DOMPurify; |
| 1835 | } |
| 1836 | var purify = createDOMPurify(); |
| 1837 | return purify; |
| 1838 | }); |
| 1839 | |
| 1840 | },{}]},[], null, "parcelRequirec571") |
| 1841 | |
| 1842 | //# sourceMappingURL=purify.2550ab20.js.map |
| 1843 |