web-dev-qa-db-fra.com

Comment afficher du code HTML brut en PRE ou quelque chose de similaire, mais sans y échapper

J'aimerais afficher du HTML brut. Nous savons tous qu'il faut échapper à chaque "<" et ">" comme ceci

     <PRE> this is a test  &ltDIV&gt </PRE>

Cependant, je ne veux pas faire cela. Je voudrais un moyen de garder le code HTML tel quel (puisqu'il est plus facile à lire (dans l'éditeur) et de le copier et de le réutiliser moi-même comme code HTML, sans avoir à changez-le à nouveau ou utilisez 2 versions du même code, l'une échappée et l'autre non échappée).

Existe-t-il un environnement plus "brut" que PRE qui pourrait permettre cela? Il n'est donc pas nécessaire de continuer à éditer le HTML et à tout changer à chaque fois qu'ils veulent montrer du code HTML brut, peut-être en HTML5?

Quelque chose comme <REALLY_REALLY_VERBATIM> ...... </<REALLY_REALLY_VERBATIM>

capture d'écran

La solution javascript ne fonctionne pas sur FF 21, voici une capture d'écran enter image description here

capture d'écran 2

La première solution ne fonctionne toujours pas sur Firefox, voici une capture d'écran enter image description here

57
Robert H

Vous pouvez utiliser l'élément xmp, voir À quoi servait la balise <XMP>?? . Il est en HTML depuis le début et est supporté par tous les navigateurs. Les spécifications ne sont pas claires, mais HTML5 CR le décrit toujours et demande aux navigateurs de le prendre en charge (bien qu'il indique également aux auteurs de ne pas l'utiliser, mais il ne peut pas vraiment vous en empêcher).

Tout ce qui se trouve à l'intérieur de xmp est pris en tant que tel, aucune balise (balises ou références de caractères) n'y est reconnue, sauf, pour une raison apparente, la balise de fin de l'élément lui-même, </xmp>.

Sinon, xmp est rendu comme pre.

Lorsque vous utilisez "réel XHTML", c’est-à-dire que XHTML est utilisé avec un type de support XML (ce qui est rare), les règles d’analyse syntaxique spéciales ne s’appliquent pas. xmp est donc traité comme pre. Mais en "vrai XHTML", vous pouvez utiliser une section CDATA, ce qui implique des règles d'analyse similaires. Il n’a pas de formatage particulier, vous voudrez donc probablement l’envelopper dans un élément pre:

<pre><![CDATA[
This is a demo, tags like <p> will
appear literally.
]]></pre>

Je ne vois pas comment vous pourriez combiner xmp et la section CDATA pour obtenir un balisage dit polyglotte

90
Jukka K. Korpela

Essentiellement, la question initiale peut être décomposée en 2 parties:

  • Objectif principal/défi: incorporer (/ transporter) un extrait de code formaté brut (tout type de code) dans le balisage d'une page Web (pour un copier/coller/éditer simple car aucun encodage/échappement n'est généré)
  • afficher/restituer correctement cet extrait de code (éventuellement le modifier) ​​dans le navigateur

La réponse courte (mais) ambiguë est: vous ne pouvez pas , ... mais vous peut (se rapprocher).
(Je sais, ce sont 3 réponses contradictoires, alors continuez à lire ...)

