preserve style element name during livePreview
also strip _ from methods as we don't use such convention
This commit is contained in:
		
							parent
							
								
									fcad0ee523
								
							
						
					
					
						commit
						2e021f6ac9
					
				| 
						 | 
					@ -9,8 +9,8 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
  const PATCH_ID = 'transition-patch';
 | 
					  const PATCH_ID = 'transition-patch';
 | 
				
			||||||
  // styles are out of order if any of these elements is injected between them
 | 
					  // styles are out of order if any of these elements is injected between them
 | 
				
			||||||
  const ORDERED_TAGS = new Set(['head', 'body', 'frameset', 'style', 'link']);
 | 
					  const ORDERED_TAGS = new Set(['head', 'body', 'frameset', 'style', 'link']);
 | 
				
			||||||
  const docRewriteObserver = RewriteObserver(_sort);
 | 
					  const docRewriteObserver = RewriteObserver(sort);
 | 
				
			||||||
  const docRootObserver = RootObserver(_sortIfNeeded);
 | 
					  const docRootObserver = RootObserver(sortIfNeeded);
 | 
				
			||||||
  const toSafeChar = c => String.fromCharCode(0xFF00 + c.charCodeAt(0) - 0x20);
 | 
					  const toSafeChar = c => String.fromCharCode(0xFF00 + c.charCodeAt(0) - 0x20);
 | 
				
			||||||
  const list = [];
 | 
					  const list = [];
 | 
				
			||||||
  const table = new Map();
 | 
					  const table = new Map();
 | 
				
			||||||
