Socket
Socket
Sign inDemoInstall

dom-mutator

Package Overview
Dependencies
0
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.3.2 to 0.4.0

276

dist/dom-mutator.cjs.development.js

@@ -13,12 +13,8 @@ 'use strict';

function getObserverInit(attr) {
if (attr === 'html') {
return {
childList: true,
subtree: true,
attributes: true,
characterData: true
};
}
return {
return attr === 'html' ? {
childList: true,
subtree: true,
attributes: true,
characterData: true
} : {
childList: false,

@@ -31,19 +27,19 @@ subtree: false,

function getElementRecord(el) {
var ret = elements.get(el);
function getElementRecord(element) {
var record = elements.get(element);
if (!ret) {
ret = {
el: el,
if (!record) {
record = {
element: element,
attributes: {}
};
elements.set(el, ret);
elements.set(element, record);
}
return ret;
return record;
}
function newMutatedElementAttribute(el, attr, getCurrentValue, setValue, runMutations) {
function createElementPropertyRecord(el, attr, getCurrentValue, setValue, mutationRunner) {
var currentValue = getCurrentValue(el);
var ret = {
var record = {
isDirty: false,

@@ -56,29 +52,14 @@ originalValue: currentValue,

var currentValue = getCurrentValue(el);
if (currentValue === ret.virtualValue) return;
ret.originalValue = currentValue;
runMutations(ret);
if (currentValue === record.virtualValue) return;
record.originalValue = currentValue;
mutationRunner(record);
}),
runMutations: runMutations,
mutationRunner: mutationRunner,
setValue: setValue,
getCurrentValue: getCurrentValue
};
ret.observer.observe(el, getObserverInit(attr));
return ret;
record.observer.observe(el, getObserverInit(attr));
return record;
}
function stringRunner(record) {
var val = record.originalValue;
record.mutations.forEach(function (m) {
return val = m.mutate(val);
});
return val;
}
function setRunner(val, record) {
record.mutations.forEach(function (m) {
return m.mutate(val);
});
return val;
}
function queueIfNeeded(val, record) {

@@ -94,13 +75,24 @@ var currentVal = record.getCurrentValue(record.el);

function HTMLMutationRunner(record) {
queueIfNeeded(getTransformedHTML(stringRunner(record)), record);
function htmlMutationRunner(record) {
var val = record.originalValue;
record.mutations.forEach(function (m) {
return val = m.mutate(val);
});
queueIfNeeded(getTransformedHTML(val), record);
}
function ClassMutationRunner(record) {
var val = setRunner(new Set(record.originalValue.split(/\s+/).filter(Boolean)), record);
function classMutationRunner(record) {
var val = new Set(record.originalValue.split(/\s+/).filter(Boolean));
record.mutations.forEach(function (m) {
return m.mutate(val);
});
queueIfNeeded(Array.from(val).filter(Boolean).join(' '), record);
}
function AttributeMutationRunner(record) {
queueIfNeeded(stringRunner(record), record);
function attrMutationRunner(record) {
var val = record.originalValue;
record.mutations.forEach(function (m) {
return val = m.mutate(val);
});
queueIfNeeded(val, record);
}

@@ -116,7 +108,7 @@

function getElementHTMLRecord(el) {
var elementRecord = getElementRecord(el);
function getElementHTMLRecord(element) {
var elementRecord = getElementRecord(element);
if (!elementRecord.html) {
elementRecord.html = newMutatedElementAttribute(el, 'html', getHTMLValue, setHTMLValue, HTMLMutationRunner);
elementRecord.html = createElementPropertyRecord(element, 'html', getHTMLValue, setHTMLValue, htmlMutationRunner);
}

@@ -139,3 +131,3 @@

if (!elementRecord.classes) {
elementRecord.classes = newMutatedElementAttribute(el, 'class', getClassValue, setClassValue, ClassMutationRunner);
elementRecord.classes = createElementPropertyRecord(el, 'class', getClassValue, setClassValue, classMutationRunner);
}

@@ -146,2 +138,16 @@

var getAttrValue = function getAttrValue(attrName) {
return function (el) {
var _el$getAttribute;
return (_el$getAttribute = el.getAttribute(attrName)) != null ? _el$getAttribute : null;
};
};
var setAttrValue = function setAttrValue(attrName) {
return function (el, val) {
return val !== null ? el.setAttribute(attrName, val) : el.removeAttribute(attrName);
};
};
function getElementAttributeRecord(el, attr) {

@@ -151,7 +157,3 @@ var elementRecord = getElementRecord(el);

if (!elementRecord.attributes[attr]) {
elementRecord.attributes[attr] = newMutatedElementAttribute(el, attr, function (el) {
return el.getAttribute(attr) || '';
}, function (el, val) {
return val ? el.setAttribute(attr, val) : el.removeAttribute(attr);
}, AttributeMutationRunner);
elementRecord.attributes[attr] = createElementPropertyRecord(el, attr, getAttrValue(attr), setAttrValue(attr), attrMutationRunner);
}

@@ -162,6 +164,4 @@

function deleteElementAttributeRecord(el, attr) {
function deleteElementPropertyRecord(el, attr) {
var element = elements.get(el);
/* istanbul ignore next */
if (!element) return;

@@ -198,3 +198,3 @@

function setAttributeValue(el, attr, m) {
function setPropertyValue(el, attr, m) {
if (!m.isDirty) return;

@@ -205,3 +205,3 @@ m.isDirty = false;

if (!m.mutations.length) {
deleteElementAttributeRecord(el, attr);
deleteElementPropertyRecord(el, attr);
}

@@ -215,6 +215,6 @@

function setValue(m, el) {
m.html && setAttributeValue(el, 'html', m.html);
m.classes && setAttributeValue(el, 'class', m.classes);
m.html && setPropertyValue(el, 'html', m.html);
m.classes && setPropertyValue(el, 'class', m.classes);
Object.keys(m.attributes).forEach(function (attr) {
setAttributeValue(el, attr, m.attributes[attr]);
setPropertyValue(el, attr, m.attributes[attr]);
});

@@ -233,74 +233,55 @@ }

}
}
} // find or create ElementPropertyRecord, add mutation to it, then run
function startMutating(mutation, el) {
mutation.elements.add(el);
function startMutating(mutation, element) {
var record = null;
if (mutation.kind === 'html') {
var record = getElementHTMLRecord(el);
record.mutations.push(mutation);
record.runMutations(record);
record = getElementHTMLRecord(element);
} else if (mutation.kind === 'class') {
var _record = getElementClassRecord(el);
_record.mutations.push(mutation);
_record.runMutations(_record);
record = getElementClassRecord(element);
} else if (mutation.kind === 'attribute') {
var _record2 = getElementAttributeRecord(el, mutation.attribute);
record = getElementAttributeRecord(element, mutation.attribute);
}
_record2.mutations.push(mutation);
if (!record) return;
record.mutations.push(mutation);
record.mutationRunner(record);
} // get (existing) ElementPropertyRecord, remove mutation from it, then run
_record2.runMutations(_record2);
}
}
function stopMutating(mutation, el) {
mutation.elements["delete"](el);
var record = null;
if (mutation.kind === 'html') {
var record = getElementHTMLRecord(el);
var index = record.mutations.indexOf(mutation);
if (index !== -1) {
record.mutations.splice(index, 1);
}
record.runMutations(record);
record = getElementHTMLRecord(el);
} else if (mutation.kind === 'class') {
var _record3 = getElementClassRecord(el);
var _index = _record3.mutations.indexOf(mutation);
if (_index !== -1) {
_record3.mutations.splice(_index, 1);
}
_record3.runMutations(_record3);
record = getElementClassRecord(el);
} else if (mutation.kind === 'attribute') {
var _record4 = getElementAttributeRecord(el, mutation.attribute);
record = getElementAttributeRecord(el, mutation.attribute);
}
var _index2 = _record4.mutations.indexOf(mutation);
if (!record) return;
var index = record.mutations.indexOf(mutation);
if (index !== -1) record.mutations.splice(index, 1);
record.mutationRunner(record);
} // maintain list of elements associated with mutation
if (_index2 !== -1) {
_record4.mutations.splice(_index2, 1);
}
_record4.runMutations(_record4);
}
}
function refreshElementsSet(mutation) {
var existingEls = new Set(mutation.elements);
var existingElements = new Set(mutation.elements);
var newElements = new Set();
var nodes = document.querySelectorAll(mutation.selector);
nodes.forEach(function (el) {
var matchingElements = document.querySelectorAll(mutation.selector);
matchingElements.forEach(function (el) {
newElements.add(el);
if (!existingEls.has(el)) {
if (!existingElements.has(el)) {
mutation.elements.add(el);
startMutating(mutation, el);
}
});
existingEls.forEach(function (el) {
existingElements.forEach(function (el) {
if (!newElements.has(el)) {
mutation.elements["delete"](el);
stopMutating(mutation, el);

@@ -312,5 +293,4 @@ }

function revertMutation(mutation) {
var els = new Set(mutation.elements);
els.forEach(function (el) {
stopMutating(mutation, el);
mutation.elements.forEach(function (el) {
return stopMutating(mutation, el);
});

@@ -331,3 +311,2 @@ mutation.elements.clear();

function connectGlobalObserver() {
/* istanbul ignore next */
if (typeof document === 'undefined') return;

@@ -348,13 +327,12 @@

});
}
} // run on init
connectGlobalObserver();
function newMutationRecord(m) {
/* istanbul ignore next */
if (typeof document === 'undefined') {
// Not in a browser
return nullController;
}
function newMutation(m) {
// Not in a browser
if (typeof document === 'undefined') return nullController; // add to global index of mutations
mutations.add(m);
mutations.add(m); // run refresh on init to establish list of elements associated w/ mutation
refreshElementsSet(m);

@@ -369,3 +347,3 @@ return {

function html(selector, mutate) {
return newMutationRecord({
return newMutation({
kind: 'html',

@@ -379,3 +357,3 @@ elements: new Set(),

function classes(selector, mutate) {
return newMutationRecord({
return newMutation({
kind: 'class',

@@ -388,28 +366,21 @@ elements: new Set(),

function attribute(selector, attribute, _mutate) {
if (!validAttributeName.test(attribute)) {
return nullController;
}
function attribute(selector, attribute, mutate) {
if (!validAttributeName.test(attribute)) return nullController;
if (attribute === 'class' || attribute === 'className') {
return newMutationRecord({
kind: 'class',
elements: new Set(),
mutate: function mutate(classes) {
var val = _mutate(Array.from(classes).join(' '));
classes.clear();
val.split(/\s+/g).filter(Boolean).forEach(function (c) {
classes.add(c);
});
},
selector: selector
return classes(selector, function (classnames) {
var mutatedClassnames = mutate(Array.from(classnames).join(' '));
classnames.clear();
if (!mutatedClassnames) return;
mutatedClassnames.split(/\s+/g).filter(Boolean).forEach(function (c) {
return classnames.add(c);
});
});
}
return newMutationRecord({
return newMutation({
kind: 'attribute',
attribute: attribute,
elements: new Set(),
mutate: _mutate,
mutate: mutate,
selector: selector

@@ -428,7 +399,7 @@ });

return html(selector, function (val) {
return val + value;
return val + (value != null ? value : '');
});
} else if (action === 'set') {
return html(selector, function () {
return value;
return value != null ? value : '';
});

@@ -439,7 +410,7 @@ }

return classes(selector, function (val) {
return val.add(value);
if (value) val.add(value);
});
} else if (action === 'remove') {
return classes(selector, function (val) {
return val["delete"](value);
if (value) val["delete"](value);
});

@@ -449,3 +420,3 @@ } else if (action === 'set') {

val.clear();
val.add(value);
if (value) val.add(value);
});

@@ -456,8 +427,12 @@ }

return attribute(selector, attr, function (val) {
return val + value;
return val !== null ? val + (value != null ? value : '') : value != null ? value : '';
});
} else if (action === 'set') {
return attribute(selector, attr, function () {
return value;
return value != null ? value : '';
});
} else if (action === 'remove') {
return attribute(selector, attr, function () {
return null;
});
}

@@ -479,2 +454,3 @@ }

exports.disconnectGlobalObserver = disconnectGlobalObserver;
exports.validAttributeName = validAttributeName;
//# sourceMappingURL=dom-mutator.cjs.development.js.map

@@ -1,2 +0,2 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=/^[a-zA-Z:_][a-zA-Z0-9:_.-]*$/,e={revert:function(){}},n=new Map,r=new Set;function u(t){var e=n.get(t);return e||n.set(t,e={el:t,attributes:{}}),e}function i(t,e,n,r,u){var i=n(t),a={isDirty:!1,originalValue:i,virtualValue:i,mutations:[],el:t,observer:new MutationObserver((function(){var e=n(t);e!==a.virtualValue&&(a.originalValue=e,u(a))})),runMutations:u,setValue:r,getCurrentValue:n};return a.observer.observe(t,function(t){return"html"===t?{childList:!0,subtree:!0,attributes:!0,characterData:!0}:{childList:!1,subtree:!1,attributes:!0,attributeFilter:[t]}}(e)),a}function a(t){var e=t.originalValue;return t.mutations.forEach((function(t){return e=t.mutate(e)})),e}function s(t,e){var n=e.getCurrentValue(e.el);e.virtualValue=t,t!==n&&(e.isDirty=!0,g||(g=!0,requestAnimationFrame(y)))}function o(t){s(function(t){return v||(v=document.createElement("div")),v.innerHTML=t,v.innerHTML}(a(t)),t)}function l(t){var e=function(t,e){return e.mutations.forEach((function(e){return e.mutate(t)})),t}(new Set(t.originalValue.split(/\s+/).filter(Boolean)),t);s(Array.from(e).filter(Boolean).join(" "),t)}function c(t){s(a(t),t)}var f=function(t){return t.innerHTML},m=function(t,e){return t.innerHTML=e};function d(t){var e=u(t);return e.html||(e.html=i(t,"html",f,m,o)),e.html}var v,b=function(t,e){return e?t.className=e:t.removeAttribute("class")},h=function(t){return t.className};function p(t){var e=u(t);return e.classes||(e.classes=i(t,"class",h,b,l)),e.classes}function M(t,e){var n=u(t);return n.attributes[e]||(n.attributes[e]=i(t,e,(function(t){return t.getAttribute(e)||""}),(function(t,n){return n?t.setAttribute(e,n):t.removeAttribute(e)}),c)),n.attributes[e]}function w(t,e,r){if(r.isDirty){r.isDirty=!1;var u=r.virtualValue;r.mutations.length||function(t,e){var r,u,i=n.get(t);if(i)if("html"===e)null==(r=i.html)||null==(u=r.observer)||u.disconnect(),delete i.html;else if("class"===e){var a,s;null==(a=i.classes)||null==(s=a.observer)||s.disconnect(),delete i.classes}else{var o,l,c;null==(o=i.attributes)||null==(l=o[e])||null==(c=l.observer)||c.disconnect(),delete i.attributes[e]}}(t,e),r.setValue(t,u)}}var V,g=!1;function k(t,e){t.html&&w(e,"html",t.html),t.classes&&w(e,"class",t.classes),Object.keys(t.attributes).forEach((function(n){w(e,n,t.attributes[n])}))}function y(){g=!1,n.forEach(k)}function E(t,e){if(t.elements.delete(e),"html"===t.kind){var n=d(e),r=n.mutations.indexOf(t);-1!==r&&n.mutations.splice(r,1),n.runMutations(n)}else if("class"===t.kind){var u=p(e),i=u.mutations.indexOf(t);-1!==i&&u.mutations.splice(i,1),u.runMutations(u)}else if("attribute"===t.kind){var a=M(e,t.attribute),s=a.mutations.indexOf(t);-1!==s&&a.mutations.splice(s,1),a.runMutations(a)}}function A(t){var e=new Set(t.elements),n=new Set;document.querySelectorAll(t.selector).forEach((function(r){n.add(r),e.has(r)||function(t,e){if(t.elements.add(e),"html"===t.kind){var n=d(e);n.mutations.push(t),n.runMutations(n)}else if("class"===t.kind){var r=p(e);r.mutations.push(t),r.runMutations(r)}else if("attribute"===t.kind){var u=M(e,t.attribute);u.mutations.push(t),u.runMutations(u)}}(t,r)})),e.forEach((function(e){n.has(e)||E(t,e)}))}function S(){r.forEach(A)}function O(){"undefined"!=typeof document&&(V||(V=new MutationObserver((function(){S()}))),S(),V.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!1,characterData:!1}))}function x(t){return"undefined"==typeof document?e:(r.add(t),A(t),{revert:function(){var e;e=t,new Set(e.elements).forEach((function(t){E(e,t)})),e.elements.clear(),r.delete(e)}})}function L(t,e){return x({kind:"html",elements:new Set,mutate:e,selector:t})}function D(t,e){return x({kind:"class",elements:new Set,mutate:e,selector:t})}function j(n,r,u){return t.test(r)?x("class"===r||"className"===r?{kind:"class",elements:new Set,mutate:function(t){var e=u(Array.from(t).join(" "));t.clear(),e.split(/\s+/g).filter(Boolean).forEach((function(e){t.add(e)}))},selector:n}:{kind:"attribute",attribute:r,elements:new Set,mutate:u,selector:n}):e}O();var H={html:L,classes:D,attribute:j,declarative:function(t){var n=t.selector,r=t.action,u=t.value,i=t.attribute;if("html"===i){if("append"===r)return L(n,(function(t){return t+u}));if("set"===r)return L(n,(function(){return u}))}else if("class"===i){if("append"===r)return D(n,(function(t){return t.add(u)}));if("remove"===r)return D(n,(function(t){return t.delete(u)}));if("set"===r)return D(n,(function(t){t.clear(),t.add(u)}))}else{if("append"===r)return j(n,i,(function(t){return t+u}));if("set"===r)return j(n,i,(function(){return u}))}return e}};exports.connectGlobalObserver=O,exports.default=H,exports.disconnectGlobalObserver=function(){V&&V.disconnect()};
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=/^[a-zA-Z:_][a-zA-Z0-9:_.-]*$/,e={revert:function(){}},n=new Map,r=new Set;function u(t){var e=n.get(t);return e||n.set(t,e={element:t,attributes:{}}),e}function i(t,e,n,r,u){var i=n(t),a={isDirty:!1,originalValue:i,virtualValue:i,mutations:[],el:t,observer:new MutationObserver((function(){var e=n(t);e!==a.virtualValue&&(a.originalValue=e,u(a))})),mutationRunner:u,setValue:r,getCurrentValue:n};return a.observer.observe(t,function(t){return"html"===t?{childList:!0,subtree:!0,attributes:!0,characterData:!0}:{childList:!1,subtree:!1,attributes:!0,attributeFilter:[t]}}(e)),a}function a(t,e){var n=e.getCurrentValue(e.el);e.virtualValue=t,t!==n&&(e.isDirty=!0,E||(E=!0,requestAnimationFrame(A)))}function l(t){var e=t.originalValue;t.mutations.forEach((function(t){return e=t.mutate(e)})),a(function(t){return d||(d=document.createElement("div")),d.innerHTML=t,d.innerHTML}(e),t)}function s(t){var e=new Set(t.originalValue.split(/\s+/).filter(Boolean));t.mutations.forEach((function(t){return t.mutate(e)})),a(Array.from(e).filter(Boolean).join(" "),t)}function o(t){var e=t.originalValue;t.mutations.forEach((function(t){return e=t.mutate(e)})),a(e,t)}var c=function(t){return t.innerHTML},f=function(t,e){return t.innerHTML=e};function m(t){var e=u(t);return e.html||(e.html=i(t,"html",c,f,l)),e.html}var d,v=function(t,e){return e?t.className=e:t.removeAttribute("class")},b=function(t){return t.className};function h(t){var e=u(t);return e.classes||(e.classes=i(t,"class",b,v,s)),e.classes}function p(t,e){var n,r=u(t);return r.attributes[e]||(r.attributes[e]=i(t,e,(n=e,function(t){var e;return null!=(e=t.getAttribute(n))?e:null}),function(t){return function(e,n){return null!==n?e.setAttribute(t,n):e.removeAttribute(t)}}(e),o)),r.attributes[e]}function V(t,e,r){if(r.isDirty){r.isDirty=!1;var u=r.virtualValue;r.mutations.length||function(t,e){var r,u,i=n.get(t);if(i)if("html"===e)null==(r=i.html)||null==(u=r.observer)||u.disconnect(),delete i.html;else if("class"===e){var a,l;null==(a=i.classes)||null==(l=a.observer)||l.disconnect(),delete i.classes}else{var s,o,c;null==(s=i.attributes)||null==(o=s[e])||null==(c=o.observer)||c.disconnect(),delete i.attributes[e]}}(t,e),r.setValue(t,u)}}var g,E=!1;function y(t,e){t.html&&V(e,"html",t.html),t.classes&&V(e,"class",t.classes),Object.keys(t.attributes).forEach((function(n){V(e,n,t.attributes[n])}))}function A(){E=!1,n.forEach(y)}function k(t,e){var n=null;if("html"===t.kind?n=m(e):"class"===t.kind?n=h(e):"attribute"===t.kind&&(n=p(e,t.attribute)),n){var r=n.mutations.indexOf(t);-1!==r&&n.mutations.splice(r,1),n.mutationRunner(n)}}function w(t){var e=new Set(t.elements),n=new Set;document.querySelectorAll(t.selector).forEach((function(r){n.add(r),e.has(r)||(t.elements.add(r),function(t,e){var n=null;"html"===t.kind?n=m(e):"class"===t.kind?n=h(e):"attribute"===t.kind&&(n=p(e,t.attribute)),n&&(n.mutations.push(t),n.mutationRunner(n))}(t,r))})),e.forEach((function(e){n.has(e)||(t.elements.delete(e),k(t,e))}))}function M(){r.forEach(w)}function S(){"undefined"!=typeof document&&(g||(g=new MutationObserver((function(){M()}))),M(),g.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!1,characterData:!1}))}function L(t){return"undefined"==typeof document?e:(r.add(t),w(t),{revert:function(){var e;(e=t).elements.forEach((function(t){return k(e,t)})),e.elements.clear(),r.delete(e)}})}function O(t,e){return L({kind:"html",elements:new Set,mutate:e,selector:t})}function x(t,e){return L({kind:"class",elements:new Set,mutate:e,selector:t})}function D(n,r,u){return t.test(r)?"class"===r||"className"===r?x(n,(function(t){var e=u(Array.from(t).join(" "));t.clear(),e&&e.split(/\s+/g).filter(Boolean).forEach((function(e){return t.add(e)}))})):L({kind:"attribute",attribute:r,elements:new Set,mutate:u,selector:n}):e}S();var j={html:O,classes:x,attribute:D,declarative:function(t){var n=t.selector,r=t.action,u=t.value,i=t.attribute;if("html"===i){if("append"===r)return O(n,(function(t){return t+(null!=u?u:"")}));if("set"===r)return O(n,(function(){return null!=u?u:""}))}else if("class"===i){if("append"===r)return x(n,(function(t){u&&t.add(u)}));if("remove"===r)return x(n,(function(t){u&&t.delete(u)}));if("set"===r)return x(n,(function(t){t.clear(),u&&t.add(u)}))}else{if("append"===r)return D(n,i,(function(t){return null!==t?t+(null!=u?u:""):null!=u?u:""}));if("set"===r)return D(n,i,(function(){return null!=u?u:""}));if("remove"===r)return D(n,i,(function(){return null}))}return e}};exports.connectGlobalObserver=S,exports.default=j,exports.disconnectGlobalObserver=function(){g&&g.disconnect()},exports.validAttributeName=t;
//# sourceMappingURL=dom-mutator.cjs.production.min.js.map

@@ -9,12 +9,8 @@ var validAttributeName = /^[a-zA-Z:_][a-zA-Z0-9:_.-]*$/;

function getObserverInit(attr) {
if (attr === 'html') {
return {
childList: true,
subtree: true,
attributes: true,
characterData: true
};
}
return {
return attr === 'html' ? {
childList: true,
subtree: true,
attributes: true,
characterData: true
} : {
childList: false,

@@ -27,19 +23,19 @@ subtree: false,

function getElementRecord(el) {
var ret = elements.get(el);
function getElementRecord(element) {
var record = elements.get(element);
if (!ret) {
ret = {
el: el,
if (!record) {
record = {
element: element,
attributes: {}
};
elements.set(el, ret);
elements.set(element, record);
}
return ret;
return record;
}
function newMutatedElementAttribute(el, attr, getCurrentValue, setValue, runMutations) {
function createElementPropertyRecord(el, attr, getCurrentValue, setValue, mutationRunner) {
var currentValue = getCurrentValue(el);
var ret = {
var record = {
isDirty: false,

@@ -52,29 +48,14 @@ originalValue: currentValue,

var currentValue = getCurrentValue(el);
if (currentValue === ret.virtualValue) return;
ret.originalValue = currentValue;
runMutations(ret);
if (currentValue === record.virtualValue) return;
record.originalValue = currentValue;
mutationRunner(record);
}),
runMutations: runMutations,
mutationRunner: mutationRunner,
setValue: setValue,
getCurrentValue: getCurrentValue
};
ret.observer.observe(el, getObserverInit(attr));
return ret;
record.observer.observe(el, getObserverInit(attr));
return record;
}
function stringRunner(record) {
var val = record.originalValue;
record.mutations.forEach(function (m) {
return val = m.mutate(val);
});
return val;
}
function setRunner(val, record) {
record.mutations.forEach(function (m) {
return m.mutate(val);
});
return val;
}
function queueIfNeeded(val, record) {

@@ -90,13 +71,24 @@ var currentVal = record.getCurrentValue(record.el);

function HTMLMutationRunner(record) {
queueIfNeeded(getTransformedHTML(stringRunner(record)), record);
function htmlMutationRunner(record) {
var val = record.originalValue;
record.mutations.forEach(function (m) {
return val = m.mutate(val);
});
queueIfNeeded(getTransformedHTML(val), record);
}
function ClassMutationRunner(record) {
var val = setRunner(new Set(record.originalValue.split(/\s+/).filter(Boolean)), record);
function classMutationRunner(record) {
var val = new Set(record.originalValue.split(/\s+/).filter(Boolean));
record.mutations.forEach(function (m) {
return m.mutate(val);
});
queueIfNeeded(Array.from(val).filter(Boolean).join(' '), record);
}
function AttributeMutationRunner(record) {
queueIfNeeded(stringRunner(record), record);
function attrMutationRunner(record) {
var val = record.originalValue;
record.mutations.forEach(function (m) {
return val = m.mutate(val);
});
queueIfNeeded(val, record);
}

@@ -112,7 +104,7 @@

function getElementHTMLRecord(el) {
var elementRecord = getElementRecord(el);
function getElementHTMLRecord(element) {
var elementRecord = getElementRecord(element);
if (!elementRecord.html) {
elementRecord.html = newMutatedElementAttribute(el, 'html', getHTMLValue, setHTMLValue, HTMLMutationRunner);
elementRecord.html = createElementPropertyRecord(element, 'html', getHTMLValue, setHTMLValue, htmlMutationRunner);
}

@@ -135,3 +127,3 @@

if (!elementRecord.classes) {
elementRecord.classes = newMutatedElementAttribute(el, 'class', getClassValue, setClassValue, ClassMutationRunner);
elementRecord.classes = createElementPropertyRecord(el, 'class', getClassValue, setClassValue, classMutationRunner);
}

@@ -142,2 +134,16 @@

var getAttrValue = function getAttrValue(attrName) {
return function (el) {
var _el$getAttribute;
return (_el$getAttribute = el.getAttribute(attrName)) != null ? _el$getAttribute : null;
};
};
var setAttrValue = function setAttrValue(attrName) {
return function (el, val) {
return val !== null ? el.setAttribute(attrName, val) : el.removeAttribute(attrName);
};
};
function getElementAttributeRecord(el, attr) {

@@ -147,7 +153,3 @@ var elementRecord = getElementRecord(el);

if (!elementRecord.attributes[attr]) {
elementRecord.attributes[attr] = newMutatedElementAttribute(el, attr, function (el) {
return el.getAttribute(attr) || '';
}, function (el, val) {
return val ? el.setAttribute(attr, val) : el.removeAttribute(attr);
}, AttributeMutationRunner);
elementRecord.attributes[attr] = createElementPropertyRecord(el, attr, getAttrValue(attr), setAttrValue(attr), attrMutationRunner);
}

@@ -158,6 +160,4 @@

function deleteElementAttributeRecord(el, attr) {
function deleteElementPropertyRecord(el, attr) {
var element = elements.get(el);
/* istanbul ignore next */
if (!element) return;

@@ -194,3 +194,3 @@

function setAttributeValue(el, attr, m) {
function setPropertyValue(el, attr, m) {
if (!m.isDirty) return;

@@ -201,3 +201,3 @@ m.isDirty = false;

if (!m.mutations.length) {
deleteElementAttributeRecord(el, attr);
deleteElementPropertyRecord(el, attr);
}

@@ -211,6 +211,6 @@

function setValue(m, el) {
m.html && setAttributeValue(el, 'html', m.html);
m.classes && setAttributeValue(el, 'class', m.classes);
m.html && setPropertyValue(el, 'html', m.html);
m.classes && setPropertyValue(el, 'class', m.classes);
Object.keys(m.attributes).forEach(function (attr) {
setAttributeValue(el, attr, m.attributes[attr]);
setPropertyValue(el, attr, m.attributes[attr]);
});

@@ -229,74 +229,55 @@ }

}
}
} // find or create ElementPropertyRecord, add mutation to it, then run
function startMutating(mutation, el) {
mutation.elements.add(el);
function startMutating(mutation, element) {
var record = null;
if (mutation.kind === 'html') {
var record = getElementHTMLRecord(el);
record.mutations.push(mutation);
record.runMutations(record);
record = getElementHTMLRecord(element);
} else if (mutation.kind === 'class') {
var _record = getElementClassRecord(el);
_record.mutations.push(mutation);
_record.runMutations(_record);
record = getElementClassRecord(element);
} else if (mutation.kind === 'attribute') {
var _record2 = getElementAttributeRecord(el, mutation.attribute);
record = getElementAttributeRecord(element, mutation.attribute);
}
_record2.mutations.push(mutation);
if (!record) return;
record.mutations.push(mutation);
record.mutationRunner(record);
} // get (existing) ElementPropertyRecord, remove mutation from it, then run
_record2.runMutations(_record2);
}
}
function stopMutating(mutation, el) {
mutation.elements["delete"](el);
var record = null;
if (mutation.kind === 'html') {
var record = getElementHTMLRecord(el);
var index = record.mutations.indexOf(mutation);
if (index !== -1) {
record.mutations.splice(index, 1);
}
record.runMutations(record);
record = getElementHTMLRecord(el);
} else if (mutation.kind === 'class') {
var _record3 = getElementClassRecord(el);
var _index = _record3.mutations.indexOf(mutation);
if (_index !== -1) {
_record3.mutations.splice(_index, 1);
}
_record3.runMutations(_record3);
record = getElementClassRecord(el);
} else if (mutation.kind === 'attribute') {
var _record4 = getElementAttributeRecord(el, mutation.attribute);
record = getElementAttributeRecord(el, mutation.attribute);
}
var _index2 = _record4.mutations.indexOf(mutation);
if (!record) return;
var index = record.mutations.indexOf(mutation);
if (index !== -1) record.mutations.splice(index, 1);
record.mutationRunner(record);
} // maintain list of elements associated with mutation
if (_index2 !== -1) {
_record4.mutations.splice(_index2, 1);
}
_record4.runMutations(_record4);
}
}
function refreshElementsSet(mutation) {
var existingEls = new Set(mutation.elements);
var existingElements = new Set(mutation.elements);
var newElements = new Set();
var nodes = document.querySelectorAll(mutation.selector);
nodes.forEach(function (el) {
var matchingElements = document.querySelectorAll(mutation.selector);
matchingElements.forEach(function (el) {
newElements.add(el);
if (!existingEls.has(el)) {
if (!existingElements.has(el)) {
mutation.elements.add(el);
startMutating(mutation, el);
}
});
existingEls.forEach(function (el) {
existingElements.forEach(function (el) {
if (!newElements.has(el)) {
mutation.elements["delete"](el);
stopMutating(mutation, el);

@@ -308,5 +289,4 @@ }

function revertMutation(mutation) {
var els = new Set(mutation.elements);
els.forEach(function (el) {
stopMutating(mutation, el);
mutation.elements.forEach(function (el) {
return stopMutating(mutation, el);
});

@@ -327,3 +307,2 @@ mutation.elements.clear();

function connectGlobalObserver() {
/* istanbul ignore next */
if (typeof document === 'undefined') return;

@@ -344,13 +323,12 @@

});
}
} // run on init
connectGlobalObserver();
function newMutationRecord(m) {
/* istanbul ignore next */
if (typeof document === 'undefined') {
// Not in a browser
return nullController;
}
function newMutation(m) {
// Not in a browser
if (typeof document === 'undefined') return nullController; // add to global index of mutations
mutations.add(m);
mutations.add(m); // run refresh on init to establish list of elements associated w/ mutation
refreshElementsSet(m);

@@ -365,3 +343,3 @@ return {

function html(selector, mutate) {
return newMutationRecord({
return newMutation({
kind: 'html',

@@ -375,3 +353,3 @@ elements: new Set(),

function classes(selector, mutate) {
return newMutationRecord({
return newMutation({
kind: 'class',

@@ -384,28 +362,21 @@ elements: new Set(),

function attribute(selector, attribute, _mutate) {
if (!validAttributeName.test(attribute)) {
return nullController;
}
function attribute(selector, attribute, mutate) {
if (!validAttributeName.test(attribute)) return nullController;
if (attribute === 'class' || attribute === 'className') {
return newMutationRecord({
kind: 'class',
elements: new Set(),
mutate: function mutate(classes) {
var val = _mutate(Array.from(classes).join(' '));
classes.clear();
val.split(/\s+/g).filter(Boolean).forEach(function (c) {
classes.add(c);
});
},
selector: selector
return classes(selector, function (classnames) {
var mutatedClassnames = mutate(Array.from(classnames).join(' '));
classnames.clear();
if (!mutatedClassnames) return;
mutatedClassnames.split(/\s+/g).filter(Boolean).forEach(function (c) {
return classnames.add(c);
});
});
}
return newMutationRecord({
return newMutation({
kind: 'attribute',
attribute: attribute,
elements: new Set(),
mutate: _mutate,
mutate: mutate,
selector: selector

@@ -424,7 +395,7 @@ });

return html(selector, function (val) {
return val + value;
return val + (value != null ? value : '');
});
} else if (action === 'set') {
return html(selector, function () {
return value;
return value != null ? value : '';
});

@@ -435,7 +406,7 @@ }

return classes(selector, function (val) {
return val.add(value);
if (value) val.add(value);
});
} else if (action === 'remove') {
return classes(selector, function (val) {
return val["delete"](value);
if (value) val["delete"](value);
});

@@ -445,3 +416,3 @@ } else if (action === 'set') {

val.clear();
val.add(value);
if (value) val.add(value);
});

@@ -452,8 +423,12 @@ }

return attribute(selector, attr, function (val) {
return val + value;
return val !== null ? val + (value != null ? value : '') : value != null ? value : '';
});
} else if (action === 'set') {
return attribute(selector, attr, function () {
return value;
return value != null ? value : '';
});
} else if (action === 'remove') {
return attribute(selector, attr, function () {
return null;
});
}

@@ -473,3 +448,3 @@ }

export default index;
export { connectGlobalObserver, disconnectGlobalObserver };
export { connectGlobalObserver, disconnectGlobalObserver, validAttributeName };
//# sourceMappingURL=dom-mutator.esm.js.map

@@ -0,6 +1,7 @@

export declare const validAttributeName: RegExp;
export declare function disconnectGlobalObserver(): void;
export declare function connectGlobalObserver(): void;
declare function html(selector: string, mutate: (value: string) => string): MutationController;
declare function classes(selector: string, mutate: (classes: Set<string>) => void): MutationController;
declare function attribute(selector: string, attribute: string, mutate: (value: string) => string): MutationController;
declare function html(selector: HTMLMutation['selector'], mutate: HTMLMutation['mutate']): MutationController;
declare function classes(selector: ClassnameMutation['selector'], mutate: ClassnameMutation['mutate']): MutationController;
declare function attribute(selector: AttrMutation['selector'], attribute: AttrMutation['attribute'], mutate: AttrMutation['mutate']): MutationController;
declare function declarative({ selector, action, value, attribute: attr, }: DeclarativeMutation): MutationController;

@@ -14,3 +15,3 @@ export declare type MutationController = {

action: 'append' | 'set' | 'remove';
value: string;
value?: string;
};

@@ -17,0 +18,0 @@ declare const _default: {

@@ -1,41 +0,40 @@

interface HTMLMutationRecord {
kind: 'html';
interface BaseMutation {
selector: string;
mutate: (val: string) => string;
elements: Set<Element>;
}
interface ClassMutationRecord {
interface HTMLMutation extends BaseMutation {
kind: 'html';
mutate: (innerHtml: string) => string;
}
interface ClassnameMutation extends BaseMutation {
kind: 'class';
selector: string;
mutate: (val: Set<string>) => void;
elements: Set<Element>;
mutate: (classNames: Set<string>) => void;
}
interface AttributeMutationRecord {
interface AttrMutation extends BaseMutation {
kind: 'attribute';
attribute: string;
selector: string;
mutate: (val: string) => string;
elements: Set<Element>;
mutate: (value: string | null) => string | null;
}
declare type AnyMutationRecord = StringMutationRecord | SetMutationRecord;
declare type StringMutationRecord = HTMLMutationRecord | AttributeMutationRecord;
declare type SetMutationRecord = ClassMutationRecord;
interface ElementAttributeRecord<T> {
declare type Mutation = HTMLMutation | ClassnameMutation | AttrMutation;
interface ElementPropertyRecord<T, V> {
observer: MutationObserver;
originalValue: string;
virtualValue: string;
originalValue: V;
virtualValue: V;
isDirty: boolean;
mutations: T[];
el: Element;
getCurrentValue: (el: Element) => string;
setValue: (el: Element, value: string) => void;
runMutations: (record: ElementAttributeRecord<T>) => void;
getCurrentValue: (el: Element) => V;
setValue: (el: Element, value: V) => void;
mutationRunner: (record: ElementPropertyRecord<T, V>) => void;
}
declare type HTMLRecord = ElementPropertyRecord<HTMLMutation, string>;
declare type ClassnameRecord = ElementPropertyRecord<ClassnameMutation, string>;
declare type AttributeRecord = ElementPropertyRecord<AttrMutation, string | null>;
interface ElementRecord {
el: Element;
html?: ElementAttributeRecord<HTMLMutationRecord>;
classes?: ElementAttributeRecord<ClassMutationRecord>;
element: Element;
html?: HTMLRecord;
classes?: ClassnameRecord;
attributes: {
[key: string]: ElementAttributeRecord<AttributeMutationRecord>;
[key: string]: AttributeRecord;
};
}
{
"version": "0.3.2",
"version": "0.4.0",
"license": "MIT",

@@ -4,0 +4,0 @@ "main": "dist/index.js",

@@ -1,2 +0,2 @@

const validAttributeName = /^[a-zA-Z:_][a-zA-Z0-9:_.-]*$/;
export const validAttributeName = /^[a-zA-Z:_][a-zA-Z0-9:_.-]*$/;
const nullController: MutationController = {

@@ -7,39 +7,40 @@ revert: () => {},

const elements: Map<Element, ElementRecord> = new Map();
const mutations: Set<AnyMutationRecord> = new Set();
const mutations: Set<Mutation> = new Set();
function getObserverInit(attr: string): MutationObserverInit {
if (attr === 'html') {
return {
childList: true,
subtree: true,
attributes: true,
characterData: true,
};
}
return {
childList: false,
subtree: false,
attributes: true,
attributeFilter: [attr],
};
return attr === 'html'
? {
childList: true,
subtree: true,
attributes: true,
characterData: true,
}
: {
childList: false,
subtree: false,
attributes: true,
attributeFilter: [attr],
};
}
function getElementRecord(el: Element): ElementRecord {
let ret = elements.get(el);
if (!ret) {
ret = { el, attributes: {} };
elements.set(el, ret);
function getElementRecord(element: Element): ElementRecord {
let record = elements.get(element);
if (!record) {
record = { element, attributes: {} };
elements.set(element, record);
}
return ret;
return record;
}
function newMutatedElementAttribute<T>(
function createElementPropertyRecord(
el: Element,
attr: string,
getCurrentValue: (el: Element) => string,
setValue: (el: Element, val: string) => void,
runMutations: (record: ElementAttributeRecord<T>) => void
): ElementAttributeRecord<T> {
getCurrentValue: (el: Element) => any,
setValue: (el: Element, val: any) => void,
mutationRunner: (record: ElementPropertyRecord<any, any>) => void
) {
const currentValue = getCurrentValue(el);
const ret: ElementAttributeRecord<T> = {
const record: ElementPropertyRecord<any, any> = {
isDirty: false,

@@ -52,39 +53,17 @@ originalValue: currentValue,

const currentValue = getCurrentValue(el);
if (currentValue === ret.virtualValue) return;
ret.originalValue = currentValue;
runMutations(ret);
if (currentValue === record.virtualValue) return;
record.originalValue = currentValue;
mutationRunner(record);
}),
runMutations,
mutationRunner,
setValue,
getCurrentValue,
};
ret.observer.observe(el, getObserverInit(attr));
return ret;
record.observer.observe(el, getObserverInit(attr));
return record;
}
function stringRunner(record: {
originalValue: string;
mutations: { mutate: (v: string) => string }[];
}) {
let val = record.originalValue;
record.mutations.forEach(m => (val = m.mutate(val)));
return val;
}
function setRunner(
val: Set<string>,
record: {
mutations: { mutate: (v: Set<string>) => void }[];
}
) {
record.mutations.forEach(m => m.mutate(val));
return val;
}
function queueIfNeeded(
val: string,
record: {
el: Element;
getCurrentValue: (el: Element) => string;
virtualValue: string;
isDirty: boolean;
}
val: string | null,
record: ElementPropertyRecord<any, any>
) {

@@ -99,14 +78,10 @@ const currentVal = record.getCurrentValue(record.el);

function HTMLMutationRunner(
record: ElementAttributeRecord<HTMLMutationRecord>
) {
queueIfNeeded(getTransformedHTML(stringRunner(record)), record);
function htmlMutationRunner(record: HTMLRecord) {
let val = record.originalValue;
record.mutations.forEach(m => (val = m.mutate(val)));
queueIfNeeded(getTransformedHTML(val), record);
}
function ClassMutationRunner(
record: ElementAttributeRecord<ClassMutationRecord>
) {
const val = setRunner(
new Set(record.originalValue.split(/\s+/).filter(Boolean)),
record
);
function classMutationRunner(record: ClassnameRecord) {
const val = new Set(record.originalValue.split(/\s+/).filter(Boolean));
record.mutations.forEach(m => m.mutate(val));
queueIfNeeded(

@@ -119,6 +94,6 @@ Array.from(val)

}
function AttributeMutationRunner(
record: ElementAttributeRecord<AttributeMutationRecord>
) {
queueIfNeeded(stringRunner(record), record);
function attrMutationRunner(record: AttributeRecord) {
let val: string | null = record.originalValue;
record.mutations.forEach(m => (val = m.mutate(val)));
queueIfNeeded(val, record);
}

@@ -128,13 +103,11 @@

const setHTMLValue = (el: Element, value: string) => (el.innerHTML = value);
function getElementHTMLRecord(
el: Element
): ElementAttributeRecord<HTMLMutationRecord> {
const elementRecord = getElementRecord(el);
function getElementHTMLRecord(element: Element): HTMLRecord {
const elementRecord = getElementRecord(element);
if (!elementRecord.html) {
elementRecord.html = newMutatedElementAttribute(
el,
elementRecord.html = createElementPropertyRecord(
element,
'html',
getHTMLValue,
setHTMLValue,
HTMLMutationRunner
htmlMutationRunner
);

@@ -148,8 +121,6 @@ }

const getClassValue = (el: Element) => el.className;
function getElementClassRecord(
el: Element
): ElementAttributeRecord<ClassMutationRecord> {
function getElementClassRecord(el: Element): ClassnameRecord {
const elementRecord = getElementRecord(el);
if (!elementRecord.classes) {
elementRecord.classes = newMutatedElementAttribute(
elementRecord.classes = createElementPropertyRecord(
el,

@@ -159,3 +130,3 @@ 'class',

setClassValue,
ClassMutationRunner
classMutationRunner
);

@@ -166,15 +137,15 @@ }

function getElementAttributeRecord(
el: Element,
attr: string
): ElementAttributeRecord<AttributeMutationRecord> {
const getAttrValue = (attrName: string) => (el: Element) =>
el.getAttribute(attrName) ?? null;
const setAttrValue = (attrName: string) => (el: Element, val: string | null) =>
val !== null ? el.setAttribute(attrName, val) : el.removeAttribute(attrName);
function getElementAttributeRecord(el: Element, attr: string): AttributeRecord {
const elementRecord = getElementRecord(el);
if (!elementRecord.attributes[attr]) {
elementRecord.attributes[attr] = newMutatedElementAttribute(
elementRecord.attributes[attr] = createElementPropertyRecord(
el,
attr,
el => el.getAttribute(attr) || '',
(el, val) =>
val ? el.setAttribute(attr, val) : el.removeAttribute(attr),
AttributeMutationRunner
getAttrValue(attr),
setAttrValue(attr),
attrMutationRunner
);

@@ -185,5 +156,4 @@ }

function deleteElementAttributeRecord(el: Element, attr: string) {
function deleteElementPropertyRecord(el: Element, attr: string) {
const element = elements.get(el);
/* istanbul ignore next */
if (!element) return;

@@ -211,6 +181,6 @@ if (attr === 'html') {

function setAttributeValue<T>(
function setPropertyValue<T extends ElementPropertyRecord<any, any>>(
el: Element,
attr: string,
m: ElementAttributeRecord<T>
m: T
) {

@@ -221,3 +191,3 @@ if (!m.isDirty) return;

if (!m.mutations.length) {
deleteElementAttributeRecord(el, attr);
deleteElementPropertyRecord(el, attr);
}

@@ -228,7 +198,8 @@ m.setValue(el, val);

let raf = false;
function setValue(m: ElementRecord, el: Element) {
m.html && setAttributeValue(el, 'html', m.html);
m.classes && setAttributeValue(el, 'class', m.classes);
m.html && setPropertyValue<HTMLRecord>(el, 'html', m.html);
m.classes && setPropertyValue<ClassnameRecord>(el, 'class', m.classes);
Object.keys(m.attributes).forEach(attr => {
setAttributeValue(el, attr, m.attributes[attr]);
setPropertyValue<AttributeRecord>(el, attr, m.attributes[attr]);
});

@@ -247,54 +218,43 @@ }

function startMutating(mutation: AnyMutationRecord, el: Element) {
mutation.elements.add(el);
// find or create ElementPropertyRecord, add mutation to it, then run
function startMutating(mutation: Mutation, element: Element) {
let record: ElementPropertyRecord<any, any> | null = null;
if (mutation.kind === 'html') {
const record = getElementHTMLRecord(el);
record.mutations.push(mutation);
record.runMutations(record);
record = getElementHTMLRecord(element);
} else if (mutation.kind === 'class') {
const record = getElementClassRecord(el);
record.mutations.push(mutation);
record.runMutations(record);
record = getElementClassRecord(element);
} else if (mutation.kind === 'attribute') {
const record = getElementAttributeRecord(el, mutation.attribute);
record.mutations.push(mutation);
record.runMutations(record);
record = getElementAttributeRecord(element, mutation.attribute);
}
if (!record) return;
record.mutations.push(mutation);
record.mutationRunner(record);
}
function stopMutating(mutation: AnyMutationRecord, el: Element) {
mutation.elements.delete(el);
// get (existing) ElementPropertyRecord, remove mutation from it, then run
function stopMutating(mutation: Mutation, el: Element) {
let record: ElementPropertyRecord<any, any> | null = null;
if (mutation.kind === 'html') {
const record = getElementHTMLRecord(el);
const index = record.mutations.indexOf(mutation);
if (index !== -1) {
record.mutations.splice(index, 1);
}
record.runMutations(record);
record = getElementHTMLRecord(el);
} else if (mutation.kind === 'class') {
const record = getElementClassRecord(el);
const index = record.mutations.indexOf(mutation);
if (index !== -1) {
record.mutations.splice(index, 1);
}
record.runMutations(record);
record = getElementClassRecord(el);
} else if (mutation.kind === 'attribute') {
const record = getElementAttributeRecord(el, mutation.attribute);
const index = record.mutations.indexOf(mutation);
if (index !== -1) {
record.mutations.splice(index, 1);
}
record.runMutations(record);
record = getElementAttributeRecord(el, mutation.attribute);
}
if (!record) return;
const index = record.mutations.indexOf(mutation);
if (index !== -1) record.mutations.splice(index, 1);
record.mutationRunner(record);
}
function refreshElementsSet(mutation: AnyMutationRecord) {
const existingEls = new Set(mutation.elements);
// maintain list of elements associated with mutation
function refreshElementsSet(mutation: Mutation) {
const existingElements = new Set(mutation.elements);
const newElements: Set<Element> = new Set();
const nodes = document.querySelectorAll(mutation.selector);
nodes.forEach(el => {
const matchingElements = document.querySelectorAll(mutation.selector);
matchingElements.forEach(el => {
newElements.add(el);
if (!existingEls.has(el)) {
if (!existingElements.has(el)) {
mutation.elements.add(el);
startMutating(mutation, el);

@@ -304,4 +264,5 @@ }

existingEls.forEach(el => {
existingElements.forEach(el => {
if (!newElements.has(el)) {
mutation.elements.delete(el);
stopMutating(mutation, el);

@@ -312,7 +273,4 @@ }

function revertMutation(mutation: AnyMutationRecord) {
const els = new Set(mutation.elements);
els.forEach(el => {
stopMutating(mutation, el);
});
function revertMutation(mutation: Mutation) {
mutation.elements.forEach(el => stopMutating(mutation, el));
mutation.elements.clear();

@@ -332,3 +290,2 @@ mutations.delete(mutation);

export function connectGlobalObserver() {
/* istanbul ignore next */
if (typeof document === 'undefined') return;

@@ -350,14 +307,13 @@

}
// run on init
connectGlobalObserver();
function newMutationRecord(m: AnyMutationRecord): MutationController {
/* istanbul ignore next */
if (typeof document === 'undefined') {
// Not in a browser
return nullController;
}
function newMutation(m: Mutation): MutationController {
// Not in a browser
if (typeof document === 'undefined') return nullController;
// add to global index of mutations
mutations.add(m);
// run refresh on init to establish list of elements associated w/ mutation
refreshElementsSet(m);
return {

@@ -370,4 +326,7 @@ revert: () => {

function html(selector: string, mutate: (value: string) => string) {
return newMutationRecord({
function html(
selector: HTMLMutation['selector'],
mutate: HTMLMutation['mutate']
) {
return newMutation({
kind: 'html',

@@ -380,4 +339,7 @@ elements: new Set(),

function classes(selector: string, mutate: (classes: Set<string>) => void) {
return newMutationRecord({
function classes(
selector: ClassnameMutation['selector'],
mutate: ClassnameMutation['mutate']
) {
return newMutation({
kind: 'class',

@@ -389,29 +351,23 @@ elements: new Set(),

}
function attribute(
selector: string,
attribute: string,
mutate: (value: string) => string
selector: AttrMutation['selector'],
attribute: AttrMutation['attribute'],
mutate: AttrMutation['mutate']
) {
if (!validAttributeName.test(attribute)) {
return nullController;
}
if (!validAttributeName.test(attribute)) return nullController;
if (attribute === 'class' || attribute === 'className') {
return newMutationRecord({
kind: 'class',
elements: new Set(),
mutate: classes => {
const val = mutate(Array.from(classes).join(' '));
classes.clear();
val
.split(/\s+/g)
.filter(Boolean)
.forEach(c => {
classes.add(c);
});
},
selector,
return classes(selector, classnames => {
const mutatedClassnames = mutate(Array.from(classnames).join(' '));
classnames.clear();
if (!mutatedClassnames) return;
mutatedClassnames
.split(/\s+/g)
.filter(Boolean)
.forEach(c => classnames.add(c));
});
}
return newMutationRecord({
return newMutation({
kind: 'attribute',

@@ -433,15 +389,19 @@ attribute,

if (action === 'append') {
return html(selector, val => val + value);
return html(selector, val => val + (value ?? ''));
} else if (action === 'set') {
return html(selector, () => value);
return html(selector, () => value ?? '');
}
} else if (attr === 'class') {
if (action === 'append') {
return classes(selector, val => val.add(value));
return classes(selector, val => {
if (value) val.add(value);
});
} else if (action === 'remove') {
return classes(selector, val => val.delete(value));
return classes(selector, val => {
if (value) val.delete(value);
});
} else if (action === 'set') {
return classes(selector, val => {
val.clear();
val.add(value);
if (value) val.add(value);
});

@@ -451,5 +411,9 @@ }

if (action === 'append') {
return attribute(selector, attr, val => val + value);
return attribute(selector, attr, val =>
val !== null ? val + (value ?? '') : value ?? ''
);
} else if (action === 'set') {
return attribute(selector, attr, () => value);
return attribute(selector, attr, () => value ?? '');
} else if (action === 'remove') {
return attribute(selector, attr, () => null);
}

@@ -468,3 +432,3 @@ }

action: 'append' | 'set' | 'remove';
value: string;
value?: string;
};

@@ -471,0 +435,0 @@

@@ -1,44 +0,47 @@

interface HTMLMutationRecord {
kind: 'html';
interface BaseMutation {
selector: string;
mutate: (val: string) => string;
elements: Set<Element>;
}
interface ClassMutationRecord {
interface HTMLMutation extends BaseMutation {
kind: 'html';
mutate: (innerHtml: string) => string;
}
interface ClassnameMutation extends BaseMutation {
kind: 'class';
selector: string;
mutate: (val: Set<string>) => void;
elements: Set<Element>;
mutate: (classNames: Set<string>) => void;
}
interface AttributeMutationRecord {
interface AttrMutation extends BaseMutation {
kind: 'attribute';
attribute: string;
selector: string;
mutate: (val: string) => string;
elements: Set<Element>;
mutate: (value: string | null) => string | null;
}
type AnyMutationRecord = StringMutationRecord | SetMutationRecord;
type StringMutationRecord = HTMLMutationRecord | AttributeMutationRecord;
type Mutation = HTMLMutation | ClassnameMutation | AttrMutation;
type SetMutationRecord = ClassMutationRecord;
interface ElementAttributeRecord<T> {
interface ElementPropertyRecord<T, V> {
observer: MutationObserver;
originalValue: string;
virtualValue: string;
originalValue: V;
virtualValue: V;
isDirty: boolean;
mutations: T[];
el: Element;
getCurrentValue: (el: Element) => string;
setValue: (el: Element, value: string) => void;
runMutations: (record: ElementAttributeRecord<T>) => void;
getCurrentValue: (el: Element) => V;
setValue: (el: Element, value: V) => void;
mutationRunner: (record: ElementPropertyRecord<T, V>) => void;
}
type HTMLRecord = ElementPropertyRecord<HTMLMutation, string>;
type ClassnameRecord = ElementPropertyRecord<ClassnameMutation, string>;
type AttributeRecord = ElementPropertyRecord<AttrMutation, string | null>;
interface ElementRecord {
el: Element;
html?: ElementAttributeRecord<HTMLMutationRecord>;
classes?: ElementAttributeRecord<ClassMutationRecord>;
element: Element;
html?: HTMLRecord;
classes?: ClassnameRecord;
attributes: {
[key: string]: ElementAttributeRecord<AttributeMutationRecord>;
[key: string]: AttributeRecord;
};
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc