コマンドの実行を示すとき、コマンドであることを伝えるためにも、次のようにプロンプト($)を書くことが多い。
```bash {iscopy=true}
$ hugo new posts/ramen.md
$ hugo server
```
反対に、コードブロックをコピーしたときのテキストにプロンプトが含まれていると、コマンドとして実行できない。
プロンプト($)を除外してコピーできると便利そうなので、その実現方法を調べる。
コードブロックのコピーボタンを表示する
実装方法

HUGOにはCode Block Render Hooksという、コードブロックがHTMLにレンダリングされる際、処理を差し込める機能がある。
Code Block Render Hooksの使い方は次の記事で説明したため、詳細の詳細は割愛する。
今回は、次のように言語の識別子の後に{iscopy=true}と書くと、コピーボタンを表示することにする。
```js {iscopy=true}
(() => {
  'use strict';
  console.log("Hello World!");
})();
```
実装
layouts/_default/_markup/render-codeblock.htmlは、次のように書く。
iscopyにtrueが渡されたときだけコピーボタンのDOMを生成する。
<div class="codeblock-container">
  {{ if .Attributes.iscopy }}
  <button class="codeblock-button" title="copy">
    Copy
  </button>{{ end }}
  <div class="codeblock-content">
    {{- highlight ( .Inner | safeHTML) .Type .Options }}
  </div>
</div>
コピーボタンを押した際の処理を行うJavaScriptのコードは次のとおり。
(function () {
  const copyToClipboad = async (text) => {
    if (navigator.clipboard) {
      navigator.clipboard.writeText(text);
    }
  };
  window.addEventListener("load", function () {
    const button = document.querySelector(".codeblock-button");
    if (button) {
      button.addEventListener("click", function () {
        const codeblock = document.querySelector(".codeblock-content");
        if (codeblock) {
          // 最後にスペース 2 つが入るので除外する
          const content = codeblock.textContent.replace(/  $/g, "");
          copyToClipboad(content);
        }
      });
    }
  });
})();
このJavaScriptのコードをHUGOテンプレートで読み込む。
<body>
{{- $js := resources.Get "js/copy.js" | resources.Minify | resources.Fingerprint -}}
{{- with $js -}}
<script src="{{ .RelPermalink }}"></script>
{{- end -}}
</body>
動作確認
[Copy]を押すと、次の内容をコピーできた。
(() => {
  'use strict';
  console.log("Hello World!");
})();
コピー時にプロンプト($)を除外する
実装
プロンプト($)を書くのは、言語の識別子にbashを指定したときだけにする。
render-codeblock.html内で分岐しても良いが、render-codeblock-言語の識別子.htmlというファイルで言語ごとに処理を分けることもできる。
今回の言語の識別子はbashなのでlayouts/_default/_markup/render-codeblock-bash.htmlというファイルを作成する。
プロンプトを取り除く処理は、JavaScript側で行う。
コードブロックのコピーボタンを表示するで示したコードに対し、冒頭の$ を正規表現で取り除く処理を追加する。
(function () {
  const copyToClipboad = async (text) => {
    if (navigator.clipboard) {
      navigator.clipboard.writeText(text);
    }
  };
  window.addEventListener("load", function () {
    const button = document.querySelector(".codeblock-button");
    if (button) {
      button.addEventListener("click", function () {
        const codeblock = document.querySelector(".codeblock-content");
        if (codeblock) {
          // 最後にスペース 2 つが入るので除外する
          const content = codeblock.textContent.replace(/  $/g, "");
-          copyToClipboad(content);
+          const contentWithoutPrompt = content.replace(/^\$\s+/gm, "");
+          copyToClipboad(contentWithoutPrompt);
        }
      });
    }
  });
})();
JavaScriptのコードをテンプレートで読み込む処理は、先ほどと同じなので省略する。
動作確認
[Copy]を押すと、次の内容をコピーできた。
hugo new posts/ramen.md
hugo server
補足:CSS
今回は、コピーボタンに次のCSSを適用した。
.codeblock-button {
  width: fit-content;
  margin: 1rem 0 0;
  padding: 0.4rem;
  font-size: 0.9rem;
  color: rgb(255, 255, 255);
  background-color: #05acc1;
  border: 0;
}
.codeblock-button:hover {
  filter: brightness(1.25);
}
.codeblock-button + .codeblock-content {
  margin-top: -1.25rem;
}