@touchvue/chat 1.0.0-beta.51 → 1.0.0-beta.53

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.
Files changed (143) hide show
  1. package/README.md +70 -70
  2. package/es/node_modules/.pnpm/{dompurify@3.4.3 → dompurify@3.3.0}/node_modules/dompurify/dist/purify.es.mjs +143 -299
  3. package/es/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.mjs.map +1 -0
  4. package/es/package.json.css +1 -1
  5. package/es/package.json.mjs +1 -1
  6. package/es/packages/components/resolver.mjs.map +1 -1
  7. package/es/packages/components/touchchat/component/AiRobot/HelloChat.vue2.mjs.map +1 -1
  8. package/es/packages/components/touchchat/component/AiRobot/letter.vue.mjs +1 -1
  9. package/es/packages/components/touchchat/component/AiRobot/letter.vue2.mjs +9 -9
  10. package/es/packages/components/touchchat/component/AiRobot/letter.vue2.mjs.map +1 -1
  11. package/es/packages/components/touchchat/component/FileContent.vue2.mjs +3 -3
  12. package/es/packages/components/touchchat/component/FileContent.vue2.mjs.map +1 -1
  13. package/es/packages/components/touchchat/component/FileView.vue2.mjs +45 -15
  14. package/es/packages/components/touchchat/component/FileView.vue2.mjs.map +1 -1
  15. package/es/packages/components/touchchat/component/HelloChat.vue2.mjs.map +1 -1
  16. package/es/packages/components/touchchat/component/ImageFile.vue2.mjs +6 -6
  17. package/es/packages/components/touchchat/component/ImageFile.vue2.mjs.map +1 -1
  18. package/es/packages/components/touchchat/component/ImageView.vue2.mjs +1 -1
  19. package/es/packages/components/touchchat/component/ImageView.vue2.mjs.map +1 -1
  20. package/es/packages/components/touchchat/component/LinkView.vue2.mjs +4 -4
  21. package/es/packages/components/touchchat/component/LinkView.vue2.mjs.map +1 -1
  22. package/es/packages/components/touchchat/component/MarkLayer.vue2.mjs +1 -1
  23. package/es/packages/components/touchchat/component/MarkLayer.vue2.mjs.map +1 -1
  24. package/es/packages/components/touchchat/component/ModuleSelect.vue2.mjs +2 -2
  25. package/es/packages/components/touchchat/component/ModuleSelect.vue2.mjs.map +1 -1
  26. package/es/packages/components/touchchat/component/PDFFile.vue2.mjs +10 -10
  27. package/es/packages/components/touchchat/component/PDFFile.vue2.mjs.map +1 -1
  28. package/es/packages/components/touchchat/component/QuoteContent.vue2.mjs.map +1 -1
  29. package/es/packages/components/touchchat/component/RealtimeVoice.vue2.mjs +1 -1
  30. package/es/packages/components/touchchat/component/RealtimeVoice.vue2.mjs.map +1 -1
  31. package/es/packages/components/touchchat/component/UploadView.vue2.mjs.map +1 -1
  32. package/es/packages/components/touchchat/component/VideoFile.vue.mjs +1 -1
  33. package/es/packages/components/touchchat/component/VideoFile.vue2.mjs.map +1 -1
  34. package/es/packages/components/touchchat/src/AiChat/AgentsView.vue2.mjs +1 -1
  35. package/es/packages/components/touchchat/src/AiChat/AgentsView.vue2.mjs.map +1 -1
  36. package/es/packages/components/touchchat/src/AiChat/AiMessage.vue2.mjs +30 -30
  37. package/es/packages/components/touchchat/src/AiChat/AiMessage.vue2.mjs.map +1 -1
  38. package/es/packages/components/touchchat/src/AiChat/Chat/scriptMatcher.mjs.map +1 -1
  39. package/es/packages/components/touchchat/src/AiChat/Chat/types.mjs.map +1 -1
  40. package/es/packages/components/touchchat/src/AiChat/Chat/useChat.mjs +6 -0
  41. package/es/packages/components/touchchat/src/AiChat/Chat/useChat.mjs.map +1 -1
  42. package/es/packages/components/touchchat/src/AiChat/Chat/useCopy.mjs.map +1 -1
  43. package/es/packages/components/touchchat/src/AiChat/Chat/useMessageRender.mjs +1 -1
  44. package/es/packages/components/touchchat/src/AiChat/Chat/useMessageRender.mjs.map +1 -1
  45. package/es/packages/components/touchchat/src/AiChat/Chat/useSSE.mjs +93 -4
  46. package/es/packages/components/touchchat/src/AiChat/Chat/useSSE.mjs.map +1 -1
  47. package/es/packages/components/touchchat/src/AiChat/ChatInput.vue2.mjs +5 -5
  48. package/es/packages/components/touchchat/src/AiChat/ChatInput.vue2.mjs.map +1 -1
  49. package/es/packages/components/touchchat/src/AiChat/HistoryList.vue2.mjs +1 -1
  50. package/es/packages/components/touchchat/src/AiChat/HistoryList.vue2.mjs.map +1 -1
  51. package/es/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.mjs +3 -3
  52. package/es/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.mjs.map +1 -1
  53. package/es/packages/components/touchchat/src/AiChat/MessageActions.vue2.mjs +11 -11
  54. package/es/packages/components/touchchat/src/AiChat/MessageActions.vue2.mjs.map +1 -1
  55. package/es/packages/components/touchchat/src/AiChat/SiderBarView.vue2.mjs +3 -3
  56. package/es/packages/components/touchchat/src/AiChat/SiderBarView.vue2.mjs.map +1 -1
  57. package/es/packages/components/touchchat/src/AiChat/TouchAgent.vue2.mjs +1 -1
  58. package/es/packages/components/touchchat/src/AiChat/TouchChat.vue2.mjs.map +1 -1
  59. package/es/packages/components/touchchat/src/AiChat/TouchHistory.vue2.mjs.map +1 -1
  60. package/es/packages/components/touchchat/src/AiChat/UserMessage.vue2.mjs +16 -16
  61. package/es/packages/components/touchchat/src/AiChat/UserMessage.vue2.mjs.map +1 -1
  62. package/es/packages/components/touchchat/src/index.vue2.mjs +4 -1
  63. package/es/packages/components/touchchat/src/index.vue2.mjs.map +1 -1
  64. package/es/packages/components/touchchat/utils/a2aService.mjs.map +1 -1
  65. package/es/packages/components/touchchat/utils/fetchStream.mjs.map +1 -1
  66. package/es/packages/components/touchchat/utils/markdown.mjs +1 -1
  67. package/lib/node_modules/.pnpm/{dompurify@3.4.3 → dompurify@3.3.0}/node_modules/dompurify/dist/purify.es.js +143 -299
  68. package/lib/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.js.map +1 -0
  69. package/lib/package.json.css +1 -1
  70. package/lib/package.json.js +1 -1
  71. package/lib/packages/components/resolver.js.map +1 -1
  72. package/lib/packages/components/touchchat/component/AiRobot/HelloChat.vue2.js.map +1 -1
  73. package/lib/packages/components/touchchat/component/AiRobot/letter.vue.js +1 -1
  74. package/lib/packages/components/touchchat/component/AiRobot/letter.vue2.js +9 -9
  75. package/lib/packages/components/touchchat/component/AiRobot/letter.vue2.js.map +1 -1
  76. package/lib/packages/components/touchchat/component/FileContent.vue2.js +3 -3
  77. package/lib/packages/components/touchchat/component/FileContent.vue2.js.map +1 -1
  78. package/lib/packages/components/touchchat/component/FileView.vue2.js +44 -14
  79. package/lib/packages/components/touchchat/component/FileView.vue2.js.map +1 -1
  80. package/lib/packages/components/touchchat/component/HelloChat.vue2.js.map +1 -1
  81. package/lib/packages/components/touchchat/component/ImageFile.vue2.js +6 -6
  82. package/lib/packages/components/touchchat/component/ImageFile.vue2.js.map +1 -1
  83. package/lib/packages/components/touchchat/component/ImageView.vue2.js +1 -1
  84. package/lib/packages/components/touchchat/component/ImageView.vue2.js.map +1 -1
  85. package/lib/packages/components/touchchat/component/LinkView.vue2.js +4 -4
  86. package/lib/packages/components/touchchat/component/LinkView.vue2.js.map +1 -1
  87. package/lib/packages/components/touchchat/component/MarkLayer.vue2.js +1 -1
  88. package/lib/packages/components/touchchat/component/MarkLayer.vue2.js.map +1 -1
  89. package/lib/packages/components/touchchat/component/ModuleSelect.vue2.js +2 -2
  90. package/lib/packages/components/touchchat/component/ModuleSelect.vue2.js.map +1 -1
  91. package/lib/packages/components/touchchat/component/PDFFile.vue2.js +10 -10
  92. package/lib/packages/components/touchchat/component/PDFFile.vue2.js.map +1 -1
  93. package/lib/packages/components/touchchat/component/QuoteContent.vue2.js.map +1 -1
  94. package/lib/packages/components/touchchat/component/RealtimeVoice.vue2.js +1 -1
  95. package/lib/packages/components/touchchat/component/RealtimeVoice.vue2.js.map +1 -1
  96. package/lib/packages/components/touchchat/component/UploadView.vue2.js.map +1 -1
  97. package/lib/packages/components/touchchat/component/VideoFile.vue.js +1 -1
  98. package/lib/packages/components/touchchat/component/VideoFile.vue2.js.map +1 -1
  99. package/lib/packages/components/touchchat/src/AiChat/AgentsView.vue2.js +1 -1
  100. package/lib/packages/components/touchchat/src/AiChat/AgentsView.vue2.js.map +1 -1
  101. package/lib/packages/components/touchchat/src/AiChat/AiMessage.vue2.js +30 -30
  102. package/lib/packages/components/touchchat/src/AiChat/AiMessage.vue2.js.map +1 -1
  103. package/lib/packages/components/touchchat/src/AiChat/Chat/scriptMatcher.js.map +1 -1
  104. package/lib/packages/components/touchchat/src/AiChat/Chat/types.js.map +1 -1
  105. package/lib/packages/components/touchchat/src/AiChat/Chat/useChat.js +6 -0
  106. package/lib/packages/components/touchchat/src/AiChat/Chat/useChat.js.map +1 -1
  107. package/lib/packages/components/touchchat/src/AiChat/Chat/useCopy.js.map +1 -1
  108. package/lib/packages/components/touchchat/src/AiChat/Chat/useMessageRender.js +1 -1
  109. package/lib/packages/components/touchchat/src/AiChat/Chat/useMessageRender.js.map +1 -1
  110. package/lib/packages/components/touchchat/src/AiChat/Chat/useSSE.js +93 -4
  111. package/lib/packages/components/touchchat/src/AiChat/Chat/useSSE.js.map +1 -1
  112. package/lib/packages/components/touchchat/src/AiChat/ChatInput.vue2.js +5 -5
  113. package/lib/packages/components/touchchat/src/AiChat/ChatInput.vue2.js.map +1 -1
  114. package/lib/packages/components/touchchat/src/AiChat/HistoryList.vue2.js +1 -1
  115. package/lib/packages/components/touchchat/src/AiChat/HistoryList.vue2.js.map +1 -1
  116. package/lib/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.js +3 -3
  117. package/lib/packages/components/touchchat/src/AiChat/HistorySidebar.vue2.js.map +1 -1
  118. package/lib/packages/components/touchchat/src/AiChat/MessageActions.vue2.js +11 -11
  119. package/lib/packages/components/touchchat/src/AiChat/MessageActions.vue2.js.map +1 -1
  120. package/lib/packages/components/touchchat/src/AiChat/SiderBarView.vue2.js +3 -3
  121. package/lib/packages/components/touchchat/src/AiChat/SiderBarView.vue2.js.map +1 -1
  122. package/lib/packages/components/touchchat/src/AiChat/TouchAgent.vue2.js +1 -1
  123. package/lib/packages/components/touchchat/src/AiChat/TouchChat.vue2.js.map +1 -1
  124. package/lib/packages/components/touchchat/src/AiChat/TouchHistory.vue2.js.map +1 -1
  125. package/lib/packages/components/touchchat/src/AiChat/UserMessage.vue2.js +16 -16
  126. package/lib/packages/components/touchchat/src/AiChat/UserMessage.vue2.js.map +1 -1
  127. package/lib/packages/components/touchchat/src/index.vue2.js +4 -1
  128. package/lib/packages/components/touchchat/src/index.vue2.js.map +1 -1
  129. package/lib/packages/components/touchchat/utils/a2aService.js.map +1 -1
  130. package/lib/packages/components/touchchat/utils/fetchStream.js.map +1 -1
  131. package/lib/packages/components/touchchat/utils/markdown.js +1 -1
  132. package/package.json +83 -83
  133. package/theme/components/index.css +76 -10
  134. package/theme/font/iconfont.woff +0 -0
  135. package/theme/font/iconfont.woff2 +0 -0
  136. package/theme/index.css +76 -10
  137. package/theme/skin/default.css +76 -10
  138. package/es/node_modules/.pnpm/dompurify@3.4.3/node_modules/dompurify/dist/purify.es.mjs.map +0 -1
  139. package/es/packages/components/touchchat/img/file.png.mjs +0 -4
  140. package/es/packages/components/touchchat/img/file.png.mjs.map +0 -1
  141. package/lib/node_modules/.pnpm/dompurify@3.4.3/node_modules/dompurify/dist/purify.es.js.map +0 -1
  142. package/lib/packages/components/touchchat/img/file.png.js +0 -8
  143. package/lib/packages/components/touchchat/img/file.png.js.map +0 -1
