Rewrite extension and update version to 3.0.0 rileyjshaw/dark-theme-everywhere

Initially, this extension grabbed the content of a CSS file with an XMLHttpRequest and injected it into the bottom of the page. This had a few advantages:

  1. Text content could be easy processed and manipulated (admittedly, I wasn't using this for anything).
  2. Toggling styles was as easy as adding and removing a <style> element from <body>.
  3. In theory, this strategy would beat out almost every other style rule (some inline styles excepted). User !important rules used to override author !important rules, but Chrome no-longer does user stylesheets. I figured an aggressively !important author stylesheet added at the very bottom of the page was pretty solid.

After some testing, I realized that !important styles from content_scripts injection (along with chrome.tabs.insertCSS) actually do take precedence over author stylesheets. Since 3) was the key consideration for my original decision, I re-wrote the extension to inject a stylesheet from content_scripts.

This change in architecture had pros and cons.

+ Improved chance of dark theme winning out over author styles.
+ Allowed styles to be applied before any other DOM is constructed, substantially reducing time-to-darkness.
+ Simplified the callbacks between background.js and client.js, reduced code, and made the entire extension easier to reason about.

- With 1) above, I could've handled variant rules (eg. specificityHelper) with a few regular expressions. Locking into a static stylesheet added some huge copypastas, tripling the size of main.css.
- Injected stylesheets aren't accessible once they've been added. Rather than "turning the styles off" like in 2), the best option was to add a toggle class to <body>.
- Rewrites take time.

This commit was essentially a full rewrite, so I changed some smaller things while I was at it:

  • Styles now look for :not(.off) instead of .on. This makes the default dark and avoids a Blinding White Flash before the class changes.
  • Added id specificity helpers; it's discussed further in client.js:24.
  • Renamed some files for clarity.

I came across some unfortunate Chromium bugs while working on this, which caused me to dive into that project. It's huge! Lots of fun to poke around :)