highlight.jsをファイル読み込みで読み込んだコードに使ってみる

# はじめに
　コードハイライトのライブラリであるhighlight.jsを使ってみる。

https://highlightjs.org/

適用するのはネット上の、自作ライブラリのコード。

https://github.com/inaridarkfox4231/fisceToyBox/tree/main

ちょっとしたツールボックス。

## つかいかた
　ここに詳しく書いてある。

https://github.com/highlightjs/highlight.js

CDNを使おうと思う。

## コード全文

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Code Highlight</title>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/styles/base16/oceanicnext.min.css" /> <!-- パレット -->
    <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/highlight.min.js"></script> <!-- 生成機 -->
    <style>
      /* カスタマイズは自由自在。 */
      .hljs-comment{
        color:aquamarine;
      }
    </style>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@200..900&display=swap" rel="stylesheet" />
  </head>
  <body>
    <pre><code class="javascript" id="target-tag">
</code></pre>
    <!--<script>hljs.highlightAll();</script>-->
    <script src="main.js"></script>
  </body>
</html>
```

```javascript:main.js
async function getText(url){
  // text string
  const response = await fetch(url);
  if(!response.ok){
    throw new Error(`response.status: ${response.status}`);
  }
  const txt = response.text(); // テキストデータが欲しい時はこれ
  return txt;
}

getText("https://inaridarkfox4231.github.io/fisceToyBox/fisceToyBox.js").then((res) => {
  const codeDom = document.getElementById("target-tag");

  res = res.replaceAll('&', '&amp;');
  res = res.replaceAll('<', '&lt;');
  res = res.replaceAll('>', '&gt;');
  res = res.replaceAll('"', '&quot;');
  res = res.replaceAll("'", '&apos;');

  codeDom.innerHTML = res;

  hljs.highlightElement(codeDom);
});
```

```css:style.css
code {
  font-family: Inconsolata;
  line-height:130%;
  font-size:18px;
  margin:0;
}
```

結果（一部）

![wqswc2wc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/500478c6-2a91-45aa-adb3-11a22f32b344.png)

## 解説
　コードのフォントは人気のInconsolataで、Google fontの一種で、こっちから使える：

https://fonts.google.com/specimen/Inconsolata

テーマはたくさんあり、ここで選ぶことができる：

https://highlightjs.org/demo

自分はoceanicnextが気に入ったのでこれを使ってる。demoのうちbase16とあるものは、コードにもあるようにbase16をはさんで指定する。最後にminを付けるのを忘れずに。ここから取ってるらしい：

https://github.com/highlightjs/highlight.js/tree/main/src/styles

```html
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/styles/base16/oceanicnext.min.css"> <!-- パレット -->
    <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/highlight.min.js"></script> <!-- 生成機 -->
```
そのあとスクリプトを埋め込んでいる。このときhljsがグローバルになり、いろいろ呼び出すことができる。

　なお、oceanicnextはコメントアウトが見えづらかったのでそこだけカスタマイズさせていただいてる：
```html
    <style>
      /* カスタマイズは自由自在。 */
      .hljs-comment{
        color:aquamarine;
      }
    </style>
```

直接埋め込んでもいいが、今回は読み込んだファイルを使いたいので、スクリプトでコードを入れてから関数で動的にハイライトを掛けている。

```js
async function getText(url){
  // text string
  const response = await fetch(url);
  if(!response.ok){
    throw new Error(`response.status: ${response.status}`);
  }
  const txt = response.text(); // テキストデータが欲しい時はこれ
  return txt;
}
```
この関数で非同期的にテキストデータを取得できる。jsでも、htmlでも、cssでも、何でも。
これを次のようにプロミスでinnerHTMLにセットして、highlightElementで動的にハイライトする。
```js
getText("https://inaridarkfox4231.github.io/fisceToyBox/fisceToyBox.js").then((res) => {
  const codeDom = document.getElementById("target-tag");

  res = res.replaceAll('&', '&amp;');
  res = res.replaceAll('<', '&lt;');
  res = res.replaceAll('>', '&gt;');
  res = res.replaceAll('"', '&quot;');
  res = res.replaceAll("'", '&apos;');

  codeDom.innerHTML = res;

  hljs.highlightElement(codeDom);
});
```
なお、その際にエスケープシーケンスによる置き換え処理を実行している。実はなくてもうまくいくようになっているが、その場合セキュリティエラーを出されてしまう。試しにこれらすべてをコメントアウトすると：

![adqdw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/3a1ac03d-ddbc-4cf7-93f6-45853a59923b.png)

このように変換はうまくいくがエラーを食らう。なのでなるべくなら変換した方がよい。

## 直接ハイライトする場合
　ファイルを読み込まずに直接ハイライトする場合は、普通に書けばいい。
```html
  <body>
    <pre><code class="javascript" id="target-tag">console.log("hello, world!");
const p = (2 < 3) && (4 > 1);
</code></pre>
    <script>hljs.highlightAll();</script>
    <!--<script src="main.js"></script>-->
  </body>
```

結果：

![qfwqcwv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/d67d2d48-24d2-47eb-903e-d402fb1cfce3.png)

この場合もエスケープは不要だが、エスケープしても同じ結果にはなる。

```html
  <body>
    <pre><code class="javascript" id="target-tag">console.log("hello, world!");
const p = (2 &lt; 3) &amp;&amp; (4 &gt; 1);
</code></pre>
    <script>hljs.highlightAll();</script>
    <!--<script src="main.js"></script>-->
  </body>
```
結果：同じ

なお、当然だがhtmlでこんなことをすればエラーを食らうし、正常な結果にならない。
```html
  <body>
    <pre><code class="html" id="target-tag"><p>こんにちは！せかい！</p>
</code></pre>
    <script>hljs.highlightAll();</script>
    <!--<script src="main.js"></script>-->
  </body>
```

結果：

![fswgvwvev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/d14d615e-324f-4e60-962d-7fe5b8e4263d.png)

エスケープしましょう。

```html
  <body>
    <pre><code class="html" id="target-tag">&lt;p&gt;こんにちは！せかい！&lt;/p&gt;
</code></pre>
    <script>hljs.highlightAll();</script>
    <!--<script src="main.js"></script>-->
  </body>
```

結果：

![wwfwfw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/caf27e47-5c72-4bb3-b711-02fb3f79154c.png)

# おわりに
　コードハイライトにはいろんな方法があるようです。今回はテーマの豊富さからこれを選びました。次の記事は非常に参考になりました。ありがとうございます。

https://qiita.com/tadnakam/items/99088d78512a20e75ff3

拝読感謝。