Gatsbyjs で html のコードハイライトの見た目がおかしいのを直す

このサイトは Gatsbyjs で markdown から HTML を生成しており、 .md に記述したコードブロックは、prismjs によってコードハイライトされる。

それらは gatsby-transformer-remarkgatsby-remark-prismjs で行われるようだ(詳しくない)。

HTML のコードハイライトがダサい

JavaScript や C# など、大抵のコードブロックは期待通りの見た目になるが、HTML はどうも見た目が良くない。例えば次にHTMLとJavaScriptのコードブロックから生成された「見た目」を示す。

image.png

この画像の生成元であるコードブロックをこう↓だ。

実際には launguage に htmljavascript を記述しているが、ここではプレーンな見た目にしたいので削除している。

<!DOCTYPE html>
<html>
  <body>
    <h1 class="my-header">My First Heading</h1>
    <p 
      id="myParagraph"
      style="
        font-size: 8px;
        padding: 4px;
      "
    >
      My first paragraph.
    </p>
  </body>
</html>
const p = document.getElementById('myParagraph');
p.onclick = () => {
  console.log(`myParagraph clicked.`);
};

画像とコードを比べる通り、JavaScript は問題ないが、HTML の画像は、

  • DOCTYPE 以外のタグの文字サイズが小さい
  • スペースが挿入されている(<html >)など。
  • インラインstyleの改行が削除されている

など、見た目が非常に気になる。

尚、各ライブラリのバージョンは以下。現(2023年3月)時点で最新にしたつもり。

  • gatsby: 5.7.0
  • prismjs: 1.29.0
  • gatsby-transformer-remark: 6.7.0
  • gatsby-remark-prismjs: 7.7.0

原因と対策

生成されたハイライト済みの HTML と CSS を調べてみると、.tag:not(body) に適用されているスタイルがよろしくないようで、いくつかのプロパティを外してみたら他の言語と遜色ない見た目になった。

Untitled4.gif

対策として、このスタイルを上書きするスタイルを、私の構成でのスタイルファイル all.scss に記述して、プロパティを無効にする。

all.scss

.tag:not(body) {
  display: inherit;
  font-size: inherit;
  line-height: inherit;
  white-space: inherit;
  padding-left: inherit;
  padding-right: inherit;
}

その結果、無事スタイルが上書き無効化され、期待通りの見た目を得ることができた。

image.png

.tag:not(body) が定義されているのは (pack された後の) common.css で、これは prism.js の持ち物のようだが、HTML の見た目が冒頭のようになってしまうのが、仕様なのかバグなのか使い方の問題なのかは不明。

この対策も Workaround だけど、やらないよりマシなので適用しておく。

最後に、このサイトに Workaround が適用されればダサくない見た目であることが確認できるように、改めてコードブロックを貼っておく。

<!DOCTYPE html>
<html>
  <body>
    <h1 class="my-header">My First Heading</h1>
    <p 
      id="myParagraph"
      style="
        font-size: 8px;
        padding: 4px;
      "
    >
      My first paragraph.
    </p>
  </body>
</html>
const p = document.getElementById('myParagraph');
p.onclick = () => {
  console.log(`myParagraph clicked.`);
};