dompurify 3.2.0 → 3.2.2

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 CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
8
8
 
9
- It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version **v3.2.0**.
9
+ It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version **v3.2.2**.
10
10
 
11
11
  DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Edge, Firefox and Chrome - as well as almost anything else using Blink, Gecko or WebKit). It doesn't break on MSIE or other legacy browsers. It simply does nothing.
12
12
 
@@ -1,4 +1,5 @@
1
- /*! @license DOMPurify 3.2.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.2.0/LICENSE */
1
+ /// <reference types="trusted-types" />
2
+ /*! @license DOMPurify 3.2.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.2/LICENSE */
2
3
 
3
4
  /**
4
5
  * Configuration to control DOMPurify behavior.
@@ -206,9 +207,9 @@ declare const _default: DOMPurify;
206
207
 
207
208
  interface DOMPurify {
208
209
  /**
209
- * Creates a DOMPurify instance using the given window-like object.
210
+ * Creates a DOMPurify instance using the given window-like object. Defaults to `window`.
210
211
  */
211
- (root: WindowLike): DOMPurify;
212
+ (root?: WindowLike): DOMPurify;
212
213
  /**
213
214
  * Version label, exposed for easier checks
214
215
  * if DOMPurify is up to date or not
@@ -297,7 +298,21 @@ interface DOMPurify {
297
298
  * @param entryPoint entry point for the hook to add
298
299
  * @param hookFunction function to execute
299
300
  */
300
- addHook(entryPoint: BasicHookName, hookFunction: Hook): void;
301
+ addHook(entryPoint: BasicHookName, hookFunction: NodeHook): void;
302
+ /**
303
+ * Adds a DOMPurify hook.
304
+ *
305
+ * @param entryPoint entry point for the hook to add
306
+ * @param hookFunction function to execute
307
+ */
308
+ addHook(entryPoint: ElementHookName, hookFunction: ElementHook): void;
309
+ /**
310
+ * Adds a DOMPurify hook.
311
+ *
312
+ * @param entryPoint entry point for the hook to add
313
+ * @param hookFunction function to execute
314
+ */
315
+ addHook(entryPoint: DocumentFragmentHookName, hookFunction: DocumentFragmentHook): void;
301
316
  /**
302
317
  * Adds a DOMPurify hook.
303
318
  *
@@ -319,7 +334,23 @@ interface DOMPurify {
319
334
  * @param entryPoint entry point for the hook to remove
320
335
  * @returns removed(popped) hook
321
336
  */
322
- removeHook(entryPoint: BasicHookName): Hook | undefined;
337
+ removeHook(entryPoint: BasicHookName): NodeHook | undefined;
338
+ /**
339
+ * Remove a DOMPurify hook at a given entryPoint
340
+ * (pops it from the stack of hooks if more are present)
341
+ *
342
+ * @param entryPoint entry point for the hook to remove
343
+ * @returns removed(popped) hook
344
+ */
345
+ removeHook(entryPoint: ElementHookName): ElementHook | undefined;
346
+ /**
347
+ * Remove a DOMPurify hook at a given entryPoint
348
+ * (pops it from the stack of hooks if more are present)
349
+ *
350
+ * @param entryPoint entry point for the hook to remove
351
+ * @returns removed(popped) hook
352
+ */
353
+ removeHook(entryPoint: DocumentFragmentHookName): DocumentFragmentHook | undefined;
323
354
  /**
324
355
  * Remove a DOMPurify hook at a given entryPoint
325
356
  * (pops it from the stack of hooks if more are present)
@@ -369,13 +400,17 @@ interface RemovedAttribute {
369
400
  */
370
401
  from: Node;
371
402
  }