(polyglot) (x) (ht) ml Les langages de balisage reposent sur le wrapping (presque) de tout ce qui se situe entre les balises/caractères de début/fin et de fin/fin.
Donc, pour incorporer any une sorte de code/extrait brut dans votre langage de balisage, il faudra toujours échapper/encoder chaque instance (à l'intérieur de cet extrait) qui ressemble au caractère (-quence) qui ferait fermer l'élément 'conteneur' d'emballage dans le balisage. ( Au cours de cet article, je parlerai de ceci sous le nom de règle n ° 1 .)
Pensez à "some "data" here" Ou <i>..close italics with '</i>'-tag</i>, Où il est évident que vous devez échapper/encoder (quelque chose dans) </i Et " (Ou changer Le caractère de citation du conteneur de " à ').

Donc, à cause de la règle n ° 1, vous ne pouvez pas 'incorporez' n'importe quel ' extrait de code brut inconnu dans le balisage.
Parce que, si on doit échapper/encoder même un caractère à l'intérieur de l'extrait de code brut, cet extrait de code ne serait plus le même 'code brut pur' original que tout le monde peut copier/coller/éditer dans le balisage du document sans plus réfléchir. Cela conduirait à un balisage mal formé/illégal et Mojibake (principalement) à cause d'entités.
En outre, devrait cet extrait contient de tels caractères, vous encore avez besoin de javascript pour "traduire" ce caractère (séquence) à partir de ( et à) c'est une représentation échappée/encodée pour afficher l'extrait correctement dans la 'page Web' (pour copier/coller/éditer).

Cela nous amène à (certains) des types de données spécifiés par les langages de balisage. Ces types de données définissent essentiellement ce qui est considéré comme des "caractères valides" et leur signification (par balise, propriété, etc.):

  • PCDATA (DATA analysé): développera les entités et on devra échapper à <, & (et > selon le langage/la version du balisage).
    La plupart des balises comme body, div, pre, etc, mais aussi textarea (jusqu'à HTML5) relèvent de ce type.
    Ainsi, non seulement vous devez encoder toutes les séquences de caractères de fermeture du conteneur dans l'extrait de code, vous devez également encoder tous les <, & (, >) caractères (au minimum).
    Inutile de dire que coder/échapper à autant de caractères sort du cadre de cet objectif consistant à incorporer un extrait brut dans le balisage.
    '.. Mais une zone de texte semble fonctionner ...', oui, soit à cause du moteur d'erreur du navigateur qui tente d'en tirer quelque chose, soit à cause de HTML5:

  • RCDATA (données de caractère remplaçables): ne traitera pas les balises à l'intérieur du texte comme des balises (elles sont néanmoins régies par la règle 1), il n'est donc pas nécessaire de coder < (>). MAIS les entités sont toujours développées, donc elles et les "esperluettes ambigus" (&) Nécessitent une attention particulière.
    Le actuelLa spécification HTML5 indique que la zone de texte est maintenant un champ RCDATA et (quote):

    Le texte des éléments raw text Et RCDATA ne doit pas contenir aucune occurrence de la chaîne "</" ( U + 003C SIGNE MOINS, U + 002F SOLIDUS) suivis de caractères ne faisant pas la distinction entre les majuscules et les minuscules, avec le nom de balise de l'élément suivi de l'un des caractères U + 0009 TABULATION DE CARACTERES (onglet), U + 000A LINE FEED (LF), U + 000C ALIMENT POUR FORMULAIRES (FF), U + 000D RETOUR DE CHARIOT (CR), U + 0020 ESPACE, U + 003E GRAND SIGNE (>) ou U + 002F SOLIDUS (/).

    Ainsi, peu importe ce qui se passe, textarea a besoin d’un gestionnaire de traduction d’entités lourd ou bien il le sera éventuellement Mojibake sur les entités!

  • CDATA (Données de caractère) ne traitera pas les balises à l'intérieur du texte comme des balises et ne développera pas les entités .
    Aussi longtemps que le code d’extrait brut ne contrevient pas à la règle 1 (le caractère de fermeture des conteneurs ne peut pas être inséré dans l’extrait), cela nécessite pas autre échappement/encodage.

Clairement cela se résume à: comment pouvons-nous minimiser le nombre de caractères/séquences de caractères qui doivent encore être codés dans l'extrait brut source et le nombre de fois que ce caractère (séquence) peut apparaître dans un extrait de code moyen; quelque chose qui est également important pour le javascript qui gère la traduction de ces caractères (s’ils se produisent).

Alors quels 'conteneurs' ont ce contexte CDATA?

La plupart des propriétés de valeur des balises sont CDATA, donc on pourrait (ab) utiliser une propriété de valeur masquée ( preuve de concept jsfiddle ici ).
Cependant (règle de conformité 1), cela crée un problème d'encodage/évasion avec des guillemets imbriqués (" Et ') Dans l'extrait de code brut et il faut un peu de javascript pour obtenir/traduire et définissez l'extrait de code dans un autre élément (visible) (ou simplement en le définissant comme valeur de zone de texte). D'une certaine manière, cela m'a donné des problèmes avec les entités dans FF (comme dans une zone de texte). Mais cela n’a pas vraiment d’importance, car le "prix" de devoir échapper/encoder des guillemets imbriqués est plus élevé qu’un texte (HTML5) (les guillemets sont assez courants dans le code source ..).

Pourquoi ne pas essayer d'utiliser (ab) <![CDATA[<tag>bla & bla</tag>]]>?
Comme le souligne Jukka dans sa réponse détaillée, cela ne fonctionnerait que dans (rare) 'real xhtml'.
J'ai pensé utiliser un script-tag (avec ou sans un tel wrapper CDATA dans le script-tag) avec un commentaire multiligne /* */ Qui enveloppe le fragment de code brut (les balises de script peuvent avoir un id et vous pouvez y accéder par nombre). Mais puisque ceci introduit évidemment un problème d'échappement avec */, ]]> Et </script Dans l'extrait de code brut, cela ne semble pas être une solution non plus.

