nikkie-ftnextの日記

イベントレポートや読書メモを発信

sphinx-revealjs製のスライドのコードブロックを、ボタン一発でコピーできるようにしたい!

はじめに

恋アスが現実に!胸熱... nikkieです。

登壇資料作成にはsphinx-revealjsを愛用して静的サイトとしてホストしています1
このたびブレイクスルーが起きました!
コードブロックをワンクリックでコピーできるボタンを設置できたのです🙌

目次

結論

Reveal.jsのプラグインを使って実現しました!

https://ftnext.github.io/2024-slides/pyconshizu/logging-with-nullhandler.html#/4/1 を開いて、「Copy」ボタンでコード(4行)をコピーできます

初手、sphinx-copybutton!

まず試したのですが、結論としてはできませんでした(私の設定が悪い可能性はあります)

sphinx-revealjsで作るスライドのHTMLには適用できませんでしたが、Sphinxで作る(通常の)HTMLにはめちゃめちゃ便利です!

Reveal.js CopyCode

sphinx-revealjsはReveal.jsを使ったHTML(=スライド)をビルドします。
そこでReveal.jsのプラグインを探しました。

見つかったのがCopyCode!

A simple plugin for Reveal.js that automatically shows a 'copy' button in code blocks.

以下のようなコードブロック(Reveal.js製スライド内のコードブロックと理解)に、

<pre>
  <code>
    Here is the code
  </code>
</pre>

Copyボタンを追加してくれます!(<pre>に追加するらしい)

設定方法は、スライドのHTMLに以下を追加
(※sphinx-revealjsがビルドした手元のHTMLをいじっています)

<!-- build/revealjs/practice/slide.html -->
<div>
  <!-- Presentation body -->
</div>

<script src="../_static/revealjs4/dist/reveal.js"></script>
<script src="../_static/revealjs4/plugin/copycode/copycode.js"></script>
<script>
    var revealjsConfig = new Object();
    revealjsConfig.plugins = [
      CopyCode,
    ];
    Reveal.initialize(revealjsConfig);
</script>

ref: https://github.com/Martinomagnifico/reveal.js-copycode/tree/v1.2.0?tab=readme-ov-file#adding-copycode-to-your-presentation

CopyCodeのソースコードGitHubからダウンロードして置きました
ここにある3つのファイルです:https://github.com/Martinomagnifico/reveal.js-copycode/tree/v1.2.0/plugin/copycode

sphinx-revealjsの機構を利用する

sphinx-revealjs 2系 (2.9.3)2 で動かしています(3系は未検証)

revealjs_script_pluginsという設定値を指定しました。
https://sphinx-revealjs.readthedocs.io/en/v2.9.3/configurations/#confval-revealjs_script_plugins

# conf.py
revealjs_script_plugins = [
    {
        "name": "CopyCode",
        "src": "revealjs4/plugin/copycode/copycode.js",
    },
]

これでビルド時に上で示したようなHTMLが生成されます。

残るは、プラグインの設定値に示したsrcのファイル群をどう扱うか。
ここで、sphinx-revealjsはいくつかのプラグインを内蔵しています。
設定値revealjs_script_pluginsのドキュメントより

revealjs_script_plugins = [
    {
        "src": "revealjs4/plugin/highlight/highlight.js",
        "name": "RevealHighlight",
    },
]

このhighlight.jsは、sphinx-revealjsにバンドルされています。
私の環境でのパス:venv/lib/python3.12/site-packages/sphinx_revealjs/themes/sphinx_revealjs/static/revealjs4/plugin/highlight/highlight.js

(脱線)GitHubではこちら:https://github.com/attakei/sphinx-revealjs/tree/v2.9.3/sphinx_revealjs/themes/sphinx_revealjs/static
パッケージとして配布する際にReveal.jsのソースコードを含める実装になっているようです3
ref: https://github.com/attakei/sphinx-revealjs/blob/v2.9.3/.github/workflows/release.yml#L18-L22 (脱線終わり)

sphinx-revealjsの動きとして、venv/lib/python3.12/site-packages/sphinx_revealjs/themes/sphinx_revealjs/static/revealjs4/plugin下はbuild/revealjsディレクトリ以下の静的ファイル配置ディレクトリにコピーされているんですよね。
そこでまずはここにCopyCodeのソースを置いてみようと考えました。
これがうまくいって、ビルドしたスライドにCopyボタンが表示できています!

終わりに

sphinx-revealjs製のスライドのコードブロックにCopyボタンを出しました。
Reveal.jsのCopyCodeプラグインを採用し、sphinx-revealjsの仕組みを利用しています。

  • 設定値revealjs_script_plugins
  • CopyCodeのソースのファイルを入れたcopycodeディレクトリを、site-packagesのsphinx_revealjs/themes/sphinx_revealjs/static/revealjs4/plugin下に置く

「発表スライド中のコードをボタン一発でコピーできるようにしたい!」というやりたいことに対して、sphinx-revealjsを設定(正確にはハック?)して実現できてとても達成感があります。
こういうの、好きなんですよね〜
Martinomagnificoさん、素晴らしいプラグインをありがとうございます!

CopyCodeのソースの配置4は誰でも簡単にできるわけではないという伸びしろを感じているので、ここはなにか考えてみたいところです。