如何在PRE或类似的东西中显示原始html代码但不转义它

时间:2013-05-28 04:09:22

标签: html pre

我想显示原始HTML。我们都知道必须逃避每个“<”和“>”像这样

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

但是,我不想这样做。我想要一种方法来保持HTML代码(因为它更容易阅读,(在编辑器内)我可能想要复制它并自己再次使用它作为实际的HTML代码,并且不希望再次更改它或者有两个版本的相同代码一个转义,一个没有转义)。

是否有任何其他环境比PRE更“原始”可能允许这样做?因此,每次他们想要显示一些原始HTML代码时,不必继续编辑HTML并更改所有内容,可能是HTML5格式吗?

<REALLY_REALLY_VERBATIM> ...... </<REALLY_REALLY_VERBATIM>

这样的东西

屏幕截图

javascript解决方案在FF 21上不起作用,这是屏幕截图 enter image description here

屏幕截图2

第一个解决方案仍然无法在firefox上运行,这里是屏幕截图 enter image description here

8 个答案:

答案 0 :(得分:89)

您可以使用xmp元素,请参阅What was the <XMP> tag used for?。它从一开始就是HTML,并且得到所有浏览器的支持。规格不屑一顾,但HTML5 CR仍然描述它并要求浏览器支持它(虽然它也告诉作者不要使用它,但它不能真正阻止你)。

xmp内的所有内容都是这样的,在那里没有识别标记(标记或字符引用),除了明显的原因,元素本身的结束标记</xmp>

否则xmp呈现为pre

当使用“真正的XHTML”时,即XHTML使用XML媒体类型(很少见),特殊的解析规则不适用,因此xmp被视为pre。但在“真正的XHTML”中,您可以使用CDATA部分,这意味着类似的解析规则。它没有特殊的格式,因此您可能希望将其包含在pre元素中:

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

我看不出如何将xmp和CDATA部分结合起来实现所谓的多语言标记

答案 1 :(得分:22)

基本上,原始问题可以分为两部分:

  • 主要目标/挑战:嵌入(/传输)原始格式化代码片段 (网页的标记中的任何类型的代码)(由于没有,因此可以进行简单的复制/粘贴/编辑) 编码/逃逸)
  • 正确显示/呈现该代码片段(可能编辑它) 浏览器

简短(但)含糊不清的答案是:你不能 ......但你可以(非常接近)。
(我知道,这是3个相互矛盾的答案,请继续阅读......)

(polyglot)(x)(ht)ml标记语言依赖于(几乎)包含开始/打开和结束/结束标记/字符(序列)之间的所有内容。
因此,要在您的标记语言中嵌入任何类型的原始代码/代码段,人们将始终必须转义/编码类似于将关闭的字符(-sequence)的每个实例(在该代码段内)包装容器&#39;标记中的元素。 (在这篇文章中,我将其称为规则1 。)
想想"some "data" here"<i>..close italics with '</i>'-tag</i>,很明显应该逃避/编码(某些内容)</i"(或更改容器&#39; s引用字符来自"')。

所以,由于规则1, 你不能 &#39;只是&#39;嵌入任何&#39;标记内的未知原始代码片段。
因为,如果必须在原始代码段内转义/编码甚至一个字符,那么该代码段将不再是原始纯粹的原始代码&#39;任何人都可以在文档的标记中进行复制/粘贴/编辑,而无需进一步考虑。由于实体,它会导致格式错误/非法标记和Mojibake(主要) 此外, 该片段包含此类字符,您需要一些javascript来翻译&#39;该字符(序列)来自(和)其转义/编码表示,以便在&#39;网页中正确显示 的片段 (用于复制/粘贴/编辑)。

