| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- 'use strict';
- var getWindow = require('../misc/getWindow.js');
- var Blob = require('./Blob.js');
- var DataTransfer = require('./DataTransfer.js');
- // Clipboard is not available in jsdom
- function _define_property(obj, key, value) {
- if (key in obj) {
- Object.defineProperty(obj, key, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: true
- });
- } else {
- obj[key] = value;
- }
- return obj;
- }
- // MDN lists string|Blob|Promise<Blob|string> as possible types in ClipboardItemData
- // lib.dom.d.ts lists only Promise<Blob|string>
- // https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem#syntax
- function createClipboardItem(window, ...blobs) {
- const dataMap = Object.fromEntries(blobs.map((b)=>[
- typeof b === 'string' ? 'text/plain' : b.type,
- Promise.resolve(b)
- ]));
- // use real ClipboardItem if available
- /* istanbul ignore if */ if (typeof window.ClipboardItem !== 'undefined') {
- return new window.ClipboardItem(dataMap);
- }
- return new class ClipboardItem {
- get types() {
- return Array.from(Object.keys(this.data));
- }
- async getType(type) {
- const value = await this.data[type];
- if (!value) {
- throw new Error(`${type} is not one of the available MIME types on this item.`);
- }
- return value instanceof window.Blob ? value : new window.Blob([
- value
- ], {
- type
- });
- }
- constructor(d){
- _define_property(this, "data", undefined);
- this.data = d;
- }
- }(dataMap);
- }
- const ClipboardStubControl = Symbol('Manage ClipboardSub');
- function createClipboardStub(window, control) {
- return Object.assign(new class Clipboard extends window.EventTarget {
- async read() {
- return Array.from(this.items);
- }
- async readText() {
- let text = '';
- for (const item of this.items){
- const type = item.types.includes('text/plain') ? 'text/plain' : item.types.find((t)=>t.startsWith('text/'));
- if (type) {
- text += await item.getType(type).then((b)=>Blob.readBlobText(b, window.FileReader));
- }
- }
- return text;
- }
- async write(data) {
- this.items = data;
- }
- async writeText(text) {
- this.items = [
- createClipboardItem(window, text)
- ];
- }
- constructor(...args){
- super(...args), _define_property(this, "items", []);
- }
- }(), {
- [ClipboardStubControl]: control
- });
- }
- function isClipboardStub(clipboard) {
- return !!(clipboard === null || clipboard === undefined ? undefined : clipboard[ClipboardStubControl]);
- }
- function attachClipboardStubToView(window) {
- if (isClipboardStub(window.navigator.clipboard)) {
- return window.navigator.clipboard[ClipboardStubControl];
- }
- const realClipboard = Object.getOwnPropertyDescriptor(window.navigator, 'clipboard');
- let stub;
- const control = {
- resetClipboardStub: ()=>{
- stub = createClipboardStub(window, control);
- },
- detachClipboardStub: ()=>{
- /* istanbul ignore if */ if (realClipboard) {
- Object.defineProperty(window.navigator, 'clipboard', realClipboard);
- } else {
- Object.defineProperty(window.navigator, 'clipboard', {
- value: undefined,
- configurable: true
- });
- }
- }
- };
- stub = createClipboardStub(window, control);
- Object.defineProperty(window.navigator, 'clipboard', {
- get: ()=>stub,
- configurable: true
- });
- return stub[ClipboardStubControl];
- }
- function resetClipboardStubOnView(window) {
- if (isClipboardStub(window.navigator.clipboard)) {
- window.navigator.clipboard[ClipboardStubControl].resetClipboardStub();
- }
- }
- function detachClipboardStubFromView(window) {
- if (isClipboardStub(window.navigator.clipboard)) {
- window.navigator.clipboard[ClipboardStubControl].detachClipboardStub();
- }
- }
- async function readDataTransferFromClipboard(document) {
- const window = document.defaultView;
- const clipboard = window === null || window === undefined ? undefined : window.navigator.clipboard;
- const items = clipboard && await clipboard.read();
- if (!items) {
- throw new Error('The Clipboard API is unavailable.');
- }
- const dt = DataTransfer.createDataTransfer(window);
- for (const item of items){
- for (const type of item.types){
- dt.setData(type, await item.getType(type).then((b)=>Blob.readBlobText(b, window.FileReader)));
- }
- }
- return dt;
- }
- async function writeDataTransferToClipboard(document, clipboardData) {
- const window = getWindow.getWindow(document);
- const clipboard = window.navigator.clipboard;
- const items = [];
- for(let i = 0; i < clipboardData.items.length; i++){
- const dtItem = clipboardData.items[i];
- const blob = await DataTransfer.getBlobFromDataTransferItem(window, dtItem);
- items.push(createClipboardItem(window, blob));
- }
- const written = clipboard && await clipboard.write(items).then(()=>true, // Can happen with other implementations that e.g. require permissions
- /* istanbul ignore next */ ()=>false);
- if (!written) {
- throw new Error('The Clipboard API is unavailable.');
- }
- }
- const g = globalThis;
- /* istanbul ignore else */ if (typeof g.afterEach === 'function') {
- g.afterEach(()=>resetClipboardStubOnView(globalThis.window));
- }
- /* istanbul ignore else */ if (typeof g.afterAll === 'function') {
- g.afterAll(()=>detachClipboardStubFromView(globalThis.window));
- }
- exports.attachClipboardStubToView = attachClipboardStubToView;
- exports.createClipboardItem = createClipboardItem;
- exports.detachClipboardStubFromView = detachClipboardStubFromView;
- exports.readDataTransferFromClipboard = readDataTransferFromClipboard;
- exports.resetClipboardStubOnView = resetClipboardStubOnView;
- exports.writeDataTransferToClipboard = writeDataTransferToClipboard;
|