vendor: 7,252 bytes, lines 1-193
1(function() { 2 try { 3 var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}; 4 e.SENTRY_RELEASE = { id: "b96dc26" }; 5 var n = new e.Error().stack; 6 n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "210a779f-938b-4d2e-a2f7-65aeca084e9e", e._sentryDebugIdIdentifier = "sentry-dbid-210a779f-938b-4d2e-a2f7-65aeca084e9e"); 7 } catch (e) {} 8})(); 9import { n as __esmMin } from "./rolldown-runtime-sLwMD6dS.js"; 10//#region node_modules/.pnpm/[email protected]/node_modules/dompurify/dist/purify.es.mjs 11/*! @license DOMPurify 3.4.15 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.15/LICENSE */ 12function _arrayLikeToArray(r, a) { 13 (null == a || a > r.length) && (a = r.length); 14 for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; 15 return n; 16} 17function _arrayWithHoles(r) { 18 if (Array.isArray(r)) return r; 19} 20function _iterableToArrayLimit(r, l) { 21 var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; 22 if (null != t) { 23 var e, n, i, u, a = [], f = true, o = false; 24 try { 25 if (i = (t = t.call(r)).next, 0 === l); 26 else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); 27 } catch (r) { 28 o = true, n = r; 29 } finally { 30 try { 31 if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; 32 } finally { 33 if (o) throw n; 34 } 35 } 36 return a; 37 } 38} 39function _nonIterableRest() { 40 throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); 41} 42function _slicedToArray(r, e) { 43 return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); 44} 45function _unsupportedIterableToArray(r, a) { 46 if (r) { 47 if ("string" == typeof r) return _arrayLikeToArray(r, a); 48 var t = {}.toString.call(r).slice(8, -1); 49 return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; 50 } 51} 52/** 53* Creates a new function that calls the given function with a specified thisArg and arguments. 54* 55* @param func - The function to be wrapped and called. 56* @returns A new function that calls the given function with a specified thisArg and arguments. 57*/ 58function unapply(func) { 59 return function(thisArg) { 60 if (thisArg instanceof RegExp) thisArg.lastIndex = 0; 61 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) args[_key3 - 1] = arguments[_key3]; 62 return apply(func, thisArg, args); 63 }; 64} 65/** 66* Creates a new function that constructs an instance of the given constructor function with the provided arguments. 67* 68* @param func - The constructor function to be wrapped and called. 69* @returns A new function that constructs an instance of the given constructor function with the provided arguments. 70*/ 71function unconstruct(Func) { 72 return function() { 73 for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) args[_key4] = arguments[_key4]; 74 return construct(Func, args); 75 }; 76} 77/** 78* Add properties to a lookup table 79* 80* @param set - The set to which elements will be added. 81* @param array - The array containing elements to be added to the set. 82* @param transformCaseFunc - An optional function to transform the case of each element before adding to the set. 83* @returns The modified set with added elements. 84*/ 85function addToSet(set, array) { 86 let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase; 87 if (setPrototypeOf) setPrototypeOf(set, null); 88 if (!arrayIsArray(array)) return set; 89 let l = array.length; 90 while (l--) { 91 let element = array[l]; 92 if (typeof element === "string") { 93 const lcElement = transformCaseFunc(element); 94 if (lcElement !== element) { 95 if (!isFrozen(array)) array[l] = lcElement; 96 element = lcElement; 97 } 98 } 99 set[element] = true; 100 } 101 return set; 102} 103/** 104* Clean up an array to harden against CSPP 105* 106* @param array - The array to be cleaned. 107* @returns The cleaned version of the array 108*/ 109function cleanArray(array) { 110 for (let index = 0; index < array.length; index++) if (!objectHasOwnProperty(array, index)) array[index] = null; 111 return array; 112} 113/** 114* Shallow clone an object 115* 116* @param object - The object to be cloned. 117* @returns A new object that copies the original. 118*/ 119function clone(object) { 120 const newObject = create(null); 121 for (const _ref2 of entries(object)) { 122 var _ref3 = _slicedToArray(_ref2, 2); 123 const property = _ref3[0]; 124 const value = _ref3[1]; 125 if (objectHasOwnProperty(object, property)) { 126 if (arrayIsArray(value)) newObject[property] = cleanArray(value); 127 else if (value && typeof value === "object" && value.constructor === Object) newObject[property] = clone(value); 128 else newObject[property] = value; 129 } 130 } 131 return newObject; 132} 133/** 134* Convert non-node values into strings without depending on direct property access. 135* 136* @param value - The value to stringify. 137* @returns A string representation of the provided value. 138*/ 139function stringifyValue(value) { 140 switch (typeof value) { 141 case "string": return value; 142 case "number": return numberToString(value); 143 case "boolean": return booleanToString(value); 144 case "bigint": return bigintToString ? bigintToString(value) : "0"; 145 case "symbol": return symbolToString ? symbolToString(value) : "Symbol()"; 146 case "undefined": return objectToString(value); 147 case "function": 148 case "object": { 149 if (value === null) return objectToString(value); 150 const valueAsRecord = value; 151 const valueToString = lookupGetter(valueAsRecord, "toString"); 152 if (typeof valueToString === "function") { 153 const stringified = valueToString(valueAsRecord); 154 return typeof stringified === "string" ? stringified : objectToString(stringified); 155 } 156 return objectToString(value); 157 } 158 default: return objectToString(value); 159 } 160} 161/** 162* This method automatically checks if the prop is function or getter and behaves accordingly. 163* 164* @param object - The object to look up the getter function in its prototype chain. 165* @param prop - The property name for which to find the getter function. 166* @returns The getter function found in the prototype chain or a fallback function. 167*/ 168function lookupGetter(object, prop) { 169 while (object !== null) { 170 const desc = getOwnPropertyDescriptor(object, prop); 171 if (desc) { 172 if (desc.get) return unapply(desc.get); 173 if (typeof desc.value === "function") return unapply(desc.value); 174 } 175 object = getPrototypeOf(object); 176 } 177 function fallbackValue() { 178 return null; 179 } 180 return fallbackValue; 181} 182function isRegex(value) { 183 try { 184 regExpTest(value, ""); 185 return true; 186 } catch (_unused) { 187 return false; 188 } 189} 190function createDOMPurify() { 191 let window = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal(); 192 const DOMPurify = (root) => createDOMPurify(root); 193 DOMPurify.version = "3.4.15
vendor: 44,004 bytes, lines 193-1183
193"; 194 DOMPurify.removed = []; 195 if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) { 196 DOMPurify.isSupported = false; 197 return DOMPurify; 198 } 199 let document = window.document; 200 const originalDocument = document; 201 const currentScript = originalDocument.currentScript; 202 window.DocumentFragment; 203 const HTMLTemplateElement = window.HTMLTemplateElement, Node = window.Node, Element = window.Element, NodeFilter = window.NodeFilter; 204 window.NamedNodeMap === void 0 && (window.NamedNodeMap || window.MozNamedAttrMap); 205 window.HTMLFormElement; 206 const DOMParser = window.DOMParser, trustedTypes = window.trustedTypes; 207 const ElementPrototype = Element.prototype; 208 const cloneNode = lookupGetter(ElementPrototype, "cloneNode"); 209 const remove = lookupGetter(ElementPrototype, "remove"); 210 const removeAttributeNode = lookupGetter(ElementPrototype, "removeAttributeNode"); 211 const getNextSibling = lookupGetter(ElementPrototype, "nextSibling"); 212 const getChildNodes = lookupGetter(ElementPrototype, "childNodes"); 213 const getParentNode = lookupGetter(ElementPrototype, "parentNode"); 214 const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot"); 215 const getAttributes = lookupGetter(ElementPrototype, "attributes"); 216 const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null; 217 const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null; 218 const getOwnerDocument = Node && Node.prototype ? lookupGetter(Node.prototype, "ownerDocument") : null; 219 const _readNodeType = function _readNodeType(node) { 220 return getNodeType ? getNodeType(node) : node.nodeType; 221 }; 222 const _readNodeName = function _readNodeName(node) { 223 return getNodeName ? getNodeName(node) : node.nodeName; 224 }; 225 if (typeof HTMLTemplateElement === "function") { 226 const template = document.createElement("template"); 227 if (template.content && template.content.ownerDocument) document = template.content.ownerDocument; 228 } 229 let trustedTypesPolicy; 230 let emptyHTML = ""; 231 let defaultTrustedTypesPolicy; 232 let defaultTrustedTypesPolicyResolved = false; 233 let IN_TRUSTED_TYPES_POLICY = 0; 234 const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy() { 235 if (IN_TRUSTED_TYPES_POLICY > 0) throw typeErrorCreate("A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the \"DOMPurify and Trusted Types\" section of the README."); 236 }; 237 const _createTrustedHTML = function _createTrustedHTML(html) { 238 _assertNotInTrustedTypesPolicy(); 239 IN_TRUSTED_TYPES_POLICY++; 240 try { 241 return trustedTypesPolicy.createHTML(html); 242 } finally { 243 IN_TRUSTED_TYPES_POLICY--; 244 } 245 }; 246 const _createTrustedScriptURL = function _createTrustedScriptURL(scriptUrl) { 247 _assertNotInTrustedTypesPolicy(); 248 IN_TRUSTED_TYPES_POLICY++; 249 try { 250 return trustedTypesPolicy.createScriptURL(scriptUrl); 251 } finally { 252 IN_TRUSTED_TYPES_POLICY--; 253 } 254 }; 255 const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy() { 256 if (!defaultTrustedTypesPolicyResolved) { 257 defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); 258 defaultTrustedTypesPolicyResolved = true; 259 } 260 return defaultTrustedTypesPolicy; 261 }; 262 const _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName; 263 const importNode = originalDocument.importNode; 264 let hooks = _createHooksMap(); 265 /** 266 * Expose whether this browser supports running the full DOMPurify. 267 */ 268 DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0; 269 const 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, CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT; 270 let IS_ALLOWED_URI$1 = IS_ALLOWED_URI; 271 /** 272 * We consider the elements and attributes below to be safe. Ideally 273 * don't add any new ones but feel free to remove unwanted ones. 274 */ 275 let ALLOWED_TAGS = null; 276 const DEFAULT_ALLOWED_TAGS = addToSet({}, [ 277 ...html$1, 278 ...svg$1, 279 ...svgFilters, 280 ...mathMl$1, 281 ...text 282 ]); 283 let ALLOWED_ATTR = null; 284 const DEFAULT_ALLOWED_ATTR = addToSet({}, [ 285 ...html, 286 ...svg, 287 ...mathMl, 288 ...xml 289 ]); 290 let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, { 291 tagNameCheck: { 292 writable: true, 293 configurable: false, 294 enumerable: true, 295 value: null 296 }, 297 attributeNameCheck: { 298 writable: true, 299 configurable: false, 300 enumerable: true, 301 value: null 302 }, 303 allowCustomizedBuiltInElements: { 304 writable: true, 305 configurable: false, 306 enumerable: true, 307 value: false 308 } 309 })); 310 let FORBID_TAGS = null; 311 let FORBID_ATTR = null; 312 const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, { 313 tagCheck: { 314 writable: true, 315 configurable: false, 316 enumerable: true, 317 value: null 318 }, 319 attributeCheck: { 320 writable: true, 321 configurable: false, 322 enumerable: true, 323 value: null 324 } 325 })); 326 let ALLOW_ARIA_ATTR = true; 327 let ALLOW_DATA_ATTR = true; 328 let ALLOW_UNKNOWN_PROTOCOLS = false; 329 let ALLOW_SELF_CLOSE_IN_ATTR = true; 330 let SAFE_FOR_TEMPLATES = false; 331 let SAFE_FOR_XML = true; 332 let WHOLE_DOCUMENT = false; 333 let SET_CONFIG = false; 334 let SET_CONFIG_ALLOWED_TAGS = null; 335 let SET_CONFIG_ALLOWED_ATTR = null; 336 let FORCE_BODY = false; 337 let RETURN_DOM = false; 338 let RETURN_DOM_FRAGMENT = false; 339 let RETURN_TRUSTED_TYPE = false; 340 let SANITIZE_DOM = true; 341 let SANITIZE_NAMED_PROPS = false; 342 const SANITIZE_NAMED_PROPS_PREFIX = "user-content-"; 343 let KEEP_CONTENT = true; 344 let IN_PLACE = false; 345 let USE_PROFILES = {}; 346 let FORBID_CONTENTS = null; 347 const DEFAULT_FORBID_CONTENTS = addToSet({}, [ 348 "annotation-xml", 349 "audio", 350 "colgroup", 351 "desc", 352 "foreignobject", 353 "head", 354 "iframe", 355 "math", 356 "mi", 357 "mn", 358 "mo", 359 "ms", 360 "mtext", 361 "noembed", 362 "noframes", 363 "noscript", 364 "plaintext", 365 "script", 366 "selectedcontent", 367 "style", 368 "svg", 369 "template", 370 "thead", 371 "title", 372 "video", 373 "xmp" 374 ]); 375 let DATA_URI_TAGS = null; 376 const DEFAULT_DATA_URI_TAGS = addToSet({}, [ 377 "audio", 378 "video", 379 "img", 380 "source", 381 "image", 382 "track" 383 ]); 384 let URI_SAFE_ATTRIBUTES = null; 385 const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [ 386 "alt", 387 "class", 388 "for", 389 "id", 390 "label", 391 "name", 392 "pattern", 393 "placeholder", 394 "role", 395 "summary", 396 "title", 397 "value", 398 "style", 399 "xmlns" 400 ]); 401 const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML"; 402 const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; 403 const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; 404 let NAMESPACE = HTML_NAMESPACE; 405 let IS_EMPTY_INPUT = false; 406 let ALLOWED_NAMESPACES = null; 407 const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [ 408 MATHML_NAMESPACE, 409 SVG_NAMESPACE, 410 HTML_NAMESPACE 411 ], stringToString); 412 const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze([ 413 "mi", 414 "mo", 415 "mn", 416 "ms", 417 "mtext" 418 ]); 419 let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS); 420 const DEFAULT_HTML_INTEGRATION_POINTS = freeze(["annotation-xml"]); 421 let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS); 422 const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [ 423 "title", 424 "style", 425 "font", 426 "a", 427 "script" 428 ]); 429 let PARSER_MEDIA_TYPE = null; 430 const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"]; 431 const DEFAULT_PARSER_MEDIA_TYPE = "text/html"; 432 let transformCaseFunc = null; 433 let CONFIG = null; 434 const formElement = document.createElement("form"); 435 const isRegexOrFunction = function isRegexOrFunction(testValue) { 436 return testValue instanceof RegExp || testValue instanceof Function; 437 }; 438 /** 439 * _parseConfig 440 * 441 * @param cfg optional config literal 442 */ 443 const _parseConfig = function _parseConfig() { 444 let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; 445 if (CONFIG && CONFIG === cfg) return; 446 if (!cfg || typeof cfg !== "object") cfg = {}; 447 cfg = clone(cfg); 448 PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE; 449 transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase; 450 ALLOWED_TAGS = _resolveSetOption(cfg, "ALLOWED_TAGS", DEFAULT_ALLOWED_TAGS, { transform: transformCaseFunc }); 451 ALLOWED_ATTR = _resolveSetOption(cfg, "ALLOWED_ATTR", DEFAULT_ALLOWED_ATTR, { transform: transformCaseFunc }); 452 ALLOWED_NAMESPACES = _resolveSetOption(cfg, "ALLOWED_NAMESPACES", DEFAULT_ALLOWED_NAMESPACES, { transform: stringToString }); 453 URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, "ADD_URI_SAFE_ATTR", DEFAULT_URI_SAFE_ATTRIBUTES, { 454 transform: transformCaseFunc, 455 base: DEFAULT_URI_SAFE_ATTRIBUTES 456 }); 457 DATA_URI_TAGS = _resolveSetOption(cfg, "ADD_DATA_URI_TAGS", DEFAULT_DATA_URI_TAGS, { 458 transform: transformCaseFunc, 459 base: DEFAULT_DATA_URI_TAGS 460 }); 461 FORBID_CONTENTS = _resolveSetOption(cfg, "FORBID_CONTENTS", DEFAULT_FORBID_CONTENTS, { transform: transformCaseFunc }); 462 FORBID_TAGS = _resolveSetOption(cfg, "FORBID_TAGS", clone({}), { transform: transformCaseFunc }); 463 FORBID_ATTR = _resolveSetOption(cfg, "FORBID_ATTR", clone({}), { transform: transformCaseFunc }); 464 USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false; 465 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; 466 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; 467 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; 468 ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; 469 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; 470 SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; 471 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; 472 RETURN_DOM = cfg.RETURN_DOM || false; 473 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; 474 RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; 475 FORCE_BODY = cfg.FORCE_BODY || false; 476 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; 477 SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; 478 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; 479 IN_PLACE = cfg.IN_PLACE || false; 480 IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; 481 NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE; 482 MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(cfg, "MATHML_TEXT_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS)); 483 HTML_INTEGRATION_POINTS = _resolveObjectOption(cfg, "HTML_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS)); 484 const customElementHandling = _resolveObjectOption(cfg, "CUSTOM_ELEMENT_HANDLING", () => create(null)); 485 CUSTOM_ELEMENT_HANDLING = create(null); 486 if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; 487 if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; 488 if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; 489 seal(CUSTOM_ELEMENT_HANDLING); 490 if (SAFE_FOR_TEMPLATES) ALLOW_DATA_ATTR = false; 491 if (RETURN_DOM_FRAGMENT) RETURN_DOM = true; 492 if (USE_PROFILES) { 493 ALLOWED_TAGS = addToSet({}, text); 494 ALLOWED_ATTR = create(null); 495 if (USE_PROFILES.html === true) { 496 addToSet(ALLOWED_TAGS, html$1); 497 addToSet(ALLOWED_ATTR, html); 498 } 499 if (USE_PROFILES.svg === true) { 500 addToSet(ALLOWED_TAGS, svg$1); 501 addToSet(ALLOWED_ATTR, svg); 502 addToSet(ALLOWED_ATTR, xml); 503 } 504 if (USE_PROFILES.svgFilters === true) { 505 addToSet(ALLOWED_TAGS, svgFilters); 506 addToSet(ALLOWED_ATTR, svg); 507 addToSet(ALLOWED_ATTR, xml); 508 } 509 if (USE_PROFILES.mathMl === true) { 510 addToSet(ALLOWED_TAGS, mathMl$1); 511 addToSet(ALLOWED_ATTR, mathMl); 512 addToSet(ALLOWED_ATTR, xml); 513 } 514 } 515 EXTRA_ELEMENT_HANDLING.tagCheck = null; 516 EXTRA_ELEMENT_HANDLING.attributeCheck = null; 517 if (objectHasOwnProperty(cfg, "ADD_TAGS")) { 518 if (typeof cfg.ADD_TAGS === "function") EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS; 519 else if (arrayIsArray(cfg.ADD_TAGS)) { 520 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) ALLOWED_TAGS = clone(ALLOWED_TAGS); 521 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); 522 } 523 } 524 if (objectHasOwnProperty(cfg, "ADD_ATTR")) { 525 if (typeof cfg.ADD_ATTR === "function") EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR; 526 else if (arrayIsArray(cfg.ADD_ATTR)) { 527 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) ALLOWED_ATTR = clone(ALLOWED_ATTR); 528 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); 529 } 530 } 531 if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) { 532 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS); 533 addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc); 534 } 535 if (KEEP_CONTENT) ALLOWED_TAGS["#text"] = true; 536 if (WHOLE_DOCUMENT) addToSet(ALLOWED_TAGS, [ 537 "html", 538 "head", 539 "body" 540 ]); 541 if (ALLOWED_TAGS.table) { 542 addToSet(ALLOWED_TAGS, ["tbody"]); 543 delete FORBID_TAGS.tbody; 544 } 545 if (cfg.TRUSTED_TYPES_POLICY) { 546 if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") throw typeErrorCreate("TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook."); 547 if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") throw typeErrorCreate("TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook."); 548 const previousTrustedTypesPolicy = trustedTypesPolicy; 549 trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY; 550 try { 551 emptyHTML = _createTrustedHTML(""); 552 } catch (error) { 553 trustedTypesPolicy = previousTrustedTypesPolicy; 554 throw error; 555 } 556 } else if (cfg.TRUSTED_TYPES_POLICY === null) { 557 trustedTypesPolicy = void 0; 558 emptyHTML = ""; 559 } else { 560 if (trustedTypesPolicy === void 0) trustedTypesPolicy = _getDefaultTrustedTypesPolicy(); 561 if (trustedTypesPolicy && typeof emptyHTML === "string") emptyHTML = _createTrustedHTML(""); 562 } 563 if (freeze) freeze(cfg); 564 CONFIG = cfg; 565 }; 566 const ALL_SVG_TAGS = addToSet({}, [ 567 ...svg$1, 568 ...svgFilters, 569 ...svgDisallowed 570 ]); 571 const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]); 572 /** 573 * Namespace rules for an element in the SVG namespace. 574 * 575 * @param tagName the element's lowercase tag name 576 * @param parent the (possibly simulated) parent node 577 * @param parentTagName the parent's lowercase tag name 578 * @returns true if a spec-compliant parser could produce this element 579 */ 580 const _checkSvgNamespace = function _checkSvgNamespace(tagName, parent, parentTagName) { 581 if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "svg"; 582 if (parent.namespaceURI === MATHML_NAMESPACE) return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); 583 return Boolean(ALL_SVG_TAGS[tagName]); 584 }; 585 /** 586 * Namespace rules for an element in the MathML namespace. 587 * 588 * @param tagName the element's lowercase tag name 589 * @param parent the (possibly simulated) parent node 590 * @param parentTagName the parent's lowercase tag name 591 * @returns true if a spec-compliant parser could produce this element 592 */ 593 const _checkMathMlNamespace = function _checkMathMlNamespace(tagName, parent, parentTagName) { 594 if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "math"; 595 if (parent.namespaceURI === SVG_NAMESPACE) return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName]; 596 return Boolean(ALL_MATHML_TAGS[tagName]); 597 }; 598 /** 599 * Namespace rules for an element in the HTML namespace. 600 * 601 * @param tagName the element's lowercase tag name 602 * @param parent the (possibly simulated) parent node 603 * @param parentTagName the parent's lowercase tag name 604 * @returns true if a spec-compliant parser could produce this element 605 */ 606 const _checkHtmlNamespace = function _checkHtmlNamespace(tagName, parent, parentTagName) { 607 if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) return false; 608 if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) return false; 609 return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); 610 }; 611 /** 612 * @param element a DOM element whose namespace is being checked 613 * @returns Return false if the element has a 614 * namespace that a spec-compliant parser would never 615 * return. Return true otherwise. 616 */ 617 const _checkValidNamespace = function _checkValidNamespace(element) { 618 let parent = getParentNode(element); 619 if (!parent || !parent.tagName) parent = { 620 namespaceURI: NAMESPACE, 621 tagName: "template" 622 }; 623 const tagName = stringToLowerCase(element.tagName); 624 const parentTagName = stringToLowerCase(parent.tagName); 625 if (!ALLOWED_NAMESPACES[element.namespaceURI]) return false; 626 if (element.namespaceURI === SVG_NAMESPACE) return _checkSvgNamespace(tagName, parent, parentTagName); 627 if (element.namespaceURI === MATHML_NAMESPACE) return _checkMathMlNamespace(tagName, parent, parentTagName); 628 if (element.namespaceURI === HTML_NAMESPACE) return _checkHtmlNamespace(tagName, parent, parentTagName); 629 if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) return true; 630 return false; 631 }; 632 /** 633 * _forceRemove 634 * 635 * @param node a DOM node 636 */ 637 const _forceRemove = function _forceRemove(node) { 638 arrayPush(DOMPurify.removed, { element: node }); 639 try { 640 getParentNode(node).removeChild(node); 641 } catch (_) { 642 remove(node); 643 if (!getParentNode(node)) throw typeErrorCreate("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place"); 644 } 645 }; 646 /** 647 * _stripAttributeNode 648 * 649 * Remove a single Attr node case/namespace-exactly on an attribute-teardown 650 * path. Name-based removeAttribute() ASCII-lowercases its lookup key for an 651 * HTML element in an HTML document and so silently misses a case-preserved 652 * handler (e.g. `ONERROR` off an XML/XHTML import) - the same defect 653 * _removeAttribute() was fixed for, which a name-based call would reintroduce 654 * on these IN_PLACE teardown paths. Unlike _removeAttribute this does not 655 * record into DOMPurify.removed: the neutralize passes intentionally do not 656 * book-keep. A clobbered/detached node falls back to best-effort name-based 657 * removal. 658 * 659 * @param element the element to strip the attribute from 660 * @param attribute the Attr node to remove 661 * @param name the attribute's name, for the fallback path 662 */ 663 const _stripAttributeNode = function _stripAttributeNode(element, attribute, name) { 664 try { 665 removeAttributeNode(element, attribute); 666 } catch (_) { 667 try { 668 element.removeAttribute(name); 669 } catch (_) {} 670 } 671 }; 672 /** 673 * _neutralizeRoot 674 * 675 * Fail-closed teardown of an in-place root after the sanitize walk aborts 676 * (campaign-3 F2). An internal throw mid-walk — e.g. a page-registered 677 * custom element's reaction detaches a node so `_forceRemove`'s deliberate 678 * parentless guard throws, or any other re-entrant engine mutation — would 679 * otherwise leave the caller's *live* tree half-sanitized, with everything 680 * after the abort point still carrying its handlers. There is no safe way 681 * to resume the walk (the tree mutated under us), so we strip the root bare: 682 * remove every child and every attribute, then let the caller's catch see 683 * the original error. Clobber-safe (cached `remove`/`childNodes`/`attributes` 684 * getters; the root was already clobber-pre-flighted at the IN_PLACE entry). 685 * 686 * @param root the in-place root to empty 687 */ 688 const _neutralizeRoot = function _neutralizeRoot(root) { 689 _neutralizeSubtree(root); 690 const childNodes = getChildNodes(root); 691 if (childNodes) { 692 const snapshot = []; 693 arrayForEach(childNodes, (child) => { 694 arrayPush(snapshot, child); 695 }); 696 arrayForEach(snapshot, (child) => { 697 try { 698 remove(child); 699 } catch (_) {} 700 }); 701 } 702 const attributes = getAttributes(root); 703 if (attributes) for (let i = attributes.length - 1; i >= 0; --i) { 704 const attribute = attributes[i]; 705 const name = attribute && attribute.name; 706 if (typeof name === "string") _stripAttributeNode(root, attribute, name); 707 } 708 }; 709 /** 710 * _removeAttribute 711 * 712 * Name-based getAttributeNode()/removeAttribute() ASCII-lowercase their 713 * lookup key for HTML elements in an HTML document, so they silently miss an 714 * attribute whose stored qualified name still contains uppercase ASCII 715 * letters. That happens when the node came from a case-preserving source 716 * (an XML/XHTML document imported via importNode(), or createAttributeNS()), 717 * where e.g. `ONERROR` survives the walk: the policy check lowercases to 718 * `onerror` and rejects it, but `removeAttribute('ONERROR')` looks up 719 * `onerror` and finds nothing. Remove the exact Attr node instead, which is 720 * case- and namespace-exact, and fall back to name-based removal only when 721 * the caller could not supply the node. 722 * 723 * @param name an Attribute name 724 * @param element a DOM node 725 * @param attr the exact Attr node to remove, when the caller has it 726 */ 727 const _removeAttribute = function _removeAttribute(name, element, attr) { 728 if (!attr) try { 729 attr = element.getAttributeNode(name); 730 } catch (_) { 731 attr = null; 732 } 733 arrayPush(DOMPurify.removed, { 734 attribute: attr || null, 735 from: element 736 }); 737 try { 738 if (attr) removeAttributeNode(element, attr); 739 else element.removeAttribute(name); 740 } catch (_) { 741 try { 742 element.removeAttribute(name); 743 } catch (_) {} 744 } 745 if (name === "is") { 746 if (RETURN_DOM || RETURN_DOM_FRAGMENT) try { 747 _forceRemove(element); 748 } catch (_) {} 749 else try { 750 element.setAttribute(name, ""); 751 } catch (_) {} 752 } 753 }; 754 /** 755 * _stripDisallowedAttributes 756 * 757 * Removes every attribute the active configuration does not allow from a 758 * single element, using the same allowlist as the main attribute pass (so 759 * `on*` handlers go, but no `/^on/` blocklist is introduced). Used only to 760 * neutralise nodes that are being discarded from an in-place tree. 761 * 762 * @param element the element to strip 763 */ 764 const _stripDisallowedAttributes = function _stripDisallowedAttributes(element) { 765 const attributes = getAttributes(element); 766 if (!attributes) return; 767 for (let i = attributes.length - 1; i >= 0; --i) { 768 const attribute = attributes[i]; 769 const name = attribute && attribute.name; 770 if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) continue; 771 _stripAttributeNode(element, attribute, name); 772 } 773 }; 774 /** 775 * _neutralizeSubtree 776 * 777 * Completes the audit-5 F1 fix across every removal path. The KEEP_CONTENT 778 * move-hoist neutralises only disallowed-tag removals; clobber, mXSS-canary, 779 * namespace, comment, processing-instruction and KEEP_CONTENT:false removals 780 * all drop their subtree wholesale via `_forceRemove`. On the IN_PLACE path 781 * those dropped nodes are detached from the caller's LIVE tree but a 782 * handler-bearing original among them (an `<img onerror>`/`<video>` that was 783 * loading) keeps its queued resource event, which fires in page scope after 784 * sanitize returns. This walks a removed subtree and strips every attribute 785 * the active configuration does not allow — so `on*` handlers are cancelled 786 * through the SAME allowlist that governs kept nodes, not a separate `/^on/` 787 * blocklist. Run synchronously before sanitize returns, i.e. before any 788 * queued event can fire. Hook-free by design: these nodes leave the output, 789 * so firing attribute hooks for them would be surprising. Clobber-safe reads; 790 * a doomed clobbered node may shadow `removeAttribute` (its own attributes are 791 * irrelevant — it is discarded — while its non-clobbered descendants, e.g. 792 * the `<img>`, are reached and scrubbed). 793 * 794 * @param root the root of a removed subtree to neutralise 795 */ 796 const _neutralizeSubtree = function _neutralizeSubtree(root) { 797 const stack = [root]; 798 while (stack.length > 0) { 799 const node = stack.pop(); 800 if (_readNodeType(node) === NODE_TYPE.element) _stripDisallowedAttributes(node); 801 const childNodes = getChildNodes(node); 802 if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]); 803 } 804 }; 805 /** 806 * _neutralizePatchLinkage 807 * 808 * IN_PLACE entry pre-pass (declarative-partial-updates / streaming 809 * hardening, https://github.com/WICG/declarative-partial-updates). 810 * 811 * The main walk strips patch linkage (`for`/`patchsrc`) and removes range 812 * markers (PIs / markup comments) node-by-node, in document order, AS it 813 * reaches each node. On a live in-place root that leaves a window: from the 814 * moment the root is connected until the walk arrives at a given node, that 815 * node's linkage is live. A patch applied on connection/stream can fire as 816 * a microtask during the walk and inject or teleport an unsanitized DOM 817 * range into a region the iterator has already passed and will not revisit, 818 * so the post-return "tree is sanitized" contract is violated. Sweep the 819 * whole tree once up front and sever every linkage before the walk begins, 820 * closing that window. 821 * 822 * This CANNOT undo a patch that already fired before sanitize ran — that is 823 * the irreducible "do not IN_PLACE a live-connected attacker tree" caveat — 824 * but it closes everything from sanitize-start onward. Gated on SAFE_FOR_XML 825 * to group with the rest of the declarative-partial-updates handling and 826 * stay overridable, consistent with the codebase. 827 * 828 * Clobber-safe traversal (cached childNodes getter); per-node try/catch so a 829 * clobbered root cannot defeat the sweep of its non-clobbered descendants. 830 * 831 * NOTE (pending real-Chrome confirmation, see test/declarative-patch-probe 832 * .html Q1): this mirrors the existing policy of keeping `for` on 833 * <label>/<output>. If the shipping feature can drive a patch through a 834 * surviving `for`-on-label/output + `id` pair, this pre-pass and the 835 * attribute check at _isBasicCustomElement's caller must additionally drop 836 * that pair on the IN_PLACE path. Left as-is until the taxonomy is verified. 837 * 838 * @param root the in-place root to sweep 839 */ 840 /** 841 * Central policy for declarative-partial-updates patch-linkage attributes, 842 * shared by the _neutralizePatchLinkage pre-pass and _isValidAttribute so 843 * the two sites cannot drift: `patchsrc` always links, `for` links 844 * everywhere except on <label>/<output>, and the whole policy is gated on 845 * SAFE_FOR_XML (see the rationale block in _isValidAttribute). 846 * 847 * @param lcName the transformCaseFunc'd attribute name 848 * @param lcTag the transformCaseFunc'd tag name of the carrying element 849 * @return true if the attribute is patch linkage and must be dropped 850 */ 851 const _isPatchLinkageAttribute = function _isPatchLinkageAttribute(lcName, lcTag) { 852 if (!SAFE_FOR_XML) return false; 853 if (lcName === "patchsrc") return true; 854 return lcName === "for" && lcTag !== "label" && lcTag !== "output"; 855 }; 856 const _neutralizePatchLinkage = function _neutralizePatchLinkage(root) { 857 if (!SAFE_FOR_XML) return; 858 const stack = [root]; 859 while (stack.length > 0) { 860 const node = stack.pop(); 861 const nodeType = _readNodeType(node); 862 if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) { 863 try { 864 remove(node); 865 } catch (_) {} 866 continue; 867 } 868 if (nodeType === NODE_TYPE.element) { 869 const element = node; 870 const lcTag = transformCaseFunc(_readNodeName(node)); 871 try { 872 if (element.hasAttribute && element.hasAttribute("patchsrc")) element.removeAttribute("patchsrc"); 873 if (element.hasAttribute && element.hasAttribute("for") && _isPatchLinkageAttribute("for", lcTag)) element.removeAttribute("for"); 874 } catch (_) {} 875 } 876 const childNodes = getChildNodes(node); 877 if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]); 878 } 879 }; 880 /** 881 * _initDocument 882 * 883 * @param dirty - a string of dirty markup 884 * @return a DOM, filled with the dirty markup 885 */ 886 const _initDocument = function _initDocument(dirty) { 887 let doc = null; 888 let leadingWhitespace = null; 889 if (FORCE_BODY) dirty = "<remove></remove>" + dirty; 890 else { 891 const matches = stringMatch(dirty, /^[\r\n\t ]+/); 892 leadingWhitespace = matches && matches[0]; 893 } 894 if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) dirty = "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>" + dirty + "</body></html>"; 895 const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty; 896 if (NAMESPACE === HTML_NAMESPACE) try { 897 doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE); 898 } catch (_) {} 899 if (!doc || !doc.documentElement) { 900 doc = implementation.createDocument(NAMESPACE, "template", null); 901 try { 902 doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload; 903 } catch (_) {} 904 } 905 const body = doc.body || doc.documentElement; 906 if (dirty && leadingWhitespace) body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null); 907 if (NAMESPACE === HTML_NAMESPACE) return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0]; 908 return WHOLE_DOCUMENT ? doc.documentElement : body; 909 }; 910 /** 911 * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. 912 * 913 * @param root The root element or node to start traversing on. 914 * @return The created NodeIterator 915 */ 916 const _createNodeIterator = function _createNodeIterator(root) { 917 const doc = getOwnerDocument ? getOwnerDocument(root) : root.ownerDocument; 918 return createNodeIterator.call(doc || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null); 919 }; 920 /** 921 * Replace template expression syntax (mustache, ERB, template 922 * literal) with a space; shared by all SAFE_FOR_TEMPLATES scrub 923 * sites. Order matters: mustache, then ERB, then template literal. 924 * 925 * @param value the string to scrub 926 * @returns the scrubbed string 927 */ 928 const _stripTemplateExpressions = function _stripTemplateExpressions(value) { 929 value = stringReplace(value, MUSTACHE_EXPR$1, " "); 930 value = stringReplace(value, ERB_EXPR$1, " "); 931 value = stringReplace(value, TMPLIT_EXPR$1, " "); 932 return value; 933 }; 934 /** 935 * Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the 936 * character data of an element subtree. Used as the final safety net for 937 * SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions 938 * which only form after text-node normalization (e.g. fragments split across 939 * stripped elements) cannot survive into a template-evaluating framework. 940 * 941 * Walks text/comment/CDATA/processing-instruction nodes and mutates `.data` 942 * in place rather than round-tripping through innerHTML. This preserves 943 * descendant node references (important for IN_PLACE callers), avoids a 944 * serialize/reparse cycle, and reads literal character data — which means 945 * `<%...%>` in text content matches the ERB regex against its real bytes 946 * instead of the HTML-entity-escaped form innerHTML would produce. 947 * 948 * Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for 949 * attributes is performed during the per-node `_sanitizeAttributes` pass. 950 * 951 * @param node The root element whose character data should be scrubbed. 952 */ 953 const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) { 954 var _node$querySelectorAl; 955 node.normalize(); 956 const doc = getOwnerDocument ? getOwnerDocument(node) : node.ownerDocument; 957 const walker = createNodeIterator.call(doc || node, node, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null); 958 let currentNode = walker.nextNode(); 959 while (currentNode) { 960 currentNode.data = _stripTemplateExpressions(currentNode.data); 961 currentNode = walker.nextNode(); 962 } 963 const templates = (_node$querySelectorAl = node.querySelectorAll) === null || _node$querySelectorAl === void 0 ? void 0 : _node$querySelectorAl.call(node, "template"); 964 if (templates) arrayForEach(templates, (tmpl) => { 965 if (_isDocumentFragment(tmpl.content)) _scrubTemplateExpressions2(tmpl.content); 966 }); 967 }; 968 /** 969 * _isClobbered 970 * 971 * Detect DOM-clobbering on HTMLFormElement nodes. Form is the only HTML 972 * interface with [LegacyOverrideBuiltIns]; a descendant element with a 973 * `name` attribute matching a prototype property shadows that property 974 * on direct reads. We use this check at the IN_PLACE entry-point and 975 * during attribute sanitization to refuse clobbered forms. 976 * 977 * @param element element to check for clobbering attacks 978 * @return true if clobbered, false if safe 979 */ 980 const _isClobbered = function _isClobbered(element) { 981 const realTagName = getNodeName ? getNodeName(element) : null; 982 if (typeof realTagName !== "string") return false; 983 if (transformCaseFunc(realTagName) !== "form") return false; 984 return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.removeAttributeNode !== "function" || typeof element.getAttributeNode !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || element.nodeType !== getNodeType(element) || element.childNodes !== getChildNodes(element); 985 }; 986 /** 987 * Checks whether the given value is a DocumentFragment from any realm. 988 * 989 * The realm-independent replacement reads `nodeType` through the cached 990 * Node.prototype getter and compares to the DOCUMENT_FRAGMENT_NODE 991 * constant (11). nodeType is a numeric value resolved from the node's 992 * internal slot, identical across realms for the same kind of node. 993 * 994 * @param value object to check 995 * @return true if value is a DocumentFragment-shaped node from any realm 996 */ 997 const _isDocumentFragment = function _isDocumentFragment(value) { 998 if (!getNodeType || typeof value !== "object" || value === null) return false; 999 try { 1000 return getNodeType(value) === NODE_TYPE.documentFragment; 1001 } catch (_) { 1002 return false; 1003 } 1004 }; 1005 /** 1006 * Checks whether the given object is a DOM node, including nodes that 1007 * originate from a different window/realm (e.g. an iframe's 1008 * contentDocument). The previous `value instanceof Node` check was 1009 * realm-bound: nodes from a different window failed it, causing 1010 * sanitize() to silently stringify them and reset IN_PLACE to false, 1011 * returning the original node unsanitized. See GHSA-4w3q-35jp-p934. 1012 * 1013 * @param value object to check whether it's a DOM node 1014 * @return true if value is a DOM node from any realm 1015 */ 1016 const _isNode = function _isNode(value) { 1017 if (!getNodeType || typeof value !== "object" || value === null) return false; 1018 try { 1019 return typeof getNodeType(value) === "number"; 1020 } catch (_) { 1021 return false; 1022 } 1023 }; 1024 function _executeHooks(hooks, currentNode, data) { 1025 if (hooks.length === 0) return; 1026 arrayForEach(hooks, (hook) => { 1027 hook.call(DOMPurify, currentNode, data, CONFIG); 1028 }); 1029 } 1030 /** 1031 * Structural-threat checks that condemn a node regardless of the 1032 * allowlists: mXSS via namespace confusion, risky CSS construction, 1033 * processing instructions, markup-bearing comments. Pure predicate; 1034 * the caller removes. Check order is load-bearing. 1035 * 1036 * @param currentNode the node to inspect 1037 * @param tagName the node's transformCaseFunc'd tag name 1038 * @return true if the node must be removed 1039 */ 1040 const _isUnsafeNode = function _isUnsafeNode(currentNode, tagName) { 1041 if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) return true; 1042 if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && LITERAL_TEXT_ELEMENTS[tagName] && (_isNode(currentNode.firstElementChild) || typeof currentNode.textContent === "string" && regExpTest(LITERAL_TEXT_CLOSE[tagName], currentNode.textContent))) return true; 1043 if (currentNode.nodeType === NODE_TYPE.processingInstruction) return true; 1044 if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) return true; 1045 return false; 1046 }; 1047 /** 1048 * Evaluate a CUSTOM_ELEMENT_HANDLING check (a RegExp or a predicate 1049 * function, per the validation in _parseConfig) against a name. 1050 * Additional arguments are forwarded to predicate functions - the 1051 * attributeNameCheck predicate receives the tag name as its second 1052 * argument. A null/absent check never matches. 1053 * 1054 * @param check the configured tagNameCheck / attributeNameCheck value 1055 * @param name the name to test 1056 * @param args extra arguments forwarded to a predicate function 1057 * @return true if the check matches the name 1058 */ 1059 const _matchesNameCheck = function _matchesNameCheck(check, name) { 1060 if (check instanceof RegExp) return regExpTest(check, name); 1061 if (check instanceof Function) { 1062 for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) args[_key - 2] = arguments[_key]; 1063 return Boolean(check(name, ...args)); 1064 } 1065 return false; 1066 }; 1067 /** 1068 * Handle a node whose tag is forbidden or not allowlisted: keep 1069 * allowed custom elements (false return exits _sanitizeElements 1070 * early - the namespace and fallback-tag removal checks are 1071 * intentionally skipped for kept custom elements), else hoist 1072 * content per KEEP_CONTENT and remove. 1073 * 1074 * A kept custom element is the ONLY case in which this function 1075 * returns false, so the caller uses that return value to run the 1076 * afterSanitizeElements hook on the kept element and keep the 1077 * element-hook lifecycle consistent with normal allowlisted 1078 * elements (GHSA-c2j3-45gr-mqc4). 1079 * 1080 * @param currentNode the disallowed node 1081 * @param tagName the node's transformCaseFunc'd tag name 1082 * @return true if the node was removed, false if kept 1083 */ 1084 const _sanitizeDisallowedNode = function _sanitizeDisallowedNode(currentNode, tagName, root) { 1085 if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false; 1086 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) { 1087 const parentNode = getParentNode(currentNode); 1088 const childNodes = getChildNodes(currentNode); 1089 if (childNodes && parentNode) { 1090 const childCount = childNodes.length; 1091 for (let i = childCount - 1; i >= 0; --i) { 1092 const hoisted = currentNode === root ? cloneNode(childNodes[i], true) : childNodes[i]; 1093 parentNode.insertBefore(hoisted, getNextSibling(currentNode)); 1094 } 1095 } 1096 } 1097 _forceRemove(currentNode); 1098 return true; 1099 }; 1100 /** 1101 * Fork a hook-mutable allowlist off its shared binding the first time a 1102 * (possibly lazily-installed) uponSanitize* hook is about to see it, so the 1103 * hook cannot widen the per-instance default or the setConfig binding by 1104 * reference and leak past the call. Returns the set unchanged once it is 1105 * already call-local, so repeated calls across elements are idempotent. 1106 * 1107 * @param hookList the uponSanitize* hook array for this event 1108 * @param set the current ALLOWED_TAGS / ALLOWED_ATTR binding 1109 * @param defaultSet the per-instance DEFAULT_ALLOWED_* constant 1110 * @param setConfigSet the captured setConfig() binding, or null 1111 * @return a call-local clone if a hook is present and set is still shared, 1112 * else set unchanged 1113 */ 1114 const _forkSharedAllowlist = function _forkSharedAllowlist(hookList, set, defaultSet, setConfigSet) { 1115 if (hookList.length === 0) return set; 1116 return set === defaultSet || set === setConfigSet ? clone(set) : set; 1117 }; 1118 /** 1119 * Shared guard for a node that a hook has detached from the walk tree, 1120 * used after each element-hook site in _sanitizeElements. Detaching is a 1121 * long-standing user pattern (issue #469; draw.io-style foreignObject 1122 * filtering). Per the cached, unclobberable parentNode getter the node is 1123 * genuinely out of the tree, so it can reach neither the serialized 1124 * output nor an IN_PLACE live tree; treat it as removed and stop 1125 * processing it. Without this guard, the unsafe-node / namespace checks 1126 * would call _forceRemove on a parentless node and hit the REPORT-3 1127 * fail-closed throw — which exists for nodes DOMPurify wants gone but 1128 * *cannot* detach (clobbered / parentless roots), the opposite of a node 1129 * that is already safely gone. The walk root is exempt: a detached 1130 * IN_PLACE root is legitimate input and must still be fully sanitized, 1131 * and a kill-decision on it must keep hitting the REPORT-3 throw. 1132 * 1133 * Nodes detached by hooks stay the hook's responsibility for placement: 1134 * they are not recorded in DOMPurify.removed, so the post-walk IN_PLACE 1135 * pass (which iterates DOMPurify.removed) does not reach them. But a 1136 * hook-detached subtree can still hold a queued resource-event handler - 1137 * e.g. an <img onload> that began loading when the caller built the live 1138 * tree - which fires in page scope after sanitize returns even though the 1139 * handler never reached the returned tree. That is the audit-5 F1 hazard, 1140 * and the documented node.remove() hook pattern walks straight into it. 1141 * So on the IN_PLACE path we neutralize the detached subtree inline, 1142 * stripping its non-allow-listed attributes before returning, exactly as 1143 * the post-walk pass does for _forceRemove'd subtrees. 1144 * 1145 * @param currentNode the node a hook may have detached 1146 * @param root the current walk root 1147 * @return true if the node is detached and now handled, false otherwise 1148 */ 1149 const _handleHookDetachedNode = function _handleHookDetachedNode(currentNode, root) { 1150 if (currentNode === root || getParentNode(currentNode) !== null) return false; 1151 if (IN_PLACE) _neutralizeSubtree(currentNode); 1152 return true; 1153 }; 1154 /** 1155 * _sanitizeElements 1156 * 1157 * @protect nodeName 1158 * @protect textContent 1159 * @protect removeChild 1160 * @param currentNode to check for permission to exist 1161 * @return true if node was killed, false if left alive 1162 */ 1163 const _sanitizeElements = function _sanitizeElements(currentNode, root) { 1164 _executeHooks(hooks.beforeSanitizeElements, currentNode, null); 1165 if (_handleHookDetachedNode(currentNode, root)) return true; 1166 if (_isClobbered(currentNode)) { 1167 _forceRemove(currentNode); 1168 return true; 1169 } 1170 const tagName = transformCaseFunc(_readNodeName(currentNode)); 1171 ALLOWED_TAGS = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS); 1172 _executeHooks(hooks.uponSanitizeElement, currentNode, { 1173 tagName, 1174 allowedTags: ALLOWED_TAGS 1175 }); 1176 if (_handleHookDetachedNode(currentNode, root)) return true; 1177 if (_isUnsafeNode(currentNode, tagName)) { 1178 _forceRemove(currentNode); 1179 return true; 1180 } 1181 if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) { 1182 const removed = _sanitizeDisallowedNode(currentNode, tagName, root); 1183 if (removed === false)
vendor: 24,299 bytes, lines 1183-1953
1183_executeHooks(hooks.afterSanitizeElements, currentNode, null); 1184 return removed; 1185 } 1186 if (_readNodeType(currentNode) === NODE_TYPE.element && !_checkValidNamespace(currentNode)) { 1187 _forceRemove(currentNode); 1188 return true; 1189 } 1190 if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) { 1191 _forceRemove(currentNode); 1192 return true; 1193 } 1194 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) { 1195 const content = _stripTemplateExpressions(currentNode.textContent); 1196 if (currentNode.textContent !== content) { 1197 arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() }); 1198 currentNode.textContent = content; 1199 } 1200 } 1201 _executeHooks(hooks.afterSanitizeElements, currentNode, null); 1202 return false; 1203 }; 1204 /** 1205 * _isValidAttribute 1206 * 1207 * @param lcTag Lowercase tag name of containing element. 1208 * @param lcName Lowercase attribute name. 1209 * @param value Attribute value. 1210 * @return Returns true if `value` is valid, otherwise false. 1211 */ 1212 const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) { 1213 if (FORBID_ATTR[lcName]) return false; 1214 if (_isPatchLinkageAttribute(lcName, lcTag)) return false; 1215 if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document || value in formElement)) return false; 1216 const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag); 1217 if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) return true; 1218 if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) return true; 1219 if (!nameIsPermitted) return _isBasicCustomElement(lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName, lcTag) || lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value); 1220 if (URI_SAFE_ATTRIBUTES[lcName]) return true; 1221 if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true; 1222 if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) return true; 1223 if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true; 1224 return !value; 1225 }; 1226 const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, [ 1227 "annotation-xml", 1228 "color-profile", 1229 "font-face", 1230 "font-face-format", 1231 "font-face-name", 1232 "font-face-src", 1233 "font-face-uri", 1234 "missing-glyph" 1235 ]); 1236 /** 1237 * _isBasicCustomElement 1238 * checks if at least one dash is included in tagName, and it's not the first char 1239 * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name 1240 * 1241 * @param tagName name of the tag of the node to sanitize 1242 * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false. 1243 */ 1244 const _isBasicCustomElement = function _isBasicCustomElement(tagName) { 1245 return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName); 1246 }; 1247 /** 1248 * Wrap an attribute value in the matching Trusted Types object when 1249 * the active policy requires it. Namespaced attributes pass through 1250 * unchanged (no TT support yet, see 1251 * https://bugs.chromium.org/p/chromium/issues/detail?id=1305293). 1252 * 1253 * @param lcTag lowercase tag name of the containing element 1254 * @param lcName lowercase attribute name 1255 * @param namespaceURI the attribute's namespace, if any 1256 * @param value the attribute value to wrap 1257 * @return the value, wrapped when Trusted Types demand it 1258 */ 1259 const _applyTrustedTypesToAttribute = function _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value) { 1260 if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function" && !namespaceURI) switch (trustedTypes.getAttributeType(lcTag, lcName)) { 1261 case "TrustedHTML": return _createTrustedHTML(value); 1262 case "TrustedScriptURL": return _createTrustedScriptURL(value); 1263 } 1264 return value; 1265 }; 1266 /** 1267 * Write a modified attribute value back onto the element. On 1268 * success, re-probe for clobbering introduced by the new value and 1269 * remove the element when found; otherwise, when this writeback is the 1270 * recreate half of the SANITIZE_NAMED_PROPS remove-and-recreate, pop the 1271 * removal entry that path recorded so it does not show as removed. On 1272 * failure, remove the attribute instead. 1273 * 1274 * Returns true only on a clean write (the value was set and the new value 1275 * introduced no clobbering). The caller uses that, together with its own 1276 * knowledge of whether this attribute pushed a DOMPurify.removed record, to 1277 * decide whether to pop that record. The pop must happen ONLY for the 1278 * named-prop remove-and-recreate; popping on any other value change (trim, 1279 * template scrubbing, Trusted Types) would consume an unrelated _forceRemove 1280 * subtree-cleanup record and let that detached subtree keep a live event 1281 * handler through the IN_PLACE neutralization pass (SO-001). 1282 * 1283 * @param currentNode the element carrying the attribute 1284 * @param name the attribute name as present on the element 1285 * @param namespaceURI the attribute's namespace, if any 1286 * @param value the new attribute value 1287 * @return true if the value was written without introducing clobbering 1288 */ 1289 const _setAttributeValue = function _setAttributeValue(currentNode, name, namespaceURI, value) { 1290 try { 1291 if (namespaceURI) currentNode.setAttributeNS(namespaceURI, name, value); 1292 else currentNode.setAttribute(name, value); 1293 if (_isClobbered(currentNode)) { 1294 _forceRemove(currentNode); 1295 return false; 1296 } 1297 return true; 1298 } catch (_) { 1299 _removeAttribute(name, currentNode); 1300 return false; 1301 } 1302 }; 1303 /** 1304 * _sanitizeAttributes 1305 * 1306 * @protect attributes 1307 * @protect nodeName 1308 * @protect removeAttribute 1309 * @protect setAttribute 1310 * 1311 * @param currentNode to sanitize 1312 */ 1313 const _sanitizeAttributes = function _sanitizeAttributes(currentNode) { 1314 _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null); 1315 const attributes = currentNode.attributes; 1316 if (!attributes || _isClobbered(currentNode)) return; 1317 ALLOWED_ATTR = _forkSharedAllowlist(hooks.uponSanitizeAttribute, ALLOWED_ATTR, DEFAULT_ALLOWED_ATTR, SET_CONFIG_ALLOWED_ATTR); 1318 const hookEvent = { 1319 attrName: "", 1320 attrValue: "", 1321 keepAttr: true, 1322 allowedAttributes: ALLOWED_ATTR, 1323 forceKeepAttr: void 0 1324 }; 1325 let l = attributes.length; 1326 const lcTag = transformCaseFunc(currentNode.nodeName); 1327 while (l--) { 1328 const attr = attributes[l]; 1329 const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value; 1330 const lcName = transformCaseFunc(name); 1331 const initValue = attrValue; 1332 let value = name === "value" ? initValue : stringTrim(initValue); 1333 let recreatedNamedProp = false; 1334 hookEvent.attrName = lcName; 1335 hookEvent.attrValue = value; 1336 hookEvent.keepAttr = true; 1337 hookEvent.forceKeepAttr = void 0; 1338 _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent); 1339 value = hookEvent.attrValue; 1340 if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) { 1341 _removeAttribute(name, currentNode, attr); 1342 value = SANITIZE_NAMED_PROPS_PREFIX + value; 1343 recreatedNamedProp = true; 1344 } 1345 if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) { 1346 _removeAttribute(name, currentNode, attr); 1347 continue; 1348 } 1349 if (lcName === "attributename" && stringMatch(value, "href")) { 1350 _removeAttribute(name, currentNode, attr); 1351 continue; 1352 } 1353 if (hookEvent.forceKeepAttr) continue; 1354 if (!hookEvent.keepAttr) { 1355 _removeAttribute(name, currentNode, attr); 1356 continue; 1357 } 1358 if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) { 1359 _removeAttribute(name, currentNode, attr); 1360 continue; 1361 } 1362 if (SAFE_FOR_TEMPLATES) value = _stripTemplateExpressions(value); 1363 if (!_isValidAttribute(lcTag, lcName, value)) { 1364 _removeAttribute(name, currentNode, attr); 1365 continue; 1366 } 1367 value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value); 1368 if (value !== initValue) { 1369 if (_setAttributeValue(currentNode, name, namespaceURI, value) && recreatedNamedProp) arrayPop(DOMPurify.removed); 1370 } 1371 } 1372 _executeHooks(hooks.afterSanitizeAttributes, currentNode, null); 1373 }; 1374 /** 1375 * _sanitizeShadowDOM 1376 * 1377 * @param fragment to iterate over recursively 1378 */ 1379 const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) { 1380 let shadowNode = null; 1381 const shadowIterator = _createNodeIterator(fragment); 1382 _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null); 1383 while (shadowNode = shadowIterator.nextNode()) { 1384 _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null); 1385 _sanitizeElements(shadowNode, fragment); 1386 _sanitizeAttributes(shadowNode); 1387 if (_isDocumentFragment(shadowNode.content)) _sanitizeShadowDOM2(shadowNode.content); 1388 if (_readNodeType(shadowNode) === NODE_TYPE.element) { 1389 const innerSr = getShadowRoot(shadowNode); 1390 if (_isDocumentFragment(innerSr)) { 1391 _sanitizeAttachedShadowRoots(innerSr); 1392 _sanitizeShadowDOM2(innerSr); 1393 } 1394 } 1395 } 1396 _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null); 1397 }; 1398 /** 1399 * _sanitizeAttachedShadowRoots 1400 * 1401 * Walks `root` and feeds every attached shadow root we encounter into 1402 * the existing _sanitizeShadowDOM pipeline. The default node iterator 1403 * does not descend into shadow trees, so nodes inside an attached 1404 * shadow root would otherwise be skipped entirely. 1405 * 1406 * Two real input paths put attached shadow roots in front of us: 1407 * 1. IN_PLACE on a DOM node that already has shadow roots attached. 1408 * 2. DOM-node input where importNode(dirty, true) deep-clones the 1409 * shadow root because it was created with `clonable: true`. 1410 * 1411 * This pass runs once, up front, so the main iteration loop (and the 1412 * existing _sanitizeShadowDOM template-content recursion) stay 1413 * untouched — string-input paths are not affected. 1414 * 1415 * @param root the subtree root to walk for attached shadow roots 1416 */ 1417 const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots(root) { 1418 const stack = [{ 1419 node: root, 1420 shadow: null 1421 }]; 1422 while (stack.length > 0) { 1423 const item = stack.pop(); 1424 if (item.shadow) { 1425 _sanitizeShadowDOM2(item.shadow); 1426 continue; 1427 } 1428 const node = item.node; 1429 const isElement = _readNodeType(node) === NODE_TYPE.element; 1430 const childNodes = getChildNodes(node); 1431 if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push({ 1432 node: childNodes[i], 1433 shadow: null 1434 }); 1435 if (isElement) { 1436 const rootName = getNodeName ? getNodeName(node) : null; 1437 if (typeof rootName === "string" && transformCaseFunc(rootName) === "template") { 1438 const content = node.content; 1439 if (_isDocumentFragment(content)) stack.push({ 1440 node: content, 1441 shadow: null 1442 }); 1443 } 1444 } 1445 if (isElement) { 1446 const sr = getShadowRoot(node); 1447 if (_isDocumentFragment(sr)) stack.push({ 1448 node: null, 1449 shadow: sr 1450 }, { 1451 node: sr, 1452 shadow: null 1453 }); 1454 } 1455 } 1456 }; 1457 DOMPurify.sanitize = function(dirty) { 1458 let cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}; 1459 let body = null; 1460 let importedNode = null; 1461 let currentNode = null; 1462 let returnNode = null; 1463 IS_EMPTY_INPUT = !dirty; 1464 if (IS_EMPTY_INPUT) dirty = "<!-->"; 1465 if (typeof dirty !== "string" && !_isNode(dirty)) { 1466 dirty = stringifyValue(dirty); 1467 if (typeof dirty !== "string") throw typeErrorCreate("dirty is not a string, aborting"); 1468 } 1469 if (!DOMPurify.isSupported) return dirty; 1470 if (SET_CONFIG) { 1471 ALLOWED_TAGS = SET_CONFIG_ALLOWED_TAGS; 1472 ALLOWED_ATTR = SET_CONFIG_ALLOWED_ATTR; 1473 } else _parseConfig(cfg); 1474 if (hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) ALLOWED_TAGS = clone(ALLOWED_TAGS); 1475 if (hooks.uponSanitizeAttribute.length > 0) ALLOWED_ATTR = clone(ALLOWED_ATTR); 1476 DOMPurify.removed = []; 1477 const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty); 1478 if (inPlace) { 1479 _neutralizePatchLinkage(dirty); 1480 const nn = _readNodeName(dirty); 1481 if (typeof nn === "string") { 1482 const tagName = transformCaseFunc(nn); 1483 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { 1484 _neutralizeRoot(dirty); 1485 throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place"); 1486 } 1487 } 1488 if (_isClobbered(dirty)) { 1489 _neutralizeRoot(dirty); 1490 throw typeErrorCreate("root node is clobbered and cannot be sanitized in-place"); 1491 } 1492 try { 1493 _sanitizeAttachedShadowRoots(dirty); 1494 } catch (error) { 1495 _neutralizeRoot(dirty); 1496 throw error; 1497 } 1498 } else if (_isNode(dirty)) { 1499 body = _initDocument("<!---->"); 1500 importedNode = body.ownerDocument.importNode(dirty, true); 1501 if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") body = importedNode; 1502 else if (importedNode.nodeName === "HTML") body = importedNode; 1503 else body.appendChild(importedNode); 1504 _sanitizeAttachedShadowRoots(body); 1505 } else { 1506 if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf("<") === -1) return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty; 1507 body = _initDocument(dirty); 1508 if (!body) return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : ""; 1509 } 1510 if (body && FORCE_BODY) _forceRemove(body.firstChild); 1511 const walkRoot = inPlace ? dirty : body; 1512 try { 1513 const nodeIterator = _createNodeIterator(walkRoot); 1514 while (currentNode = nodeIterator.nextNode()) { 1515 _sanitizeElements(currentNode, walkRoot); 1516 _sanitizeAttributes(currentNode); 1517 if (_isDocumentFragment(currentNode.content)) _sanitizeShadowDOM2(currentNode.content); 1518 } 1519 } catch (error) { 1520 if (inPlace) { 1521 _neutralizeRoot(dirty); 1522 arrayForEach(DOMPurify.removed, (entry) => { 1523 if (entry.element) _neutralizeSubtree(entry.element); 1524 }); 1525 } 1526 throw error; 1527 } 1528 if (inPlace) { 1529 arrayForEach(DOMPurify.removed, (entry) => { 1530 if (entry.element) _neutralizeSubtree(entry.element); 1531 }); 1532 if (SAFE_FOR_TEMPLATES) _scrubTemplateExpressions2(dirty); 1533 return dirty; 1534 } 1535 if (RETURN_DOM) { 1536 if (SAFE_FOR_TEMPLATES) _scrubTemplateExpressions2(body); 1537 if (RETURN_DOM_FRAGMENT) { 1538 returnNode = createDocumentFragment.call(body.ownerDocument); 1539 while (body.firstChild) returnNode.appendChild(body.firstChild); 1540 } else returnNode = body; 1541 if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) returnNode = importNode.call(originalDocument, returnNode, true); 1542 return returnNode; 1543 } 1544 let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; 1545 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; 1546 if (SAFE_FOR_TEMPLATES) serializedHTML = _stripTemplateExpressions(serializedHTML); 1547 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML; 1548 }; 1549 DOMPurify.setConfig = function() { 1550 let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; 1551 _parseConfig(cfg); 1552 SET_CONFIG = true; 1553 SET_CONFIG_ALLOWED_TAGS = ALLOWED_TAGS; 1554 SET_CONFIG_ALLOWED_ATTR = ALLOWED_ATTR; 1555 }; 1556 DOMPurify.clearConfig = function() { 1557 CONFIG = null; 1558 SET_CONFIG = false; 1559 SET_CONFIG_ALLOWED_TAGS = null; 1560 SET_CONFIG_ALLOWED_ATTR = null; 1561 trustedTypesPolicy = defaultTrustedTypesPolicy; 1562 emptyHTML = ""; 1563 }; 1564 DOMPurify.isValidAttribute = function(tag, attr, value) { 1565 if (!CONFIG) _parseConfig({}); 1566 const lcTag = transformCaseFunc(tag); 1567 const lcName = transformCaseFunc(attr); 1568 return _isValidAttribute(lcTag, lcName, value); 1569 }; 1570 DOMPurify.addHook = function(entryPoint, hookFunction) { 1571 if (typeof hookFunction !== "function") return; 1572 if (!objectHasOwnProperty(hooks, entryPoint)) return; 1573 arrayPush(hooks[entryPoint], hookFunction); 1574 }; 1575 DOMPurify.removeHook = function(entryPoint, hookFunction) { 1576 if (!objectHasOwnProperty(hooks, entryPoint)) return; 1577 if (hookFunction !== void 0) { 1578 const index = arrayLastIndexOf(hooks[entryPoint], hookFunction); 1579 return index === -1 ? void 0 : arraySplice(hooks[entryPoint], index, 1)[0]; 1580 } 1581 return arrayPop(hooks[entryPoint]); 1582 }; 1583 DOMPurify.removeHooks = function(entryPoint) { 1584 if (!objectHasOwnProperty(hooks, entryPoint)) return; 1585 hooks[entryPoint] = []; 1586 }; 1587 DOMPurify.removeAllHooks = function() { 1588 hooks = _createHooksMap(); 1589 }; 1590 return DOMPurify; 1591} 1592var entries, setPrototypeOf, isFrozen, getPrototypeOf, getOwnPropertyDescriptor, freeze, seal, create, _ref, apply, construct, arrayForEach, arrayLastIndexOf, arrayPop, arrayPush, arraySplice, arrayIsArray, stringToLowerCase, stringToString, stringMatch, stringReplace, stringIndexOf, stringTrim, numberToString, booleanToString, bigintToString, symbolToString, objectHasOwnProperty, objectToString, regExpTest, typeErrorCreate, html$1, svg$1, svgFilters, svgDisallowed, mathMl$1, mathMlDisallowed, text, html, svg, mathMl, xml, MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR, DATA_ATTR, ARIA_ATTR, IS_ALLOWED_URI, IS_SCRIPT_OR_DATA, ATTR_WHITESPACE, DOCTYPE_NAME, CUSTOM_ELEMENT, ELEMENT_MARKUP_PROBE, COMMENT_MARKUP_PROBE, FALLBACK_TAG_CLOSE, SELF_CLOSING_TAG, NODE_TYPE, LITERAL_TEXT_ELEMENT_NAMES, LITERAL_TEXT_ELEMENTS, LITERAL_TEXT_CLOSE, getGlobal, _createTrustedTypesPolicy, _createHooksMap, _resolveSetOption, _resolveObjectOption, purify; 1593function init_purify_es() { 1594 return (init_purify_es = __esmMin((() => { 1595 entries = Object.entries; 1596 setPrototypeOf = Object.setPrototypeOf; 1597 isFrozen = Object.isFrozen; 1598 getPrototypeOf = Object.getPrototypeOf; 1599 getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 1600 freeze = Object.freeze; 1601 seal = Object.seal; 1602 create = Object.create; 1603 _ref = typeof Reflect !== "undefined" && Reflect; 1604 apply = _ref.apply; 1605 construct = _ref.construct; 1606 if (!freeze) freeze = function freeze(x) { 1607 return x; 1608 }; 1609 if (!seal) seal = function seal(x) { 1610 return x; 1611 }; 1612 if (!apply) apply = function apply(func, thisArg) { 1613 for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) args[_key - 2] = arguments[_key]; 1614 return func.apply(thisArg, args); 1615 }; 1616 if (!construct) construct = function construct(Func) { 1617 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) args[_key2 - 1] = arguments[_key2]; 1618 return new Func(...args); 1619 }; 1620 arrayForEach = unapply(Array.prototype.forEach); 1621 arrayLastIndexOf = unapply(Array.prototype.lastIndexOf); 1622 arrayPop = unapply(Array.prototype.pop); 1623 arrayPush = unapply(Array.prototype.push); 1624 arraySplice = unapply(Array.prototype.splice); 1625 arrayIsArray = Array.isArray; 1626 stringToLowerCase = unapply(String.prototype.toLowerCase); 1627 stringToString = unapply(String.prototype.toString); 1628 stringMatch = unapply(String.prototype.match); 1629 stringReplace = unapply(String.prototype.replace); 1630 stringIndexOf = unapply(String.prototype.indexOf); 1631 stringTrim = unapply(String.prototype.trim); 1632 numberToString = unapply(Number.prototype.toString); 1633 booleanToString = unapply(Boolean.prototype.toString); 1634 bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString); 1635 symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString); 1636 objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); 1637 objectToString = unapply(Object.prototype.toString); 1638 regExpTest = unapply(RegExp.prototype.test); 1639 typeErrorCreate = unconstruct(TypeError); 1640 html$1 = freeze([ 1641 "a", 1642 "abbr", 1643 "acronym", 1644 "address", 1645 "area", 1646 "article", 1647 "aside", 1648 "audio", 1649 "b", 1650 "bdi", 1651 "bdo", 1652 "big", 1653 "blink", 1654 "blockquote", 1655 "body", 1656 "br", 1657 "button", 1658 "canvas", 1659 "caption", 1660 "center", 1661 "cite", 1662 "code", 1663 "col", 1664 "colgroup", 1665 "content", 1666 "data", 1667 "datalist", 1668 "dd", 1669 "decorator", 1670 "del", 1671 "details", 1672 "dfn", 1673 "dialog", 1674 "dir", 1675 "div", 1676 "dl", 1677 "dt", 1678 "element", 1679 "em", 1680 "fieldset", 1681 "figcaption", 1682 "figure", 1683 "font", 1684 "footer", 1685 "form", 1686 "h1", 1687 "h2", 1688 "h3", 1689 "h4", 1690 "h5", 1691 "h6", 1692 "head", 1693 "header", 1694 "hgroup", 1695 "hr", 1696 "html", 1697 "i", 1698 "img", 1699 "input", 1700 "ins", 1701 "kbd", 1702 "label", 1703 "legend", 1704 "li", 1705 "main", 1706 "map", 1707 "mark", 1708 "marquee", 1709 "menu", 1710 "menuitem", 1711 "meter", 1712 "nav", 1713 "nobr", 1714 "ol", 1715 "optgroup", 1716 "option", 1717 "output", 1718 "p", 1719 "picture", 1720 "pre", 1721 "progress", 1722 "q", 1723 "rp", 1724 "rt", 1725 "ruby", 1726 "s", 1727 "samp", 1728 "search", 1729 "section", 1730 "select", 1731 "shadow", 1732 "slot", 1733 "small", 1734 "source", 1735 "spacer", 1736 "span", 1737 "strike", 1738 "strong", 1739 "style", 1740 "sub", 1741 "summary", 1742 "sup", 1743 "table", 1744 "tbody", 1745 "td", 1746 "template", 1747 "textarea", 1748 "tfoot", 1749 "th", 1750 "thead", 1751 "time", 1752 "tr", 1753 "track", 1754 "tt", 1755 "u", 1756 "ul", 1757 "var", 1758 "video", 1759 "wbr" 1760 ]); 1761 svg$1 = freeze([ 1762 "svg", 1763 "a", 1764 "altglyph", 1765 "altglyphdef", 1766 "altglyphitem", 1767 "animatecolor", 1768 "animatemotion", 1769 "animatetransform", 1770 "circle", 1771 "clippath", 1772 "defs", 1773 "desc", 1774 "ellipse", 1775 "enterkeyhint", 1776 "exportparts", 1777 "filter", 1778 "font", 1779 "g", 1780 "glyph", 1781 "glyphref", 1782 "hkern", 1783 "image", 1784 "inputmode", 1785 "line", 1786 "lineargradient", 1787 "marker", 1788 "mask", 1789 "metadata", 1790 "mpath", 1791 "part", 1792 "path", 1793 "pattern", 1794 "polygon", 1795 "polyline", 1796 "radialgradient", 1797 "rect", 1798 "stop", 1799 "style", 1800 "switch", 1801 "symbol", 1802 "text", 1803 "textpath", 1804 "title", 1805 "tref", 1806 "tspan", 1807 "view", 1808 "vkern" 1809 ]); 1810 svgFilters = freeze([ 1811 "feBlend", 1812 "feColorMatrix", 1813 "feComponentTransfer", 1814 "feComposite", 1815 "feConvolveMatrix", 1816 "feDiffuseLighting", 1817 "feDisplacementMap", 1818 "feDistantLight", 1819 "feDropShadow", 1820 "feFlood", 1821 "feFuncA", 1822 "feFuncB", 1823 "feFuncG", 1824 "feFuncR", 1825 "feGaussianBlur", 1826 "feImage", 1827 "feMerge", 1828 "feMergeNode", 1829 "feMorphology", 1830 "feOffset", 1831 "fePointLight", 1832 "feSpecularLighting", 1833 "feSpotLight", 1834 "feTile", 1835 "feTurbulence" 1836 ]); 1837 svgDisallowed = freeze([ 1838 "animate", 1839 "color-profile", 1840 "cursor", 1841 "discard", 1842 "font-face", 1843 "font-face-format", 1844 "font-face-name", 1845 "font-face-src", 1846 "font-face-uri", 1847 "foreignobject", 1848 "hatch", 1849 "hatchpath", 1850 "mesh", 1851 "meshgradient", 1852 "meshpatch", 1853 "meshrow", 1854 "missing-glyph", 1855 "script", 1856 "set", 1857 "solidcolor", 1858 "unknown", 1859 "use" 1860 ]); 1861 mathMl$1 = freeze([ 1862 "math", 1863 "menclose", 1864 "merror", 1865 "mfenced", 1866 "mfrac", 1867 "mglyph", 1868 "mi", 1869 "mlabeledtr", 1870 "mmultiscripts", 1871 "mn", 1872 "mo", 1873 "mover", 1874 "mpadded", 1875 "mphantom", 1876 "mroot", 1877 "mrow", 1878 "ms", 1879 "mspace", 1880 "msqrt", 1881 "mstyle", 1882 "msub", 1883 "msup", 1884 "msubsup", 1885 "mtable", 1886 "mtd", 1887 "mtext", 1888 "mtr", 1889 "munder", 1890 "munderover", 1891 "mprescripts" 1892 ]); 1893 mathMlDisallowed = freeze([ 1894 "maction", 1895 "maligngroup", 1896 "malignmark", 1897 "mlongdiv", 1898 "mscarries", 1899 "mscarry", 1900 "msgroup", 1901 "mstack", 1902 "msline", 1903 "msrow", 1904 "semantics", 1905 "annotation", 1906 "annotation-xml", 1907 "mprescripts", 1908 "none" 1909 ]); 1910 text = freeze(["#text"]); 1911 html = freeze([ 1912 "accept", 1913 "action", 1914 "align", 1915 "alt", 1916 "autocapitalize", 1917 "autocomplete", 1918 "autopictureinpicture", 1919 "autoplay", 1920 "background", 1921 "bgcolor", 1922 "border", 1923 "capture", 1924 "cellpadding", 1925 "cellspacing", 1926 "checked", 1927 "cite", 1928 "class", 1929 "clear", 1930 "color", 1931 "cols", 1932 "colspan", 1933 "command", 1934 "commandfor", 1935 "controls", 1936 "controlslist", 1937 "coords", 1938 "crossorigin", 1939 "datetime", 1940 "decoding", 1941 "default", 1942 "dir", 1943 "disabled", 1944 "disablepictureinpicture", 1945 "disableremoteplayback", 1946 "download", 1947 "draggable", 1948 "enctype", 1949 "enterkeyhint", 1950 "exportparts", 1951 "face", 1952 "for", 1953 "headers",
1954 "height", 1955 "hidden", 1956 "high", 1957 "href", 1958 "hreflang", 1959 "id", 1960 "inert", 1961 "inputmode", 1962 "integrity", 1963 "ismap", 1964 "kind", 1965 "label", 1966 "lang", 1967 "list", 1968 "loading", 1969 "loop", 1970 "low", 1971 "max", 1972 "maxlength", 1973 "media", 1974 "method", 1975 "min", 1976 "minlength", 1977 "multiple", 1978 "muted", 1979 "name", 1980 "nonce", 1981 "noshade", 1982 "novalidate", 1983 "nowrap", 1984 "open", 1985 "optimum", 1986 "part", 1987 "pattern", 1988 "placeholder", 1989 "playsinline", 1990 "popover", 1991 "popovertarget", 1992 "popovertargetaction", 1993 "poster", 1994 "preload", 1995 "pubdate", 1996 "radiogroup", 1997 "readonly", 1998 "rel", 1999 "required", 2000 "rev", 2001 "reversed", 2002 "role", 2003 "rows", 2004 "rowspan", 2005 "spellcheck", 2006 "scope", 2007 "selected", 2008 "shape", 2009 "size", 2010 "sizes", 2011 "slot", 2012 "span", 2013 "srclang", 2014 "start", 2015 "src", 2016 "srcset", 2017 "step", 2018 "style", 2019 "summary", 2020 "tabindex", 2021 "title", 2022 "translate", 2023 "type", 2024 "usemap", 2025 "valign", 2026 "value", 2027 "width", 2028 "wrap", 2029 "xmlns" 2030 ]); 2031 svg = freeze([ 2032 "accent-height", 2033 "accumulate", 2034 "additive", 2035 "alignment-baseline", 2036 "amplitude", 2037 "ascent", 2038 "attributename", 2039 "attributetype", 2040 "azimuth", 2041 "basefrequency", 2042 "baseline-shift", 2043 "begin", 2044 "bias", 2045 "by", 2046 "class", 2047 "clip", 2048 "clippathunits", 2049 "clip-path", 2050 "clip-rule", 2051 "color", 2052 "color-interpolation", 2053 "color-interpolation-filters", 2054 "color-profile", 2055 "color-rendering", 2056 "cx", 2057 "cy", 2058 "d", 2059 "dx", 2060 "dy", 2061 "diffuseconstant", 2062 "direction", 2063 "display", 2064 "divisor", 2065 "dominant-baseline", 2066 "dur", 2067 "edgemode", 2068 "elevation", 2069 "end", 2070 "exponent", 2071 "fill", 2072 "fill-opacity", 2073 "fill-rule", 2074 "filter", 2075 "filterunits", 2076 "flood-color", 2077 "flood-opacity", 2078 "font-family", 2079 "font-size", 2080 "font-size-adjust", 2081 "font-stretch", 2082 "font-style", 2083 "font-variant", 2084 "font-weight", 2085 "fx", 2086 "fy", 2087 "g1", 2088 "g2", 2089 "glyph-name", 2090 "glyphref", 2091 "gradientunits", 2092 "gradienttransform", 2093 "height", 2094 "href", 2095 "id", 2096 "image-rendering", 2097 "in", 2098 "in2", 2099 "intercept", 2100 "k", 2101 "k1", 2102 "k2", 2103 "k3", 2104 "k4", 2105 "kerning", 2106 "keypoints", 2107 "keysplines", 2108 "keytimes", 2109 "lang", 2110 "lengthadjust", 2111 "letter-spacing", 2112 "kernelmatrix", 2113 "kernelunitlength", 2114 "lighting-color", 2115 "local", 2116 "marker-end", 2117 "marker-mid", 2118 "marker-start", 2119 "markerheight", 2120 "markerunits", 2121 "markerwidth", 2122 "maskcontentunits", 2123 "maskunits", 2124 "max", 2125 "mask", 2126 "mask-type", 2127 "media", 2128 "method", 2129 "mode", 2130 "min", 2131 "name", 2132 "numoctaves", 2133 "offset", 2134 "operator", 2135 "opacity", 2136 "order", 2137 "orient", 2138 "orientation", 2139 "origin", 2140 "overflow", 2141 "paint-order", 2142 "path", 2143 "pathlength", 2144 "patterncontentunits", 2145 "patterntransform", 2146 "patternunits", 2147 "pointer-events", 2148 "points", 2149 "preservealpha", 2150 "preserveaspectratio", 2151 "primitiveunits", 2152 "r", 2153 "rx", 2154 "ry", 2155 "radius", 2156 "refx", 2157 "refy", 2158 "repeatcount", 2159 "repeatdur", 2160 "restart", 2161 "result", 2162 "rotate", 2163 "scale", 2164 "seed", 2165 "shape-rendering", 2166 "slope", 2167 "specularconstant", 2168 "specularexponent", 2169 "spreadmethod", 2170 "startoffset", 2171 "stddeviation", 2172 "stitchtiles", 2173 "stop-color", 2174 "stop-opacity", 2175 "stroke-dasharray", 2176 "stroke-dashoffset", 2177 "stroke-linecap", 2178 "stroke-linejoin", 2179 "stroke-miterlimit", 2180 "stroke-opacity", 2181 "stroke", 2182 "stroke-width", 2183 "style", 2184 "surfacescale", 2185 "systemlanguage", 2186 "tabindex", 2187 "tablevalues", 2188 "targetx", 2189 "targety", 2190 "transform", 2191 "transform-origin", 2192 "text-anchor", 2193 "text-decoration", 2194 "text-orientation", 2195 "text-rendering", 2196 "textlength", 2197 "type", 2198 "u1", 2199 "u2", 2200 "unicode", 2201 "values", 2202 "vector-effect", 2203 "viewbox", 2204 "visibility", 2205 "version", 2206 "vert-adv-y", 2207 "vert-origin-x", 2208 "vert-origin-y", 2209 "width", 2210 "word-spacing", 2211 "wrap", 2212 "writing-mode", 2213 "xchannelselector", 2214 "ychannelselector", 2215 "x", 2216 "x1", 2217 "x2", 2218 "xmlns", 2219 "y", 2220 "y1", 2221 "y2", 2222 "z", 2223 "zoomandpan" 2224 ]); 2225 mathMl = freeze([ 2226 "accent", 2227 "accentunder", 2228 "align", 2229 "bevelled", 2230 "close", 2231 "columnalign", 2232 "columnlines", 2233 "columnspacing", 2234 "columnspan", 2235 "denomalign", 2236 "depth", 2237 "dir", 2238 "display", 2239 "displaystyle", 2240 "encoding", 2241 "fence", 2242 "frame",
2243 "height", 2244 "href", 2245 "id", 2246 "largeop", 2247 "length", 2248 "linethickness", 2249 "lquote", 2250 "lspace", 2251 "mathbackground", 2252 "mathcolor", 2253 "mathsize", 2254 "mathvariant", 2255 "maxsize", 2256 "minsize", 2257 "movablelimits", 2258 "notation", 2259 "numalign", 2260 "open", 2261 "rowalign", 2262 "rowlines", 2263 "rowspacing", 2264 "rowspan", 2265 "rspace", 2266 "rquote", 2267 "scriptlevel", 2268 "scriptminsize", 2269 "scriptsizemultiplier", 2270 "selection", 2271 "separator", 2272 "separators", 2273 "stretchy", 2274 "subscriptshift", 2275 "supscriptshift", 2276 "symmetric", 2277 "voffset", 2278 "width", 2279 "xmlns" 2280 ]); 2281 xml = freeze([ 2282 "xlink:href", 2283 "xml:id", 2284 "xlink:title", 2285 "xml:space", 2286 "xmlns:xlink" 2287 ]); 2288 MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g); 2289 ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g); 2290 TMPLIT_EXPR = seal(/\${[\w\W]*/g); 2291 DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); 2292 ARIA_ATTR = seal(/^aria-[\-\w]+$/); 2293 IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i); 2294 IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); 2295 ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g); 2296 DOCTYPE_NAME = seal(/^html$/i); 2297 CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); 2298 ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g); 2299 COMMENT_MARKUP_PROBE = seal(/<[/\w]/g); 2300 FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i); 2301 SELF_CLOSING_TAG = seal(/\/>/i); 2302 NODE_TYPE = { 2303 element: 1, 2304 attribute: 2, 2305 text: 3, 2306 cdataSection: 4, 2307 entityReference: 5, 2308 entityNode: 6, 2309 processingInstruction: 7, 2310 comment: 8, 2311 document: 9, 2312 documentType: 10, 2313 documentFragment: 11, 2314 notation: 12 2315 }; 2316 LITERAL_TEXT_ELEMENT_NAMES = [ 2317 "style", 2318 "script", 2319 "xmp", 2320 "iframe", 2321 "noembed", 2322 "noframes", 2323 "plaintext", 2324 "noscript" 2325 ]; 2326 LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES)); 2327 LITERAL_TEXT_CLOSE = function() { 2328 const map = {}; 2329 arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, (name) => { 2330 map[name] = seal(new RegExp("</" + name + "(?=[\\t\\n\\f\\r />])", "i")); 2331 }); 2332 return freeze(map); 2333 }(); 2334 getGlobal = function getGlobal() { 2335 return typeof window === "undefined" ? null : window; 2336 }; 2337 _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) { 2338 if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") return null; 2339 let suffix = null; 2340 const ATTR_NAME = "data-tt-policy-suffix"; 2341 if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) suffix = purifyHostElement.getAttribute(ATTR_NAME); 2342 const policyName = "dompurify" + (suffix ? "#" + suffix : ""); 2343 try { 2344 return trustedTypes.createPolicy(policyName, { 2345 createHTML(html) { 2346 return html; 2347 }, 2348 createScriptURL(scriptUrl) { 2349 return scriptUrl; 2350 } 2351 }); 2352 } catch (_) { 2353 console.warn("TrustedTypes policy " + policyName + " could not be created."); 2354 return null; 2355 } 2356 }; 2357 _createHooksMap = function _createHooksMap() { 2358 return { 2359 afterSanitizeAttributes: [], 2360 afterSanitizeElements: [], 2361 afterSanitizeShadowDOM: [], 2362 beforeSanitizeAttributes: [], 2363 beforeSanitizeElements: [], 2364 beforeSanitizeShadowDOM: [], 2365 uponSanitizeAttribute: [], 2366 uponSanitizeElement: [], 2367 uponSanitizeShadowNode: [] 2368 }; 2369 }; 2370 _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) { 2371 return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback; 2372 }; 2373 _resolveObjectOption = function _resolveObjectOption(cfg, key, makeFallback) { 2374 const value = objectHasOwnProperty(cfg, key) ? cfg[key] : void 0; 2375 return value && typeof value === "object" ? clone(value) : makeFallback(); 2376 }; 2377 purify = createDOMPurify(); 2378 })))(); 2379} 2380//#endregion 2381export { purify as n, init_purify_es as t };
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.