Javascript 检测并替换标记文档中的文本段落

Javascript 检测并替换标记文档中的文本段落,javascript,regex,markdown,Javascript,Regex,Markdown,我正在绞尽脑汁尝试编写/使用一个现有的markdown解析器来查找和替换markdown文档中的每个文本段落,而保留所有其他内容不变 输入示例: # A First Level Header ## Second Level Header Now is the time for all good men to come to the aid of their country. This is just a regular paragraph. The quick brown fox jump

我正在绞尽脑汁尝试编写/使用一个现有的markdown解析器来查找和替换markdown文档中的每个文本段落,而保留所有其他内容不变

输入示例:

# A First Level Header

## Second Level Header

Now is the time for all good men to come to the aid of their country. This is just a regular paragraph.

The quick brown fox jumped over the lazy dog's back.

### Header 3

> This is a blockquote.
> 
> This is the second paragraph in the blockquote.
>
> ## This is an H2 in a blockquote
理想的效果是识别段落并替换它们,例如

# A First Level Header

## Second Level Header

[replaced]

[replaced]

### Header 3

> This is a blockquote.
> 
> This is the second paragraph in the blockquote.
>
> ## This is an H2 in a blockquote
现有的库(如或)似乎无法在没有副作用的情况下解析和重新创建标记文档


在标记文档中查找和替换文本段落的最佳方法是什么?

标记文档中的段落本质上是任何文本块,而不是任何其他块级构造(由定义)。因此,段落是一个文本块,它不是标题、列表、块引号、代码块或水平规则(因为这些是Markdown中定义的唯一其他块级结构——忽略一些非官方的扩展)


由于您只对查找根级别的段落(而不是嵌套段落)感兴趣,一种简单的方法可能是简单地在双换行符上拆分文档,并在每个块的开头运行正则表达式,以检查标识非段落类型的标记。如果它以四个或更多空格(或一个选项卡)开头;没有一段。如果它以0-3个空格和哈希开头;没有一段。如果以0-3个空格开始,则为
和空格;没有一段。如果它以0-3个空格开头,则为
*、-、+
中的一个空格,而不是段落。等等

一个问题是头部。标题只能是一行,哈希标题与后面的段落之间可能没有空行。然而,这很容易解决,因为标题只能是一行。如果您找到一个标题(以散列开头的块),将第一行拆分,其他任何内容都是一个单独的块,可能是段落,也可能不是段落

当然,更棘手的问题是setextheaders,因为第二行标识它们有头。但是,如果正则表达式查找第一个换行符,然后是3个或更多的
-
=
,则应该执行此操作


如果您查看一些现有的降价实现,您需要的大部分正则表达式都已经存在。当然,您将开发自己的各种标记解析器,并且各种边缘情况可能会偷偷出现。然而,考虑到您非常特殊的需求,我不确定您是否会找到一个现有的解析器来满足您的需求。

这是一个众所周知的问题类型-按结果元素查找源范围所需的源映射信息。目前我还不知道markdown解析器对源代码映射有完全正确的支持


但是标记它和引用commonmark解析器可以提供关于源代码行的信息(没有列)。如果您只需要对根块执行某些操作,那么这种有限的行信息将非常有用。例如,同步使用线条映射到srcoll窗格。

您至少应该提供输入和所需输出的示例。我可能会很快得出结论,但降价段落是否会以字母开头?@Thomas我可以想出很多例子,当段落不以字符开头时,例如,当列表发挥作用时,它变得有点棘手,例如
1。a
a。a
表示列表的开始。对于记录,有一个关于如何使用
标记它来实现此目标的讨论(在撰写本报告时没有结论)。“如果它以0-3个空格开始,其中一个是*,-,+和一个空格,而不是一个段落。”这不是真的。段落可以以强调符号(例如
*foo*bar.
)或链接(例如
[foo](..)bar.
)开头。是的,但如果您有
*foo*bar.
,则这是一个列表项。注意第一个
*
后面的空格。我通过声明令牌后面必须有一个空格来覆盖该场景。是的,就是这么简单。这就是引用实现使用的方法。请参见此处的示例:*foo*+bar.%0A%0A*+foo*+bar.Close。一个段落的开头最多可以有三个空格,并且仍然是一个段落,但是您的正则表达式与此不匹配。另外,您应该向示例文档中添加一些列表。考虑多行列表项。第二行不需要缩进,但不是段落。但是,您的正则表达式仍然与之匹配。