@@ -1,62 +1,21 @@
1
- /*! @license DOMPurify 3.4.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.3/LICENSE */
1
+ /*! @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 */
2
2
 
3
- function _arrayLikeToArray(r, a) {
4
- (null == a || a > r.length) && (a = r.length);
5
- for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
6
- return n;
7
- }
8
- function _arrayWithHoles(r) {
9
- if (Array.isArray(r)) return r;
10
- }
11
- function _iterableToArrayLimit(r, l) {
12
- var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
13
- if (null != t) {
14
- var e,
15
- n,
16
- i,
17
- u,
18
- a = [],
19
- f = true,
20
- o = false;
21
- try {
22
- 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);
23
- } catch (r) {
24
- o = true, n = r;
25
- } finally {
26
- try {
27
- if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
28
- } finally {
29
- if (o) throw n;
30
- }
31
- }
32
- return a;
33
- }
34
- }
35
- function _nonIterableRest() {
36
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
37
- }
38
- function _slicedToArray(r, e) {
39
- return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
40
- }
41
- function _unsupportedIterableToArray(r, a) {
42
- if (r) {
43
- if ("string" == typeof r) return _arrayLikeToArray(r, a);
44
- var t = {}.toString.call(r).slice(8, -1);
45
- 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;
46
- }
47
- }
48
-
49
- const entries = Object.entries,
50
- setPrototypeOf = Object.setPrototypeOf,
51
- isFrozen = Object.isFrozen,
52
- getPrototypeOf = Object.getPrototypeOf,
53
- getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
54
- let freeze = Object.freeze,
55
- seal = Object.seal,
56
- create = Object.create; // eslint-disable-line import/no-mutable-exports
57
- let _ref = typeof Reflect !== 'undefined' && Reflect,
58
- apply = _ref.apply,
59
- construct = _ref.construct;
3
+ const {
4
+ entries,
5
+ setPrototypeOf,
6
+ isFrozen,
7
+ getPrototypeOf,
8
+ getOwnPropertyDescriptor
9
+ } = Object;
10
+ let {
11
+ freeze,
12
+ seal,
13
+ create
14
+ } = Object; // eslint-disable-line import/no-mutable-exports
15
+ let {
16
+ apply,
17
+ construct
18
+ } = typeof Reflect !== 'undefined' && Reflect;
60
19
  if (!freeze) {
61
20
  freeze = function freeze(x) {
62
21
  return x;
@@ -88,19 +47,13 @@ const arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
88
47
  const arrayPop = unapply(Array.prototype.pop);
89
48
  const arrayPush = unapply(Array.prototype.push);
90
49
  const arraySplice = unapply(Array.prototype.splice);
91
- const arrayIsArray = Array.isArray;
92
50
  const stringToLowerCase = unapply(String.prototype.toLowerCase);
93
51
  const stringToString = unapply(String.prototype.toString);
94
52
  const stringMatch = unapply(String.prototype.match);
95
53
  const stringReplace = unapply(String.prototype.replace);
96
54
  const stringIndexOf = unapply(String.prototype.indexOf);
97
55
  const stringTrim = unapply(String.prototype.trim);
98
- const numberToString = unapply(Number.prototype.toString);
99
- const booleanToString = unapply(Boolean.prototype.toString);
100
- const bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);
101
- const symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);
102
56
  const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
