Skip to main content
Categories
CMS中級の学習学習

Gatsbyブログのコードに色付け

  • Post Author
    By pitang1965
  • Post Date
    Tue Feb 08 2022
pexels-photo-10208097

概要

一目瞭然、私のGatsbyによるヘッドレスWordPressブログはCSSがなっていません。

とりあえずソースコードだけでも色付けしたいと思いました。

色のついていないソースコード

これを次のようにしました。

色のついたソースコード

使用したパッケージ

sugar-highを用いました。まだ新しいのパッケージなので使用は注意が必要と思います。

$ yarn add sugar-hig

sugar-highを用いた関数

src\util\highlightCode.js というコードを追加しました。highlightCodeContents という関数をエクスポートしています。

import { highlight } from 'sugar-high';

const entityConvert = (org_string) => {
  let converted = org_string.replace(/(&lt;)/g,"<");
  converted = converted.replace(/(&gt;)/g,">");
  return (converted);
}

const removeCodeTags = (org_string) => {
  let converted = org_string.replace("<code xmlns=\"http://www.w3.org/1999/xhtml\">","");
  converted = converted.replace("</code>","");
  return (converted);
}

export function highlightCodeContents(htmlContent) {
  try {
    // HTML文字列をDOMのDocumentとして解釈
    const parser = new DOMParser();
    const doc = parser.parseFromString(htmlContent, 'text/html');
    if (doc === null) return htmlContent;

    // コードブロック(<code> ... </code>)群を検索
    const codes = doc.querySelectorAll('code');
    
    // DOM ツリーを表すXML 文字列を構築するための準備
    const serializer = new XMLSerializer();
    
    // 各コードブロックを処理
    codes.forEach((code) => {
      let codeString = serializer.serializeToString(code); // codeタグの間を取りたいが、codeタグやエンティティ文字を含んでいたりいなかったり
      codeString = entityConvert(codeString); // エンティティ文字を通常の文字へ変換
      codeString = removeCodeTags(codeString);
      codeString = highlight(codeString);
      const newCode = document.createElement('code');
      newCode.innerHTML = codeString
      const parent = code.parentNode
      parent.replaceChild(newCode, code);
    });
    
    // DOMツリーを表す文字列を構築
    return serializer.serializeToString(doc);
  } catch (ex) {
    console.error(ex.message);
  }

  return htmlContent;
}

ブログ投稿の静的ファイルを作るコードの変更

src\templates\blog-post.js というコードを次のように2行変更しました。

:
import { highlightCodeContents } from '../util/highlightCode'; // 色付け関数をインポート
:
:
const BlogPostTemplate = ({ data: { previous, next, post } }) => {
:
        {!!post.content && (
          <ContentWrapper itemProp="articleBody">
            {parse(highlightCodeContents(post.content))}   // 色付け関数を使用
          </ContentWrapper>
        )}

sugar-high用及び<code>用のCSSの設定

src\style.css に次を追加しました。

.wp-block-code > code {
  background-color: #193549;
}

.sh__class {
  color: #66f2ff;
}
.sh__identifier {
  color: #fff2d0;
}
.sh__sign {
  color: #e1efff;
}
.sh__string {
  color: #a5ff7e;
}
.sh__keyword {
  color: #ff902f;
}
.sh__comment {
  color: #0088ff;
}

その他

  • gatsby developでテストする場合はその前に gatsby clean を実行します。
  • 今回使用した関数だけを試すプロジェクトはこちらをご覧ください。
  • ビルド時には次のようなエラーが出ました。Gatsby Cloudでも同様のエラーが出ています。しかし、コードは色付けされていました。
ビルドエラー
  • これについては、次の1行を追加してエラーは出なくなりました。
export function highlightCodeContents(htmlContent) {
  try {
    if (typeof window === 'undefined') return htmlContent; <--- この1行