将原始 HTML 插入 Markdown

flu*_*ffy 2 markdown

我需要将原始 HTML 插入到 Markdown 文档中,以便逐字放置在输出中;具体来说,我试图确保文档的某些部分包含在容器中(例如<div><aside>、 或<section>),而不会破坏其中内容的格式。

但是,如果我采用以下明显的方法:

<aside>

## My heading
Some text, some text, some more text.

</aside>
Run Code Online (Sandbox Code Playgroud)

然后 Markdown 处理器生成这个无效的 HTML:

<aside>

## My heading
Some text, some text, some more text.

</aside>
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试将添加的标签放在要处理的文本上,例如

<aside>
## My heading
Some text, some text, some more text.
</aside>
Run Code Online (Sandbox Code Playgroud)

然后根据格式化的实际内容会发生一些不同的事情,但没有一个是正确的 -无论如何<aside>仍然被包裹<p>

如果我使用<div>,则所有内容都呈现为纯文本。

有没有办法指示 Markdown 处理器逐字处理输入文本,而不进行任何处理?

我目前正在使用 Hoedown(通过Misaka),它支持许多现代 Markdown 扩展,但如果有更现代的 Markdown 引擎可以更好地处理这个问题,我肯定会考虑切换到它。

Way*_*lan 8

安全的答案是使用以下内容:

<div class="aside">
<h2>My heading</h2>
<p>Some text, some text, some more text.</p>
</div>
Run Code Online (Sandbox Code Playgroud)

然而,它比许多可能的答案更复杂。哪个答案适用于您取决于您​​使用的 Markdown 实现,因为它们之间存在细微差别。让我们从参考实现 (markdown.pl) 和原始规则开始,因为这就是 Hoedown 声称要遵循的(见下文)。

老派降价

许多较旧的解析器最初是在从 HTML4 到 XHTML1 的过渡期间开发的,它们对原始 HTML 的行为和处理反映了这一点。也就是说,最近几年已经更新了一些,以增加对更新的 HTML 功能的支持。但是,参考实现已经十多年没有更新了,这是一个很好的起点。通常,如果您可以在参考实现中得到一些东西,它就可以在任何实现中运行,所以让我们关注一下。

这些规则首先描述了块级 HTML 标签的处理,然后描述了跨级行为,就好像它是例外一样。然而,在代码中,事情是相反的。跨度级行为是默认的,块级行为是特殊的例外。

自然地,当使用跨度级别的标签时,您希望结果是包装<p>标签。例如,foo <i>bar</i> baz应该导致<p>foo <i>bar</i> baz</p>. 因此,为了避免将原始 HTML 包裹在<p>标签中,规则要求有一组非常具体的情况:

唯一的限制是块级HTML元素- ?例如 <div><table><pre><p>,etc.?-?must从周围用空行内容分离,并且该块的开始和结束标签不应与制表符或空格缩进. Markdown 足够聪明,不会<p>在 HTML 块级标签周围添加额外的(不需要的)标签。

那里有3个要求:

  1. 原始 HTML 块必须以已知的块级标记开始。如前所述,在较旧的实现中,这些标签必须是 HTML4/XHTML1 规范中的有效块级标签。最近在 HTML5 中引入的任何内容在不同的实现中可能无法一致地工作。
  2. 开始标签前必须有一个空行或文档的开头,结束标签必须后跟一个空行或文档的结尾。
  3. 开始标记必须以行的第一个字符开始。任何缩进都会导致解析器无法将文本块识别为块级原始 HTML。

最后,规则规定:

请注意,Markdown 格式语法不会在块级 HTML 标签内处理。例如,您不能*emphasis* 在 HTML 块中使用 Markdown 样式。

请注意,这与跨级 HTML 不同:

与块级 HTML 标记不同,Markdown 语法在跨级标记内处理。

在这种情况下,<span>foo *bar*</span>结果为<p><span>foo <em>bar</em></span></p>,而<div>foo *bar*<div>结果为<div>foo *bar*</div>。请注意,在第一个示例中,在处理 Markdown 语法 ( *bar*) 时,整个内容都包含在<p>标签中。反过来。在第二个示例中,*bar*未处理Markdown 语法 ( ),但块未包含在<p>标记中。因此,任何包裹在块级原始 HTML 中的内容都必须是原始 HTML。

因此,让我们将这些规则应用到您的示例中:

<div>
<aside>
<h2>My heading</h2>
<p>Some text, some text, some more text.</p>
</aside>
</div>
Run Code Online (Sandbox Code Playgroud)