103
- const objectToString = unapply(Object.prototype.toString);
104
57
  const regExpTest = unapply(RegExp.prototype.test);
105
58
  const typeErrorCreate = unconstruct(TypeError);
106
59
  /**
@@ -150,9 +103,6 @@ function addToSet(set, array) {
150
103
  // Prevent prototype setters from intercepting set as a this value.
151
104
  setPrototypeOf(set, null);
152
105
  }
153
- if (!arrayIsArray(array)) {
154
- return set;
155
- }
156
106
  let l = array.length;
157
107
  while (l--) {
158
108
  let element = array[l];
@@ -193,13 +143,10 @@ function cleanArray(array) {
193
143
  */
194
144
  function clone(object) {
195
145
  const newObject = create(null);
196
- for (const _ref2 of entries(object)) {
197
- var _ref3 = _slicedToArray(_ref2, 2);
198
- const property = _ref3[0];
199
- const value = _ref3[1];
146
+ for (const [property, value] of entries(object)) {
200
147
  const isPropertyExist = objectHasOwnProperty(object, property);
201
148
  if (isPropertyExist) {
202
- if (arrayIsArray(value)) {
149
+ if (Array.isArray(value)) {
203
150
  newObject[property] = cleanArray(value);
204
151
  } else if (value && typeof value === 'object' && value.constructor === Object) {
205
152
  newObject[property] = clone(value);
@@ -210,58 +157,6 @@ function clone(object) {
210
157
  }
211
158
  return newObject;
212
159
  }
213
- /**
214
- * Convert non-node values into strings without depending on direct property access.
215
- *
216
- * @param value - The value to stringify.
217
- * @returns A string representation of the provided value.
218
- */
219
- function stringifyValue(value) {
220
- switch (typeof value) {
221
- case 'string':
222
- {
223
- return value;
224
- }
225
- case 'number':
226
- {
227
- return numberToString(value);
228
- }
229
- case 'boolean':
230
- {
231
- return booleanToString(value);
232
- }
233
- case 'bigint':
234
- {
235
- return bigintToString ? bigintToString(value) : '0';
236
- }
237
- case 'symbol':
238
- {
239
- return symbolToString ? symbolToString(value) : 'Symbol()';
240
- }
241
- case 'undefined':
242
- {
243
- return objectToString(value);
244
- }
245
- case 'function':
246
- case 'object':
247
- {
248
- if (value === null) {
249
- return objectToString(value);
250
- }
251
- const valueAsRecord = value;
252
- const valueToString = lookupGetter(valueAsRecord, 'toString');
253
- if (typeof valueToString === 'function') {
254
- const stringified = valueToString(valueAsRecord);
255
- return typeof stringified === 'string' ? stringified : objectToString(stringified);
256
- }
257
- return objectToString(value);
258
- }
259
- default:
260
- {
261
- return objectToString(value);
262
- }
263
- }
264
- }
265
160
  /**
266
161
  * This method automatically checks if the prop is function or getter and behaves accordingly.
267
162
  *
@@ -287,14 +182,6 @@ function lookupGetter(object, prop) {
287
182
  }
288
183
  return fallbackValue;
289
184
  }
290
- function isRegex(value) {
291
- try {
292
- regExpTest(value, '');
293
- return true;
294
- } catch (_unused) {
295
- return false;
296
- }
297
- }
298
185
 
299
186
  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']);
300
187
  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']);
@@ -310,14 +197,15 @@ const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mgly
310
197
  const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
311
198
  const text = freeze(['#text']);
312
199
 
313
- 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']);
200
+ 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']);
314
201
  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']);
315
- const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', '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']);
202
+ 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']);
316
203
  const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
317
204
 
318
- const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
319
- const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
320
- const TMPLIT_EXPR = seal(/\${[\w\W]*/g);
205
+ // eslint-disable-next-line unicorn/better-regex
206
+ const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
207
+ const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
208
+ const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
321
209
  const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
322
210
  const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
323
211
  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
@@ -328,15 +216,38 @@ const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205
328
216
  const DOCTYPE_NAME = seal(/^html$/i);
329
217
  const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
330
218
 
219
+ var EXPRESSIONS = /*#__PURE__*/Object.freeze({
220
+ __proto__: null,
221
+ ARIA_ATTR: ARIA_ATTR,
222
+ ATTR_WHITESPACE: ATTR_WHITESPACE,
223
+ CUSTOM_ELEMENT: CUSTOM_ELEMENT,
224
+ DATA_ATTR: DATA_ATTR,
225
+ DOCTYPE_NAME: DOCTYPE_NAME,
226
+ ERB_EXPR: ERB_EXPR,
227
+ IS_ALLOWED_URI: IS_ALLOWED_URI,
228
+ IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
229
+ MUSTACHE_EXPR: MUSTACHE_EXPR,
230
+ TMPLIT_EXPR: TMPLIT_EXPR
231
+ });
232
+
331
233
  /* eslint-disable @typescript-eslint/indent */
332
234
  // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
333
235
  const NODE_TYPE = {
334
236
  element: 1,
237
+ attribute: 2,
335
238
  text: 3,
239
+ cdataSection: 4,
240
+ entityReference: 5,
241
+ // Deprecated
242
+ entityNode: 6,
336
243
  // Deprecated
337
244
  progressingInstruction: 7,
338
245
  comment: 8,
339
- document: 9};
246
+ document: 9,
247
+ documentType: 10,
248
+ documentFragment: 11,
249
+ notation: 12 // Deprecated
250
+ };
340
251
  const getGlobal = function getGlobal() {
341
252
  return typeof window === 'undefined' ? null : window;
342
253
  };
@@ -394,7 +305,7 @@ const _createHooksMap = function _createHooksMap() {
394
305
  function createDOMPurify() {
395
306
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
396
307
  const DOMPurify = root => createDOMPurify(root);
397
- DOMPurify.version = '3.4.3';
308
+ DOMPurify.version = '3.3.0';
398
309
  DOMPurify.removed = [];
399
310
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
400
311
  // Not running in a browser, provide a factory function
@@ -402,19 +313,22 @@ function createDOMPurify() {
402
313
  DOMPurify.isSupported = false;
403
314
  return DOMPurify;
404
315
  }
405
- let document = window.document;
316
+ let {
317
+ document
318
+ } = window;
406
319
  const originalDocument = document;
407
320
  const currentScript = originalDocument.currentScript;
408
- const DocumentFragment = window.DocumentFragment,
409
- HTMLTemplateElement = window.HTMLTemplateElement,
410
- Node = window.Node,
411
- Element = window.Element,
412
- NodeFilter = window.NodeFilter,
413
- _window$NamedNodeMap = window.NamedNodeMap,
414
- NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
415
- HTMLFormElement = window.HTMLFormElement,
416
- DOMParser = window.DOMParser,
417
- trustedTypes = window.trustedTypes;
321
+ const {
322
+ DocumentFragment,
323
+ HTMLTemplateElement,
324
+ Node,
325
+ Element,
326
+ NodeFilter,
327
+ NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
328
+ HTMLFormElement,
329
+ DOMParser,
330
+ trustedTypes
331
+ } = window;
418
332
  const ElementPrototype = Element.prototype;
419
333
  const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
420
334
  const remove = lookupGetter(ElementPrototype, 'remove');
@@ -435,26 +349,33 @@ function createDOMPurify() {
435
349
  }
436
350
  let trustedTypesPolicy;
437
351
  let emptyHTML = '';
438
- const _document = document,
439
- implementation = _document.implementation,
440
- createNodeIterator = _document.createNodeIterator,
441
- createDocumentFragment = _document.createDocumentFragment,
442
- getElementsByTagName = _document.getElementsByTagName;
443
- const importNode = originalDocument.importNode;
352
+ const {
353
+ implementation,
354
+ createNodeIterator,
355
+ createDocumentFragment,
356
+ getElementsByTagName
357
+ } = document;
358
+ const {
359
+ importNode
360
+ } = originalDocument;
444
361
  let hooks = _createHooksMap();
445
362
  /**
446
363
  * Expose whether this browser supports running the full DOMPurify.
447
364
  */
448
365
  DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
449
- const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
450
- ERB_EXPR$1 = ERB_EXPR,
451
- TMPLIT_EXPR$1 = TMPLIT_EXPR,
452
- DATA_ATTR$1 = DATA_ATTR,
453
- ARIA_ATTR$1 = ARIA_ATTR,
454
- IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
455
- ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
456
- CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
457
- let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
366
+ const {
367
+ MUSTACHE_EXPR,
368
+ ERB_EXPR,
369
+ TMPLIT_EXPR,
370
+ DATA_ATTR,
371
+ ARIA_ATTR,
372
+ IS_SCRIPT_OR_DATA,
373
+ ATTR_WHITESPACE,
374
+ CUSTOM_ELEMENT
375
+ } = EXPRESSIONS;
376
+ let {
377
+ IS_ALLOWED_URI: IS_ALLOWED_URI$1
378
+ } = EXPRESSIONS;
458
379
  /**
459
380
  * We consider the elements and attributes below to be safe. Ideally
460
381
  * don't add any new ones but feel free to remove unwanted ones.
@@ -632,15 +553,15 @@ function createDOMPurify() {
632
553
  // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
633
554
  transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
634
555
  /* Set configuration parameters */
635
- ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') && arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
636
- ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
637
- ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') && arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
638
- URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR) ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
639
- DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') && arrayIsArray(cfg.ADD_DATA_URI_TAGS) ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
640
- FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
641
- FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') && arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
642
- FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
643
- USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === 'object' ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
556
+ ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
557
+ ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
558
+ ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
559
+ 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;
560
+ 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;
561
+ FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
562
+ FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
563
+ FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
564
+ USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
644
565
  ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
645
566
  ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
646
567
  ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
@@ -656,20 +577,19 @@ function createDOMPurify() {
656
577
  SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
657
578
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
658
579
  IN_PLACE = cfg.IN_PLACE || false; // Default false
659
- IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; // Default regexp
660
- NAMESPACE = typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace
661
- MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'MATHML_TEXT_INTEGRATION_POINTS') && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === 'object' ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']); // Default built-in map
662
- HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'HTML_INTEGRATION_POINTS') && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === 'object' ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, ['annotation-xml']); // Default built-in map
663
- const customElementHandling = objectHasOwnProperty(cfg, 'CUSTOM_ELEMENT_HANDLING') && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === 'object' ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
664
- CUSTOM_ELEMENT_HANDLING = create(null);
665
- if (objectHasOwnProperty(customElementHandling, 'tagNameCheck') && isRegexOrFunction(customElementHandling.tagNameCheck)) {
666
- CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined
580
+ IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
581
+ NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
582
+ MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
583
+ HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
584
+ CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
585
+ if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
586
+ CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
667
587
  }
668
- if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
669
- CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined
588
+ if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
589
+ CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
670
590
  }
671
- if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') && typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {
672
- CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined
591
+ if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
592
+ CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
673
593
  }
