はじめに

PaperMod テーマには記事を共有するボタンを表示させる機能が提供されています。機能を有効にすることで、記事の下部に共有ボタンが表示されるようになります。この機能で表示されるボタンの種類は設定でカスタマイズできます。

PaperModテーマで提供されている共有ボタン

また、Hugo の検索順序によって、テーマを上書きできます。これはテーマの FAQs にも記載されていました。これらの仕組みを利用して、記事タイトルと URL をクリップボードにコピーするボタンを作成し、それ以外を非表示にします。

本記事のゴール

「記事タイトル - URL」の文字列をクリップボードにコピーするボタンを作成し、そのボタン以外は非表示にすることがゴールです。

記事タイトルとURLをクリップボードにコピーするボタン(クリックでテキストを一時的に変更)のみの状態

実装

共有ボタンの種類を clipboard としてテーマに追加するための実装を行います。

共有ボタンを表示させる設定を行う

記事の下部に共有ボタンを表示させるためは、 Hugo の設定ファイルの paramsShowShareButtonstrue に設定する必要があります。1

以下は toml の設定ファイルを使用している場合の差分です。

[params]
UseHugoToc = true
showtoc = true
DateFormat = '2006-01-02'
ShowCodeCopyButtons = true
ShowBreadCrumbs = true
disableSpecial1stPost = true
ShowPostNavLinks = true
+ShowShareButtons = true

設定後、記事の下部に共有ボタンが表示されます。

PaperModテーマで提供されている共有ボタン

テーマファイルを編集する準備を行う

テーマを上書きするために、 themes/PaperMod/layouts/partials/share_icons.htmllayouts/partials/share_icons.html にコピーします。コピーされたファイルを編集することで、元のテーマファイルをそのままにしながらテーマの編集ができます。

クリップボードに記事のタイトルと URL をコピーする処理を作成する

2024-01-13 時点のテーマでは、 ycombinator の設定が一番下に定義されていました。今回はその下の に clipboard 用の設定を追加してみます。差分を以下に示します。

    {{- if (cond ($custom) (in $ShareButtons "ycombinator") (true)) }}
    <li>
        <a target="_blank" rel="noopener noreferrer" aria-label="share {{ $title | plainify }} on ycombinator"
            href="https://news.ycombinator.com/submitlink?t={{ $title }}&u={{ $pageurl }}">
            <svg version="1.1" xml:space="preserve" width="30px" height="30px" viewBox="0 0 512 512" fill="currentColor"
                xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
                <path
                    d="M449.446 0C483.971 0 512 28.03 512 62.554L512 449.446C512 483.97 483.97 512 449.446 512L62.554 512C28.03 512 0 483.97 0 449.446L0 62.554C0 28.03 28.029 0 62.554 0L449.446 0ZM183.8767 87.9921H121.8427L230.6673 292.4508V424.0079H281.3328V292.4508L390.1575 87.9921H328.1233L256 238.2489z" />
            </svg>
        </a>
    </li>
    {{- end }}
+    {{- if (cond ($custom) (in $ShareButtons "clipboard") (true)) }}
+    <li>
+        <button type="button" id="copy-page-title-and-url">クリップボードに記事タイトルとURLをコピーする</button>
+    </li>
+    {{- end }}
</ul>

+{{- if (cond ($custom) (in $ShareButtons "clipboard") (true)) }}
+<script>
+    const copyButton = document.querySelector('#copy-page-title-and-url')
+    copyButton.addEventListener('click', () => {
+        navigator.clipboard.writeText('{{ $title }} - {{ $pageurl }}')
+    })
+</script>
+{{- end }}

コピーボタンを作成し、ボタンが押された時の処理を JavaScript で実装しました。 '{{ $title }} - {{ $pageurl }}' の部分が「記事タイトル - URL」の形式になります。クリップボードにコピーする処理は非同期クリップボード APIClipboard.writeText() を使用しています。

この変更で以下のような表示になり、「クリップボードに記事タイトルとURLをコピーする」を選択すると、記事タイトルとURLがコピーされた状態になります。

記事タイトルとURLをクリップボードにコピーするボタンを追加

コピーされたことをわかりやすくする

現状では「クリップボードに記事タイトルとURLをコピーする」を選択した時の感触が無いため、一時的に「コピーしました!」と表示される仕組みを JavaScript で実装します。差分を以下に示します。

{{- if (cond ($custom) (in $ShareButtons "clipboard") (true)) }}
<script>
    const copyButton = document.querySelector('#copy-page-title-and-url')
    copyButton.addEventListener('click', () => {
-        navigator.clipboard.writeText('{{ $title }} - {{ $pageurl }}')
+        navigator.clipboard.writeText('{{ $title }} - {{ $pageurl }}').then(
+            () => {
+                const beforeText = copyButton.textContent
+                copyButton.textContent = 'コピーしました!'
+                setTimeout(() => {
+                    copyButton.textContent = beforeText
+                }, 1000)
+            }
+        )
    })
</script>
{{- end }}

「コピーしました!」と表示された1秒後(1000ミリ秒後)に元のテキストへ戻す処理になっています。

記事タイトルとURLをクリップボードにコピーするボタン(クリックでテキストを一時的に変更)

共有ボタンの種類を指定する

記事の下部に表示される共有ボタンの種類を指定するには、 Hugo の設定ファイルの paramsShareButtons を定義する必要があります。2 今回は clipboard のみ設定しました。

以下は toml の設定ファイルを使用している場合の差分です。

[params]
UseHugoToc = true
showtoc = true
DateFormat = '2006-01-02'
ShowCodeCopyButtons = true
ShowBreadCrumbs = true
disableSpecial1stPost = true
ShowPostNavLinks = true
ShowShareButtons = true
+ShareButtons = ['clipboard']

この変更で他の共有ボタンが表示されなくなりました。

記事タイトルとURLをクリップボードにコピーするボタン(クリックでテキストを一時的に変更)のみの状態

最後に

本記事では「記事タイトル - URL」の文字列をクリップボードにコピーするボタンの作成方法を紹介しました。

テーマ固有の配置ではありますが、提供元のテーマへの影響を与えずにテーマを編集することができました。また、今回の編集を経て、クリップボードに任意のテキストをコピーする処理は非同期クリップボード API で簡単に実装できることがわかりました。

本記事が誰かの役に立てられたら幸いです。最後まで読んでいただきありがとうございました。