Veuillez poster d'autres 'conteneurs' viables dans les commentaires de cette réponse.

À propos, encoder ou compter le nombre de caractères - Et les équilibrer dans une balise de commentaire <!-- --> Est simplement insensé pour cela (à part la règle 1).


Cela nous laisse avec excellente réponse de Jukka K. Korpela : La balise <xmp> Semble être la meilleure option!

Le mot "oublié" <xmp> Contient CDATA, est prévu à cet effet ET est toujours dans le actuel HTML 5 spec ( et a été au moins depuis HTML3.2); exactement ce dont nous avons besoin! Il est également largement supporté, même dans IE6 (c'est-à-dire jusqu'à ce qu'il souffre de la même régression que le corps du tableau qui défile).
Remarque: comme l'a souligné Jukka, cela ne fonctionnera pas en vrai xhtml ou en polyglotte (cela le traitera comme un pre) et la balise xmp devra toujours adhérer à la règle no. 1. Mais c'est la "seule" règle.

Considérez le balisage suivant:

<!-- ATTENTION: replace any occurrence of &lt;/xmp with </xmp -->
<xmp id="snippet-container">
<div>
    <div>this is an example div &amp; holds an xmp tag:<br />
        <xmp> 
<html><head>  <!-- indentation col 0!! -->
    <title>My Title</title>
</head><body>
    <p>hello world !!</p>
</body></html>
        &lt;/xmp>  <!-- note this encoded/escaped tag -->
    </div>
    This line is also part of the snippet
</div>
</xmp>

Le codeblok ci-dessus illustre une partie brute du balisage où <xmp id="snippet-container"> Contient un extrait de code (presque brut) (contenant div>div>xmp>html-document).
Remarquez la balise de fermeture codée dans ce balisage? Pour se conformer à la règle n ° 1, ceci a été encodé/échappé).

Donc, intégrer/transporter le code (parfois presque) brut est/semble résolu.

Qu'en est-il d'afficher/rendre l'extrait de code (et celui codé &lt;/xmp>)?

