From b552fe5c09f95fbbe43f68c584c236828c7df0b4 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Tue, 2 Nov 2021 20:28:46 +0100 Subject: [PATCH 1/7] docs: add spec for clipboard rearchitecture --- .gitignore | 1 + .../clipboard-rearchitecture.md | 105 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 .gitignore create mode 100644 wg-api/spec-documents/clipboard-rearchitecture.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..496ee2ca6a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/wg-api/spec-documents/clipboard-rearchitecture.md b/wg-api/spec-documents/clipboard-rearchitecture.md new file mode 100644 index 0000000000..2c28a61d9d --- /dev/null +++ b/wg-api/spec-documents/clipboard-rearchitecture.md @@ -0,0 +1,105 @@ +# Clipboard Module Rearchitecture + +> Shelley Vohr and John Kleinschmidt + +## Summary + +This RFC outlines a rearchitecturing of the `clipboard` module in Electron to improve alignment with the Clipboard API as specified by the [W3C](https://w3c.github.io/clipboard-apis/#clipboard-interface). + +## Platforms + +All - macOS, Windows, Linux. + +## Impetus + +Over the course of the last few months, Chromium has been making significant changes to their Clipboard API, including the ability to handle [Custom Formats](https://bugs.chromium.org/p/chromium/issues/detail?id=106449). Electron has had to break small aspects of its clipboard API to account for this, and it's unclear what other changes we may be forced to adapt to as they continue this work. Beyond this, users have been asking for an improved Clipboard API as well as surfaced a number of bugs with its current implementation - the most detailed of which is [here](https://github.com/electron/electron/issues/23156). + +Some other related issues include: + +- [#31130](https://github.com/electron/electron/issues/31130) +- [#31115](https://github.com/electron/electron/issues/31115) +- [#30699](https://github.com/electron/electron/issues/30699) +- [#26377](https://github.com/electron/electron/issues/26377) +- [#11838](https://github.com/electron/electron/issues/11838) +- [#9035](https://github.com/electron/electron/issues/9035) +- [#5078](https://github.com/electron/electron/issues/5078) +- [electron/governance#229](https://github.com/electron/governance/pull/229) + +Electron provided a `clipboard` API to its users preceding the specification of the [Clipboard API by the W3C](https://w3c.github.io/clipboard-apis/#clipboard-interface). As a result, we locked into an API surface and created an API contract with our users that became progressively harder to alter without breaking said contract while the web drove a more standardized approach. On top of this confusion, the `clipboard` module provided by Electron is a dual-process module, meaning that it exists in parallel to the more robust API provided by Chromium in the renderer process via `navigator.clipboard` global. + +At this point, it becomes clear that it is in users' and maintainers' best interest to reconsider how we approach the `clipboard` module - breaking changes might be difficult in the short term but provide more consistency and functionality as we look to the future of the module. + +## API Design + +The largest consideration for changes to the `clipboard` module is to what degree we should choose to align with the W3C specification. As we consider this, we should consider what needs or use cases might exist for Electron uses which necessarily wouldn't exist for Chrome users, and how we would plan to account for that in our new design. + +### Potential Options + +1. Strict alignment with W3C specification - no additional APIs exposed. +2. Alignment with W3C where possible, with some additional APIs exposed to handle desktop use cases which aren’t addressed by the specification. +3. Leave API as-is and continue to adapt it as required by upstream changes by Chromium development. + +### Preferred Approach/Solution + +Alignment with W3C where possible, with some additional APIs exposed to handle desktop use cases which aren’t considered by the specification. + +**APIs to Preserve** +* `clipboard.readBookmark()` + * Not supported through existing Web APIs or in the specification. +* `clipboard.writeBookmark(title, url[, type])` + * Not supported through existing Web APIs or in the specification. +* `clipboard.readFindText()` _macOS_ + * Not supported through existing Web APIs or in the specification. +* `clipboard.writeFindText(text)` + * Not supported through existing Web APIs or in the specification. +* `clipboard.clear([type])` + * Not supported through existing Web APIs or in the specification. +* `clipboard.readText([type])` + * Already implemented per specification. +* `clipboard.writeText(text[, type])` + * Already implemented per specification. + +**APIs to Remove** +* `clipboard.availableFormats([type])` + * Superseded by `clipboard.read` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) +* `clipboard.has(format[, type])` + * Superseded by `clipboard.read` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) +* `clipboard.readBuffer(format)` + * Superseded by `clipboard.read`[Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) +* `clipboard.writeBuffer(format, buffer[, type])` + * Superseded by `clipboard.write` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write) +* `clipboard.readHTML()` + * Superseded by `clipboard.read` with `text/html` MIME type +* `clipboard.writeHTML(markup[, type])` + * Superseded by `clipboard.write` with `text/html` MIME type +* `clipboard.readImage([type])` + * Superseded by `clipboard.read()` with `image/*` (where * is bmp, gif, jpeg, png, svg+xml, etc.) +* `clipboard.writeImage(image[, type])` + * Superseded by `clipboard.write` with `image/*` (where * is bmp, gif, jpeg, png, svg+xml, etc.) +* `clipboard.readRTF([type])` + * Superseded by `clipboard.read` with `application/rtf` MIME type +* `clipboard.writeRTF(text[, type])` + * Superseded by `clipboard.write` with `application/rtf` MIME type + +**APIs to Modify** +* `clipboard.read(format)` + * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` + * Ensure that raw formats are preserved + * Custom MIME types e.g. `electron/filepath` +* `clipboard.write(data[, type])​` + * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` + * Ensure that raw formats are preserved + * Custom MIME types e.g. `electron/filepath` + +**APIs to Add** +* `onclipboardchange` event + * Outlined in the spec but has yet been implemented by Chromium (see [this crbug](https://bugs.chromium.org/p/chromium/issues/detail?id=933608)) + * We would implement this as such time Chromium does so. + +### Usage examples + +TODO + +## Rollout Plan + +TODO From 676d0eb3b0b30d03e69f8a6c422d700bdc5a53d3 Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Thu, 4 Nov 2021 12:17:22 -0400 Subject: [PATCH 2/7] Update wg-api/spec-documents/clipboard-rearchitecture.md Co-authored-by: Charles Kerr --- wg-api/spec-documents/clipboard-rearchitecture.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wg-api/spec-documents/clipboard-rearchitecture.md b/wg-api/spec-documents/clipboard-rearchitecture.md index 2c28a61d9d..9a9916822c 100644 --- a/wg-api/spec-documents/clipboard-rearchitecture.md +++ b/wg-api/spec-documents/clipboard-rearchitecture.md @@ -92,7 +92,7 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d * Custom MIME types e.g. `electron/filepath` **APIs to Add** -* `onclipboardchange` event +* `clipboardchange` event * Outlined in the spec but has yet been implemented by Chromium (see [this crbug](https://bugs.chromium.org/p/chromium/issues/detail?id=933608)) * We would implement this as such time Chromium does so. From d30afd392025494a4cfdd71cd9ab1f57a0edd641 Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Mon, 8 Nov 2021 17:35:04 -0500 Subject: [PATCH 3/7] Remove more APIs; add migration code --- .../clipboard-rearchitecture.md | 200 +++++++++++++++++- 1 file changed, 190 insertions(+), 10 deletions(-) diff --git a/wg-api/spec-documents/clipboard-rearchitecture.md b/wg-api/spec-documents/clipboard-rearchitecture.md index 9a9916822c..d9e922d795 100644 --- a/wg-api/spec-documents/clipboard-rearchitecture.md +++ b/wg-api/spec-documents/clipboard-rearchitecture.md @@ -44,14 +44,6 @@ The largest consideration for changes to the `clipboard` module is to what degre Alignment with W3C where possible, with some additional APIs exposed to handle desktop use cases which aren’t considered by the specification. **APIs to Preserve** -* `clipboard.readBookmark()` - * Not supported through existing Web APIs or in the specification. -* `clipboard.writeBookmark(title, url[, type])` - * Not supported through existing Web APIs or in the specification. -* `clipboard.readFindText()` _macOS_ - * Not supported through existing Web APIs or in the specification. -* `clipboard.writeFindText(text)` - * Not supported through existing Web APIs or in the specification. * `clipboard.clear([type])` * Not supported through existing Web APIs or in the specification. * `clipboard.readText([type])` @@ -64,10 +56,18 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d * Superseded by `clipboard.read` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) * `clipboard.has(format[, type])` * Superseded by `clipboard.read` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) +* `clipboard.readBookmark()` + * Superseded by `clipboard.read` with custom `electron/bookmark` MIME type +* `clipboard.writeBookmark(title, url[, type])` + * Superseded by `clipboard.write` with custom `electron/bookmark` MIME type * `clipboard.readBuffer(format)` * Superseded by `clipboard.read`[Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) * `clipboard.writeBuffer(format, buffer[, type])` * Superseded by `clipboard.write` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write) +* `clipboard.readFindText()` _macOS_ + * Superseded by `clipboard.read` with custom `electron/findtext` MIME type +* `clipboard.writeFindText(text)` + * Superseded by `clipboard.write` with custom `electron/findtext` MIME type * `clipboard.readHTML()` * Superseded by `clipboard.read` with `text/html` MIME type * `clipboard.writeHTML(markup[, type])` @@ -82,20 +82,200 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d * Superseded by `clipboard.write` with `application/rtf` MIME type **APIs to Modify** -* `clipboard.read(format)` +* `clipboard.read([clipboardType])` * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` * Ensure that raw formats are preserved * Custom MIME types e.g. `electron/filepath` -* `clipboard.write(data[, type])​` + * clipboardType is only used for Linux to specify if clipboard is regular clipboard or `selection` clipboard. +* `clipboard.write(data[, clipboardType]])​` * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` * Ensure that raw formats are preserved * Custom MIME types e.g. `electron/filepath` + * clipboardType is only used for Linux to specify if clipboard is regular clipboard or `selection` clipboard. **APIs to Add** * `clipboardchange` event * Outlined in the spec but has yet been implemented by Chromium (see [this crbug](https://bugs.chromium.org/p/chromium/issues/detail?id=933608)) * We would implement this as such time Chromium does so. + +### Example migration code +```js +const { serialize, deserialize } = require("v8") + +function availableFormats(clipboardType) { + const clipboardItems = clipboard.read(clipboardType); + const clipboardFormats = []; + for (const clipboardItem of clipboardItems) { + for (const type of clipboardItem.types) { + if (!clipboardFormats.includes(type)) { + clipboardFormats.push(type); + } + } + } + return clipboardFormats; +} + +function has(format, clipboardType) { + const clipboardItems = clipboard.read(clipboardType); + const bookmarkItem = clipboardItems.find(clipboardItem => { + return clipboardItem.types.includes(format); + }); + if (bookmarkItem) { + return true; + } +} + +const BOOKMARK_MIME_TYPE = 'electron/bookmark'; +function readBookmark() { + const clipboardItems = clipboard.read(); + const bookmarkItem = clipboardItems.find(clipboardItem => { + return clipboardItem.types.includes(BOOKMARK_MIME_TYPE); + }); + if (bookmarkItem) { + const buffer = bookmarkItem.getType(BOOKMARK_MIME_TYPE); + return deserialize(buffer); + } +} + +function writeBookmark(title, url) { + const buffer = serialize({ + text: title, + bookmark: url + }); + clipboard.write([ + { + [BOOKMARK_MIME_TYPE]: buffer + } + ]); +} + +function readBuffer(format) { + const clipboardItems = clipboard.read(clipboardType); + const foundItem = clipboardItems.find(clipboardItem => { + return clipboardItem.types.includes(format); + }); + if (foundItem) { + const buffer = foundItem.getType(format); + return buffer; + } +} + +function writeBuffer(format, buffer, clipboardType) { + clipboard.write([ + { + [format]: buffer + } + ], clipboardType); +} + +const FILE_PATH_MIME_TYPE = 'electron/filepath'; +function readFilePaths() { + const filepaths = []; + const clipboardItems = clipboard.read(); + const clipboardFormats = []; + for (const clipboardItem of clipboardItems) { + if (clipboardItem.types.includes(FILE_PATH_MIME_TYPE)) { + const buffer = await findTextItem.getType(FILE_PATH_MIME_TYPE); + filepaths.push(buffer.toString()); + } + } + return filepaths; +} + +function writeFilePaths(paths) { + const filePathClipboardItems = paths.map(path => { + return { + [FILE_PATH_MIME_TYPE]: Buffer.from(text) + } + }) +} + +const FIND_TEXT_MIME_TYPE = 'electron/findtext'; +function readFindText() { + return readClipboard(FIND_TEXT_MIME_TYPE); +} + +function writeFindText(text) { + writeClipboard(FIND_TEXT_MIME_TYPE, text); +} + +const HTML_MIME_TYPE = 'text/html'; +function readHTML(clipboardType) { + return readClipboard(HTML_MIME_TYPE, clipboardType); +} + +function writeHTML(markup, clipboardType) { + writeClipboard(HTML_MIME_TYPE, markup, clipboardType); +} + +const PNG_MIME_TYPE = 'image/png'; +const JPEG_MIME_TYPE = 'image/jpeg'; +function readImage(clipboardType)​ { + const clipboardItems = clipboard.read(clipboardType); + //Look for PNG first + let foundItem = clipboardItems.find(clipboardItem => { + return clipboardItem.types.includes(PNG_MIME_TYPE); + }); + if (!foundItem) { + foundItem = clipboardItems.find(clipboardItem => { + return clipboardItem.types.includes(JPEG_MIME_TYPE); + }); + } + if (foundItem) { + let buffer; + if (foundItem.types.includes(PNG_MIME_TYPE)) { + buffer = foundItem.getType(PNG_MIME_TYPE); + } else { + buffer = foundItem.getType(JPEG_MIME_TYPE); + } + return nativeImage.createFromBuffer(buffer); + } +} + +function writeImage(image, clipboardType)​ { + const buffer = image.getBitmap(); + const dataUrl = image.toDataURL(); + const regex = /^data:(.+\/.+);.*$/; + const matches = dataUrl.match(regex); + clipboard.write([ + { + [matches[1]]: buffer + } + ], clipboardType); +} + +const RTF_MIME_TYPE = 'application/rtf'; +function readRTF(clipboardType) { + return readClipboard(RTF_MIME_TYPE, clipboardType); +} + +function writeRTF(text, clipboardType)​ { + writeClipboard(RTF_MIME_TYPE, text, clipboardType); +} + +function readClipboard(format, clipboardType) { + const clipboardItems = clipboard.read(clipboardType); + const foundItem = clipboardItems.find(clipboardItem => { + return clipboardItem.types.includes(format); + }); + if (foundItem) { + const buffer = await findTextItem.getType(format); + return buffer.toString(); + } +} + +function writeClipboard(format, text, clipboardType) { + clipboard.write([ + { + [format]: Buffer.from(text) + } + ], clipboardType); +} +``` + + + ### Usage examples TODO From 488ba1c9c588ca5444766b3236bf2a2d9f9837cd Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Thu, 10 Nov 2022 11:50:22 -0500 Subject: [PATCH 4/7] chore: add reference to Web Custom formats for Async Clipboard API Also, clean up migration script --- .../clipboard-rearchitecture.md | 167 ++++++++---------- 1 file changed, 76 insertions(+), 91 deletions(-) diff --git a/wg-api/spec-documents/clipboard-rearchitecture.md b/wg-api/spec-documents/clipboard-rearchitecture.md index d9e922d795..2efe2d46b5 100644 --- a/wg-api/spec-documents/clipboard-rearchitecture.md +++ b/wg-api/spec-documents/clipboard-rearchitecture.md @@ -85,12 +85,14 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d * `clipboard.read([clipboardType])` * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` * Ensure that raw formats are preserved - * Custom MIME types e.g. `electron/filepath` + * Custom MIME types e.g. `electron/filepath` will be supported to allow support of non-standard clipboard formats. This follows + the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md) * clipboardType is only used for Linux to specify if clipboard is regular clipboard or `selection` clipboard. * `clipboard.write(data[, clipboardType]])​` * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` * Ensure that raw formats are preserved - * Custom MIME types e.g. `electron/filepath` + * Custom MIME types e.g. `electron/filepath` will be supported to allow support of non-standard clipboard formats. This follows + the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md) * clipboardType is only used for Linux to specify if clipboard is regular clipboard or `selection` clipboard. **APIs to Add** @@ -103,55 +105,27 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d ```js const { serialize, deserialize } = require("v8") -function availableFormats(clipboardType) { - const clipboardItems = clipboard.read(clipboardType); - const clipboardFormats = []; - for (const clipboardItem of clipboardItems) { - for (const type of clipboardItem.types) { - if (!clipboardFormats.includes(type)) { - clipboardFormats.push(type); - } - } - } - return clipboardFormats; -} - -function has(format, clipboardType) { - const clipboardItems = clipboard.read(clipboardType); - const bookmarkItem = clipboardItems.find(clipboardItem => { +async function readClipboard(format, clipboardType) { + const clipboardItems = await clipboard.read(clipboardType); + const foundItem = clipboardItems.find(clipboardItem => { return clipboardItem.types.includes(format); }); - if (bookmarkItem) { - return true; - } -} - -const BOOKMARK_MIME_TYPE = 'electron/bookmark'; -function readBookmark() { - const clipboardItems = clipboard.read(); - const bookmarkItem = clipboardItems.find(clipboardItem => { - return clipboardItem.types.includes(BOOKMARK_MIME_TYPE); - }); - if (bookmarkItem) { - const buffer = bookmarkItem.getType(BOOKMARK_MIME_TYPE); - return deserialize(buffer); + if (foundItem) { + const buffer = await findTextItem.getType(format); + return buffer.toString(); } } -function writeBookmark(title, url) { - const buffer = serialize({ - text: title, - bookmark: url - }); - clipboard.write([ +async function writeClipboard(format, text, clipboardType) { + return clipboard.write([ { - [BOOKMARK_MIME_TYPE]: buffer + [format]: Buffer.from(text) } - ]); + ], clipboardType); } -function readBuffer(format) { - const clipboardItems = clipboard.read(clipboardType); +async function readBuffer(format, clipboardType) { + const clipboardItems = await clipboard.read(clipboardType); const foundItem = clipboardItems.find(clipboardItem => { return clipboardItem.types.includes(format); }); @@ -161,58 +135,88 @@ function readBuffer(format) { } } -function writeBuffer(format, buffer, clipboardType) { - clipboard.write([ +async function writeBuffer(format, buffer, clipboardType) { + return clipboard.write([ { [format]: buffer } ], clipboardType); } -const FILE_PATH_MIME_TYPE = 'electron/filepath'; -function readFilePaths() { - const filepaths = []; - const clipboardItems = clipboard.read(); +async function availableFormats(clipboardType) { + const clipboardItems = await clipboard.read(clipboardType); const clipboardFormats = []; for (const clipboardItem of clipboardItems) { - if (clipboardItem.types.includes(FILE_PATH_MIME_TYPE)) { - const buffer = await findTextItem.getType(FILE_PATH_MIME_TYPE); - filepaths.push(buffer.toString()); + for (const type of clipboardItem.types) { + if (!clipboardFormats.includes(type)) { + clipboardFormats.push(type); + } } } - return filepaths; + return clipboardFormats; } -function writeFilePaths(paths) { - const filePathClipboardItems = paths.map(path => { - return { - [FILE_PATH_MIME_TYPE]: Buffer.from(text) - } - }) +async function has(format, clipboardType) { + const clipboardItems = await clipboard.read(clipboardType); + const matchingClipboardItem = clipboardItems.find(clipboardItem => { + return clipboardItem.types.includes(format); + }); + if (matchingClipboardItem) { + return true; + } +} + +const BOOKMARK_MIME_TYPE = 'web electron/bookmark'; +async function readBookmark() { + const bookmarkItem = await readBuffer(BOOKMARK_MIME_TYPE); + if (bookmarkItem) { + return deserialize(bookmarkItem); + } +} + +async function writeBookmark(title, url) { + const buffer = serialize({ + text: title, + bookmark: url + }); + return writeBuffer(BOOKMARK_MIME_TYPE, buffer); +} + +const FILE_PATH_MIME_TYPE = 'web electron/filepath'; +async function readFilePaths() { + const filePathsItem = await readBuffer(FILE_PATH_MIME_TYPE); + if (filePathsItem) { + return deserialize(filePathsItem); + } } -const FIND_TEXT_MIME_TYPE = 'electron/findtext'; -function readFindText() { +async function writeFilePaths(paths) { + const filePathsBuffer = serialize(paths); + return writeBuffer(BOOKMARK_MIME_TYPE, filePathsBuffer); +} + +const FIND_TEXT_MIME_TYPE = 'web electron/findtext'; +async function readFindText() { return readClipboard(FIND_TEXT_MIME_TYPE); } -function writeFindText(text) { - writeClipboard(FIND_TEXT_MIME_TYPE, text); +async function writeFindText(text) { + return writeClipboard(FIND_TEXT_MIME_TYPE, text); } const HTML_MIME_TYPE = 'text/html'; -function readHTML(clipboardType) { +async function readHTML(clipboardType) { return readClipboard(HTML_MIME_TYPE, clipboardType); } -function writeHTML(markup, clipboardType) { - writeClipboard(HTML_MIME_TYPE, markup, clipboardType); +async function writeHTML(markup, clipboardType) { + return writeClipboard(HTML_MIME_TYPE, markup, clipboardType); } const PNG_MIME_TYPE = 'image/png'; const JPEG_MIME_TYPE = 'image/jpeg'; -function readImage(clipboardType)​ { - const clipboardItems = clipboard.read(clipboardType); +async function readImage(clipboardType)​ { + const clipboardItems = await clipboard.read(clipboardType); //Look for PNG first let foundItem = clipboardItems.find(clipboardItem => { return clipboardItem.types.includes(PNG_MIME_TYPE); @@ -233,12 +237,12 @@ function readImage(clipboardType)​ { } } -function writeImage(image, clipboardType)​ { +async function writeImage(image, clipboardType)​ { const buffer = image.getBitmap(); const dataUrl = image.toDataURL(); const regex = /^data:(.+\/.+);.*$/; const matches = dataUrl.match(regex); - clipboard.write([ + return clipboard.write([ { [matches[1]]: buffer } @@ -246,31 +250,12 @@ function writeImage(image, clipboardType)​ { } const RTF_MIME_TYPE = 'application/rtf'; -function readRTF(clipboardType) { +async function readRTF(clipboardType) { return readClipboard(RTF_MIME_TYPE, clipboardType); } -function writeRTF(text, clipboardType)​ { - writeClipboard(RTF_MIME_TYPE, text, clipboardType); -} - -function readClipboard(format, clipboardType) { - const clipboardItems = clipboard.read(clipboardType); - const foundItem = clipboardItems.find(clipboardItem => { - return clipboardItem.types.includes(format); - }); - if (foundItem) { - const buffer = await findTextItem.getType(format); - return buffer.toString(); - } -} - -function writeClipboard(format, text, clipboardType) { - clipboard.write([ - { - [format]: Buffer.from(text) - } - ], clipboardType); +async function writeRTF(text, clipboardType)​ { + return writeClipboard(RTF_MIME_TYPE, text, clipboardType); } ``` From 6a7ed0a8023807c9695130b9725fc83a3a3177d9 Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Thu, 10 Nov 2022 12:11:05 -0500 Subject: [PATCH 5/7] Document clipboard.read/write parameters and return values. --- wg-api/spec-documents/clipboard-rearchitecture.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/wg-api/spec-documents/clipboard-rearchitecture.md b/wg-api/spec-documents/clipboard-rearchitecture.md index 2efe2d46b5..1964b0e97a 100644 --- a/wg-api/spec-documents/clipboard-rearchitecture.md +++ b/wg-api/spec-documents/clipboard-rearchitecture.md @@ -83,13 +83,18 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d **APIs to Modify** * `clipboard.read([clipboardType])` - * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` + * `clipboardType` string (optional) - Can be `selection` or `clipboard`; default is `clipboard`. `selection` is only available on Linux. + * This API will be modified to bring into spec compliance with the [Web API clipboard.read](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) + * Returns a Promise that resolves with an array of [ClipboardItem](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem) objects containing the + clipboard's contents. The promise is rejected if permission to access the clipboard is not granted. * Ensure that raw formats are preserved * Custom MIME types e.g. `electron/filepath` will be supported to allow support of non-standard clipboard formats. This follows the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md) - * clipboardType is only used for Linux to specify if clipboard is regular clipboard or `selection` clipboard. * `clipboard.write(data[, clipboardType]])​` - * Modify to bring into spec compliance with [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) `clipboard.read` + * `data` an array of [ClipboardItem](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem) objects containing data to be written to the clipboard. + * `clipboardType` string (optional) - Can be `selection` or `clipboard`; default is `clipboard`. `selection` is only available on Linux. + * This API will be modified to bring into spec compliance with the [Web API`clipboard.write](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write). + * Returns a Promise which is resolved when the data has been written to the clipboard. The promise is rejected if the clipboard is unable to complete the clipboard access. * Ensure that raw formats are preserved * Custom MIME types e.g. `electron/filepath` will be supported to allow support of non-standard clipboard formats. This follows the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md) From ff0d8f5394208f9719cc05e042ac09fe3bc645f4 Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Tue, 21 Mar 2023 12:29:05 -0400 Subject: [PATCH 6/7] add more documentation about custom types. --- .../clipboard-rearchitecture.md | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/wg-api/spec-documents/clipboard-rearchitecture.md b/wg-api/spec-documents/clipboard-rearchitecture.md index 1964b0e97a..917033615a 100644 --- a/wg-api/spec-documents/clipboard-rearchitecture.md +++ b/wg-api/spec-documents/clipboard-rearchitecture.md @@ -50,12 +50,12 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d * Already implemented per specification. * `clipboard.writeText(text[, type])` * Already implemented per specification. +* `clipboard.has(format[, type])` + * Convenience method to quickly check if a particular format is available. **APIs to Remove** * `clipboard.availableFormats([type])` * Superseded by `clipboard.read` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) -* `clipboard.has(format[, type])` - * Superseded by `clipboard.read` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/read) * `clipboard.readBookmark()` * Superseded by `clipboard.read` with custom `electron/bookmark` MIME type * `clipboard.writeBookmark(title, url[, type])` @@ -88,16 +88,18 @@ Alignment with W3C where possible, with some additional APIs exposed to handle d * Returns a Promise that resolves with an array of [ClipboardItem](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem) objects containing the clipboard's contents. The promise is rejected if permission to access the clipboard is not granted. * Ensure that raw formats are preserved - * Custom MIME types e.g. `electron/filepath` will be supported to allow support of non-standard clipboard formats. This follows - the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md) + * Custom MIME types e.g. `electron application/filepath` will be used to allow support of non-standard clipboard formats. This follows + the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md#custom-formats). + The exception here is that instead of using the `web` prefix, we will use the `electron` prefix to prevent possible collisions with custom web formats. * `clipboard.write(data[, clipboardType]])​` * `data` an array of [ClipboardItem](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem) objects containing data to be written to the clipboard. * `clipboardType` string (optional) - Can be `selection` or `clipboard`; default is `clipboard`. `selection` is only available on Linux. * This API will be modified to bring into spec compliance with the [Web API`clipboard.write](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write). * Returns a Promise which is resolved when the data has been written to the clipboard. The promise is rejected if the clipboard is unable to complete the clipboard access. * Ensure that raw formats are preserved - * Custom MIME types e.g. `electron/filepath` will be supported to allow support of non-standard clipboard formats. This follows - the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md) + * Custom MIME types e.g. `electron application/filepath` will be used to allow support of non-standard clipboard formats. This follows + the W3C proposal for supporting [Web Custom formats for Async Clipboard API](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md#custom-formats). + The exception here is that instead of using the `web` prefix, we will use the `electron` prefix to prevent possible collisions with custom web formats. * clipboardType is only used for Linux to specify if clipboard is regular clipboard or `selection` clipboard. **APIs to Add** @@ -171,7 +173,7 @@ async function has(format, clipboardType) { } } -const BOOKMARK_MIME_TYPE = 'web electron/bookmark'; +const BOOKMARK_MIME_TYPE = 'electron application/bookmark'; async function readBookmark() { const bookmarkItem = await readBuffer(BOOKMARK_MIME_TYPE); if (bookmarkItem) { @@ -187,7 +189,7 @@ async function writeBookmark(title, url) { return writeBuffer(BOOKMARK_MIME_TYPE, buffer); } -const FILE_PATH_MIME_TYPE = 'web electron/filepath'; +const FILE_PATH_MIME_TYPE = 'electron application/filepath'; async function readFilePaths() { const filePathsItem = await readBuffer(FILE_PATH_MIME_TYPE); if (filePathsItem) { @@ -200,7 +202,7 @@ async function writeFilePaths(paths) { return writeBuffer(BOOKMARK_MIME_TYPE, filePathsBuffer); } -const FIND_TEXT_MIME_TYPE = 'web electron/findtext'; +const FIND_TEXT_MIME_TYPE = 'electron application/findtext'; async function readFindText() { return readClipboard(FIND_TEXT_MIME_TYPE); } From f55616d317ae3bde135c295e00cda4b2ba871d71 Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Tue, 21 Mar 2023 12:30:01 -0400 Subject: [PATCH 7/7] this should not have been committed --- .gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 496ee2ca6a..0000000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store \ No newline at end of file