dompurify 2.2.4 → 2.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/dist/purify.cjs.js +210 -34
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +210 -34
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +210 -34
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +1 -1
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -1
package/dist/purify.js
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
var hasOwnProperty = Object.hasOwnProperty,
|
|
12
12
|
setPrototypeOf = Object.setPrototypeOf,
|
|
13
|
-
isFrozen = Object.isFrozen
|
|
13
|
+
isFrozen = Object.isFrozen,
|
|
14
|
+
getPrototypeOf = Object.getPrototypeOf,
|
|
15
|
+
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
14
16
|
var freeze = Object.freeze,
|
|
15
17
|
seal = Object.seal,
|
|
16
18
|
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
@@ -121,18 +123,56 @@
|
|
|
121
123
|
return newObject;
|
|
122
124
|
}
|
|
123
125
|
|
|
126
|
+
/* IE10 doesn't support __lookupGetter__ so lets'
|
|
127
|
+
* simulate it. It also automatically checks
|
|
128
|
+
* if the prop is function or getter and behaves
|
|
129
|
+
* accordingly. */
|
|
130
|
+
function lookupGetter(object, prop) {
|
|
131
|
+
while (object !== null) {
|
|
132
|
+
var desc = getOwnPropertyDescriptor(object, prop);
|
|
133
|
+
if (desc) {
|
|
134
|
+
if (desc.get) {
|
|
135
|
+
return unapply(desc.get);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (typeof desc.value === 'function') {
|
|
139
|
+
return unapply(desc.value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
object = getPrototypeOf(object);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function fallbackValue(element) {
|
|
147
|
+
console.warn('fallback value for', element);
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return fallbackValue;
|
|
152
|
+
}
|
|
153
|
+
|
|
124
154
|
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']);
|
|
125
155
|
|
|
126
156
|
// SVG
|
|
127
|
-
var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', '
|
|
157
|
+
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']);
|
|
128
158
|
|
|
129
159
|
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
130
160
|
|
|
161
|
+
// List of SVG elements that are disallowed by default.
|
|
162
|
+
// We still need to know them so that we can do namespace
|
|
163
|
+
// checks properly in case one wants to add them to
|
|
164
|
+
// allow-list.
|
|
165
|
+
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'feimage', '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']);
|
|
166
|
+
|
|
131
167
|
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']);
|
|
132
168
|
|
|
169
|
+
// Similarly to SVG, we want to know all MathML elements,
|
|
170
|
+
// even those that we disallow by default.
|
|
171
|
+
var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
172
|
+
|
|
133
173
|
var text = freeze(['#text']);
|
|
134
174
|
|
|
135
|
-
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', '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']);
|
|
175
|
+
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', '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']);
|
|
136
176
|
|
|
137
177
|
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']);
|
|
138
178
|
|
|
@@ -209,7 +249,7 @@
|
|
|
209
249
|
* Version label, exposed for easier checks
|
|
210
250
|
* if DOMPurify is up to date or not
|
|
211
251
|
*/
|
|
212
|
-
DOMPurify.version = '2.2.
|
|
252
|
+
DOMPurify.version = '2.2.8';
|
|
213
253
|
|
|
214
254
|
/**
|
|
215
255
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -231,6 +271,7 @@
|
|
|
231
271
|
var DocumentFragment = window.DocumentFragment,
|
|
232
272
|
HTMLTemplateElement = window.HTMLTemplateElement,
|
|
233
273
|
Node = window.Node,
|
|
274
|
+
Element = window.Element,
|
|
234
275
|
NodeFilter = window.NodeFilter,
|
|
235
276
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
236
277
|
NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
@@ -239,13 +280,20 @@
|
|
|
239
280
|
DOMParser = window.DOMParser,
|
|
240
281
|
trustedTypes = window.trustedTypes;
|
|
241
282
|
|
|
283
|
+
|
|
284
|
+
var ElementPrototype = Element.prototype;
|
|
285
|
+
|
|
286
|
+
var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
287
|
+
var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
288
|
+
var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
289
|
+
var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
290
|
+
|
|
242
291
|
// As per issue #47, the web-components registry is inherited by a
|
|
243
292
|
// new document created via createHTMLDocument. As per the spec
|
|
244
293
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
245
294
|
// a new empty registry is used when creating a template contents owner
|
|
246
295
|
// document, so we use that as our parent document to ensure nothing
|
|
247
296
|
// is inherited.
|
|
248
|
-
|
|
249
297
|
if (typeof HTMLTemplateElement === 'function') {
|
|
250
298
|
var template = document.createElement('template');
|
|
251
299
|
if (template.content && template.content.ownerDocument) {
|
|
@@ -259,7 +307,6 @@
|
|
|
259
307
|
var _document = document,
|
|
260
308
|
implementation = _document.implementation,
|
|
261
309
|
createNodeIterator = _document.createNodeIterator,
|
|
262
|
-
getElementsByTagName = _document.getElementsByTagName,
|
|
263
310
|
createDocumentFragment = _document.createDocumentFragment;
|
|
264
311
|
var importNode = originalDocument.importNode;
|
|
265
312
|
|
|
@@ -274,7 +321,7 @@
|
|
|
274
321
|
/**
|
|
275
322
|
* Expose whether this browser supports running the full DOMPurify.
|
|
276
323
|
*/
|
|
277
|
-
DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
324
|
+
DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
278
325
|
|
|
279
326
|
var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
|
|
280
327
|
ERB_EXPR$$1 = ERB_EXPR,
|
|
@@ -367,7 +414,7 @@
|
|
|
367
414
|
var USE_PROFILES = {};
|
|
368
415
|
|
|
369
416
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
370
|
-
var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
417
|
+
var 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']);
|
|
371
418
|
|
|
372
419
|
/* Tags that are safe for data: URIs */
|
|
373
420
|
var DATA_URI_TAGS = null;
|
|
@@ -377,6 +424,12 @@
|
|
|
377
424
|
var URI_SAFE_ATTRIBUTES = null;
|
|
378
425
|
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
379
426
|
|
|
427
|
+
var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
428
|
+
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
429
|
+
var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
430
|
+
/* Document namespace */
|
|
431
|
+
var NAMESPACE = HTML_NAMESPACE;
|
|
432
|
+
|
|
380
433
|
/* Keep a reference to config to pass to hooks */
|
|
381
434
|
var CONFIG = null;
|
|
382
435
|
|
|
@@ -426,6 +479,7 @@
|
|
|
426
479
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
427
480
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
428
481
|
IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
|
|
482
|
+
NAMESPACE = cfg.NAMESPACE || NAMESPACE;
|
|
429
483
|
if (SAFE_FOR_TEMPLATES) {
|
|
430
484
|
ALLOW_DATA_ATTR = false;
|
|
431
485
|
}
|
|
@@ -508,6 +562,111 @@
|
|
|
508
562
|
CONFIG = cfg;
|
|
509
563
|
};
|
|
510
564
|
|
|
565
|
+
var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
566
|
+
|
|
567
|
+
var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);
|
|
568
|
+
|
|
569
|
+
/* Keep track of all possible SVG and MathML tags
|
|
570
|
+
* so that we can perform the namespace checks
|
|
571
|
+
* correctly. */
|
|
572
|
+
var ALL_SVG_TAGS = addToSet({}, svg);
|
|
573
|
+
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
574
|
+
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
575
|
+
|
|
576
|
+
var ALL_MATHML_TAGS = addToSet({}, mathMl);
|
|
577
|
+
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
*
|
|
581
|
+
*
|
|
582
|
+
* @param {Element} element a DOM element whose namespace is being checked
|
|
583
|
+
* @returns {boolean} Return false if the element has a
|
|
584
|
+
* namespace that a spec-compliant parser would never
|
|
585
|
+
* return. Return true otherwise.
|
|
586
|
+
*/
|
|
587
|
+
var _checkValidNamespace = function _checkValidNamespace(element) {
|
|
588
|
+
var parent = getParentNode(element);
|
|
589
|
+
|
|
590
|
+
// In JSDOM, if we're inside shadow DOM, then parentNode
|
|
591
|
+
// can be null. We just simulate parent in this case.
|
|
592
|
+
if (!parent || !parent.tagName) {
|
|
593
|
+
parent = {
|
|
594
|
+
namespaceURI: HTML_NAMESPACE,
|
|
595
|
+
tagName: 'template'
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
var tagName = stringToLowerCase(element.tagName);
|
|
600
|
+
var parentTagName = stringToLowerCase(parent.tagName);
|
|
601
|
+
|
|
602
|
+
if (element.namespaceURI === SVG_NAMESPACE) {
|
|
603
|
+
// The only way to switch from HTML namespace to SVG
|
|
604
|
+
// is via <svg>. If it happens via any other tag, then
|
|
605
|
+
// it should be killed.
|
|
606
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
607
|
+
return tagName === 'svg';
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// The only way to switch from MathML to SVG is via
|
|
611
|
+
// svg if parent is either <annotation-xml> or MathML
|
|
612
|
+
// text integration points.
|
|
613
|
+
if (parent.namespaceURI === MATHML_NAMESPACE) {
|
|
614
|
+
return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// We only allow elements that are defined in SVG
|
|
618
|
+
// spec. All others are disallowed in SVG namespace.
|
|
619
|
+
return Boolean(ALL_SVG_TAGS[tagName]);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (element.namespaceURI === MATHML_NAMESPACE) {
|
|
623
|
+
// The only way to switch from HTML namespace to MathML
|
|
624
|
+
// is via <math>. If it happens via any other tag, then
|
|
625
|
+
// it should be killed.
|
|
626
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
627
|
+
return tagName === 'math';
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// The only way to switch from SVG to MathML is via
|
|
631
|
+
// <math> and HTML integration points
|
|
632
|
+
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
633
|
+
return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// We only allow elements that are defined in MathML
|
|
637
|
+
// spec. All others are disallowed in MathML namespace.
|
|
638
|
+
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (element.namespaceURI === HTML_NAMESPACE) {
|
|
642
|
+
// The only way to switch from SVG to HTML is via
|
|
643
|
+
// HTML integration points, and from MathML to HTML
|
|
644
|
+
// is via MathML text integration points
|
|
645
|
+
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Certain elements are allowed in both SVG and HTML
|
|
654
|
+
// namespace. We need to specify them explicitly
|
|
655
|
+
// so that they don't get erronously deleted from
|
|
656
|
+
// HTML namespace.
|
|
657
|
+
var commonSvgAndHTMLElements = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
658
|
+
|
|
659
|
+
// We disallow tags that are specific for MathML
|
|
660
|
+
// or SVG and should never appear in HTML namespace
|
|
661
|
+
return !ALL_MATHML_TAGS[tagName] && (commonSvgAndHTMLElements[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// The code should never reach this place (this means
|
|
665
|
+
// that the element somehow got namespace that is not
|
|
666
|
+
// HTML, SVG or MathML). Return false just in case.
|
|
667
|
+
return false;
|
|
668
|
+
};
|
|
669
|
+
|
|
511
670
|
/**
|
|
512
671
|
* _forceRemove
|
|
513
672
|
*
|
|
@@ -546,6 +705,19 @@
|
|
|
546
705
|
}
|
|
547
706
|
|
|
548
707
|
node.removeAttribute(name);
|
|
708
|
+
|
|
709
|
+
// We void attribute values for unremovable "is"" attributes
|
|
710
|
+
if (name === 'is' && !ALLOWED_ATTR[name]) {
|
|
711
|
+
if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
|
|
712
|
+
try {
|
|
713
|
+
_forceRemove(node);
|
|
714
|
+
} catch (_) {}
|
|
715
|
+
} else {
|
|
716
|
+
try {
|
|
717
|
+
node.setAttribute(name, '');
|
|
718
|
+
} catch (_) {}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
549
721
|
};
|
|
550
722
|
|
|
551
723
|
/**
|
|
@@ -568,27 +740,30 @@
|
|
|
568
740
|
}
|
|
569
741
|
|
|
570
742
|
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
571
|
-
/*
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
743
|
+
/*
|
|
744
|
+
* Use the DOMParser API by default, fallback later if needs be
|
|
745
|
+
* DOMParser not work for svg when has multiple root element.
|
|
746
|
+
*/
|
|
747
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
748
|
+
try {
|
|
749
|
+
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
750
|
+
} catch (_) {}
|
|
751
|
+
}
|
|
575
752
|
|
|
576
753
|
/* Use createHTMLDocument in case DOMParser is not available */
|
|
577
754
|
if (!doc || !doc.documentElement) {
|
|
578
|
-
doc = implementation.
|
|
579
|
-
|
|
580
|
-
body = _doc.body;
|
|
581
|
-
|
|
582
|
-
body.parentNode.removeChild(body.parentNode.firstElementChild);
|
|
583
|
-
body.outerHTML = dirtyPayload;
|
|
755
|
+
doc = implementation.createDocument(NAMESPACE, 'template', null);
|
|
756
|
+
doc.documentElement.innerHTML = dirtyPayload;
|
|
584
757
|
}
|
|
585
758
|
|
|
759
|
+
var body = doc.body || doc.documentElement;
|
|
760
|
+
|
|
586
761
|
if (dirty && leadingWhitespace) {
|
|
587
|
-
|
|
762
|
+
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
588
763
|
}
|
|
589
764
|
|
|
590
765
|
/* Work on whole document or just its body */
|
|
591
|
-
return
|
|
766
|
+
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
592
767
|
};
|
|
593
768
|
|
|
594
769
|
/**
|
|
@@ -614,7 +789,7 @@
|
|
|
614
789
|
return false;
|
|
615
790
|
}
|
|
616
791
|
|
|
617
|
-
if (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') {
|
|
792
|
+
if (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') {
|
|
618
793
|
return true;
|
|
619
794
|
}
|
|
620
795
|
|
|
@@ -695,29 +870,30 @@
|
|
|
695
870
|
/* Remove element if anything forbids its presence */
|
|
696
871
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
697
872
|
/* Keep content except for bad-listed elements */
|
|
698
|
-
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
|
|
702
|
-
} catch (_) {}
|
|
703
|
-
}
|
|
873
|
+
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
874
|
+
var parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
875
|
+
var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
704
876
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
877
|
+
if (childNodes && parentNode) {
|
|
878
|
+
var childCount = childNodes.length;
|
|
879
|
+
|
|
880
|
+
for (var i = childCount - 1; i >= 0; --i) {
|
|
881
|
+
parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
708
885
|
|
|
709
|
-
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
710
886
|
_forceRemove(currentNode);
|
|
711
887
|
return true;
|
|
712
888
|
}
|
|
713
889
|
|
|
714
|
-
|
|
890
|
+
/* Check whether element has a valid namespace */
|
|
891
|
+
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
|
|
715
892
|
_forceRemove(currentNode);
|
|
716
893
|
return true;
|
|
717
894
|
}
|
|
718
895
|
|
|
719
|
-
|
|
720
|
-
if (tagName === 'svg' && currentNode.querySelectorAll('p, br, table, form, noscript').length > 0) {
|
|
896
|
+
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
721
897
|
_forceRemove(currentNode);
|
|
722
898
|
return true;
|
|
723
899
|
}
|