Commit b4857fe7 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Copy raw HTML to clipboard together with rich HTML

parent 1bbcc6d6
...@@ -58,16 +58,23 @@ export async function copyHTML( ...@@ -58,16 +58,23 @@ export async function copyHTML(
/* istanbul ignore next - test seam */ /* istanbul ignore next - test seam */
document_ = document, document_ = document,
) { ) {
// We want to copy the `text` both with plain and html media types, to make
// sure it is possible to paste in both rich text and plain text contexts.
// For the second one, the raw HTML markup will be pasted.
const types = ['text/html', 'text/plain'];
if (navigator_.clipboard.write) { if (navigator_.clipboard.write) {
const type = 'text/html'; const blobs = types.reduce<Record<string, Blob>>((acc, type) => {
const blob = new Blob([text], { type }); acc[type] = new Blob([text], { type });
await navigator_.clipboard.write([new ClipboardItem({ [type]: blob })]); return acc;
}, {});
await navigator_.clipboard.write([new ClipboardItem(blobs)]);
} else { } else {
// Fallback to deprecated document.execCommand('copy') on the assumptions // Fallback to deprecated document.execCommand('copy') on the assumptions
// that all browsers will implement the new clipboard API before removing // that all browsers will implement the new clipboard API before removing
// the deprecated one. // the deprecated one.
const copyHandler = (e: ClipboardEvent) => { const copyHandler = (e: ClipboardEvent) => {
e.clipboardData?.setData('text/html', text); types.forEach(type => e.clipboardData?.setData(type, text));
e.preventDefault(); e.preventDefault();
}; };
......
...@@ -72,7 +72,17 @@ describe('copy-to-clipboard', () => { ...@@ -72,7 +72,17 @@ describe('copy-to-clipboard', () => {
await copyHTML(text, createFakeNavigator({ write })); await copyHTML(text, createFakeNavigator({ write }));
assert.called(write); assert.calledOnce(write);
const [clipboardItem] = write.lastCall.args[0];
const getTextForType = async type => {
const blob = await clipboardItem.getType(type);
return blob.text();
};
assert.deepEqual(clipboardItem.types, ['text/html', 'text/plain']);
assert.equal(await getTextForType('text/html'), text);
assert.equal(await getTextForType('text/plain'), text);
}); });
it('falls back to execCommand if clipboard API is not supported', async () => { it('falls back to execCommand if clipboard API is not supported', async () => {
...@@ -92,6 +102,7 @@ describe('copy-to-clipboard', () => { ...@@ -92,6 +102,7 @@ describe('copy-to-clipboard', () => {
assert.calledWith(document.execCommand, 'copy'); assert.calledWith(document.execCommand, 'copy');
assert.equal(clipboardData.getData('text/html'), text); assert.equal(clipboardData.getData('text/html'), text);
assert.equal(clipboardData.getData('text/plain'), text);
}); });
}); });
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment