1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JSでスタイル付きテキストとプレーンテキストを同時にコピーする方法

1
Posted at

はじめに

Web アプリケーションにおいて「コピー」機能を実装する際、貼り付け先が「リッチテキストエディタ(Outlook, Teams, Word 等)」か「プレーンテキスト入力(textarea, ターミナル, LLM のプロンプト欄等)」かによって、期待されるデータ形式は異なります。

本記事では、JavaScript の Clipboard API を活用し、スタイルが付いているリッチテキスト(HTML)とプレーンテキストの双方に最適化されたデータを同時にクリップボードへ書き込む実装のポイントを解説します。

TL;DR

構造を維持してマルチフォーマットでコピーする実用コード

以下の関数は、入力されたテキスト(または HTML)を正規化し、リッチテキスト形式とプレーンテキスト形式の両方でクリップボードに書き込みます。

/**
 * リッチテキストとプレーンテキストを同時にコピーする
 * @param {string} rawContent - コピー対象のテキストまたはHTML
 */
async function copyRichAndPlain(rawContent) {
  // 1. HTMLの正規化(タグを除去して改行構造を抽出)
  const plain = String(rawContent || '').trim()
    .replace(/<br\s*\/?>/gi, '\n')
    .replace(/<div[^>]*>/gi, '\n')
    .replace(/<\/div>/gi, '')
    .replace(/<p[^>]*>/gi, '\n')
    .replace(/<\/p>/gi, '')
    .replace(/&nbsp;/gi, ' ');

  // 2. 空行維持ハック(リッチエディタでの行崩れを防止)
  // 完全に空の行に半角スペースを一つ入れることで、貼り付け先での意図しない行圧縮を防ぐ
  const stablePlain = plain.replace(/^$/gm, ' ');

  // 3. クリップボード用HTMLの構築
  const escaped = plain
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/\n/g, '<br>');
  const html = `<div style="font-family: sans-serif; line-height: 1.6;">${escaped}</div>`;

  // 4. Clipboard API による書き込み
  const blobs = {
    'text/html': new Blob([html], { type: 'text/html' }),
    'text/plain': new Blob([stablePlain], { type: 'text/plain' })
  };
  
  try {
    await navigator.clipboard.write([
      new ClipboardItem(blobs)
    ]);
    console.log("Copied successfully");
  } catch (err) {
    console.error("Copy failed", err);
  }
}

実装の解説

1. マルチフォーマット書き込みの重要性

navigator.clipboard.writeClipboardItem を使用することで、一つのデータに複数の MIME タイプを付与できます。

貼り付け先のアプリケーション(Teams やメールクライアントなど)は、クリップボードの中から自身が扱える最もリッチな形式を優先して選択するため、text/htmltext/plain をセットで提供することが、ユーザー体験の向上に直結します。

[!TIP]
もしリッチテキストエディタに対してあえてプレーンテキストとして貼り付けたい場合は、多くのブラウザやアプリで Ctrl+Shift+V (Mac は Cmd+Shift+V) キーを使用することで、書式なしの貼り付け(プレーンテキスト貼り付け)を強制することが可能です。

2. 独自 DOM を持ち込ませない「正規化」

エディタ上の innerHTML をそのままコピーすると、不要な CSS クラスやエディタ固有のタグが貼り付け先に混入し、レイアウト崩れの原因になります。

そのため、一度プレーンテキストに正規化(brp を改行コードに変換)してから、プレーンな <div><br> のみで構成された「安全な HTML」を再構築するのが無難です。

3. 空行の消失を防ぐ「スペース」のテクニック

一部のリッチテキストエディタでは、プレーンテキストを貼り付ける際に「完全に空の行」を無視して行間を詰めてしまう挙動があります。

これを回避するための実用的なハックとして、空行に半角スペースを一つ挿入する 手法があります。これにより、貼り付け先での段落間のリズムや視覚的な余白がより正確に維持されます。

まとめ

クリップボードの実装において重要なのは「ピクセルパーフェクトな再現」ではなく、「貼り付け先での読みやすさ(Readability)」 です。

  • text/htmltext/plain をセットで提供する
  • 不要なタグを除去して構造を整理する
  • 空行にスペースを仕込むなどの調整で、貼り付け時の安定性を高める

これらを組み合わせることで、多様な貼り付け先に対応したコピー機能を実現できます。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?