晴耕雨読

working in the fields on fine days and reading books on rainy days

[JavaScript] Webページでコマンド例の「$」の部分をコピペさせない

Webページで $ command args のようにコマンド例を示すときに $ をコピペさせないようにする方法について説明します。 加えて、Prism.js で $ をコピペさせない設定方法も紹介します。

結論から言うと、$ の部分を user-select: none にします。 何もしていないHTMLでは以下のように書きますが、これでは $ も選択できるので、コピーされてしまいます。

  • HTMLソース

    <pre><code>$ command args</code></pre>
    
  • 実際の表示のされ方 ($ の部分は選択できます)

    $ command args

そこで $ の部分を span で囲んでスタイルを user-select: none にします。 こうすることで、$ は選択できなくなり、コピーされなくなります。

  • HTMLソース

    <pre><code><span style="user-select: none">$ </span>command args</code></pre>
    
  • 実際の表示のされ方 ($ の部分が選択できません)

    $ command args

Prism.js で $ をコピペさせない

Webページで表示させるプログラムのシンタックスハイライトに Prism.js を使っている場合は、$ の部分を token として認識させることで簡単に、user-select: none を適用させることができます。

bash の行頭にある $ を選択できないようにするには次のHTMLを使います。

<link rel="stylesheet" href="path/to/prism.css">
<script src="path/to/prism.js"></script>

<!-- token の追加 -->
<script type="text/javascript">
  Prism.languages.bash.prompt = /^\$ /m;
</script>

<!-- token に対するスタイルの設定 -->
<style>
  .token.prompt {
    user-select: none;
  }
</style>

正規表現 /^\$ /m について、オプション m を指定すると、行頭 ^ のマッチングが、文字列の先頭だけでなく、各行の行頭にもマッチするようになります。これにより、各行の行頭にある $ だけを token として取り出すことができます。

取り出した token は タグが付けられるので、CSSで .token.prompt のスタイルを user-select: none にします。

結果は以下の通りです。コピーするときのUXがいい感じになりました。行頭の $ は選択できませんが、変数名などは選択できることが確認できると思います。

$ echo hello world
$ echo $PATH

ちなみに元ネタは @junya さんのツイートです1

Prism.js で PS> をコピペさせない

2021/10追記:PowerShellのプロンプトである PS> を選択できないようにするには、次のJavaScriptを追加します。

Prism.languages.insertBefore('powershell', 'function', {
  'prompt': /^PS> /m,
})

PowerShellの字句解析でPromptの部分「PS>」もtokenにするためのプログラムです。 デフォルトだとPSがfunctionと判定されるので、insertBeforeでfunctionの解析を前に先に評価するようにする必要があります。

以上です。


  1. Webページで "$ command args" みたいなコマンド例をユーザーにコピペさせる際に、"$" の部分 user-select: none しておくとUXがいい感じになるのか 📝 – ᴊᴜɴʏᴀ oɢᴜ®ᴀ @junya