- From: Domenic Denicola <notifications@github.com>
- Date: Fri, 05 Nov 2021 14:08:38 -0700
- To: w3c/clipboard-apis <clipboard-apis@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <w3c/clipboard-apis/pull/158/review/799309863@github.com>
@domenic commented on this pull request. I got further this time. Let's try to get ClipboardItem solid and then we can tackle Clipboard itself... I suspect the hardest part will be getType(). In general I'd encourage you to adopt the mindset: if I knew nothing about the current implementation of this in Chromium, could I read this spec from top to bottom and implement the result from scratch, in a way that behaves identical to the Chromium implementation? That's the bar we need to meet; see e.g. the specifications section of the [Blink values in Practice](https://www.chromium.org/blink/guidelines/web-platform-changes-guidelines) document. > - typedef (DOMString or Blob) ClipboardItemDataType; - typedef Promise<ClipboardItemDataType> ClipboardItemData; + [SecureContext, Exposed=Window] + interface ClipboardItem { + constructor(record<DOMString, ClipboardItemData> items, + optional ClipboardItemOptions options = {}); These indents still don't quite line up in the output. I suspect because of a mixing of tabs and spaces. > + {[format1]: promise_text_blob}, + {options: "unspecified"}); + </pre> + + <dt><code><var>clipboardItem</var>.getType(<var>type</var>)</code> + <dd><p>Returns a [=Promise=] to the [=Blob=] corresponding to <var>type</var>.</p> + + <dt><code><var>clipboardItem</var>.<var>types</var></code> + <dd><p>Returns the list of <var>types</var> contained in the <var>clipboardItem</var> object. + + </dl> + <p> + A {{ClipboardItem}} object has an associated [=clipboard item=]. + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/presentationStyle}} is its [=clipboard item=]'s [=presentation style=]. It's best to delete this paragraph; it's confusing because it seems like an alternate definition of the getter steps below. > + + <dt><code><var>clipboardItem</var>.getType(<var>type</var>)</code> + <dd><p>Returns a [=Promise=] to the [=Blob=] corresponding to <var>type</var>.</p> + + <dt><code><var>clipboardItem</var>.<var>types</var></code> + <dd><p>Returns the list of <var>types</var> contained in the <var>clipboardItem</var> object. + + </dl> + <p> + A {{ClipboardItem}} object has an associated [=clipboard item=]. + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/presentationStyle}} is its [=clipboard item=]'s [=presentation style=]. + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/types}} is its [=clipboard item=]'s [=types=]. Same here > + </p> + + <p>A [=clipboard item=] has an associated <dfn>types</dfn> which contains the MIME types.</p> + + <dl class=note> + <dt><code><var>clipboardItem</var> = new ClipboardItem([<var>items</var>, <var>options</var>])</code> + <dd> + Creates a new {{ClipboardItem}} object. <var>items</var> are used to fill its MIME types and [=Promise=]s to [=Blob=]s or {{DOMString}}s corresponding to the MIME types, <var>options</var> can be used to fill its {{ClipboardItemOptions}}, + as per the example below. + + <pre class="example javascript" highlight=js> + const format1 = 'text/plain'; + const promise_text_blob = Promise.resolve(new Blob(['hello'], {type: format1})); + const clipboardItemInput = new ClipboardItem( + {[format1]: promise_text_blob}, + {options: "unspecified"}); I believe this should read `presentationStyle: "unspecified"` > + + <dt><code><var>clipboardItem</var>.<var>types</var></code> + <dd><p>Returns the list of <var>types</var> contained in the <var>clipboardItem</var> object. + + </dl> + <p> + A {{ClipboardItem}} object has an associated [=clipboard item=]. + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/presentationStyle}} is its [=clipboard item=]'s [=presentation style=]. + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/types}} is its [=clipboard item=]'s [=types=]. + </p> + <p> + The <a constructor lt="ClipboardItem()">constructor</a> steps for <code>new ClipboardItem(<var>items</var>, <var>options</var>)</code> are to set [=this=]'s items to <var>items</var> and options to <var>options</var>. So, you have defined a ClipboardItem to have exactly one associated value: its "clipboard item". You have not defined that it has associated "items" or "options", so you cannot set those on it. I believe you want to instead do something like the following: 1. Set this's clipboard item to a new clipboard item. 2. Set this's clipboard item's presentation style to options["presentationStyle"]. 3. ??? do something with items to store them somewhere ??? Step 3 is tricky because I don't know how to map a `record<DOMString, ClipboardItemData>` into any other concepts defined in this spec. A guess might be that each clipboard item has **representations**, which is a [map](https://infra.spec.whatwg.org/#maps) from [MIME types](https://mimesniff.spec.whatwg.org/#mime-type) to `ClipboardItemData` values. (If so, that should be stated and defined in the section on "clipboard item".) Then you would do something like the following: 3. For each (key, value) of items: 1. Let mimeType be the result of [parsing a MIME type](https://mimesniff.spec.whatwg.org/#parse-a-mime-type) given key. 2. If mimeType is failure, then throw a TypeError. 3. Set this's clipboard item's representations[mimeType] to value. but there are variants, e.g.: maybe you don't want to parse the MIME types and will accept any random string; maybe you want to unwrap the promises instead of storing them internally so that later, when you get the data, you don't have to wait for the promise; etc. > + <p> + A {{ClipboardItem}} object has an associated [=clipboard item=]. + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/presentationStyle}} is its [=clipboard item=]'s [=presentation style=]. + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/types}} is its [=clipboard item=]'s [=types=]. + </p> + <p> + The <a constructor lt="ClipboardItem()">constructor</a> steps for <code>new ClipboardItem(<var>items</var>, <var>options</var>)</code> are to set [=this=]'s items to <var>items</var> and options to <var>options</var>. + </p> + + <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4> + <p> + Each {{ClipboardItem}} has a {{ClipboardItem/presentationStyle}}, which is a {{PresentationStyle}}. The first sentence here is redundant with the IDL. > + Making the range of cells available as an image will allow the user to paste the cells into Photoshop, while the text/plain format can be used by applications like Windows Notepad. + + Apps that support pasting only a single [=clipboard item=] should use the first [=clipboard item=]. + Apps that support pasting more than one [=clipboard item=] could, for example, provide a user interface that previews the contents of each [=clipboard item=] and allow the user to choose which one to paste. + Further, apps are expected to enumerate the mime-types of the [=clipboard item=] they are pasting and select the one best-suited for the app according to some app-specific algorithm. + Alternatively, an app can present the user with options on how to paste a [=clipboard item=], e.g. “paste as image” or “paste formatted text”, etc. + + A [=clipboard item=] contains multiple representations. Each representation consists of a MIME type and a corresponding {{DOMString}} or [=Blob=]. + + <p>A [=clipboard item=] has an associated <dfn>presentation style</dfn> which is <code>"unspecified"</code> or <code>"inline"</code> or <code>"attachment"</code>. + [=presentation style=] helps distinguish between "inline" data(e.g. selecting text on a web page and copying), vs. file-like data (e.g. copying a plain text file). + This difference is used to provide a hint when writing to the system pasteboard on iOS/iPadOS. This allows apps like Notes to insert a file attachment when copying a plain text file from the Files app, but insert text inline when + copying a selected piece of plain text from another app. In both cases, the MIME type in the pasteboard would be text/plain. This is used for both reading and writing. + </p> + + <p>A [=clipboard item=] has an associated <dfn>types</dfn> which contains the MIME types.</p> What is this? Below I suggested maybe it should be a map of representations? But I don't think that works for how you're using it... more suggestions in the getter section. > + </p> + <p> + A {{ClipboardItem}} object's {{ClipboardItem/types}} is its [=clipboard item=]'s [=types=]. + </p> + <p> + The <a constructor lt="ClipboardItem()">constructor</a> steps for <code>new ClipboardItem(<var>items</var>, <var>options</var>)</code> are to set [=this=]'s items to <var>items</var> and options to <var>options</var>. + </p> + + <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4> + <p> + Each {{ClipboardItem}} has a {{ClipboardItem/presentationStyle}}, which is a {{PresentationStyle}}. + The {{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s [=clipboard item=]'s [=presentation style=]. + </p> + + <h4 attribute for=ClipboardItem lt=types>types</h4> + <p> Each {{ClipboardItem}} has a {{ClipboardItem/types}}, which contains the MIME types. Since a clipboard item's "types" doesn't have a defined type, it's hard to tell if this works. Also, nothing ever sets the types, so this isn't well-defined. My suggestion is to add something to the above constructor steps which accumulates the MIME type strings into a [list](https://infra.spec.whatwg.org/#lists), and then [creates a frozen array](https://webidl.spec.whatwg.org/#dfn-create-frozen-array) from them. And then, store that on a "types" field of the `{{ClipboardItem}}` (not the "clipboard item"), so that the getter steps can be to "return this's types". > + const format1 = 'text/plain'; + const promise_text_blob = Promise.resolve(new Blob(['hello'], {type: format1})); + const clipboardItemInput = new ClipboardItem( + {[format1]: promise_text_blob}, + {options: "unspecified"}); + </pre> + + <dt><code><var>clipboardItem</var>.getType(<var>type</var>)</code> + <dd><p>Returns a [=Promise=] to the [=Blob=] corresponding to <var>type</var>.</p> + + <dt><code><var>clipboardItem</var>.<var>types</var></code> + <dd><p>Returns the list of <var>types</var> contained in the <var>clipboardItem</var> object. + + </dl> + <p> + A {{ClipboardItem}} object has an associated [=clipboard item=]. This is on the right track, but you should have separate `<dfn>`s: one for the "clipboard item" type (what you have), and one for the "`ClipboardItem`'s clipboard item" (which you don't have). Something like ```html A {{ClipboardItem}} object has an associated <dfn for="ClipboardItem">clipboard item</dfn>, which is a [=clipboard item=] ``` Then, you can reference this field elsewhere using the syntax like `[=this=]'s [=ClipboardItem/clipboard item=]`. > + + <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4> + <p> + Each {{ClipboardItem}} has a {{ClipboardItem/presentationStyle}}, which is a {{PresentationStyle}}. + The {{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s [=clipboard item=]'s [=presentation style=]. + </p> + + <h4 attribute for=ClipboardItem lt=types>types</h4> + <p> Each {{ClipboardItem}} has a {{ClipboardItem/types}}, which contains the MIME types. + {{ClipboardItem/types}} getter steps are to return [=this=]'s [=clipboard item=]'s [=types=].</p> + + <h4 method for=ClipboardItem lt=getType(type)>getType(type)</a> must run the below steps:</h4> + + 1. Let |realm| be [=this=]'s [=relevant realm=]. + + 1. If |type| is not listed in the [=mandatory data types=] list, then [=a promise rejected with=] "The type was not found" DOMException in |realm|. This is not one of the defined DOMException names: https://webidl.spec.whatwg.org/#idl-DOMException-error-names > + The {{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s [=clipboard item=]'s [=presentation style=]. + </p> + + <h4 attribute for=ClipboardItem lt=types>types</h4> + <p> Each {{ClipboardItem}} has a {{ClipboardItem/types}}, which contains the MIME types. + {{ClipboardItem/types}} getter steps are to return [=this=]'s [=clipboard item=]'s [=types=].</p> + + <h4 method for=ClipboardItem lt=getType(type)>getType(type)</a> must run the below steps:</h4> + + 1. Let |realm| be [=this=]'s [=relevant realm=]. + + 1. If |type| is not listed in the [=mandatory data types=] list, then [=a promise rejected with=] "The type was not found" DOMException in |realm|. + + 1. Let |p| be [=a new promise=] in |realm|. + + 1. Let |blobData| be a [=Blob=] corresponding to the |type|. I have no idea how to implement this. My best guess is that if you passed in `text/plain` as a type, this would return a promise for the blob created with `new Blob(["text/plain"])`, i.e. containing the string "text/plain" in UTF-8 encoding. > - Promise<Blob> getType(DOMString type); - }; + 1. Return |p|. + + <h4 typedef>ClipboardItemDataType</h4> These two sections are just confusing and redundant with the IDL; it's best to leave them out. > + + <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4> + <p> + Each {{ClipboardItem}} has a {{ClipboardItem/presentationStyle}}, which is a {{PresentationStyle}}. + The {{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s [=clipboard item=]'s [=presentation style=]. + </p> + + <h4 attribute for=ClipboardItem lt=types>types</h4> + <p> Each {{ClipboardItem}} has a {{ClipboardItem/types}}, which contains the MIME types. + {{ClipboardItem/types}} getter steps are to return [=this=]'s [=clipboard item=]'s [=types=].</p> + + <h4 method for=ClipboardItem lt=getType(type)>getType(type)</a> must run the below steps:</h4> + + 1. Let |realm| be [=this=]'s [=relevant realm=]. + + 1. If |type| is not listed in the [=mandatory data types=] list, then [=a promise rejected with=] "The type was not found" DOMException in |realm|. This is short on detail. Do inexact matches count? E.g. the "mandatory data types" list contains `text/plain`, but does `text/plain;charset=utf-8` count? How about `text/PLAIN`? I would suggest running [parse a MIME type](https://mimesniff.spec.whatwg.org/#parse-a-mime-type) on the input and comparing its [essence](https://mimesniff.spec.whatwg.org/#mime-type-essence) to the list of mandatory data types. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/w3c/clipboard-apis/pull/158#pullrequestreview-799309863
Received on Friday, 5 November 2021 21:08:52 UTC