2023-02-21 16:24:34 +08:00
( window [ "webpackJsonp" ] = window [ "webpackJsonp" ] || [ ] ) . push ( [ [ 24 ] , {
/***/ "qZ2Q" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . / node _modules / html2pdf . js / node _modules / dompurify / dist / purify . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/*! no static exports found */
/*! all exports used */
/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/*! @license DOMPurify 2.3.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.4/LICENSE */
( function ( global , factory ) {
true ? module . exports = factory ( ) :
undefined ;
} ( this , function ( ) { 'use strict' ;
function _toConsumableArray ( arr ) { if ( Array . isArray ( arr ) ) { for ( var i = 0 , arr2 = Array ( arr . length ) ; i < arr . length ; i ++ ) { arr2 [ i ] = arr [ i ] ; } return arr2 ; } else { return Array . from ( arr ) ; } }
var hasOwnProperty = Object . hasOwnProperty ,
setPrototypeOf = Object . setPrototypeOf ,
isFrozen = Object . isFrozen ,
getPrototypeOf = Object . getPrototypeOf ,
getOwnPropertyDescriptor = Object . getOwnPropertyDescriptor ;
var freeze = Object . freeze ,
seal = Object . seal ,
create = Object . create ; // eslint-disable-line import/no-mutable-exports
var _ref = typeof Reflect !== 'undefined' && Reflect ,
apply = _ref . apply ,
construct = _ref . construct ;
if ( ! apply ) {
apply = function apply ( fun , thisValue , args ) {
return fun . apply ( thisValue , args ) ;
} ;
}
if ( ! freeze ) {
freeze = function freeze ( x ) {
return x ;
} ;
}
if ( ! seal ) {
seal = function seal ( x ) {
return x ;
} ;
}
if ( ! construct ) {
construct = function construct ( Func , args ) {
return new ( Function . prototype . bind . apply ( Func , [ null ] . concat ( _toConsumableArray ( args ) ) ) ) ( ) ;
} ;
}
var arrayForEach = unapply ( Array . prototype . forEach ) ;
var arrayPop = unapply ( Array . prototype . pop ) ;
var arrayPush = unapply ( Array . prototype . push ) ;
var stringToLowerCase = unapply ( String . prototype . toLowerCase ) ;
var stringMatch = unapply ( String . prototype . match ) ;
var stringReplace = unapply ( String . prototype . replace ) ;
var stringIndexOf = unapply ( String . prototype . indexOf ) ;
var stringTrim = unapply ( String . prototype . trim ) ;
var regExpTest = unapply ( RegExp . prototype . test ) ;
var typeErrorCreate = unconstruct ( TypeError ) ;
function unapply ( func ) {
return function ( thisArg ) {
for ( var _len = arguments . length , args = Array ( _len > 1 ? _len - 1 : 0 ) , _key = 1 ; _key < _len ; _key ++ ) {
args [ _key - 1 ] = arguments [ _key ] ;
}
return apply ( func , thisArg , args ) ;
} ;
}
function unconstruct ( func ) {
return function ( ) {
for ( var _len2 = arguments . length , args = Array ( _len2 ) , _key2 = 0 ; _key2 < _len2 ; _key2 ++ ) {
args [ _key2 ] = arguments [ _key2 ] ;
}
return construct ( func , args ) ;
} ;
}
/* Add properties to a lookup table */
function addToSet ( set , array ) {
if ( setPrototypeOf ) {
// Make 'in' and truthy checks like Boolean(set.constructor)
// independent of any properties defined on Object.prototype.
// Prevent prototype setters from intercepting set as a this value.
setPrototypeOf ( set , null ) ;
}
var l = array . length ;
while ( l -- ) {
var element = array [ l ] ;
if ( typeof element === 'string' ) {
var lcElement = stringToLowerCase ( element ) ;
if ( lcElement !== element ) {
// Config presets (e.g. tags.js, attrs.js) are immutable.
if ( ! isFrozen ( array ) ) {
array [ l ] = lcElement ;
}
element = lcElement ;
}
}
set [ element ] = true ;
}
return set ;
}
/* Shallow clone an object */
function clone ( object ) {
var newObject = create ( null ) ;
var property = void 0 ;
for ( property in object ) {
if ( apply ( hasOwnProperty , object , [ property ] ) ) {
newObject [ property ] = object [ property ] ;
}
}
return newObject ;
}
/ * I E 1 0 d o e s n ' t s u p p o r t _ _ l o o k u p G e t t e r _ _ s o l e t s '
* simulate it . It also automatically checks
* if the prop is function or getter and behaves
* accordingly . * /
function lookupGetter ( object , prop ) {
while ( object !== null ) {
var desc = getOwnPropertyDescriptor ( object , prop ) ;
if ( desc ) {
if ( desc . get ) {
return unapply ( desc . get ) ;
}
if ( typeof desc . value === 'function' ) {
return unapply ( desc . value ) ;
}
}
object = getPrototypeOf ( object ) ;
}
function fallbackValue ( element ) {
console . warn ( 'fallback value for' , element ) ;
return null ;
}
return fallbackValue ;
}
var html = freeze ( [ 'a' , 'abbr' , 'acronym' , 'address' , 'area' , 'article' , 'aside' , 'audio' , 'b' , 'bdi' , 'bdo' , 'big' , 'blink' , 'blockquote' , 'body' , 'br' , 'button' , 'canvas' , 'caption' , 'center' , 'cite' , 'code' , 'col' , 'colgroup' , 'content' , 'data' , 'datalist' , 'dd' , 'decorator' , 'del' , 'details' , 'dfn' , 'dialog' , 'dir' , 'div' , 'dl' , 'dt' , 'element' , 'em' , 'fieldset' , 'figcaption' , 'figure' , 'font' , 'footer' , 'form' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'head' , 'header' , 'hgroup' , 'hr' , 'html' , 'i' , 'img' , 'input' , 'ins' , 'kbd' , 'label' , 'legend' , 'li' , 'main' , 'map' , 'mark' , 'marquee' , 'menu' , 'menuitem' , 'meter' , 'nav' , 'nobr' , 'ol' , 'optgroup' , 'option' , 'output' , 'p' , 'picture' , 'pre' , 'progress' , 'q' , 'rp' , 'rt' , 'ruby' , 's' , 'samp' , 'section' , 'select' , 'shadow' , 'small' , 'source' , 'spacer' , 'span' , 'strike' , 'strong' , 'style' , 'sub' , 'summary' , 'sup' , 'table' , 'tbody' , 'td' , 'template' , 'textarea' , 'tfoot' , 'th' , 'thead' , 'time' , 'tr' , 'track' , 'tt' , 'u' , 'ul' , 'var' , 'video' , 'wbr' ] ) ;
// SVG
var svg = freeze ( [ 'svg' , 'a' , 'altglyph' , 'altglyphdef' , 'altglyphitem' , 'animatecolor' , 'animatemotion' , 'animatetransform' , 'circle' , 'clippath' , 'defs' , 'desc' , 'ellipse' , 'filter' , 'font' , 'g' , 'glyph' , 'glyphref' , 'hkern' , 'image' , 'line' , 'lineargradient' , 'marker' , 'mask' , 'metadata' , 'mpath' , 'path' , 'pattern' , 'polygon' , 'polyline' , 'radialgradient' , 'rect' , 'stop' , 'style' , 'switch' , 'symbol' , 'text' , 'textpath' , 'title' , 'tref' , 'tspan' , 'view' , 'vkern' ] ) ;
var svgFilters = freeze ( [ 'feBlend' , 'feColorMatrix' , 'feComponentTransfer' , 'feComposite' , 'feConvolveMatrix' , 'feDiffuseLighting' , 'feDisplacementMap' , 'feDistantLight' , 'feFlood' , 'feFuncA' , 'feFuncB' , 'feFuncG' , 'feFuncR' , 'feGaussianBlur' , 'feImage' , 'feMerge' , 'feMergeNode' , 'feMorphology' , 'feOffset' , 'fePointLight' , 'feSpecularLighting' , 'feSpotLight' , 'feTile' , 'feTurbulence' ] ) ;
// List of SVG elements that are disallowed by default.
// We still need to know them so that we can do namespace
// checks properly in case one wants to add them to
// allow-list.
var svgDisallowed = freeze ( [ 'animate' , 'color-profile' , 'cursor' , 'discard' , 'fedropshadow' , 'font-face' , 'font-face-format' , 'font-face-name' , 'font-face-src' , 'font-face-uri' , 'foreignobject' , 'hatch' , 'hatchpath' , 'mesh' , 'meshgradient' , 'meshpatch' , 'meshrow' , 'missing-glyph' , 'script' , 'set' , 'solidcolor' , 'unknown' , 'use' ] ) ;
var mathMl = freeze ( [ 'math' , 'menclose' , 'merror' , 'mfenced' , 'mfrac' , 'mglyph' , 'mi' , 'mlabeledtr' , 'mmultiscripts' , 'mn' , 'mo' , 'mover' , 'mpadded' , 'mphantom' , 'mroot' , 'mrow' , 'ms' , 'mspace' , 'msqrt' , 'mstyle' , 'msub' , 'msup' , 'msubsup' , 'mtable' , 'mtd' , 'mtext' , 'mtr' , 'munder' , 'munderover' ] ) ;
// Similarly to SVG, we want to know all MathML elements,
// even those that we disallow by default.
var mathMlDisallowed = freeze ( [ 'maction' , 'maligngroup' , 'malignmark' , 'mlongdiv' , 'mscarries' , 'mscarry' , 'msgroup' , 'mstack' , 'msline' , 'msrow' , 'semantics' , 'annotation' , 'annotation-xml' , 'mprescripts' , 'none' ] ) ;
var text = freeze ( [ '#text' ] ) ;
var html$1 = freeze ( [ 'accept' , 'action' , 'align' , 'alt' , 'autocapitalize' , 'autocomplete' , 'autopictureinpicture' , 'autoplay' , 'background' , 'bgcolor' , 'border' , 'capture' , 'cellpadding' , 'cellspacing' , 'checked' , 'cite' , 'class' , 'clear' , 'color' , 'cols' , 'colspan' , 'controls' , 'controlslist' , 'coords' , 'crossorigin' , 'datetime' , 'decoding' , 'default' , 'dir' , 'disabled' , 'disablepictureinpicture' , 'disableremoteplayback' , 'download' , 'draggable' , 'enctype' , 'enterkeyhint' , 'face' , 'for' , 'headers' , 'height' , 'hidden' , 'high' , 'href' , 'hreflang' , 'id' , 'inputmode' , 'integrity' , 'ismap' , 'kind' , 'label' , 'lang' , 'list' , 'loading' , 'loop' , 'low' , 'max' , 'maxlength' , 'media' , 'method' , 'min' , 'minlength' , 'multiple' , 'muted' , 'name' , 'nonce' , 'noshade' , 'novalidate' , 'nowrap' , 'open' , 'optimum' , 'pattern' , 'placeholder' , 'playsinline' , 'poster' , 'preload' , 'pubdate' , 'radiogroup' , 'readonly' , 'rel' , 'required' , 'rev' , 'reversed' , 'role' , 'rows' , 'rowspan' , 'spellcheck' , 'scope' , 'selected' , 'shape' , 'size' , 'sizes' , 'span' , 'srclang' , 'start' , 'src' , 'srcset' , 'step' , 'style' , 'summary' , 'tabindex' , 'title' , 'translate' , 'type' , 'usemap' , 'valign' , 'value' , 'width' , 'xmlns' , 'slot' ] ) ;
var svg$1 = freeze ( [ 'accent-height' , 'accumulate' , 'additive' , 'alignment-baseline' , 'ascent' , 'attributename' , 'attributetype' , 'azimuth' , 'basefrequency' , 'baseline-shift' , 'begin' , 'bias' , 'by' , 'class' , 'clip' , 'clippathunits' , 'clip-path' , 'clip-rule' , 'color' , 'color-interpolation' , 'color-interpolation-filters' , 'color-profile' , 'color-rendering' , 'cx' , 'cy' , 'd' , 'dx' , 'dy' , 'diffuseconstant' , 'direction' , 'display' , 'divisor' , 'dur' , 'edgemode' , 'elevation' , 'end' , 'fill' , 'fill-opacity' , 'fill-rule' , 'filter' , 'filterunits' , 'flood-color' , 'flood-opacity' , 'font-family' , 'font-size' , 'font-size-adjust' , 'font-stretch' , 'font-style' , 'font-variant' , 'font-weight' , 'fx' , 'fy' , 'g1' , 'g2' , 'glyph-name' , 'glyphref' , 'gradientunits' , 'gradienttransform' , 'height' , 'href' , 'id' , 'image-rendering' , 'in' , 'in2' , 'k' , 'k1' , 'k2' , 'k3' , 'k4' , 'kerning' , 'keypoints' , 'keysplines' , 'keytimes' , 'lang' , 'lengthadjust' , 'letter-spacing' , 'kernelmatrix' , 'kernelunitlength' , 'lighting-color' , 'local' , 'marker-end' , 'marker-mid' , 'marker-start' , 'markerheight' , 'markerunits' , 'markerwidth' , 'maskcontentunits' , 'maskunits' , 'max' , 'mask' , 'media' , 'method' , 'mode' , 'min' , 'name' , 'numoctaves' , 'offset' , 'operator' , 'opacity' , 'order' , 'orient' , 'orientation' , 'origin' , 'overflow' , 'paint-order' , 'path' , 'pathlength' , 'patterncontentunits' , 'patterntransform' , 'patternunits' , 'points' , 'preservealpha' , 'preserveaspectratio' , 'primitiveunits' , 'r' , 'rx' , 'ry' , 'radius' , 'refx' , 'refy' , 'repeatcount' , 'repeatdur' , 'restart' , 'result' , 'rotate' , 'scale' , 'seed' , 'shape-rendering' , 'specularconstant' , 'specularexponent' , 'spreadmethod' , 'startoffset' , 'stddeviation' , 'stitchtiles' , 'stop-color' , 'stop-opacity' , 'stroke-dasharray' , 'stroke-dashoffset' , 'stroke-linecap' , 'stroke-linejoin' , 'stroke-miterlimit' , 'stroke-opacity' , 'stroke' , 'stroke-width' , 'style' , 'surfacescale' , 'systemlanguage' , 'tabindex' , 'targetx' , 'targety' , 'transform' , 'text-anchor' , 'text-decoration' , 'text-rendering' , 'textlength' , 'type' , 'u1' , 'u2' , 'unicode' , 'values' , 'viewbox' , 'visibility' , 'version' , 'vert-adv-y' , 'vert-origin-x' , 'vert-origin-y' , 'width' , 'word-spacing' , 'wrap' , 'writing-mode' , 'xchannelselector' , 'ychannelselector' , 'x' , 'x1' , 'x2' , 'xmlns' , 'y' , 'y1' , 'y2' , 'z' , 'zoomandpan' ] ) ;
var mathMl$1 = freeze ( [ 'accent' , 'accentunder' , 'align' , 'bevelled' , 'close' , 'columnsalign' , 'columnlines' , 'columnspan' , 'denomalign' , 'depth' , 'dir' , 'display' , 'displaystyle' , 'encoding' , 'fence' , 'frame' , 'height' , 'href' , 'id' , 'largeop' , 'length' , 'linethickness' , 'lspace' , 'lquote' , 'mathbackground' , 'mathcolor' , 'mathsize' , 'mathvariant' , 'maxsize' , 'minsize' , 'movablelimits' , 'notation' , 'numalign' , 'open' , 'rowalign' , 'rowlines' , 'rowspacing' , 'rowspan' , 'rspace' , 'rquote' , 'scriptlevel' , 'scriptminsize' , 'scriptsizemultiplier' , 'selection' , 'separator' , 'separators' , 'stretchy' , 'subscriptshift' , 'supscriptshift' , 'symmetric' , 'voffset' , 'width' , 'xmlns' ] ) ;
var xml = freeze ( [ 'xlink:href' , 'xml:id' , 'xlink:title' , 'xml:space' , 'xmlns:xlink' ] ) ;
// eslint-disable-next-line unicorn/better-regex
var MUSTACHE _EXPR = seal ( /\{\{[\s\S]*|[\s\S]*\}\}/gm ) ; // Specify template detection regex for SAFE_FOR_TEMPLATES mode
var ERB _EXPR = seal ( /<%[\s\S]*|[\s\S]*%>/gm ) ;
var DATA _ATTR = seal ( /^data-[\-\w.\u00B7-\uFFFF]/ ) ; // eslint-disable-line no-useless-escape
var ARIA _ATTR = seal ( /^aria-[\-\w]+$/ ) ; // eslint-disable-line no-useless-escape
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
) ;
var IS _SCRIPT _OR _DATA = seal ( /^(?:\w+script|data):/i ) ;
var ATTR _WHITESPACE = seal ( /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
) ;
var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ;
function _toConsumableArray$1 ( arr ) { if ( Array . isArray ( arr ) ) { for ( var i = 0 , arr2 = Array ( arr . length ) ; i < arr . length ; i ++ ) { arr2 [ i ] = arr [ i ] ; } return arr2 ; } else { return Array . from ( arr ) ; } }
var getGlobal = function getGlobal ( ) {
return typeof window === 'undefined' ? null : window ;
} ;
/ * *
* Creates a no - op policy for internal use only .
* Don ' t export this function outside this module !
* @ param { ? TrustedTypePolicyFactory } trustedTypes The policy factory .
* @ param { Document } document The document object ( to determine policy name suffix )
* @ return { ? TrustedTypePolicy } The policy created ( or null , if Trusted Types
* are not supported ) .
* /
var _createTrustedTypesPolicy = function _createTrustedTypesPolicy ( trustedTypes , document ) {
if ( ( typeof trustedTypes === 'undefined' ? 'undefined' : _typeof ( trustedTypes ) ) !== 'object' || typeof trustedTypes . createPolicy !== 'function' ) {
return null ;
}
// Allow the callers to control the unique policy name
// by adding a data-tt-policy-suffix to the script element with the DOMPurify.
// Policy creation with duplicate names throws in Trusted Types.
var suffix = null ;
var ATTR _NAME = 'data-tt-policy-suffix' ;
if ( document . currentScript && document . currentScript . hasAttribute ( ATTR _NAME ) ) {
suffix = document . currentScript . getAttribute ( ATTR _NAME ) ;
}
var policyName = 'dompurify' + ( suffix ? '#' + suffix : '' ) ;
try {
return trustedTypes . createPolicy ( policyName , {
createHTML : function createHTML ( html$$1 ) {
return html$$1 ;
}
} ) ;
} catch ( _ ) {
// Policy creation failed (most likely another DOMPurify script has
// already run). Skip creating the policy, as this will only cause errors
// if TT are enforced.
console . warn ( 'TrustedTypes policy ' + policyName + ' could not be created.' ) ;
return null ;
}
} ;
function createDOMPurify ( ) {
var window = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : getGlobal ( ) ;
var DOMPurify = function DOMPurify ( root ) {
return createDOMPurify ( root ) ;
} ;
/ * *
* Version label , exposed for easier checks
* if DOMPurify is up to date or not
* /
DOMPurify . version = '2.3.4' ;
/ * *
* Array of elements that DOMPurify removed during sanitation .
* Empty if nothing was removed .
* /
DOMPurify . removed = [ ] ;
if ( ! window || ! window . document || window . document . nodeType !== 9 ) {
// Not running in a browser, provide a factory function
// so that you can pass your own Window
DOMPurify . isSupported = false ;
return DOMPurify ;
}
var originalDocument = window . document ;
var document = window . document ;
var DocumentFragment = window . DocumentFragment ,
HTMLTemplateElement = window . HTMLTemplateElement ,
Node = window . Node ,
Element = window . Element ,
NodeFilter = window . NodeFilter ,
_window$NamedNodeMap = window . NamedNodeMap ,
NamedNodeMap = _window$NamedNodeMap === undefined ? window . NamedNodeMap || window . MozNamedAttrMap : _window$NamedNodeMap ,
HTMLFormElement = window . HTMLFormElement ,
DOMParser = window . DOMParser ,
trustedTypes = window . trustedTypes ;
var ElementPrototype = Element . prototype ;
var cloneNode = lookupGetter ( ElementPrototype , 'cloneNode' ) ;
var getNextSibling = lookupGetter ( ElementPrototype , 'nextSibling' ) ;
var getChildNodes = lookupGetter ( ElementPrototype , 'childNodes' ) ;
var getParentNode = lookupGetter ( ElementPrototype , 'parentNode' ) ;
// As per issue #47, the web-components registry is inherited by a
// new document created via createHTMLDocument. As per the spec
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
// a new empty registry is used when creating a template contents owner
// document, so we use that as our parent document to ensure nothing
// is inherited.
if ( typeof HTMLTemplateElement === 'function' ) {
var template = document . createElement ( 'template' ) ;
if ( template . content && template . content . ownerDocument ) {
document = template . content . ownerDocument ;
}
}
var trustedTypesPolicy = _createTrustedTypesPolicy ( trustedTypes , originalDocument ) ;
var emptyHTML = trustedTypesPolicy && RETURN _TRUSTED _TYPE ? trustedTypesPolicy . createHTML ( '' ) : '' ;
var _document = document ,
implementation = _document . implementation ,
createNodeIterator = _document . createNodeIterator ,
createDocumentFragment = _document . createDocumentFragment ,
getElementsByTagName = _document . getElementsByTagName ;
var importNode = originalDocument . importNode ;
var documentMode = { } ;
try {
documentMode = clone ( document ) . documentMode ? document . documentMode : { } ;
} catch ( _ ) { }
var hooks = { } ;
/ * *
* Expose whether this browser supports running the full DOMPurify .
* /
DOMPurify . isSupported = typeof getParentNode === 'function' && implementation && typeof implementation . createHTMLDocument !== 'undefined' && documentMode !== 9 ;
var MUSTACHE _EXPR$$1 = MUSTACHE _EXPR ,
ERB _EXPR$$1 = ERB _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 ;
var IS _ALLOWED _URI$$1 = IS _ALLOWED _URI ;
/ * *
* We consider the elements and attributes below to be safe . Ideally
* don ' t add any new ones but feel free to remove unwanted ones .
* /
/* allowed element names */
var ALLOWED _TAGS = null ;
var DEFAULT _ALLOWED _TAGS = addToSet ( { } , [ ] . concat ( _toConsumableArray$1 ( html ) , _toConsumableArray$1 ( svg ) , _toConsumableArray$1 ( svgFilters ) , _toConsumableArray$1 ( mathMl ) , _toConsumableArray$1 ( text ) ) ) ;
/* Allowed attribute names */
var ALLOWED _ATTR = null ;
var DEFAULT _ALLOWED _ATTR = addToSet ( { } , [ ] . concat ( _toConsumableArray$1 ( html$1 ) , _toConsumableArray$1 ( svg$1 ) , _toConsumableArray$1 ( mathMl$1 ) , _toConsumableArray$1 ( xml ) ) ) ;
/ *
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built - in elements .
* @ property { RegExp | Function | null } tagNameCheck one of [ null , regexPattern , predicate ] . Default : ` null ` ( disallow any custom elements )
* @ property { RegExp | Function | null } attributeNameCheck one of [ null , regexPattern , predicate ] . Default : ` null ` ( disallow any attributes not on the allow list )
* @ property { boolean } allowCustomizedBuiltInElements allow custom elements derived from built - ins if they pass CUSTOM _ELEMENT _HANDLING . tagNameCheck . Default : ` false ` .
* /
var CUSTOM _ELEMENT _HANDLING = Object . seal ( Object . create ( null , {
tagNameCheck : {
writable : true ,
configurable : false ,
enumerable : true ,
value : null
} ,
attributeNameCheck : {
writable : true ,
configurable : false ,
enumerable : true ,
value : null
} ,
allowCustomizedBuiltInElements : {
writable : true ,
configurable : false ,
enumerable : true ,
value : false
}
} ) ) ;
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
var FORBID _TAGS = null ;
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
var FORBID _ATTR = null ;
/* Decide if ARIA attributes are okay */
var ALLOW _ARIA _ATTR = true ;
/* Decide if custom data attributes are okay */
var ALLOW _DATA _ATTR = true ;
/* Decide if unknown protocols are okay */
var ALLOW _UNKNOWN _PROTOCOLS = false ;
/ * O u t p u t s h o u l d b e s a f e f o r c o m m o n t e m p l a t e e n g i n e s .
* This means , DOMPurify removes data attributes , mustaches and ERB
* /
var SAFE _FOR _TEMPLATES = false ;
/* Decide if document with <html>... should be returned */
var WHOLE _DOCUMENT = false ;
/* Track whether config is already set on this instance of DOMPurify. */
var SET _CONFIG = false ;
/ * D e c i d e i f a l l e l e m e n t s ( e . g . s t y l e , s c r i p t ) m u s t b e c h i l d r e n o f
* document . body . By default , browsers might move them to document . head * /
var FORCE _BODY = false ;
/ * D e c i d e i f a D O M ` H T M L B o d y E l e m e n t ` s h o u l d b e r e t u r n e d , i n s t e a d o f a h t m l
* string ( or a TrustedHTML object if Trusted Types are supported ) .
* If ` WHOLE_DOCUMENT ` is enabled a ` HTMLHtmlElement ` will be returned instead
* /
var RETURN _DOM = false ;
/ * D e c i d e i f a D O M ` D o c u m e n t F r a g m e n t ` s h o u l d b e r e t u r n e d , i n s t e a d o f a h t m l
* string ( or a TrustedHTML object if Trusted Types are supported ) * /
var RETURN _DOM _FRAGMENT = false ;
/ * T r y t o r e t u r n a T r u s t e d T y p e o b j e c t i n s t e a d o f a s t r i n g , r e t u r n a s t r i n g i n
* case Trusted Types are not supported * /
var RETURN _TRUSTED _TYPE = false ;
/* Output should be free from DOM clobbering attacks? */
var SANITIZE _DOM = true ;
/* Keep element content when removing element? */
var KEEP _CONTENT = true ;
/ * I f a ` N o d e ` i s p a s s e d t o s a n i t i z e ( ) , t h e n p e r f o r m s s a n i t i z a t i o n i n - p l a c e i n s t e a d
* of importing it into a new Document and returning a sanitized copy * /
var IN _PLACE = false ;
/* Allow usage of profiles like html, svg and mathMl */
var USE _PROFILES = { } ;
/* Tags to ignore content of when KEEP_CONTENT is true */
var FORBID _CONTENTS = null ;
var DEFAULT _FORBID _CONTENTS = addToSet ( { } , [ 'annotation-xml' , 'audio' , 'colgroup' , 'desc' , 'foreignobject' , 'head' , 'iframe' , 'math' , 'mi' , 'mn' , 'mo' , 'ms' , 'mtext' , 'noembed' , 'noframes' , 'noscript' , 'plaintext' , 'script' , 'style' , 'svg' , 'template' , 'thead' , 'title' , 'video' , 'xmp' ] ) ;
/* Tags that are safe for data: URIs */
var DATA _URI _TAGS = null ;
var DEFAULT _DATA _URI _TAGS = addToSet ( { } , [ 'audio' , 'video' , 'img' , 'source' , 'image' , 'track' ] ) ;
/* Attributes safe for values like "javascript:" */
var URI _SAFE _ATTRIBUTES = null ;
var DEFAULT _URI _SAFE _ATTRIBUTES = addToSet ( { } , [ 'alt' , 'class' , 'for' , 'id' , 'label' , 'name' , 'pattern' , 'placeholder' , 'role' , 'summary' , 'title' , 'value' , 'style' , 'xmlns' ] ) ;
var MATHML _NAMESPACE = 'http://www.w3.org/1998/Math/MathML' ;
var SVG _NAMESPACE = 'http://www.w3.org/2000/svg' ;
var HTML _NAMESPACE = 'http://www.w3.org/1999/xhtml' ;
/* Document namespace */
var NAMESPACE = HTML _NAMESPACE ;
var IS _EMPTY _INPUT = false ;
/* Parsing of strict XHTML documents */
var PARSER _MEDIA _TYPE = void 0 ;
var SUPPORTED _PARSER _MEDIA _TYPES = [ 'application/xhtml+xml' , 'text/html' ] ;
var DEFAULT _PARSER _MEDIA _TYPE = 'text/html' ;
var transformCaseFunc = void 0 ;
/* Keep a reference to config to pass to hooks */
var CONFIG = null ;
/* Ideally, do not touch anything below this line */
/* ______________________________________________ */
var formElement = document . createElement ( 'form' ) ;
var isRegexOrFunction = function isRegexOrFunction ( testValue ) {
return testValue instanceof RegExp || testValue instanceof Function ;
} ;
/ * *
* _parseConfig
*
* @ param { Object } cfg optional config literal
* /
// eslint-disable-next-line complexity
var _parseConfig = function _parseConfig ( cfg ) {
if ( CONFIG && CONFIG === cfg ) {
return ;
}
/* Shield configuration object from tampering */
if ( ! cfg || ( typeof cfg === 'undefined' ? 'undefined' : _typeof ( cfg ) ) !== 'object' ) {
cfg = { } ;
}
/* Shield configuration object from prototype pollution */
cfg = clone ( cfg ) ;
/* Set configuration parameters */
ALLOWED _TAGS = 'ALLOWED_TAGS' in cfg ? addToSet ( { } , cfg . ALLOWED _TAGS ) : DEFAULT _ALLOWED _TAGS ;
ALLOWED _ATTR = 'ALLOWED_ATTR' in cfg ? addToSet ( { } , cfg . ALLOWED _ATTR ) : DEFAULT _ALLOWED _ATTR ;
URI _SAFE _ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet ( clone ( DEFAULT _URI _SAFE _ATTRIBUTES ) , cfg . ADD _URI _SAFE _ATTR ) : DEFAULT _URI _SAFE _ATTRIBUTES ;
DATA _URI _TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet ( clone ( DEFAULT _DATA _URI _TAGS ) , cfg . ADD _DATA _URI _TAGS ) : DEFAULT _DATA _URI _TAGS ;
FORBID _CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet ( { } , cfg . FORBID _CONTENTS ) : DEFAULT _FORBID _CONTENTS ;
FORBID _TAGS = 'FORBID_TAGS' in cfg ? addToSet ( { } , cfg . FORBID _TAGS ) : { } ;
FORBID _ATTR = 'FORBID_ATTR' in cfg ? addToSet ( { } , cfg . FORBID _ATTR ) : { } ;
USE _PROFILES = 'USE_PROFILES' in cfg ? cfg . USE _PROFILES : false ;
ALLOW _ARIA _ATTR = cfg . ALLOW _ARIA _ATTR !== false ; // Default true
ALLOW _DATA _ATTR = cfg . ALLOW _DATA _ATTR !== false ; // Default true
ALLOW _UNKNOWN _PROTOCOLS = cfg . ALLOW _UNKNOWN _PROTOCOLS || false ; // Default false
SAFE _FOR _TEMPLATES = cfg . SAFE _FOR _TEMPLATES || false ; // Default false
WHOLE _DOCUMENT = cfg . WHOLE _DOCUMENT || false ; // Default false
RETURN _DOM = cfg . RETURN _DOM || false ; // Default false
RETURN _DOM _FRAGMENT = cfg . RETURN _DOM _FRAGMENT || false ; // Default false
RETURN _TRUSTED _TYPE = cfg . RETURN _TRUSTED _TYPE || false ; // Default false
FORCE _BODY = cfg . FORCE _BODY || false ; // Default false
SANITIZE _DOM = cfg . SANITIZE _DOM !== false ; // Default true
KEEP _CONTENT = cfg . KEEP _CONTENT !== false ; // Default true
IN _PLACE = cfg . IN _PLACE || false ; // Default false
IS _ALLOWED _URI$$1 = cfg . ALLOWED _URI _REGEXP || IS _ALLOWED _URI$$1 ;
NAMESPACE = cfg . NAMESPACE || HTML _NAMESPACE ;
if ( cfg . CUSTOM _ELEMENT _HANDLING && isRegexOrFunction ( cfg . CUSTOM _ELEMENT _HANDLING . tagNameCheck ) ) {
CUSTOM _ELEMENT _HANDLING . tagNameCheck = cfg . CUSTOM _ELEMENT _HANDLING . tagNameCheck ;
}
if ( cfg . CUSTOM _ELEMENT _HANDLING && isRegexOrFunction ( cfg . CUSTOM _ELEMENT _HANDLING . attributeNameCheck ) ) {
CUSTOM _ELEMENT _HANDLING . attributeNameCheck = cfg . CUSTOM _ELEMENT _HANDLING . attributeNameCheck ;
}
if ( cfg . CUSTOM _ELEMENT _HANDLING && typeof cfg . CUSTOM _ELEMENT _HANDLING . allowCustomizedBuiltInElements === 'boolean' ) {
CUSTOM _ELEMENT _HANDLING . allowCustomizedBuiltInElements = cfg . CUSTOM _ELEMENT _HANDLING . allowCustomizedBuiltInElements ;
}
PARSER _MEDIA _TYPE =
// eslint-disable-next-line unicorn/prefer-includes
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.
transformCaseFunc = PARSER _MEDIA _TYPE === 'application/xhtml+xml' ? function ( x ) {
return x ;
} : stringToLowerCase ;
if ( SAFE _FOR _TEMPLATES ) {
ALLOW _DATA _ATTR = false ;
}
if ( RETURN _DOM _FRAGMENT ) {
RETURN _DOM = true ;
}
/* Parse profile info */
if ( USE _PROFILES ) {
ALLOWED _TAGS = addToSet ( { } , [ ] . concat ( _toConsumableArray$1 ( text ) ) ) ;
ALLOWED _ATTR = [ ] ;
if ( USE _PROFILES . html === true ) {
addToSet ( ALLOWED _TAGS , html ) ;
addToSet ( ALLOWED _ATTR , html$1 ) ;
}
if ( USE _PROFILES . svg === true ) {
addToSet ( ALLOWED _TAGS , svg ) ;
addToSet ( ALLOWED _ATTR , svg$1 ) ;
addToSet ( ALLOWED _ATTR , xml ) ;
}
if ( USE _PROFILES . svgFilters === true ) {
addToSet ( ALLOWED _TAGS , svgFilters ) ;
addToSet ( ALLOWED _ATTR , svg$1 ) ;
addToSet ( ALLOWED _ATTR , xml ) ;
}
if ( USE _PROFILES . mathMl === true ) {
addToSet ( ALLOWED _TAGS , mathMl ) ;
addToSet ( ALLOWED _ATTR , mathMl$1 ) ;
addToSet ( ALLOWED _ATTR , xml ) ;
}
}
/* Merge configuration parameters */
if ( cfg . ADD _TAGS ) {
if ( ALLOWED _TAGS === DEFAULT _ALLOWED _TAGS ) {
ALLOWED _TAGS = clone ( ALLOWED _TAGS ) ;
}
addToSet ( ALLOWED _TAGS , cfg . ADD _TAGS ) ;
}
if ( cfg . ADD _ATTR ) {
if ( ALLOWED _ATTR === DEFAULT _ALLOWED _ATTR ) {
ALLOWED _ATTR = clone ( ALLOWED _ATTR ) ;
}
addToSet ( ALLOWED _ATTR , cfg . ADD _ATTR ) ;
}
if ( cfg . ADD _URI _SAFE _ATTR ) {
addToSet ( URI _SAFE _ATTRIBUTES , cfg . ADD _URI _SAFE _ATTR ) ;
}
if ( cfg . FORBID _CONTENTS ) {
if ( FORBID _CONTENTS === DEFAULT _FORBID _CONTENTS ) {
FORBID _CONTENTS = clone ( FORBID _CONTENTS ) ;
}
addToSet ( FORBID _CONTENTS , cfg . FORBID _CONTENTS ) ;
}
/* Add #text in case KEEP_CONTENT is set to true */
if ( KEEP _CONTENT ) {
ALLOWED _TAGS [ '#text' ] = true ;
}
/* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
if ( WHOLE _DOCUMENT ) {
addToSet ( ALLOWED _TAGS , [ 'html' , 'head' , 'body' ] ) ;
}
/* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
if ( ALLOWED _TAGS . table ) {
addToSet ( ALLOWED _TAGS , [ 'tbody' ] ) ;
delete FORBID _TAGS . tbody ;
}
// Prevent further manipulation of configuration.
// Not available in IE8, Safari 5, etc.
if ( freeze ) {
freeze ( cfg ) ;
}
CONFIG = cfg ;
} ;
var MATHML _TEXT _INTEGRATION _POINTS = addToSet ( { } , [ 'mi' , 'mo' , 'mn' , 'ms' , 'mtext' ] ) ;
var HTML _INTEGRATION _POINTS = addToSet ( { } , [ 'foreignobject' , 'desc' , 'title' , 'annotation-xml' ] ) ;
/ * K e e p t r a c k o f a l l p o s s i b l e S V G a n d M a t h M L t a g s
* so that we can perform the namespace checks
* correctly . * /
var ALL _SVG _TAGS = addToSet ( { } , svg ) ;
addToSet ( ALL _SVG _TAGS , svgFilters ) ;
addToSet ( ALL _SVG _TAGS , svgDisallowed ) ;
var ALL _MATHML _TAGS = addToSet ( { } , mathMl ) ;
addToSet ( ALL _MATHML _TAGS , mathMlDisallowed ) ;
/ * *
*
*
* @ param { Element } element a DOM element whose namespace is being checked
* @ returns { boolean } Return false if the element has a
* namespace that a spec - compliant parser would never
* return . Return true otherwise .
* /
var _checkValidNamespace = function _checkValidNamespace ( element ) {
var parent = getParentNode ( element ) ;
// In JSDOM, if we're inside shadow DOM, then parentNode
// can be null. We just simulate parent in this case.
if ( ! parent || ! parent . tagName ) {
parent = {
namespaceURI : HTML _NAMESPACE ,
tagName : 'template'
} ;
}
var tagName = stringToLowerCase ( element . tagName ) ;
var parentTagName = stringToLowerCase ( parent . tagName ) ;
if ( element . namespaceURI === SVG _NAMESPACE ) {
// The only way to switch from HTML namespace to SVG
// is via <svg>. If it happens via any other tag, then
// it should be killed.
if ( parent . namespaceURI === HTML _NAMESPACE ) {
return tagName === 'svg' ;
}
// The only way to switch from MathML to SVG is via
// svg if parent is either <annotation-xml> or MathML
// text integration points.
if ( parent . namespaceURI === MATHML _NAMESPACE ) {
return tagName === 'svg' && ( parentTagName === 'annotation-xml' || MATHML _TEXT _INTEGRATION _POINTS [ parentTagName ] ) ;
}
// We only allow elements that are defined in SVG
// spec. All others are disallowed in SVG namespace.
return Boolean ( ALL _SVG _TAGS [ tagName ] ) ;
}
if ( element . namespaceURI === MATHML _NAMESPACE ) {
// The only way to switch from HTML namespace to MathML
// is via <math>. If it happens via any other tag, then
// it should be killed.
if ( parent . namespaceURI === HTML _NAMESPACE ) {
return tagName === 'math' ;
}
// The only way to switch from SVG to MathML is via
// <math> and HTML integration points
if ( parent . namespaceURI === SVG _NAMESPACE ) {
return tagName === 'math' && HTML _INTEGRATION _POINTS [ parentTagName ] ;
}
// We only allow elements that are defined in MathML
// spec. All others are disallowed in MathML namespace.
return Boolean ( ALL _MATHML _TAGS [ tagName ] ) ;
}
if ( element . namespaceURI === HTML _NAMESPACE ) {
// The only way to switch from SVG to HTML is via
// HTML integration points, and from MathML to HTML
// is via MathML text integration points
if ( parent . namespaceURI === SVG _NAMESPACE && ! HTML _INTEGRATION _POINTS [ parentTagName ] ) {
return false ;
}
if ( parent . namespaceURI === MATHML _NAMESPACE && ! MATHML _TEXT _INTEGRATION _POINTS [ parentTagName ] ) {
return false ;
}
// Certain elements are allowed in both SVG and HTML
// namespace. We need to specify them explicitly
// so that they don't get erronously deleted from
// HTML namespace.
var commonSvgAndHTMLElements = addToSet ( { } , [ 'title' , 'style' , 'font' , 'a' , 'script' ] ) ;
// We disallow tags that are specific for MathML
// or SVG and should never appear in HTML namespace
return ! ALL _MATHML _TAGS [ tagName ] && ( commonSvgAndHTMLElements [ tagName ] || ! ALL _SVG _TAGS [ tagName ] ) ;
}
// The code should never reach this place (this means
// that the element somehow got namespace that is not
// HTML, SVG or MathML). Return false just in case.
return false ;
} ;
/ * *
* _forceRemove
*
* @ param { Node } node a DOM node
* /
var _forceRemove = function _forceRemove ( node ) {
arrayPush ( DOMPurify . removed , { element : node } ) ;
try {
// eslint-disable-next-line unicorn/prefer-dom-node-remove
node . parentNode . removeChild ( node ) ;
} catch ( _ ) {
try {
node . outerHTML = emptyHTML ;
} catch ( _ ) {
node . remove ( ) ;
}
}
} ;
/ * *
* _removeAttribute
*
* @ param { String } name an Attribute name
* @ param { Node } node a DOM node
* /
var _removeAttribute = function _removeAttribute ( name , node ) {
try {
arrayPush ( DOMPurify . removed , {
attribute : node . getAttributeNode ( name ) ,
from : node
} ) ;
} catch ( _ ) {
arrayPush ( DOMPurify . removed , {
attribute : null ,
from : node
} ) ;
}
node . removeAttribute ( name ) ;
// We void attribute values for unremovable "is"" attributes
if ( name === 'is' && ! ALLOWED _ATTR [ name ] ) {
if ( RETURN _DOM || RETURN _DOM _FRAGMENT ) {
try {
_forceRemove ( node ) ;
} catch ( _ ) { }
} else {
try {
node . setAttribute ( name , '' ) ;
} catch ( _ ) { }
}
}
} ;
/ * *
* _initDocument
*
* @ param { String } dirty a string of dirty markup
* @ return { Document } a DOM , filled with the dirty markup
* /
var _initDocument = function _initDocument ( dirty ) {
/* Create a HTML document */
var doc = void 0 ;
var leadingWhitespace = void 0 ;
if ( FORCE _BODY ) {
dirty = '<remove></remove>' + dirty ;
} else {
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
var matches = stringMatch ( dirty , /^[\r\n\t ]+/ ) ;
leadingWhitespace = matches && matches [ 0 ] ;
}
if ( PARSER _MEDIA _TYPE === 'application/xhtml+xml' ) {
// Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>' ;
}
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy . createHTML ( dirty ) : dirty ;
/ *
* Use the DOMParser API by default , fallback later if needs be
* DOMParser not work for svg when has multiple root element .
* /
if ( NAMESPACE === HTML _NAMESPACE ) {
try {
doc = new DOMParser ( ) . parseFromString ( dirtyPayload , PARSER _MEDIA _TYPE ) ;
} catch ( _ ) { }
}
/* Use createHTMLDocument in case DOMParser is not available */
if ( ! doc || ! doc . documentElement ) {
doc = implementation . createDocument ( NAMESPACE , 'template' , null ) ;
try {
doc . documentElement . innerHTML = IS _EMPTY _INPUT ? '' : dirtyPayload ;
} catch ( _ ) {
// Syntax error if dirtyPayload is invalid xml
}
}
var body = doc . body || doc . documentElement ;
if ( dirty && leadingWhitespace ) {
body . insertBefore ( document . createTextNode ( leadingWhitespace ) , body . childNodes [ 0 ] || null ) ;
}
/* Work on whole document or just its body */
if ( NAMESPACE === HTML _NAMESPACE ) {
return getElementsByTagName . call ( doc , WHOLE _DOCUMENT ? 'html' : 'body' ) [ 0 ] ;
}
return WHOLE _DOCUMENT ? doc . documentElement : body ;
} ;
/ * *
* _createIterator
*
* @ param { Document } root document / fragment to create iterator for
* @ return { Iterator } iterator instance
* /
var _createIterator = function _createIterator ( root ) {
return createNodeIterator . call ( root . ownerDocument || root , root , NodeFilter . SHOW _ELEMENT | NodeFilter . SHOW _COMMENT | NodeFilter . SHOW _TEXT , null , false ) ;
} ;
/ * *
* _isClobbered
*
* @ param { Node } elm element to check for clobbering attacks
* @ return { Boolean } true if clobbered , false if safe
* /
var _isClobbered = function _isClobbered ( elm ) {
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' ) ;
} ;
/ * *
* _isNode
*
* @ param { Node } obj object to check whether it ' s a DOM node
* @ return { Boolean } true is object is a DOM node
* /
var _isNode = function _isNode ( object ) {
return ( typeof Node === 'undefined' ? 'undefined' : _typeof ( Node ) ) === 'object' ? object instanceof Node : object && ( typeof object === 'undefined' ? 'undefined' : _typeof ( object ) ) === 'object' && typeof object . nodeType === 'number' && typeof object . nodeName === 'string' ;
} ;
/ * *
* _executeHook
* Execute user configurable hooks
*
* @ param { String } entryPoint Name of the hook ' s entry point
* @ param { Node } currentNode node to work on with the hook
* @ param { Object } data additional hook parameters
* /
var _executeHook = function _executeHook ( entryPoint , currentNode , data ) {
if ( ! hooks [ entryPoint ] ) {
return ;
}
arrayForEach ( hooks [ entryPoint ] , function ( hook ) {
hook . call ( DOMPurify , currentNode , data , CONFIG ) ;
} ) ;
} ;
/ * *
* _sanitizeElements
*
* @ protect nodeName
* @ protect textContent
* @ protect removeChild
*
* @ param { Node } currentNode to check for permission to exist
* @ return { Boolean } true if node was killed , false if left alive
* /
var _sanitizeElements = function _sanitizeElements ( currentNode ) {
var content = void 0 ;
/* Execute a hook if present */
_executeHook ( 'beforeSanitizeElements' , currentNode , null ) ;
/* Check if element is clobbered or can clobber */
if ( _isClobbered ( currentNode ) ) {
_forceRemove ( currentNode ) ;
return true ;
}
/* Check if tagname contains Unicode */
if ( stringMatch ( currentNode . nodeName , /[\u0080-\uFFFF]/ ) ) {
_forceRemove ( currentNode ) ;
return true ;
}
/* Now let's check the element's type and name */
var tagName = transformCaseFunc ( currentNode . nodeName ) ;
/* Execute a hook if present */
_executeHook ( 'uponSanitizeElement' , currentNode , {
tagName : tagName ,
allowedTags : ALLOWED _TAGS
} ) ;
/* Detect mXSS attempts abusing namespace confusion */
if ( ! _isNode ( currentNode . firstElementChild ) && ( ! _isNode ( currentNode . content ) || ! _isNode ( currentNode . content . firstElementChild ) ) && regExpTest ( /<[/\w]/g , currentNode . innerHTML ) && regExpTest ( /<[/\w]/g , currentNode . textContent ) ) {
_forceRemove ( currentNode ) ;
return true ;
}
/* Mitigate a problem with templates inside select */
if ( tagName === 'select' && regExpTest ( /<template/i , currentNode . innerHTML ) ) {
_forceRemove ( currentNode ) ;
return true ;
}
/* Remove element if anything forbids its presence */
if ( ! ALLOWED _TAGS [ tagName ] || FORBID _TAGS [ tagName ] ) {
/* Keep content except for bad-listed elements */
if ( KEEP _CONTENT && ! FORBID _CONTENTS [ tagName ] ) {
var parentNode = getParentNode ( currentNode ) || currentNode . parentNode ;
var childNodes = getChildNodes ( currentNode ) || currentNode . childNodes ;
if ( childNodes && parentNode ) {
var childCount = childNodes . length ;
for ( var i = childCount - 1 ; i >= 0 ; -- i ) {
parentNode . insertBefore ( cloneNode ( childNodes [ i ] , true ) , getNextSibling ( currentNode ) ) ;
}
}
}
if ( ! FORBID _TAGS [ tagName ] && _basicCustomElementTest ( tagName ) ) {
if ( CUSTOM _ELEMENT _HANDLING . tagNameCheck instanceof RegExp && regExpTest ( CUSTOM _ELEMENT _HANDLING . tagNameCheck , tagName ) ) return false ;
if ( CUSTOM _ELEMENT _HANDLING . tagNameCheck instanceof Function && CUSTOM _ELEMENT _HANDLING . tagNameCheck ( tagName ) ) return false ;
}
_forceRemove ( currentNode ) ;
return true ;
}
/* Check whether element has a valid namespace */
if ( currentNode instanceof Element && ! _checkValidNamespace ( currentNode ) ) {
_forceRemove ( currentNode ) ;
return true ;
}
if ( ( tagName === 'noscript' || tagName === 'noembed' ) && regExpTest ( /<\/no(script|embed)/i , currentNode . innerHTML ) ) {
_forceRemove ( currentNode ) ;
return true ;
}
/* Sanitize element content to be template-safe */
if ( SAFE _FOR _TEMPLATES && currentNode . nodeType === 3 ) {
/* Get the element's text content */
content = currentNode . textContent ;
content = stringReplace ( content , MUSTACHE _EXPR$$1 , ' ' ) ;
content = stringReplace ( content , ERB _EXPR$$1 , ' ' ) ;
if ( currentNode . textContent !== content ) {
arrayPush ( DOMPurify . removed , { element : currentNode . cloneNode ( ) } ) ;
currentNode . textContent = content ;
}
}
/* Execute a hook if present */
_executeHook ( 'afterSanitizeElements' , currentNode , null ) ;
return false ;
} ;
/ * *
* _isValidAttribute
*
* @ param { string } lcTag Lowercase tag name of containing element .
* @ param { string } lcName Lowercase attribute name .
* @ param { string } value Attribute value .
* @ return { Boolean } Returns true if ` value ` is valid , otherwise false .
* /
// eslint-disable-next-line complexity
var _isValidAttribute = function _isValidAttribute ( lcTag , lcName , value ) {
/* Make sure attribute cannot clobber */
if ( SANITIZE _DOM && ( lcName === 'id' || lcName === 'name' ) && ( value in document || value in formElement ) ) {
return false ;
}
/ * A l l o w v a l i d d a t a - * a t t r i b u t e s : A t l e a s t o n e c h a r a c t e r a f t e r " - "
( https : //html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
XML - compatible ( https : //html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
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 ) ) ; else if ( ALLOW _ARIA _ATTR && regExpTest ( ARIA _ATTR$$1 , lcName ) ) ; else if ( ! ALLOWED _ATTR [ lcName ] || FORBID _ATTR [ lcName ] ) {
if (
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
_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 ) ) ||
// Alternative, second condition checks if it's an `is`-attribute, AND
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
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 ) ) ) ; else {
return false ;
}
/* Check value is safe. First, is attr inert? If so, is safe */
} else if ( URI _SAFE _ATTRIBUTES [ lcName ] ) ; else if ( regExpTest ( IS _ALLOWED _URI$$1 , stringReplace ( value , ATTR _WHITESPACE$$1 , '' ) ) ) ; else if ( ( lcName === 'src' || lcName === 'xlink:href' || lcName === 'href' ) && lcTag !== 'script' && stringIndexOf ( value , 'data:' ) === 0 && DATA _URI _TAGS [ lcTag ] ) ; else if ( ALLOW _UNKNOWN _PROTOCOLS && ! regExpTest ( IS _SCRIPT _OR _DATA$$1 , stringReplace ( value , ATTR _WHITESPACE$$1 , '' ) ) ) ; else if ( ! value ) ; else {
return false ;
}
return true ;
} ;
/ * *
* _basicCustomElementCheck
* checks if at least one dash is included in tagName , and it ' s not the first char
* for more sophisticated checking see https : //github.com/sindresorhus/validate-element-name
* @ param { string } tagName name of the tag of the node to sanitize
* /
var _basicCustomElementTest = function _basicCustomElementTest ( tagName ) {
return tagName . indexOf ( '-' ) > 0 ;
} ;
/ * *
* _sanitizeAttributes
*
* @ protect attributes
* @ protect nodeName
* @ protect removeAttribute
* @ protect setAttribute
*
* @ param { Node } currentNode to sanitize
* /
var _sanitizeAttributes = function _sanitizeAttributes ( currentNode ) {
var attr = void 0 ;
var value = void 0 ;
var lcName = void 0 ;
var l = void 0 ;
/* Execute a hook if present */
_executeHook ( 'beforeSanitizeAttributes' , currentNode , null ) ;
var attributes = currentNode . attributes ;
/* Check if we have attributes; if not we might have a text node */
if ( ! attributes ) {
return ;
}
var hookEvent = {
attrName : '' ,
attrValue : '' ,
keepAttr : true ,
allowedAttributes : ALLOWED _ATTR
} ;
l = attributes . length ;
/* Go backwards over all attributes; safely remove bad ones */
while ( l -- ) {
attr = attributes [ l ] ;
var _attr = attr ,
name = _attr . name ,
namespaceURI = _attr . namespaceURI ;
value = stringTrim ( attr . value ) ;
lcName = transformCaseFunc ( name ) ;
/* Execute a hook if present */
hookEvent . attrName = lcName ;
hookEvent . attrValue = value ;
hookEvent . keepAttr = true ;
hookEvent . forceKeepAttr = undefined ; // Allows developers to see this is a property they can set
_executeHook ( 'uponSanitizeAttribute' , currentNode , hookEvent ) ;
value = hookEvent . attrValue ;
/* Did the hooks approve of the attribute? */
if ( hookEvent . forceKeepAttr ) {
continue ;
}
/* Remove attribute */
_removeAttribute ( name , currentNode ) ;
/* Did the hooks approve of the attribute? */
if ( ! hookEvent . keepAttr ) {
continue ;
}
/* Work around a security issue in jQuery 3.0 */
if ( regExpTest ( /\/>/i , value ) ) {
_removeAttribute ( name , currentNode ) ;
continue ;
}
/* Sanitize attribute content to be template-safe */
if ( SAFE _FOR _TEMPLATES ) {
value = stringReplace ( value , MUSTACHE _EXPR$$1 , ' ' ) ;
value = stringReplace ( value , ERB _EXPR$$1 , ' ' ) ;
}
/* Is `value` valid for this attribute? */
var lcTag = transformCaseFunc ( currentNode . nodeName ) ;
if ( ! _isValidAttribute ( lcTag , lcName , value ) ) {
continue ;
}
/* Handle invalid data-* attribute set by try-catching it */
try {
if ( namespaceURI ) {
currentNode . setAttributeNS ( namespaceURI , name , value ) ;
} else {
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
currentNode . setAttribute ( name , value ) ;
}
arrayPop ( DOMPurify . removed ) ;
} catch ( _ ) { }
}
/* Execute a hook if present */
_executeHook ( 'afterSanitizeAttributes' , currentNode , null ) ;
} ;
/ * *
* _sanitizeShadowDOM
*
* @ param { DocumentFragment } fragment to iterate over recursively
* /
var _sanitizeShadowDOM = function _sanitizeShadowDOM ( fragment ) {
var shadowNode = void 0 ;
var shadowIterator = _createIterator ( fragment ) ;
/* Execute a hook if present */
_executeHook ( 'beforeSanitizeShadowDOM' , fragment , null ) ;
while ( shadowNode = shadowIterator . nextNode ( ) ) {
/* Execute a hook if present */
_executeHook ( 'uponSanitizeShadowNode' , shadowNode , null ) ;
/* Sanitize tags and elements */
if ( _sanitizeElements ( shadowNode ) ) {
continue ;
}
/* Deep shadow DOM detected */
if ( shadowNode . content instanceof DocumentFragment ) {
_sanitizeShadowDOM ( shadowNode . content ) ;
}
/* Check attributes, sanitize if necessary */
_sanitizeAttributes ( shadowNode ) ;
}
/* Execute a hook if present */
_executeHook ( 'afterSanitizeShadowDOM' , fragment , null ) ;
} ;
/ * *
* Sanitize
* Public method providing core sanitation functionality
*
* @ param { String | Node } dirty string or DOM node
* @ param { Object } configuration object
* /
// eslint-disable-next-line complexity
DOMPurify . sanitize = function ( dirty , cfg ) {
var body = void 0 ;
var importedNode = void 0 ;
var currentNode = void 0 ;
var oldNode = void 0 ;
var returnNode = void 0 ;
/ * M a k e s u r e w e h a v e a s t r i n g t o s a n i t i z e .
DO NOT return early , as this will return the wrong type if
the user has requested a DOM object rather than a string * /
IS _EMPTY _INPUT = ! dirty ;
if ( IS _EMPTY _INPUT ) {
dirty = '<!-->' ;
}
/* Stringify, in case dirty is an object */
if ( typeof dirty !== 'string' && ! _isNode ( dirty ) ) {
// eslint-disable-next-line no-negated-condition
if ( typeof dirty . toString !== 'function' ) {
throw typeErrorCreate ( 'toString is not a function' ) ;
} else {
dirty = dirty . toString ( ) ;
if ( typeof dirty !== 'string' ) {
throw typeErrorCreate ( 'dirty is not a string, aborting' ) ;
}
}
}
/* Check we can run. Otherwise fall back or ignore */
if ( ! DOMPurify . isSupported ) {
if ( _typeof ( window . toStaticHTML ) === 'object' || typeof window . toStaticHTML === 'function' ) {
if ( typeof dirty === 'string' ) {
return window . toStaticHTML ( dirty ) ;
}
if ( _isNode ( dirty ) ) {
return window . toStaticHTML ( dirty . outerHTML ) ;
}
}
return dirty ;
}
/* Assign config vars */
if ( ! SET _CONFIG ) {
_parseConfig ( cfg ) ;
}
/* Clean up removed elements */
DOMPurify . removed = [ ] ;
/* Check if dirty is correctly typed for IN_PLACE */
if ( typeof dirty === 'string' ) {
IN _PLACE = false ;
}
if ( IN _PLACE ) ; else if ( dirty instanceof Node ) {
/ * I f d i r t y i s a D O M e l e m e n t , a p p e n d t o a n e m p t y d o c u m e n t t o a v o i d
elements being stripped by the parser * /
body = _initDocument ( '<!---->' ) ;
importedNode = body . ownerDocument . importNode ( dirty , true ) ;
if ( importedNode . nodeType === 1 && importedNode . nodeName === 'BODY' ) {
/* Node is already a body, use as is */
body = importedNode ;
} else if ( importedNode . nodeName === 'HTML' ) {
body = importedNode ;
} else {
// eslint-disable-next-line unicorn/prefer-dom-node-append
body . appendChild ( importedNode ) ;
}
} else {
/* Exit directly if we have nothing to do */
if ( ! RETURN _DOM && ! SAFE _FOR _TEMPLATES && ! WHOLE _DOCUMENT &&
// eslint-disable-next-line unicorn/prefer-includes
dirty . indexOf ( '<' ) === - 1 ) {
return trustedTypesPolicy && RETURN _TRUSTED _TYPE ? trustedTypesPolicy . createHTML ( dirty ) : dirty ;
}
/* Initialize the document to work on */
body = _initDocument ( dirty ) ;
/* Check we have a DOM node from the data */
if ( ! body ) {
return RETURN _DOM ? null : emptyHTML ;
}
}
/* Remove first element node (ours) if FORCE_BODY is set */
if ( body && FORCE _BODY ) {
_forceRemove ( body . firstChild ) ;
}
/* Get node iterator */
var nodeIterator = _createIterator ( IN _PLACE ? dirty : body ) ;
/* Now start iterating over the created document */
while ( currentNode = nodeIterator . nextNode ( ) ) {
/* Fix IE's strange behavior with manipulated textNodes #89 */
if ( currentNode . nodeType === 3 && currentNode === oldNode ) {
continue ;
}
/* Sanitize tags and elements */
if ( _sanitizeElements ( currentNode ) ) {
continue ;
}
/* Shadow DOM detected, sanitize it */
if ( currentNode . content instanceof DocumentFragment ) {
_sanitizeShadowDOM ( currentNode . content ) ;
}
/* Check attributes, sanitize if necessary */
_sanitizeAttributes ( currentNode ) ;
oldNode = currentNode ;
}
oldNode = null ;
/* If we sanitized `dirty` in-place, return it. */
if ( IN _PLACE ) {
return dirty ;
}
/* Return sanitized string or DOM */
if ( RETURN _DOM ) {
if ( RETURN _DOM _FRAGMENT ) {
returnNode = createDocumentFragment . call ( body . ownerDocument ) ;
while ( body . firstChild ) {
// eslint-disable-next-line unicorn/prefer-dom-node-append
returnNode . appendChild ( body . firstChild ) ;
}
} else {
returnNode = body ;
}
if ( ALLOWED _ATTR . shadowroot ) {
/ *
AdoptNode ( ) is not used because internal state is not reset
( e . g . the past names map of a HTMLFormElement ) , this is safe
in theory but we would rather not risk another attack vector .
The state that is cloned by importNode ( ) is explicitly defined
by the specs .
* /
returnNode = importNode . call ( originalDocument , returnNode , true ) ;
}
return returnNode ;
}
var serializedHTML = WHOLE _DOCUMENT ? body . outerHTML : body . innerHTML ;
/* Sanitize final string template-safe */
if ( SAFE _FOR _TEMPLATES ) {
serializedHTML = stringReplace ( serializedHTML , MUSTACHE _EXPR$$1 , ' ' ) ;
serializedHTML = stringReplace ( serializedHTML , ERB _EXPR$$1 , ' ' ) ;
}
return trustedTypesPolicy && RETURN _TRUSTED _TYPE ? trustedTypesPolicy . createHTML ( serializedHTML ) : serializedHTML ;
} ;
/ * *
* Public method to set the configuration once
* setConfig
*
* @ param { Object } cfg configuration object
* /
DOMPurify . setConfig = function ( cfg ) {
_parseConfig ( cfg ) ;
SET _CONFIG = true ;
} ;
/ * *
* Public method to remove the configuration
* clearConfig
*
* /
DOMPurify . clearConfig = function ( ) {
CONFIG = null ;
SET _CONFIG = false ;
} ;
/ * *
* Public method to check if an attribute value is valid .
* Uses last set config , if any . Otherwise , uses config defaults .
* isValidAttribute
*
* @ param { string } tag Tag name of containing element .
* @ param { string } attr Attribute name .
* @ param { string } value Attribute value .
* @ return { Boolean } Returns true if ` value ` is valid . Otherwise , returns false .
* /
DOMPurify . isValidAttribute = function ( tag , attr , value ) {
/* Initialize shared config vars if necessary. */
if ( ! CONFIG ) {
_parseConfig ( { } ) ;
}
var lcTag = transformCaseFunc ( tag ) ;
var lcName = transformCaseFunc ( attr ) ;
return _isValidAttribute ( lcTag , lcName , value ) ;
} ;
/ * *
* AddHook
* Public method to add DOMPurify hooks
*
* @ param { String } entryPoint entry point for the hook to add
* @ param { Function } hookFunction function to execute
* /
DOMPurify . addHook = function ( entryPoint , hookFunction ) {
if ( typeof hookFunction !== 'function' ) {
return ;
}
hooks [ entryPoint ] = hooks [ entryPoint ] || [ ] ;
arrayPush ( hooks [ entryPoint ] , hookFunction ) ;
} ;
/ * *
* RemoveHook
* Public method to remove a DOMPurify hook at a given entryPoint
* ( pops it from the stack of hooks if more are present )
*
* @ param { String } entryPoint entry point for the hook to remove
* /
DOMPurify . removeHook = function ( entryPoint ) {
if ( hooks [ entryPoint ] ) {
arrayPop ( hooks [ entryPoint ] ) ;
}
} ;
/ * *
* RemoveHooks
* Public method to remove all DOMPurify hooks at a given entryPoint
*
* @ param { String } entryPoint entry point for the hooks to remove
* /
DOMPurify . removeHooks = function ( entryPoint ) {
if ( hooks [ entryPoint ] ) {
hooks [ entryPoint ] = [ ] ;
}
} ;
/ * *
* RemoveAllHooks
* Public method to remove all DOMPurify hooks
*
* /
DOMPurify . removeAllHooks = function ( ) {
hooks = { } ;
} ;
return DOMPurify ;
}
var purify = createDOMPurify ( ) ;
return purify ;
} ) ) ;
//# sourceMappingURL=purify.js.map
/***/ } )
} ] ) ;