2

Using the new Clipboard API I can easily read out the current content as text (sample code) and the API looks like it could support multiple 'types', but at least in Chrome and Edge it always only returns text/plain. Is this a bug/limitation in the new API, or should I do my call differently?

Full example how to trigger this behavior

Note: make sure to copy rich text content beforehand. (This is not a snippet as the new clipboard API doesn't seem to work in iframes)

<!DOCTYPE html>
<html>
  <head> </head>
  <body>
    <div contenteditable>
      paste into this area for old api
    </div>
    <button id="async">async api</button>
    <script>
      document.querySelector("#async").addEventListener("click", (e) => {
        navigator.permissions
          .query({ name: "clipboard-read" })
          .then((result) => {
            // If permission to read the clipboard is granted or if the user will
            // be prompted to allow it, we proceed.

            if (result.state == "granted" || result.state == "prompt") {
              navigator.clipboard.read().then((data) => {
                console.log(data.map((d) => d.types)); // always returns only [['text/plain']]
              });
            }
          });
      });
      document.querySelector("div").addEventListener("paste", (e) => {
        console.log(e.clipboardData.types); // returns for the same content ["text/plain", "text/html"]
      });
    </script>
  </body>
</html>
David Mulder
  • 26,123
  • 9
  • 51
  • 114

2 Answers2

5

Chrome is still working on it: https://bugs.chromium.org/p/chromium/issues/detail?id=897289

For the time being, only text/plain and image/png can be retrieved and written through this API.

Unfortunately, they also blocked the access of this feature to cross-origin frames, meaning almost all online js fiddlers, Stack-Snippets included.

So here is a link to a code-sandbox external window, not sure how long these things last, and below is the main code of that sandbox:

  button.onclick = async (evt) => {
    const clipboard = navigator.clipboard;
    const item = (await clipboard.read())[0];
    const image =
      item.types.includes("image/png") && (await item.getType("image/png"));
    const text =
      item.types.includes("text/plain") && item.getType("text/plain");

    if (image) {
      document.body.appendChild(new Image()).src = URL.createObjectURL(
        image
      );
    }
    console.log(text);
  };

Note that the synchronous API accessible through the ClipboardEvent's clipboardData, can access these types.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Current Chromium ticket state: "Given the security implications with this proposal, we're abandoning it." – Nakilon Jun 10 '22 at 17:12
0

Since readText() (and read(), for that matter) returns an empty string if the clipboard isn't text, this code is safe.

Source: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API

Ibraheem
  • 2,168
  • 20
  • 27