@touchvue/chat 1.0.0-beta.51 → 1.0.0-beta.52
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 +70 -70
- package/es/node_modules/.pnpm/{dompurify@3.4.3 → dompurify@3.3.0}/node_modules/dompurify/dist/purify.es.mjs +143 -299
- package/es/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.mjs.map +1 -0
- package/es/package.json.css +1 -1
- package/es/package.json.mjs +1 -1
- package/es/packages/components/resolver.mjs.map +1 -1
- package/es/packages/components/touchchat/component/AiRobot/HelloChat.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/AiRobot/letter.vue.mjs +1 -1
- package/es/packages/components/touchchat/component/AiRobot/letter.vue2.mjs +9 -9
- package/es/packages/components/touchchat/component/AiRobot/letter.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/FileContent.vue2.mjs +3 -3
- package/es/packages/components/touchchat/component/FileContent.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/FileView.vue2.mjs +2 -2
- package/es/packages/components/touchchat/component/FileView.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/HelloChat.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/ImageFile.vue2.mjs +6 -6
- package/es/packages/components/touchchat/component/ImageFile.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/ImageView.vue2.mjs +1 -1
- package/es/packages/components/touchchat/component/ImageView.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/LinkView.vue2.mjs +4 -4
- package/es/packages/components/touchchat/component/LinkView.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/MarkLayer.vue2.mjs +1 -1
- package/es/packages/components/touchchat/component/MarkLayer.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/ModuleSelect.vue2.mjs +2 -2
- package/es/packages/components/touchchat/component/ModuleSelect.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/PDFFile.vue2.mjs +10 -10
- package/es/packages/components/touchchat/component/PDFFile.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/QuoteContent.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/RealtimeVoice.vue2.mjs +1 -1
- package/es/packages/components/touchchat/component/RealtimeVoice.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/UploadView.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/component/VideoFile.vue.mjs +1 -1
- package/es/packages/components/touchchat/component/VideoFile.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/AgentsView.vue2.mjs +1 -1
- package/es/packages/components/touchchat/src/AiChat/AgentsView.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/AiMessage.vue2.mjs +30 -30
- package/es/packages/components/touchchat/src/AiChat/AiMessage.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/Chat/scriptMatcher.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/Chat/types.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/Chat/useChat.mjs +6 -0
- package/es/packages/components/touchchat/src/AiChat/Chat/useChat.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/Chat/useCopy.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/Chat/useMessageRender.mjs +1 -1
- package/es/packages/components/touchchat/src/AiChat/Chat/useMessageRender.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/Chat/useSSE.mjs +93 -4
- package/es/packages/components/touchchat/src/AiChat/Chat/useSSE.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/ChatInput.vue2.mjs +5 -5
- package/es/packages/components/touchchat/src/AiChat/ChatInput.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/HistoryList.vue2.mjs +1 -1
- package/es/packages/components/touchchat/src/AiChat/HistoryList.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.mjs +3 -3
- package/es/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/MessageActions.vue2.mjs +11 -11
- package/es/packages/components/touchchat/src/AiChat/MessageActions.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/SiderBarView.vue2.mjs +3 -3
- package/es/packages/components/touchchat/src/AiChat/SiderBarView.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/TouchAgent.vue2.mjs +1 -1
- package/es/packages/components/touchchat/src/AiChat/TouchChat.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/TouchHistory.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/AiChat/UserMessage.vue2.mjs +16 -16
- package/es/packages/components/touchchat/src/AiChat/UserMessage.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/src/index.vue2.mjs.map +1 -1
- package/es/packages/components/touchchat/utils/a2aService.mjs.map +1 -1
- package/es/packages/components/touchchat/utils/fetchStream.mjs.map +1 -1
- package/es/packages/components/touchchat/utils/markdown.mjs +1 -1
- package/lib/node_modules/.pnpm/{dompurify@3.4.3 → dompurify@3.3.0}/node_modules/dompurify/dist/purify.es.js +143 -299
- package/lib/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.js.map +1 -0
- package/lib/package.json.css +1 -1
- package/lib/package.json.js +1 -1
- package/lib/packages/components/resolver.js.map +1 -1
- package/lib/packages/components/touchchat/component/AiRobot/HelloChat.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/AiRobot/letter.vue.js +1 -1
- package/lib/packages/components/touchchat/component/AiRobot/letter.vue2.js +9 -9
- package/lib/packages/components/touchchat/component/AiRobot/letter.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/FileContent.vue2.js +3 -3
- package/lib/packages/components/touchchat/component/FileContent.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/FileView.vue2.js +2 -2
- package/lib/packages/components/touchchat/component/FileView.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/HelloChat.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/ImageFile.vue2.js +6 -6
- package/lib/packages/components/touchchat/component/ImageFile.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/ImageView.vue2.js +1 -1
- package/lib/packages/components/touchchat/component/ImageView.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/LinkView.vue2.js +4 -4
- package/lib/packages/components/touchchat/component/LinkView.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/MarkLayer.vue2.js +1 -1
- package/lib/packages/components/touchchat/component/MarkLayer.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/ModuleSelect.vue2.js +2 -2
- package/lib/packages/components/touchchat/component/ModuleSelect.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/PDFFile.vue2.js +10 -10
- package/lib/packages/components/touchchat/component/PDFFile.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/QuoteContent.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/RealtimeVoice.vue2.js +1 -1
- package/lib/packages/components/touchchat/component/RealtimeVoice.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/UploadView.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/component/VideoFile.vue.js +1 -1
- package/lib/packages/components/touchchat/component/VideoFile.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/AgentsView.vue2.js +1 -1
- package/lib/packages/components/touchchat/src/AiChat/AgentsView.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/AiMessage.vue2.js +30 -30
- package/lib/packages/components/touchchat/src/AiChat/AiMessage.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/Chat/scriptMatcher.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/Chat/types.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/Chat/useChat.js +6 -0
- package/lib/packages/components/touchchat/src/AiChat/Chat/useChat.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/Chat/useCopy.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/Chat/useMessageRender.js +1 -1
- package/lib/packages/components/touchchat/src/AiChat/Chat/useMessageRender.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/Chat/useSSE.js +93 -4
- package/lib/packages/components/touchchat/src/AiChat/Chat/useSSE.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/ChatInput.vue2.js +5 -5
- package/lib/packages/components/touchchat/src/AiChat/ChatInput.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/HistoryList.vue2.js +1 -1
- package/lib/packages/components/touchchat/src/AiChat/HistoryList.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.js +3 -3
- package/lib/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/MessageActions.vue2.js +11 -11
- package/lib/packages/components/touchchat/src/AiChat/MessageActions.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/SiderBarView.vue2.js +3 -3
- package/lib/packages/components/touchchat/src/AiChat/SiderBarView.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/TouchAgent.vue2.js +1 -1
- package/lib/packages/components/touchchat/src/AiChat/TouchChat.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/TouchHistory.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/AiChat/UserMessage.vue2.js +16 -16
- package/lib/packages/components/touchchat/src/AiChat/UserMessage.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/src/index.vue2.js.map +1 -1
- package/lib/packages/components/touchchat/utils/a2aService.js.map +1 -1
- package/lib/packages/components/touchchat/utils/fetchStream.js.map +1 -1
- package/lib/packages/components/touchchat/utils/markdown.js +1 -1
- package/package.json +83 -83
- package/es/node_modules/.pnpm/dompurify@3.4.3/node_modules/dompurify/dist/purify.es.mjs.map +0 -1
- package/lib/node_modules/.pnpm/dompurify@3.4.3/node_modules/dompurify/dist/purify.es.js.map +0 -1
|
@@ -2,65 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
/*! @license DOMPurify 3.
|
|
5
|
+
/*! @license DOMPurify 3.3.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.0/LICENSE */
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
f = true,
|
|
24
|
-
o = false;
|
|
25
|
-
try {
|
|
26
|
-
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
|
|
27
|
-
} catch (r) {
|
|
28
|
-
o = true, n = r;
|
|
29
|
-
} finally {
|
|
30
|
-
try {
|
|
31
|
-
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
32
|
-
} finally {
|
|
33
|
-
if (o) throw n;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return a;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function _nonIterableRest() {
|
|
40
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
41
|
-
}
|
|
42
|
-
function _slicedToArray(r, e) {
|
|
43
|
-
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
44
|
-
}
|
|
45
|
-
function _unsupportedIterableToArray(r, a) {
|
|
46
|
-
if (r) {
|
|
47
|
-
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
48
|
-
var t = {}.toString.call(r).slice(8, -1);
|
|
49
|
-
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const entries = Object.entries,
|
|
54
|
-
setPrototypeOf = Object.setPrototypeOf,
|
|
55
|
-
isFrozen = Object.isFrozen,
|
|
56
|
-
getPrototypeOf = Object.getPrototypeOf,
|
|
57
|
-
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
58
|
-
let freeze = Object.freeze,
|
|
59
|
-
seal = Object.seal,
|
|
60
|
-
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
61
|
-
let _ref = typeof Reflect !== 'undefined' && Reflect,
|
|
62
|
-
apply = _ref.apply,
|
|
63
|
-
construct = _ref.construct;
|
|
7
|
+
const {
|
|
8
|
+
entries,
|
|
9
|
+
setPrototypeOf,
|
|
10
|
+
isFrozen,
|
|
11
|
+
getPrototypeOf,
|
|
12
|
+
getOwnPropertyDescriptor
|
|
13
|
+
} = Object;
|
|
14
|
+
let {
|
|
15
|
+
freeze,
|
|
16
|
+
seal,
|
|
17
|
+
create
|
|
18
|
+
} = Object; // eslint-disable-line import/no-mutable-exports
|
|
19
|
+
let {
|
|
20
|
+
apply,
|
|
21
|
+
construct
|
|
22
|
+
} = typeof Reflect !== 'undefined' && Reflect;
|
|
64
23
|
if (!freeze) {
|
|
65
24
|
freeze = function freeze(x) {
|
|
66
25
|
return x;
|
|
@@ -92,19 +51,13 @@ const arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
|
|
|
92
51
|
const arrayPop = unapply(Array.prototype.pop);
|
|
93
52
|
const arrayPush = unapply(Array.prototype.push);
|
|
94
53
|
const arraySplice = unapply(Array.prototype.splice);
|
|
95
|
-
const arrayIsArray = Array.isArray;
|
|
96
54
|
const stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
97
55
|
const stringToString = unapply(String.prototype.toString);
|
|
98
56
|
const stringMatch = unapply(String.prototype.match);
|
|
99
57
|
const stringReplace = unapply(String.prototype.replace);
|
|
100
58
|
const stringIndexOf = unapply(String.prototype.indexOf);
|
|
101
59
|
const stringTrim = unapply(String.prototype.trim);
|
|
102
|
-
const numberToString = unapply(Number.prototype.toString);
|
|
103
|
-
const booleanToString = unapply(Boolean.prototype.toString);
|
|
104
|
-
const bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);
|
|
105
|
-
const symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);
|
|
106
60
|
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
107
|
-
const objectToString = unapply(Object.prototype.toString);
|
|
108
61
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
109
62
|
const typeErrorCreate = unconstruct(TypeError);
|
|
110
63
|
/**
|
|
@@ -154,9 +107,6 @@ function addToSet(set, array) {
|
|
|
154
107
|
// Prevent prototype setters from intercepting set as a this value.
|
|
155
108
|
setPrototypeOf(set, null);
|
|
156
109
|
}
|
|
157
|
-
if (!arrayIsArray(array)) {
|
|
158
|
-
return set;
|
|
159
|
-
}
|
|
160
110
|
let l = array.length;
|
|
161
111
|
while (l--) {
|
|
162
112
|
let element = array[l];
|
|
@@ -197,13 +147,10 @@ function cleanArray(array) {
|
|
|
197
147
|
*/
|
|
198
148
|
function clone(object) {
|
|
199
149
|
const newObject = create(null);
|
|
200
|
-
for (const
|
|
201
|
-
var _ref3 = _slicedToArray(_ref2, 2);
|
|
202
|
-
const property = _ref3[0];
|
|
203
|
-
const value = _ref3[1];
|
|
150
|
+
for (const [property, value] of entries(object)) {
|
|
204
151
|
const isPropertyExist = objectHasOwnProperty(object, property);
|
|
205
152
|
if (isPropertyExist) {
|
|
206
|
-
if (
|
|
153
|
+
if (Array.isArray(value)) {
|
|
207
154
|
newObject[property] = cleanArray(value);
|
|
208
155
|
} else if (value && typeof value === 'object' && value.constructor === Object) {
|
|
209
156
|
newObject[property] = clone(value);
|
|
@@ -214,58 +161,6 @@ function clone(object) {
|
|
|
214
161
|
}
|
|
215
162
|
return newObject;
|
|
216
163
|
}
|
|
217
|
-
/**
|
|
218
|
-
* Convert non-node values into strings without depending on direct property access.
|
|
219
|
-
*
|
|
220
|
-
* @param value - The value to stringify.
|
|
221
|
-
* @returns A string representation of the provided value.
|
|
222
|
-
*/
|
|
223
|
-
function stringifyValue(value) {
|
|
224
|
-
switch (typeof value) {
|
|
225
|
-
case 'string':
|
|
226
|
-
{
|
|
227
|
-
return value;
|
|
228
|
-
}
|
|
229
|
-
case 'number':
|
|
230
|
-
{
|
|
231
|
-
return numberToString(value);
|
|
232
|
-
}
|
|
233
|
-
case 'boolean':
|
|
234
|
-
{
|
|
235
|
-
return booleanToString(value);
|
|
236
|
-
}
|
|
237
|
-
case 'bigint':
|
|
238
|
-
{
|
|
239
|
-
return bigintToString ? bigintToString(value) : '0';
|
|
240
|
-
}
|
|
241
|
-
case 'symbol':
|
|
242
|
-
{
|
|
243
|
-
return symbolToString ? symbolToString(value) : 'Symbol()';
|
|
244
|
-
}
|
|
245
|
-
case 'undefined':
|
|
246
|
-
{
|
|
247
|
-
return objectToString(value);
|
|
248
|
-
}
|
|
249
|
-
case 'function':
|
|
250
|
-
case 'object':
|
|
251
|
-
{
|
|
252
|
-
if (value === null) {
|
|
253
|
-
return objectToString(value);
|
|
254
|
-
}
|
|
255
|
-
const valueAsRecord = value;
|
|
256
|
-
const valueToString = lookupGetter(valueAsRecord, 'toString');
|
|
257
|
-
if (typeof valueToString === 'function') {
|
|
258
|
-
const stringified = valueToString(valueAsRecord);
|
|
259
|
-
return typeof stringified === 'string' ? stringified : objectToString(stringified);
|
|
260
|
-
}
|
|
261
|
-
return objectToString(value);
|
|
262
|
-
}
|
|
263
|
-
default:
|
|
264
|
-
{
|
|
265
|
-
return objectToString(value);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
164
|
/**
|
|
270
165
|
* This method automatically checks if the prop is function or getter and behaves accordingly.
|
|
271
166
|
*
|
|
@@ -291,14 +186,6 @@ function lookupGetter(object, prop) {
|
|
|
291
186
|
}
|
|
292
187
|
return fallbackValue;
|
|
293
188
|
}
|
|
294
|
-
function isRegex(value) {
|
|
295
|
-
try {
|
|
296
|
-
regExpTest(value, '');
|
|
297
|
-
return true;
|
|
298
|
-
} catch (_unused) {
|
|
299
|
-
return false;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
189
|
|
|
303
190
|
const html$1 = 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', 'search', 'section', 'select', 'shadow', 'slot', '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']);
|
|
304
191
|
const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
|
|
@@ -314,14 +201,15 @@ const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mgly
|
|
|
314
201
|
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
315
202
|
const text = freeze(['#text']);
|
|
316
203
|
|
|
317
|
-
const html = 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', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', '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', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']);
|
|
204
|
+
const html = 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', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', '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', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
|
|
318
205
|
const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', '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', 'exponent', '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', 'intercept', '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', 'mask-type', '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', 'slope', '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', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', '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']);
|
|
319
|
-
const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', '
|
|
206
|
+
const mathMl = 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']);
|
|
320
207
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
321
208
|
|
|
322
|
-
|
|
323
|
-
const
|
|
324
|
-
const
|
|
209
|
+
// eslint-disable-next-line unicorn/better-regex
|
|
210
|
+
const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
211
|
+
const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
|
|
212
|
+
const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
|
|
325
213
|
const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
|
|
326
214
|
const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
327
215
|
const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
|
|
@@ -332,15 +220,38 @@ const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205
|
|
|
332
220
|
const DOCTYPE_NAME = seal(/^html$/i);
|
|
333
221
|
const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
|
|
334
222
|
|
|
223
|
+
var EXPRESSIONS = /*#__PURE__*/Object.freeze({
|
|
224
|
+
__proto__: null,
|
|
225
|
+
ARIA_ATTR: ARIA_ATTR,
|
|
226
|
+
ATTR_WHITESPACE: ATTR_WHITESPACE,
|
|
227
|
+
CUSTOM_ELEMENT: CUSTOM_ELEMENT,
|
|
228
|
+
DATA_ATTR: DATA_ATTR,
|
|
229
|
+
DOCTYPE_NAME: DOCTYPE_NAME,
|
|
230
|
+
ERB_EXPR: ERB_EXPR,
|
|
231
|
+
IS_ALLOWED_URI: IS_ALLOWED_URI,
|
|
232
|
+
IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
|
|
233
|
+
MUSTACHE_EXPR: MUSTACHE_EXPR,
|
|
234
|
+
TMPLIT_EXPR: TMPLIT_EXPR
|
|
235
|
+
});
|
|
236
|
+
|
|
335
237
|
/* eslint-disable @typescript-eslint/indent */
|
|
336
238
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
337
239
|
const NODE_TYPE = {
|
|
338
240
|
element: 1,
|
|
241
|
+
attribute: 2,
|
|
339
242
|
text: 3,
|
|
243
|
+
cdataSection: 4,
|
|
244
|
+
entityReference: 5,
|
|
245
|
+
// Deprecated
|
|
246
|
+
entityNode: 6,
|
|
340
247
|
// Deprecated
|
|
341
248
|
progressingInstruction: 7,
|
|
342
249
|
comment: 8,
|
|
343
|
-
document: 9
|
|
250
|
+
document: 9,
|
|
251
|
+
documentType: 10,
|
|
252
|
+
documentFragment: 11,
|
|
253
|
+
notation: 12 // Deprecated
|
|
254
|
+
};
|
|
344
255
|
const getGlobal = function getGlobal() {
|
|
345
256
|
return typeof window === 'undefined' ? null : window;
|
|
346
257
|
};
|
|
@@ -398,7 +309,7 @@ const _createHooksMap = function _createHooksMap() {
|
|
|
398
309
|
function createDOMPurify() {
|
|
399
310
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
400
311
|
const DOMPurify = root => createDOMPurify(root);
|
|
401
|
-
DOMPurify.version = '3.
|
|
312
|
+
DOMPurify.version = '3.3.0';
|
|
402
313
|
DOMPurify.removed = [];
|
|
403
314
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
404
315
|
// Not running in a browser, provide a factory function
|
|
@@ -406,19 +317,22 @@ function createDOMPurify() {
|
|
|
406
317
|
DOMPurify.isSupported = false;
|
|
407
318
|
return DOMPurify;
|
|
408
319
|
}
|
|
409
|
-
let
|
|
320
|
+
let {
|
|
321
|
+
document
|
|
322
|
+
} = window;
|
|
410
323
|
const originalDocument = document;
|
|
411
324
|
const currentScript = originalDocument.currentScript;
|
|
412
|
-
const
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
NamedNodeMap =
|
|
419
|
-
HTMLFormElement
|
|
420
|
-
DOMParser
|
|
421
|
-
trustedTypes
|
|
325
|
+
const {
|
|
326
|
+
DocumentFragment,
|
|
327
|
+
HTMLTemplateElement,
|
|
328
|
+
Node,
|
|
329
|
+
Element,
|
|
330
|
+
NodeFilter,
|
|
331
|
+
NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
|
|
332
|
+
HTMLFormElement,
|
|
333
|
+
DOMParser,
|
|
334
|
+
trustedTypes
|
|
335
|
+
} = window;
|
|
422
336
|
const ElementPrototype = Element.prototype;
|
|
423
337
|
const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
424
338
|
const remove = lookupGetter(ElementPrototype, 'remove');
|
|
@@ -439,26 +353,33 @@ function createDOMPurify() {
|
|
|
439
353
|
}
|
|
440
354
|
let trustedTypesPolicy;
|
|
441
355
|
let emptyHTML = '';
|
|
442
|
-
const
|
|
443
|
-
implementation
|
|
444
|
-
createNodeIterator
|
|
445
|
-
createDocumentFragment
|
|
446
|
-
getElementsByTagName
|
|
447
|
-
|
|
356
|
+
const {
|
|
357
|
+
implementation,
|
|
358
|
+
createNodeIterator,
|
|
359
|
+
createDocumentFragment,
|
|
360
|
+
getElementsByTagName
|
|
361
|
+
} = document;
|
|
362
|
+
const {
|
|
363
|
+
importNode
|
|
364
|
+
} = originalDocument;
|
|
448
365
|
let hooks = _createHooksMap();
|
|
449
366
|
/**
|
|
450
367
|
* Expose whether this browser supports running the full DOMPurify.
|
|
451
368
|
*/
|
|
452
369
|
DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
370
|
+
const {
|
|
371
|
+
MUSTACHE_EXPR,
|
|
372
|
+
ERB_EXPR,
|
|
373
|
+
TMPLIT_EXPR,
|
|
374
|
+
DATA_ATTR,
|
|
375
|
+
ARIA_ATTR,
|
|
376
|
+
IS_SCRIPT_OR_DATA,
|
|
377
|
+
ATTR_WHITESPACE,
|
|
378
|
+
CUSTOM_ELEMENT
|
|
379
|
+
} = EXPRESSIONS;
|
|
380
|
+
let {
|
|
381
|
+
IS_ALLOWED_URI: IS_ALLOWED_URI$1
|
|
382
|
+
} = EXPRESSIONS;
|
|
462
383
|
/**
|
|
463
384
|
* We consider the elements and attributes below to be safe. Ideally
|
|
464
385
|
* don't add any new ones but feel free to remove unwanted ones.
|
|
@@ -636,15 +557,15 @@ function createDOMPurify() {
|
|
|
636
557
|
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
637
558
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
|
|
638
559
|
/* Set configuration parameters */
|
|
639
|
-
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS')
|
|
640
|
-
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR')
|
|
641
|
-
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES')
|
|
642
|
-
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR')
|
|
643
|
-
DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS')
|
|
644
|
-
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS')
|
|
645
|
-
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS')
|
|
646
|
-
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR')
|
|
647
|
-
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES
|
|
560
|
+
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
561
|
+
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
562
|
+
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
563
|
+
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
564
|
+
DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
|
|
565
|
+
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
566
|
+
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
567
|
+
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
568
|
+
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
|
|
648
569
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
649
570
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
650
571
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
@@ -660,20 +581,19 @@ function createDOMPurify() {
|
|
|
660
581
|
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
|
|
661
582
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
662
583
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
663
|
-
IS_ALLOWED_URI$1 =
|
|
664
|
-
NAMESPACE =
|
|
665
|
-
MATHML_TEXT_INTEGRATION_POINTS =
|
|
666
|
-
HTML_INTEGRATION_POINTS =
|
|
667
|
-
|
|
668
|
-
CUSTOM_ELEMENT_HANDLING
|
|
669
|
-
|
|
670
|
-
CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined
|
|
584
|
+
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
|
|
585
|
+
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
586
|
+
MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
|
|
587
|
+
HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
|
|
588
|
+
CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
|
|
589
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
590
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
671
591
|
}
|
|
672
|
-
if (
|
|
673
|
-
CUSTOM_ELEMENT_HANDLING.attributeNameCheck =
|
|
592
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
|
|
593
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
|
|
674
594
|
}
|
|
675
|
-
if (
|
|
676
|
-
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements =
|
|
595
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
|
|
596
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
|
|
677
597
|
}
|
|
678
598
|
if (SAFE_FOR_TEMPLATES) {
|
|
679
599
|
ALLOW_DATA_ATTR = false;
|
|
@@ -684,7 +604,7 @@ function createDOMPurify() {
|
|
|
684
604
|
/* Parse profile info */
|
|
685
605
|
if (USE_PROFILES) {
|
|
686
606
|
ALLOWED_TAGS = addToSet({}, text);
|
|
687
|
-
ALLOWED_ATTR =
|
|
607
|
+
ALLOWED_ATTR = [];
|
|
688
608
|
if (USE_PROFILES.html === true) {
|
|
689
609
|
addToSet(ALLOWED_TAGS, html$1);
|
|
690
610
|
addToSet(ALLOWED_ATTR, html);
|
|
@@ -705,46 +625,36 @@ function createDOMPurify() {
|
|
|
705
625
|
addToSet(ALLOWED_ATTR, xml);
|
|
706
626
|
}
|
|
707
627
|
}
|
|
708
|
-
/* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
|
|
709
|
-
* leaking across calls when switching from function to array config */
|
|
710
|
-
EXTRA_ELEMENT_HANDLING.tagCheck = null;
|
|
711
|
-
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
712
628
|
/* Merge configuration parameters */
|
|
713
|
-
if (
|
|
629
|
+
if (cfg.ADD_TAGS) {
|
|
714
630
|
if (typeof cfg.ADD_TAGS === 'function') {
|
|
715
631
|
EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
|
|
716
|
-
} else
|
|
632
|
+
} else {
|
|
717
633
|
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
718
634
|
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
719
635
|
}
|
|
720
636
|
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
721
637
|
}
|
|
722
638
|
}
|
|
723
|
-
if (
|
|
639
|
+
if (cfg.ADD_ATTR) {
|
|
724
640
|
if (typeof cfg.ADD_ATTR === 'function') {
|
|
725
641
|
EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
|
|
726
|
-
} else
|
|
642
|
+
} else {
|
|
727
643
|
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
728
644
|
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
729
645
|
}
|
|
730
646
|
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
731
647
|
}
|
|
732
648
|
}
|
|
733
|
-
if (
|
|
649
|
+
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
734
650
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
735
651
|
}
|
|
736
|
-
if (
|
|
652
|
+
if (cfg.FORBID_CONTENTS) {
|
|
737
653
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
738
654
|
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
739
655
|
}
|
|
740
656
|
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
741
657
|
}
|
|
742
|
-
if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
|
|
743
|
-
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
744
|
-
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
745
|
-
}
|
|
746
|
-
addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
|
|
747
|
-
}
|
|
748
658
|
/* Add #text in case KEEP_CONTENT is set to true */
|
|
749
659
|
if (KEEP_CONTENT) {
|
|
750
660
|
ALLOWED_TAGS['#text'] = true;
|
|
@@ -1031,11 +941,6 @@ function createDOMPurify() {
|
|
|
1031
941
|
_forceRemove(currentNode);
|
|
1032
942
|
return true;
|
|
1033
943
|
}
|
|
1034
|
-
/* Remove risky CSS construction leading to mXSS */
|
|
1035
|
-
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
|
|
1036
|
-
_forceRemove(currentNode);
|
|
1037
|
-
return true;
|
|
1038
|
-
}
|
|
1039
944
|
/* Remove any occurrence of processing instructions */
|
|
1040
945
|
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
1041
946
|
_forceRemove(currentNode);
|
|
@@ -1047,7 +952,7 @@ function createDOMPurify() {
|
|
|
1047
952
|
return true;
|
|
1048
953
|
}
|
|
1049
954
|
/* Remove element if anything forbids its presence */
|
|
1050
|
-
if (
|
|
955
|
+
if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])) {
|
|
1051
956
|
/* Check if we have a custom element to handle */
|
|
1052
957
|
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
1053
958
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
@@ -1065,6 +970,7 @@ function createDOMPurify() {
|
|
|
1065
970
|
const childCount = childNodes.length;
|
|
1066
971
|
for (let i = childCount - 1; i >= 0; --i) {
|
|
1067
972
|
const childClone = cloneNode(childNodes[i], true);
|
|
973
|
+
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
1068
974
|
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
1069
975
|
}
|
|
1070
976
|
}
|
|
@@ -1086,7 +992,7 @@ function createDOMPurify() {
|
|
|
1086
992
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
|
1087
993
|
/* Get the element's text content */
|
|
1088
994
|
content = currentNode.textContent;
|
|
1089
|
-
arrayForEach([MUSTACHE_EXPR
|
|
995
|
+
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
1090
996
|
content = stringReplace(content, expr, ' ');
|
|
1091
997
|
});
|
|
1092
998
|
if (currentNode.textContent !== content) {
|
|
@@ -1110,20 +1016,15 @@ function createDOMPurify() {
|
|
|
1110
1016
|
*/
|
|
1111
1017
|
// eslint-disable-next-line complexity
|
|
1112
1018
|
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
1113
|
-
/* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
|
|
1114
|
-
if (FORBID_ATTR[lcName]) {
|
|
1115
|
-
return false;
|
|
1116
|
-
}
|
|
1117
1019
|
/* Make sure attribute cannot clobber */
|
|
1118
1020
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1119
1021
|
return false;
|
|
1120
1022
|
}
|
|
1121
|
-
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
1122
1023
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
1123
1024
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
1124
1025
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
1125
1026
|
We don't need to check the value; it's always URI safe. */
|
|
1126
|
-
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR
|
|
1027
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
1127
1028
|
if (
|
|
1128
1029
|
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1129
1030
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
@@ -1135,15 +1036,11 @@ function createDOMPurify() {
|
|
|
1135
1036
|
return false;
|
|
1136
1037
|
}
|
|
1137
1038
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
1138
|
-
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE
|
|
1039
|
+
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; 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, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {
|
|
1139
1040
|
return false;
|
|
1140
1041
|
} else ;
|
|
1141
1042
|
return true;
|
|
1142
1043
|
};
|
|
1143
|
-
/* Names the HTML spec reserves from valid-custom-element-name; these must
|
|
1144
|
-
* never be treated as basic custom elements even when a permissive
|
|
1145
|
-
* CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */
|
|
1146
|
-
const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ['annotation-xml', 'color-profile', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'missing-glyph']);
|
|
1147
1044
|
/**
|
|
1148
1045
|
* _isBasicCustomElement
|
|
1149
1046
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
@@ -1153,7 +1050,7 @@ function createDOMPurify() {
|
|
|
1153
1050
|
* @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
|
|
1154
1051
|
*/
|
|
1155
1052
|
const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
|
|
1156
|
-
return
|
|
1053
|
+
return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);
|
|
1157
1054
|
};
|
|
1158
1055
|
/**
|
|
1159
1056
|
* _sanitizeAttributes
|
|
@@ -1168,7 +1065,9 @@ function createDOMPurify() {
|
|
|
1168
1065
|
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
1169
1066
|
/* Execute a hook if present */
|
|
1170
1067
|
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
|
1171
|
-
const
|
|
1068
|
+
const {
|
|
1069
|
+
attributes
|
|
1070
|
+
} = currentNode;
|
|
1172
1071
|
/* Check if we have attributes; if not we might have a text node */
|
|
1173
1072
|
if (!attributes || _isClobbered(currentNode)) {
|
|
1174
1073
|
return;
|
|
@@ -1184,9 +1083,11 @@ function createDOMPurify() {
|
|
|
1184
1083
|
/* Go backwards over all attributes; safely remove bad ones */
|
|
1185
1084
|
while (l--) {
|
|
1186
1085
|
const attr = attributes[l];
|
|
1187
|
-
const
|
|
1188
|
-
|
|
1189
|
-
|
|
1086
|
+
const {
|
|
1087
|
+
name,
|
|
1088
|
+
namespaceURI,
|
|
1089
|
+
value: attrValue
|
|
1090
|
+
} = attr;
|
|
1190
1091
|
const lcName = transformCaseFunc(name);
|
|
1191
1092
|
const initValue = attrValue;
|
|
1192
1093
|
let value = name === 'value' ? initValue : stringTrim(initValue);
|
|
@@ -1200,16 +1101,14 @@ function createDOMPurify() {
|
|
|
1200
1101
|
/* Full DOM Clobbering protection via namespace isolation,
|
|
1201
1102
|
* Prefix id and name attributes with `user-content-`
|
|
1202
1103
|
*/
|
|
1203
|
-
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')
|
|
1104
|
+
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
|
|
1204
1105
|
// Remove the attribute with this value
|
|
1205
1106
|
_removeAttribute(name, currentNode);
|
|
1206
1107
|
// Prefix the value and later re-create the attribute with the sanitized value
|
|
1207
1108
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
1208
1109
|
}
|
|
1209
|
-
// Else: already prefixed, leave the attribute alone — the prefix is
|
|
1210
|
-
// itself the clobbering protection, and re-applying it is incorrect.
|
|
1211
1110
|
/* Work around a security issue with comments inside attributes */
|
|
1212
|
-
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|
|
|
1111
|
+
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title|textarea)/i, value)) {
|
|
1213
1112
|
_removeAttribute(name, currentNode);
|
|
1214
1113
|
continue;
|
|
1215
1114
|
}
|
|
@@ -1234,7 +1133,7 @@ function createDOMPurify() {
|
|
|
1234
1133
|
}
|
|
1235
1134
|
/* Sanitize attribute content to be template-safe */
|
|
1236
1135
|
if (SAFE_FOR_TEMPLATES) {
|
|
1237
|
-
arrayForEach([MUSTACHE_EXPR
|
|
1136
|
+
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
1238
1137
|
value = stringReplace(value, expr, ' ');
|
|
1239
1138
|
});
|
|
1240
1139
|
}
|
|
@@ -1288,7 +1187,7 @@ function createDOMPurify() {
|
|
|
1288
1187
|
*
|
|
1289
1188
|
* @param fragment to iterate over recursively
|
|
1290
1189
|
*/
|
|
1291
|
-
const
|
|
1190
|
+
const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
1292
1191
|
let shadowNode = null;
|
|
1293
1192
|
const shadowIterator = _createNodeIterator(fragment);
|
|
1294
1193
|
/* Execute a hook if present */
|
|
@@ -1302,55 +1201,12 @@ function createDOMPurify() {
|
|
|
1302
1201
|
_sanitizeAttributes(shadowNode);
|
|
1303
1202
|
/* Deep shadow DOM detected */
|
|
1304
1203
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
1305
|
-
|
|
1204
|
+
_sanitizeShadowDOM(shadowNode.content);
|
|
1306
1205
|
}
|
|
1307
1206
|
}
|
|
1308
1207
|
/* Execute a hook if present */
|
|
1309
1208
|
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
|
|
1310
1209
|
};
|
|
1311
|
-
/**
|
|
1312
|
-
* _sanitizeAttachedShadowRoots
|
|
1313
|
-
*
|
|
1314
|
-
* Walks `root` and feeds every attached shadow root we encounter into
|
|
1315
|
-
* the existing _sanitizeShadowDOM pipeline. The default node iterator
|
|
1316
|
-
* does not descend into shadow trees, so nodes inside an attached
|
|
1317
|
-
* shadow root would otherwise be skipped entirely.
|
|
1318
|
-
*
|
|
1319
|
-
* Two real input paths put attached shadow roots in front of us:
|
|
1320
|
-
* 1. IN_PLACE on a DOM node that already has shadow roots attached.
|
|
1321
|
-
* 2. DOM-node input where importNode(dirty, true) deep-clones the
|
|
1322
|
-
* shadow root because it was created with `clonable: true`.
|
|
1323
|
-
*
|
|
1324
|
-
* This pass runs once, up front, so the main iteration loop (and the
|
|
1325
|
-
* existing _sanitizeShadowDOM template-content recursion) stay
|
|
1326
|
-
* untouched — string-input paths are not affected.
|
|
1327
|
-
*
|
|
1328
|
-
* @param root the subtree root to walk for attached shadow roots
|
|
1329
|
-
*/
|
|
1330
|
-
const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
|
|
1331
|
-
if (root.nodeType === NODE_TYPE.element && root.shadowRoot instanceof DocumentFragment) {
|
|
1332
|
-
const sr = root.shadowRoot;
|
|
1333
|
-
// Recurse first so that nested shadow roots are reached even if
|
|
1334
|
-
// _sanitizeShadowDOM removes hosts at this level.
|
|
1335
|
-
_sanitizeAttachedShadowRoots2(sr);
|
|
1336
|
-
_sanitizeShadowDOM2(sr);
|
|
1337
|
-
}
|
|
1338
|
-
// Snapshot children before recursing. Sanitization of one subtree
|
|
1339
|
-
// (e.g. via an uponSanitizeShadowNode hook) may detach siblings,
|
|
1340
|
-
// and naive nextSibling traversal would silently skip the rest of
|
|
1341
|
-
// the list once a node is detached.
|
|
1342
|
-
const childNodes = root.childNodes;
|
|
1343
|
-
if (!childNodes) {
|
|
1344
|
-
return;
|
|
1345
|
-
}
|
|
1346
|
-
const snapshot = [];
|
|
1347
|
-
arrayForEach(childNodes, child => {
|
|
1348
|
-
arrayPush(snapshot, child);
|
|
1349
|
-
});
|
|
1350
|
-
for (const child of snapshot) {
|
|
1351
|
-
_sanitizeAttachedShadowRoots2(child);
|
|
1352
|
-
}
|
|
1353
|
-
};
|
|
1354
1210
|
// eslint-disable-next-line complexity
|
|
1355
1211
|
DOMPurify.sanitize = function (dirty) {
|
|
1356
1212
|
let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
@@ -1367,9 +1223,13 @@ function createDOMPurify() {
|
|
|
1367
1223
|
}
|
|
1368
1224
|
/* Stringify, in case dirty is an object */
|
|
1369
1225
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
1370
|
-
dirty
|
|
1371
|
-
|
|
1372
|
-
|
|
1226
|
+
if (typeof dirty.toString === 'function') {
|
|
1227
|
+
dirty = dirty.toString();
|
|
1228
|
+
if (typeof dirty !== 'string') {
|
|
1229
|
+
throw typeErrorCreate('dirty is not a string, aborting');
|
|
1230
|
+
}
|
|
1231
|
+
} else {
|
|
1232
|
+
throw typeErrorCreate('toString is not a function');
|
|
1373
1233
|
}
|
|
1374
1234
|
}
|
|
1375
1235
|
/* Return dirty HTML if DOMPurify cannot run */
|
|
@@ -1388,16 +1248,12 @@ function createDOMPurify() {
|
|
|
1388
1248
|
}
|
|
1389
1249
|
if (IN_PLACE) {
|
|
1390
1250
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
const tagName = transformCaseFunc(nn);
|
|
1251
|
+
if (dirty.nodeName) {
|
|
1252
|
+
const tagName = transformCaseFunc(dirty.nodeName);
|
|
1394
1253
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1395
1254
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
1396
1255
|
}
|
|
1397
1256
|
}
|
|
1398
|
-
/* Sanitize attached shadow roots before the main iterator runs.
|
|
1399
|
-
The iterator does not descend into shadow trees. */
|
|
1400
|
-
_sanitizeAttachedShadowRoots2(dirty);
|
|
1401
1257
|
} else if (dirty instanceof Node) {
|
|
1402
1258
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
1403
1259
|
elements being stripped by the parser */
|
|
@@ -1412,10 +1268,6 @@ function createDOMPurify() {
|
|
|
1412
1268
|
// eslint-disable-next-line unicorn/prefer-dom-node-append
|
|
1413
1269
|
body.appendChild(importedNode);
|
|
1414
1270
|
}
|
|
1415
|
-
/* Clonable shadow roots are deep-cloned by importNode(); sanitize
|
|
1416
|
-
them before the main iterator runs, since the iterator does not
|
|
1417
|
-
descend into shadow trees. */
|
|
1418
|
-
_sanitizeAttachedShadowRoots2(importedNode);
|
|
1419
1271
|
} else {
|
|
1420
1272
|
/* Exit directly if we have nothing to do */
|
|
1421
1273
|
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
|
|
@@ -1444,7 +1296,7 @@ function createDOMPurify() {
|
|
|
1444
1296
|
_sanitizeAttributes(currentNode);
|
|
1445
1297
|
/* Shadow DOM detected, sanitize it */
|
|
1446
1298
|
if (currentNode.content instanceof DocumentFragment) {
|
|
1447
|
-
|
|
1299
|
+
_sanitizeShadowDOM(currentNode.content);
|
|
1448
1300
|
}
|
|
1449
1301
|
}
|
|
1450
1302
|
/* If we sanitized `dirty` in-place, return it. */
|
|
@@ -1453,14 +1305,6 @@ function createDOMPurify() {
|
|
|
1453
1305
|
}
|
|
1454
1306
|
/* Return sanitized string or DOM */
|
|
1455
1307
|
if (RETURN_DOM) {
|
|
1456
|
-
if (SAFE_FOR_TEMPLATES) {
|
|
1457
|
-
body.normalize();
|
|
1458
|
-
let html = body.innerHTML;
|
|
1459
|
-
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
1460
|
-
html = stringReplace(html, expr, ' ');
|
|
1461
|
-
});
|
|
1462
|
-
body.innerHTML = html;
|
|
1463
|
-
}
|
|
1464
1308
|
if (RETURN_DOM_FRAGMENT) {
|
|
1465
1309
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
1466
1310
|
while (body.firstChild) {
|
|
@@ -1489,7 +1333,7 @@ function createDOMPurify() {
|
|
|
1489
1333
|
}
|
|
1490
1334
|
/* Sanitize final string template-safe */
|
|
1491
1335
|
if (SAFE_FOR_TEMPLATES) {
|
|
1492
|
-
arrayForEach([MUSTACHE_EXPR
|
|
1336
|
+
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
1493
1337
|
serializedHTML = stringReplace(serializedHTML, expr, ' ');
|
|
1494
1338
|
});
|
|
1495
1339
|
}
|