eleventy-plugin-code-clipboard

| 4 min read
Author: 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" 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 には対応していません。 ↩︎