674
594
  if (SAFE_FOR_TEMPLATES) {
675
595
  ALLOW_DATA_ATTR = false;
@@ -680,7 +600,7 @@ function createDOMPurify() {
680
600
  /* Parse profile info */
681
601
  if (USE_PROFILES) {
682
602
  ALLOWED_TAGS = addToSet({}, text);
683
- ALLOWED_ATTR = create(null);
603
+ ALLOWED_ATTR = [];
684
604
  if (USE_PROFILES.html === true) {
685
605
  addToSet(ALLOWED_TAGS, html$1);
686
606
  addToSet(ALLOWED_ATTR, html);
@@ -701,46 +621,36 @@ function createDOMPurify() {
701
621
  addToSet(ALLOWED_ATTR, xml);
702
622
  }
703
623
  }
704
- /* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
705
- * leaking across calls when switching from function to array config */
706
- EXTRA_ELEMENT_HANDLING.tagCheck = null;
707
- EXTRA_ELEMENT_HANDLING.attributeCheck = null;
708
624
  /* Merge configuration parameters */
709
- if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {
625
+ if (cfg.ADD_TAGS) {
710
626
  if (typeof cfg.ADD_TAGS === 'function') {
711
627
  EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
712
- } else if (arrayIsArray(cfg.ADD_TAGS)) {
628
+ } else {
713
629
  if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
714
630
  ALLOWED_TAGS = clone(ALLOWED_TAGS);
715
631
  }
716
632
  addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
717
633
  }
718
634
  }
719
- if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {
635
+ if (cfg.ADD_ATTR) {
720
636
  if (typeof cfg.ADD_ATTR === 'function') {
721
637
  EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
722
- } else if (arrayIsArray(cfg.ADD_ATTR)) {
638
+ } else {
723
639
  if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
724
640
  ALLOWED_ATTR = clone(ALLOWED_ATTR);
725
641
  }
726
642
  addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
727
643
  }
728
644
  }
729
- if (objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
645
+ if (cfg.ADD_URI_SAFE_ATTR) {
730
646
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
731
647
  }
732
- if (objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS)) {
648
+ if (cfg.FORBID_CONTENTS) {
733
649
  if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
734
650
  FORBID_CONTENTS = clone(FORBID_CONTENTS);
735
651
  }
736
652
  addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
737
653
  }
738
- if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
739
- if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
740
- FORBID_CONTENTS = clone(FORBID_CONTENTS);
741
- }
742
- addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
743
- }
744
654
  /* Add #text in case KEEP_CONTENT is set to true */
745
655
  if (KEEP_CONTENT) {
746
656
  ALLOWED_TAGS['#text'] = true;
@@ -1027,11 +937,6 @@ function createDOMPurify() {
1027
937
  _forceRemove(currentNode);
1028
938
  return true;
1029
939
  }
1030
- /* Remove risky CSS construction leading to mXSS */
1031
- if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
1032
- _forceRemove(currentNode);
1033
- return true;
1034
- }
1035
940
  /* Remove any occurrence of processing instructions */
1036
941
  if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
1037
942
  _forceRemove(currentNode);
@@ -1043,7 +948,7 @@ function createDOMPurify() {
1043
948
  return true;
1044
949
  }
1045
950
  /* Remove element if anything forbids its presence */
1046
- if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
951
+ if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])) {
1047
952
  /* Check if we have a custom element to handle */
1048
953
  if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
1049
954
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
@@ -1061,6 +966,7 @@ function createDOMPurify() {
1061
966
  const childCount = childNodes.length;
1062
967
  for (let i = childCount - 1; i >= 0; --i) {
1063
968
  const childClone = cloneNode(childNodes[i], true);
969
+ childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
1064
970
  parentNode.insertBefore(childClone, getNextSibling(currentNode));
1065
971
  }
1066
972
  }
@@ -1082,7 +988,7 @@ function createDOMPurify() {
1082
988
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
1083
989
  /* Get the element's text content */
1084
990
  content = currentNode.textContent;
1085
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
991
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
1086
992
  content = stringReplace(content, expr, ' ');
1087
993
  });
