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:
- Text content could be easy processed and manipulated (admittedly, I wasn't using this for anything).
- Toggling styles was as easy as adding and removing a element from <body>.</li> <li>In theory, this strategy would beat out almost every other style rule (some inline styles excepted). <a href="http://www.w3.org/TR/CSS2/cascade.html#cascading-order">User <code>!important</code> rules used to override author <code>!important</code> rules</a>, but Chrome <a href="https://src.chromium.org/viewvc/chrome?revision=234007&view=revision">no-longer does user stylesheets</a>. I figured an aggressively <code>!important</code> author stylesheet added at the very bottom of the page was pretty solid.</li> </ol> <p>After some testing, I realized that <code>!important</code> styles from <code>content_scripts</code> injection (along with chrome.tabs.insertCSS) actually <em>do</em> 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 <code>content_scripts</code>.</p> <p>This change in architecture had pros and cons.</p> <pre><code>+ 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. </code></pre> <p>This commit was essentially a full rewrite, so I changed some smaller things while I was at it:</p> <ul> <li>Styles now look for :not(.off) instead of .on. This makes the default dark and avoids a Blinding White Flash before the class changes.</li> <li>Added id specificity helpers; it's discussed further in client.js:24.</li> <li>Renamed some files for clarity.</li> </ul> <p>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 :)</p>