1. 引言
本节是非规范性的。
本规范定义了系统剪贴板如何向 Web 应用程序公开。
本规范描述了两种通用 API:
-
剪贴板事件 API - 此 API 提供了一种挂钩到常见剪贴板操作(剪切、复制和粘贴)的方法,以便 Web 应用程序可以根据需要调整剪贴板数据。
-
异步剪贴板 API - 此 API 提供对读取和写入剪贴板数据的直接访问。由于这被认为是一个强大的功能, 因此对此 API 的访问受权限控制。
2. 用例
本节是非规范性的。
2.1. 更改默认剪贴板操作
在许多情况下,需要更改默认的剪贴板操作(剪切/复制/粘贴)。以下是一些示例:
- 元数据 从文档存储库复制文本时,让复制的文本包含有关所复制内容来源的元数据会很有用。
- 富内容编辑 复制包含超链接或其他结构的文本时,能够重新格式化内容以保留重要信息通常很有用。
- 具有内置语义的图形 为了使 Web 应用程序能够处理富文本或图形内容(例如 [SVG11]),提供一种允许复制不仅仅是渲染内容的机制会很有用。
- 数学信息 对于数学等内容,简单地复制渲染的文本并将其粘贴到另一个应用程序中通常会导致大部分语义丢失。MathML 通常需要转换为纯文本才能复制,例如,为了确保在公式纯文本输入中用脱字符“^”显示“的幂”。XML 源代码也可以放在剪贴板中,并在粘贴时进行适当的转换。
2.2. 远程剪贴板同步
对于与远程设备通信的 Web 应用程序(例如,远程访问或远程 shell 应用程序),通常需要在两个设备之间保持剪贴板数据同步。
此用例的一个重要方面是,它需要在没有用户手势或交互的情况下访问剪贴板。
write()
到本地剪贴板。 2.3. 触发剪贴板操作
为用户代理提供备用界面的应用程序有时需要能够触发用户代理中的剪贴板操作。
例如,考虑一个屏幕阅读器应用程序,它为标准 Web 浏览器提供更易于访问的界面。虽然阅读器可以显示内容并允许用户与之交互,但像剪贴板复制这样的操作需要在底层浏览器中进行,以确保正确设置剪贴板内容(以及浏览器在复制过程中添加的任何元数据)。
3. 术语
术语 可编辑上下文 指任何作为 编辑宿主、textarea 元素或其 type 属性设置为 "text"、"search"、"tel"、"url"、"email"、"password" 或 "number" 之一的 input 元素的元素。
4. 模型
平台提供一个 系统剪贴板。
系统剪贴板有一个系统剪贴板项目列表,这些项目统称为 系统剪贴板数据。
每个系统剪贴板项目都有一个系统剪贴板表示列表。
每个系统剪贴板表示都有一个名称(一个字符串)和数据(一个字节序列)。
5. 剪贴板事件
5.1. 剪贴板事件接口
ClipboardEvent 接口扩展了 Event
接口。
dictionary :
ClipboardEventInit EventInit {DataTransfer ?=
clipboardData null ; };
- clipboardData
-
一个
DataTransfer
对象,用于保存与事件相关的数据和元数据。
[Exposed =Window ]interface :
ClipboardEvent Event {(
constructor DOMString ,
type optional ClipboardEventInit = {});
eventInitDict readonly attribute DataTransfer ?; };
clipboardData
- clipboardData
-
clipboardData 属性是
DataTransfer
接口的一个实例,它允许脚本在用户发起的复制、剪切和粘贴操作期间读取和操作系统剪贴板上的值。关联的拖放数据存储是系统剪贴板的实时但经过筛选的视图,公开了实现知道脚本可以安全访问的强制数据类型。对于合成事件,拖放数据存储包含创建事件的脚本添加的数据。
该接口可用于构造事件。 下面给出一个示例:
var pasteEvent = new ClipboardEvent('paste'); pasteEvent.clipboardData.items.add('My string', 'text/plain'); document.dispatchEvent(pasteEvent);
注意: 合成的剪贴板事件实际上不会修改剪贴板或文档。换句话说,虽然上面的脚本会触发粘贴事件,但数据不会被粘贴到文档中。
5.2. 剪贴板事件
5.2.1.
clipboardchange
事件
当系统剪贴板的内容发生更改时,会触发 clipboardchange
事件。这些更改可能由以下任何原因(非详尽列表)引起:
-
用户发起的剪切或复制操作
-
使用 § 7 异步剪贴板 API 写入剪贴板的脚本
-
在用户代理外部更新剪贴板的操作
如果剪贴板内容在用户代理外部发生更改,则当用户代理重新获得焦点时,必须触发 clipboardchange
事件。
由于合成的 cut
和 copy
事件不会更新系统剪贴板,
因此它们不会触发 "clipboardchange" 事件。
5.2.2. copy
事件
当用户发起复制操作时,用户代理会触发一个名为 copy
的剪贴板事件。
如果事件未被取消,则当前选定的数据将被复制到系统剪贴板。 当前文档选择不受影响。
copy
事件会冒泡,可以取消,并且是组合事件。
有关此事件处理模型的详细说明,请参阅 § 8.1 复制操作。
可以手动构造和分派合成的 copy
事件,但它不会影响系统剪贴板的内容。
5.2.3. cut
事件
当用户发起剪切操作时,用户代理会触发一个名为 cut
的剪贴板事件。
在可编辑上下文中,如果事件未被取消,则该操作会将当前选定的数据放置在系统剪贴板上,并从文档中删除所选内容。
在删除所选数据之前会触发 cut
事件。剪切操作完成后,选择将折叠。
在非可编辑上下文中,clipboardData
将是一个空列表。请注意,在这种情况下仍会触发 cut
事件。
cut
事件会冒泡,可以取消,并且是组合事件。
有关此事件处理模型的详细说明,请参阅 § 8.2 剪切操作。
可以手动构造和分派合成的 cut
事件,但它不会影响文档内容或系统剪贴板的内容。
5.2.4.
paste
事件
当用户发起粘贴操作时,用户代理会触发一个名为 paste
的剪贴板事件。
在将任何剪贴板数据插入文档之前会触发该事件。
如果光标位于可编辑上下文中,则粘贴操作将以给定上下文支持的最合适格式(如果有)插入剪贴板数据。
粘贴操作在非可编辑上下文中无效,但无论如何都会触发
paste
事件。
paste
事件会冒泡,可以取消,并且是组合事件。
有关此事件处理模型的详细说明,请参阅 § 8.3 粘贴操作。
可以手动构造和分派合成的 paste
事件,但它不会影响文档内容。
5.3. 与其他脚本和事件的集成
5.3.1. 允许修改剪贴板的事件处理程序
如果满足以下任一条件,事件处理程序可以写入剪贴板:
-
触发事件的操作是从用户代理自身的用户界面调用的,例如从“复制”菜单项或快捷键调用的。
-
触发事件的操作是从允许显示弹出窗口的脚本线程调用的。
如果实现作者认为其他受信任的事件类型可能表达用户意图,则实现可以允许这些事件类型修改剪贴板。实现还可以支持信任特定站点或应用程序修改剪贴板的配置,而不管脚本线程的来源如何。
合成的 cut
和 copy
事件不得修改系统剪贴板上的数据。
5.3.2. 允许从剪贴板读取的事件处理程序
如果满足以下任一条件,事件处理程序可以从系统剪贴板读取数据:
-
触发事件的操作是从用户代理自身的用户界面调用的,例如“粘贴”菜单项或快捷键。
-
触发操作的脚本正在通过依赖于实现的机制被授予从剪贴板读取数据的权限的站点上运行。
-
触发事件的操作是在具有读取剪贴板权限的应用程序中触发的。
合成的 paste
事件不得授予脚本访问真实系统剪贴板上数据的权限。
5.3.3. 与富文本编辑 API 的集成
如果实现支持通过脚本执行剪贴板命令的方法,例如通过使用命令 "cut"、"copy" 和 "paste" 调用 document.execCommand()
方法,则实现必须触发相应的操作,这将再次分派关联的剪贴板事件。
以下是通过脚本 API 触发复制、剪切或粘贴操作时要遵循的步骤:
-
同步执行相应的操作。
-
使用操作的返回值作为 API 调用的返回值。
注意: 通过脚本 API 触发的复制和剪切命令仅在事件是由受信任且由用户触发的事件分派,或者实现配置为允许此操作时,才会影响真实剪贴板的内容。通过脚本 API 触发的粘贴命令仅在实现配置为允许此操作时才会触发粘贴事件并授予对剪贴板内容的访问权限。如何配置实现以允许对剪贴板的读取或写入访问超出了本规范的范围。
5.3.4. 与其他事件的交互
如果剪贴板操作是由键盘输入触发的,则实现必须触发启动剪贴板操作的相应事件。该事件是异步的,但必须在相关键的 keyup 事件之前分派。
剪切和粘贴操作可能导致实现分派其他支持的事件,例如 textInput、input、change、验证事件、DOMCharacterDataModified 和 DOMNodeRemoved / DOMNodeInserted。任何此类事件都将排队,以便在剪切/粘贴事件处理完成后触发。
实现不得响应复制操作而分派其他与输入相关的事件,例如 textInput、input、change 和验证事件。
5.3.5. 修改选择或焦点的事件侦听器
如果事件侦听器修改选择或可聚焦区域,则剪贴板操作必须在修改后的选择上完成。
6. 剪贴板事件 API
剪贴板事件 API 允许您覆盖用户代理的默认剪切、复制和粘贴行为。
对剪贴板的访问是使用标准的 DataTransfer
方法来改变 ClipboardEvent
的
clipboardData
属性上的 items
来执行的。
这样做的结果之一是,这些剪贴板 API 只能在 ClipboardEvent
处理程序的上下文中访问剪贴板数据。
注意: 如果您需要在剪贴板事件处理程序之外访问剪贴板,请参阅 § 7 异步剪贴板 API。
注意: 剪贴板事件 API 是同步的,因此它们的功能有限。这些 API 不支持可能阻塞的操作(例如请求权限或转码图像)。有关可以支持阻塞或其他耗时操作的更强大 API,请参阅 § 7 异步剪贴板 API。
6.1. 覆盖复制事件
要覆盖默认的 copy
事件行为,必须添加一个 copy
事件处理程序,并且此事件处理程序必须调用 preventDefault()
来取消事件。
为了使用 clipboardData
中的数据更新系统剪贴板,需要取消事件。
如果未取消 ClipboardEvent
,则将复制当前文档选择中的数据。
// 覆盖复制到剪贴板的内容。 document.addEventListener('copy', function(e) { // e.clipboardData 最初为空,但我们可以将其设置为 // 我们希望复制到剪贴板的数据。 e.clipboardData.setData('text/plain', 'Hello, world!'); e.clipboardData.setData('text/html', '<b>Hello, world!</b>'); // 这是防止将当前文档选择写入剪贴板所必需的。 e.preventDefault(); });
6.2. 覆盖剪切事件
要覆盖默认的 cut
事件行为,必须添加一个 cut
事件处理程序,并且此事件处理程序必须调用 preventDefault()
来取消事件。
为了使用 clipboardData
中的数据更新系统剪贴板,需要取消事件。
如果未取消 ClipboardEvent
,则将复制当前文档选择中的数据。
请注意,取消 cut
事件还将阻止更新文档(即,不会删除当前选择)。事件处理程序将需要手动更新文档以删除当前选定的文本。
// 覆盖复制到剪贴板的内容。 document.addEventListener('cut', function(e) { // e.clipboardData 最初为空,但我们可以将其设置为 // 我们希望作为剪切操作的一部分复制到剪贴板的数据。 // 写入我们希望复制到剪贴板的数据。 e.clipboardData.setData('text/plain', 'Hello, world!'); e.clipboardData.setData('text/html', '<b>Hello, world!</b>'); // 由于我们将取消剪切操作,因此需要手动 // 更新文档以删除当前选定的文本。 deleteCurrentDocumentSelection(); // 这是防止将文档选择写入剪贴板所必需的。 e.preventDefault(); });
6.3. 覆盖粘贴事件
要覆盖默认的 paste
事件行为,必须添加一个 paste
事件处理程序,并且此事件处理程序必须调用 preventDefault()
来取消事件。
为了使用户代理不使用系统剪贴板中的数据更新文档,需要取消事件。
请注意,取消 paste
事件还将阻止更新文档(即,不会将任何内容粘贴到文档中)。事件处理程序将需要手动将数据粘贴到文档中。
另请注意,粘贴时,拖放数据存储模式标志为只读,因此从 paste
事件处理程序调用 setData()
不会修改插入的数据,也不会修改剪贴板上的数据。
// 覆盖粘贴到剪贴板的内容。 document.addEventListener('paste', function(e) { // e.clipboardData 包含即将粘贴的数据。 if (e.clipboardData.types.indexOf('text/html') > -1) { var oldData = e.clipboardData.getData('text/html'); var newData = '<b>Ha Ha!</b> ' + oldData; // 由于我们正在取消粘贴操作,因此需要手动 // 将数据粘贴到文档中。 pasteClipboardData(newData); // 这是防止默认粘贴操作所必需的。 e.preventDefault(); } });
6.4. 强制数据类型
实现必须识别以下数据类型的本机操作系统剪贴板格式描述,以便能够使用正确的描述填充 DataTransferItemList
和 ClipboardItem
以用于粘贴事件,并在响应复制和剪切事件时在操作系统剪贴板上设置正确的数据格式。
6.4.1. 从剪贴板读取
如果剪贴板上存在相应的本机类型,则粘贴事件必须公开这些数据类型:
-
text/plain
-
text/html
-
image/png
6.4.2. 写入剪贴板
如果在复制和剪切事件期间将这些数据类型添加到 DataTransfer
对象,则必须使用相应的本机类型描述将它们放置在剪贴板上。
-
text/plain
-
text/html
-
image/png
警告!出于安全预防措施,限制了不受信任的脚本允许写入剪贴板的数据类型。不受信任的脚本可能会通过将已知会触发本地软件中安全漏洞的数据放置在剪贴板上,从而尝试利用这些漏洞。
6.5. 可选数据类型
实现可以识别以下数据类型的本机操作系统剪贴板格式描述,以便能够使用正确的描述填充 ClipboardItem
以用于粘贴事件,并在响应复制和剪切事件时在操作系统剪贴板上设置正确的数据格式。
如果剪贴板上存在相应的本机类型,用户代理 (UA) 可以公开这些数据类型:
-
text/uri-list
-
image/svg+xml
-
自定义格式,其开头为 `"web "`(“web”后跟 U+0020 空格)前缀,并且后缀(去除 `"web "` 后)通过解析 MIME 类型检查。
6.6. 未清理的数据类型
本节是非规范性的。用户代理 (UA) 不得清理这些数据类型:
-
image/png
用户代理 (UA) 可以不清理这些数据类型:
可选的未清理数据类型是 Web 作者指定的MIME 类型,用户代理可以不清理这些类型。 下面列出了有效的可选的未清理数据类型:
-
text/html
由于其隐私要求,用户代理可能不支持可选的未清理数据类型。
7. 异步剪贴板 API
7.1. Navigator 接口
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute Clipboard ; };
clipboard
7.2. ClipboardItem 接口
typedef Promise <(DOMString or Blob )>; [
ClipboardItemData SecureContext ,Exposed =Window ]interface {
ClipboardItem constructor (record <DOMString ,ClipboardItemData >,
items optional ClipboardItemOptions = {});
options readonly attribute PresentationStyle presentationStyle ;readonly attribute FrozenArray <DOMString >types ;Promise <Blob >getType (DOMString );
type static boolean supports (DOMString ); };
type enum {
PresentationStyle ,
"unspecified" ,
"inline" };
"attachment" dictionary {
ClipboardItemOptions PresentationStyle = "unspecified"; };
presentationStyle
clipboardItem = new ClipboardItem([items, options])
-
创建一个新的
ClipboardItem
对象。items 表示表示形式列表,每个表示形式都有一个MIME 类型和一个Promise
,该 Promise 解析为与MIME 类型对应的Blob
或DOMString
, options 可用于填充其ClipboardItemOptions
, 如下例所示。const format1= 'text/plain' ; const promise_text_blob= Promise. resolve( new Blob([ 'hello' ], { type: format1})); const clipboardItemInput= new ClipboardItem( {[ format1] : promise_text_blob}, { presentationStyle: "unspecified" }); clipboardItem.getType(type)
- 返回一个
Promise
, 该 Promise 解析为与MIME 类型 type 对应的Blob
。 clipboardItem.types
- 返回剪贴板项目对象中包含的MIME 类型列表。
ClipboardItem
.supports(type)- 如果 type 属于强制数据类型或可选数据类型,则返回 true,否则返回 false。
一个剪贴板项目在概念上是用户通过调用“剪切”或“复制”命令表示希望共享的数据。一个剪贴板项目有两个用途。首先,它允许网站读取用户复制到系统剪贴板的数据。其次,它允许网站向系统剪贴板写入数据。
例如,如果用户从本机应用程序的电子表格中复制一系列单元格,则会产生一个剪贴板项目。如果用户从桌面复制一组文件,则该文件列表将由多个剪贴板项目表示。
某些平台可能支持在剪贴板上同时拥有多个剪贴板项目,而其他平台则用新的剪贴板项目替换前一个。
一个剪贴板项目有一个表示形式列表,每个表示形式都有一个关联的MIME 类型(一个MIME 类型),一个isCustom 标志(初始值为 false),指示此表示形式是否应被视为Web 自定义格式(而不是系统剪贴板的已知格式),以及数据(一个
ClipboardItemData
)。
一个Web 自定义格式的 isCustom 设置为 true。
在用户从电子表格复制单元格区域的示例中,它可以表示为图像 (image/png)、HTML 表格 (text/html) 或纯文本 (text/plain),或者 Web 自定义格式 (web text/csv)。
这些MIME 类型中的每一个都描述了同一剪贴板项目在不同保真度级别下的不同表示形式,并使剪贴板项目在粘贴期间更容易被目标应用程序使用。
将单元格区域作为图像提供,将允许用户将单元格粘贴到照片编辑应用程序中,而 text/plain 格式可供文本编辑器应用程序使用。
一个剪贴板项目有一个表示样式(一个
PresentationStyle
)。
它有助于区分“粘贴”剪贴板项目的应用程序是应该在粘贴点内联插入适当表示形式的内容,还是应该将其视为附件。
仅支持粘贴单个剪贴板项目的 Web 应用程序应使用第一个剪贴板项目。
支持粘贴多个剪贴板项目的 Web 应用程序可以(例如)提供一个用户界面,预览每个剪贴板项目的内容,并允许用户选择要粘贴哪一个。 此外,应用程序应枚举它们正在粘贴的剪贴板项目的MIME 类型,并根据某些特定于应用程序的算法选择最适合该应用程序的类型。 或者,应用程序可以向用户显示有关如何粘贴剪贴板项目的选项,例如“粘贴为图像”或“粘贴带格式的文本”等。
一个 ClipboardItem
对象有一个关联的剪贴板项目,它是一个剪贴板项目。
一个 ClipboardItem
对象有一个关联的类型数组,它是一个 FrozenArray
<DOMString
>。
要创建一个
ClipboardItem
对象,给定一个剪贴板项目
clipboardItem 和一个领域 realm,
请执行以下步骤:
-
令 clipboardItemObject 为一个新的
ClipboardItem
, 其领域为 realm。 -
将 clipboardItemObject 的剪贴板项目设置为 clipboardItem。
new ClipboardItem(items, options)
构造函数步骤如下:
-
如果 items 为空,则抛出
TypeError
。 -
如果 options 为空,则设置 options["presentationStyle"] = "unspecified"。
-
将此对象的 剪贴板项目的表示样式设置为 options["
presentationStyle
"]。 -
令 types 为一个
DOMString
列表。 -
对于 items 中的每个 (key, value):
-
令 representation 为一个新的表示形式。
-
令 isCustom 为 false。
-
如果 key 以 `"web "` 前缀开头,则
-
移除 `"web "` 前缀并将剩余字符串赋给 key。
-
设置 isCustom 为 true
-
-
将 representation 的isCustom 标志设置为 isCustom。
-
令 mimeType 为给定 key 解析 MIME 类型的结果。
-
如果 mimeType 为失败,则抛出
TypeError
。 -
如果此对象的剪贴板项目的表示形式列表 包含一个表示形式,其MIME 类型为 mimeType 且其 [representation/isCustom] 为 isCustom,则抛出
TypeError
。
上述步骤可防止用户代理已知的 MIME 类型与作者希望视为自定义类型的 MIME 类型之间发生冲突。例如,作者的项目列表可能包含 "text/html" 以及 "web text/html" 的表示形式。
-
7.2.1. presentationStyle
presentationStyle
getter 的步骤是返回此对象的剪贴板项目的表示样式。
7.2.2. types
7.2.3. getType(type)
此方法必须运行以下步骤:
-
令 isCustom 为 false。
-
如果 type 以 `"web "` 前缀开头,则:
-
移除 `"web "` 前缀并将剩余字符串赋给 type。
-
设置 isCustom 为 true。
-
-
令 mimeType 为给定 type 解析 MIME 类型的结果。
-
如果 mimeType 为失败,则抛出
TypeError
。 -
令 p 为 realm 中的一个新的 promise。
-
对于 itemTypeList 中的每个 representation:
-
如果 representation 的MIME 类型是 mimeType 并且 representation 的isCustom 是 isCustom,则:
-
令 representationDataPromise 为 representation 的数据。
-
响应 representationDataPromise:
-
如果 representationDataPromise 以值 v 完成,则:
-
如果 representationDataPromise 被拒绝,则:
-
在 realm 中用
"NotFoundError"
DOMException
拒绝 p。
-
-
-
返回 p。
-
-
-
在 realm 中用
"NotFoundError"
DOMException
拒绝 p。 -
返回 p。
7.2.4. supports(type)
此方法必须运行以下步骤:
7.3. 剪贴板接口
typedef sequence <ClipboardItem >; [
ClipboardItems SecureContext ,Exposed =Window ]interface :
Clipboard EventTarget {Promise <ClipboardItems >read (optional ClipboardUnsanitizedFormats = {});
formats Promise <DOMString >readText ();Promise <undefined >write (ClipboardItems );
data Promise <undefined >writeText (DOMString ); };
data dictionary {
ClipboardUnsanitizedFormats sequence <DOMString >; };
unsanitized
剪贴板
接口的一些方法接受或返回多个 ClipboardItem
对象。但是,并非所有平台都支持多个剪贴板项目;在此类平台上,以下算法将忽略传递给 write()
的第一个 ClipboardItem
对象之后的任何对象,并且 read()
和 readText()
仅从操作系统获取一个剪贴板项目。
Web 作者需要创建一个 data,它是一个 ClipboardItem
数组,以便使用 write(data)
方法将内容写入系统剪贴板。 read()
返回一个 Promise
,
该 Promise 解析为表示系统剪贴板数据内容的剪贴板项目对象。
unsanitized
是一个序列,包含 DOMString
,
对应于作者希望被视为可选的未清理数据类型的MIME 类型。
用户代理可能不支持 unsanitized
选项。Web 作者不应假定 unsanitized
中列出的 MIME 类型的内容将是未清理的,因为在某些隐私模式下可能不允许此选项。
剪贴板任务源是在读取或写入系统剪贴板数据时触发的。
7.3.1. read(formats)
read(formats)
方法必须执行以下步骤:
-
令 p 为 realm 中的一个新的 promise。
-
如果 formats 不为空,则:
-
对于 formats["
unsanitized
"] 中的每个 format:-
如果 format 不在可选的未清理数据类型中,则在 realm 中用 format
"NotAllowedError"
DOMException
拒绝 p。
-
-
-
并行运行以下步骤:
-
令 r 为运行检查剪贴板读取权限的结果。
-
如果 r 为 false,则:
-
在权限任务源上,给定 realm 的全局对象,将一个全局任务排队,以在 realm 中用
"NotAllowedError"
DOMException
拒绝 p。 -
中止这些步骤。
-
-
令 data 为系统剪贴板数据的副本。
-
对于 data 中的每个 systemClipboardItem:
-
令 item 为一个新的剪贴板项目。
-
对于 systemClipboardItem 中的每个 systemClipboardRepresentation:
-
令 mimeType 为给定 systemClipboardRepresentation 的名称运行从操作系统特定格式获取已知 MIME 类型算法的结果。
-
如果 mimeType 为 null,则继续此循环。
-
令 representation 为一个新的表示形式。
-
将 representation 的MIME 类型设置为 mimeType。
-
令 isUnsanitized 为 false。
-
如果 formats 不为空,则:
-
对于 formats["
unsanitized
"] 中的每个 format:-
如果 format 等于MIME 类型,则将 isUnsanitized 设置为 true。
-
-
-
用户代理可以清理 representation 的数据,除非 representation 的MIME 类型的本质是 "image/png"(应保持未清理以保留元数据),或者如果它满足以下条件:
-
将 representation 附加到 item 的表示形式列表。
-
将 isUnsanitized 设置为 false。
-
-
如果 item 的表示形式列表的大小大于 0,则将 item 附加到 items。
-
-
如果 items 的大小 > 0,则:
-
令 firstItem 为 items[0]
-
给定 firstItem 运行读取 Web 自定义格式算法。
-
-
否则:
-
令 customItem 为一个新的剪贴板项目。
-
给定 customItem 运行读取 Web 自定义格式算法。
-
如果 customItem 的表示形式列表的大小大于 0,则将 customItem 附加到 items。
-
-
在剪贴板任务源上,给定 realm 的全局对象,将一个全局任务排队,以执行以下步骤:
-
令 clipboardItems 为一个序列<
ClipboardItem
>。 -
对于 items 中的每个剪贴板项目 underlyingItem:
-
令 clipboardItem 为给定 underlyingItem 和 realm 运行创建 ClipboardItem 对象的步骤的结果。
-
将 clipboardItem 附加到 clipboardItems。
-
-
用 clipboardItems 解析 p。
-
-
-
返回 p。
const items= await navigator. clipboard. read(); const textBlob= await items[ 0 ]. getType( "text/plain" ); const text= await ( new Response( textBlob)). text();
7.3.2. readText()
readText()
方法必须执行以下步骤:
-
令 p 为 realm 中的一个新的 promise。
-
并行运行以下步骤:
-
令 r 为运行检查剪贴板读取权限的结果。
-
如果 r 为 false,则:
-
在权限任务源上,给定 realm 的全局对象,将一个全局任务排队,以在 realm 中用
"NotAllowedError"
DOMException
拒绝 p。 -
中止这些步骤。
-
-
令 data 为系统剪贴板数据的副本。
某些操作系统包含多个剪贴板(例如 Linux 中的“primary”、“secondary”、“selection”)。定义从哪个剪贴板读取数据。
-
在剪贴板任务源上,给定 realm 的全局对象,将一个全局任务排队,以执行以下步骤:
-
对于 data 中的每个 systemClipboardItem:
-
对于 systemClipboardItem 中的每个 systemClipboardRepresentation:
-
令 mimeType 为给定 systemClipboardRepresentation 的名称运行从操作系统特定格式获取已知 MIME 类型算法的结果。
-
如果 mimeType 为 null,则继续此循环。
-
令 representation 为一个新的表示形式。
-
如果 representation 的MIME 类型的本质是 "text/plain",则:
-
将 representation 的MIME 类型设置为 mimeType。
-
令 representationDataPromise 为 representation 的数据。
-
响应 representationDataPromise:
-
如果 representationDataPromise 以值 v 完成,则:
-
如果 representationDataPromise 被拒绝,则:
-
在 realm 中用
"NotFoundError"
DOMException
拒绝 p。 -
返回 p。
-
-
-
-
-
-
在 realm 中用
"NotFoundError"
DOMException
拒绝 p。 -
返回 p。
-
-
navigator. clipboard. readText(). then( function ( data) { console. log( "你的字符串: " , data); });
7.3.3. write(data)
write(data)
方法必须执行以下步骤:
-
令 p 为 realm 中的一个新的 promise。
-
并行运行以下步骤:
-
令 r 为运行检查剪贴板写入权限的结果。
clipboard-write 已在 https://github.com/w3c/clipboard-apis/pull/164 中移除。
-
如果 r 为 false,则:
-
在权限任务源上,给定 realm 的全局对象,将一个全局任务排队,以在 realm 中用
"NotAllowedError"
DOMException
拒绝 p。 -
中止这些步骤。
-
-
在剪贴板任务源上,给定 realm 的全局对象,将一个全局任务排队,以执行以下步骤:
-
令 dataList 为一个序列<
ClipboardItem
>。 -
如果 data 的大小大于 1,并且当前操作系统不支持系统剪贴板上的多个本机剪贴板项目,则将 data[0] 添加到 dataList,否则,将 dataList 设置为 data。
-
对于 dataList 中的每个 clipboardItem:
-
对于 clipboardItem 的剪贴板项目的 表示形式列表中的每个 representation:
-
令 representationDataPromise 为 representation 的数据。
-
响应 representationDataPromise:
-
如果 representationDataPromise 以值 v 完成,则:
-
如果 representationDataPromise 被拒绝, 则:
-
在 realm 中用
"NotAllowedError"
DOMException
拒绝 p。 -
中止这些步骤。
-
-
-
-
对于 itemList 中的每个 blob:
-
令 type 为 blob 的
type
。 -
如果 type 不在强制数据类型或可选数据类型列表中,则在 realm 中用
"NotAllowedError"
DOMException
拒绝 p 并中止这些步骤。 -
令 cleanItem 为 blob 的一个可选的已清理副本。
-
如果尝试了清理但未成功完成,则执行以下步骤:
-
在 realm 中用
"NotAllowedError"
DOMException 拒绝 p。 -
中止这些步骤。
-
-
将 cleanItem 附加到 cleanItemList。
-
-
使用 cleanItemList 和 option 将 blob 和选项写入剪贴板。
-
-
解析 p。
-
-
返回 p。
var data= [ new ClipboardItem({ "text/plain" : Promise. resolve( new Blob([ "文本数据" ], { type: "text/plain" })) })]; navigator. clipboard. write( data). then( function () { console. log( "已成功复制到剪贴板!" ); }, function () { console. error( "无法写入剪贴板。 :-(" ); });
7.3.4. writeText(data)
writeText(data)
方法必须执行以下步骤:
-
令 p 为 realm 中的一个新的 promise。
-
并行运行以下步骤:
-
返回 p。
await navigator. clipboard. writeText( "你好,伙伴!" );
8. 剪贴板操作
本节定义剪贴板操作和事件分发的处理模型。
每个剪贴板操作都有两个标志,称为脚本触发和脚本可访问剪贴板。
如果操作因脚本而运行(例如 document.execCommand()
调用),则设置 脚本触发
标志。未来与剪贴板交互的脚本 API 也应使用这些操作,并且必须相应地设置 脚本触发标志。
脚本可访问剪贴板 标志设置如下:
8.1. 复制操作
复制操作包括以下步骤:
-
如果设置了脚本触发标志,则
-
如果未设置脚本可访问剪贴板标志,则
-
从复制操作返回 false,终止此算法
-
-
-
如果事件未被取消,则
-
将选定的内容(如有)复制到剪贴板。当选择网页中的内容时,实现应创建备用的 text/html 和 text/plain 剪贴板格式。
-
触发一个名为
clipboardchange
的剪贴板事件
-
-
否则,如果事件被取消,则
-
调用将内容写入剪贴板算法, 传递
DataTransferItemList
列表 items、 一个 clear-was-called 标志和一个 types-to-clear 列表。
-
-
从复制操作返回 true
8.2. 剪切操作
剪切操作包括以下步骤:
-
如果设置了脚本触发标志,则
-
如果未设置脚本可访问剪贴板标志,则
-
从剪切操作返回 false,终止此算法
-
-
-
如果事件未被取消,则
-
如果在启用了剪切的可编辑上下文中存在选区,则
-
将选定的内容(如有)复制到剪贴板。当选择网页中的内容时,实现应创建备用的 text/html 和 text/plain 剪贴板格式。
-
从文档中删除选区的内容并折叠选区。
-
触发一个名为
clipboardchange
的剪贴板事件 -
将由于修改而应触发的任何事件排队,有关详细信息,请参阅§ 5.3 与其他脚本和事件的集成。
-
-
否则,如果没有选区或上下文不可编辑,则
-
返回 false
-
-
-
否则,如果事件被取消,则
-
调用将内容写入剪贴板算法, 传递
DataTransferItemList
列表 items、 一个 clear-was-called 标志和一个 types-to-clear 列表。 -
触发一个名为
clipboardchange
的剪贴板事件
-
-
从剪切操作返回 true
8.3. 粘贴操作
对于粘贴操作,脚本可访问剪贴板标志取决于实现特定的权限机制,用于确定哪些站点或应用可以从剪贴板读取。当脚本触发粘贴操作时,实现不得在未经用户许可的情况下提供剪贴板内容。如果尚未授予权限,则权限提示必须包括与脚本线程关联的文档的主机名。
粘贴操作包括以下步骤:
9. Permissions API 集成
[permissions] API 为网站提供了一种统一的方式来访问强大的功能,例如剪贴板。它允许网站向用户请求权限并查询它们拥有的权限。
对于剪贴板,定义了一个权限:"clipboard-write"
注意:剪贴板权限目前仅适用于异步剪贴板 API。 此规范的未来版本可能会更新以将此权限应用于其他剪贴板交互。
这些剪贴板权限是强大的功能,与权限相关的算法和类型定义如下:
- 权限描述符类型
-
dictionary
:ClipboardPermissionDescriptor PermissionDescriptor {boolean
=allowWithoutGesture false ; };
有 4 个剪贴板权限:
-
{ name: "clipboard-write", allowWithoutGesture: false }
-
{ name: "clipboard-write", allowWithoutGesture: true }
具有以下关系:
-
{ "clipboard-write" + true }
强于{ "clipboard-write" + false }
虽然用户代理必须支持本规范中描述的 ClipboardPermissionDescriptor
,
但它们当然保留对默认设置以及如何(或是否)向用户公开这些设置的完全控制权。
-
{ "clipboard-write" + false }
公开给用户控制 -
{ "clipboard-write" + true }
始终是denied
9.1. 剪贴板读取权限
9.2. 剪贴板写入权限
9.2.1. 检查剪贴板写入权限
-
令 writeWithoutGesture 为
{ name: "clipboard-write", allowWithoutGesture: true }
权限的权限状态。 -
如果 writeWithoutGesture 为
granted
, 则返回 true。 -
如果 hasGesture 为 true,则:
-
如果当前脚本是由于用户与用户代理或操作系统创建的“剪切”或“复制”元素交互而运行的,则令 systemCopy 为 true。
-
如果 systemCopy 为 true,则返回 true。
-
返回请求使用权限
{ name: "clipboard-write", allowWithoutGesture: false }
权限的结果。注意:用户代理可以选择请求一个更强的权限,该权限将隐式更新此权限。
-
-
返回请求使用权限
{ name: "clipboard-write", allowWithoutGesture: true }
权限的结果。
10. 安全注意事项
允许作者更改用户复制的内容,或自动复制从未被选中的内容,以及允许无限制地调用粘贴信息,这些都可能引发各种安全问题。
一些示例场景包括:
-
用户选择一个链接并复制它,但一个不同的链接被复制到剪贴板。 其影响范围可以从粘贴时的意外结果到企图进行的“网络钓鱼”攻击。
-
(Self-XSS)可以将 Shell 命令或可执行脚本放入剪贴板,意图让用户运行粘贴的内容。
-
可以将特制图像写入剪贴板,以利用核心操作系统图像处理代码中的错误。
10.1. 粘贴 HTML 和多部分数据
本节是非规范性的。
粘贴格式化或多部分数据存在某些安全风险。
-
用户可能在没有意识到隐藏数据存在的情况下粘贴了隐藏数据。例如,如果标记包含 <input type="hidden"> 标签或 HTML 注释,就可能发生这种情况。此类隐藏数据可能包含敏感信息。
-
用户可能将恶意 JavaScript 粘贴到受信任的页面中。
-
实现可能会授予脚本访问用户不打算公开的本地文件的权限。
为了确定使用哪些策略,我们考虑的因素有:
-
被粘贴数据的来源
-
数据子部分(如引用的图像)的来源
-
运行脚本的来源
以下是场景和可能的安全策略概述:
数据来源 | 脚本来源 | 规则 |
---|---|---|
源自在线资源 | 与数据相同 | 不清理 HTML。不访问任何本地文件。 |
不同来源 | 可选地清理内容。不访问任何本地文件。 | |
源自本地应用程序 | 任何 | 不清理 HTML。授予对本地文件的访问权限 |
一些实现通过在粘贴富文本时默认剥离潜在的恶意内容(例如 SCRIPT 元素和 javascript: 链接)来降低与粘贴富文本相关的风险,但允许粘贴事件处理程序检索和处理原始的、未清理的数据。
10.2. 通用安全策略
实现不得下载引用的在线资源,或在 files
列表或 DataTransferItemList
中公开其内容。
如果剪贴板上的数据不是来自本地应用程序,则实现不得授予对任何引用的本地文件的访问权限。例如,如果数据包含 <img src="file://localhost/example.jpg"> 但数据的来源是在线资源,则实现不得将 example.jpg 的条目添加到 clipboardData.items 列表中。
10.3. 转码图像
为防止恶意图像数据被放置在剪贴板上,可以对图像数据进行转码以生成图像的安全版本。这可以防止网站试图利用其他应用程序中的安全漏洞。
实现不应转码从剪贴板读取的图像。转码图像可能会丢失重要的元数据(例如图像的物理分辨率)。 这也与可以与网站共享图像的其他方法(例如 `<input type=file>`)一致。
10.4. 滋扰注意事项
脚本可以使用 DataTransfer
API 通过更改复制和剪切事件中系统剪贴板上的数据来骚扰和迷惑用户。本规范不试图阻止此类滋扰,但实现可能会添加额外的限制。
实现必须妥善处理试图在剪贴板上放置过多数据的脚本。
11. 隐私注意事项
由于这些 API 提供了对用户剪贴板数据的访问权限,因此存在严重的隐私问题,因为剪贴板可能包含个人身份信息 (PII),例如姓名、地址或密码。
通常,用户代理必须确保不受信任的脚本无法通过这些 API 不受控制地访问用户的剪贴板数据。
11.1. 隐私和剪贴板事件 API
剪贴板事件 API 允许在剪贴板事件处理程序上下文中运行的脚本访问系统剪贴板的副本,并可能修改写入剪贴板的数据。
用户代理应注意以下有关保护剪贴板事件 API 访问的数据的要求:
-
实现
DataTransfer
接口以返回剪贴板数据的对象不得在提供数据的 ClipboardEvent 事件处理程序之外可用。 -
如果脚本存储对实现
DataTransfer
接口的对象的引用,以便在 ClipboardEvent 事件处理程序之外使用,则在预期上下文之外调用时,所有方法必须为空操作。 -
实现不得让脚本创建合成剪贴板事件以获取对真实剪贴板数据的访问权限(除非用户已配置为这样做)。
尽管剪贴板事件 API 不受剪贴板权限的保护,但用户代理可以选择提供一种方法,让用户禁用此 API 或配置允许哪些站点访问它。
11.2. 隐私和异步剪贴板 API
异步剪贴板 API 是一项强大的功能,因为它允许从任何脚本访问剪贴板数据(访问不限于剪贴板事件处理程序),并且可以在没有用户提供手势的情况下访问数据。
为帮助防止滥用,此 API 不得可用,除非脚本在具有焦点的文档上下文中执行。
11.2.1. 隐私和剪贴板权限
剪贴板权限控制对此 API 的访问,但用户代理可以选择权限默认值以及用户可以设置哪些权限设置。例如,用户代理可以选择仅在存在用户手势时才允许访问异步剪贴板 API,并始终拒绝脚本在没有手势的情况下访问的请求。
用户代理可以选择让此权限在用户授予权限后的某个时间自动过期,例如,通过让权限过期:
-
首次授予权限后的一段时间
-
用户上次访问站点后的一段时间
-
当用户离开页面时
11.3. 其他隐私问题
如果用户代理允许使用 document.execCommand("paste")
读取剪贴板数据,则用户代理必须确保用户已明确允许进行该访问。
12. 致谢
本节为非规范性内容
编辑们感谢前任编辑们所做的贡献,他们帮助本规范经历了各种会议和邮件列表讨论,使其达到目前的状态。
-
Hallvord R. M. Steen
编辑们也感谢微软的 Data Transfer 功能文档 [MICROSOFT-CLIP-OP] 以及 [HTML5] 规范的早期草案在知识上的启发。 我们也感谢 Paul Libbrecht 提供的“安全复制和粘贴”草案(此草案已无法在网络上找到)。
最后,我们要感谢以下人员所做的贡献:
Adam Barth, Shawn Carnell, Daniel Cheng, Daniel Dardailler, Domenic Denicola, Al Gilman, James Graham, James Greene, Ian Hickson, Darwin Huang, Lachlan Hunt, Philip Jägenstedt, Anne van Kesteren, Marijn Kruisselbrink, Aaron Leventhal, Jim Ley, Paul Libbrecht, "Martijn", Glenn Maynard, Chris Mills, ms2ger, Ryosuke Niwa, Robert O’Callahan, Dave Poehlman, "ROBO Design", Janina Sajka, Rich Schwerdtfeger, Jonas Sicking, Maciej Stachowiak, Mihai Sucan, Dmitry Titov, Ojan Vafai, Tarquin Wilton-Jones, Tom Wlodkowski, Bo Cupp, mbrodesser 和 Boris Zbarsky。
附录 A:算法
将内容写入剪贴板
- 输入
-
items,一个要写入的项目的
DataTransferItemList
列表 -
clear-was-called,一个布尔值
-
types-to-clear,一个列表
- 输出
-
无
-
如果 items 列表不为空,则
-
清除剪贴板
-
对于列表中的每个部分,
-
如果数据类型是 text/plain,则
-
确保编码根据操作系统和区域设置约定是正确的
-
根据平台约定规范化行尾
-
使用适当的操作系统剪贴板格式描述将文本放置在剪贴板上
-
-
否则,如果数据类型是强制数据类型列表中列出的类型,则
-
使用适当的操作系统剪贴板格式描述将部分放置在剪贴板上
-
-
否则
-
-
-
否则,items 列表为空。按照以下步骤确定是否清除剪贴板:
将 blob 和选项写入剪贴板
-
对于 items 中的每个 item:
-
令 formatString 为运行特定于操作系统的已知格式的结果,给定 item 的
type
。 -
如果 formatString 为空,则执行以下步骤:
-
令 webCustomFormatString 为 item 的
type
。 -
令 webCustomFormat 为一个空的
type
。 -
如果 webCustomFormatString 以 `"web "` 前缀开头,则移除 `"web "` 前缀并将剩余字符串存储在 webMimeTypeString 中。
-
令 webMimeType 为解析 MIME 类型的结果,给定 webMimeTypeString。
-
如果 webMimeType 失败,则中止所有步骤。
-
将 item 的
type
设置为 webCustomFormat。 -
将 webCustomFormat 附加到 webCustomFormats。
-
-
令 payload 为UTF-8 解码 item 的底层字节序列的结果。
-
使用 formatString 作为本机剪贴板格式,将 payload 和 presentationStyle 插入到系统剪贴板中。
某些操作系统包含多个剪贴板(例如 Linux 中的“primary”、“secondary”、“selection”)。定义数据写入到其中的哪一个。
-
-
给定 webCustomFormats,写入 Web 自定义格式。
特定于操作系统的已知格式
- 输入
-
mimeType,一个
type
- 输出
-
wellKnownFormat,一个平台特定的字符串类型。在 Mac 上是 NSPasteboardType,在 Windows 上是 LPCWSTR,在 Linux 上是 const char*。
对于 Windows,请参阅 https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats 和 https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-atom-tables?redirectedfrom=MSDN 对于 Mac,请参阅 https://developer.apple.com/documentation/appkit/nspasteboardtype
-
令 wellKnownFormat 为一个空字符串。
-
如果 mimeType 的本质是 "text/plain",则
在 Windows 上,遵循以下描述的约定:
-
将 CF_UNICODETEXT 分配给 wellKnownFormat。
在 MacOS 上,遵循以下描述的约定:
-
将 NSPasteboardTypeString 分配给 wellKnownFormat。
在 Linux、ChromeOS 和 Android 上,遵循以下描述的约定:
-
将 "text/plain" 分配给 wellKnownFormat。
-
-
否则,如果 mimeType 的本质是 "text/html",则
在 Windows 上,遵循以下描述的约定:
-
将 CF_HTML 分配给 wellKnownFormat。
在 MacOS 上,遵循以下描述的约定:
-
将 NSPasteboardTypeHTML 分配给 wellKnownFormat。
在 Linux、ChromeOS 和 Android 上,遵循以下描述的约定:
-
将 "text/html" 分配给 wellKnownFormat。
-
-
否则,如果 mimeType 的本质是 "image/png",则
在 Windows 上,遵循以下描述的约定:
-
将 "PNG" 分配给 wellKnownFormat。
在 MacOS 上,遵循以下描述的约定:
-
将 NSPasteboardTypePNG 分配给 wellKnownFormat。
在 Linux、ChromeOS 和 Android 上,遵循以下描述的约定:
-
将 "image/png" 分配给 wellKnownFormat。
-
-
Else, if mimeType’s essence is "image/svg+xml", then
在 Windows 上,遵循以下描述的约定:
-
将 CFSTR_MIME_SVG_XML 分配给 wellKnownFormat。
在 MacOS 上,遵循以下描述的约定:
-
将 UTTypeSVG 分配给 wellKnownFormat。
在 Linux、ChromeOS 和 Android 上,遵循以下描述的约定:
-
将 "image/svg+xml" 分配给 wellKnownFormat。
-
-
返回 wellKnownFormat。
从特定于操作系统的格式获取已知 MIME 类型
- 输入
-
osFormatName,一个平台特定的字符串类型。在 Mac 上是 NSPasteboardType,在 Windows 上是 LPCWSTR,在 Linux 上是 const char*。
- 输出
-
mimeType,一个 MIME 类型
对于 Windows,请参阅 https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats 和 https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-atom-tables?redirectedfrom=MSDN 对于 Mac,请参阅 https://developer.apple.com/documentation/appkit/nspasteboardtype
在 Windows 上,遵循以下描述的约定:
-
如果 osFormatName 是 "UnicodeText",则将 mimeTypeString 设置为 "text/plain"。
-
否则,如果 osFormatName 是 "HTML Format",则将 mimeTypeString 设置为 "text/html"。
-
否则,如果 osFormatName 是 "PNG",则将 mimeTypeString 设置为 "image/png"。
-
否则,如果 osFormatName 是 CFSTR_MIME_SVG_XML,则将 mimeTypeString 设置为 "image/svg+xml"。
在 MacOS 上,遵循以下描述的约定:
-
如果 osFormatName 是 NSPasteboardTypeString,则将 mimeTypeString 设置为 "text/plain"。
-
否则,如果 osFormatName 是 NSPasteboardTypeHTML,则将 mimeTypeString 设置为 "text/html"。
-
否则,如果 osFormatName 是 NSPasteboardTypePNG,则将 mimeTypeString 设置为 "image/png"。
-
否则,如果 osFormatName 是 UTTypeSVG,则将 mimeTypeString 设置为 "image/svg+xml"。
在 Linux、ChromeOS 和 Android 上,遵循以下描述的约定:
-
如果 osFormatName 是 "text/plain",则将 mimeTypeString 设置为 "text/plain"。
-
否则,如果 osFormatName 是 "text/html",则将 mimeTypeString 设置为 "text/html"。
-
否则,如果 osFormatName 是 "image/png",则将 mimeTypeString 设置为 "image/png"。
-
否则,如果 osFormatName 是 "image/svg+xml",则将 mimeTypeString 设置为 "image/svg+xml"。
-
令 mimeType 为解析 MIME 类型的结果,给定 mimeTypeString。
-
返回 mimeType。
读取 Web 自定义格式
- 输入
-
item,一个剪贴板项目
-
令 webCustomFormatMap 为特定于操作系统的自定义映射名称。
-
从系统剪贴板读取 webCustomFormatMap。
-
如果 webCustomFormatMap 为空,则返回 item。
-
令 webCustomFormatMapString 为从 webCustomFormatMap 反序列化得到的 JSON 字符串。
注意:需要一个 JSON 读取器来从 webCustomFormatMap 反序列化内容。
-
对于 webCustomFormatMapString 中的每个 (key, value):
写入 Web 自定义格式
-
令 idx 为一个初始化为 0 的数字。
-
令 webCustomFormatMap 为特定于操作系统的自定义映射名称。
-
令 webCustomFormatMapString 为一个空的 JSON 字符串。
-
对于 items 中的每个 item:
-
令 webCustomFormat 为特定于操作系统的自定义名称。
-
令 webCustomFormatIdx 为将 idx 附加到 webCustomFormat 的结果。
-
使用 JSON 序列化器将 item 的
type
作为键,webCustomFormatIdx 作为值插入到 webCustomFormatMapString 中。注意:需要一个 JSON 写入器将内容序列化到 webCustomFormatMapString 中。
-
使用 webCustomFormatIdx 作为格式,将 item 插入到系统剪贴板中。
-
递增 idx。
-
如果 idx 大于 100,则跳出此循环。
-
-
使用 webCustomFormatMap 作为格式,将 webCustomFormatMapString 插入到系统剪贴板中。
特定于操作系统的自定义映射名称
- 输出
-
webCustomFormatMap,一个字符串
在 Windows 上,遵循以下描述的约定:
-
将 "Web Custom Format Map" 分配给 webCustomFormatMap。
-
返回 webCustomFormatMap。
在 MacOS 上,遵循以下描述的约定:
-
将 "org.w3.web-custom-format.map" 分配给 webCustomFormatMap。
-
返回 webCustomFormatMap。
在 Linux、ChromeOS 和 Android 上,遵循以下描述的约定:
-
将 "application/web;type=\"custom/formatmap\"" 分配给 webCustomFormatMap。
-
返回 webCustomFormatMap。
特定于操作系统的自定义名称
- 输出
-
webCustomFormat,一个字符串
在 Windows 上,遵循以下描述的约定:
-
将 "Web Custom Format" 分配给 webCustomFormat。
-
返回 webCustomFormat。
在 MacOS 上,遵循以下描述的约定:
-
将 "org.w3.web-custom-format.type-" 分配给 webCustomFormat。
-
返回 webCustomFormat。
在 Linux、ChromeOS 和 Android 上,遵循以下描述的约定:
-
将 "application/web;type="custom/format" 分配给 webCustomFormat。
-
返回 webCustomFormat。
触发剪贴板事件
- 输入
-
e,要触发的
ClipboardEvent
- 输出
-
无
-
令 clear-was-called 为 false
-
令 types-to-clear 为一个空列表
-
令 clipboard-event-data 为一个新的
DataTransfer
对象,其items
列表为空。 -
令 clipboard-entry 为当前剪贴板内容的序列号,如果操作系统剪贴板不支持序列号,则为 null
-
如果事件由用户代理生成,则令 trusted 为 true,否则为 false
-
按如下方式设置 target:
-
按如下方式处理事件:
-
如果 e 是 "paste",则
-
如果 trusted 为 true,或者实现配置为授予脚本生成的事件对操作系统剪贴板的读取权限
-
对于操作系统剪贴板上的每个 clipboard-part,执行以下步骤:
-
如果 clipboard-part 包含纯文本,则
-
确保文本使用脚本引擎内部使用的编码
-
令 new-data 为一个新的
DataTransferItem
, 其拖放数据项种类设置为 string,拖放数据项类型字符串设置为 text/plain。 -
将 new-data 的数据设置为纯文本。
-
将 new-data 添加到 clipboard-event-data 的
items
中
-
-
如果 clipboard-part 表示文件引用,则对于每个文件引用:
-
确定引用文件的 MIME 类型
-
令 new-data 为一个新的
DataTransferItem
, 其拖放数据项种类设置为 file,拖放数据项类型字符串设置为相应的 MIME 类型,如果文件类型未知,则设置为application/octet-stream
。 -
将 new-data 的数据设置为文件引用数据。
-
将 new-data 添加到 clipboard-event-data 的
items
中
-
-
如果 clipboard-part 包含 HTML 或 XHTML 格式的文本(根据操作系统描述此类剪贴板格式的约定),则
-
如果实现支持粘贴 HTML,则实现必须通过使用 clipboard-part 和 clipboard-event-data 调用处理 html 粘贴事件来处理标记。
-
-
如果 clipboard-part 包含其他受支持的二进制或基于文本的格式的数据(请参阅强制数据类型),则
-
确定数据的 MIME 类型
-
令 new-data 为一个新的
DataTransferItem
, 其拖放数据项种类设置为 file,拖放数据项类型字符串设置为相应的 MIME 类型 -
将 new-data 的数据设置为二进制或基于文本的数据。
-
将 new-data 添加到 clipboard-event-data 的
items
中
-
-
-
-
更新 clipboard-event-data 的
files
属性以匹配 clipboard-event-data 的items
中的条目。 -
更新 clipboard-event-data 的
types
属性以匹配 clipboard-event-data 的items
中的条目。
-
如果 e 是 "copy" 或 "cut",则
-
将关联的
DataTransfer
对象的内部拖放数据存储模式标志设置为读/写
-
-
-
将 e 的
clipboardData
设置为 clipboard-event-data。 -
将 e 的
isTrusted
设置为 trusted。 -
将 e 的
composed
设置为 true。 -
在 target 处分派事件 e,该事件冒泡且可取消,并使用
ClipboardEvent
接口。事件分派期间数据访问的实现要求在[HTML]中定义。下面给出了一些额外的剪贴板事件特定处理规则:
-
如果脚本调用 clearData() 或
clear()
并且DataTransfer
对象的内部拖放数据存储模式标志是读/写,则-
将 clear-was-called 标志设置为 true。如果给定了参数,则将该参数添加到 types-to-clear 列表中。
-
-
如果脚本调用 setData() 或修改项目并且 clear-was-called 标志为 true,则
-
如果 types-to-clear 列表为空,则
-
将 clear-was-called 标志设置为 false,则
-
-
否则,如果 setData() 的
type
参数或新项目的拖放数据项类型字符串在 types-to-clear 列表中找到,则-
将其从列表中删除。如果列表现在为空,则将 clear-was-called 标志设置为 false。
-
-
-
如果脚本调用 getData() 或访问
DataTransferItemList
中的项目并且设置了 clipboard-entry,则-
检查剪贴板数据的序列号是否与 clipboard-entry 匹配。如果剪贴板不再包含相同的条目,则将
DataTransferItemList
对象的内部拖放数据存储模式设置为受保护。
-
警告!监听粘贴事件的恶意脚本可能会设置一个无限循环,以便读取用户将来放置在剪贴板上的内容。在无法使用剪贴板序列号的平台上,应实施其他限制。
-
处理 HTML 粘贴事件
- 输入
-
clipboard-part,要处理的剪贴板部分
-
clipboard-event-data,此事件的
DataTransfer
对象 - 输出
-
无
-
令 new-data 为一个新的
DataTransferItem
, 其拖放数据项种类设置为纯 Unicode 字符串,拖放数据项类型字符串相应地设置为 text/html 或 application/xhtml+xml。 -
从 clipboard-part 中提取标记,并使用相关的解析器构建 DOM 树。
-
如果标记的源 URL 已知,则使用源 URL 作为基础 URL 解析 HREF 和 SRC 属性中的所有相对 URL,并将相应的属性设置为解析后的绝对 URL。
-
如果标记的来源是本地应用程序,则检查是否存在对本地文件和/或操作系统剪贴板内容的其他部分的引用。如果找到此类引用,则对子部分的引用必须使用 cid: URL 方案 [RFC2392] 替换为内容 ID 引用。为此,请按照以下步骤处理每个引用本地文件或剪贴板部分的属性:
这些步骤是必要的吗?我们是否了解支持具有内部引用的多个部分的本机(平台)剪贴板实现?
此功能存在风险,因为尚不清楚是否需要它,并且难以进行跨平台测试。
-
如果 clipboard-event-data 的
items
已经包含对引用的文件或剪贴板部分的条目,则-
将 itemNumber 设置为现有条目的索引。
-
-
否则,
-
令 new-file-data 为一个新的
DataTransferItem
, 其拖放数据项种类设置为 "file",拖放数据项类型字符串设置为文件或剪贴板部分的 MIME 类型(如果已知),如果文件类型未知,则设置为application/octet-stream
。 -
令 file-info 为一个新的
File
对象,其name
设置为 HTML 属性内容的名称部分,lastModified
设置为引用文件的时间戳,如果条目引用剪贴板部分,则设置为 0。 -
将 new-file-data 的内部
File
对象设置为 file-info。 -
将 new-file-data 添加到 clipboard-event-data 的
items
中,并令 itemNumber 为此条目在DataTransferItemList
中的索引。
-
-
更新引用本地文件或剪贴板部分的 DOM 属性,使其包含字符串 'cid:' 后跟 itemNumber。
-
-
序列化处理后的 DOM 并使用生成的 HTML 代码更新 new-data。
-
将 new-data 添加到 clipboard-event-data 的
items
中。