1088
994
  if (currentNode.textContent !== content) {
@@ -1106,20 +1012,15 @@ function createDOMPurify() {
1106
1012
  */
1107
1013
  // eslint-disable-next-line complexity
1108
1014
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1109
- /* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
1110
- if (FORBID_ATTR[lcName]) {
1111
- return false;
1112
- }
1113
1015
  /* Make sure attribute cannot clobber */
1114
1016
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1115
1017
  return false;
1116
1018
  }
1117
- const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
1118
1019
  /* Allow valid data-* attributes: At least one character after "-"
1119
1020
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1120
1021
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1121
1022
  We don't need to check the value; it's always URI safe. */
1122
- if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ; else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
1023
+ 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]) {
1123
1024
  if (
1124
1025
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1125
1026
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
@@ -1131,15 +1032,11 @@ function createDOMPurify() {
1131
1032
  return false;
1132
1033
  }
1133
1034
  /* Check value is safe. First, is attr inert? If so, is safe */
1134
- } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if (value) {
1035
+ } 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) {
1135
1036
  return false;
1136
1037
  } else ;
1137
1038
  return true;
1138
1039
  };
1139
- /* Names the HTML spec reserves from valid-custom-element-name; these must
1140
- * never be treated as basic custom elements even when a permissive
1141
- * CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */
1142
- 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']);
1143
1040
  /**
1144
1041
  * _isBasicCustomElement
1145
1042
  * checks if at least one dash is included in tagName, and it's not the first char
@@ -1149,7 +1046,7 @@ function createDOMPurify() {
1149
1046
  * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
1150
1047
  */
