Até agora, a API Async Clipboard era compatível com um conjunto limitado de
tipos MIME que podiam ser copiados e colados da área de transferência do sistema, mais especificamente: text/plain
,
text/html
e image/png
. O navegador normalmente limpa isso para, por exemplo, remover elementos
script
incorporados ou links javascript:
de uma string HTML ou para evitar ataques de
bomba de descompactação do PNG.
Em alguns casos, no entanto, pode ser desejável oferecer suporte a conteúdo não corrigido na área de transferência:
- Situações em que o aplicativo lida com a própria limpeza.
- Situações em que é essencial que os dados copiados sejam idênticos aos 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, por si só, com suporte a imagens tem suporte a partir do Chromium 76. Os formatos personalizados da Web para a API Async Clipboard têm suporte no Chromium para computador e dispositivos móveis a partir da versão 104.
Gravar formatos personalizados da Web na área de transferência
Gravar formatos personalizados da Web na área de transferência é quase idêntico a
escrever formatos limpos, exceto pelo requisito
de incluir a string "web "
(incluindo o espaço à direita) no 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);
}
Ler formatos personalizados da Web da área de transferência
Assim como na gravação, a leitura de formatos personalizados da Web da á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 com tipo que comece 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 aplicativos típicos
específicos da plataforma entendem (já que esperariam image/jpeg
). Com o tempo, é esperado que os apps em questão
adicionem suporte a esses formatos, por exemplo, 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 diversos
formatos estão presentes em vários formatos prontos para consumo, como pode ser visto na
captura de tela para macOS abaixo.
Demonstração
Você pode testar a demonstração abaixo e ver o código-fonte para ver como a demonstração funciona.
Agradecimentos
Este artigo foi revisado por Joe Medley e François Beaufort. Imagem principal de Neon Tommy, usada sob uma licença CC BY-SA 2.0 (em inglês).