Compartir a través de


Formato del Portapapeles HTML

Los requisitos para transferir texto HTML mediante el Portapapeles difieren en función del escenario. Este artículo se ocupa de cortar y pegar fragmentos de un documento HTML. Puede haber requisitos para transferir documentos HTML completos a través del Portapapeles; sin embargo, este artículo se basa en un requisito para transferir fragmentos de texto HTML seleccionado. Por lo tanto, un método que requería copiar todo el documento HTML en el Portapapeles se considera demasiado pesado.

El CF_HTML formato del Portapapeles permite almacenar un fragmento de texto HTML sin formato y su contexto (es decir, HTML externo) en el Portapapeles como ASCII. Esto permite examinar el contexto del fragmento HTML, que consta de todas las etiquetas circundantes anteriores, para que una aplicación pueda observar las etiquetas circundantes del fragmento HTML con sus atributos. Aunque depende de las aplicaciones decidir cómo interpretar estos fragmentos, aquí se incluyen algunas directrices básicas basadas en implementaciones de IE4/MSHTML.

El nombre oficial del Portapapeles (la cadena usada por RegisterClipboardFormat) es "HTML Format".

Descripción

CF_HTML es un formato de Portapapeles de texto, aunque siempre use la codificación UTF-8. Tenga en cuenta que el uso de UTF-8 aquí es una excepción a la regla general que la API de Windows usa UTF-16 para representar cadenas de texto, especialmente cadenas legibles (es decir, localizables).

Puede describir el diseño general o la sintaxis del portapapeles de CF_HTML en forma pseudo-Backus-Naur de la siguiente manera:

Nota

Esta gramática no es 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"

Descripción Encabezados y desplazamientos

El encabezado description incluye el número de versión y los desplazamientos del Portapapeles, que indican dónde se inicia y finaliza el contexto y el fragmento. La descripción es una lista de palabras clave de texto ASCII seguidas de una cadena y separadas por dos puntos (:).

  • Version: número de versión vv del Portapapeles. La versión inicial es Version:0.9. A partir de Windows 10 20H2, ahora se Version:1.0.
  • StartHTML: desplazamiento (en bytes) desde el principio del Portapapeles hasta el inicio del contexto o -1 si no hay ningún contexto.
  • EndHTML: desplazamiento (en bytes) desde el principio del Portapapeles hasta el final del contexto o -1 si no hay ningún contexto.
  • StartFragment: desplazamiento (en bytes) desde el principio del Portapapeles hasta el inicio del fragmento.
  • EndFragment: desplazamiento (en bytes) desde el principio del Portapapeles hasta el final del fragmento.
  • StartSelection: opcional. Desplazamiento (en bytes) desde el principio del Portapapeles hasta el inicio de la selección.
  • EndSelection: opcional. Desplazamiento (en bytes) desde el principio del Portapapeles hasta el final de la selección.

Las palabras clave StartSelection y EndSelection son opcionales y deben omitirse si no desea que la aplicación genere esta información.

Las revisiones futuras del formato del Portapapeles de CF_HTML pueden extender el encabezado, por ejemplo, ya que el CÓDIGO HTML comienza en el desplazamiento StartHTML, se podrían agregar varios pares de StartFragment y EndFragment más adelante para admitir la selección no contigua de fragmentos.

Sintaxis de desplazamiento

Para la comodidad de los programas que generan los desplazamientos de bytes, los valores de desplazamiento pueden ser opcionalmente rellenados a la izquierda con una cantidad arbitraria de cero dígitos '0'. La razón de esto es que los programas que examinan el HTML de los desplazamientos podrían escribir diez (10) ceros en su búfer de salida para cada palabra clave (por ejemplo, StartHTML: 0000000000). Más adelante, cuando se conoce el desplazamiento exacto StartHTML (por ejemplo, 71), el programa puede sobrescribir los ceros más a la derecha con "71" en el búfer (por ejemplo, lo que da como resultado StartHTML: 0000000071).

El único juego de caracteres admitido por el Portapapeles es Unicode (UTF-8). Dado que los primeros caracteres de UTF-8 y ASCII coinciden, la descripción siempre es ASCII, pero los bytes del contexto (a partir de StartHTML) podrían usar cualquier otro carácter codificado en UTF-8.

Los extremos de las líneas en el encabezado de formato del Portapapeles (<br> anterior) pueden representarse mediante CRLF (Windows), LF (Unix) o CR solitario (arcaico).