1151
1048
  const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
1152
- return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
1049
+ return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);
1153
1050
  };
1154
1051
  /**
1155
1052
  * _sanitizeAttributes
@@ -1164,7 +1061,9 @@ function createDOMPurify() {
1164
1061
  const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1165
1062
  /* Execute a hook if present */
1166
1063
  _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
1167
- const attributes = currentNode.attributes;
1064
+ const {
1065
+ attributes
1066
+ } = currentNode;
1168
1067
  /* Check if we have attributes; if not we might have a text node */
1169
1068
  if (!attributes || _isClobbered(currentNode)) {
1170
1069
  return;
@@ -1180,9 +1079,11 @@ function createDOMPurify() {
1180
1079
  /* Go backwards over all attributes; safely remove bad ones */
1181
1080
  while (l--) {
1182
1081
  const attr = attributes[l];
1183
- const name = attr.name,
1184
- namespaceURI = attr.namespaceURI,
1185
- attrValue = attr.value;
1082
+ const {
1083
+ name,
1084
+ namespaceURI,
1085
+ value: attrValue
1086
+ } = attr;
1186
1087
  const lcName = transformCaseFunc(name);
1187
1088
  const initValue = attrValue;
1188
1089
  let value = name === 'value' ? initValue : stringTrim(initValue);
@@ -1196,16 +1097,14 @@ function createDOMPurify() {
1196
1097
  /* Full DOM Clobbering protection via namespace isolation,
1197
1098
  * Prefix id and name attributes with `user-content-`
1198
1099
  */
1199
- if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name') && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
1100
+ if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
1200
1101
  // Remove the attribute with this value
1201
1102
  _removeAttribute(name, currentNode);
1202
1103
  // Prefix the value and later re-create the attribute with the sanitized value
1203
1104
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
1204
1105
  }
1205
- // Else: already prefixed, leave the attribute alone — the prefix is
1206
- // itself the clobbering protection, and re-applying it is incorrect.
1207
1106
  /* Work around a security issue with comments inside attributes */
1208
- if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
1107
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title|textarea)/i, value)) {
1209
1108
  _removeAttribute(name, currentNode);
1210
1109
  continue;
1211
1110
  }