Le navigateur va (ou il devrait) rendre l’extrait de code (le contenu à l'intérieur de snippet-container) exactement tel que vous le voyez dans le code ci-dessus (avec quelques divergences entre les navigateurs, que l'extrait commence par une ligne vide).
Cela comprend le formatage/l'indentation, les entités (comme la chaîne &amp;), Les balises complètes, les commentaires ET la balise de fermeture codée &lt;/xmp> (Juste comme il a été encodé dans le balisage). Et en fonction du navigateur (version), vous pouvez même essayer d’utiliser la propriété contenteditable="true" Pour éditer cet extrait (tout cela sans javascript activé). Faire quelque chose comme textarea.value=xmp.innerHTML Est aussi un jeu d'enfant.

Ainsi, vous pouvez ... si l'extrait de code ne contient pas les conteneurs fermant la séquence de caractères.

Cependant , devrait un extrait de code contenant la séquence de caractères de fermeture </xmp (Car il s'agit d'un exemple de xmp lui-même ou contenant des expressions rationnelles, etc.), vous devez accepter le fait que vous devez encoder/échapper cette séquence dans l’extrait brut ET avoir besoin d’un gestionnaire javascript pour traduire cet encodage afin d’afficher/restituer le code codé &lt;/xmp> comme </xmp> dans un textarea (pour l'édition/la publication) ou (par exemple) un pre juste pour restituer correctement le code de l'extrait de code (ou semble-t-il).

Un très rudimentaire exemple jsfiddle de ceci ici . Notez que l’obtention/incorporation/affichage/récupération-dans-zone de texte a fonctionné parfaitement, même dans IE6. Mais configurer xmp pour innerHTML a révélé un comportement intéressant "potentiellement intelligent" de la part d'IE. Il existe une note plus complète et une solution de contournement à ce sujet dans le violon.

Mais maintenant vient le important kicker (une autre raison pour laquelle vous n’êtes que très proche ): Juste à titre d'exemple simpliste, imaginez ceci rabbit-hole:

Extrait de code brut prévu:

<!-- remember to translate between </xmp> and &lt;/xmp> -->
<xmp>
<p>a paragraph</p>
</xmp>

Eh bien, pour se conformer à la règle 1, il suffit de coder ces séquences </xmp[> \n\r\t\f\/], N'est-ce pas?

Cela nous donne donc le balisage suivant (en utilisant seulement un encodage possible):

<xmp id="container">
<!-- remember to translate between &lt;/xmp> and &lt;/xmp> -->
<xmp>
<p>a paragraph</p>
&lt;/xmp>
</xmp>

Hmm .. dois-je obtenir ma boule de cristal ou une pièce de monnaie? Non, laissez l'ordinateur examiner son horloge système et indiquer qu'un nombre dérivé est "aléatoire". Oui, ça devrait le faire ..

Utiliser une expression rationnelle like: xmp.innerHTML.replace(/&lt;(?=\/xmp[> \n\r\t\f\/])/gi, '<');, traduirait 'back' en ceci:

<!-- remember to translate between </xmp> and </xmp> -->
<xmp>
<p>a paragraph</p>
</xmp>

Hmm .. semble que ce générateur aléatoire est cassé ... Houston ..?
Si vous avez manqué la blague/le problème, relisez-le en commençant par "l'extrait de code brut prévu".

Attendez, je sais, nous (aussi) avons besoin d'encoder .... pour ....
OK, revenez en arrière sur "extrait de code brut prévu" et relisez-le.
Tout cela commence à sentir comme la célèbre réponse hilarante, mais vraie, rexgex sur SO , une bonne lecture pour les personnes parlant couramment le mojibake.

Peut-être que quelqu'un connaît un algorithme intelligent ou une solution pour résoudre ce problème, mais je suppose que le code brut incorporé deviendra de plus en plus obscur au point où il vaudrait mieux échapper/encoder correctement votre <, & (Et >), Tout comme le reste du monde.

Conclusion: (en utilisant la balise xmp)

  • cela peut être fait avec des fragments connus qui ne contiennent pas la séquence de caractères de fermeture du conteneur,
  • nous pouvons nous rapprocher de l'objectif initial avec des fragments connus qui n'utilisent que le codage d'échappement de base de base; nous ne tombons donc pas dans le rabbithole,
  • mais finalement il semble qu'on ne puisse pas le faire de manière fiable dans un "environnement de production" où les gens peuvent/devraient copier/coller/éditer des extraits bruts "tout inconnu" sans connaître ni comprendre les implications/rules/rabbithole (selon votre mise en œuvre de la manipulation/traduction pour la règle 1 et le trou de lapin).

J'espère que cela t'aides!

PS: Bien que j'apprécie beaucoup plus si vous trouvez cette explication utile, je pense que la réponse de Jukka devrait être la réponse acceptée (il ne devrait pas y avoir de meilleure option/réponse), car c'est lui qui s'est souvenu de la balise xmp oublié au fil des ans et a été "distrait" par les éléments PCDATA couramment préconisés comme pre, textarea, etc.).
Cette réponse tire son origine de l’explication de la raison pour laquelle vous ne pouvez pas le faire (avec un extrait brut inconnu) et de l’explication de quelques pièges évidents que d’autres réponses (maintenant supprimées) ont été omises lorsqu’il est conseillé d’ajouter une zone de texte à intégrer ou à transporter. J'ai élargi mon explication existante pour prendre également en charge et expliquer davantage la réponse de Jukka (étant donné que toute cette entité et le contenu * CDATA sont presque plus difficiles que les pages de code).

22
GitaarLAB

Réponse pas chère et gaie:

<textarea>Some raw content</textarea>

La zone de texte gérera les onglets, les espaces multiples, les nouvelles lignes et les retours à la ligne. Il copie et colle bien et son code HTML valide jusqu'au bout. Il permet également à l'utilisateur de redimensionner la zone de code. Vous n'avez besoin d'aucun CSS, JS, échappement, encodage.

Vous pouvez également modifier l'apparence et le comportement. Voici une police monospace, édition désactivée, police plus petite, pas de bordure:

<textarea
    style="width:100%; font-family: Monospace; font-size:10px; border:0;"
    rows="30" disabled
>Some raw content</textarea>

Cette solution n'est probablement pas sémantiquement correcte. Donc, si vous en avez besoin, le mieux serait de choisir une réponse plus sophistiquée.

7
Henry
echo '<pre>' . htmlspecialchars("<div><b>raw HTML</b></div>") . '</pre>';

Je pense que c'est ce que vous cherchez?

En d'autres termes, utilisez htmlspecialchars () en PHP

3
tribulant

@GitaarLAB et @Jukka expliquent que <xmp>tag est obsolète, mais reste le meilleur. Quand je l'utilise comme ça

<xmp>
<div>Lorem ipsum</div>
<p>Hello</p>
</xmp>

alors le premier EOL est inséré dans le code, et il est affreux .

Il peut être résolu en supprimant cette fin de vie

<xmp><div>Lorem ipsum</div>
<p>Hello</p>
</xmp>

mais alors il semble mauvais dans la source. J'avais l'habitude de le résoudre avec l'emballage <div>, mais récemment, j'ai trouvé une règle de Nice en CSS3, j'espère que cela aidera aussi quelqu'un:

xmp { margin: 5px 0; padding: 0 5px 5px 5px; background: #CCC; }
xmp:before { content: ""; display: block; height: 1em; margin: 0 -5px -2em -5px; }

Ceci semble mieux .

3
Jan Turoň

xmp est la voie à suivre, c'est-à-dire:

<xmp>
  # your code...
</xmp>
2
Pedro Lobito

Si jQuery est activé, vous pouvez utiliser une fonction escapeXml sans avoir à vous soucier des flèches ou des caractères spéciaux.

<pre>
  ${fn:escapeXml('
    <!-- all your code --> 
  ')};
</pre>
1
PanicBus