highlight.jsのスタイルをダークモードに応じて切り替える
ページ上のコードにシンタックスハイライトを適用するのに、highlight.jsというプラグインがあります。
ハイライトのスタイルもたくさんの種類が用意されていて、当ブログでは今までatom-one-darkを適用していたのですが、ライトモード時はコード部分を白背景にしたかったのもあって、ダークモードに応じてhighlight.jsのスタイルも切り替わるようにしてみました。
表示サンプル
ヘッダーにあるダークモードスイッチで切り替えてみてください。atom-one-lightとatom-one-darkが入れ替わります。
class MyClass {
public static myValue: string;
constructor(init: string) {
this.myValue = init;
}
}
import fs = require("fs");
module MyModule {
export interface MyInterface extends Other {
myProperty: any;
}
}
declare magicNumber number;
myArray.forEach(() => { }); // fat arrow syntax
やったこと
highlight.jsのスタイルは、lightとdarkのセットで用意されているものがあり、その組み合わせであればCSSの構造も似通っているので、カスタマイズする際は、それらを使うのが簡単だと思います。
やることは単純で、
- lightの方のファイルをコピーして、色指定部分をそれぞれCSS変数に置き換える
- CSS変数にライトモードの色を代入する
- darkの方を参考にしながら、ダークモード時の色をメディアクエリで変数に上書きする
という地道な作業です。これで2つのスタイルが1つにまとまるという訳ですね。
atom-one-lightは、コメントアウト部分に使う色がまとめてあったので、ハイフンを先頭につけるだけでそのままCSS変数として利用でき、作業が楽でした。
atom-one-light/dark
当ブログで適用している、atom-one-lightとatom-one-darkが切り替わるスタイルです。BSDライセンスということで、配布してもよさそうなので下に置いておきます。
/*
Atom One Light by Daniel Gamage
Original One Light Syntax theme from https://github.com/atom/one-light-syntax
base: #fafafa
mono-1: #383a42
mono-2: #686b77
mono-3: #a0a1a7
hue-1: #0184bb
hue-2: #4078f2
hue-3: #a626a4
hue-4: #50a14f
hue-5: #e45649
hue-5-2: #c91243
hue-6: #986801
hue-6-2: #c18401
*/
/*
Atom One Dark by Daniel Gamage
Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax
base: #282c34
mono-1: #abb2bf
mono-2: #818896
mono-3: #5c6370
hue-1: #56b6c2
hue-2: #61aeee
hue-3: #c678dd
hue-4: #98c379
hue-5: #e06c75
hue-5-2: #be5046
hue-6: #d19a66
hue-6-2: #e6c07b
*/
.hljs {
--base: #fafafa;
--mono-1: #383a42;
--mono-2: #686b77;
--mono-3: #a0a1a7;
--hue-1: #0184bb;
--hue-2: #4078f2;
--hue-3: #a626a4;
--hue-4: #50a14f;
--hue-5: #e45649;
--hue-5-2: #c91243;
--hue-6: #986801;
--hue-6-2: #c18401;
}
@media (prefers-color-scheme: dark) {
.hljs{
--base: #282c34;
--mono-1: #abb2bf;
--mono-2: #818896;
--mono-3: #5c6370;
--hue-1: #56b6c2;
--hue-2: #61aeee;
--hue-3: #c678dd;
--hue-4: #98c379;
--hue-5: #e06c75;
--hue-5-2: #be5046;
--hue-6: #d19a66;
--hue-6-2: #e6c07b;
}
}
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: var(--mono-1);
background: var(--base);
}
.hljs-comment,
.hljs-quote {
color: var(--mono-3);
font-style: italic;
}
.hljs-doctag,
.hljs-keyword,
.hljs-formula {
color: var(--hue-3);
}
.hljs-section,
.hljs-name,
.hljs-selector-tag,
.hljs-deletion,
.hljs-subst {
color: var(--hue-5);
}
.hljs-literal {
color: var(--hue-1);
}
.hljs-string,
.hljs-regexp,
.hljs-addition,
.hljs-attribute,
.hljs-meta-string {
color: var(--hue-4);
}
.hljs-built_in,
.hljs-class .hljs-title {
color: var(--hue-6-2);
}
.hljs-attr,
.hljs-variable,
.hljs-template-variable,
.hljs-type,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-number {
color: var(--hue-6);
}
.hljs-symbol,
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-title {
color: var(--hue-2);
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
.hljs-link {
text-decoration: underline;
}