@@ -1230,7 +1129,7 @@ function createDOMPurify() {
1230
1129
  }
1231
1130
  /* Sanitize attribute content to be template-safe */
1232
1131
  if (SAFE_FOR_TEMPLATES) {
1233
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
1132
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
1234
1133
  value = stringReplace(value, expr, ' ');
1235
1134
  });
1236
1135
  }
@@ -1284,7 +1183,7 @@ function createDOMPurify() {
1284
1183
  *
1285
1184
  * @param fragment to iterate over recursively
1286
1185
  */
1287
- const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
1186
+ const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1288
1187
  let shadowNode = null;
1289
1188
  const shadowIterator = _createNodeIterator(fragment);
1290
1189
  /* Execute a hook if present */
@@ -1298,55 +1197,12 @@ function createDOMPurify() {
1298
1197
  _sanitizeAttributes(shadowNode);
1299
1198
  /* Deep shadow DOM detected */
1300
1199
  if (shadowNode.content instanceof DocumentFragment) {
1301
- _sanitizeShadowDOM2(shadowNode.content);
1200
+ _sanitizeShadowDOM(shadowNode.content);
1302
1201
  }
1303
1202
  }
1304
1203
  /* Execute a hook if present */
1305
1204
  _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
1306
1205
  };
1307
- /**
1308
- * _sanitizeAttachedShadowRoots
1309
- *
1310
- * Walks `root` and feeds every attached shadow root we encounter into
1311
- * the existing _sanitizeShadowDOM pipeline. The default node iterator
1312
- * does not descend into shadow trees, so nodes inside an attached
1313
- * shadow root would otherwise be skipped entirely.
1314
- *
1315
- * Two real input paths put attached shadow roots in front of us:
1316
- * 1. IN_PLACE on a DOM node that already has shadow roots attached.
1317
- * 2. DOM-node input where importNode(dirty, true) deep-clones the
1318
- * shadow root because it was created with `clonable: true`.
1319
- *
1320
- * This pass runs once, up front, so the main iteration loop (and the
1321
- * existing _sanitizeShadowDOM template-content recursion) stay
1322
- * untouched — string-input paths are not affected.
1323
- *
1324
- * @param root the subtree root to walk for attached shadow roots
1325
- */
1326
- const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
1327
- if (root.nodeType === NODE_TYPE.element && root.shadowRoot instanceof DocumentFragment) {
1328
- const sr = root.shadowRoot;
1329
- // Recurse first so that nested shadow roots are reached even if
1330
- // _sanitizeShadowDOM removes hosts at this level.
1331
- _sanitizeAttachedShadowRoots2(sr);
1332
- _sanitizeShadowDOM2(sr);
1333
- }
1334
- // Snapshot children before recursing. Sanitization of one subtree
1335
- // (e.g. via an uponSanitizeShadowNode hook) may detach siblings,
1336
- // and naive nextSibling traversal would silently skip the rest of
1337
- // the list once a node is detached.
1338
- const childNodes = root.childNodes;
1339
- if (!childNodes) {
1340
- return;
1341
- }
1342
- const snapshot = [];
1343
- arrayForEach(childNodes, child => {
1344
- arrayPush(snapshot, child);
1345
- });
1346
- for (const child of snapshot) {
1347
- _sanitizeAttachedShadowRoots2(child);
1348
- }
1349
- };
1350
1206
  // eslint-disable-next-line complexity
