dompurify 3.0.4 → 3.0.6
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/LICENSE +201 -11
- package/README.md +64 -71
- package/dist/purify.cjs.js +115 -75
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +115 -75
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +115 -75
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -1
package/dist/purify.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.0.
|
|
1
|
+
/*! @license DOMPurify 3.0.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.6/LICENSE */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -20,12 +20,6 @@ let {
|
|
|
20
20
|
construct
|
|
21
21
|
} = typeof Reflect !== 'undefined' && Reflect;
|
|
22
22
|
|
|
23
|
-
if (!apply) {
|
|
24
|
-
apply = function apply(fun, thisValue, args) {
|
|
25
|
-
return fun.apply(thisValue, args);
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
23
|
if (!freeze) {
|
|
30
24
|
freeze = function freeze(x) {
|
|
31
25
|
return x;
|
|
@@ -38,6 +32,12 @@ if (!seal) {
|
|
|
38
32
|
};
|
|
39
33
|
}
|
|
40
34
|
|
|
35
|
+
if (!apply) {
|
|
36
|
+
apply = function apply(fun, thisValue, args) {
|
|
37
|
+
return fun.apply(thisValue, args);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
41
|
if (!construct) {
|
|
42
42
|
construct = function construct(Func, args) {
|
|
43
43
|
return new Func(...args);
|
|
@@ -55,6 +55,13 @@ const stringIndexOf = unapply(String.prototype.indexOf);
|
|
|
55
55
|
const stringTrim = unapply(String.prototype.trim);
|
|
56
56
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
57
57
|
const typeErrorCreate = unconstruct(TypeError);
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new function that calls the given function with a specified thisArg and arguments.
|
|
60
|
+
*
|
|
61
|
+
* @param {Function} func - The function to be wrapped and called.
|
|
62
|
+
* @returns {Function} A new function that calls the given function with a specified thisArg and arguments.
|
|
63
|
+
*/
|
|
64
|
+
|
|
58
65
|
function unapply(func) {
|
|
59
66
|
return function (thisArg) {
|
|
60
67
|
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
@@ -64,6 +71,14 @@ function unapply(func) {
|
|
|
64
71
|
return apply(func, thisArg, args);
|
|
65
72
|
};
|
|
66
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Creates a new function that constructs an instance of the given constructor function with the provided arguments.
|
|
76
|
+
*
|
|
77
|
+
* @param {Function} func - The constructor function to be wrapped and called.
|
|
78
|
+
* @returns {Function} A new function that constructs an instance of the given constructor function with the provided arguments.
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
|
|
67
82
|
function unconstruct(func) {
|
|
68
83
|
return function () {
|
|
69
84
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
@@ -73,12 +88,18 @@ function unconstruct(func) {
|
|
|
73
88
|
return construct(func, args);
|
|
74
89
|
};
|
|
75
90
|
}
|
|
76
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Add properties to a lookup table
|
|
93
|
+
*
|
|
94
|
+
* @param {Object} set - The set to which elements will be added.
|
|
95
|
+
* @param {Array} array - The array containing elements to be added to the set.
|
|
96
|
+
* @param {Function} transformCaseFunc - An optional function to transform the case of each element before adding to the set.
|
|
97
|
+
* @returns {Object} The modified set with added elements.
|
|
98
|
+
*/
|
|
77
99
|
|
|
78
|
-
function addToSet(set, array, transformCaseFunc) {
|
|
79
|
-
var _transformCaseFunc;
|
|
80
100
|
|
|
81
|
-
|
|
101
|
+
function addToSet(set, array) {
|
|
102
|
+
let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;
|
|
82
103
|
|
|
83
104
|
if (setPrototypeOf) {
|
|
84
105
|
// Make 'in' and truthy checks like Boolean(set.constructor)
|
|
@@ -110,19 +131,32 @@ function addToSet(set, array, transformCaseFunc) {
|
|
|
110
131
|
|
|
111
132
|
return set;
|
|
112
133
|
}
|
|
113
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Shallow clone an object
|
|
136
|
+
*
|
|
137
|
+
* @param {Object} object - The object to be cloned.
|
|
138
|
+
* @returns {Object} A new object that copies the original.
|
|
139
|
+
*/
|
|
140
|
+
|
|
114
141
|
|
|
115
142
|
function clone(object) {
|
|
116
143
|
const newObject = create(null);
|
|
117
144
|
|
|
118
145
|
for (const [property, value] of entries(object)) {
|
|
119
|
-
|
|
146
|
+
if (getOwnPropertyDescriptor(object, property) !== undefined) {
|
|
147
|
+
newObject[property] = value;
|
|
148
|
+
}
|
|
120
149
|
}
|
|
121
150
|
|
|
122
151
|
return newObject;
|
|
123
152
|
}
|
|
124
|
-
|
|
125
|
-
* or getter and behaves accordingly.
|
|
153
|
+
/**
|
|
154
|
+
* This method automatically checks if the prop is function or getter and behaves accordingly.
|
|
155
|
+
*
|
|
156
|
+
* @param {Object} object - The object to look up the getter function in its prototype chain.
|
|
157
|
+
* @param {String} prop - The property name for which to find the getter function.
|
|
158
|
+
* @returns {Function} The getter function found in the prototype chain or a fallback function.
|
|
159
|
+
*/
|
|
126
160
|
|
|
127
161
|
function lookupGetter(object, prop) {
|
|
128
162
|
while (object !== null) {
|
|
@@ -197,7 +231,9 @@ var EXPRESSIONS = /*#__PURE__*/Object.freeze({
|
|
|
197
231
|
DOCTYPE_NAME: DOCTYPE_NAME
|
|
198
232
|
});
|
|
199
233
|
|
|
200
|
-
const getGlobal = ()
|
|
234
|
+
const getGlobal = function getGlobal() {
|
|
235
|
+
return typeof window === 'undefined' ? null : window;
|
|
236
|
+
};
|
|
201
237
|
/**
|
|
202
238
|
* Creates a no-op policy for internal use only.
|
|
203
239
|
* Don't export this function outside this module!
|
|
@@ -255,7 +291,7 @@ function createDOMPurify() {
|
|
|
255
291
|
*/
|
|
256
292
|
|
|
257
293
|
|
|
258
|
-
DOMPurify.version = '3.0.
|
|
294
|
+
DOMPurify.version = '3.0.6';
|
|
259
295
|
/**
|
|
260
296
|
* Array of elements that DOMPurify removed during sanitation.
|
|
261
297
|
* Empty if nothing was removed.
|
|
@@ -270,11 +306,11 @@ function createDOMPurify() {
|
|
|
270
306
|
return DOMPurify;
|
|
271
307
|
}
|
|
272
308
|
|
|
273
|
-
const originalDocument = window.document;
|
|
274
|
-
const currentScript = originalDocument.currentScript;
|
|
275
309
|
let {
|
|
276
310
|
document
|
|
277
311
|
} = window;
|
|
312
|
+
const originalDocument = document;
|
|
313
|
+
const currentScript = originalDocument.currentScript;
|
|
278
314
|
const {
|
|
279
315
|
DocumentFragment,
|
|
280
316
|
HTMLTemplateElement,
|
|
@@ -354,7 +390,7 @@ function createDOMPurify() {
|
|
|
354
390
|
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
355
391
|
*/
|
|
356
392
|
|
|
357
|
-
let CUSTOM_ELEMENT_HANDLING = Object.seal(
|
|
393
|
+
let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
|
|
358
394
|
tagNameCheck: {
|
|
359
395
|
writable: true,
|
|
360
396
|
configurable: false,
|
|
@@ -478,10 +514,10 @@ function createDOMPurify() {
|
|
|
478
514
|
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
|
479
515
|
/* Parsing of strict XHTML documents */
|
|
480
516
|
|
|
481
|
-
let PARSER_MEDIA_TYPE;
|
|
517
|
+
let PARSER_MEDIA_TYPE = null;
|
|
482
518
|
const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
483
519
|
const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
484
|
-
let transformCaseFunc;
|
|
520
|
+
let transformCaseFunc = null;
|
|
485
521
|
/* Keep a reference to config to pass to hooks */
|
|
486
522
|
|
|
487
523
|
let CONFIG = null;
|
|
@@ -502,7 +538,9 @@ function createDOMPurify() {
|
|
|
502
538
|
// eslint-disable-next-line complexity
|
|
503
539
|
|
|
504
540
|
|
|
505
|
-
const _parseConfig = function _parseConfig(
|
|
541
|
+
const _parseConfig = function _parseConfig() {
|
|
542
|
+
let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
543
|
+
|
|
506
544
|
if (CONFIG && CONFIG === cfg) {
|
|
507
545
|
return;
|
|
508
546
|
}
|
|
@@ -721,8 +759,6 @@ function createDOMPurify() {
|
|
|
721
759
|
const ALL_MATHML_TAGS = addToSet({}, mathMl$1);
|
|
722
760
|
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
723
761
|
/**
|
|
724
|
-
*
|
|
725
|
-
*
|
|
726
762
|
* @param {Element} element a DOM element whose namespace is being checked
|
|
727
763
|
* @returns {boolean} Return false if the element has a
|
|
728
764
|
* namespace that a spec-compliant parser would never
|
|
@@ -878,8 +914,8 @@ function createDOMPurify() {
|
|
|
878
914
|
|
|
879
915
|
const _initDocument = function _initDocument(dirty) {
|
|
880
916
|
/* Create a HTML document */
|
|
881
|
-
let doc;
|
|
882
|
-
let leadingWhitespace;
|
|
917
|
+
let doc = null;
|
|
918
|
+
let leadingWhitespace = null;
|
|
883
919
|
|
|
884
920
|
if (FORCE_BODY) {
|
|
885
921
|
dirty = '<remove></remove>' + dirty;
|
|
@@ -932,16 +968,16 @@ function createDOMPurify() {
|
|
|
932
968
|
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
933
969
|
};
|
|
934
970
|
/**
|
|
935
|
-
*
|
|
971
|
+
* Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.
|
|
936
972
|
*
|
|
937
|
-
* @param {
|
|
938
|
-
* @return {
|
|
973
|
+
* @param {Node} root The root element or node to start traversing on.
|
|
974
|
+
* @return {NodeIterator} The created NodeIterator
|
|
939
975
|
*/
|
|
940
976
|
|
|
941
977
|
|
|
942
|
-
const
|
|
978
|
+
const _createNodeIterator = function _createNodeIterator(root) {
|
|
943
979
|
return createNodeIterator.call(root.ownerDocument || root, root, // eslint-disable-next-line no-bitwise
|
|
944
|
-
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null
|
|
980
|
+
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null);
|
|
945
981
|
};
|
|
946
982
|
/**
|
|
947
983
|
* _isClobbered
|
|
@@ -955,15 +991,15 @@ function createDOMPurify() {
|
|
|
955
991
|
return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
|
|
956
992
|
};
|
|
957
993
|
/**
|
|
958
|
-
*
|
|
994
|
+
* Checks whether the given object is a DOM node.
|
|
959
995
|
*
|
|
960
|
-
* @param {Node}
|
|
996
|
+
* @param {Node} object object to check whether it's a DOM node
|
|
961
997
|
* @return {Boolean} true is object is a DOM node
|
|
962
998
|
*/
|
|
963
999
|
|
|
964
1000
|
|
|
965
1001
|
const _isNode = function _isNode(object) {
|
|
966
|
-
return typeof Node === '
|
|
1002
|
+
return typeof Node === 'function' && object instanceof Node;
|
|
967
1003
|
};
|
|
968
1004
|
/**
|
|
969
1005
|
* _executeHook
|
|
@@ -997,7 +1033,7 @@ function createDOMPurify() {
|
|
|
997
1033
|
|
|
998
1034
|
|
|
999
1035
|
const _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
1000
|
-
let content;
|
|
1036
|
+
let content = null;
|
|
1001
1037
|
/* Execute a hook if present */
|
|
1002
1038
|
|
|
1003
1039
|
_executeHook('beforeSanitizeElements', currentNode, null);
|
|
@@ -1022,7 +1058,7 @@ function createDOMPurify() {
|
|
|
1022
1058
|
/* Detect mXSS attempts abusing namespace confusion */
|
|
1023
1059
|
|
|
1024
1060
|
|
|
1025
|
-
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) &&
|
|
1061
|
+
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
|
|
1026
1062
|
_forceRemove(currentNode);
|
|
1027
1063
|
|
|
1028
1064
|
return true;
|
|
@@ -1032,9 +1068,14 @@ function createDOMPurify() {
|
|
|
1032
1068
|
|
|
1033
1069
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1034
1070
|
/* Check if we have a custom element to handle */
|
|
1035
|
-
if (!FORBID_TAGS[tagName] &&
|
|
1036
|
-
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
|
|
1037
|
-
|
|
1071
|
+
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
1072
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
1073
|
+
return false;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1038
1079
|
}
|
|
1039
1080
|
/* Keep content except for bad-listed elements */
|
|
1040
1081
|
|
|
@@ -1078,9 +1119,9 @@ function createDOMPurify() {
|
|
|
1078
1119
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
1079
1120
|
/* Get the element's text content */
|
|
1080
1121
|
content = currentNode.textContent;
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1122
|
+
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
1123
|
+
content = stringReplace(content, expr, ' ');
|
|
1124
|
+
});
|
|
1084
1125
|
|
|
1085
1126
|
if (currentNode.textContent !== content) {
|
|
1086
1127
|
arrayPush(DOMPurify.removed, {
|
|
@@ -1122,7 +1163,7 @@ function createDOMPurify() {
|
|
|
1122
1163
|
if ( // First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1123
1164
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1124
1165
|
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
1125
|
-
|
|
1166
|
+
_isBasicCustomElement(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
|
|
1126
1167
|
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1127
1168
|
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 {
|
|
1128
1169
|
return false;
|
|
@@ -1136,14 +1177,16 @@ function createDOMPurify() {
|
|
|
1136
1177
|
return true;
|
|
1137
1178
|
};
|
|
1138
1179
|
/**
|
|
1139
|
-
*
|
|
1180
|
+
* _isBasicCustomElement
|
|
1140
1181
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
1141
1182
|
* for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
|
|
1183
|
+
*
|
|
1142
1184
|
* @param {string} tagName name of the tag of the node to sanitize
|
|
1185
|
+
* @returns {boolean} Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
|
|
1143
1186
|
*/
|
|
1144
1187
|
|
|
1145
1188
|
|
|
1146
|
-
const
|
|
1189
|
+
const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
|
|
1147
1190
|
return tagName.indexOf('-') > 0;
|
|
1148
1191
|
};
|
|
1149
1192
|
/**
|
|
@@ -1159,12 +1202,7 @@ function createDOMPurify() {
|
|
|
1159
1202
|
|
|
1160
1203
|
|
|
1161
1204
|
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
1162
|
-
let attr;
|
|
1163
|
-
let value;
|
|
1164
|
-
let lcName;
|
|
1165
|
-
let l;
|
|
1166
1205
|
/* Execute a hook if present */
|
|
1167
|
-
|
|
1168
1206
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
|
1169
1207
|
|
|
1170
1208
|
const {
|
|
@@ -1182,17 +1220,18 @@ function createDOMPurify() {
|
|
|
1182
1220
|
keepAttr: true,
|
|
1183
1221
|
allowedAttributes: ALLOWED_ATTR
|
|
1184
1222
|
};
|
|
1185
|
-
l = attributes.length;
|
|
1223
|
+
let l = attributes.length;
|
|
1186
1224
|
/* Go backwards over all attributes; safely remove bad ones */
|
|
1187
1225
|
|
|
1188
1226
|
while (l--) {
|
|
1189
|
-
attr = attributes[l];
|
|
1227
|
+
const attr = attributes[l];
|
|
1190
1228
|
const {
|
|
1191
1229
|
name,
|
|
1192
|
-
namespaceURI
|
|
1230
|
+
namespaceURI,
|
|
1231
|
+
value: attrValue
|
|
1193
1232
|
} = attr;
|
|
1194
|
-
|
|
1195
|
-
|
|
1233
|
+
const lcName = transformCaseFunc(name);
|
|
1234
|
+
let value = name === 'value' ? attrValue : stringTrim(attrValue);
|
|
1196
1235
|
/* Execute a hook if present */
|
|
1197
1236
|
|
|
1198
1237
|
hookEvent.attrName = lcName;
|
|
@@ -1230,9 +1269,9 @@ function createDOMPurify() {
|
|
|
1230
1269
|
|
|
1231
1270
|
|
|
1232
1271
|
if (SAFE_FOR_TEMPLATES) {
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1272
|
+
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
1273
|
+
value = stringReplace(value, expr, ' ');
|
|
1274
|
+
});
|
|
1236
1275
|
}
|
|
1237
1276
|
/* Is `value` valid for this attribute? */
|
|
1238
1277
|
|
|
@@ -1301,9 +1340,9 @@ function createDOMPurify() {
|
|
|
1301
1340
|
|
|
1302
1341
|
|
|
1303
1342
|
const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
1304
|
-
let shadowNode;
|
|
1343
|
+
let shadowNode = null;
|
|
1305
1344
|
|
|
1306
|
-
const shadowIterator =
|
|
1345
|
+
const shadowIterator = _createNodeIterator(fragment);
|
|
1307
1346
|
/* Execute a hook if present */
|
|
1308
1347
|
|
|
1309
1348
|
|
|
@@ -1339,17 +1378,17 @@ function createDOMPurify() {
|
|
|
1339
1378
|
* Public method providing core sanitation functionality
|
|
1340
1379
|
*
|
|
1341
1380
|
* @param {String|Node} dirty string or DOM node
|
|
1342
|
-
* @param {Object}
|
|
1381
|
+
* @param {Object} cfg object
|
|
1343
1382
|
*/
|
|
1344
1383
|
// eslint-disable-next-line complexity
|
|
1345
1384
|
|
|
1346
1385
|
|
|
1347
1386
|
DOMPurify.sanitize = function (dirty) {
|
|
1348
1387
|
let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1349
|
-
let body;
|
|
1350
|
-
let importedNode;
|
|
1351
|
-
let currentNode;
|
|
1352
|
-
let returnNode;
|
|
1388
|
+
let body = null;
|
|
1389
|
+
let importedNode = null;
|
|
1390
|
+
let currentNode = null;
|
|
1391
|
+
let returnNode = null;
|
|
1353
1392
|
/* Make sure we have a string to sanitize.
|
|
1354
1393
|
DO NOT return early, as this will return the wrong type if
|
|
1355
1394
|
the user has requested a DOM object rather than a string */
|
|
@@ -1444,7 +1483,7 @@ function createDOMPurify() {
|
|
|
1444
1483
|
/* Get node iterator */
|
|
1445
1484
|
|
|
1446
1485
|
|
|
1447
|
-
const nodeIterator =
|
|
1486
|
+
const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
|
|
1448
1487
|
/* Now start iterating over the created document */
|
|
1449
1488
|
|
|
1450
1489
|
|
|
@@ -1509,9 +1548,9 @@ function createDOMPurify() {
|
|
|
1509
1548
|
|
|
1510
1549
|
|
|
1511
1550
|
if (SAFE_FOR_TEMPLATES) {
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1551
|
+
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
1552
|
+
serializedHTML = stringReplace(serializedHTML, expr, ' ');
|
|
1553
|
+
});
|
|
1515
1554
|
}
|
|
1516
1555
|
|
|
1517
1556
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
@@ -1524,7 +1563,9 @@ function createDOMPurify() {
|
|
|
1524
1563
|
*/
|
|
1525
1564
|
|
|
1526
1565
|
|
|
1527
|
-
DOMPurify.setConfig = function (
|
|
1566
|
+
DOMPurify.setConfig = function () {
|
|
1567
|
+
let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1568
|
+
|
|
1528
1569
|
_parseConfig(cfg);
|
|
1529
1570
|
|
|
1530
1571
|
SET_CONFIG = true;
|
|
@@ -1545,9 +1586,9 @@ function createDOMPurify() {
|
|
|
1545
1586
|
* Uses last set config, if any. Otherwise, uses config defaults.
|
|
1546
1587
|
* isValidAttribute
|
|
1547
1588
|
*
|
|
1548
|
-
* @param {
|
|
1549
|
-
* @param {
|
|
1550
|
-
* @param {
|
|
1589
|
+
* @param {String} tag Tag name of containing element.
|
|
1590
|
+
* @param {String} attr Attribute name.
|
|
1591
|
+
* @param {String} value Attribute value.
|
|
1551
1592
|
* @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
|
|
1552
1593
|
*/
|
|
1553
1594
|
|
|
@@ -1610,7 +1651,6 @@ function createDOMPurify() {
|
|
|
1610
1651
|
/**
|
|
1611
1652
|
* RemoveAllHooks
|
|
1612
1653
|
* Public method to remove all DOMPurify hooks
|
|
1613
|
-
*
|
|
1614
1654
|
*/
|
|
1615
1655
|
|
|
1616
1656
|
|