<div>规定是由旧的实现识别的标签。并且内容都是原始 HTML,因为它无论如何都不会作为 Markdown 处理。Babelmark表明这适用于所有实现。

当然,同时使用<aside><div>标签是多余的,所以你可以简单地使用一个<div>带有适当类的标签:

<div class="aside">
<h2>My heading</h2>
<p>Some text, some text, some more text.</p>
</div>
Run Code Online (Sandbox Code Playgroud)

正如 Babelmark所示,这也适用于任何地方。

如果您使用的实现添加了对 HTML5 块级标记的支持,您可以<aside>直接标记:

<aside>
<h2>My heading</h2>
<p>Some text, some text, some more text.</p>
</aside>
Run Code Online (Sandbox Code Playgroud)

当然,我们仍然需要使用所有原始 HTML。正如 Babelmark 所展示的,这适用于大多数但不是所有的实现。

扩展降价

多年来,许多 Markdown 实现都向语法添加了非标准扩展,从而增加了额外的功能。出于显而易见的原因,许多用户希望能够在原始 HTML 块中处理 Markdown 语法。因此,多年前,PHP Markdown Extra引入markdown="1"已被许多实现复制的解决方法。但是,大多数支持扩展的实现都需要显式启用扩展。默认情况下不启用。

如果您正在使用支持扩展的实现,并且启用了扩展,那么您可以使用它(如果支持较新的 HTML5 标签):

<aside markdown="1">
## My heading
Some text, some text, some more text.
</aside>
Run Code Online (Sandbox Code Playgroud)

或者这个(如果不支持 HTML5 标签):

<div markdown="1">
<aside>
## My heading
Some text, some text, some more text.
</aside>
</div>
Run Code Online (Sandbox Code Playgroud)

或者...

<div class="aside" markdown="1">
## My heading
Some text, some text, some more text.
</div>
Run Code Online (Sandbox Code Playgroud)

通用标志

有些人对实现之间的不一致感到沮丧,并着手定义一个严格的规范,该规范后来被称为 Commonmark。然而,Commonmark 规范自己承认,打破了原始实现中一些非常明确定义的规则。具有讽刺意味的是,这只会增加更多的不一致。最严重的违规行为之一是原始 HTML 处理。

只要您的原始 HTML 块不包含任何空行,Commonmark 就会以与老式 Markdown 实现相同的方式处理您的块。但是,一旦您引入了一个空行,该空行之后的任何内容都将被解析为 Markdown。

此外,Commonmark 规范明确定义了哪些标签被视为块级标签的完整列表。碰巧,<aside>是在标签列表中。

因此,如果您使用的是兼容的 Commonmark 实现,以下内容将起作用:

<aside>

## My heading
Some text, some text, some more text.

</aside>
Run Code Online (Sandbox Code Playgroud)

请注意,<aside>标签后面紧跟一个空行,它指示解析器将标签的任何内容视为 Markdown。正如 Babelmark 所展示的,这适用于 Commonmark 实现,但不适用于老式实现。

锄头

Hoedown 特别声称“完全符合标准”与“官方 Markdown v1.0.0 和 v1.0.3 测试套件”。请注意,这些是旧式参考实现的测试套件,而不是较新的 Commonmark 规范。在这种情况下,我们可以假设在原始 HTML 块中处理 Markdown 的 Commonmark 技巧将不起作用。当然,您当然可以尝试确定。

Hoedown 还声称“对几个(非官方)Markdown 扩展提供了可选支持”。但是,没有可用扩展的完整列表,也没有关于如何启用它们的任何说明。我没有安装该工具,但也许可以从命令行获得说明?如果您能找到启用markdown="1"扩展的方法,那么您可以使用该技巧在原始 HTML 块中进行 Markdown 处理。

然而,如果没有任何明确的文档,我认为 Hoedown 是一个老派的实现。我还注意到repo 中的html_block_names.gperf文件没有aside列为已知的 HTML 块级标记。因此,我们可以假设任何原始 HTML 块都必须包含在该文件中列出的 24 个标签之一中。

鉴于上述情况,我们可以安全地假设以下是从 Hoedown 获得所需结果的唯一可靠方法:

<div>
<aside>
<h2>My heading</h2>
<p>Some text, some text, some more text.</p>
</aside>
</div>
Run Code Online (Sandbox Code Playgroud)

或者...

<div class="aside">
<h2>My heading</h2>
<p>Some text, some text, some more text.</p>
</div>
Run Code Online (Sandbox Code Playgroud)