11/* BOF */
2+ ;
23DOMPurify = { } ;
34DOMPurify . sanitize = function ( a ) {
45 /******* /***************************************************************
@@ -10,68 +11,63 @@ DOMPurify.sanitize = function(a){
1011 * /
1112 /* allowed element names */
1213 var ALLOWED_TAGS = [
14+
1315 // HTML
14- 'a' , 'abbr' , 'acronym' , 'address' , 'area' , 'article' ,
15- 'aside' , 'audio' , 'b' , 'bdi' , 'bdo' , 'big' , 'blink' ,
16- 'blockquote' , 'body' , 'br' , 'button' , 'canvas' , 'caption' ,
17- 'center' , 'cite' , 'code' , 'col' , 'colgroup' , 'content' , 'data' ,
18- 'datalist' , 'dd' , 'decorator' , 'del' , 'details' , 'dfn' , 'dir' ,
19- 'div' , 'dl' , 'dt' , 'element' , 'em' , 'fieldset' ,
20- 'figcaption' , 'figure' , 'font' , 'footer' , 'form' , 'h1' , 'h2' , 'h3' ,
21- 'h4' , 'h5' , 'h6' , 'header' , 'hgroup' , 'hr' , 'html' , 'i' ,
22- 'img' , 'input' , 'ins' , 'kbd' , 'label' , 'legend' , 'li' , 'main' , 'map' ,
23- 'mark' , 'marquee' , 'menu' , 'menuitem' , 'meter' , 'nav' ,
24- 'nobr' , 'ol' , 'optgroup' , 'option' , 'output' , 'p' , 'pre' ,
25- 'progress' , 'q' , 'rp' , 'rt' , 'ruby' , 's' , 'samp' , 'section' , 'select' ,
26- 'shadow' , 'small' , 'source' , 'spacer' , 'span' , 'strike' , 'strong' , 'style' ,
27- 'sub' , 'summary' , 'sup' , 'table' , 'tbody' , 'td' , 'template' , 'textarea' ,
28- 'tfoot' , 'th' , 'thead' , 'time' , 'tr' , 'track' , 'tt' , 'u' ,
29- 'ul' , 'var' , 'video' , 'wbr' ,
16+ 'a' , 'abbr' , 'acronym' , 'address' , 'area' , 'article' , 'aside' , 'audio' , 'b' ,
17+ 'bdi' , 'bdo' , 'big' , 'blink' , 'blockquote' , 'body' , 'br' , 'button' , 'canvas' ,
18+ 'caption' , 'center' , 'cite' , 'code' , 'col' , 'colgroup' , 'content' , 'data' ,
19+ 'datalist' , 'dd' , 'decorator' , 'del' , 'details' , 'dfn' , 'dir' , 'div' , 'dl' , 'dt' ,
20+ 'element' , 'em' , 'fieldset' , 'figcaption' , 'figure' , 'font' , 'footer' , 'form' ,
21+ 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'header' , 'hgroup' , 'hr' , 'html' , 'i' , 'img' ,
22+ 'input' , 'ins' , 'kbd' , 'label' , 'legend' , 'li' , 'main' , 'map' , 'mark' , 'marquee' ,
23+ 'menu' , 'menuitem' , 'meter' , 'nav' , 'nobr' , 'ol' , 'optgroup' , 'option' , 'output'
24+ , 'p' , 'pre' , 'progress' , 'q' , 'rp' , 'rt' , 'ruby' , 's' , 'samp' , 'section' ,
25+ 'select' , 'shadow' , 'small' , 'source' , 'spacer' , 'span' , 'strike' , 'strong' ,
26+ 'style' , 'sub' , 'summary' , 'sup' , 'table' , 'tbody' , 'td' , 'template' ,
27+ 'textarea' , 'tfoot' , 'th' , 'thead' , 'time' , 'tr' , 'track' , 'tt' , 'u' , 'ul' , 'var' ,
28+ 'video' , 'wbr' ,
3029
3130 // SVG
3231 'svg' , 'altglyph' , 'altglyphdef' , 'altglyphitem' , 'animatecolor' ,
33- 'animatemotion' , 'animatetransform' , 'circle' , 'clippath' , 'defs' ,
34- 'desc' , 'ellipse' , 'font' , 'g' , 'glyph' , 'glyphref' , 'hkern' , 'image' ,
35- 'line' , 'lineargradient' , 'marker' , 'mask' , 'metadata' ,
36- 'mpath' , 'path' , 'pattern' , 'polygon' , 'polyline' , 'radialgradient' ,
37- 'rect' , 'stop' , 'switch' , 'symbol' , 'text' , 'textpath' , 'title' ,
38- 'tref' , 'tspan' , 'view' , 'vkern' ,
32+ 'animatemotion' , 'animatetransform' , 'circle' , 'clippath' , 'defs' , 'desc' ,
33+ 'ellipse' , 'font' , 'g' , 'glyph' , 'glyphref' , 'hkern' , 'image' , 'line' ,
34+ 'lineargradient' , 'marker' , 'mask' , 'metadata' , 'mpath' , 'path' , 'pattern' ,
35+ 'polygon' , 'polyline' , 'radialgradient' , 'rect' , 'stop' , 'switch' , 'symbol' ,
36+ 'text' , 'textpath' , 'title' , 'tref' , 'tspan' , 'view' , 'vkern' ,
3937
4038 //MathML
4139 'math' , 'menclose' , 'merror' , 'mfenced' , 'mfrac' , 'mglyph' , 'mi' , 'mlabeledtr' ,
4240 'mmuliscripts' , 'mn' , 'mo' , 'mover' , 'mpadded' , 'mphantom' , 'mroot' , 'mrow' ,
43- 'ms' , 'mpspace' , 'msqrt' , 'mystyle' , 'msub' , 'msup' , 'msubsup' , 'mtable' ,
44- 'mtd' , ' mtext', 'mtr' , 'munder' , 'munderover'
41+ 'ms' , 'mpspace' , 'msqrt' , 'mystyle' , 'msub' , 'msup' , 'msubsup' , 'mtable' , 'mtd' ,
42+ 'mtext' , 'mtr' , 'munder' , 'munderover'
4543 ] ;
4644
47- /* decide if custom data attributes are okay */
45+ /* Decide if custom data attributes are okay */
4846 var ALLOW_DATA_ATTRIBUTES = true ;
4947
50- /* allowed attribute names */
48+ /* Output should be safe for jQuery's $() factory? */
49+ var SAFE_FOR_JQUERY = true ;
50+
51+ /* Allowed attribute names */
5152 var ALLOWED_ATTR = [
53+
5254 //HTML
53- 'name' , 'id' , 'href' , 'action' , 'class' , 'title' ,
54- 'alt' , 'src' , 'type' , 'height' , 'width' , 'method' , 'rev' , 'rel' ,
55- 'accept' , 'align' , 'autocomplete' , 'xmlns' ,
56- 'bgcolor' , 'border' , 'checked' , 'cite' , 'color' , 'cols' ,
57- 'colspan' , 'coords' , 'datetime' , 'default' , 'dir' ,
58- 'disabled' , 'download' , 'enctype' , 'for' , 'headers' ,
59- 'hidden' , 'high' , 'hreflang' , 'ismap' , 'label' , 'lang' ,
60- 'list' , 'loop' , 'low' , 'max' , 'maxlength' , 'media' , 'min' ,
61- 'multiple' , 'novalidate' , 'open' , 'optimum' , 'pattern' ,
62- 'placeholder' , 'poster' , 'preload' , 'pubdate' , 'radiogroup' ,
63- 'readonly' , 'required' , 'reversed' , 'rows' , 'rowspan' ,
64- 'spellcheck' , 'scope' , 'selected' , 'shape' , 'size' ,
65- 'span' , 'srclang' , 'start' , 'step' , 'style' , 'summary' ,
66- 'tabindex' , 'usemap' , 'value' ,
55+ 'name' , 'id' , 'href' , 'action' , 'class' , 'title' , 'alt' , 'src' , 'type' ,
56+ 'height' , 'width' , 'method' , 'rev' , 'rel' , 'accept' , 'align' , 'autocomplete' ,
57+ 'xmlns' , 'bgcolor' , 'border' , 'checked' , 'cite' , 'color' , 'cols' , 'colspan' ,
58+ 'coords' , 'datetime' , 'default' , 'dir' , 'disabled' , 'download' , 'enctype' ,
59+ 'for' , 'headers' , 'hidden' , 'high' , 'hreflang' , 'ismap' , 'label' , 'lang' ,
60+ 'list' , 'loop' , 'low' , 'max' , 'maxlength' , 'media' , 'min' , 'multiple' ,
61+ 'novalidate' , 'open' , 'optimum' , 'pattern' , 'placeholder' , 'poster' ,
62+ 'preload' , 'pubdate' , 'radiogroup' , 'readonly' , 'required' , 'reversed' ,
63+ 'rows' , 'rowspan' , 'spellcheck' , 'scope' , 'selected' , 'shape' , 'size' , 'span' ,
64+ 'srclang' , 'start' , 'step' , 'style' , 'summary' , 'tabindex' , 'usemap' , 'value' ,
6765
6866 //SVG
69- 'wrap' , 'clip' , 'cx' , 'cy' ,
70- 'd' , 'dy' , 'dy' , 'in' , 'in2' , 'k1' , 'k2' , 'k3' , 'k4' , 'mask' , 'mode' ,
71- 'opacity' , 'order' , 'overflow' , 'path' , 'points' , 'radius' ,
72- 'rx' , 'ry' , 'scale' , 'stroke' , 'stroke-width' , 'transform' ,
73- 'u1' , 'u2' , 'r' , 'x' , 'y' , 'x1' , 'viewbox' ,
74- 'x2' , 'y1' , 'y2' , 'z' , 'fill' ,
67+ 'wrap' , 'clip' , 'cx' , 'cy' , 'd' , 'dy' , 'dy' , 'in' , 'in2' , 'k1' , 'k2' , 'k3' , 'k4' ,
68+ 'mask' , 'mode' , 'opacity' , 'order' , 'overflow' , 'path' , 'points' , 'radius' ,
69+ 'rx' , 'ry' , 'scale' , 'stroke' , 'stroke-width' , 'transform' , 'u1' , 'u2' , 'r' , 'x' ,
70+ 'y' , 'x1' , 'viewbox' , 'x2' , 'y1' , 'y2' , 'z' , 'fill' ,
7571
7672 //MathML
7773 'accent' , 'accentunder' , 'bevelled' , 'close' , 'columnsalign' , 'columnlines' ,
@@ -109,6 +105,7 @@ DOMPurify.sanitize = function(a){
109105 var _isClobbered = function ( elm ) {
110106 if ( ( elm . children && ! ( elm . children instanceof HTMLCollection ) )
111107 || typeof elm . nodeName !== 'string'
108+ || typeof elm . textContent !== 'string'
112109 || typeof elm . nodeType !== 'number'
113110 || typeof elm . setAttribute !== 'function'
114111 || typeof elm . removeAttributeNode !== 'function'
@@ -124,6 +121,8 @@ DOMPurify.sanitize = function(a){
124121 * @protect removeChild
125122 * @protect nodeType
126123 * @protect nodeName
124+ * @protect children
125+ * @protect textContent
127126 * @protect currentNode
128127 *
129128 * @param node to check for permission to exist
@@ -136,6 +135,10 @@ DOMPurify.sanitize = function(a){
136135 currentNode . parentNode . removeChild ( currentNode ) ;
137136 return true ;
138137 }
138+ if ( SAFE_FOR_JQUERY && currentNode . children . length === 0 ) {
139+ currentNode . textContent
140+ = currentNode . textContent . replace ( / \/ + > / g, '>' ) ;
141+ }
139142 return false ;
140143 }
141144
0 commit comments