A place to cache linked articles (think custom and personal wayback machine)
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

2 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Why not everything I do is “Open” or “Free” (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Documented, feel free to shoot an email. -->
  28. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  29. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  30. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  31. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  36. <script>
  37. function toggleTheme(themeName) {
  38. document.documentElement.classList.toggle(
  39. 'forced-dark',
  40. themeName === 'dark'
  41. )
  42. document.documentElement.classList.toggle(
  43. 'forced-light',
  44. themeName === 'light'
  45. )
  46. }
  47. const selectedTheme = localStorage.getItem('theme')
  48. if (selectedTheme !== 'undefined') {
  49. toggleTheme(selectedTheme)
  50. }
  51. </script>
  52. <meta name="robots" content="noindex, nofollow">
  53. <meta content="origin-when-cross-origin" name="referrer">
  54. <!-- Canonical URL for SEO purposes -->
  55. <link rel="canonical" href="https://overengineer.dev/blog/2021/12/12/why-not-everything-i-do-is-open-or-free.html">
  56. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  57. <article>
  58. <header>
  59. <h1>Why not everything I do is “Open” or “Free”</h1>
  60. </header>
  61. <nav>
  62. <p class="center">
  63. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  64. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  65. </svg> Accueil</a> •
  66. <a href="https://overengineer.dev/blog/2021/12/12/why-not-everything-i-do-is-open-or-free.html" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <p>There is a high chance that, if you know me, you know me for some of my work on Free and/or Open Source projects, and you might know me as a supporter of such projects and parts of the culture. So it might seem odd that I deliberately decide <em>not</em> to release some of my work under such terms. I have been asked so many times about this, I decided to take the time and put my thoughts into a thing I can link to. This is more a collection of individual thoughts rather than a cohesive article.</p>
  71. <h2 id="software-projects">Software projects</h2>
  72. <p>I consider myself lucky in the way that I not only got the chance to work on and with a lot of amazing Free and/or Open Source projects in my free time, but that I am also able to spend my workdays working on Open Source software and earn my living that way. I had the chance to join a great project in its early days. Over time, that project grew to over 12k stars on GitHub, and I eventually ended up leading that project from an administrative side. Unfortunately, while most of that work was incredibly rewarding and fun, I also learned about the issues in such projects.</p>
  73. <h3 id="code-dumping-does-not-work">“Code dumping” does not work</h3>
  74. <p>A lot of people suggest “just upload your code to a code-sharing site and be done with it”. Not only do I personally find that incredibly counterproductive, but the whole idea of “Dump and Forget” does not work out.</p>
  75. <p>Imagine building a little RTMP server in Rust, because you are frustrated with the nginx RTMP modules, and you wanted to learn Rust anyway. So you create a public GitHub repository and start working on it. After some months, you have reached a state where “the basics work just fine”, and then you stop working on it because you moved on towards new and more exciting things. Maybe you even had the foresight to add a “this project is incomplete and unmaintained” notice to the README. Sometime in the future, somebody will find your project. It could be that they searched for “RTMP server in Rust” and found it. Maybe they just looked through the “#rtmp” tag on GitHub, or they reached your project by other means. And instead of just moving on and looking at other projects, some people <em>will</em> skip your warnings.</p>
  76. <p>I had multiple projects of that kind. And even though I had very explicit warnings about projects not being production-ready in the README - some projects even had the “archived” status on GitHub - that did not stop people from actually looking into it. I received countless issues and emails with “suggestions” (read: demands) on what to add and questions about how to build and run things because some outdated dependency did break or was no longer available. I even once had a company reach out to me, asking for help because a piece of server automation I shared ended up messing up their production environment, hoping I could help them figure out what happened. Unfortunately, I could not, and I ended up deleting that project.</p>
  77. <p>When I share software projects publicly, then I do this because I think that a) someone could use that project to help them solve an issue, or b) they could learn something from looking at how I solved an issue or how I implemented a specific piece of logic. Quite honestly, for most of the projects we all create “on the side”, neither is true. Dumping unfinished, unpolished, unmaintained, and potentially badly designed or even insecure projects onto the internet is not benefitting anyone.</p>
  78. <h3 id="open-source-is-not-just-about-open-source">Open Source is not just about open source</h3>
  79. <p>Here is the thing: making a project’s code accessible to any audience is just a small piece of running an open-source <em>project</em>. Take GitHub, for example: you can turn off the issue tracker and turn off project discussions, but you cannot turn off the ability for people to create pull requests. And I get that, the whole “fork it, change it, and submit your changes upstream” culture is a huge part of open source - and one part I really like about (F)OSS projects.</p>
  80. <p>The problem, though, is that reviewing pull requests, paying adequate attention, and providing helpful feedback takes <em>a lot</em> of time and energy. Reviewing code sometimes feels harder than writing code, and I do believe that this is true to a certain extend: you not only have to understand the intentions of the person writing the code, you also have to think about how this new code fits into the existing system and if there are any side-effects that might be tricky to catch from looking at the implementation itself. As an individual who just uploaded pieces of code to GitHub without considering them “a project”, you have two options:</p>
  81. <ol>
  82. <li>Just merging pretty much everything without too much care or attention. This is surprisingly common in smaller projects, but I can’t see how that’s a good idea. Projects that work like that frequently make breaking changes by accident, break completely, or end up in a state where the code is inconsistent or hard to maintain. When your project is large enough that people actually do submit pull requests for it, then your project is likely used by a non-zero amount of other folks. Leaving your project in an unstable or unpredictable state will cause more frustration and harm than not making your project available in the first place.</li>
  83. <li>Ignoring Pull Requests completely. This is just… kinda disrespectful. Sure, if you have a note in your README that says you’ll not accept pull requests, or something similar, then you would be justified in just ignoring them or closing them without taking a look. But if you get a pull request, then someone else has spent time on your project, and just throwing that away is not good. Ignoring pull requests has an unfortunate side effect as well: the people working on and with your project could just continue their work in their own fork without ever bringing the changes upstream. This might sound like a feature at first, but this can become harmful as soon as there is more than one active fork. Forks usually do not sync back up, so you end up with multiple completely diverging projects that all have their pros and cons, and the “which fork should I be using?” question becomes a big issue for users.</li>
  84. </ol>
  85. <p>Running a (F)OSS project is not just about managing contributions to code, though. You will also get questions from users of your project, you usually have to provide a lot of documentation, maybe even plan out “stable” releases, and properly tag and distribute those… There’s a lot of stuff that needs to be done, and that all takes a lot of time. If you’re not committed to spending that time, then you cannot run a project, and you shouldn’t even try.</p>
  86. <h3 id="when-projects-become-big">When projects become big</h3>
  87. <p>If you are lucky - or unlucky - enough, your project might become big. Unless you are a company, or your project is for some other reason part of your work life and not just a volunteering side project, I consider projects becoming big a curse. The increase in contributors is not proportional to the increase of time and effort you have to spend to keep a project alive. Even if you publish something like a code library that’s only ever used by fellow programmers, the amount of questions and suggestions will always exceed the number of contributions - and unfortunately, providing support is one of the tasks most contributors don’t like to help out on, because “that’s the maintainers job”.</p>
  88. <p>In one large project I’ve worked on, I found myself in a situation where 90% of my time was spent helping people, leading discussions, generally moderating communication channels, reviewing pull requests, making architectural suggestions, … - and only 10% with actually writing code. All that non-code work can be super fun and rewarding, and I enjoyed it a lot. But if you start a project because you want to write code, this can be troubling. :)</p>
  89. <p>One thing that <em>does</em> scale with your project size is the number of bad actors. And I’m not even talking about people who’re trying to find security vulnerabilities in your project with malicious intents, but rather people who disrupt discussions and people whose primary motivation appears to be to annoy maintainers. Now, this is obviously not a binary state, but rather a huge gradient of different behaviors, and sometimes, the bad behavior might not even be deliberate.</p>
  90. <p>If you are using a project, and that project breaks or changes in a way that you find bad, you might be annoyed. If you found a project that <em>almost</em> solves your need but falls short on a single aspect, you might request a feature or suggest a change, and you might be agitated if you do not get positive responses to that. If you are a contributor, and your pull request got rejected, or you just received the fourth round of review tasks that will take you multiple days, you might be angry and wish for that task to just be done already. All those people might use a project’s discussion board, chatrooms, issue trackers, or just social media, to vent that frustration. And honestly, I kinda get that.</p>
  91. <p>Unfortunately, all this sums up if you are on the receiving end of those vents. You could leave all that stuff alone and just ignore it, but you know that this will turn your project’s communication channel into a wasteland that nobody can use productively. Or you start moderating things, but this will make the people in question even angrier and thus will cause you even more work. There is no win-condition here, and no matter how Rainbow Unicorn’y your project is, you <em>will</em> run into those situations.</p>
  92. <p>As soon as your project becomes big, a lot of people will be very angry with you, all the time, for all kinds of reasons. The project’s website with documentation went down while you were sleeping? You shipped a bug affecting a company that makes millions with an application that uses your library? You need more than eleven seconds to resolve a security issue and ship a release? You decide that you would like to take the project in a different direction and one of your contributors is not happy with it? You decide that you will not be looking at this one giant pull request this Sunday? You asked for … a donation? You will be yelled at, no matter what you do.</p>
  93. <h3 id="responsibility-and-mental-stress">Responsibility, and mental stress</h3>
  94. <p>I am trying to make this post as generic as possible, but this is a section where I have to talk about <em>me</em>. Many people are fine with the things I wrote above, and they can just deal with the constant negative things and just feed off the positive experiences. Unfortunately, I am not that kind of person. Nobody would call 2020 or 2021 <em>good</em> years, but for me, my (F)OSS work reached a point where I had to hit the emergency brake. While I am usually okay with not letting yelling people get to me, brains do this funny thing where they accumulate multiple simultaneous problems into a state where everything wants to explode.</p>
  95. <p>I worked on a project that was always very important to me for years. Not just because I used it a lot, but also because I thought it was an important project and because I liked the community around it. Over time, I naturally “evolved” from writing code into spending most of my time with the other non-code’y things I mentioned above, and honestly, I quite liked it. At one point, I decided that the project’s less-than-ideal public-facing website, as well as developer and user documentation, is something that needs more attention. So I did what every rational human would do and came up with a plan to rebuild everything in that category completely from scratch. You will not be surprised to learn that, while this decision made sense and the plans I came up with were pretty good, this did not get done. There just were too many other things that needed to be done, and I am not the kind of person who gets a lot of satisfaction out of spending all of my free time writing documentation and marketing texts.</p>
  96. <p>However, this left me in a peculiar spot. We all agreed that this work was important, I started this work, and I owned this work. More often than not, when I felt like working on that project, I did not feel like working on the documentation piece. But because I felt this work was the <em>most important</em> thing I could do, I convinced myself that I should prioritize that work and not do other things. This, however, only resulted in me not doing anything at all. Eventually, I felt <em>bad</em> for not working on that project and then tried to force myself into it. This <em>worked</em> a bit, but my output was, naturally, not the best quality. Because the project was important to me, and because I can be a bit of a perfectionist, this led into a spiral where I felt bad for the work that was done and thus felt like not working on it, while also feeling bad for not working on it. Very fun state to be in!</p>
  97. <p>I tried powering through that, and this is how it went:</p>
  98. <p class="center"><img src="/statics/blog/20211212/github-graph.png" alt='A screenshot of the "GitHub Contribution Graph". The first half of the graph shows a lot of activity, where the majority of squares are marked. The second half, however, shows a significant drop in activity.' class="center">
  99. (<em>Screenshot of my “GitHub Contribution Graph”, taken in May 2021. You can clearly see the point where I decided I had enough: December 2020.</em>)</p>
  100. <p>This “documentation project” issue alone would have been resolvable. I could have just ended that project or gotten other people into contributing more to those efforts. Unfortunately, such problems never come alone in large projects because you’re not working alone and you’re not in a bubble. In my case, these feelings were paired with me using that project less and less, with a not insignificant amount of people constantly demanding to implement certain features, asking “why is X not done yet?”, and continuously criticizing some of my decisions and some of the project’s decision in a very aggressive manner.</p>
  101. <p>I ended up completely dropping out of that project as a way of preserving my mental health. In fact, I dropped out of all my (F)OSS projects, and I even deleted some of my “code dump” projects on GitHub.</p>
  102. <p>Now, I’m not going to write about burnout, especially (F)OSS maintainer’s burnout, or about the unreasonable expectations people have towards project maintainers. If you have read this post this far, you most likely have read articles about this that explained things far better than I could do. But this whole ordeal has absolutely contributed to my decision to massively scale down the number of “open” and “free” things I work on. If I want to release a project as Open Source, then I absolutely want to make sure that these things do not become an issue again. However, for most projects, this kind of preparation is simply not worth it.</p>
  103. <h2 id="hardware-projects-and-hardware-designs">Hardware projects and hardware designs</h2>
  104. <p>Enough about software. Sometimes, I do hardware projects as well: everything from 3D printed designs to electrical engineering. These projects are lesser-known, mainly because I’ve never really shared them besides some post on social media and some chats with friends, but they exist nonetheless<sup id="fnref:1"></sup>. All the reasons I previously explained still apply here, and I do not want these projects to be open for collaboration most of the time. However, there are additional points here, and the most important one is:</p>
  105. <p>I’m not an expert on these things.</p>
  106. <p>Hardware projects are always a bit more complicated than software projects. If software goes wrong, at least for the kinds of software I create, you might get a crash or two, or something might not work correctly, but no considerable harm will be done. For hardware projects, the consequences of a “bug” are far more severe: You could waste a lot of material and energy trying to reproduce a 3D print. You could actually physically <em>break</em> stuff while trying to modify an existing appliance. Hardware projects could result in broken components, or worse: in broken devices you attached my projects to. I don’t want to be responsible for any of that.</p>
  107. <p>When I work on a hardware project, I very much only build things for myself. The measurements are <em>exactly</em> what I need and fine-tuned to what I know I can produce. Electronics are designed to work in the environment I build and the limitations I set up. The firmware does precisely what I need it to in a very stubborn way, and especially the “smart” “devices” usually depend on other pieces of infrastructure that are very special to my home.</p>
  108. <p>While turning those projects into things that could be useful in other environments and more generalized setups, I consider them a playground (and learning ground) for myself, and I generally do not want to spend the time on making it more useful to more than just me.</p>
  109. <h2 id="artsy-and-creative-things">Artsy and creative things</h2>
  110. <p>I used to publish all my photos and other stuff using a license that allowed usage of my things without any license fees, even in commercial environments. The only limitation was that you needed to properly credit me as the author. These days, I do not use free licenses for my contents anymore.</p>
  111. <p>“Clearly state who made this thing” sounds like a simple requirement, but it was frustrating how frequently this was violated. Frequently, users of “alternative social networks” posted my content without any credit whatsoever and then reacted aggressively and defensively when asked to stop doing that and asked to respect the license terms. This is especially ironic since it’s the same group of people that frequently <em>shames</em> artists for not using those kinds of licenses in the first place.</p>
  112. <p>However, what finally tipped me over into no longer using this kind of license was when a multi-billion dollar company used several of my photos from a certain location in a print brochure to advertise their expensive all-inclusive holiday packages to that exact location. Being a nice guy, I started by sending them a friendly email, asking them to maybe consider not violating my license, and instructing them how and where to properly credit me according to the license. As you would expect, I received zero response to that.</p>
  113. <p>So I ended up hiring a lawyer and pursuing legal action against that company. Unfortunately, this turned out to be a huge pain. Many legal systems are based around the concept of <em>damages</em> and <em>indemnification</em>, but as it turns out, it’s really hard to claim damage when you’re literally giving away stuff for free. Try finding an attorney with experience in international copyright affairs if the monetary damage you claim is Zero! It’s also super frustrating if the same case involves parties from many different countries, where Copyright appears to be even weirder than it is in Germany. Ultimately, after way more than a year of legal battle, the best outcome we could achieve was that that company paid a laughable amount of money (actually less than my camera setup that took this photo is worth), stops printing new flyers with my photos, and that the company has to cover my legal expenses in this case.</p>
  114. <p>If dealing with such topics is part of sharing things online anyway, then at least I want to have some control over it. I share things because I want others to look at them and not because I want others to re-use them. I can achieve what I want to achieve by simply not using the kinds of licenses that have caused me issues before, and as time has shown, the individuals who redistribute things without any credit or care will do it anyway.</p>
  115. <h2 id="but-what-if-you-really-want-to-use-something-i-did">But what if you <em>really</em> want to use something I did?</h2>
  116. <p>There is a chance that you’ve reached this article because I linked to it somewhere else. In that case, you might still be really interested in using or getting access to a thing I did. If that is the case, simply reach out to me. You can find contact information on <a href="/me/card.html">my profile on this website</a>.</p>
  117. <p>If you’re a private individual who wants to use a photo on a personal website, or you want to build something on top of a hardware project I did, this should be really simple to work out. Get in touch, and let’s have a chat. If you have commercial interests or are a company, I still encourage you to reach out. However, please note that I’m unlikely to give away things for free depending on what we’re talking about and depending on your use case. At the same time, I can provide you with legal and taxable invoices for almost all countries, so I am sure you will be fine.</p>
  118. <p>If you made it this far into this text… I hope you have a nice day. Stay safe, take care!</p>
  119. </article>
  120. <hr>
  121. <footer>
  122. <p>
  123. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  124. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  125. </svg> Accueil</a> •
  126. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  127. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  128. </svg> Suivre</a> •
  129. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  130. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  131. </svg> Pro</a> •
  132. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  133. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  134. </svg> Email</a> •
  135. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  136. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  137. </svg> Légal</abbr>
  138. </p>
  139. <template id="theme-selector">
  140. <form>
  141. <fieldset>
  142. <legend><svg class="icon icon-brightness-contrast">
  143. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  144. </svg> Thème</legend>
  145. <label>
  146. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  147. </label>
  148. <label>
  149. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  150. </label>
  151. <label>
  152. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  153. </label>
  154. </fieldset>
  155. </form>
  156. </template>
  157. </footer>
  158. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  159. <script>
  160. function loadThemeForm(templateName) {
  161. const themeSelectorTemplate = document.querySelector(templateName)
  162. const form = themeSelectorTemplate.content.firstElementChild
  163. themeSelectorTemplate.replaceWith(form)
  164. form.addEventListener('change', (e) => {
  165. const chosenColorScheme = e.target.value
  166. localStorage.setItem('theme', chosenColorScheme)
  167. toggleTheme(chosenColorScheme)
  168. })
  169. const selectedTheme = localStorage.getItem('theme')
  170. if (selectedTheme && selectedTheme !== 'undefined') {
  171. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  172. }
  173. }
  174. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  175. window.addEventListener('load', () => {
  176. let hasDarkRules = false
  177. for (const styleSheet of Array.from(document.styleSheets)) {
  178. let mediaRules = []
  179. for (const cssRule of styleSheet.cssRules) {
  180. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  181. continue
  182. }
  183. // WARNING: Safari does not have/supports `conditionText`.
  184. if (cssRule.conditionText) {
  185. if (cssRule.conditionText !== prefersColorSchemeDark) {
  186. continue
  187. }
  188. } else {
  189. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  190. continue
  191. }
  192. }
  193. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  194. }
  195. // WARNING: do not try to insert a Rule to a styleSheet you are
  196. // currently iterating on, otherwise the browser will be stuck
  197. // in a infinite loop…
  198. for (const mediaRule of mediaRules) {
  199. styleSheet.insertRule(mediaRule.cssText)
  200. hasDarkRules = true
  201. }
  202. }
  203. if (hasDarkRules) {
  204. loadThemeForm('#theme-selector')
  205. }
  206. })
  207. </script>
  208. </body>
  209. </html>