|
|
|
|
|
|
|
|
|
|
|
<!doctype html><!-- This is a valid HTML5 document. --> |
|
|
|
|
|
<!-- Screen readers, SEO, extensions and so on. --> |
|
|
|
|
|
<html lang="fr"> |
|
|
|
|
|
<!-- Has to be within the first 1024 bytes, hence before the `title` element |
|
|
|
|
|
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset --> |
|
|
|
|
|
<meta charset="utf-8"> |
|
|
|
|
|
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 --> |
|
|
|
|
|
<!-- The viewport meta is quite crowded and we are responsible for that. |
|
|
|
|
|
See: https://codepen.io/tigt/post/meta-viewport-for-2015 --> |
|
|
|
|
|
<meta name="viewport" content="width=device-width,initial-scale=1"> |
|
|
|
|
|
<!-- Required to make a valid HTML5 document. --> |
|
|
|
|
|
<title>The web browser as a tool of thought (archive) — David Larlet</title> |
|
|
|
|
|
<meta name="description" content="Publication mise en cache pour en conserver une trace."> |
|
|
|
|
|
<!-- That good ol' feed, subscribe :). --> |
|
|
|
|
|
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/"> |
|
|
|
|
|
<!-- Generated from https://realfavicongenerator.net/ such a mess. --> |
|
|
|
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png"> |
|
|
|
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png"> |
|
|
|
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png"> |
|
|
|
|
|
<link rel="manifest" href="/static/david/icons2/site.webmanifest"> |
|
|
|
|
|
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c"> |
|
|
|
|
|
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico"> |
|
|
|
|
|
<meta name="msapplication-TileColor" content="#f7f7f7"> |
|
|
|
|
|
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml"> |
|
|
|
|
|
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)"> |
|
|
|
|
|
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)"> |
|
|
|
|
|
<!-- Documented, feel free to shoot an email. --> |
|
|
|
|
|
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css"> |
|
|
|
|
|
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. --> |
|
|
|
|
|
<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> |
|
|
|
|
|
<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> |
|
|
|
|
|
<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> |
|
|
|
|
|
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin> |
|
|
|
|
|
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin> |
|
|
|
|
|
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin> |
|
|
|
|
|
<script> |
|
|
|
|
|
function toggleTheme(themeName) { |
|
|
|
|
|
document.documentElement.classList.toggle( |
|
|
|
|
|
'forced-dark', |
|
|
|
|
|
themeName === 'dark' |
|
|
|
|
|
) |
|
|
|
|
|
document.documentElement.classList.toggle( |
|
|
|
|
|
'forced-light', |
|
|
|
|
|
themeName === 'light' |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
const selectedTheme = localStorage.getItem('theme') |
|
|
|
|
|
if (selectedTheme !== 'undefined') { |
|
|
|
|
|
toggleTheme(selectedTheme) |
|
|
|
|
|
} |
|
|
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
|
|
<meta name="robots" content="noindex, nofollow"> |
|
|
|
|
|
<meta content="origin-when-cross-origin" name="referrer"> |
|
|
|
|
|
<!-- Canonical URL for SEO purposes --> |
|
|
|
|
|
<link rel="canonical" href="https://thesephist.com/posts/browser/"> |
|
|
|
|
|
|
|
|
|
|
|
<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all"> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<article> |
|
|
|
|
|
<header> |
|
|
|
|
|
<h1>The web browser as a tool of thought</h1> |
|
|
|
|
|
</header> |
|
|
|
|
|
<nav> |
|
|
|
|
|
<p class="center"> |
|
|
|
|
|
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home"> |
|
|
|
|
|
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use> |
|
|
|
|
|
</svg> Accueil</a> • |
|
|
|
|
|
<a href="https://thesephist.com/posts/browser/" title="Lien vers le contenu original">Source originale</a> |
|
|
|
|
|
</p> |
|
|
|
|
|
</nav> |
|
|
|
|
|
<hr> |
|
|
|
|
|
<p>A month ago, I built a <a href="/posts/monocle/">personal search engine called <em>Monocle</em></a> that let me search through a trove of personal information I’ve saved over time, from notes to journal entries to bookmarks and tweets. Shortly thereafter, I switched my default search engine in my web browser from Google to Monocle, marking the start of my slow descent into the fascinating rabbit hole that is transmogrifying my web browser into my best, most flexible, most versatile tool for thinking, learning, and remembering.</p> |
|
|
|
|
|
<p>A couple of weeks later, I built and started using <a href="https://github.com/thesephist/revery">Revery</a>, a browser extension that shows quick summaries and topically related notes and bookmarks from my collection whenever I’m reading anything on the Web.</p> |
|
|
|
|
|
<p><img src="https://thesephist.com/img/revery-devices.png" alt="Revery running on an iPad and a laptop"></p> |
|
|
|
|
|
<p>Living with these small bits of customization and intelligence scattered throughout my browser, I’m increasingly convinced that <strong>the future of the web browser is the best tool – nay, <em>medium</em> – for thought</strong>.</p> |
|
|
|
|
|
<p>This conviction comes from a myriad of ideas and realizations, but most significant among them are three insights I’ve discovered while building and living with these projects for the last month:</p> |
|
|
|
|
|
<ol> |
|
|
|
|
|
<li><a href="#_medium_-for-thought-not-just-a-tool"><em>Medium</em> for thought, not just a tool</a></li> |
|
|
|
|
|
<li><a href="#information-lives-outside-of-tools">Information lives outside of tools</a></li> |
|
|
|
|
|
<li><a href="#to-surf-the-web-you-must-first-understand-it">To surf the Web, you must first understand it</a></li> |
|
|
|
|
|
</ol> |
|
|
|
|
|
<p>At the end, I’ll try to bring these ideas together to muse a little on what I want to see as <a href="#a-web-browser-for-thoughts-not-documents-or-apps">the future of the browser</a>.</p> |
|
|
|
|
|
|
|
|
|
|
|
<p>In <em><a href="https://thesephist.com/posts/medium/">Designing a better thinking-writing medium</a></em>, I wrote on the difference between a tool and a medium:</p> |
|
|
|
|
|
<blockquote> |
|
|
|
|
|
<p>A tool is something that takes an existing workflow, and makes it more efficient. A nail is an efficient way of holding pieces of wood together; a to-do app is an efficient way of remembering your responsibilities. A medium, on the other hand, gives us new agency or power by which we can do something we couldn’t do before.</p> |
|
|
|
|
|
<p>As with any dichotomy, there are grey areas. Powerful, effective tools can become mediums and enablers too. The graphical computer user interface wasn’t just a better way to write scientific simulations or data processing systems – it also became a new medium for creative work. Programming languages began history as a more efficient way to store and maintain punchcard programs, but a half-century of innovation has made it a medium for expressing programs that couldn’t be written before.</p> |
|
|
|
|
|
</blockquote> |
|
|
|
|
|
<p>Despite the renewed focus I see in the community of people and companies trying to build better tools for thought, I think much of our work is still confined to tool-making. That is, most of our efforts are about creating more automatic, more efficient ways to do what we already know how to do – spaced repetition, Zettelkasten, journaling, and so on. <strong>We are busy making more effective command-line apps for thought, rather than dreaming up graphical interfaces.</strong></p> |
|
|
|
|
|
<p>Building a tool is a relatively straightforward affair. We can look around at existing workflows and needs that people have, and design some set of features <a href="/posts/tools/">around the workflows</a> and needs that we observe.</p> |
|
|
|
|
|
<p>However, to build an enabling medium that’s more than a single-purpose tool, it isn’t simply enough to look at existing workflows and build tools around them. To design a good creative medium, we can’t solve for a particular use case. <strong>The best mediums are instead collections of generic, multi-purpose <em>components</em> that mesh together well</strong> to let the user construct their own solutions. For example, Microsoft Excel is ostensibly a tool for calculation, but it’s also a medium for manipulating data in a 2-D grid for lots of other use cases, from organizing a budget to collecting a poll to even creating simple graphics. This flexibility comes from the fact that Excel is really just composed of a few powerful primitive components: the 2-D grid of cells, formulas that can reference other cells, and a responsive programming model that lets the whole table change anytime a value somewhere changes.</p> |
|
|
|
|
|
<p>Designing a <em>medium for thought</em> requires that we discover what these primitive components of a thinking medium should be. Should there be some sense of <a href="https://darkblueheaven.com/spatialsoftware/">geometry and space</a>? How important should text be, against drawings and images? How should people collaborate and share their thoughts? I propose that the solution to these questions are not an opinionated tool with a “Share” button and a rigid way to use an image in a project, but something with a <em>collection of capabilities</em> that happen to include inserting and positioning text and images, sharing and collaborating on those objects on the page, and connecting ideas. These capabilities should work well together, to leave room for any combination of use cases. The line here can be blurry, so I don’t think it’s worthwhile to argue whether any particular tool is a good tool or a good medium, but in the future, I want to see more mediums like Excel, Google Docs, and Figma that seem like multi-purpose canvases that leave room for creativity, and fewer tools like Zoom, Slack, and of course the venerable web browser of today that lock you into particular use cases and make you feel like you need to “learn how to use” the thing.</p> |
|
|
|
|
|
<p>The current state web browsers is particularly damning from this perspective. Web browsers have access to such a treasure trove of valuable, often well-structured information about what we learn and how we think, what interests we have, and who we talk to. Rather than trying to take that information and let us build workflows out of them, browsers remain a strictly utilitarian tool – a rectangular window into documents and apps that play dumb, ignorant of the valuable information that transits through them every day. I think we can do better.</p> |
|
|
|
|
|
|
|
|
|
|
|
<p>Once I started using my personal search engine, <em>Monocle</em>, day-to-day, I made an observation about how Monocle seemed different than most of my other software tools. I wrote on my <a href="/#newsletter">newsletter</a>:</p> |
|
|
|
|
|
<blockquote> |
|
|
|
|
|
<p>Every productivity app company these days seems to embrace the phrase “second brain,” as in “make X app your second brain.” One of my big takeaways from using Monocle on a daily basis for the last week has been that <strong>no single app can be my second brain</strong>. There are going to be parts of my life that are inherently spread out across different apps. For example, there’s a huge amount of knowledge sitting in my email inbox and my blog, and there are some things I only remember because I tweeted about it once, or recorded in a quick journal entry. There are ideas saved in text messages and contacts. “Notes apps,” it turns out, are not the only places where knowledge lives. And a true “second brain”, or whatever you want to call it, needs to recognize that and let you wield its magic over all of your digital footprint.</p> |
|
|
|
|
|
</blockquote> |
|
|
|
|
|
<p>Most of us don’t realize just how much the “app-centric” mindset is ingrained into us, until we get a chance to think in a “problem-centric” way free from the limitations of apps. One of my most frequent kinds of search on Monocle is a search for people – people whose names I vaguely remember, people whom I’ve never heard of but might have been mentioned in a news article, people whose birthdays might be coming up. Before Monocle, to find some information about a person, my first thought would have been “What app did I write that down in? Should I check my messages or my contacts?” I might even have given up, after searching a couple of apps without finding the result I was looking for. With Monocle, the question doesn’t need to be asked. I just search for the right person, and Monocle searches across all my data.</p> |
|
|
|
|
|
<p>If we want to organize information that flows through our lives, we simply can’t restrict our design space to be a single product or app. No matter how great a note-taking app is, my emails are going to live outside of it. No matter how seamless the experience in my contacts app, my text conversations are going to live outside of it. We should acknowledge this fundamental limitation of the “note-taking app” approach to building tools for thought, and shift our focus away from building such siloed apps to designing something that lives on top of these smaller alcoves of personal knowledge to help us organize it regardless of its provenance.</p> |
|
|
|
|
|
<p>If we want to build a software system that can organize information across apps, what better place to start than the one piece of software that has access to it all, where most of us live and work nearly all the time? I think the browser is a rich place to build experiments in this space, and my personal experience building Monocle and Revery support this idea so far.</p> |
|
|
|
|
|
<h2 id="to-surf-the-web-you-must-first-understand-it">To surf the Web, you must first understand it</h2> |
|
|
|
|
|
<p>One of my perennial complaints about the current crop of “tools for thought” has been that most of them aren’t really about <em>thinking</em> per se, just about improving memory. We can take down information into apps like Roam Research or Notion and recall them easily later, but it’s an overstatement to call them tools for <em>thought</em>. Recollection is such a small, basic part of thinking! There is so much more to thinking than simply remembering something accurately. I think we can acknowledge the benefits these apps bring while also admitting that better tools for thought should help us do more with ideas than just remember and recall.</p> |
|
|
|
|
|
<p>Even when using the best of these apps, it’s up to the human users to manually annotate every single connection, every single hierarchy, and every single highlight and summary we want to remember about what we write. Humans are still doing most of the “thinking” work. It’s as if we had invented a “calculator” that was purely a record of the results of our arithmetic, rather than a machine that performed calculations. Sure, a record of our computation is helpful, but it’s hardly an effective calculator. It almost feels disingenuous to say that this current generation of tools help us think. I think it’s more accurate to say they <em>encourage</em> us to think with the promise of perfect recall, but we are not yet living amongst tools that truly help us think better thoughts, faster.</p> |
|
|
|
|
|
<p>So, what are the building blocks of a powerful thinking medium that can actually help us think, more than just recall? For a tool that has such broad access to information like a web browser, I think a critical piece of the puzzle is better machine understanding of language.</p> |
|
|
|
|
|
<p>Most existing tools and browsers treat web pages and pieces of notes like complete black boxes of information. These tools know how to scan for keywords, and they have access to the metadata we use to tag our information like hashtags and timestamps, but unlike a human, most current tools don’t try to peer into the contents of our notes or reading materials and operate with an <em>understanding</em> of our information.</p> |
|
|
|
|
|
<p>With ratcheting progress in machine understanding of language, I think we have good high-quality building blocks to start building thinking mediums and information systems that operate with some understanding of our ideas themselves, rather than simply “this is some text”.</p> |
|
|
|
|
|
<p>Take my custom browser extension <a href="https://github.com/thesephist/revery">Revery</a> as an example. I’ve been using it as the testing ground for some of my own ideas about what these tools should be able to do. While it doesn’t take advantage of any of the <a href="https://dotink.co/posts/gpt3/">more recent advancements in NLP</a>, its current capabilities are still changing how I browse the web. For any webpage I visit, Revery currently:</p> |
|
|
|
|
|
<ul> |
|
|
|
|
|
<li>Scans the page and surfaces information from my personal search index that might be topically relevant to what I’m reading. For example, on an article about South Korea’s economic and cultural ascent, Revery surfaced my bookmarks on parallel stories from Taiwan and Singapore, letting me contextualize the current article.</li> |
|
|
|
|
|
<li>Provides a quick <a href="https://en.wikipedia.org/wiki/Automatic_summarization">extractive summary</a> of long articles for me to scan before I decide to spend time reading the rest of the page.</li> |
|
|
|
|
|
</ul> |
|
|
|
|
|
<p>In addition, Revery could in the future pick out important keywords and topics from the page and automatically search my search engine for them, or help me spot key people and places I know that appear on the page.</p> |
|
|
|
|
|
<p>Because all of these experiments are grounded in my web browser rather than any particular application, these tricks and workflows work on any website, including other notes applications. I could visit my <a href="/posts/ideaflow/">Ideaflow</a> notes or someone else’s Roam graph and take advantage of these capabilities of my browser just as easily. It’s not that far-fetched to imagine a scenario in which I visit a well-connected Roam graph, and realize that my browser has made just as many connections between their notes and my notes as the author of the Roam notes have across their information.</p> |
|
|
|
|
|
<p>If we were to build a medium for better thinking on top of the web browser, it’s reckless to expect the average user to manually connect, organize, and annotate the information they come across. Just as the early World Wide Web started out manually-curated and eventually became curated by algorithms and communities, I think we’ll see a shift in how individual personal landscapes of information are curated, from manual organization to mostly machine-driven organization. Humans will leave connections and highlights as a trail of their thinking, rather than as their primary way of exploring their knowledge and memory.</p> |
|
|
|
|
|
<p>In the browser of the future, the boundary between my personal information and the wider Web’s information landscape will blur, and a smarter, more literate browser will help me navigate both worlds with a deeper understanding of what I’m thinking about and what I want to discover. It’ll remind me of relevant bookmarks when I’m taking lecture notes; it’ll summarize and pick out interesting details from long news articles for me; it’ll let me search across the Web and my personal data to remember more and learn faster.</p> |
|
|
|
|
|
<h2 id="a-web-browser-for-thoughts-not-documents-or-apps">A web browser for thoughts, not documents or apps</h2> |
|
|
|
|
|
<p>The web browser has advanced remarkably far in the first couple of decades of its history. But despite the technical achievements, it staunchly remains a pure utility, a tool meant to be used almost exclusively for visiting what lies at the other end of URLs.</p> |
|
|
|
|
|
<p>There’s a renewed attention in the web browser space today. Too many of them are simply focused on making existing browsers faster and more powerful, but there’s an exciting small clan of founders and engineers trying to make the browser something more.</p> |
|
|
|
|
|
<p>The vision of the web browser that excites me the most is one where the browser is a medium for creativity, learning, and thinking deeply that spans personal and public spheres of knowledge. This browser will be fast and private, of course, but more than that, this browser will let me explore the Web from the comfort of my own garden of information. It’ll break the barriers between different apps that silo our information to help us search and remember across all of them. It’ll use a deeper machine understanding of language and images to summarize articles, highlight important ideas, and remind me what I should remember. It’ll let me do it all together with other people in a way that feels like real presence, rather than just avatars on screen.</p> |
|
|
|
|
|
<p>Forget space tourism – the most thought-provoking ideas, the most romantic stories, the most beautiful reveries of the future are right here, on the Web. There is still much to explore, and such beautiful worlds deserve a better spacecraft. One built to help us think new thoughts, together.</p> |
|
|
|
|
|
<hr> |
|
|
|
|
|
<p>This post is a culmination of ideas sparked by conversations with Jess Martin, Raj Thimmiah, Jacob Cole, Molly Mielke, Karina Nguyen, and Josh Miller. Thanks to them for such enlightening conversations, and in many cases, for their own work in pushing these ideas forward!</p> |
|
|
|
|
|
</article> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<hr> |
|
|
|
|
|
|
|
|
|
|
|
<footer> |
|
|
|
|
|
<p> |
|
|
|
|
|
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home"> |
|
|
|
|
|
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use> |
|
|
|
|
|
</svg> Accueil</a> • |
|
|
|
|
|
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2"> |
|
|
|
|
|
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-rss2"></use> |
|
|
|
|
|
</svg> Suivre</a> • |
|
|
|
|
|
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie"> |
|
|
|
|
|
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-user-tie"></use> |
|
|
|
|
|
</svg> Pro</a> • |
|
|
|
|
|
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail"> |
|
|
|
|
|
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-mail"></use> |
|
|
|
|
|
</svg> Email</a> • |
|
|
|
|
|
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2"> |
|
|
|
|
|
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-hammer2"></use> |
|
|
|
|
|
</svg> Légal</abbr> |
|
|
|
|
|
</p> |
|
|
|
|
|
<template id="theme-selector"> |
|
|
|
|
|
<form> |
|
|
|
|
|
<fieldset> |
|
|
|
|
|
<legend><svg class="icon icon-brightness-contrast"> |
|
|
|
|
|
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-brightness-contrast"></use> |
|
|
|
|
|
</svg> Thème</legend> |
|
|
|
|
|
<label> |
|
|
|
|
|
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto |
|
|
|
|
|
</label> |
|
|
|
|
|
<label> |
|
|
|
|
|
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé |
|
|
|
|
|
</label> |
|
|
|
|
|
<label> |
|
|
|
|
|
<input type="radio" value="light" name="chosen-color-scheme"> Clair |
|
|
|
|
|
</label> |
|
|
|
|
|
</fieldset> |
|
|
|
|
|
</form> |
|
|
|
|
|
</template> |
|
|
|
|
|
</footer> |
|
|
|
|
|
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script> |
|
|
|
|
|
<script> |
|
|
|
|
|
function loadThemeForm(templateName) { |
|
|
|
|
|
const themeSelectorTemplate = document.querySelector(templateName) |
|
|
|
|
|
const form = themeSelectorTemplate.content.firstElementChild |
|
|
|
|
|
themeSelectorTemplate.replaceWith(form) |
|
|
|
|
|
|
|
|
|
|
|
form.addEventListener('change', (e) => { |
|
|
|
|
|
const chosenColorScheme = e.target.value |
|
|
|
|
|
localStorage.setItem('theme', chosenColorScheme) |
|
|
|
|
|
toggleTheme(chosenColorScheme) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const selectedTheme = localStorage.getItem('theme') |
|
|
|
|
|
if (selectedTheme && selectedTheme !== 'undefined') { |
|
|
|
|
|
form.querySelector(`[value="${selectedTheme}"]`).checked = true |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const prefersColorSchemeDark = '(prefers-color-scheme: dark)' |
|
|
|
|
|
window.addEventListener('load', () => { |
|
|
|
|
|
let hasDarkRules = false |
|
|
|
|
|
for (const styleSheet of Array.from(document.styleSheets)) { |
|
|
|
|
|
let mediaRules = [] |
|
|
|
|
|
for (const cssRule of styleSheet.cssRules) { |
|
|
|
|
|
if (cssRule.type !== CSSRule.MEDIA_RULE) { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
// WARNING: Safari does not have/supports `conditionText`. |
|
|
|
|
|
if (cssRule.conditionText) { |
|
|
|
|
|
if (cssRule.conditionText !== prefersColorSchemeDark) { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules)) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// WARNING: do not try to insert a Rule to a styleSheet you are |
|
|
|
|
|
// currently iterating on, otherwise the browser will be stuck |
|
|
|
|
|
// in a infinite loop… |
|
|
|
|
|
for (const mediaRule of mediaRules) { |
|
|
|
|
|
styleSheet.insertRule(mediaRule.cssText) |
|
|
|
|
|
hasDarkRules = true |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (hasDarkRules) { |
|
|
|
|
|
loadThemeForm('#theme-selector') |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
</script> |
|
|
|
|
|
</body> |
|
|
|
|
|
</html> |