HTML 剪贴板格式
通过剪贴板传输 HTML 文本的要求因方案而异。 本文涉及剪切和粘贴 HTML 文档的片段。 可能需要通过剪贴板传输整个 HTML 文档;但是,本文由传输所选 HTML 文本片段的要求驱动。 因此,需要将整个 HTML 文档复制到剪贴板的方法被视为太重。
CF_HTML
剪贴板格式允许将原始 HTML 文本及其上下文(即外部 HTML)的片段作为 ASCII 存储在剪贴板上。 这允许应用程序检查 HTML 片段的上下文(由前面所有周围的标记组成),以便可以使用其属性来记录 HTML 片段的周围标记。 尽管应用程序决定如何解释此类片段,但此处提供了一些基于 IE4/MSHTML 实现的基本准则。
剪贴板的官方名称(RegisterClipboardFormat
使用的字符串)是“HTML Format
”。
描述
CF_HTML
是文本剪贴板格式,但始终使用 UTF-8 编码。 请注意,此处的 UTF-8 的使用是 Windows API 使用 UTF-16 来表示文本字符串的一般规则(尤其是可本地化的)字符串的例外。
可以使用伪 Backus–Naur 形式描述 CF_HTML
剪贴板的常规布局或语法,如下所示:
注意
此语法不规范**
<cf-html> ::= <description-header> <context>
<context> ::= [<preceding-context>] <fragment> [<trailing-context>]
<description-header> ::= "Version:" <version> <br> ( <header-offset-keyword> ":" <header-offset-value> <br> )*
<header-offset-keyword> ::= "StartHTML" | "EndHTML" | "StartFragment" | "EndFragment" | "StartSelection" | "EndSelection"
<header-offset-value> ::= { Base 10 (decimal) integer string with optional _multiple_ leading zero digits (see "Offset syntax" below) }
<version> ::= "0.9" | "1.0"
<fragment> ::= <fragment-start-comment> <fragment-text> <fragment-end-comment>
<fragment-start-comment> ::= "<!--StartFragment -->"
<fragment-end-comment> ::= "<!--EndFragment -->"
<preceding-context> ::= { Arbitrary HTML }
<trailing-context> ::= { Arbitrary HTML }
<fragment-text> ::= { Arbitrary HTML }
<br> ::= "\r" | "\n" | "\r\n"
说明标头和偏移量
说明标头包括剪贴板版本号和偏移量,指示上下文和片段开始和结束的位置。 说明是 ASCII 文本关键字的列表,后跟一个字符串,并用冒号(:)分隔)。
-
Version
:剪贴板的 vv 版本号。 起始版本Version:0.9
。 从 Windows 10 20H2 开始,现在Version:1.0
。 -
StartHTML
:从剪贴板开头到上下文开头的偏移量(以字节为单位),如果没有上下文,则-1
。 -
EndHTML
:从剪贴板开头到上下文末尾的偏移量(以字节为单位),如果没有上下文,则-1
。 -
StartFragment
:从剪贴板开头到片段开头的偏移量(以字节为单位)。 -
EndFragment
:从剪贴板开头到片段末尾的偏移量(以字节为单位)。 -
StartSelection
:可选。 从剪贴板的开头到所选内容的开头的偏移量(以字节为单位)。 -
EndSelection
:可选。 从剪贴板的开头到所选内容的末尾的偏移量(以字节为单位)。
StartSelection
和 EndSelection
关键字是可选的,如果不希望应用程序生成此信息,则必须省略这两个关键字。
CF_HTML
剪贴板格式的未来修订可能会扩展标头,例如,由于 HTML 从 StartHTML
偏移处开始,因此以后可以添加多个 StartFragment
和 EndFragment
对以支持不连续的片段选择。
偏移语法
为了方便程序生成字节偏移量,偏移值可以选择左填充,其中任意数量的零位 '0'
。 原因是程序嗅探偏移量的 HTML 可能会为每个关键字(例如 StartHTML: 0000000000
)将十(10)零写入其输出缓冲区。 稍后,当确切的 StartHTML
偏移量已知(例如,71),程序可以在缓冲区中使用“71”覆盖最右边的零(例如,导致 StartHTML: 0000000071
)。
剪贴板支持的唯一字符集是 Unicode (UTF-8)。 由于 UTF-8 和 ASCII 的第一个字符匹配,说明始终为 ASCII,但上下文(从 StartHTML
开始)的字节可以使用 UTF-8 中编码的任何其他字符。
剪贴板格式标头(上<br>
)中的行的末尾可以由 CRLF(Windows)、LF(Unix)或孤独的 CR(原型)表示。
片段、所选内容及其上下文
元素 | 说明标头 | 需要对开始和结束字符位置使用有效的 HTML |
---|---|---|
上下文 |
StartHTML 和 EndHTML |
是的 |
片段 |
StartFragment 和 EndFragment |
是的 |
选择 |
StartSelection 和 EndSelection |
不 |
上下文
上下文 是一个有效的、完整的 HTML 文档 -虽然这并不意味着包含用户选择的整个原始源 HTML 文档将逐字执行;相反,它可以是一个最小的,但格式正确的 HTML 文档。
此 上下文 包含 片段 和前面的所有周围标记(开始和结束标记;这些前面的周围标记表示片段的所有父节点,直到 HTML 节点)。 上面的示例文章包含一个完整的 HTML <head>
元素,该元素允许使用 <base href="">
和 <title>
元素。 例如,可以插入此元素以获取此附加信息。 将 HTML 片段复制到剪贴板的应用程序可以选择创建一个 <base href="">
元素,以将其包含在上下文中(如果此类元素尚不存在)。 这样,就可以解析 HTML 片段中的非绝对 URI。
上下文 是可选的,因为片段中包含足够的信息,以便进行 HTML 片段的基本粘贴。 如果未存储上下文,则仅存储片段和 StartHTML=EndHTML=-1
。
片段
片段(上<fragment-text>
)包含有效的 HTML 片段。
有效的 HTML 片段由单个外部 HTML 元素组成。 此元素可能包含子代 HTML 元素,前提是它们正确嵌套。 例如,片段可以是包含 3 个 <p>
元素的单个 <div>
元素。 包含三个 <p>
元素的 <span>
元素组成的片段无效,因为 <span>
元素(元素)不能包含块级元素作为子元素。
因此,片段有效地表示屏幕上 更大的区域,用户在其中进行了文本选择(例如复制)。 所选内容包含所选文本以及任何元素的开始标记和属性,这些元素在所选文本中具有结束标记,以及包含的任何开始标记的片段末尾的结束标记。 这是基本粘贴 HTML 片段所需的所有信息。
片段 前面,后跟 HTML 注释 <!--StartFragment-->
和 <!--EndFragment-->
,以指示片段的开始和结束位置;这些 HTML 注释必须使用 逐字,每个注释本身中没有空格字符。 因此,片段的开始和结尾由这些注释的存在 和 StartFragment
和 EndFragment
标头 表示。 工具应生成此信息。 这种冗余是有意的,引入后能够找到片段的开头(从字节计数),并直接标记片段在 HTML 树中的位置。
选择
选择 是可选的,因为片段中包含足够的信息用于基本粘贴。 如果未存储所选内容,则 StartSelection
和 EndSelection
都不会存储在标头中。
如果存在,则 选择 是用户选择的 确切 文本范围(在 片段中);这将通过指示确切的选定文本、而不 格式正确的开始和结束标记和结束标记以及结束标记来向片段添加更多信息。
请记住,选择 可以表示文本的运行,该文本可在任何给定元素中开始,并在 后续元素或上级元素中结束。 因此,无法使用 HTML 来表示文本选择。
场景
以下方案描述了 IE4/MSHTML HTML 编辑器如何处理 HTML 剪切和粘贴;其他应用程序可能或可能不遵循这些方案。 此处所述的剪贴板格式旨在允许应用程序选择如何正常运行的灵活性。 (这些方案仅显示良好的 HTML,即没有重叠的标记。
方案 1 - HTML 的简单片段
假定以下 HTML 文本:
<body>This is normal. <b>This is bold.</b> <i><b>This is bold italic.</b> This is italic.</i></body>
如下所示:
这是正常的。 这是粗体。这是粗体斜体。这是斜体。
当用户将上述 HTML 文本加载到基于 MSHTML 的应用程序(MSHTML(aka Trident)是 Internet Explorer 的引擎时,MSHTML 将处理复制 HTML 子字符串,如下所示:
- 用户从上面的示例中选择不带任何前导或尾随空格的文本,例如“粗体,这是粗体。
- 若要将文本复制到剪贴板,用户单击“复制”命令按钮。
MSHTML 会将此 HTML 文本放入 Windows 剪贴板,如下所示:
Version:1.0
StartHTML:0121
EndHTML:0272
StartFragment:0006
EndFragment:0106
StartSelection:0180
EndSelection:0225
<html><!--StartFragment--><body>This is normal. <b>This is bold.</b> <i><b>This is bold italic.</b> This is italic.</i></body><!--EndFragment--></html>
方案 2 - HTML 中表的片段
假定以下 HTML 文本:
<BODY><TABLE BORDER><TR><TH ROWSPAN=2>Head1</TH><TD>Item 1</TD><TD>Item 2</TD><TD>Item 3</TD><TD>Item 4</TD></TR><TR><TD>Item 5</TD><TD>Item 6</TD><TD>Item 7</TD><TD>Item 8</TD></TR><TR><TH>Head2</TH><TD>Item 9</TD><TD>Item 10</TD><TD>Item 11</TD><TD>Item 12</TD></TR></TABLE></BODY>
如下所示:
头 1 项目 1 项目 2 项目 3 项目 4 项目 5 项目 6 项目 7 项目 8 头 2 项目 9 项目 10 项目 11 项目 12
MSHTML 如何处理从表复制 HTML 子字符串
当用户使用鼠标选择表格单元格时,项 6、Item 7、Item 10以及 Item 11。 然后,此选择将复制到剪贴板。
以下是剪贴板上的内容(请注意这是 IE4/MSHTML 的解释)。 为了清楚起见,添加了换行符。
<!DOCTYPE
<HTML>
<BODY>
<TABLE BORDER>
<!--StartFragment-->
**<TR>
<TD>Item 6</TD>
<TD>Item 7</TD>
</TR>
<TR>
<TD>Item 10</TD>
<TD>Item 11</TD>
</TR>**
<!--EndFragment-->
</TABLE>
</BODY>
</HTML>
所选内容以 StartSelection
和 EndSelection
分隔,以粗体显示。
方案 3 - 将有序列表的片段粘贴到纯文本 <ol>
假定以下 HTML 文本:
<BODY><OL TYPE="a"><LI>Item 1<LI>Item 2<LI>Item 3<LI>Item 4<LI>Item 5<LI>Item 6</OL></BODY>
如下所示:
- 项目 1
- 项目 2
- 项目 3
- 项目 4
- 项目 5
- 项目 6
MSHTML 如何处理复制 HTML 编号列表项的子字符串
- 用户从 项 3开始,到第 4 项 ,到 第 5 项的末尾进行文本选择。 用户调用 Copy 命令。
- 以下 HTML 位于剪贴板(为清楚起见而添加换行符) -
<!--Star/EndFragment -->
注释的精确位置取决于用户如何处理其浏览器的文本选择逻辑:
<html>
<body>
<ol>
<!-- StartFragment-->
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<!-- EndFragment-->
</ol>
</body>
</html>
如果此片段现在粘贴到空文档中,将创建以下 HTML:
<body>
<ol>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ol>
</body>
如下所示:
- 项目 3
- 项目 4
- 项目 5
方案 5 - 粘贴部分选定的区域
假定以下 HTML 文本:
<p>IE4/MSHTML is a WYSIWYG Editor that supports:</p>
<ul><li>Cut<li>Copy<li>Paste</ul>
<p>This is a Great Tool!</p>
如下所示:
IE4/MSHTML 是支持以下项的 WYSIWYG 编辑器:
- 切
- 复制
- 糊
这是一个很好的工具!
MSHTML 如何处理复制 HTML 列表项的子字符串
用户使用鼠标拖动文本选择,例如“支持:剪切 Cop 的 WYSIWYG 编辑器”。 就像它是纯文本一样,该选择将类似于此损坏的 HTML 片段:
WYSIWYG Editor, which supports:</p>
<ul>
<li>Cut</li>
<li>Cop
当用户按下“复制”命令按钮时,其剪贴板将如下所示(为了清楚起见,添加了换行符;粗体文本表示用户实际选择的内容):
<html> <body> <!-- StartFragment--> <p>WYSIWYG Editor, which supports</p> <ul> <li>Cut</li> <li>Cop</li> </ul> <!-- EndFragment--> </body> </html>
请注意:
- 删除了“WYSIWYG”之前的文本。
- 列表项(
<li>Paste</li>
)已删除,因为用户选择中没有任何列表项。 - “复制”中的“y”已删除。