Formatos personalizados da Web para a API Async Clipboard

Até agora, a API Async Clipboard oferecia suporte a um conjunto limitado de tipos MIME para copiar e colar na área de transferência do sistema, especificamente: text/plain, text/html e image/png. O navegador geralmente limpa isso para, por exemplo, remover elementos script ou links javascript: incorporados de uma string HTML ou para impedir ataques de bomba de descompressão do PNG.

No entanto, em alguns casos, pode ser desejável oferecer suporte a conteúdo não higienizado na área de transferência:

  • Situações em que o aplicativo lida com a desinfecção.
  • Situações em que é crucial que os dados copiados sejam idênticos aos dados colados.

Para esses casos, a API Async Clipboard agora oferece suporte a formatos personalizados da Web que permitem que os desenvolvedores gravem dados arbitrários na área de transferência.

Suporte ao navegador

A API Async Clipboard em si com suporte a imagem tem suporte no Chromium 76. Formatos personalizados da Web para a API Async Clipboard têm suporte no Chromium para computadores e dispositivos móveis a partir da versão 104.

Como gravar formatos personalizados da Web na área de transferência

Escrever formatos personalizados da Web na área de transferência é quase idêntico a escrever formatos limpos, exceto pelo requisito de adicionar a string "web " (incluindo o espaço final) ao tipo MIME do 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);
}

Leitura de formatos personalizados da Web da área de transferência

Assim como na gravação, a leitura de formatos personalizados da Web na área de transferência é quase idêntica à leitura de formatos limpos. A única diferença é que o app agora precisa procurar itens da área de transferência cujo tipo começa com "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);
}

Interoperabilidade com apps específicos da plataforma

Formatos personalizados da Web, como web image/jpeg, não são algo que os aplicativos típicos específicos da plataforma entendam, já que eles esperam image/jpeg. Com o tempo, espera-se que os apps em questão adicionem suporte a esses formatos como uma opção de ativação se os desenvolvedores considerarem que o suporte a formatos personalizados da Web é relevante para os usuários. Na área de transferência do sistema operacional, os vários formatos estão presentes em vários formatos prontos para consumo, como pode ser visto na captura de tela do macOS abaixo.

Expector de área de transferência no macOS mostrando um mapa de formato personalizado com dois formatos personalizados da Web.

Demonstração

Teste a demonstração e confira o código-fonte para saber como ela funciona.

Agradecimentos

Este documento foi revisado por Joe Medley e François Beaufort.