El fragmento, la selección y su contexto

Elemento Encabezados de descripción Requiere HTML válido para las posiciones de caracteres de inicio y finalización
Contexto StartHTML y EndHTML
Fragmento StartFragment y EndFragment
Selección StartSelection y EndSelection No

Contexto

El contexto es un documento HTML válido y completo, aunque esto no significa que todo el documento HTML de origen original que contenga la selección del usuario se llevará a cabo textualmente; por el contrario, puede ser un documento HTML mínimo, pero bien formado.

Este contexto contiene el de fragmento de y todas las etiquetas circundantes anteriores (etiquetas iniciales y finales; estas etiquetas adyacentes anteriores representan todos los nodos primarios del fragmento, hasta el nodo HTML). El artículo de ejemplo anterior tiene un elemento html completo <head> que permite el uso de elementos <base href=""> y <title>. Por ejemplo, este elemento se puede insertar para obtener esta información adicional. Una aplicación que copia un fragmento de HTML en el Portapapeles puede optar por crear un elemento <base href=""> para incluirlo en el contexto si dicho elemento aún no está presente. De este modo, se pueden resolver los URI no absolutos del fragmento HTML.

El de contexto de es opcional, ya que se incluye información suficiente en el fragmento para el pegado básico de un fragmento HTML. Si el contexto no se almacena, el fragmento solo se almacena y el StartHTML=EndHTML=-1.

Fragmento

El fragmento de (<fragment-text> anterior) contiene un fragmento HTML válido.

Un fragmento HTML válido consta de un único elemento HTML externo. Este elemento puede contener elementos HTML descendientes siempre que estén anidados correctamente. Por ejemplo, un fragmento podría ser un único elemento de <div> que contiene 3 elementos <p>. Un fragmento que consta de un elemento de <span> que contiene tres elementos <p> no sería válido porque un elemento <span> (un elemento) no puede contener elementos de nivel de bloque como elementos secundarios.

Por lo tanto, el fragmento representa eficazmente el área mayor en pantalla, dentro de la cual el usuario realizó su selección de texto (para copiar, por ejemplo). La selección contiene el texto seleccionado más las etiquetas de apertura y los atributos de cualquier elemento que tenga una etiqueta final dentro del texto seleccionado y etiquetas finales al final del fragmento para cualquier etiqueta de inicio incluida. Esta es toda la información necesaria para pegar un fragmento HTML básico.

El de fragmento de debe ir precedido y seguido de los comentarios HTML <!--StartFragment--> y <!--EndFragment--> para indicar dónde comienza y termina el fragmento; estos comentarios HTML deben usarse textual, sin caracteres de espacio en blanco dentro de cada comentario. Por lo tanto, el inicio y el final del fragmento se indican mediante la presencia de estos comentarios y por los encabezados StartFragment y EndFragment. Se espera que las herramientas generen esta información. Esta redundancia es intencionada y se introdujo para poder encontrar el inicio del fragmento (del recuento de bytes) y marcar la posición del fragmento directamente en el árbol HTML.

Selección

El de selección es opcional porque se incluye suficiente información en el fragmento para el pegado básico. Si la selección no está almacenada, tanto StartSelection como EndSelection no se almacenan en el encabezado.

Si está presente, el de selección de es el intervalo de texto exacto que el usuario ha seleccionado (dentro del fragmento de ); esto agrega más información al fragmento indicando el texto seleccionado exacto, sin las etiquetas iniciales y finales bien formadas y equilibradas y las etiquetas finales.

Recuerde que el de selección de puede representar una ejecución de texto que puede iniciarse en cualquier elemento dado y terminar en cualquier elemento posterior o antecesor. Por lo tanto, es imposible representar una selección de texto mediante HTML.

Escenarios

En los escenarios siguientes se describe cómo el editor HTML IE4/MSHTML controla el corte y pega HTML; Otras aplicaciones pueden seguir o no estos escenarios. El formato del Portapapeles que se describe aquí está pensado para permitir la flexibilidad de cómo una aplicación elige funcionar. (Estos escenarios solo muestran un código HTML bueno, es decir, ninguna etiqueta superpuesta).

Escenario 1: fragmento simple de HTML

Supongamos que el texto HTML siguiente:

<body>This is normal. <b>This is bold.</b> <i><b>This is bold italic.</b> This is italic.</i></body>

Esto aparecerá de la siguiente manera:

