comparison src/sceditor.js @ 20:cf42d9b17c25

more
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 08 Aug 2022 18:17:55 -0600
parents 13df5ac9b34b
children 2edd68951454
comparison
equal deleted inserted replaced
19:13df5ac9b34b 20:cf42d9b17c25
1 (function () { 1 (function () {
2 'use strict'; 2 'use strict';
3 3
4 let baseUrl = document.currentScript.getAttribute('src').match(/.*\//)[0]; 4 let baseUrl = document.currentScript.getAttribute('src').match(/.*\//)[0];
5 //console.log(baseUrl);
6 5
7 /** 6 /**
8 * Check if the passed argument is the 7 * Check if the passed argument is the
9 * the passed type. 8 * the passed type.
10 * 9 *
2729 2728
2730 2729
2731 // START_COMMAND: Ltr 2730 // START_COMMAND: Ltr
2732 ltr: { 2731 ltr: {
2733 state: function (editor, parents, firstBlock) { 2732 state: function (editor, parents, firstBlock) {
2734 return firstBlock && firstBlock.style.direction === 'ltr'; 2733 //return firstBlock && firstBlock.style.direction === 'ltr';
2734 return firstBlock && firstBlock.style && firstBlock.style.direction === 'ltr';
2735 }, 2735 },
2736 exec: function (editor) { 2736 exec: function (editor) {
2737 var rangeHelper = editor.getRangeHelper(), 2737 var rangeHelper = editor.getRangeHelper(),
2738 node = rangeHelper.getFirstBlockParent(); 2738 node = rangeHelper.getFirstBlockParent();
2739 2739
2757 // END_COMMAND 2757 // END_COMMAND
2758 2758
2759 // START_COMMAND: Rtl 2759 // START_COMMAND: Rtl
2760 rtl: { 2760 rtl: {
2761 state: function (editor, parents, firstBlock) { 2761 state: function (editor, parents, firstBlock) {
2762 return firstBlock && firstBlock.style.direction === 'rtl'; 2762 //return firstBlock && firstBlock.style.direction === 'rtl';
2763 return firstBlock && firstBlock.style && firstBlock.style.direction === 'rtl';
2763 }, 2764 },
2764 exec: function (editor) { 2765 exec: function (editor) {
2765 var rangeHelper = editor.getRangeHelper(), 2766 var rangeHelper = editor.getRangeHelper(),
2766 node = rangeHelper.getFirstBlockParent(); 2767 node = rangeHelper.getFirstBlockParent();
2767 2768
4135 construct = function construct(Func, args) { 4136 construct = function construct(Func, args) {
4136 return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray(args))))(); 4137 return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray(args))))();
4137 }; 4138 };
4138 } 4139 }
4139 4140
4140 var arrayForEach = unapply(Array.prototype.forEach);
4141 var arrayPop = unapply(Array.prototype.pop);
4142 var arrayPush = unapply(Array.prototype.push);
4143
4144 var stringToLowerCase = unapply(String.prototype.toLowerCase);
4145 var stringMatch = unapply(String.prototype.match);
4146 var stringReplace = unapply(String.prototype.replace);
4147 var stringIndexOf = unapply(String.prototype.indexOf);
4148 var stringTrim = unapply(String.prototype.trim);
4149
4150 var regExpTest = unapply(RegExp.prototype.test);
4151
4152 var typeErrorCreate = unconstruct(TypeError); 4141 var typeErrorCreate = unconstruct(TypeError);
4153 4142
4154 function unapply(func) { 4143 function unapply(func) {
4155 return function (thisArg) { 4144 return function (thisArg) {
4156 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 4145 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
4182 4171
4183 var l = array.length; 4172 var l = array.length;
4184 while (l--) { 4173 while (l--) {
4185 var element = array[l]; 4174 var element = array[l];
4186 if (typeof element === 'string') { 4175 if (typeof element === 'string') {
4187 var lcElement = stringToLowerCase(element); 4176 var lcElement = element.toLowerCase();
4188 if (lcElement !== element) { 4177 if (lcElement !== element) {
4189 // Config presets (e.g. tags.js, attrs.js) are immutable. 4178 // Config presets (e.g. tags.js, attrs.js) are immutable.
4190 if (!isFrozen(array)) { 4179 if (!isFrozen(array)) {
4191 array[l] = lcElement; 4180 array[l] = lcElement;
4192 } 4181 }
4366 Comment = window.Comment, 4355 Comment = window.Comment,
4367 DOMParser = window.DOMParser, 4356 DOMParser = window.DOMParser,
4368 trustedTypes = window.trustedTypes; 4357 trustedTypes = window.trustedTypes;
4369 4358
4370 4359
4371 var ElementPrototype = Element.prototype; 4360 var ElementPrototype = Element.prototype;
4372 4361
4373 var cloneNode = lookupGetter(ElementPrototype, 'cloneNode'); 4362 var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
4374 var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling'); 4363 var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
4375 var getChildNodes = lookupGetter(ElementPrototype, 'childNodes'); 4364 var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
4376 var getParentNode = lookupGetter(ElementPrototype, 'parentNode'); 4365 var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
4377 4366
4378 // As per issue #47, the web-components registry is inherited by a 4367 // As per issue #47, the web-components registry is inherited by a
4379 // new document created via createHTMLDocument. As per the spec 4368 // new document created via createHTMLDocument. As per the spec
4380 // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries) 4369 // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
4381 // a new empty registry is used when creating a template contents owner 4370 // a new empty registry is used when creating a template contents owner
4389 } 4378 }
4390 4379
4391 var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument); 4380 var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
4392 var emptyHTML = trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML('') : ''; 4381 var emptyHTML = trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML('') : '';
4393 4382
4394 var implementation = document.implementation, 4383 var implementation = document.implementation;
4395 //var importNode = originalDocument.importNode; 4384 //var importNode = originalDocument.importNode;
4396 4385
4397 4386
4398 var documentMode = {}; 4387 var documentMode = {};
4399 try { 4388 try {
4675 namespaceURI: HTML_NAMESPACE, 4664 namespaceURI: HTML_NAMESPACE,
4676 tagName: 'template' 4665 tagName: 'template'
4677 }; 4666 };
4678 } 4667 }
4679 4668
4680 var tagName = stringToLowerCase(element.tagName); 4669 var tagName = element.tagName.toLowerCase();
4681 var parentTagName = stringToLowerCase(parent.tagName); 4670 var parentTagName = parent.tagName.toLowerCase();
4682 4671
4683 if (element.namespaceURI === SVG_NAMESPACE) { 4672 if (element.namespaceURI === SVG_NAMESPACE) {
4684 // The only way to switch from HTML namespace to SVG 4673 // The only way to switch from HTML namespace to SVG
4685 // is via <svg>. If it happens via any other tag, then 4674 // is via <svg>. If it happens via any other tag, then
4686 // it should be killed. 4675 // it should be killed.
4752 * _forceRemove 4741 * _forceRemove
4753 * 4742 *
4754 * @param {Node} node a DOM node 4743 * @param {Node} node a DOM node
4755 */ 4744 */
4756 var _forceRemove = function _forceRemove(node) { 4745 var _forceRemove = function _forceRemove(node) {
4757 arrayPush(DOMPurify.removed, { element: node }); 4746 DOMPurify.removed.push({ element: node });
4758 try { 4747 try {
4759 node.parentNode.removeChild(node); 4748 node.parentNode.removeChild(node);
4760 } catch (_) { 4749 } catch (_) {
4761 try { 4750 try {
4762 node.outerHTML = emptyHTML; 4751 node.outerHTML = emptyHTML;
4772 * @param {String} name an Attribute name 4761 * @param {String} name an Attribute name
4773 * @param {Node} node a DOM node 4762 * @param {Node} node a DOM node
4774 */ 4763 */
4775 var _removeAttribute = function _removeAttribute(name, node) { 4764 var _removeAttribute = function _removeAttribute(name, node) {
4776 try { 4765 try {
4777 arrayPush(DOMPurify.removed, { 4766 DOMPurify.removed.push({
4778 attribute: node.getAttributeNode(name), 4767 attribute: node.getAttributeNode(name),
4779 from: node 4768 from: node
4780 }); 4769 });
4781 } catch (_) { 4770 } catch (_) {
4782 arrayPush(DOMPurify.removed, { 4771 DOMPurify.removed.push({
4783 attribute: null, 4772 attribute: null,
4784 from: node 4773 from: node
4785 }); 4774 });
4786 } 4775 }
4787 4776
4801 4790
4802 if (FORCE_BODY) { 4791 if (FORCE_BODY) {
4803 dirty = '<remove></remove>' + dirty; 4792 dirty = '<remove></remove>' + dirty;
4804 } else { 4793 } else {
4805 /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */ 4794 /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
4806 var matches = stringMatch(dirty, /^[\r\n\t ]+/); 4795 var matches = dirty.match(/^[\r\n\t ]+/);
4807 leadingWhitespace = matches && matches[0]; 4796 leadingWhitespace = matches && matches[0];
4808 } 4797 }
4809 4798
4810 var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty; 4799 var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
4811 /* Use the DOMParser API by default, fallback later if needs be */ 4800 /* Use the DOMParser API by default, fallback later if needs be */
4888 var _executeHook = function _executeHook(entryPoint, currentNode, data) { 4877 var _executeHook = function _executeHook(entryPoint, currentNode, data) {
4889 if (!hooks[entryPoint]) { 4878 if (!hooks[entryPoint]) {
4890 return; 4879 return;
4891 } 4880 }
4892 4881
4893 arrayForEach(hooks[entryPoint], function (hook) { 4882 hooks[entryPoint].forEach(function (hook) {
4894 hook.call(DOMPurify, currentNode, data, CONFIG); 4883 hook.call(DOMPurify, currentNode, data, CONFIG);
4895 }); 4884 });
4896 }; 4885 };
4897 4886
4898 /** 4887 /**
4899 * _sanitizeElements 4888 * _sanitizeElements
4916 _forceRemove(currentNode); 4905 _forceRemove(currentNode);
4917 return true; 4906 return true;
4918 } 4907 }
4919 4908
4920 /* Check if tagname contains Unicode */ 4909 /* Check if tagname contains Unicode */
4921 if (stringMatch(currentNode.nodeName, /[\u0080-\uFFFF]/)) { 4910 if (currentNode.nodeName.match(/[\u0080-\uFFFF]/)) {
4922 _forceRemove(currentNode); 4911 _forceRemove(currentNode);
4923 return true; 4912 return true;
4924 } 4913 }
4925 4914
4926 /* Now let's check the element's type and name */ 4915 /* Now let's check the element's type and name */
4927 var tagName = stringToLowerCase(currentNode.nodeName); 4916 var tagName = currentNode.nodeName.toLowerCase();
4928 4917
4929 /* Execute a hook if present */ 4918 /* Execute a hook if present */
4930 _executeHook('uponSanitizeElement', currentNode, { 4919 _executeHook('uponSanitizeElement', currentNode, {
4931 tagName: tagName, 4920 tagName: tagName,
4932 allowedTags: ALLOWED_TAGS 4921 allowedTags: ALLOWED_TAGS
4933 }); 4922 });
4934 4923
4935 /* Detect mXSS attempts abusing namespace confusion */ 4924 /* Detect mXSS attempts abusing namespace confusion */
4936 if (!_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) { 4925 if (!_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && /<[/\w]/g.test(currentNode.innerHTML) && /<[/\w]/g.text(currentNode.textContent)) {
4937 _forceRemove(currentNode); 4926 _forceRemove(currentNode);
4938 return true; 4927 return true;
4939 } 4928 }
4940 4929
4941 /* Remove element if anything forbids its presence */ 4930 /* Remove element if anything forbids its presence */
4944 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) { 4933 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
4945 var parentNode = getParentNode(currentNode); 4934 var parentNode = getParentNode(currentNode);
4946 var childNodes = getChildNodes(currentNode); 4935 var childNodes = getChildNodes(currentNode);
4947 var childCount = childNodes.length; 4936 var childCount = childNodes.length;
4948 for (var i = childCount - 1; i >= 0; --i) { 4937 for (var i = childCount - 1; i >= 0; --i) {
4949 parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode)); 4938 parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
4950 } 4939 }
4951 } 4940 }
4952 4941
4953 _forceRemove(currentNode); 4942 _forceRemove(currentNode);
4954 return true; 4943 return true;
4958 if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) { 4947 if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
4959 _forceRemove(currentNode); 4948 _forceRemove(currentNode);
4960 return true; 4949 return true;
4961 } 4950 }
4962 4951
4963 if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) { 4952 if ((tagName === 'noscript' || tagName === 'noembed') && /<\/no(script|embed)/i.test(currentNode.innerHTML)) {
4964 _forceRemove(currentNode); 4953 _forceRemove(currentNode);
4965 return true; 4954 return true;
4966 } 4955 }
4967 4956
4968 /* Sanitize element content to be template-safe */ 4957 /* Sanitize element content to be template-safe */
4969 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) { 4958 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
4970 /* Get the element's text content */ 4959 /* Get the element's text content */
4971 content = currentNode.textContent; 4960 content = currentNode.textContent;
4972 content = stringReplace(content, MUSTACHE_EXPR$$1, ' '); 4961 content = content.replace(MUSTACHE_EXPR$$1, ' ');
4973 content = stringReplace(content, ERB_EXPR$$1, ' '); 4962 content = content.replace(ERB_EXPR$$1, ' ');
4974 if (currentNode.textContent !== content) { 4963 if (currentNode.textContent !== content) {
4975 arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() }); 4964 DOMPurify.removed.push({ element: currentNode.cloneNode() });
4976 currentNode.textContent = content; 4965 currentNode.textContent = content;
4977 } 4966 }
4978 } 4967 }
4979 4968
4980 /* Execute a hook if present */ 4969 /* Execute a hook if present */
5000 4989
5001 /* Allow valid data-* attributes: At least one character after "-" 4990 /* Allow valid data-* attributes: At least one character after "-"
5002 (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes) 4991 (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
5003 XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) 4992 XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
5004 We don't need to check the value; it's always URI safe. */ 4993 We don't need to check the value; it's always URI safe. */
5005 if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) { 4994 if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) ; else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
5006 return false; 4995 return false;
5007 4996
5008 /* Check value is safe. First, is attr inert? If so, is safe */ 4997 /* Check value is safe. First, is attr inert? If so, is safe */
5009 } 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) ; else { 4998 } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {
5010 return false; 4999 return false;
5011 } 5000 }
5012 5001
5013 return true; 5002 return true;
5014 }; 5003 };
5052 attr = attributes[l]; 5041 attr = attributes[l];
5053 var _attr = attr, 5042 var _attr = attr,
5054 name = _attr.name, 5043 name = _attr.name,
5055 namespaceURI = _attr.namespaceURI; 5044 namespaceURI = _attr.namespaceURI;
5056 5045
5057 value = stringTrim(attr.value); 5046 value = attr.value.trim();
5058 lcName = stringToLowerCase(name); 5047 lcName = name.toLowerCase(name);
5059 5048
5060 /* Execute a hook if present */ 5049 /* Execute a hook if present */
5061 hookEvent.attrName = lcName; 5050 hookEvent.attrName = lcName;
5062 hookEvent.attrValue = value; 5051 hookEvent.attrValue = value;
5063 hookEvent.keepAttr = true; 5052 hookEvent.keepAttr = true;
5076 if (!hookEvent.keepAttr) { 5065 if (!hookEvent.keepAttr) {
5077 continue; 5066 continue;
5078 } 5067 }
5079 5068
5080 /* Work around a security issue in jQuery 3.0 */ 5069 /* Work around a security issue in jQuery 3.0 */
5081 if (regExpTest(/\/>/i, value)) { 5070 if (/\/>/i.test(value)) {
5082 _removeAttribute(name, currentNode); 5071 _removeAttribute(name, currentNode);
5083 continue; 5072 continue;
5084 } 5073 }
5085 5074
5086 /* Sanitize attribute content to be template-safe */ 5075 /* Sanitize attribute content to be template-safe */
5087 if (SAFE_FOR_TEMPLATES) { 5076 if (SAFE_FOR_TEMPLATES) {
5088 value = stringReplace(value, MUSTACHE_EXPR$$1, ' '); 5077 value = value.replace(MUSTACHE_EXPR$$1, ' ');
5089 value = stringReplace(value, ERB_EXPR$$1, ' '); 5078 value = value.replace(ERB_EXPR$$1, ' ');
5090 } 5079 }
5091 5080
5092 /* Is `value` valid for this attribute? */ 5081 /* Is `value` valid for this attribute? */
5093 var lcTag = currentNode.nodeName.toLowerCase(); 5082 var lcTag = currentNode.nodeName.toLowerCase();
5094 if (!_isValidAttribute(lcTag, lcName, value)) { 5083 if (!_isValidAttribute(lcTag, lcName, value)) {
5102 } else { 5091 } else {
5103 /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */ 5092 /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
5104 currentNode.setAttribute(name, value); 5093 currentNode.setAttribute(name, value);
5105 } 5094 }
5106 5095
5107 arrayPop(DOMPurify.removed); 5096 DOMPurify.removed.pop();
5108 } catch (_) {} 5097 } catch (_) {}
5109 } 5098 }
5110 5099
5111 /* Execute a hook if present */ 5100 /* Execute a hook if present */
5112 _executeHook('afterSanitizeAttributes', currentNode, null); 5101 _executeHook('afterSanitizeAttributes', currentNode, null);
5310 5299
5311 var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; 5300 var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
5312 5301
5313 /* Sanitize final string template-safe */ 5302 /* Sanitize final string template-safe */
5314 if (SAFE_FOR_TEMPLATES) { 5303 if (SAFE_FOR_TEMPLATES) {
5315 serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' '); 5304 serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
5316 serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' '); 5305 serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
5317 } 5306 }
5318 5307
5319 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML; 5308 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
5320 }; 5309 };
5321 5310
5354 /* Initialize shared config vars if necessary. */ 5343 /* Initialize shared config vars if necessary. */
5355 if (!CONFIG) { 5344 if (!CONFIG) {
5356 _parseConfig({}); 5345 _parseConfig({});
5357 } 5346 }
5358 5347
5359 var lcTag = stringToLowerCase(tag); 5348 var lcTag = tag.toLowerCase();
5360 var lcName = stringToLowerCase(attr); 5349 var lcName = attr.toLowerCase();
5361 return _isValidAttribute(lcTag, lcName, value); 5350 return _isValidAttribute(lcTag, lcName, value);
5362 }; 5351 };
5363 5352
5364 /** 5353 /**
5365 * AddHook 5354 * AddHook
5372 if (typeof hookFunction !== 'function') { 5361 if (typeof hookFunction !== 'function') {
5373 return; 5362 return;
5374 } 5363 }
5375 5364
5376 hooks[entryPoint] = hooks[entryPoint] || []; 5365 hooks[entryPoint] = hooks[entryPoint] || [];
5377 arrayPush(hooks[entryPoint], hookFunction); 5366 hooks[entryPoint].push(hookFunction);
5378 }; 5367 };
5379 5368
5380 /** 5369 /**
5381 * RemoveHook 5370 * RemoveHook
5382 * Public method to remove a DOMPurify hook at a given entryPoint 5371 * Public method to remove a DOMPurify hook at a given entryPoint
5384 * 5373 *
5385 * @param {String} entryPoint entry point for the hook to remove 5374 * @param {String} entryPoint entry point for the hook to remove
5386 */ 5375 */
5387 DOMPurify.removeHook = function (entryPoint) { 5376 DOMPurify.removeHook = function (entryPoint) {
5388 if (hooks[entryPoint]) { 5377 if (hooks[entryPoint]) {
5389 arrayPop(hooks[entryPoint]); 5378 hooks[entryPoint].pop();
5390 } 5379 }
5391 }; 5380 };
5392 5381
5393 /** 5382 /**
5394 * RemoveHooks 5383 * RemoveHooks
8036 // convert the event into a custom event to send 8025 // convert the event into a custom event to send
8037 var name = (e.target === sourceEditor ? 'scesrc' : 'scewys') + e.type; 8026 var name = (e.target === sourceEditor ? 'scesrc' : 'scewys') + e.type;
8038 8027
8039 if (eventHandlers[name]) { 8028 if (eventHandlers[name]) {
8040 eventHandlers[name].forEach(function (fn) { 8029 eventHandlers[name].forEach(function (fn) {
8041 fn.call(base, e); 8030 fn(base, e); // removed call, untested
8042 }); 8031 });
8043 } 8032 }
8044 }; 8033 };
8045 8034
8046 /** 8035 /**