如何使用正则表达式转换 HTML 包装的 Markdown 代码块

How to use regex to convert HTML-wrapped markdown code blocks

提问人:SleekEagle 提问时间:11/15/2023 最后编辑:SleekEagle 更新时间:11/15/2023 访问量:26

问:

问题

我有带有 markdown 代码块的文件,这些代码块在导出时被 HTML 标签包围。例如,代码块<p>

```python
def fn():
  pass
```                                              # comment added for formatting

导出为<p>```python</p><p>def fn():</p><p> pass</p><p>```</p>

我想要的是使用 JavaScript 将这些转换为 HTML 代码块(我目前正在使用 Google Apps 脚本,但如有必要可以使用 Node.js)。

例如,正上方的字符串应转换为<pre><code language=python>def fn():\n pass</code><pre>

最好的方法是什么?

尝试的解决方案

我首先尝试使用正则表达式分别捕获语言和代码行,然后我使用正则表达式进行格式化,但我无法编写合适的正则表达式。String.replace()

我目前正在使用这个正则表达式:.它捕获语言,然后捕获所有代码行(仍然带有标记)。例如,在第一个捕获组和第二个捕获组中返回的上述代码块上运行。/<p>```((?:\w)*)<\/p>(?:<p>((?:.)*?)<\/p>)<p>```<\/p>/gpythondef fn():</p><p> pass

然后我尝试使用 ,其中不知何故是第二个捕获组的功能(为了删除标签),但这不起作用。String.replace(regex, replacement)replacement<p>

目前,我能想到的最好的事情是遍历每个匹配项并用索引替换该子字符串:

String.prototype.replaceAt = function(start, end, replacement) {
    return this.substring(0, start) + replacement + this.substring(end);
}

  var replacedText = inputText
  while(null != (z=backtickRegex.exec(inputText))) {
    var newString = `<pre><code language=${z[1]}>${z[2].replaceAll('</p><p>', '\n')}</code></pre>`
    replacedText = replacedText.replaceAt(z.index, z.index+z[0].length, newString)
  }

然而,这感觉非常不优雅

有没有更好的方法可以做到这一点,而我却错过了?任何见解都非常感谢!

JavaScript 节点.js 解析

评论

0赞 James 11/15/2023
一般使用 DOM 解析器从 html 中解析和提取数据,参见 stackoverflow.com/questions/7372972/...

答:

0赞 SleekEagle 11/15/2023 #1

我最终只是这样做:

String.prototype.replaceAt = function(start, end, replacement) {
    return this.substring(0, start) + replacement + this.substring(end);
}

// helper to turn markdown code blocks to html
function codeBlocksToHTML(inputText) {
  // This regex captures the language in a first group, and then the code WITH P TAGS in a second
  const backtickRegex = /<p>```((?:\w)*)<\/p>(?:<p>((?:.)*?)<\/p>)<p>```<\/p>/g;
  
  // for every match, remove the code p tags
  while(null != (z=backtickRegex.exec(inputText))) {
    var newString = `<pre><code language=${z[1]}>${z[2].replaceAll('</p><p>', '\n')}</code></pre>`
    inputText = inputText.replaceAt(z.index, z.index+z[0].length, newString)  
  }

  return inputText;
}

我认为已经足够好了