Combine several incompatible selectors in one rule (es6)

by denvdmj

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify-css.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.11.0/highlight.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.11.0/styles/androidstudio.min.css">
<input class="range" type="range" value="0" max="1000" min="0" />

<h2>Source CSS</h2>
<pre id="idOutputCSS1"></pre>
<h2>Current CSS</h2>
<pre id="idOutputCSS2"></pre>
<p>now open this fiddle in firefox</p>

<pre style="display:none">
Firefox:
::-moz-range-track
::-moz-range-thumb

Internet Explorer:
::-ms-thumb
::-ms-track
::-ms-fill-lower
::-ms-fill-upper

Webkit (Chrome, Safari, Opera):
::-webkit-slider-runnable-track
::-webkit-slider-thumb
</pre>


<style>
@import url(https://codepen.io/DenVdmj/pen/NBGQxq.css);
body { font: condensed 17px/1.5 Roboto }
pre { margin: 1em 0; padding: 1em; font-size: 14px }
#idOutputCSS1 { border-top: 6px solid #099 }
#idOutputCSS2 { border-top: 6px solid #909 }
</style>

CSS

.range {
  margin: 0;
  height: 20px;
  width: calc(100% - 10px);
  background-color: #999;
 -webkit-appearance: none;
}


.range\:\:-webkit-slider-thumb,
.range\:\:-moz-range-thumb {
 -webkit-appearance: none;
  border: 1px solid red;
  border-radius: 5px;
  padding: 0;
  margin: 0;
  width: 30px;
  height: 30px;
  background-color: #BC9;
}

JavaScript

(() => {
  //
  // work arround for сombine several incompatible selectors in one rule:
  //
  for (let sheet of document.styleSheets) {
    // except those that are added dynamically
    if (!sheet.ownerNode.firstChild && !sheet.ownerNode.href) continue;
    let cssRulesEntries;
    // test on cors error
    try {
			cssRulesEntries = [].entries.call(sheet.cssRules);
    } catch (e) {
     	continue;
    }
    // patching styles:
    for (let [index, rule] of cssRulesEntries) {
      for (let selector of (rule.selectorText||'').split(/\s*,\s*/)) {
        const match = selector.match(/^(.*?)((?:\\:){1,2})(-[\w-]+)/);
        if (!match) continue;
        const cssText = match[1] + match[2].replace(/\\/g,'') +
          match[3] + ' ' + rule.cssText.substr(rule.selectorText.length+1);

        try {
          sheet.insertRule(cssText, index+1);
          sheet.deleteRule(index);
        } catch (err) {}
      }
    }
  }
})();

//////////
// DEMO //
//////////

const getCurrentCSS = filter => {
  const list = [];
  for (let sheet of document.styleSheets) {
    if (!sheet.ownerNode.firstChild && !sheet.ownerNode.href) continue;
    try { sheet.cssRules } catch (e) { continue }
    for (let rule of Array.prototype.values.call(sheet.cssRules)) {
      if (filter.test(rule.cssText))
        list.push(rule.cssText);
    }
  }
  return list.join('\n');
};

const option = { indent_size: 2 };

idOutputCSS1.textContent =
  css_beautify(
    document.querySelector('head > style').textContent,
    option
  )
;

idOutputCSS2.textContent =
  css_beautify(getCurrentCSS(/^\s*\.range/), option)
;

hljs.highlightBlock(idOutputCSS1);
hljs.highlightBlock(idOutputCSS2);