Формат буфера обмена HTML
Требования к передаче HTML-текста с помощью буфера обмена отличаются в зависимости от сценария. Эта статья связана с вырезанием и вставкой фрагментов HTML-документа. Могут потребоваться требования для передачи целых HTML-документов через буфер обмена; Однако эта статья обусловлена требованием передачи фрагментов выделенного HTML-текста. Таким образом, метод, который требует копирования всего HTML-документа в буфер обмена, рассматривается как слишком тяжелый вес.
Формат CF_HTML
буфера обмена позволяет хранить фрагмент необработанного HTML-текста и его контекст (т. е. внешний HTML) в буфере обмена как ASCII. Это позволяет контексту фрагмента HTML, состоящего из всех предыдущих окружающих тегов, проверяться приложением, чтобы окружающие теги фрагмента HTML можно было отметить с их атрибутами. Хотя это зависит от приложений, чтобы решить, как интерпретировать такие фрагменты, некоторые основные рекомендации включены здесь на основе реализаций IE4/MSHTML.
Официальное имя буфера обмена (строка, используемая RegisterClipboardFormat
) — "HTML Format
".
Description
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) или одиноким CR (архаичным).
Фрагмент, выделение и их контекст
Элемент | Заголовки описания | Требуется допустимый HTML-код для позиций начального и конечного символов |
---|---|---|
Контекст | StartHTML и EndHTML . |
Да |
Фрагмент | StartFragment и EndFragment . |
Да |
Выбор | StartSelection и EndSelection . |
No |
Контекст
Контекст является допустимым, полным 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.
Перед фрагментом следует примечания <!--StartFragment-->
HTML и <!--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, был обработчиком Интернета Обозреватель), 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 из таблицы
Когда пользователь использует мышь для выделения текста, охватывающего ячейки таблицы Item 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>
Выделение, разделенное по разделителям иEndSelection
, отображается полужирным шрифтомStartSelection
.
Сценарий 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
Пользователь использует мышь для перетаскивания выделения текста, например "Редактор 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" из "Копировать" было удалено.