| 
						 | 
					@ -25,24 +25,24 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    list,
 | 
					    list,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async apply(styleMap) {
 | 
					    async apply(styleMap) {
 | 
				
			||||||
      const styles = _styleMapToArray(styleMap);
 | 
					      const styles = styleMapToArray(styleMap);
 | 
				
			||||||
      const value = !styles.length
 | 
					      const value = !styles.length
 | 
				
			||||||
        ? []
 | 
					        ? []
 | 
				
			||||||
        : await docRootObserver.evade(() => {
 | 
					        : await docRootObserver.evade(() => {
 | 
				
			||||||
          if (!isTransitionPatched && isEnabled) {
 | 
					          if (!isTransitionPatched && isEnabled) {
 | 
				
			||||||
            _applyTransitionPatch(styles);
 | 
					            applyTransitionPatch(styles);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          return styles.map(_addUpdate);
 | 
					          return styles.map(addUpdate);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      _emitUpdate();
 | 
					      emitUpdate();
 | 
				
			||||||
      return value;
 | 
					      return value;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clear() {
 | 
					    clear() {
 | 
				
			||||||
      _addRemoveElements(false);
 | 
					      addRemoveElements(false);
 | 
				
			||||||
      list.length = 0;
 | 
					      list.length = 0;
 | 
				
			||||||
      table.clear();
 | 
					      table.clear();
 | 
				
			||||||
      _emitUpdate();
 | 
					      emitUpdate();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clearOrphans() {
 | 
					    clearOrphans() {
 | 
				
			||||||
| 
						 | 
					@ -55,12 +55,12 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    remove(id) {
 | 
					    remove(id) {
 | 
				
			||||||
      _remove(id);
 | 
					      remove(id);
 | 
				
			||||||
      _emitUpdate();
 | 
					      emitUpdate();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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 = [];
 | 
				
			||||||
      for (const style of list) {
 | 
					      for (const style of list) {
 | 
				
			||||||
| 
						 | 
					@ -68,24 +68,24 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
          removed.push(style.id);
 | 
					          removed.push(style.id);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      styles.forEach(_addUpdate);
 | 
					      styles.forEach(addUpdate);
 | 
				
			||||||
      removed.forEach(_remove);
 | 
					      removed.forEach(remove);
 | 
				
			||||||
      _emitUpdate();
 | 
					      emitUpdate();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    toggle(enable) {
 | 
					    toggle(enable) {
 | 
				
			||||||
      if (isEnabled === enable) return;
 | 
					      if (isEnabled === enable) return;
 | 
				
			||||||
      isEnabled = enable;
 | 
					      isEnabled = enable;
 | 
				
			||||||
      if (!enable) _toggleObservers(false);
 | 
					      if (!enable) toggleObservers(false);
 | 
				
			||||||
      _addRemoveElements(enable);
 | 
					      addRemoveElements(enable);
 | 
				
			||||||
      if (enable) _toggleObservers(true);
 | 
					      if (enable) toggleObservers(true);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sort: _sort,
 | 
					    sort: sort,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _add(style) {
 | 
					  function add(style) {
 | 
				
			||||||
    const el = style.el = _createStyle(style);
 | 
					    const el = style.el = createStyle(style);
 | 
				
			||||||
    const i = list.findIndex(item => compare(item, style) > 0);
 | 
					    const i = list.findIndex(item => compare(item, style) > 0);
 | 
				
			||||||
    table.set(style.id, style);
 | 
					    table.set(style.id, style);
 | 
				
			||||||
    if (isEnabled) {
 | 
					    if (isEnabled) {
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,7 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    return el;
 | 
					    return el;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _addRemoveElements(add) {
 | 
					  function addRemoveElements(add) {
 | 
				
			||||||
    for (const {el} of list) {
 | 
					    for (const {el} of list) {
 | 
				
			||||||
      if (add) {
 | 
					      if (add) {
 | 
				
			||||||
        document.documentElement.appendChild(el);
 | 
					        document.documentElement.appendChild(el);
 | 
				
			||||||
| 
						 | 
					@ -105,11 +105,11 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _addUpdate(style) {
 | 
					  function addUpdate(style) {
 | 
				
			||||||
    return table.has(style.id) ? _update(style) : _add(style);
 | 
					    return table.has(style.id) ? update(style) : add(style);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _applyTransitionPatch(styles) {
 | 
					  function applyTransitionPatch(styles) {
 | 
				
			||||||
    isTransitionPatched = true;
 | 
					    isTransitionPatched = true;
 | 
				
			||||||
    // CSS transition bug workaround: since we insert styles asynchronously,
 | 
					    // CSS transition bug workaround: since we insert styles asynchronously,
 | 
				
			||||||
    // the browsers, especially Firefox, may apply all transitions on page load
 | 
					    // the browsers, especially Firefox, may apply all transitions on page load
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
        !styles.some(s => s.code.includes('transition'))) {
 | 
					        !styles.some(s => s.code.includes('transition'))) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const el = _createStyle({id: PATCH_ID, code: `
 | 
					    const el = createStyle({id: PATCH_ID, code: `
 | 
				
			||||||
      :root:not(#\\0):not(#\\0) * {
 | 
					      :root:not(#\\0):not(#\\0) * {
 | 
				
			||||||
        transition: none !important;
 | 
					        transition: none !important;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -129,8 +129,9 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    requestAnimationFrame(() => setTimeout(() => el.remove()));
 | 
					    requestAnimationFrame(() => setTimeout(() => el.remove()));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _createStyle({id, code = '', name} = {}) {
 | 
					  function createStyle(style = {}) {
 | 
				
			||||||
    if (!creationDoc) _initCreationDoc();
 | 
					    const {id} = style;
 | 
				
			||||||
 | 
					    if (!creationDoc) initCreationDoc();
 | 
				
			||||||
    let el;
 | 
					    let el;
 | 
				
			||||||
    if (document.documentElement instanceof SVGSVGElement) {
 | 
					    if (document.documentElement instanceof SVGSVGElement) {
 | 
				
			||||||
      // SVG document style
 | 
					      // SVG document style
 | 
				
			||||||
| 
						 | 
					@ -147,26 +148,30 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
      const oldEl = document.getElementById(el.id);
 | 
					      const oldEl = document.getElementById(el.id);
 | 
				
			||||||
      if (oldEl) oldEl.id += '-superseded-by-Stylus';
 | 
					      if (oldEl) oldEl.id += '-superseded-by-Stylus';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    el.type = 'text/css';
 | 
				
			||||||
 | 
					    // SVG className is not a string, but an instance of SVGAnimatedString
 | 
				
			||||||
 | 
					    el.classList.add('stylus');
 | 
				
			||||||
 | 
					    setTextAndName(el, style);
 | 
				
			||||||
 | 
					    return el;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function setTextAndName(el, {id, code = '', name}) {
 | 
				
			||||||
    if (exposeStyleName && name) {
 | 
					    if (exposeStyleName && name) {
 | 
				
			||||||
      el.dataset.name = name;
 | 
					      el.dataset.name = name;
 | 
				
			||||||
      name = encodeURIComponent(name.replace(/[#%/@:']/g, toSafeChar));
 | 
					      name = encodeURIComponent(name.replace(/[#%/@:']/g, toSafeChar));
 | 
				
			||||||
      code += `\n/*# sourceURL=${chrome.runtime.getURL(name)}.user.css#${id} */`;
 | 
					      code += `\n/*# sourceURL=${chrome.runtime.getURL(name)}.user.css#${id} */`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    el.type = 'text/css';
 | 
					 | 
				
			||||||
    // SVG className is not a string, but an instance of SVGAnimatedString
 | 
					 | 
				
			||||||
    el.classList.add('stylus');
 | 
					 | 
				
			||||||
    el.textContent = code;
 | 
					    el.textContent = code;
 | 
				
			||||||
    return el;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _toggleObservers(shouldStart) {
 | 
					  function toggleObservers(shouldStart) {
 | 
				
			||||||
    const onOff = shouldStart && isEnabled ? 'start' : 'stop';
 | 
					    const onOff = shouldStart && isEnabled ? 'start' : 'stop';
 | 
				
			||||||
    docRewriteObserver[onOff]();
 | 
					    docRewriteObserver[onOff]();
 | 
				
			||||||
    docRootObserver[onOff]();
 | 
					    docRootObserver[onOff]();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _emitUpdate() {
 | 
					  function emitUpdate() {
 | 
				
			||||||
    _toggleObservers(list.length);
 | 
					    toggleObservers(list.length);
 | 
				
			||||||
    onUpdate();
 | 
					    onUpdate();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,11 +182,11 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
  and since userAgent.navigator can be spoofed via about:config or devtools,
 | 
					  and since userAgent.navigator can be spoofed via about:config or devtools,
 | 
				
			||||||
  we're checking for getPreventDefault that was removed in FF59
 | 
					  we're checking for getPreventDefault that was removed in FF59
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
  function _initCreationDoc() {
 | 
					  function initCreationDoc() {
 | 
				
			||||||
    creationDoc = !Event.prototype.getPreventDefault && document.wrappedJSObject;
 | 
					    creationDoc = !Event.prototype.getPreventDefault && document.wrappedJSObject;
 | 
				
			||||||
    if (creationDoc) {
 | 
					    if (creationDoc) {
 | 
				
			||||||
      ({createElement, createElementNS} = creationDoc);
 | 
					      ({createElement, createElementNS} = creationDoc);
 | 
				
			||||||
      const el = document.documentElement.appendChild(_createStyle());
 | 
					      const el = document.documentElement.appendChild(createStyle());
 | 
				
			||||||
      const isApplied = el.sheet;
 | 
					      const isApplied = el.sheet;
 | 
				
			||||||
      el.remove();
 | 
					      el.remove();
 | 
				
			||||||
      if (isApplied) return;
 | 
					      if (isApplied) return;
 | 
				
			||||||
| 
						 | 
					@ -190,7 +195,7 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    ({createElement, createElementNS} = document);
 | 
					    ({createElement, createElementNS} = document);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _remove(id) {
 | 
					  function remove(id) {
 | 
				
			||||||
    const style = table.get(id);
 | 
					    const style = table.get(id);
 | 
				
			||||||
    if (!style) return;
 | 
					    if (!style) return;
 | 
				
			||||||
    table.delete(id);
 | 
					    table.delete(id);
 | 
				
			||||||
| 
						 | 
					@ -198,14 +203,14 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    style.el.remove();
 | 
					    style.el.remove();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _sort() {
 | 
					  function sort() {
 | 
				
			||||||
    docRootObserver.evade(() => {
 | 
					    docRootObserver.evade(() => {
 | 
				
			||||||
      list.sort(compare);
 | 
					      list.sort(compare);
 | 
				
			||||||
      _addRemoveElements(true);
 | 
					      addRemoveElements(true);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _sortIfNeeded() {
 | 
					  function sortIfNeeded() {
 | 
				
			||||||
    let needsSort;
 | 
					    let needsSort;
 | 
				
			||||||
    let el = list.length && list[0].el;
 | 
					    let el = list.length && list[0].el;
 | 
				
			||||||
    if (!el) {
 | 
					    if (!el) {
 | 
				
			||||||
| 
						 | 
					@ -226,13 +231,15 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
      // some styles are not injected to the document
 | 
					      // some styles are not injected to the document
 | 
				
			||||||
      if (i < list.length) needsSort = true;
 | 
					      if (i < list.length) needsSort = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (needsSort) _sort();
 | 
					    if (needsSort) sort();
 | 
				
			||||||
    return needsSort;
 | 
					    return needsSort;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _styleMapToArray(styleMap) {
 | 
					  function styleMapToArray(styleMap) {
 | 
				
			||||||
    ({exposeStyleName} = styleMap.cfg || {});
 | 
					    if (styleMap.cfg) {
 | 
				
			||||||
 | 
					      ({exposeStyleName} = styleMap.cfg);
 | 
				
			||||||
      delete styleMap.cfg;
 | 
					      delete styleMap.cfg;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return Object.values(styleMap).map(({id, code, name}) => ({
 | 
					    return Object.values(styleMap).map(({id, code, name}) => ({
 | 
				
			||||||
      id,
 | 
					      id,
 | 
				
			||||||
      name,
 | 
					      name,
 | 
				
			||||||
| 
						 | 
					@ -240,11 +247,13 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    }));
 | 
					    }));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function _update({id, code}) {
 | 
					  function update(newStyle) {
 | 
				
			||||||
 | 
					    const {id, code} = newStyle;
 | 
				
			||||||
    const style = table.get(id);
 | 
					    const style = table.get(id);
 | 
				
			||||||
    if (style.code !== code) {
 | 
					    if (style.code !== code ||
 | 
				
			||||||
 | 
					        style.name !== newStyle.name && exposeStyleName) {
 | 
				
			||||||
      style.code = code;
 | 
					      style.code = code;
 | 
				
			||||||
      style.el.textContent = code;
 | 
					      setTextAndName(style.el, newStyle);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -253,14 +262,14 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    let root;
 | 
					    let root;
 | 
				
			||||||
    let observing = false;
 | 
					    let observing = false;
 | 
				
			||||||
    let timer;
 | 
					    let timer;
 | 
				
			||||||
    const observer = new MutationObserver(_check);
 | 
					    const observer = new MutationObserver(check);
 | 
				
			||||||
    return {start, stop};
 | 
					    return {start, stop};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function start() {
 | 
					    function start() {
 | 
				
			||||||
      if (observing) return;
 | 
					      if (observing) return;
 | 
				
			||||||
      // detect dynamic iframes rewritten after creation by the embedder i.e. externally
 | 
					      // detect dynamic iframes rewritten after creation by the embedder i.e. externally
 | 
				
			||||||
      root = document.documentElement;
 | 
					      root = document.documentElement;
 | 
				
			||||||
      timer = setTimeout(_check);
 | 
					      timer = setTimeout(check);
 | 
				
			||||||
      observer.observe(document, {childList: true});
 | 
					      observer.observe(document, {childList: true});
 | 
				
			||||||
      observing = true;
 | 
					      observing = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -272,7 +281,7 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
      observing = false;
 | 
					      observing = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function _check() {
 | 
					    function check() {
 | 
				
			||||||
      if (root !== document.documentElement) {
 | 
					      if (root !== document.documentElement) {
 | 
				
			||||||
        root = document.documentElement;
 | 
					        root = document.documentElement;
 | 
				
			||||||
        onChange();
 | 
					        onChange();
 | 
				
			||||||
| 
						 | 
					@ -302,7 +311,7 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
    function evade(fn) {
 | 
					    function evade(fn) {
 | 
				
			||||||
      const restore = observing && start;
 | 
					      const restore = observing && start;
 | 
				
			||||||
      stop();
 | 
					      stop();
 | 
				
			||||||
      return new Promise(resolve => _run(fn, resolve, _waitForRoot))
 | 
					      return new Promise(resolve => run(fn, resolve, waitForRoot))
 | 
				
			||||||
        .then(restore);
 | 
					        .then(restore);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,7 +329,7 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
      observing = false;
 | 
					      observing = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function _run(fn, resolve, wait) {
 | 
					    function run(fn, resolve, wait) {
 | 
				
			||||||
      if (document.documentElement) {
 | 
					      if (document.documentElement) {
 | 
				
			||||||
        resolve(fn());
 | 
					        resolve(fn());
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
| 
						 | 
					@ -328,8 +337,8 @@ window.StyleInjector = window.INJECTED === 1 ? window.StyleInjector : ({
 | 
				
			||||||
      if (wait) wait(fn, resolve);
 | 
					      if (wait) wait(fn, resolve);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function _waitForRoot(...args) {
 | 
					    function waitForRoot(...args) {
 | 
				
			||||||
      new MutationObserver((_, observer) => _run(...args) && observer.disconnect())
 | 
					      new MutationObserver((_, observer) => run(...args) && observer.disconnect())
 | 
				
			||||||
        .observe(document, {childList: true});
 | 
					        .observe(document, {childList: true});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user