最近ブログのデザインを変えた。その続きで少し改修した。
何を修正したのか?
コードブロックでファイル名などのラベルを出せたらいいなと思ったので対応した。
↓これはスクリーンキャプチャ。hello.java
が表示されている。シンタックスハイライトが効いていることを確認したかっただけなのでコードの内容は関係ない。
こんな感じ
↓これは実際のコードブロック。
sealed interface Mapping<T> { T value(); record A(Boolean value) implements Mapping<Boolean> {} record B(String value) implements Mapping<String> {} }
↓こう書いている
```java:hello.java sealed interface Mapping<T> { T value(); record A(Boolean value) implements Mapping<Boolean> {} record B(String value) implements Mapping<String> {} } ```
仕組み
僕は、はてなブログをマークダウンで書いているので、コードブロックは```java
みたいに言語を指定して書いている。そうするとこんな感じのHTMLになる。
<pre class="code lang-java" data-lang="java" data-unlink="">
classにlang-java
が設定されて、data-langにjava
が設定されている。ここで```java:hello.java
とコロンにつなげてラベルを書いてみるとこうなる。
<pre class="code java:hello.java" data-lang="java:hello.java" data-unlink="">
classのlang-java
がjava:hello.java
になっていて、はてなのシンタックスハイライトは効かない状態になる。だけど、僕はブログのデザインを変えたときに、コードブロックにはPrism.jsを使うようにしているので問題ない。
Prism.jsのtoolbarプラグインを使う
自分で実装しようかと思ったけど、ちょうどいいプラグインがあったから使うことにした。
- Toolbarプラグイン: https://prismjs.com/plugins/toolbar/
pre
タグにdata-label
属性を指定すると、その値をラベルとするDOMを生成してくれる。
これで材料が揃った
↓のdata-lang
の部分をコロンでスプリットして、コロンの前までを言語として扱って、コロンの後ろをラベルと扱うようにすればいい
<pre class="code java:hello.java" data-lang="java:hello.java" data-unlink="">
こう書いた
<script type="module"> function splitLangAndLabel(dataLang) { if (!dataLang) return [dataLang]; const index = dataLang.indexOf(":"); if (index == -1) return [dataLang]; return [dataLang.substring(0, index), dataLang.substring(index + 1)]; } document.addEventListener("DOMContentLoaded", (event) => { document.querySelectorAll("pre.code").forEach((pre) => { const [lang, label] = splitLangAndLabel(pre.dataset.lang); const code = document.createElement("code"); code.textContent = pre.textContent; code.className = `code language-${lang}`; pre.innerText = ""; if (label) { pre.dataset.label = label; } pre.appendChild(code); window.Prism.highlightElement(code); }); }); </script>
これでdata-label
にhello.java
が設定されてToolbarプラグインで処理されて、↓こういうHTMLがpre
タグの後ろに追加される。
<div class="toolbar"> <div class="toolbar-item"> <span>hello.java</span> </div> </div>
あとはCSSで
ごにょごにょすればいいのでGridを使ってpre
とdiv
の前後を入れ替えてできあがり。
/* コードブロックのラベル */ .code-toolbar { display: grid; grid-template-rows: auto; margin: .5em -10px; .toolbar { grid-row: 1; padding: 0 10px; background-color: #2d2d2d; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 0.8rem; .toolbar-item { border-bottom-right-radius: 0.25em; border-bottom-left-radius: 0.25em; width: fit-content; padding: 5px 10px; background-color: #424242; color: #eceff1; } } }
自分のChromeでしか確認していないから他のブラウザでどうなるかは分かっていないし、はてなブログの生成するHTMLに変更があると動かなくなるので他の人におすすめはしないけど、自分が個人で楽しむ分には満足かな。