1351
1207
  DOMPurify.sanitize = function (dirty) {
1352
1208
  let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -1363,9 +1219,13 @@ function createDOMPurify() {
1363
1219
  }
1364
1220
  /* Stringify, in case dirty is an object */
1365
1221
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
1366
- dirty = stringifyValue(dirty);
1367
- if (typeof dirty !== 'string') {
1368
- throw typeErrorCreate('dirty is not a string, aborting');
1222
+ if (typeof dirty.toString === 'function') {
1223
+ dirty = dirty.toString();
1224
+ if (typeof dirty !== 'string') {
1225
+ throw typeErrorCreate('dirty is not a string, aborting');
1226
+ }
1227
+ } else {
1228
+ throw typeErrorCreate('toString is not a function');
1369
1229
  }
1370
1230
  }
1371
1231
  /* Return dirty HTML if DOMPurify cannot run */
@@ -1384,16 +1244,12 @@ function createDOMPurify() {
1384
1244
  }
1385
1245
  if (IN_PLACE) {
1386
1246
  /* Do some early pre-sanitization to avoid unsafe root nodes */
1387
- const nn = dirty.nodeName;
1388
- if (typeof nn === 'string') {
1389
- const tagName = transformCaseFunc(nn);
1247
+ if (dirty.nodeName) {
1248
+ const tagName = transformCaseFunc(dirty.nodeName);
1390
1249
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
1391
1250
  throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
1392
1251
  }
1393
1252
  }
1394
- /* Sanitize attached shadow roots before the main iterator runs.
1395
- The iterator does not descend into shadow trees. */
1396
- _sanitizeAttachedShadowRoots2(dirty);
1397
1253
  } else if (dirty instanceof Node) {
1398
1254
  /* If dirty is a DOM element, append to an empty document to avoid
1399
1255
  elements being stripped by the parser */
@@ -1408,10 +1264,6 @@ function createDOMPurify() {
1408
1264
  // eslint-disable-next-line unicorn/prefer-dom-node-append
1409
1265
  body.appendChild(importedNode);
1410
1266
  }
1411
- /* Clonable shadow roots are deep-cloned by importNode(); sanitize
1412
- them before the main iterator runs, since the iterator does not
1413
- descend into shadow trees. */
1414
- _sanitizeAttachedShadowRoots2(importedNode);
1415
1267
  } else {
1416
1268
  /* Exit directly if we have nothing to do */
1417
1269
  if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
@@ -1440,7 +1292,7 @@ function createDOMPurify() {
1440
1292
  _sanitizeAttributes(currentNode);
1441
1293
  /* Shadow DOM detected, sanitize it */
1442
1294
  if (currentNode.content instanceof DocumentFragment) {
1443
- _sanitizeShadowDOM2(currentNode.content);
1295
+ _sanitizeShadowDOM(currentNode.content);
1444
1296
  }
1445
1297
  }
1446
1298
  /* If we sanitized `dirty` in-place, return it. */
@@ -1449,14 +1301,6 @@ function createDOMPurify() {
1449
1301
  }
1450
1302
  /* Return sanitized string or DOM */
1451
1303
  if (RETURN_DOM) {
1452
- if (SAFE_FOR_TEMPLATES) {
1453
- body.normalize();
1454
- let html = body.innerHTML;
1455
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
1456
- html = stringReplace(html, expr, ' ');
1457
- });
1458
- body.innerHTML = html;
1459
- }
1460
1304
  if (RETURN_DOM_FRAGMENT) {
1461
1305
  returnNode = createDocumentFragment.call(body.ownerDocument);
1462
1306
  while (body.firstChild) {
@@ -1485,7 +1329,7 @@ function createDOMPurify() {
1485
1329
  }
1486
1330
  /* Sanitize final string template-safe */
1487
1331
  if (SAFE_FOR_TEMPLATES) {
1488
- arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
1332
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
1489
1333
  serializedHTML = stringReplace(serializedHTML, expr, ' ');
1490
1334
  });
1491
1335
  }