这将我们带到标记语言指定的(某些)数据类型。这些数据类型基本上定义了什么被认为是有效字符&#39;及其含义(每个标签,财产等):

  • PCDATA(Parsed Character DATA):将扩展实体,必须 转义<&(和>取决于标记语言/版本) 大多数代码,例如bodydivpre等,还有textarea(直到 HTML5)属于这种类型。
    因此,您不仅需要对所​​有容器的关闭字符序列进行编码 在代码段内,您还必须对所有<&(,>)个字符进行编码 (至少) 不用说,编码/转义这么多字符不属于此范围 目标在标记中嵌入原始代码段的范围 &#39; ..但是textarea似乎有效...&#39;,是的,或者是因为浏览器 错误引擎尝试用它做出一些东西,或者因为HTML5:

  • RCDATA(可替换的字符数据):不会处理内部的标签 文本作为标记(但仍受规则1管辖),因此不需要 编码<>)。但实体仍在扩展,因此它们不明确 &符号&#39; (&)需要特别小心 当前 HTML5 spec says the textarea is now a RCDATA field和(引用):

      

    raw textRCDATA元素中的文字不得包含任何内容   出现字符串"</"(U + 003C LESS-THAN SIGN,U + 002F SOLIDUS)   后跟与字符串不敏感匹配的标记名称的字符   该元素后跟U + 0009 CHARACTER TABULATION(标签)之一,   U + 000A LINE FEED(LF),U + 000C FORM FEED(FF),U + 000D CARRIAGE RETURN   (CR),U + 0020 SPACE,U + 003E GREATER-THAN SIGN(&gt;)或U + 002F SOLIDUS(/)。

    因此无论如何,textarea需要一个庞大的实体翻译处理程序或 它最终Mojibake实体!

  • CDATA(字符数据)不会将文本中的标记视为 标记,不会扩展实体 因此,只要原始代码段代码不违反规则1(那个人就不能违反规则1) 让容器在代码片段内关闭字符(序列),这个 需要没有其他转义/编码。

显然归结为:我们如何最小化仍然需要在代码段的原始来源中编码的字符/字符序列的数量以及字符(序列)在平均片段中出现的次数;对于处理这些字符翻译的javascript(如果它们出现)也很重要的东西。

那是什么&#39;容器&#39;有这个CDATA上下文?

标签的大多数值属性都是CDATA,因此一个可以(ab)使用隐藏输入的值属性(proof of concept jsfiddle here)。
但是(符合规则1)这会在原始代码段中创建嵌套引号("')的编码/转义问题,并且需要一些javascript来获取/翻译并将代码段设置为另一个(可见)元素(或简单地将其设置为文本区域的值)。不知怎的,这给了我FF实体的问题(就像在textarea中一样)。但它并不重要,因为价格和价格相同。必须转义/编码嵌套引号高于(HTML5)textarea(引用在源代码中很常见..)。

尝试(ab)使用<![CDATA[<tag>bla & bla</tag>]]>怎么样? 正如Jukka在他的扩展答案中指出的那样,这只适用于(罕见的)真正的xhtml&#39;。
我想过使用脚本标记(在脚本标记内有或没有这样的CDATA包装)以及包含原始片段的多行注释/* */(脚本标记可以有{{1}并且您可以通过计数访问它们)。但是,由于这显然在原始代码段中引入了id*/]]>的转义问题,这似乎不是解决方案

请发布其他可行的容器&#39;在对这个答案的评论中。

顺便说一句,编码或计算</script个字符的数量并在注释标记-内平衡它们只是为此目的而疯狂(除了规则1)。


我们留下了Jukka K. Korpela's excellent answer <!-- -->代码似乎是最佳选择!

被遗忘的&#39; <xmp>保留<xmp>,用于此目的并且确实仍然是in the current HTML 5 spec(并且至少自HTML3.2起);正是我们需要的!它也得到了广泛的支持,即使在IE6中也是如此(直到它遭受与滚动表体相同的回归)。
注意:正如Jukka指出的那样,这不适用于真正的xhtml或多语言(将其视为CDATA)并且pre标记必须仍然遵守规则1。但是这样做&#39;只有&#39;规则。

考虑以下标记:

xmp

上面的代码插图说明了一个原始标记,<!-- 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> 包含一个(几乎是原始的)代码片段(包含<xmp id="snippet-container">)。
注意这个标记中的编码结束标记?为了遵守规则1,这是编码/转义的。

因此嵌入/传输(有时几乎)原始代码似乎已经解决了。

显示/呈现代码段(以及编码的div>div>xmp>html-document)怎么样?

浏览器将(或者它应该)以上面的代码块中的方式呈现代码片段(&lt;/xmp>中的内容完全(浏览器之间存在一些差异,无论是否存在差异)该片段以空行开头。) 包括格式/缩进,实体(如字符串snippet-container),完整标记,注释和编码的结束标记&amp;(就像它编码的一样)标记)。根据浏览器(版本),甚至可以尝试使用属性&lt;/xmp>来编辑此代码段(所有这些都没有启用javascript)。像contenteditable="true"这样的事情也是轻而易举的事。

所以你可以 ... 如果该代码段并不包含关闭字符序列的容器。

但是原始代码段包含结束字符序列textarea.value=xmp.innerHTML(因为它是xmp本身的一个示例,或者它包含一些正则表达式等),你必须接受你必须在原始片段中编码/转义该序列并且需要一个javascript处理程序来转换该编码以在{{1}内显示/呈现编码</xmp,如&lt;/xmp> }(用于编辑/发布)或(例如)</xmp>只是为了正确呈现代码段的代码(或者看起来如此)。

