💎
ルビを含む文字列をコピーするときに、ルビのテキストは除外したい
表題通り、Web ページ上でルビを含む文字列をコピーするときに、ルビのテキストは削除したうえでコピーできるようにしたいです。
例えば、次のような HTML があるとします。
<p><ruby>亜米利加<rt>アメリカ</rt></ruby></p>
この HTML は、次のように展開されます。
(選択箇所にもよりますが、)「亜米利加」を選択・コピーしようとすると、ルビの「アメリカ」もクリップボードにコピーされてしまいます。
ルビのアメリカまでクリップボードにコピーされてしまう。
解決方法1: user-select
最も簡単な解決方法は user-select
でしょう。
先程の HTML を次のように修正します。
変更点は rt 要素に user-select: none
を追加しています。
<p><ruby>亜米利加<rt style="user-select: none;">アメリカ</rt></ruby></p>
これでルビはコピー対象からハズれるようになりました。
mdn や can i use を見てみると、user-select
は、主要ブラウザでサポートされているようですので、気兼ねなく利用できそうですね。
解決方法2: JavaScript でなんとかする
なんらかの理由で JavaScript で解消しなければならない場合についても、触れておきます。
…触れておきますと言いつつ、面倒なので AI に書いてもらいました。
AI に丸投げだとアレなので、コメントで補足文を置いておきます。
<p><ruby>亜米利加<rt>アメリカ</rt></ruby></p>
document.addEventListener("copy", (event) => {
event.preventDefault();
const selection = document.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0); // FireFox のような複数の要素を選択可能なブラウザでは getRangeAt(0) ではなく、すべての要素を取り出すよう調整した方が良い。
const cloneContents = range.cloneContents();
const rubies = cloneContents.querySelectorAll("rt"); // ルビをすべて選択して削除する
rubies.forEach((ruby) => ruby.remove());
const div = document.createElement("div"); // ルビ削除後のテキストを div に入れる
div.appendChild(cloneContents);
const text = div.innerText;
event.clipboardData.setData("text/plain", text); // クリップボードに div のテキストを入れる
}
});
ちなみに、この JavaScript の処理は、あくまで「選択範囲に存在するルビを削除する」なので、ルビそのものを選択した場合は、ルビのテキストはコピーされます。
次のように、ルビのみを選択したときが、そうですね。
まとめ
以上、「ルビを含む文字列をコピーするときに、ルビのテキストは除外したい」でした。
てっきり JavaScript を使って実装するものと思っていましたが、意外と CSS だけで簡単にできるんですね。
では、また!
Discussion
Safari が technical preview なので Limited availability ですね。惜しいですね。
情報&コメントありがとうございます!