Esto es normal. Esta es negrita.Esta cursiva es negrita.Esta es cursiva.

Cuando el usuario ha cargado el texto HTML anterior en una aplicación basada en MSHTML (MSHTML, también conocida como Trident, era el motor de Internet Explorer), MSHTML controla la copia de una subcadena de HTML de la siguiente manera:

  1. El usuario selecciona un texto sin espacios en blanco iniciales o finales, por ejemplo, "negrita This is bold italic This" en el ejemplo anterior.
  2. Para copiar el texto en el Portapapeles, el usuario hace clic en el botón Copiar comando.

MSHTML colocará este texto HTML en el Portapapeles de Windows como se indica a continuación:

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>

Escenario 2: Fragmento de una tabla en HTML

Supongamos que el texto HTML siguiente:

<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>

Esto aparecerá de la siguiente manera:

Cabeza 1 Elemento 1 Elemento 2 Elemento 3 Elemento 4
Elemento 5 Elemento 6 Elemento 7 Elemento 8
Cabeza 2 Elemento 9 Elemento 10 Elemento 11 Elemento 12

Cómo MSHTML controla la copia de una subcadena de HTML desde una tabla

Cuando el usuario usa el mouse para realizar una selección de texto que abarque las celdas de la tabla elemento 6, elemento 7, elemento 10y elemento 11. A continuación, esta selección se copia en el Portapapeles.

Lo siguiente es lo que estará en el Portapapeles (tenga en cuenta que esta es la interpretación de IE4/MSHTML). Se han agregado saltos de línea para mayor claridad.

<!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>

La selección, tal como está delimitada por StartSelection y EndSelection, se muestra en negrita.

Escenario 3: pegar un fragmento de una lista ordenada <ol> en texto sin formato

Supongamos que el texto HTML siguiente:

<BODY><OL TYPE="a"><LI>Item 1<LI>Item 2<LI>Item 3<LI>Item 4<LI>Item 5<LI>Item 6</OL></BODY>

Esto aparecerá de la siguiente manera:

  1. Elemento 1
  2. Elemento 2
  3. Elemento 3
  4. Elemento 4
  5. Elemento 5
  6. Elemento 6

Cómo MSHTML controla la copia de una subcadena de elementos de lista numerados HTML

  1. El usuario realiza una selección de texto desde el principio de elemento 3, hasta elemento 4y hasta el final de elemento 5. El usuario invoca el comando Copy.
  2. El código HTML siguiente está en el Portapapeles (saltos de línea agregados para mayor claridad): la ubicación precisa de los comentarios <!--Star/EndFragment --> depende de cómo el usuario controle la lógica de selección de texto del explorador:
<html>
<body>
<ol>
<!-- StartFragment-->
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<!-- EndFragment-->
</ol>
</body>
</html>

Si este fragmento se pegara ahora en un documento vacío, se creará el código HTML siguiente:

<body>
<ol>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ol>
</body>

Esto aparecerá de la siguiente manera:

  1. Elemento 3
  2. Elemento 4
  3. Elemento 5

Escenario 5: Pegar una región parcialmente seleccionada

Supongamos que el texto HTML siguiente:

<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>

Esto aparecerá de la siguiente manera:

IE4/MSHTML es un editor WYSIWYG que admite:

  • Cortar
  • Copiar
  • Pegar

¡Esta es una gran herramienta!

Cómo MSHTML controla la copia de una subcadena de elementos de lista HTML

El usuario usa el mouse para arrastrar una selección de texto, por ejemplo, "EDITOR WYSIWYG que admite: Cut Cop". Como si fuera texto sin formato, esa selección tendría el siguiente fragmento HTML roto:

WYSIWYG Editor, which supports:</p>
<ul>
  <li>Cut</li>
  <li>Cop

Cuando el usuario presiona el botón Copiar comando, su Portapapeles tendrá este aspecto (se han agregado saltos de línea para mayor claridad; el texto en negrita denota lo que el usuario seleccionó realmente):

<html>
<body>
<!-- StartFragment-->
<p>WYSIWYG Editor, which supports</p>
<ul>
	<li>Cut</li>
	<li>Cop</li>
</ul>
<!-- EndFragment-->
</body>
</html>

Observe que:

  • Se quitó el texto anterior a "WYSIWYG".
  • El elemento de lista (<li>Paste</li>) se quitó porque no estaba en la selección del usuario.
  • Se quitó "y" de "Copy".

Consulte también

del Portapapeles