add/remove style elements on global toggle (#990)

This commit is contained in:
tophf 2020-07-15 07:31:33 +03:00 committed by GitHub
parent 787466fc40
commit 7e6edb9e1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -19,52 +19,47 @@ self.createStyleInjector = self.INJECTED === 1 ? self.createStyleInjector : ({
let isTransitionPatched; let isTransitionPatched;
// will store the original method refs because the page can override them // will store the original method refs because the page can override them
let creationDoc, createElement, createElementNS; let creationDoc, createElement, createElementNS;
return {
apply,
clear,
clearOrphans,
remove,
replace,
toggle,
list,
};
function apply(styleMap) { return {
list,
apply(styleMap) {
const styles = _styleMapToArray(styleMap); const styles = _styleMapToArray(styleMap);
return !styles.length ? return (
!styles.length ?
Promise.resolve([]) : Promise.resolve([]) :
docRootObserver.evade(() => { docRootObserver.evade(() => {
if (!isTransitionPatched) _applyTransitionPatch(styles); if (!isTransitionPatched && isEnabled) {
const els = styles.map(_apply); _applyTransitionPatch(styles);
_emitUpdate();
return els;
});
} }
return styles.map(_addUpdate);
})
).then(_emitUpdate);
},
function clear() { clear() {
for (const style of list) { _addRemoveElements(false);
style.el.remove();
}
list.length = 0; list.length = 0;
table.clear(); table.clear();
_emitUpdate(); _emitUpdate();
} },
function clearOrphans() { clearOrphans() {
for (const el of document.querySelectorAll(`style[id^="${PREFIX}"].stylus`)) { for (const el of document.querySelectorAll(`style[id^="${PREFIX}"].stylus`)) {
const id = el.id.slice(PREFIX.length); const id = el.id.slice(PREFIX.length);
if (/^\d+$/.test(id) || id === PATCH_ID) { if (/^\d+$/.test(id) || id === PATCH_ID) {
el.remove(); el.remove();
} }
} }
} },
function remove(id) { remove(id) {
_remove(id); _remove(id);
_emitUpdate(); _emitUpdate();
} },
function replace(styleMap) { replace(styleMap) {
const styles = _styleMapToArray(styleMap); const styles = _styleMapToArray(styleMap);
const added = new Set(styles.map(s => s.id)); const added = new Set(styles.map(s => s.id));
const removed = []; const removed = [];
@ -73,36 +68,42 @@ self.createStyleInjector = self.INJECTED === 1 ? self.createStyleInjector : ({
removed.push(style.id); removed.push(style.id);
} }
} }
styles.forEach(_apply); styles.forEach(_addUpdate);
removed.forEach(_remove); removed.forEach(_remove);
_emitUpdate(); _emitUpdate();
} },
function toggle(_enabled) { toggle(enable) {
if (isEnabled === _enabled) return; if (isEnabled === enable) return;
isEnabled = _enabled; isEnabled = enable;
for (const style of list) { if (!enable) _toggleObservers(false);
style.el.disabled = !isEnabled; _addRemoveElements(enable);
} if (enable) _toggleObservers(true);
} },
};
function _add(style) { function _add(style) {
const el = style.el = _createStyle(style.id, style.code); const el = style.el = _createStyle(style.id, style.code);
const i = list.findIndex(item => compare(item, style) > 0);
table.set(style.id, style); table.set(style.id, style);
const nextIndex = list.findIndex(i => compare(i, style) > 0); list.splice(i < 0 ? list.length : i, 0, style);
if (nextIndex < 0) { if (isEnabled) {
document.documentElement.appendChild(el); document.documentElement.insertBefore(el, i < 0 ? null : list[i].el);
list.push(style);
} else {
document.documentElement.insertBefore(el, list[nextIndex].el);
list.splice(nextIndex, 0, style);
} }
// moving an element resets its 'disabled' state
el.disabled = !isEnabled;
return el; return el;
} }
function _apply(style) { function _addRemoveElements(add) {
for (const {el} of list) {
if (add) {
document.documentElement.appendChild(el);
} else {
el.remove();
}
}
}
function _addUpdate(style) {
return table.has(style.id) ? _update(style) : _add(style); return table.has(style.id) ? _update(style) : _add(style);
} }
@ -151,15 +152,16 @@ self.createStyleInjector = self.INJECTED === 1 ? self.createStyleInjector : ({
return el; return el;
} }
function _emitUpdate() { function _toggleObservers(shouldStart) {
if (!IS_OWN_PAGE && list.length) { const onOff = shouldStart && isEnabled ? 'start' : 'stop';
docRewriteObserver.start(); docRewriteObserver[onOff]();
docRootObserver.start(); docRootObserver[onOff]();
} else {
docRewriteObserver.stop();
docRootObserver.stop();
} }
function _emitUpdate(value) {
_toggleObservers(!IS_OWN_PAGE && list.length);
onUpdate(); onUpdate();
return value;
} }
/* /*
@ -193,11 +195,7 @@ self.createStyleInjector = self.INJECTED === 1 ? self.createStyleInjector : ({
function _sort() { function _sort() {
docRootObserver.evade(() => { docRootObserver.evade(() => {
list.sort(compare); list.sort(compare);
for (const style of list) { _addRemoveElements(true);
// moving an element resets its 'disabled' state
document.documentElement.appendChild(style.el);
style.el.disabled = !isEnabled;
}
}); });
} }
@ -241,13 +239,13 @@ self.createStyleInjector = self.INJECTED === 1 ? self.createStyleInjector : ({
if (isChromePre65) { if (isChromePre65) {
const oldEl = style.el; const oldEl = style.el;
style.el = _createStyle(id, code); style.el = _createStyle(id, code);
if (isEnabled) {
oldEl.parentNode.insertBefore(style.el, oldEl.nextSibling); oldEl.parentNode.insertBefore(style.el, oldEl.nextSibling);
oldEl.remove(); oldEl.remove();
}
} else { } else {
style.el.textContent = code; style.el.textContent = code;
} }
// https://github.com/openstyles/stylus/issues/693
style.el.disabled = !isEnabled;
} }
function RewriteObserver(onChange) { function RewriteObserver(onChange) {