372
- type BasicHookName = 'beforeSanitizeElements' | 'afterSanitizeElements' | 'beforeSanitizeAttributes' | 'afterSanitizeAttributes' | 'beforeSanitizeShadowDOM' | 'uponSanitizeShadowNode' | 'afterSanitizeShadowDOM';
403
+ type BasicHookName = 'beforeSanitizeElements' | 'afterSanitizeElements' | 'uponSanitizeShadowNode';
404
+ type ElementHookName = 'beforeSanitizeAttributes' | 'afterSanitizeAttributes';
405
+ type DocumentFragmentHookName = 'beforeSanitizeShadowDOM' | 'afterSanitizeShadowDOM';
373
406
  type UponSanitizeElementHookName = 'uponSanitizeElement';
374
407
  type UponSanitizeAttributeHookName = 'uponSanitizeAttribute';
375
- type HookName = BasicHookName | UponSanitizeElementHookName | UponSanitizeAttributeHookName;
376
- type Hook = (this: DOMPurify, currentNode: Node, hookEvent: null, config: Config) => void;
408
+ type HookName = BasicHookName | ElementHookName | DocumentFragmentHookName | UponSanitizeElementHookName | UponSanitizeAttributeHookName;
409
+ type NodeHook = (this: DOMPurify, currentNode: Node, hookEvent: null, config: Config) => void;
410
+ type ElementHook = (this: DOMPurify, currentNode: Element, hookEvent: null, config: Config) => void;
411
+ type DocumentFragmentHook = (this: DOMPurify, currentNode: DocumentFragment, hookEvent: null, config: Config) => void;
377
412
  type UponSanitizeElementHook = (this: DOMPurify, currentNode: Node, hookEvent: UponSanitizeElementHookEvent, config: Config) => void;
378
- type UponSanitizeAttributeHook = (this: DOMPurify, currentNode: Node, hookEvent: UponSanitizeAttributeHookEvent, config: Config) => void;
413
+ type UponSanitizeAttributeHook = (this: DOMPurify, currentNode: Element, hookEvent: UponSanitizeAttributeHookEvent, config: Config) => void;
379
414
  interface UponSanitizeElementHookEvent {
380
415
  tagName: string;
381
416
  allowedTags: Record<string, boolean>;
@@ -396,6 +431,7 @@ type WindowLike = Pick<typeof globalThis, 'DocumentFragment' | 'HTMLTemplateElem
396
431
  trustedTypes?: typeof window.trustedTypes;
397
432
  };
398
433
 
399
- export { type Config, type Hook, type HookName, type RemovedAttribute, type RemovedElement, type UponSanitizeAttributeHook, type UponSanitizeAttributeHookEvent, type UponSanitizeElementHook, type UponSanitizeElementHookEvent, type WindowLike };
434
+ export { type Config, type DOMPurify, type DocumentFragmentHook, type ElementHook, type HookName, type NodeHook, type RemovedAttribute, type RemovedElement, type UponSanitizeAttributeHook, type UponSanitizeAttributeHookEvent, type UponSanitizeElementHook, type UponSanitizeElementHookEvent, type WindowLike };
400
435
 
436
+ // @ts-ignore
401
437
  export = _default;
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify 3.2.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.2.0/LICENSE */
1
+ /*! @license DOMPurify 3.2.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.2/LICENSE */
2
2
 
3
3
  'use strict';
4
4
 
@@ -281,10 +281,23 @@ const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedType
281
281
  return null;
282
282
  }
283
283
  };
