-
-
Save bartkl/0134c6ce4a5d532464b40d3bfbcb64e4 to your computer and use it in GitHub Desktop.
diff --git a/quartz/components/scripts/darkmode.inline.ts b/quartz/components/scripts/darkmode.inline.ts | |
index c42a367..06767b5 100644 | |
--- a/quartz/components/scripts/darkmode.inline.ts | |
+++ b/quartz/components/scripts/darkmode.inline.ts | |
@@ -1,5 +1,6 @@ | |
-const userPref = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark" | |
-const currentTheme = localStorage.getItem("theme") ?? userPref | |
+import { getUserPreferredColorScheme, renderExcalidrawLinks } from "./util" | |
+ | |
+const currentTheme = localStorage.getItem("theme") ?? getUserPreferredColorScheme() | |
document.documentElement.setAttribute("saved-theme", currentTheme) | |
document.addEventListener("nav", () => { | |
@@ -11,6 +12,7 @@ document.addEventListener("nav", () => { | |
document.documentElement.setAttribute("saved-theme", "light") | |
localStorage.setItem("theme", "light") | |
} | |
+ renderExcalidrawLinks(localStorage.getItem("theme")) | |
} | |
// Darkmode toggle |
diff --git a/quartz/components/scripts/util.ts b/quartz/components/scripts/util.ts | |
index 5fcabad..444e145 100644 | |
--- a/quartz/components/scripts/util.ts | |
+++ b/quartz/components/scripts/util.ts | |
@@ -23,3 +23,31 @@ export function removeAllChildren(node: HTMLElement) { | |
node.removeChild(node.firstChild) | |
} | |
} | |
+ | |
+export function renderExcalidrawLinks(theme: "dark" | "light") { | |
+ let currentTheme = theme == "dark" ? "light" : "dark" | |
+ Object.values(document.getElementsByTagName("img")).forEach(img => { | |
+ if (img.src.endsWith(`.excalidraw.${currentTheme}.svg`)) { | |
+ let srcParts = img.src.split(".") | |
+ srcParts.splice(-2, 1, theme) | |
+ img.src = srcParts.join(".") | |
+ } | |
+ }) | |
+} | |
+ | |
+export function getUserPreferredColorScheme() { | |
+ return window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark" | |
+} | |
+ | |
+// Have SVG images in the article adhere to the correct color scheme. | |
+document.addEventListener("nav", (e) => { | |
+ let theme = localStorage.getItem("theme") ?? getUserPreferredColorScheme() | |
+ Object.values(document.getElementsByTagName("article")[0] | |
+ .getElementsByTagName("a")).forEach(a => { | |
+ if (a.href.endsWith(".excalidraw")) { | |
+ let img = document.createElement("img") | |
+ img.src = `${a.href}.${theme}.svg` | |
+ a.replaceWith(img) | |
+ } | |
+ }) | |
+}) |
@ChakradharSai5 If you have both light and dark mode Excalidraw images, this code makes sure the right one is used wth respect to the chosen preference in your btowser.
Here's the original explanation I wrote on the Quartz Discord:
Alright, so I managed to hack something to work.
- In Obsidian, I configured the Excalidraw plugin to embed the .excalidraw file in my notes, but also export light/dark SVG files.
- Then, in Quartz, I added an event listener on the DocumentContentLoaded event in the components/scripts/util.ts file in which I search for all a elements whose href endswith .excalidraw and replace those with image elements whose src corresponds to the current color theme (light/dark)
- In components/scripts/darkmode.inline.ts I modified the event handler for when the color theme is switched to search for all image elements and replace dark/light with the updated value in place
So, in Obsidian I just focus on the Excalidraw file, keeping things simple and making it easy to edit as well. Then, when pages are loaded in the browser I get to see the correctly themed SVG version of that drawing, and when I switch color theme from there my drawings switch accordingly.
Front-end deving also has been a while, so this is probably hacky, but at least it works and it can be improved from here (edited)
I have improved the code since. If you are interested I can update this gist some time. I also now realize this concept could be generalized to non-Excalidraw images as well maybe...
I have improved the code since. If you are interested I can update this gist some time. I also now realize this concept could be generalized to non-Excalidraw images as well maybe...
I would be interested to see any improvements since I'm also interested in exporting Excalidraw drawings to a Quartz website.
The version of the code I'm currently using can be found in my repo:
https://github.com/bartkl/bartkl.github.io/blob/v4/quartz/components/RenderExcalidraw.tsx
This component is configured in the quartz.layout.tsx
file in the header of the page I believe. Anyways, you can look that up in the repo as well.
Sadly I'm very busy currently so I don't have the time to help making this more accessible or make improvements/enhancements.
@bartkl Thanks for the update. I pointed to this gist in an ongoing quartz pull request.
I think your example helped with the light/dark switching. I'm not really a quartz developer so I can't say much else about the code.
Thanks for this code.
I was a little disappointed by your approach. I'm saving all my images in light mode and let the browser revert colors with css filter.
darkmode.inline.ts
// https://francoisbest.com/posts/2020/dark-mode-for-excalidraw
function applyDarkModeFilter(): void {
const savedTheme = document.documentElement.getAttribute("saved-theme");
const images: HTMLCollectionOf<HTMLImageElement> = document.getElementsByTagName('img');
for (let i = 0; i < images.length; i++) {
const image = images[i];
if (image.src && image.src.endsWith('excalidraw.svg')) {
// It consider image as light by default
if (savedTheme === "dark")
image.classList.add('image-dark');
else
image.classList.remove('image-dark');
}
}
}
document.addEventListener('DOMContentLoaded', applyDarkModeFilter);
document.addEventListener('themechange', applyDarkModeFilter);
darkmode.scss
.image-dark {
filter: invert(100%) hue-rotate(180deg);
}
@Guillaume-Fernandez that's an interesting alternative way of doing it. I'm not mainly a front-end developer, so I wouldn't have thought of a CSS solution like that :).
However, I don't think if I prefer your solution:
- You are moving rendering logic to the client (the color inversion) and I'm not sure if this could become noticable on slower clients for example for bigger images. (This might be nitpicky, just thinking out loud.)
- I'm not sure if simply inverting the colors is the best way to get a dark mode flavour of the images. I honestly doubt that's all the Excalidraw dark mode rendering does. Anyway, I rather rely on them for implementing that logic.
@bartkl
You made me curious!
I just checked, this is how excalidraw dark mode works.
I will test my approach for few days. I think it's simpler and does not need two excalidraw exports (light and dark).
I'm using quartz with VSCode Foam, this is why I can't easily export both images from Obsidian.
@Guillaume-Fernandez Nice find! That's really interesting.
Hello, can someone explain me what this code does??