Let's use this **sample document** with _various_ types of [Markdown](http://daringfireball.net/projects/markdown/) markup.
现在,假设您使用前 20 个字符。你会得到:
Let's use this **sam
100 个字符给你:
Let's use this **sample document** with _various_ types of [Markdown](http://dar
虽然这些 char 长度是任意的,并且可能不是您会使用的长度,但关键是它们中的每一个都破坏了 Markdown 语法。更好的方法是将文档解析为 HTML,然后拆分 HTML 文档的开头。
当然,出于同样的原因,您可能希望以某种方式使用 HTML 文档模型,而不是根据原始字符长度进行拆分。为什么不直接取第一段呢?如果段落太长,则在第 N 个字符处中断,但只计算正文中的字符,而不是构成 HTML 标记的字符。如何做到这一点取决于您用来处理 HTML 的工具/库,这不是提出工具建议的地方(而且我对 Ruby/Rails 不是很熟悉——更像是一个 Python 人)。
请注意,我在上面给出的第二个示例打破了链接 URL 中间的 Markdown。如果您首先将 Markdown 转换为 HTML 并仅中断计数文本字符,那么即使链接文本(标签)被截断,URL 也会保持不变。尽管在这种情况下,最好在链接结束后截断文本。这取决于你想让你的代码有多复杂。
下一步自然是问为什么不使用 Markdown 文本而不是先将整个文档转换为 HTML 呢?你可以,但是你会重新实现你自己的 Markdown 解析器......除非你碰巧使用了一个 Markdown 解析器,它可以让你访问内部(通过一些插件 API)或输出一个解析三。如果您使用的是返回解析树的解析器,则可以截断解析树,然后将其传递给渲染器。除此之外,使用解析过的 HTML 可能是最好的选择。
无论哪种方式,让我们通过一个例子来工作。上面示例的 HTML 看起来像这样:
<p>Let's use this <strong>sample document</strong> with <emphasis>various</emphasis> types of <a href="http://daringfireball.net/projects/markdown/">Markdown</a> documents</p>
现在,让我们将该文档表示为某种伪文档对象(使用 JSON):
[{
'type': 'element',
'tag': 'p',
'children' :
[
{
'type': 'text',
'text': "Let's use this "
},
{
'type': 'element',
'tag': 'strong',
'children':
[
{
'type': text,
'text': "sample document"
}
]
},
{
'type': 'text',
'text': " with "
},
{
'type': 'element',
'tag': 'emphasis',
'children':
[
{
'type': text,
'text': "various"
}
]
},
{
'type': 'text',
'text': " types of "
},
{
'type': 'element',
'tag': 'a',
'href': 'http://daringfireball.net/projects/markdown/'
'children':
[
{
'type': text,
'text': "Markdown"
}
]
},
{
'type': 'text',
'text': " markup."
}
]
}]
现在,只需遍历该文档(及其子文档),只计算“文本”类型的“文本”字段的字符数,直到达到最大值。然后截断文档中之后的任何其他元素。当文档被渲染(使用适当的 HTML 渲染器)时,所有的 HTML 元素都将被正确关闭。显然,确切的过程将取决于文档包含在哪种文档对象中(这可能取决于您使用的 HTML 解析器和/或 Markdown 解析器)。
无论如何,截断为 20 个字符的文档会导致:
[{
'type': 'element',
'tag': 'p',
'children' :
[
{
'type': 'text',
'text': "Let's use this "
},
{
'type': 'element',
'tag': 'strong',
'children':
[
{
'type': text,
'text': "sampl"
}
]
},
]
}]
这将呈现为:
<p>Let's use this <strong>sampl</strong></p>
请注意,仅文本 (Let's us this sampl) 计为 20 个字符。
虽然上述示例使用字符,但您当然可以使用相同的原则并计算字数。