Compatibilidad con SVG para la API de Async Clipboard

La interfaz Clipboard de la API de Async Clipboard proporciona acceso de lectura y escritura al contenido del portapapeles del sistema. Esto permite que una aplicación web implemente funciones de cortar, copiar y pegar. Para pegar datos del portapapeles en una aplicación, llama al método read() y, para copiar datos en el portapapeles, llama al método write(). Además del texto, las imágenes en formato de gráficos de red portátiles (PNG), el HTML sin limpiar y limpiado, y los formatos personalizados web, la API de Async Clipboard ahora también admite copiar y pegar imágenes SVG, lo que significa que, por fin, puedes interactuar con software de edición de imágenes que se ocupa de los SVG de forma más natural copiando y pegando imágenes SVG como imágenes en lugar de como texto o usando solución de problemas poco ortodoxas.

Compatibilidad con SVG de detección de componentes

Para detectar la compatibilidad con imágenes SVG (y cualquier otro tipo de MIME), llama al método ClipboardItem.supports() estático y pásale el tipo de MIME deseado.

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

Cómo copiar una imagen SVG

Para copiar una imagen SVG, propaga ClipboardItem con un objeto. El blob con los datos de la imagen SVG es el valor y el tipo del blob (es decir, 'image/svg+xml' en este caso) como clave.

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);
  }
});

Cómo pegar una imagen SVG

Para pegar una imagen SVG, vuelve a leer ClipboardItem desde el portapapeles y obtén el tipo deseado (es decir, 'image/svg+xml' en este caso) con el método getType(). Esto muestra un BLOB que, una vez convertido en una URL de BLOB, puedes asignar al atributo src de un <img>.

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;
});

Limpieza

SVG es un formato potente que, por ejemplo, permite secuencias de comandos incorporadas. Esto puede ser peligroso cuando el usuario pega contenido de fuentes desconocidas, por lo que el navegador ejecuta un paso de limpieza. Cuando se copian datos, la API de Async Clipboard produce un documento SVG bien formado y, luego, lo escribe en el portapapeles. Cuando se pegan datos, el analizador de fragmentos produce un fragmento SVG procesado de forma estricta. Por lo tanto, antes de la operación de pegado, los atributos del controlador de eventos onclick aún están allí, pero, cuando se pegan, se quitan.

App de Clipboard Viewer en macOS que inspecciona el contenido del portapapeles. Muestra que los atributos del objeto de escucha de eventos onclick en el SVG aún están allí.
App de Clipboard Viewer en macOS que inspecciona el contenido del portapapeles. Muestra que los atributos del objeto de escucha de eventos onclick en el SVG aún están allí.

Demostración

Explora cómo copiar y pegar archivos SVG en la demo de Glitch. Consulta el código fuente para ver cómo funciona. Asegúrate de hacer clic en cualquiera de los círculos antes y después de copiar y pegar. Después de pegar, se quitan los atributos potencialmente peligrosos del controlador de eventos onclick.

Agradecimientos

El equipo de Microsoft Edge implementó la compatibilidad con SVG para la API de Async Clipboard en Chromium. Rachel Andrew y Anupam Snigdha revisaron esta entrada.