Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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>Tag #simplicité — David Larlet</title>
  13. <meta name="description" content="Publications relatives au tag #simplicité">
  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. <style type="text/css">
  53. details[open] summary {
  54. display: none;
  55. }
  56. </style>
  57. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  58. <header>
  59. <h1>Publications relatives au tag #simplicité</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 rel="tags" href="/david/#tags-2023" title="Liste de toutes les étiquettes"><svg class="icon icon-tags">
  67. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-tags"></use>
  68. </svg> Étiquettes</a>
  69. </p>
  70. </nav>
  71. <hr>
  72. <main>
  73. <p>Les plus récentes en premier, les 3 premières sont dépliées et ensuite c’est à la demande, bonne exploration !</p>
  74. <h2><a href="/david/2023/02/18/" title="Lien permanent vers cet article">Quiz</a> (2023-02-18)</h2>
  75. <blockquote>
  76. <p>On aimerait pouvoir faire des&nbsp;quiz.</p>
  77. </blockquote>
  78. <p>Il y a 20&nbsp;ans, j’aurais commencé à modéliser cela dans une base de données relationnelles avec les bons index et&nbsp;tout.</p>
  79. <p>Il y a 15&nbsp;ans, j’aurais essayé de représenter cela avec des données liées et du RDF pour une réutilisation&nbsp;sémantique.</p>
  80. <p>Il y a 10&nbsp;ans, je me serais demandé si ça pouvait rentrer dans Redis ou MongoDB et à quel point ça passerait à&nbsp;l’échelle.</p>
  81. <p>Il y a 5&nbsp;ans, j’aurais imaginé une API pour pouvoir généraliser l’usage et décliner plusieurs services&nbsp;équivalents.</p>
  82. <p><strong>Et aujourd’hui&nbsp;alors&#8239;?</strong></p>
  83. <p>Je commence par me demander comment est-ce que les utilisateur·ices vont pouvoir saisir ces données et devenir&nbsp;autonomes.</p>
  84. <p>Je n’envisage pas qu’iels puissent saisir du HTML —&nbsp;qui plus est valide et accessible&nbsp;— pour concevoir ce quiz. Je me demande quelle serait la structure la plus logique pour déterminer les réponses possibles et mentionner la bonne. Il y a un enjeu de <em>feedback</em> immédiat lors de la rédaction, par exemple en <em>CommonMark</em> un peu étendu dans un <em>pad</em> ou un forge <em>git</em>. J’imagine une structure qui ressemble&nbsp;à&nbsp;:</p>
  85. <pre><code>Le consentement c’est :
  86. * [ ] Demander la permission
  87. * [x] S’assurer à tout moment que l’autre↩
  88. est à l’aise et désire ce qu’on lui fait
  89. * [ ] Peut se donner avec un peu de pression
  90. </code></pre>
  91. <p>C’est ensuite à moi de convertir cette structure plate, textuelle, relativement compréhensible en un formulaire web interactif. C’est le seul moment où la technique entre en jeux avec des dépendances aussi minimalistes que&nbsp;possible.</p>
  92. <p>Ce qui a changé en 20&nbsp;ans, c’est que j’ai pris conscience que la pérennité d’une donnée tient à l’autonomie que l’on peut donner aux personnes qui vont s’assurer de son évolution. La «&nbsp;bonne&nbsp;» modélisation est celle qui est explicite et non réservée à une élite de&nbsp;dévelopeur·euses.</p>
  93. <p>Entre l’<em>User eXperience</em> (UX) et la <em>Developer eXperience</em> (DX), il y aurait peut-être la <em>Maintenance eXperience</em> (MX)&#8239;? Et dans ce contexte, l’autonomie vis-à-vis des données est cruciale. Ce n’est peut-être pas techniquement très propre, c’est difficile à mettre en valeur sur un CV ou dans une conférence, c’est même aux antipodes de la mode&nbsp;actuelle.</p>
  94. <p>Mais c’est là où je positionne ma valeur aujourd’hui. De la cathédrale qu’il faut reconstruire tous les 2&nbsp;ans au refuge qui ne nécessite que quelques planches et clous en maintenance annuelle pour qu’une poignée de personnes y trouvent du réconfort. Et soient en capacité de participer à l’effort&nbsp;commun.</p>
  95. <hr />
  96. <p>Bandes-dessinées de la&nbsp;semaine&nbsp;:</p>
  97. <ul>
  98. <li><a href="https://editions-sarbacane.com/bd/rene-e-aux-bois-dormants">René.e aux bois dormants</a> de Elene&nbsp;Usdin.</li>
  99. <li><a href="https://ecosociete.org/livres/megantic-un-train-dans-la-nuit">Mégantic, un train dans la nuit</a> de Anne-Marie Saint-Cerny et Christian&nbsp;Quesnel.</li>
  100. </ul>
  101. <p>Je ne sais pas si c’est le fait de résider sur ces territoires mais les deux m’ont pas mal affecté. L’héritage de la colonisation en étant sur les lieux colonisés est encore plus difficile à&nbsp;porter.</p>
  102. <hr />
  103. <p>Film de la semaine&nbsp;: <a href="https://en.wikipedia.org/wiki/The_Menu_(2022_film)">The Menu</a> (essayez de ne pas vous&nbsp;divulgâcher…).</p>
  104. <hr />
  105. <blockquote lang="en">
  106. <p>💯 Always remember that although a subset of the JavaScript community can be very loud, they represent a paltry portion of the web as a whole. This means that when they say something like “Best practices don’t actually work”—what they mean is “Best practices don’t actually work for a small subset of less than 5&nbsp;percent of the&nbsp;web”.</p>
  107. <p><cite><em><a href="https://andy-bell.co.uk/the-extremely-loud-minority/">The (extremely) loud minority</a></em>&nbsp;(<a href="/david/cache/2023/78d79db0da7f60c48a02cfd088885085/">cache</a>)</cite></p>
  108. </blockquote>
  109. <blockquote lang="en">
  110. <p>🐦 Spinners are the dumbest progress&nbsp;bar.</p>
  111. <p><cite><em><a href="https://interconnected.org/home/2023/02/10/progress">A notification center for progress bars that sounds like birdsong</a></em>&nbsp;(<a href="/david/cache/2023/29dac969af1faa8ba0338a2e7e59ebbd/">cache</a>)</cite></p>
  112. </blockquote>
  113. <h2><a href="/david/2023/01/17/" title="Lien permanent vers cet article">Populaire</a> (2023-01-17)</h2>
  114. <p>Plus j’en fais et plus je considère que le ski de fond est un sport populaire (dans le sens «&nbsp;pour le peuple&nbsp;»). Très peu d’équipement est nécessaire et même de la récupération permet de s’amuser, le façonnage des pistes requiert relativement peu d’énergies (fossiles), il est possible d’en faire même en étant très débutant·e et pas à l’aise avec les pentes. Ça devrait être une politique de santé&nbsp;publique&#8239;!</p>
  115. <p>Alors bien sûr, un bon équipement change des choses mais la technique et l’expérience compensent tellement que ça en devient presque négligeable (en loisir). Tout le monde peut se mettre dans les rails et pousser un pied devant l’autre. Bon OK, juste à côté. C’est un excellent moyen de se mettre en confiance avant d’oser glisser. Et puis, le pas s’allonge, les bras se décrispent et se mettent en mouvement aussi, les cuisses prennent le relai, les pieds se&nbsp;soulèvent.</p>
  116. <p>Lorsqu’on commence à glisser et à trouver l’équilibre, le point d’accroche, le mouvement juste, ça procure une sensation de vol incroyable et ça permet de suer en continu (autant que la course mais avec moins d’impacts). Le matériel est léger et plutôt silencieux, les pratiquant·es courtois·es (et âgé·es, <a href="/david/2021/02/10/">en tout cas l’après-midi</a>).</p>
  117. <p>Je n’en dis pas plus… il risquerait d’y avoir trop de monde dans les&nbsp;traces&nbsp;😅.</p>
  118. <p>PS&nbsp;: j’ai une petite (8&#8239;km, hamster-style) piste à 250&nbsp;mètres de chez moi et je suis tellement reconnaissant à la ville de Montréal d’aménager les parcs et pistes cyclables en hiver pour glisser dans la nature&nbsp;urbaine&nbsp;💚.</p>
  119. <figure>
  120. <a href="#2023-01-13-ski-visitation1"
  121. title="Cliquer pour une version haute résolution">
  122. <picture>
  123. <source
  124. srcset="/static/david/2023/2023-01-13-ski-visitation1.webp 2048w"
  125. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  126. type="image/webp">
  127. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  128. <img
  129. src="/static/david/2023/2023-01-13-ski-visitation1.jpg"
  130. width="2048" height="2731"
  131. srcset="/static/david/2023/2023-01-13-ski-visitation1.jpg 2048w"
  132. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  133. fetchpriority="high"
  134. decoding="sync"
  135. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  136. </picture>
  137. </a>
  138. <a href="#_" class="lightbox" id="2023-01-13-ski-visitation1">
  139. <picture style="margin:0 auto;">
  140. <source
  141. srcset="/static/david/2023/2023-01-13-ski-visitation1.webp 2048w"
  142. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  143. type="image/webp">
  144. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  145. <img
  146. src="/static/david/2023/2023-01-13-ski-visitation1.jpg"
  147. width="2048" height="2731"
  148. srcset="/static/david/2023/2023-01-13-ski-visitation1.jpg 2048w"
  149. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  150. fetchpriority="high"
  151. decoding="sync"
  152. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  153. </picture>
  154. </a>
  155. <figcaption>Parc de l’Île de la Visitation, Montréal, 13 janvier&nbsp;2023.</figcaption>
  156. </figure>
  157. <figure>
  158. <a href="#2023-01-13-ski-visitation2"
  159. title="Cliquer pour une version haute résolution">
  160. <picture>
  161. <source
  162. srcset="/static/david/2023/2023-01-13-ski-visitation2.webp 2048w"
  163. sizes="min(100vw, calc(100vh * 2048 / 1536))"
  164. type="image/webp">
  165. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  166. <img
  167. src="/static/david/2023/2023-01-13-ski-visitation2.jpg"
  168. width="2048" height="1536"
  169. srcset="/static/david/2023/2023-01-13-ski-visitation2.jpg 2048w"
  170. sizes="min(100vw, calc(100vh * 2048 / 1536))"
  171. fetchpriority="high"
  172. decoding="sync"
  173. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  174. </picture>
  175. </a>
  176. <a href="#_" class="lightbox" id="2023-01-13-ski-visitation2">
  177. <picture style="margin:0 auto;">
  178. <source
  179. srcset="/static/david/2023/2023-01-13-ski-visitation2.webp 2048w"
  180. sizes="min(100vw, calc(100vh * 2048 / 1536))"
  181. type="image/webp">
  182. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  183. <img
  184. src="/static/david/2023/2023-01-13-ski-visitation2.jpg"
  185. width="2048" height="1536"
  186. srcset="/static/david/2023/2023-01-13-ski-visitation2.jpg 2048w"
  187. sizes="min(100vw, calc(100vh * 2048 / 1536))"
  188. fetchpriority="high"
  189. decoding="sync"
  190. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  191. </picture>
  192. </a>
  193. <figcaption>Parc de l’Île de la Visitation, Montréal, 13 janvier&nbsp;2023.</figcaption>
  194. </figure>
  195. <figure>
  196. <a href="#2023-01-13-ski-visitation3"
  197. title="Cliquer pour une version haute résolution">
  198. <picture>
  199. <source
  200. srcset="/static/david/2023/2023-01-13-ski-visitation3.webp 2048w"
  201. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  202. type="image/webp">
  203. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  204. <img
  205. src="/static/david/2023/2023-01-13-ski-visitation3.jpg"
  206. width="2048" height="2731"
  207. srcset="/static/david/2023/2023-01-13-ski-visitation3.jpg 2048w"
  208. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  209. fetchpriority="high"
  210. decoding="sync"
  211. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  212. </picture>
  213. </a>
  214. <a href="#_" class="lightbox" id="2023-01-13-ski-visitation3">
  215. <picture style="margin:0 auto;">
  216. <source
  217. srcset="/static/david/2023/2023-01-13-ski-visitation3.webp 2048w"
  218. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  219. type="image/webp">
  220. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  221. <img
  222. src="/static/david/2023/2023-01-13-ski-visitation3.jpg"
  223. width="2048" height="2731"
  224. srcset="/static/david/2023/2023-01-13-ski-visitation3.jpg 2048w"
  225. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  226. fetchpriority="high"
  227. decoding="sync"
  228. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  229. </picture>
  230. </a>
  231. <figcaption>Parc de l’Île de la Visitation, Montréal, 13 janvier&nbsp;2023.</figcaption>
  232. </figure>
  233. <figure>
  234. <a href="#2023-01-13-ski-visitation4"
  235. title="Cliquer pour une version haute résolution">
  236. <picture>
  237. <source
  238. srcset="/static/david/2023/2023-01-13-ski-visitation4.webp 2048w"
  239. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  240. type="image/webp">
  241. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  242. <img
  243. src="/static/david/2023/2023-01-13-ski-visitation4.jpg"
  244. width="2048" height="2731"
  245. srcset="/static/david/2023/2023-01-13-ski-visitation4.jpg 2048w"
  246. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  247. fetchpriority="high"
  248. decoding="sync"
  249. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  250. </picture>
  251. </a>
  252. <a href="#_" class="lightbox" id="2023-01-13-ski-visitation4">
  253. <picture style="margin:0 auto;">
  254. <source
  255. srcset="/static/david/2023/2023-01-13-ski-visitation4.webp 2048w"
  256. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  257. type="image/webp">
  258. <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  259. <img
  260. src="/static/david/2023/2023-01-13-ski-visitation4.jpg"
  261. width="2048" height="2731"
  262. srcset="/static/david/2023/2023-01-13-ski-visitation4.jpg 2048w"
  263. sizes="min(100vw, calc(100vh * 2048 / 2731))"
  264. fetchpriority="high"
  265. decoding="sync"
  266. alt="Des traces de piste de ski de fond dans la tempête de neige.">
  267. </picture>
  268. </a>
  269. <figcaption>Parc de l’Île de la Visitation, Montréal, 13 janvier&nbsp;2023.</figcaption>
  270. </figure>
  271. <hr />
  272. <blockquote>
  273. <p>Et si l’attachement à la retraite des Français ne tenait plus à l’attente d’un repos ultime au terme d’une vie laborieuse et pénible, mais à la possibilité de <mark>faire retraite dès maintenant</mark> pour se réinventer dans un travail&nbsp;«&nbsp;amélioré&nbsp;»&#8239;?</p>
  274. <p><cite><em><a href="https://www.philomag.com/articles/retraite-la-fin-du-bonheur-differe-par-denis-maillard">Retraite&nbsp;: la fin du “bonheur différé”, par Denis Maillard</a></em>&nbsp;(<a href="/david/cache/2023/614fe609b04719e7835fc0717b99c1c6/">cache</a>)</cite></p>
  275. </blockquote>
  276. </main>
  277. <hr>
  278. <footer>
  279. <p>
  280. <nobr>
  281. <a href="/david/" title="Aller à l’accueil"
  282. ><svg class="icon icon-home">
  283. <use
  284. xlink:href="/static/david/icons2/symbol-defs-2022-03.svg#icon-home"
  285. ></use>
  286. </svg>
  287. Accueil</a
  288. >
  289. </nobr>
  290. <nobr>
  291. <a href="/david/log/" title="Accès au flux RSS"
  292. ><svg class="icon icon-rss2">
  293. <use xlink:href="/static/david/icons2/symbol-defs-2022-03.svg#icon-rss2"></use>
  294. </svg>
  295. Suivre</a
  296. >
  297. </nobr>
  298. <nobr>
  299. <a href="http://larlet.com" title="Go to my English profile" data-instant
  300. ><svg class="icon icon-user-tie">
  301. <use xlink:href="/static/david/icons2/symbol-defs-2022-03.svg#icon-user-tie"></use>
  302. </svg>
  303. Pro</a
  304. >
  305. </nobr>
  306. <nobr>
  307. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"
  308. ><svg class="icon icon-mail">
  309. <use xlink:href="/static/david/icons2/symbol-defs-2022-03.svg#icon-mail"></use>
  310. </svg>
  311. Email</a
  312. >
  313. </nobr>
  314. <nobr>
  315. <abbr
  316. class="nowrap"
  317. title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"
  318. ><svg class="icon icon-hammer2">
  319. <use xlink:href="/static/david/icons2/symbol-defs-2022-03.svg#icon-hammer2"></use>
  320. </svg>
  321. Légal</abbr
  322. >
  323. </nobr>
  324. </p>
  325. <template id="theme-selector">
  326. <form>
  327. <fieldset>
  328. <legend><svg class="icon icon-brightness-contrast">
  329. <use xlink:href="/static/david/icons2/symbol-defs-2022-03.svg#icon-brightness-contrast"></use>
  330. </svg> Thème</legend>
  331. <label>
  332. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  333. </label>
  334. <label>
  335. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  336. </label>
  337. <label>
  338. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  339. </label>
  340. </fieldset>
  341. </form>
  342. </template>
  343. </footer>
  344. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  345. <script>
  346. function loadThemeForm(templateName) {
  347. const themeSelectorTemplate = document.querySelector(templateName)
  348. const form = themeSelectorTemplate.content.firstElementChild
  349. themeSelectorTemplate.replaceWith(form)
  350. form.addEventListener('change', (e) => {
  351. const chosenColorScheme = e.target.value
  352. localStorage.setItem('theme', chosenColorScheme)
  353. toggleTheme(chosenColorScheme)
  354. })
  355. const selectedTheme = localStorage.getItem('theme')
  356. if (selectedTheme && selectedTheme !== 'undefined') {
  357. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  358. }
  359. }
  360. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  361. window.addEventListener('load', () => {
  362. let hasDarkRules = false
  363. for (const styleSheet of Array.from(document.styleSheets)) {
  364. let mediaRules = []
  365. for (const cssRule of styleSheet.cssRules) {
  366. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  367. continue
  368. }
  369. // WARNING: Safari does not have/supports `conditionText`.
  370. if (cssRule.conditionText) {
  371. if (cssRule.conditionText !== prefersColorSchemeDark) {
  372. continue
  373. }
  374. } else {
  375. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  376. continue
  377. }
  378. }
  379. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  380. }
  381. // WARNING: do not try to insert a Rule to a styleSheet you are
  382. // currently iterating on, otherwise the browser will be stuck
  383. // in a infinite loop…
  384. for (const mediaRule of mediaRules) {
  385. styleSheet.insertRule(mediaRule.cssText)
  386. hasDarkRules = true
  387. }
  388. }
  389. if (hasDarkRules) {
  390. loadThemeForm('#theme-selector')
  391. }
  392. })
  393. </script>
  394. </body>
  395. </html>