284
+ const _createHooksMap = function _createHooksMap() {
285
+ return {
286
+ afterSanitizeAttributes: [],
287
+ afterSanitizeElements: [],
288
+ afterSanitizeShadowDOM: [],
289
+ beforeSanitizeAttributes: [],
290
+ beforeSanitizeElements: [],
291
+ beforeSanitizeShadowDOM: [],
292
+ uponSanitizeAttribute: [],
293
+ uponSanitizeElement: [],
294
+ uponSanitizeShadowNode: []
295
+ };
296
+ };
284
297
  function createDOMPurify() {
285
298
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
286
299
  const DOMPurify = root => createDOMPurify(root);
287
- DOMPurify.version = '3.2.0';
300
+ DOMPurify.version = '3.2.2';
288
301
  DOMPurify.removed = [];
289
302
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {
290
303
  // Not running in a browser, provide a factory function
@@ -337,7 +350,7 @@ function createDOMPurify() {
337
350
  const {
338
351
  importNode
339
352
  } = originalDocument;
340
- let hooks = {};
353
+ let hooks = _createHooksMap();
341
354
  /**
342
355
  * Expose whether this browser supports running the full DOMPurify.
343
356
  */
@@ -766,8 +779,8 @@ function createDOMPurify() {
766
779
  });
767
780
  }
768
781
  element.removeAttribute(name);
769
- // We void attribute values for unremovable "is"" attributes
770
- if (name === 'is' && !ALLOWED_ATTR[name]) {
782
+ // We void attribute values for unremovable "is" attributes
783
+ if (name === 'is') {
771
784
  if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
772
785
  try {
773
786
  _forceRemove(element);
@@ -858,11 +871,8 @@ function createDOMPurify() {
858
871
  const _isNode = function _isNode(value) {
859
872
  return typeof Node === 'function' && value instanceof Node;
860
873
  };
861
- function _executeHook(entryPoint, currentNode, data) {
862
- if (!hooks[entryPoint]) {
863
- return;
864
- }
865
- arrayForEach(hooks[entryPoint], hook => {
874
+ function _executeHooks(hooks, currentNode, data) {
875
+ arrayForEach(hooks, hook => {
866
876
  hook.call(DOMPurify, currentNode, data, CONFIG);
867
877
  });
868
878
  }
@@ -878,7 +888,7 @@ function createDOMPurify() {
878
888
  const _sanitizeElements = function _sanitizeElements(currentNode) {
879
889
  let content = null;
880
890
  /* Execute a hook if present */
881
- _executeHook('beforeSanitizeElements', currentNode, null);
891
+ _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
882
892
  /* Check if element is clobbered or can clobber */
883
893
  if (_isClobbered(currentNode)) {
884
894
  _forceRemove(currentNode);
@@ -887,7 +897,7 @@ function createDOMPurify() {
887
897
  /* Now let's check the element's type and name */
888
898
  const tagName = transformCaseFunc(currentNode.nodeName);
889
899
  /* Execute a hook if present */
890
- _executeHook('uponSanitizeElement', currentNode, {
900
+ _executeHooks(hooks.uponSanitizeElement, currentNode, {
891
901
  tagName,
892
902
  allowedTags: ALLOWED_TAGS
893
903
  });
@@ -958,7 +968,7 @@ function createDOMPurify() {
958
968
  }
959
969
  }
960
970
  /* Execute a hook if present */
961
- _executeHook('afterSanitizeElements', currentNode, null);
971
+ _executeHooks(hooks.afterSanitizeElements, currentNode, null);
962
972
  return false;
963
973
  };
964
974
  /**
@@ -1019,7 +1029,7 @@ function createDOMPurify() {
1019
1029
  */
1020
1030
  const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1021
1031
  /* Execute a hook if present */
1022
- _executeHook('beforeSanitizeAttributes', currentNode, null);
1032
+ _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
1023
1033
  const {
1024
1034
  attributes
1025
1035
  } = currentNode;
@@ -1050,7 +1060,7 @@ function createDOMPurify() {
1050
1060
  hookEvent.attrValue = value;
1051
1061
  hookEvent.keepAttr = true;
1052
1062
  hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1053
- _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1063
+ _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
1054
1064
  value = hookEvent.attrValue;
1055
1065
  /* Full DOM Clobbering protection via namespace isolation,
1056
1066
  * Prefix id and name attributes with `user-content-`
@@ -1125,7 +1135,7 @@ function createDOMPurify() {
1125
1135
  } catch (_) {}
1126
1136
  }
1127
1137
  /* Execute a hook if present */
1128
- _executeHook('afterSanitizeAttributes', currentNode, null);
1138
+ _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
1129
1139
  };
1130
1140
  /**
1131
1141
  * _sanitizeShadowDOM
@@ -1136,10 +1146,10 @@ function createDOMPurify() {
1136
1146
  let shadowNode = null;
1137
1147
  const shadowIterator = _createNodeIterator(fragment);
1138
1148
  /* Execute a hook if present */
1139
- _executeHook('beforeSanitizeShadowDOM', fragment, null);
1149
+ _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
1140
1150
  while (shadowNode = shadowIterator.nextNode()) {
1141
1151
  /* Execute a hook if present */
1142
- _executeHook('uponSanitizeShadowNode', shadowNode, null);
1152
+ _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
1143
1153
  /* Sanitize tags and elements */
1144
1154
  if (_sanitizeElements(shadowNode)) {
1145
1155
  continue;
@@ -1152,7 +1162,7 @@ function createDOMPurify() {
1152
1162
  _sanitizeAttributes(shadowNode);
1153
1163
  }
1154
1164
  /* Execute a hook if present */
1155
- _executeHook('afterSanitizeShadowDOM', fragment, null);
1165
+ _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
1156
1166
  };
1157
1167
  // eslint-disable-next-line complexity
1158
1168
  DOMPurify.sanitize = function (dirty) {
@@ -1310,21 +1320,16 @@ function createDOMPurify() {
1310
1320
  if (typeof hookFunction !== 'function') {
1311
1321
  return;
1312
1322
  }
1313
- hooks[entryPoint] = hooks[entryPoint] || [];
1314
1323
  arrayPush(hooks[entryPoint], hookFunction);
1315
1324
  };
1316
1325
  DOMPurify.removeHook = function (entryPoint) {
1317
- if (hooks[entryPoint]) {
1318
- return arrayPop(hooks[entryPoint]);
1319
- }
1326
+ return arrayPop(hooks[entryPoint]);
1320
1327
  };
1321
1328
  DOMPurify.removeHooks = function (entryPoint) {
1322
- if (hooks[entryPoint]) {
1323
- hooks[entryPoint] = [];
1324
- }
1329
+ hooks[entryPoint] = [];
1325
1330
  };
1326
1331
  DOMPurify.removeAllHooks = function () {
1327
- hooks = {};
1332
+ hooks = _createHooksMap();
1328
1333
  };
1329
1334
  return DOMPurify;
1330
1335
  }
@@ -1 +1 @@
1
- {"version":3,"file":"purify.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"purify.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,4 +1,5 @@
1
- /*! @license DOMPurify 3.2.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.2.0/LICENSE */
1
+ /// <reference types="trusted-types" />
2
+ /*! @license DOMPurify 3.2.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.2/LICENSE */
2
3
 
3
4
  /**
4
5
  * Configuration to control DOMPurify behavior.
@@ -206,9 +207,9 @@ declare const _default: DOMPurify;
206
207
 
207
208
  interface DOMPurify {
208
209
  /**
209
- * Creates a DOMPurify instance using the given window-like object.
210
+ * Creates a DOMPurify instance using the given window-like object. Defaults to `window`.
210
211
  */
211
- (root: WindowLike): DOMPurify;
212
+ (root?: WindowLike): DOMPurify;
212
213
  /**
213
214
  * Version label, exposed for easier checks
214
215
  * if DOMPurify is up to date or not
@@ -297,7 +298,21 @@ interface DOMPurify {
297
298
  * @param entryPoint entry point for the hook to add
298
299
  * @param hookFunction function to execute
299
300
  */
300
- addHook(entryPoint: BasicHookName, hookFunction: Hook): void;
301
+ addHook(entryPoint: BasicHookName, hookFunction: NodeHook): void;
302
+ /**
303
+ * Adds a DOMPurify hook.
304
+ *
305
+ * @param entryPoint entry point for the hook to add
306
+ * @param hookFunction function to execute
307
+ */
308
+ addHook(entryPoint: ElementHookName, hookFunction: ElementHook): void;
309
+ /**
310
+ * Adds a DOMPurify hook.
311
+ *
312
+ * @param entryPoint entry point for the hook to add
313
+ * @param hookFunction function to execute
314
+ */
315
+ addHook(entryPoint: DocumentFragmentHookName, hookFunction: DocumentFragmentHook): void;
301
316
  /**
302
317
  * Adds a DOMPurify hook.
303
318
  *
@@ -319,7 +334,23 @@ interface DOMPurify {
319
334
  * @param entryPoint entry point for the hook to remove
320
335
  * @returns removed(popped) hook
321
336
  */
322
- removeHook(entryPoint: BasicHookName): Hook | undefined;
337
+ removeHook(entryPoint: BasicHookName): NodeHook | undefined;
338
+ /**
339
+ * Remove a DOMPurify hook at a given entryPoint
340
+ * (pops it from the stack of hooks if more are present)
341
+ *
342
+ * @param entryPoint entry point for the hook to remove
343
+ * @returns removed(popped) hook
344
+ */
345
+ removeHook(entryPoint: ElementHookName): ElementHook | undefined;
346
+ /**
347
+ * Remove a DOMPurify hook at a given entryPoint
348
+ * (pops it from the stack of hooks if more are present)
349
+ *
350
+ * @param entryPoint entry point for the hook to remove
351
+ * @returns removed(popped) hook
352
+ */
353
+ removeHook(entryPoint: DocumentFragmentHookName): DocumentFragmentHook | undefined;
323
354
  /**
324
355
  * Remove a DOMPurify hook at a given entryPoint
325
356
  * (pops it from the stack of hooks if more are present)
@@ -369,13 +400,17 @@ interface RemovedAttribute {
369
400
  */
370
401
  from: Node;
371
402
  }
372
- type BasicHookName = 'beforeSanitizeElements' | 'afterSanitizeElements' | 'beforeSanitizeAttributes' | 'afterSanitizeAttributes' | 'beforeSanitizeShadowDOM' | 'uponSanitizeShadowNode' | 'afterSanitizeShadowDOM';
403
+ type BasicHookName = 'beforeSanitizeElements' | 'afterSanitizeElements' | 'uponSanitizeShadowNode';
404
+ type ElementHookName = 'beforeSanitizeAttributes' | 'afterSanitizeAttributes';
405
+ type DocumentFragmentHookName = 'beforeSanitizeShadowDOM' | 'afterSanitizeShadowDOM';
373
406
  type UponSanitizeElementHookName = 'uponSanitizeElement';
374
407
  type UponSanitizeAttributeHookName = 'uponSanitizeAttribute';
375
- type HookName = BasicHookName | UponSanitizeElementHookName | UponSanitizeAttributeHookName;
376
- type Hook = (this: DOMPurify, currentNode: Node, hookEvent: null, config: Config) => void;
408
+ type HookName = BasicHookName | ElementHookName | DocumentFragmentHookName | UponSanitizeElementHookName | UponSanitizeAttributeHookName;
409
+ type NodeHook = (this: DOMPurify, currentNode: Node, hookEvent: null, config: Config) => void;
410
+ type ElementHook = (this: DOMPurify, currentNode: Element, hookEvent: null, config: Config) => void;
411
+ type DocumentFragmentHook = (this: DOMPurify, currentNode: DocumentFragment, hookEvent: null, config: Config) => void;
377
412
  type UponSanitizeElementHook = (this: DOMPurify, currentNode: Node, hookEvent: UponSanitizeElementHookEvent, config: Config) => void;
378
- type UponSanitizeAttributeHook = (this: DOMPurify, currentNode: Node, hookEvent: UponSanitizeAttributeHookEvent, config: Config) => void;
413
+ type UponSanitizeAttributeHook = (this: DOMPurify, currentNode: Element, hookEvent: UponSanitizeAttributeHookEvent, config: Config) => void;
379
414
  interface UponSanitizeElementHookEvent {
380
415
  tagName: string;
381
416
  allowedTags: Record<string, boolean>;
@@ -396,4 +431,4 @@ type WindowLike = Pick<typeof globalThis, 'DocumentFragment' | 'HTMLTemplateElem
396
431
  trustedTypes?: typeof window.trustedTypes;
397
432
  };
398
433
 
399
- export { type Config, type Hook, type HookName, type RemovedAttribute, type RemovedElement, type UponSanitizeAttributeHook, type UponSanitizeAttributeHookEvent, type UponSanitizeElementHook, type UponSanitizeElementHookEvent, type WindowLike, _default as default };
434
+ export { type Config, type DOMPurify, type DocumentFragmentHook, type ElementHook, type HookName, type NodeHook, type RemovedAttribute, type RemovedElement, type UponSanitizeAttributeHook, type UponSanitizeAttributeHookEvent, type UponSanitizeElementHook, type UponSanitizeElementHookEvent, type WindowLike, _default as default };
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify 3.2.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.2.0/LICENSE */
1
+ /*! @license DOMPurify 3.2.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.2/LICENSE */
2
2
 
3
3
  const {
4
4
  entries,
@@ -279,10 +279,23 @@ const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedType
279
279
  return null;
280
280
  }
281
281
  };
282
+ const _createHooksMap = function _createHooksMap() {
283
+ return {
284
+ afterSanitizeAttributes: [],
285
+ afterSanitizeElements: [],
286
+ afterSanitizeShadowDOM: [],
287
+ beforeSanitizeAttributes: [],
288
+ beforeSanitizeElements: [],
289
+ beforeSanitizeShadowDOM: [],
290
+ uponSanitizeAttribute: [],
291
+ uponSanitizeElement: [],
292
+ uponSanitizeShadowNode: []
293
+ };
294
+ };
282
295
  function createDOMPurify() {
283
296
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
284
297
  const DOMPurify = root => createDOMPurify(root);
285
- DOMPurify.version = '3.2.0';
298
+ DOMPurify.version = '3.2.2';
286
299
  DOMPurify.removed = [];
287
300
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {
288
301
  // Not running in a browser, provide a factory function
@@ -335,7 +348,7 @@ function createDOMPurify() {
335
348
  const {
336
349
  importNode
337
350
  } = originalDocument;
338
- let hooks = {};
351
+ let hooks = _createHooksMap();
339
352
  /**
340
353
  * Expose whether this browser supports running the full DOMPurify.
341
354
  */
@@ -764,8 +777,8 @@ function createDOMPurify() {
764
777
  });
765
778
  }
766
779
  element.removeAttribute(name);
767
- // We void attribute values for unremovable "is"" attributes
768
- if (name === 'is' && !ALLOWED_ATTR[name]) {
780
+ // We void attribute values for unremovable "is" attributes
781
+ if (name === 'is') {
769
782
  if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
770
783
  try {
771
784
  _forceRemove(element);
@@ -856,11 +869,8 @@ function createDOMPurify() {
856
869
  const _isNode = function _isNode(value) {
857
870
  return typeof Node === 'function' && value instanceof Node;
858
871
  };
859
- function _executeHook(entryPoint, currentNode, data) {
860
- if (!hooks[entryPoint]) {
861
- return;
862
- }
863
- arrayForEach(hooks[entryPoint], hook => {
872
+ function _executeHooks(hooks, currentNode, data) {
873
+ arrayForEach(hooks, hook => {
864
874
  hook.call(DOMPurify, currentNode, data, CONFIG);
865
875
  });
866
876
  }
@@ -876,7 +886,7 @@ function createDOMPurify() {
876
886
  const _sanitizeElements = function _sanitizeElements(currentNode) {
877
887
  let content = null;
878
888
  /* Execute a hook if present */
879
- _executeHook('beforeSanitizeElements', currentNode, null);
889
+ _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
880
890
  /* Check if element is clobbered or can clobber */
881
891
  if (_isClobbered(currentNode)) {
882
892
  _forceRemove(currentNode);
@@ -885,7 +895,7 @@ function createDOMPurify() {
885
895
  /* Now let's check the element's type and name */
886
896
  const tagName = transformCaseFunc(currentNode.nodeName);
887
897
  /* Execute a hook if present */
888
- _executeHook('uponSanitizeElement', currentNode, {
898
+ _executeHooks(hooks.uponSanitizeElement, currentNode, {
889
899
  tagName,
890
900
  allowedTags: ALLOWED_TAGS
891
901
  });
@@ -956,7 +966,7 @@ function createDOMPurify() {
956
966
  }
957
967
  }
958
968
  /* Execute a hook if present */
959
- _executeHook('afterSanitizeElements', currentNode, null);
969
+ _executeHooks(hooks.afterSanitizeElements, currentNode, null);
960
970
  return false;
961
971
  };
962
972
  /**
@@ -1017,7 +1027,7 @@ function createDOMPurify() {
1017
1027
  */
1018
1028
  const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1019
1029
  /* Execute a hook if present */
1020
- _executeHook('beforeSanitizeAttributes', currentNode, null);
1030
+ _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
1021
1031
  const {
1022
1032
  attributes
1023
1033
  } = currentNode;
@@ -1048,7 +1058,7 @@ function createDOMPurify() {
1048
1058
  hookEvent.attrValue = value;
1049
1059
  hookEvent.keepAttr = true;
1050
1060
  hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1051
- _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1061
+ _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
1052
1062
  value = hookEvent.attrValue;
1053
1063
  /* Full DOM Clobbering protection via namespace isolation,
1054
1064
  * Prefix id and name attributes with `user-content-`
@@ -1123,7 +1133,7 @@ function createDOMPurify() {
1123
1133
  } catch (_) {}
1124
1134
  }
1125
1135
  /* Execute a hook if present */
1126
- _executeHook('afterSanitizeAttributes', currentNode, null);
1136
+ _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
1127
1137
  };
1128
1138
  /**
1129
1139
  * _sanitizeShadowDOM
@@ -1134,10 +1144,10 @@ function createDOMPurify() {
1134
1144
  let shadowNode = null;
1135
1145
  const shadowIterator = _createNodeIterator(fragment);
1136
1146
  /* Execute a hook if present */
1137
- _executeHook('beforeSanitizeShadowDOM', fragment, null);
1147
+ _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
1138
1148
  while (shadowNode = shadowIterator.nextNode()) {
1139
1149
  /* Execute a hook if present */
1140
- _executeHook('uponSanitizeShadowNode', shadowNode, null);
1150
+ _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
1141
1151
  /* Sanitize tags and elements */
1142
1152
  if (_sanitizeElements(shadowNode)) {
1143
1153
  continue;
@@ -1150,7 +1160,7 @@ function createDOMPurify() {
1150
1160
  _sanitizeAttributes(shadowNode);
1151
1161
  }
1152
1162
  /* Execute a hook if present */
1153
- _executeHook('afterSanitizeShadowDOM', fragment, null);
1163
+ _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
1154
1164
  };
1155
1165
  // eslint-disable-next-line complexity
1156
1166
  DOMPurify.sanitize = function (dirty) {
@@ -1308,21 +1318,16 @@ function createDOMPurify() {
1308
1318
  if (typeof hookFunction !== 'function') {
1309
1319
  return;
1310
1320
  }
1311
- hooks[entryPoint] = hooks[entryPoint] || [];
1312
1321
  arrayPush(hooks[entryPoint], hookFunction);
1313
1322
  };
1314
1323
  DOMPurify.removeHook = function (entryPoint) {
1315
- if (hooks[entryPoint]) {
1316
- return arrayPop(hooks[entryPoint]);
1317
- }
1324
+ return arrayPop(hooks[entryPoint]);
1318
1325
  };
1319
1326
  DOMPurify.removeHooks = function (entryPoint) {
1320
- if (hooks[entryPoint]) {
1321
- hooks[entryPoint] = [];
1322
- }
1327
+ hooks[entryPoint] = [];
1323
1328
  };
1324
1329
  DOMPurify.removeAllHooks = function () {
1325
- hooks = {};
1330
+ hooks = _createHooksMap();
1326
1331
  };
1327
1332
  return DOMPurify;
1328
1333
  }
@@ -1 +1 @@
1
- {"version":3,"file":"purify.es.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"purify.es.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}