Поделиться через


Формат буфера обмена HTML

Требования к передаче HTML-текста с помощью буфера обмена отличаются в зависимости от сценария. Эта статья связана с вырезанием и вставкой фрагментов HTML-документа. Могут потребоваться требования для передачи целых HTML-документов через буфер обмена; Однако эта статья обусловлена требованием передачи фрагментов выделенного HTML-текста. Таким образом, метод, который требует копирования всего HTML-документа в буфер обмена, рассматривается как слишком тяжелый вес.

Формат буфера обмена CF_HTML позволяет хранить фрагмент необработанного HTML-текста и его контекст (т. е. внешний HTML) в буфере обмена как ASCII. Это позволяет контексту фрагмента HTML, состоящего из всех предыдущих окружающих тегов, проверяться приложением, чтобы окружающие теги фрагмента HTML можно было отметить с их атрибутами. Хотя это зависит от приложений, чтобы решить, как интерпретировать такие фрагменты, некоторые основные рекомендации включены здесь на основе реализаций IE4/MSHTML.

Официальное имя буфера обмена (строка, используемая RegisterClipboardFormat) — "HTML Format".

Описание

CF_HTML — это формат буфера обмена текста, хотя всегда использует кодировку UTF-8. Обратите внимание, что использование UTF-8 здесь является исключением из общего правила, которое API Windows использует UTF-16 для представления текстовых строк, особенно строк, доступных для чтения пользователем (например, локализуемых) строк.

Вы можете описать общий макет или синтаксис буфера обмена CF_HTML в форме псевдо-Backus–Naur следующим образом:

Заметка

Эта грамматика не является нормативным**

<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-код для смещения, могут записывать десять (10) ноль в выходной буфер для каждого ключевого слова (например, StartHTML: 0000000000). Позже, когда точное StartHTML смещение известно (например, 71), программа может перезаписать наиболее правые нули с "71" в буфере (например, в результате StartHTML: 0000000071).

Единственным набором символов, поддерживаемым буфером обмена, является Юникод (UTF-8). Так как первые символы совпадения UTF-8 и ASCII всегда являются ASCII, но байты контекста (начиная с StartHTML) могут использовать любые другие символы, закодированные в UTF-8.

Концы строк в заголовке формата буфера обмена (<br> выше) могут быть представлены CRLF (Windows), LF (Unix) или lone CR (archaic).

Фрагмент, выделение и их контекст

Элемент Заголовки описания Требуется допустимый HTML-код для позиций начального и конечного символов
Контекст StartHTML и EndHTML Да
Фрагмент StartFragment и EndFragment Да
Отбор StartSelection и EndSelection Нет

Контекст

контексте является допустимым, полным HTML-документом, хотя это не означает, что весь исходный HTML-документ, содержащий выбор пользователя, будет перенесен поверх подробного текста; напротив, это может быть минимальный, но хорошо сформированный HTML-документ.

Этот контекст содержит фрагмент и все предыдущие окружающие теги (начальные и конечные теги; указанные выше теги представляют все родительские узлы фрагмента, пока узел HTML). В приведенном выше примере статьи есть полный элемент HTML-<head>, который позволяет использовать элементы <base href=""> и <title>. Например, этот элемент можно вставить, чтобы получить эти дополнительные сведения. Приложение, копируя фрагмент HTML в буфер обмена, может создать элемент <base href="">, чтобы включить его в контекст, если такой элемент еще не присутствует. Таким образом, не абсолютные URI в фрагменте HTML можно разрешить.

Контекст является необязательным, так как достаточная информация включена в фрагмент для базовой вставки фрагмента HTML. Если контекст не хранится, фрагмент хранится только и StartHTML=EndHTML=-1.

Фрагмент

Фрагмент (<fragment-text> выше) содержит допустимый фрагмент HTML.

Допустимый фрагмент HTML состоит из одного внешнего ЭЛЕМЕНТА HTML. Этот элемент может содержать элементы HTML-потомков, если они правильно вложены. Например, фрагмент может быть одним элементом <div>, который содержит 3 <p> элементов. Фрагмент, состоящий из элемента <span>, содержащего три элемента <p>, будет недопустимым, так как элемент <span> (элемент) не может содержать элементы уровня блока в виде дочерних элементов.

Таким образом, фрагмент фактически представляет большую область на экране, в которой пользователь сделал выделение текста (например, для копирования). Выделение содержит выделенный текст, а также открывающиеся теги и атрибуты любого элемента, имеющего конечный тег в выделенном тексте, и конечные теги в конце фрагмента для любого включенного тега начала. Это все сведения, необходимые для базовой вставки фрагмента HTML.

Перед фрагментом следует следовать примечаниям HTML, <!--StartFragment--> и <!--EndFragment-->, чтобы указать, где начинается и заканчивается фрагмент; эти примечания HTML должны использоваться подробныхбез пробелов внутри каждого комментария. Таким образом, начало и конец фрагмента указываются наличием этих комментариев и заголовками StartFragment и EndFragment. Ожидается, что средства будут создавать эти сведения. Эта избыточность является намеренной и была введена для того, чтобы найти начало фрагмента (от числа байтов) и пометить положение фрагмента непосредственно в html-дереве.

Отбор

выбор является необязательным, так как достаточная информация включена в фрагмент для базовой вставки. Если выбор не хранится, оба StartSelection и EndSelection не хранятся в заголовке.

При наличии выделения является точным текстовым диапазоном, выбранным пользователем (в фрагменте); Это добавляет дополнительные сведения в фрагмент, указывая точный выделенный текст, без хорошо сформированных и сбалансированных начальных и конечных тегов.

Помните, что выделения может представлять собой запуск текста, который может начинаться в любом заданном элементе и заканчиваться любой последующим элементом или предком. Следовательно, невозможно представить выделение текста с помощью HTML.

Сценарии

В следующих сценариях описывается, как редактор HTML IE4/MSHTML обрабатывает вырезанные и вставки 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, ака Trident, был обработчиком Internet Explorer), MSHTML обрабатывает копирование подстроки HTML следующим образом:

  1. Пользователь выбирает текст без начальных или конечных пробелов, например"полужирный курсив" из приведенного выше примера.
  2. Чтобы скопировать текст в буфер обмена, пользователь нажимает кнопку "Копировать".

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, элемент 7, элемент 10и элемент 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. Элемент 1
  2. Элемент 2
  3. Элемент 3
  4. Элемент 4
  5. Элемент 5
  6. Элемент 6

Как MSHTML обрабатывает копирование подстроки нумерованного HTML-элемента списка

  1. Пользователь выбирает текст с начала элемента 3, элемента 4и до конца элемента 5. Пользователь вызывает команду Copy.
  2. Следующий 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>

Это будет выглядеть следующим образом:

  1. Элемент 3
  2. Элемент 4
  3. Элемент 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

Пользователь использует мышь для перетаскивания выделения текста, например "Редактор WYSIWYG, который поддерживает: Cut Cop". Как если бы это был обычный текст, этот фрагмент 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" из "Копировать" было удалено.

См. также

буфер обмена