Formatos web personalizados para la API de Async Clipboard

Hasta ahora, la API de Async Clipboard admitía un conjunto limitado de tipos de MIME para copiar y pegar desde el portapapeles del sistema, específicamente: text/plain, text/html y image/png. Por lo general, el navegador limpia esta información para, por ejemplo, quitar elementos script o vínculos javascript: incorporados de una cadena HTML, o bien para evitar ataques de bombas de descompresión PNG.

Sin embargo, en algunos casos, puede ser conveniente admitir contenido no sanitizado en el portapapeles:

  • Situaciones en las que la aplicación se encarga de la limpieza.
  • Situaciones en las que es fundamental que los datos copiados sean idénticos a los pegados.

En esos casos, la API de Async Clipboard ahora admite formatos web personalizados que permiten a los desarrolladores escribir datos arbitrarios en el portapapeles.

Navegadores compatibles

La API de Async Clipboard per se con compatibilidad con imágenes es compatible a partir de Chromium 76. A partir de la versión 104, los formatos personalizados web para la API del portapapeles asíncrono son compatibles con computadoras de escritorio y en Chromium para dispositivos móviles.

Cómo escribir formatos web personalizados en el portapapeles

Escribir formatos personalizados de la Web en el portapapeles es casi idéntico a escribir formatos depurados, excepto por el requisito de anteponer la string "web " (incluido el espacio final) al tipo de MIME del BLOB.

// Fetch remote JPEG and GIF images and obtain their blob representations.
const [jpegBlob, gifBlob] = await Promise.all([
  fetch('image.jpg').then((response) => response.blob()),
  fetch('image.gif').then((response) => response.blob()),
]);

try {
  // Write the image data to the clipboard, prepending the blobs' actual
  // types (`"image/jpeg"` and "image/gif") with the string `"web "`, so
  // they become `"web image/jpeg"` and `"web image/gif"` respectively.
  // The code elegantly makes use of computed property names:
  // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Object_initializer#computed_property_names.
  const clipboardItem = new ClipboardItem({
    [`web ${jpegBlob.type}`]: jpegBlob,
    [`web ${gifBlob.type}`]: gifBlob,
  });
  await navigator.clipboard.write([clipboardItem]);
} catch (err) {
  console.error(err.name, err.message);
}

Cómo leer formatos web personalizados desde el portapapeles

Al igual que con la escritura, leer formatos web personalizados desde el portapapeles es casi idéntico a leer formatos limpios. La única diferencia es que ahora la app debe buscar elementos del portapapeles cuyo tipo comience con "web ".

try {
  // Iterate over all clipboard items.
  const clipboardItems = await navigator.clipboard.read();
  for (const clipboardItem of clipboardItems) {
    for (const type of clipboardItem.types) {
      // Discard any types that are not web custom formats.
      if (!type.startsWith('web ')) {
        continue;
      }
      const blob = await clipboardItem.getType(type);
      // Sanitize the blob if you need to, then process it in your app.
    }
  }
} catch (err) {
  console.error(err.name, err.message);
}

Interoperabilidad con apps específicas de la plataforma

Los formatos personalizados web, como web image/jpeg, no son algo que las aplicaciones típicas específicas de la plataforma comprendan (ya que esperarían image/jpeg). Con el tiempo, se espera que las apps en cuestión agreguen compatibilidad con esos formatos como una opción de habilitación si sus desarrolladores consideran que la compatibilidad con los formatos personalizados web es relevante para sus usuarios. En el portapapeles del sistema operativo, los distintos formatos están presentes en varios formatos listos para el consumo, como se puede ver en la captura de pantalla de macOS a continuación.

Expector de portapapeles en macOS que muestra un mapa de formato personalizado en el que se enumeran dos formatos personalizados para la Web.

Demostración

Puedes probar la demostración y ver el código fuente para ver cómo funciona.

Agradecimientos

Joe Medley y François Beaufort revisaron este documento.