Formato da área de transferência HTML
Os requisitos para transferir texto HTML por meio da área de transferência diferem dependendo do cenário. Este artigo está preocupado com cortar e colar fragmentos de um documento HTML. Pode haver requisitos para transferir documentos HTML inteiros através da área de transferência; no entanto, este artigo é impulsionado por um requisito para transferir fragmentos de texto HTML selecionado. Como tal, um método que exigia que todo o documento HTML fosse copiado para a área de transferência é visto como muito pesado.
O formato CF_HTML
da área de transferência permite que um fragmento de texto HTML bruto e seu contexto (ou seja, HTML externo) sejam armazenados na área de transferência como ASCII. Isso permite que o contexto do fragmento HTML, que consiste em todas as tags ao redor anteriores, seja examinado por um aplicativo para que as tags ao redor do fragmento HTML possam ser anotadas com seus atributos. Embora caiba aos aplicativos decidir como interpretar tais fragmentos, algumas diretrizes básicas estão incluídas aqui com base em implementações IE4/MSHTML.
O nome oficial da área de transferência (a string usada por RegisterClipboardFormat
) é "HTML Format
".
Descrição
CF_HTML
é um formato de área de transferência de texto, embora sempre usando codificação UTF-8. Observe que o uso de UTF-8 aqui é uma exceção à regra geral de que a API do Windows usa UTF-16 para representar cadeias de texto, especialmente cadeias de caracteres legíveis por humanos (ou seja, localizáveis).
Você pode descrever o layout geral ou a sintaxe da área de transferência CF_HTML
na forma pseudo-Backus-Naur da seguinte forma:
Observação
Esta gramática não é normativa**
<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"
Descrição Cabeçalhos e Deslocamentos
O cabeçalho da descrição inclui o número da versão da área de transferência e deslocamentos, indicando onde o contexto e o fragmento começam e terminam. A descrição é uma lista de palavras-chave de texto ASCII seguidas por uma cadeia de caracteres e separadas por dois pontos (:).
-
Version
: vv número da versão da área de transferência. A versão inicial éVersion:0.9
. A partir do Windows 10 20H2 isso agora éVersion:1.0
. -
StartHTML
: Deslocamento (em bytes) do início da área de transferência para o início do contexto, ou-1
se não houver contexto. -
EndHTML
: Deslocamento (em bytes) do início da área de transferência para o final do contexto, ou-1
se não houver contexto. -
StartFragment
: Deslocamento (em bytes) do início da área de transferência para o início do fragmento. -
EndFragment
: Deslocamento (em bytes) do início da área de transferência até o final do fragmento. -
StartSelection
: Opcional. Deslocamento (em bytes) do início da área de transferência para o início da seleção. -
EndSelection
: Opcional. Deslocamento (em bytes) do início da área de transferência até o final da seleção.
As palavras-chave StartSelection
e EndSelection
são opcionais e devem ser omitidas se você não quiser que o aplicativo gere essas informações.
Revisões futuras do formato CF_HTML
área de transferência podem estender o cabeçalho, por exemplo, uma vez que o HTML começa no deslocamento StartHTML
, em seguida, vários pares StartFragment
e EndFragment
podem ser adicionados posteriormente para suportar a seleção não contígua de fragmentos.
Sintaxe de deslocamento
Para a conveniência dos programas que geram os deslocamentos de bytes, os valores de deslocamento podem ser opcionalmente acolchoados à esquerda com uma quantidade arbitrária de zero dígitos '0'
. A razão para isso é que os programas que farejam o HTML para os deslocamentos podem escrever dez (10) zeros em seu buffer de saída para cada palavra-chave (por exemplo, StartHTML: 0000000000
). Mais tarde, quando o deslocamento exato do StartHTML
é conhecido (digamos, 71), o programa pode substituir os zeros mais à direita por "71" no buffer (por exemplo, resultando em StartHTML: 0000000071
).
O único conjunto de caracteres suportado pela área de transferência é Unicode (UTF-8). Como os primeiros caracteres de UTF-8 e ASCII correspondem, a descrição é sempre ASCII, mas os bytes do contexto (começando em StartHTML
) podem estar usando quaisquer outros caracteres codificados em UTF-8.
As extremidades das linhas no cabeçalho do formato da área de transferência (<br>
acima) podem ser representadas por CRLF (Windows), LF (Unix) ou CR solitário (arcaico).
O fragmento, a seleção e seu contexto
Elemento | Cabeçalhos de descrição | Requer HTML válido para posições de caracteres iniciais e finais |
---|---|---|
Contexto |
StartHTML e EndHTML |
Sim |
Fragmento |
StartFragment e EndFragment |
Sim |
Seleção |
StartSelection e EndSelection |
Não |
Contexto
O contexto é um documento HTML válido e completo - embora isso não signifique que todo o documento HTML de origem original contendo a seleção do usuário será transportado literalmente; pelo contrário, pode ser um documento HTML mínimo, mas bem formado.
Este contexto contém o de fragmento e todas as tags circundantes anteriores (tags start e end; essas tags circundantes anteriores representam todos os nós pai do fragmento, até o nó HTML). O artigo de exemplo acima tem um elemento HTML <head>
completo que permite o uso de elementos <base href="">
e <title>
. Por exemplo, este elemento pode ser inserido para obter esta informação adicional. Um aplicativo que copia um fragmento de HTML para a área de transferência pode optar por criar um elemento <base href="">
para incluí-lo no contexto, se esse elemento ainda não estiver presente. Dessa forma, URIs não absolutos no fragmento HTML podem ser resolvidos.
A de contexto é opcional, pois informações suficientes são incluídas no fragmento para que a colagem básica de um fragmento HTML ocorra. Se o contexto não for armazenado, o fragmento será armazenado apenas e o StartHTML=EndHTML=-1
.
Fragmento
O fragmento (<fragment-text>
acima) contém um fragmento HTML válido.
Um válido fragmento HTML consiste em um único elemento HTML externo. Este elemento pode conter elementos HTML descendentes, desde que estejam aninhados corretamente. Por exemplo, um fragmento pode ser um único elemento <div>
que contém 3 elementos <p>
. Um fragmento que consiste em um elemento <span>
que contém três elementos <p>
seria inválido porque um elemento <span>
(um elemento ) não pode conter elementos de nível de bloco como filhos.
Assim, o fragmento representa efetivamente a maior área na tela, na qual o usuário fez sua seleção de texto (para copiar, por exemplo). A seleção contém o texto selecionado mais as tags de abertura e atributos de qualquer elemento que tenha uma marca final dentro do texto selecionado e tags finais no final do fragmento para qualquer tag inicial incluída. Esta é toda a informação necessária para a colagem básica de um fragmento HTML.
O do fragmento deve ser precedido e seguido pelos comentários HTML <!--StartFragment-->
e <!--EndFragment-->
para indicar onde o fragmento começa e termina; esses comentários HTML devem ser usados literais , sem caracteres de espaço em branco dentro de cada comentário em si. Assim, o início e o fim do fragmento são indicados pela presença desses comentários e pelos cabeçalhos StartFragment
e EndFragment
. Espera-se que as ferramentas produzam essas informações. Essa redundância é intencional e foi introduzida para poder encontrar o início do fragmento (a partir da contagem de bytes) e marcar a posição do fragmento diretamente na árvore HTML.
Seleção
O de seleção de é opcional porque informações suficientes são incluídas no fragmento para a colagem básica. Se a seleção não estiver armazenada, tanto StartSelection
quanto EndSelection
não serão armazenadas no cabeçalho.
Se presente, o de seleção de é o intervalo exato de texto que o usuário selecionou (dentro do de fragmento); Isso adiciona mais informações ao fragmento, indicando o texto selecionado exato sem as tags de início e fim bem formadas e equilibradas e as tags de fim.
Lembre-se, o de seleção pode representar uma série de texto que pode começar em qualquer elemento e terminar em qualquer elemento subsequente - ou ancestral. Consequentemente, é impossível representar uma seleção de texto usando HTML.
Cenários
Os cenários a seguir descrevem como o editor de HTML do IE4/MSHTML lida com o corte e colagem de HTML; Outros aplicativos podem ou não seguir esses cenários. O formato da área de transferência descrito aqui destina-se a permitir flexibilidade para a forma como uma aplicação escolhe funcionar. (Esses cenários mostram apenas um bom HTML, ou seja, sem tags sobrepostas.)
Cenário 1 - Fragmento simples de HTML
Suponha o seguinte texto HTML:
<body>This is normal. <b>This is bold.</b> <i><b>This is bold italic.</b> This is italic.</i></body>
Isso aparecerá da seguinte forma:
Isto é normal. Isto é ousado.Este texto está em negrito e itálico.Isto é itálico.
Quando o usuário carregou o texto HTML acima em um aplicativo baseado em MSHTML (MSHTML, também conhecido como Trident, era o mecanismo do Internet Explorer), o MSHTML manipula a cópia de uma substring de HTML da seguinte maneira:
- O usuário seleciona um texto sem qualquer espaço em branco à esquerda ou à direita, por exemplo, "negrito Isto é negrito itálico Isto" do exemplo acima.
- Para copiar o texto para a área de transferência, o usuário clica no botão de comando Copiar.
MSHTML colocará esse texto HTML na área de transferência do Windows da seguinte maneira:
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>
Cenário 2 - Fragmento de uma tabela em HTML
Suponha o seguinte texto 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>
Isso aparecerá da seguinte forma:
Cabeça 1 Ponto 1 Ponto 2 Ponto 3 Ponto 4 Ponto 5 Ponto 6 Ponto 7 Ponto 8 Cabeça 2 Ponto 9 Ponto 10 Ponto 11 Ponto 12
Como MSHTML lida com a cópia de uma substring de HTML de uma tabela
Quando o usuário usa o mouse para fazer uma seleção de texto cobrindo as células da tabela Item 6, Item 7, Item 10e Item 11. Essa seleção é então copiada para a área de transferência.
O que se segue é o que estará na área de transferência (note que esta é a interpretação do IE4/MSHTML). Foram adicionadas quebras de linha para maior clareza.
<!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>
A seleção, conforme delimitada por StartSelection
e EndSelection
, é mostrada em negrito.
Cenário 3 - Colando um fragmento de uma lista ordenada <ol>
em texto sem formatação
Suponha o seguinte texto 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>
Isso aparecerá da seguinte forma:
- Ponto 1
- Ponto 2
- Ponto 3
- Ponto 4
- Ponto 5
- Ponto 6
Como o MSHTML lida com a cópia de uma subcadeia de caracteres de itens de lista numerados HTML
- O usuário faz uma seleção de texto desde o início de item 3, passando por item 4, e até o final de item 5. O usuário invoca o comando Copiar.
- O HTML a seguir está na área de transferência (quebras de linha adicionadas para clareza) - a localização precisa dos comentários
<!--Star/EndFragment -->
depende de como o usuário lidou com a lógica de seleção de texto do navegador:
<html>
<body>
<ol>
<!-- StartFragment-->
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<!-- EndFragment-->
</ol>
</body>
</html>
Se este fragmento for colado em um documento vazio, o seguinte HTML será criado:
<body>
<ol>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ol>
</body>
Isso aparecerá da seguinte forma:
- Ponto 3
- Ponto 4
- Ponto 5
Cenário 5 - Colando uma região parcialmente selecionada
Suponha o seguinte texto 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>
Isso aparecerá da seguinte forma:
IE4/MSHTML é um editor WYSIWYG que suporta:
- Corte
- Copiar
- Colar
Esta é uma ótima ferramenta!
Como o MSHTML lida com a cópia de uma subcadeia de caracteres de itens de lista HTML
O usuário usa o mouse para arrastar uma seleção de texto, por exemplo, "WYSIWYG Editor que suporta: Cut Cop". Como se fosse texto simples, essa seleção se pareceria com este fragmento HTML quebrado:
WYSIWYG Editor, which supports:</p>
<ul>
<li>Cut</li>
<li>Cop
Quando o usuário pressiona o botão de comando Copiar, sua área de transferência terá esta aparência (quebras de linha foram adicionadas para clareza; o texto em negrito indica o que o usuário realmente selecionou):
<html> <body> <!-- StartFragment--> <p>WYSIWYG Editor, which supports</p> <ul> <li>Cut</li> <li>Cop</li> </ul> <!-- EndFragment--> </body> </html>
Observe que:
- O texto anterior a "WYSIWYG" foi removido.
- O item da lista (
<li>Paste</li>
) foi removido, pois nenhum deles estava na seleção do usuário. - O "y" de "Copiar" foi removido.