Async Clipboard API 向け SVG サポート

Async Clipboard API の Clipboard インターフェースは、システム クリップボードの内容への読み取り / 書き込みアクセスを提供します。これにより、ウェブ アプリケーションで切り取り、コピー、貼り付けの機能を実装できます。クリップボードからアプリにデータを貼り付けるには、read() メソッドを呼び出します。クリップボードにデータをコピーするには、write() メソッドを呼び出します。Async Clipboard API は、テキスト、Portable Network Graphics(PNG)形式の画像、サニタイズされた HTML とサニタイズされていない HTMLウェブ カスタム形式に加えて、SVG 画像のコピーと貼り付けもサポートするようになりました。これにより、SVG を扱う画像編集ソフトウェアをより自然に操作できるようになりました。SVG 画像をテキストとしてコピーして貼り付けたり、ハッキング的な回避策を使用したりする必要がなくなりました。

特徴検出の SVG サポート

静的 ClipboardItem.supports() メソッドを呼び出して、目的の MIME タイプを渡すことで、SVG 画像(および他の MIME タイプ)のサポートを検出します。

const supportsSVG = () => {
  if (
    !('supports' in window.ClipboardItem) ||
    !window.ClipboardItem.supports('image/svg+xml')
  ) {
    return false;
  }
  return true;
};

SVG 画像をコピーする

ClipboardItem にオブジェクトを入力して、SVG 画像をコピーします。SVG 画像データを含む BLOB が値で、BLOB の型(この場合は 'image/svg+xml')がキーになります。

copyButton.addEventListener('click', async () => {
  if (!supportsSVG()) {
    return;
  }
  try {
    const blob = await fetch(img.src).then((response) => response.blob());
    await navigator.clipboard.write([
      new window.ClipboardItem({
        [blob.type]: blob,
      }),
    ]);
  } catch (err) {
    console.error(err.name, err.message);
    alert(err.message);
  }
});

SVG 画像を貼り付ける

SVG 画像を貼り付けるには、クリップボードから ClipboardItem を読み取り、getType() メソッドで目的のタイプ(この場合は 'image/svg+xml')を取得します。これにより blob が返されます。この blob を blob URL に変換すると、<img>src 属性に割り当てることができます。

pasteButton.addEventListener('click', async () => {
  if (!supportsSVG()) {
    return;
  }
  const [clipboardItem] = await navigator.clipboard.read();
  const svgBlob = await clipboardItem.getType('image/svg+xml');
  if (!svgBlob) {
    alert('No SVG in the clipboard.');
    return;
  }
  const image = document.createElement('img');
  const blobURL = URL.createObjectURL(svgBlob);
  image.addEventListener('load', () => {
    URL.revokeObjectURL(blobURL);
  });
  image.src = blobURL;
});

サニタイズ

SVG は、埋め込みスクリプトなどを許可する強力な形式です。ユーザーが不明なソースからコンテンツを貼り付けると危険な可能性があるため、ブラウザはサニタイズ処理を実行します。データがコピーされると、Async Clipboard API は適切に形成された SVG ドキュメントを生成し、クリップボードに書き込みます。データが貼り付けられると、厳密に処理された SVG フラグメントがフラグメント パーサーによって生成されます。そのため、貼り付けオペレーションの前に onclick イベント ハンドラ属性は残っていますが、貼り付けると削除されます。

macOS のクリップボード ビューア アプリでクリップボードの内容を検査している様子。SVG の onclick イベント リスナー属性がまだ残っていることを示しています。
macOS のクリップボード ビューア アプリでクリップボードの内容を検査しています。SVG の onclick イベント リスナー属性がまだ残っていることを示しています。

デモ

Glitch のデモで、SVG のコピーと貼り付けを確認する。ソースコードを表示して、仕組みを確認してください。コピーと貼り付けの前後に、いずれかの円をクリックしてみてください。貼り付けると、危険な可能性がある onclick イベント ハンドラ属性が削除されます。

謝辞

Chromium の Async Clipboard API の SVG サポートは、Microsoft Edge チームによって実装されました。この記事は、Rachel Andrew と Anupam Snigdha が確認しました。