非常简陋jsfiddle example of this here。请注意,获取/嵌入/显示/检索到textarea即使在IE6中也能完美运行。但设置textarea&#39; pre会显示出一些有趣的“智能”#39}。 IE的行为部分。在小提琴中有更广泛的注释和解决方法。

但现在出现重要踢球者(另一个原因你只是非常接近): 就像一个过于简化的例子,想象一下 rabbit-hole

预期的原始代码段:

xmp

嗯,为了遵守规则1,我们只是&#39;需要编码那些innerHTML序列,对吧?

这样就为我们提供了以下标记(仅使用可能的编码):

<!-- remember to translate between </xmp> and &lt;/xmp> -->
<xmp>
<p>a paragraph</p>
</xmp>
嗯..我得到我的水晶球还是翻硬币?不,让计算机查看其系统时钟,并说明派生的数字是随机的&#39;。是的,应该这样做..

使用像这样的正则表达式</xmp[> \n\r\t\f\/],会翻译回来&#39;对此:

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

嗯..似乎这个随机发电机坏了...休斯顿..? 如果您错过了笑话/问题,请从“原始代码 - 片段”开始再次阅读。

等等,我知道,我们(也)需要编码......来.... 好的,请回到原定的原始代码段&#39;并再次阅读 不知怎的,这一切都开始闻起来像the famous hilarious-but-true rexgex-answer on SO,对于流利的mojibake的人来说是一个很好的读物。

也许有人知道一个聪明的算法或解决方案来解决这个问题,但我认为嵌入的原始代码会变得越来越模糊,以至于你更好地正确地转义/编码你的{{ 1}},xmp.innerHTML.replace(/&lt;(?=\/xmp[> \n\r\t\f\/])/gi, '<');(和<!-- remember to translate between </xmp> and </xmp> --> <xmp> <p>a paragraph</p> </xmp> ),就像世界其他地方一样。

结论:(使用<代码)

  • 可以使用不包含容器关闭字符序列的已知片段来完成,
  • 我们可以使用已知的片段非常接近原始目标,这些片段仅使用&#39;基本的第一级&#39;逃避/编码,所以我们不会落入rabbithole,
  • 最终似乎无法在“生产环境”中可靠地做到这一点。人们可以/应该复制/粘贴/编辑任何未知的&#39;原始片段,而不知道/理解含义/规则/ rabbithole(取决于您对规则1和兔子洞的处理/翻译的实施)。

希望这有帮助!

PS: 虽然如果你觉得这个解释很有用,我会很感激,我觉得Jukka的答案应该是公认的答案(不应该有更好的选择/答案),因为他是那个记住xmp标签的人(多年来我忘记了这一点,并且被普遍提倡的PCDATA元素分散了注意力,例如&>等。) 这个答案起源于解释为什么你不能这样做(使用任何未知的原始片段)并解释一些明显的陷阱,其他一些(现在删除的)答案在建议textarea嵌入/传输时被忽略了。我已经扩展了我现有的解释,以支持和进一步解释Jukka的答案(因为所有实体和* CDATA的东西几乎比代码页更难)。

答案 2 :(得分:6)

便宜又开朗的回答:

<textarea>Some raw content</textarea>

textarea将逐字处理标签,多个空格,换行符,换行。 它可以很好地复制和粘贴它的有效HTML。它还允许用户调整代码框的大小。 你不需要任何CSS,JS,转义,编码。

您也可以改变外观和行为。 这是一个等宽字体,编辑已禁用,字体较小,没有边框:

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

此解决方案可能在语义上不正确。因此,如果您需要,最好选择更复杂的答案。

答案 3 :(得分:3)

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

我认为这就是你要找的东西?

换句话说,在PHP中使用htmlspecialchars()

答案 4 :(得分:3)

@GitaarLAB和@Jukka详细说明<xmp>标签已过时,但仍然是最好的。当我像这样使用它时

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

然后在代码中插入第一个EOL,并looks awful

可以通过删除EOL

来解决
<xmp><div>Lorem ipsum</div>
<p>Hello</p>
</xmp>

但是它在源头看起来很糟糕。我曾经用包裹<div>解决它,但最近我发现了一个很好的CSS3规则,我希望它也能帮助某人:

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

looks better

答案 5 :(得分:2)

xmp是要走的路,即:

<xmp>
  # your code...
</xmp>

答案 6 :(得分:1)

如果你启用了jQuery,你可以使用escapeXml函数,而不必担心转义箭头或特殊字符。

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

答案 7 :(得分:1)

<code> 标签是个好方法,因为 <xmp><pre> 标签不支持换行

echo '<code>' . htmlspecialchars("<div><b>hello world</b></div>") . '</code>';