Пользовательские веб-форматы для API Async Clipboard

До сих пор API Async Clipboard поддерживал ограниченный набор типов MIME для копирования и вставки из системного буфера обмена, а именно: text/plain , text/html и image/png . Браузер обычно очищает это, например, для удаления встроенных элементов script или ссылок javascript: из строки HTML или для предотвращения атак декомпрессионной бомбы PNG.

Однако в некоторых случаях может быть желательно поддерживать неочищенный контент в буфере обмена:

  • Ситуации, когда приложение занимается самой санацией.
  • Ситуации, когда крайне важно, чтобы скопированные данные были идентичны вставленным.

Для таких случаев API Async Clipboard теперь поддерживает пользовательские веб-форматы, которые позволяют разработчикам записывать произвольные данные в буфер обмена.

Поддержка браузера

API Async Clipboard как таковой с поддержкой изображений поддерживается начиная с Chromium 76. Пользовательские веб-форматы для API Async Clipboard поддерживаются на настольных компьютерах и в мобильных устройствах Chromium, начиная с версии 104.

Запись пользовательских веб-форматов в буфер обмена

Запись пользовательских веб-форматов в буфер обмена практически идентична написанию очищенных форматов , за исключением необходимости добавлять строку "web " (включая завершающий пробел) к MIME-типу большого двоичного объекта.

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

Чтение пользовательских веб-форматов из буфера обмена

Как и при написании, чтение пользовательских веб-форматов из буфера обмена практически идентично чтению очищенных форматов . Единственное отличие состоит в том, что теперь приложению необходимо искать элементы буфера обмена, тип которых начинается с "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);
}

Взаимодействие с приложениями для конкретной платформы.

Пользовательские веб-форматы, такие как web image/jpeg не понимают типичные приложения, специфичные для конкретной платформы (поскольку они ожидают image/jpeg ). Ожидается, что со временем соответствующие приложения добавят поддержку таких форматов по желанию, если их разработчики сочтут поддержку пользовательских веб-форматов актуальной для их пользователей. В буфере обмена операционной системы различные форматы представлены в нескольких форматах, готовых к использованию, как это видно на снимке экрана для macOS ниже.

Ожидатель буфера обмена в macOS, показывающий карту пользовательских форматов, в которой перечислены два пользовательских веб-формата.

Демо

Вы можете попробовать демо-версию ниже и просмотреть исходный код , чтобы увидеть, как работает демо.

Благодарности

Эту статью рецензировали Джо Медли и Франсуа Бофорт . Изображение героя от Neon Tommy , используется по лицензии CC BY-SA 2.0 .