注目イベント!
春の新人向け連載企画開催中
新人エンジニアの皆さん、2024春、私たちと一緒にキャリアアップの旅を始めませんか?
IT業界への最初の一歩を踏み出す新人エンジニアをサポートする新連載スタート!
mameyose

eleventy-plugin-code-clipboard

| 5 min read
Author: noboru-kudo noboru-kudoの画像

eleventy-plugin-code-clipboardは、静的サイトジェネレータツールの1つであるeleventy(以下11ty)のカスタムプラグインです。

このプラグインは、マークダウンのコードブロックで生成されたものに対して、クリップボードコピー機能を提供するもので、本サイトでも使用されています。

プラグインは以下の2つの機能で構成されます。

markdown-it カスタムレンダラー

#

11tyのマークダウンパーサー markdown-itのカスタムレンダラーです。
マークダウンで以下のようなコードブロック[1]を記述すると...。

echo "show clipboard button on code block"

このプラグインは、以下のようなHTMLに変換します(見やすくなるように一部改行しています)。

<div style="position: relative">
  <pre class="language-shell">
    <code id="code-3" class="language-shell">
      <span class="token builtin class-name">echo</span> <span class="token string">"show clipboard button on code block"</span>
    </code>
  </pre>

  <button class="code-copy " data-clipboard-target="#code-3" 
          style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" 
          title="Copy">
    <span>
      <span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
    </span>
  </button>
</div>

オリジナルのHTML(@11ty/eleventy-plugin-syntaxhighlightで生成されたもの)の中に、クリップボードアイコンのボタンを配置します。

11ty shortcode Function(initClipboardJS)

#

11tyではShortcodeと呼ばれるテンプレートエンジンを拡張する仕組みがあります。
このプラグインではinitClipboardJSというShortcodeを提供しています。
これは、HTMLロード時にクリップボードライブラリ(clipboard.js)を初期化し、ボタンクリック時にクリップボードコピーをするソースコードを生成します。
また、クリップボードコピーに成功するとツールチップメッセージ(デフォルトはCopied!)を表示します。

使い方は以下の通りです。下記はNunjucksテンプレートを利用しています(他のテンプレートも使えるはずですが未検証です)。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link href="{{ '/css/style.css' | url }}" rel="stylesheet" />
  <body>
    {{ content | safe }}

    {% initClipboardJS %}
  </body>
</html>

{% initClipboardJS %}部分でプラグインのShortcodeを実行しています。

これで静的サイトを生成すると、以下のようにソースコードが生成されます。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link href="{{ '/css/style.css' | url }}" rel="stylesheet" />
  <body>
    <div>
      <-- Site Contents... -->
    </div>

    <script>
      function showTooltip(el, msg) {
        if (!el.trigger.className.includes('tooltipped')) {
          el.trigger.children[0].className = 'tooltipped tooltipped-s';
          el.trigger.children[0].ariaLabel = msg;
        }
      }
  
      window.onload = () => {
        const clipboard = new ClipboardJS('.code-copy');
        clipboard.on('success', (e) => showTooltip(e, 'Copied!'));
        clipboard.on('error', (e) => showTooltip(e, 'Failed...'));
      };
    </script>
    <script async src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.js"></script>
  </body>
</html>

見やすさのために圧縮前のものを載せていますが、実際にはJavaScriptソースコード部分はUglifyJSで圧縮されたものになります。

導入方法

#

基本的にはプロジェクトのdevDependenciesへのプラグインインストールと、.eleventy.jsに以下を追加するだけで利用可能になります。
具体的な設定については、リポジトリのexampleを参照してください。

const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight');
const codeClipboard = require('eleventy-plugin-code-clipboard');
const markdownIt = require('markdown-it');

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(syntaxHighlight); // 必須ライブラリ
  eleventyConfig.addPlugin(codeClipboard); // プラグイン有効化

  eleventyConfig.addPassthroughCopy('./src/css');

  // その他の設定
  
  /* Markdown Overrides */
  const markdownLibrary = markdownIt({
    html: true,
    breaks: true,
  }).use(codeClipboard.markdownItCopyButton); // プラグインのカスタムレンダラー設定

  eleventyConfig.setLibrary('md', markdownLibrary);

  return {
    passthroughFileCopy: true,
    dir: {
      input: 'src',
    },
  };
};

上記の他にも、外部CSSライブラリ(アイコン/ツールチップ)のセットアップが必要になります。
詳しくは README を参照してください。

本サイト向けに作成したものをnpmパッケージ化しただけで、まだまだ汎用性が低いですが、時間を見つけて改善していきたいと思います。


  1. 現状は言語なしのコードブロックやIndented code blocks には対応していません。 ↩︎

豆蔵では共に高め合う仲間を募集しています!

recruit

具体的な採用情報はこちらからご覧いただけます。