Reputation: 8722
I have the following code:
<head>
<title></title>
<link rel="stylesheet" href="./styles/darkula.css">
<link rel="stylesheet" href="./styles/github.css">
</head>
<body>
<div class="container">
<pre>
<code class="html">
<button class="button is-primary">Primary</button>
</code>
</pre>
<!-- Change theme button -->
<button onclick="changeTheme()">Change theme</button>
</div>
<script src="highlight.pack.js"></script>
<script>
hljs.initHighlightingOnLoad();
document.querySelectorAll("code").forEach(function(element) {
element.innerHTML = element.innerHTML.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
});
function changeTheme() {
...
}
</script>
</body>
I am loading 2 themes in my file. Because the github theme is being loaded after the darkula theme, it gets applied to all the code elements automatically. This is fine, but I would like to allow users to dynamically change the theme to darkula with the click of the button. I could not find anything in the documentation. How can I do this?
Upvotes: 8
Views: 9788
Reputation: 56905
Here's a runnable snippet, to elaborate on the existing answers and provide a quick starter approach:
const themes = getThemes();
document.querySelector("span").textContent = themes[0];
hljs.highlightAll();
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowRight") {
nextTheme();
event.preventDefault();
} else if (event.key === "ArrowLeft") {
prevTheme();
event.preventDefault();
}
});
function prevTheme() {
themes.unshift(themes.pop());
changeTheme();
}
function nextTheme() {
themes.push(themes.shift());
changeTheme();
}
function changeTheme() {
document.querySelector('link[href*="highlight.js"]').remove();
const link = document.createElement("link");
const theme = themes[0];
link.rel = "stylesheet";
link.href = `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/${theme}.min.css`;
document.querySelector("head").append(link);
document.querySelector("span").textContent = theme;
}
function getThemes() {
return [
"a11y-dark",
"a11y-light",
"agate",
"an-old-hope",
"androidstudio",
"arduino-light",
"arta",
"ascetic",
"atom-one-dark-reasonable",
"atom-one-dark",
"atom-one-light",
"brown-paper",
"codepen-embed",
"color-brewer",
"dark",
"default",
"devibeans",
"docco",
"far",
"felipec",
"foundation",
"github-dark-dimmed",
"github-dark",
"github",
"gml",
"googlecode",
"gradient-dark",
"gradient-light",
"grayscale",
"hybrid",
"idea",
"intellij-light",
"ir-black",
"isbl-editor-dark",
"isbl-editor-light",
"kimbie-dark",
"kimbie-light",
"lightfair",
"lioshi",
"magula",
"mono-blue",
"monokai-sublime",
"monokai",
"night-owl",
"nnfx-dark",
"nnfx-light",
"nord",
"obsidian",
"panda-syntax-dark",
"panda-syntax-light",
"paraiso-dark",
"paraiso-light",
"pojoaque",
"purebasic",
"qtcreator-dark",
"qtcreator-light",
"rainbow",
"routeros",
"school-book",
"shades-of-purple",
"srcery",
"stackoverflow-dark",
"stackoverflow-light",
"sunburst",
"tokyo-night-dark",
"tokyo-night-light",
"tomorrow-night-blue",
"tomorrow-night-bright",
"vs",
"vs2015",
"xcode",
"xt256",
];
}
<meta name="color-scheme" content="dark light" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/a11y-dark.min.css"
/>
<button type="button" onclick="prevTheme()"><</button>
<button type="button" onclick="nextTheme()">></button>
<span></span>
<pre><code>{
"web-app": {
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
"log": true,
"logMaxSize": null,
"dataLog": 1123
}
}
}</code></pre>
Basically, I rip out the existing style tag and replace it with the desired one. Crude, but effective.
Preloading the styles helps ensure smooth transitions, if desired.
Upvotes: 2
Reputation: 2004
There's a github response to this same question here https://github.com/highlightjs/highlight.js/issues/2115
Basically you include all the themes you want, and then disable all the link tags except for the selected theme.
The highlight.js demo page does this https://highlightjs.org/demo/
The GitHub repository is for the code can be found here.
(https://github.com/highlightjs/highlight.js/blob/master/demo/demo.js)
Upvotes: 5
Reputation: 1882
If you are using sass/scss
and handle your dependencies with npm
, you can do the next thing:
@use "sass:meta";
html[data-theme="light"] {
@include meta.load-css("highlight.js/styles/a11y-light");
}
html[data-theme="dark"] {
@include meta.load-css("highlight.js/styles/a11y-dark");
}
To make it to work, you need to define the data-theme
attribute in your html tag.
<html data-theme="light">
<!-- ensure to change it with javascript and define one with default -->
...
</html>
Upvotes: 7