尝试使用regex将markdown UL转成HTML。下面,我展示了一个示例输入的样子,结果应该是两个不同的 ul
元素,第一个包含三个 li
元素,第二个包含两个。
- Item 1
- Item 2
- Item 3
A second list:
- Item 1
- Item 2
遇到这个令人恼火的问题,其中以下正则表达式似乎没有按预期工作。问题是它似乎无法识别 \n
字符,因为第一个正则表达式 /((- |ー).*(\n|$))+/g
似乎仅在字符串结尾 ($
) 时才获得匹配项。< /p>
.replaceAll(/((- |ー).*(\n|$))+/g, function(match) {
return `<ul>${match}</ul>`.replaceAll(/(- |ー).*/g, function(match) {
return `<li>${match.match(/(?<=(- |ー)).*/)}</li>`
});
});
我不明白问题是什么,我测试了 Regexr 中的表达式,它完美地工作。
如果有帮助,这里是完整的上下文:
parse(markdown) {
return markdown
// Clean HTML brackets
.replaceAll('<', '<')
.replaceAll('>', '>')
// Change markdown links into html links
.replaceAll(/\[.*?\]\(.*?\)/g, function (match) {
return `<a href='${match.match(/(?<=\().*?(?=\))/)[0]}' target='_blank'>${match.match(/(?<=\[).*?(?=\])/)[0]}</a>`;
})
// Headings
.replaceAll(/(^|\n)# .*/g, function (match) {
return `<h1>${match.match(/(?<=# ).*/)}</h1>`
})
.replaceAll(/(^|\n)## .*/g, function (match) {
return `<h2>${match.match(/(?<=# ).*/)}</h2>`
})
.replaceAll(/(^|\n)### .*/g, function (match) {
return `<h3>${match.match(/(?<=# ).*/)}</h3>`
})
// Ordered lists
.replaceAll(/((- |ー).*($|\n))+/g, function(match) {
return `<ul>${match}</ul>`.replaceAll(/(- |ー).*/g, function(match) {
return `<li>${match.match(/(?<=(- |ー)).*/)}</li>`
});
});
请注意,\n
部分中的 // Headings
字符被完全识别。
(编辑以澄清这是在 VueJS 中,因此在组件的方法对象中使用此方法定义语法)
答案 0 :(得分:1)
它根本没有忽略 \n
。您的正则表达式模式只是将整个列表匹配为单个匹配项,而 \n|$
只是匹配最后一个匹配项——即您得到的是一个长匹配项,而不是三个单独的匹配项,每个列表项一个匹配项,因为您想要。
事实上,您误认为“在 Regexr 中它可以完美运行”。去那里再试试。你会得到一场长比赛,而不是三场。
这样做的原因是正则表达式默认是贪婪。您可以通过将 ?
附加到量词来改变它,使其 lazy 而不是 greedy:
/((- |ー).*(\n|$))+?/g
尝试在 Regexr 中使用和不使用 ?
以便您可以看到差异,并且还可以学习如何解释 Regexr 结果,因为您上次错过了这个。
ℹ️ 这不能解决您的列表项转换为 HTML 的问题;您的代码还有其他问题,但我正在回答您提出的问题。
还有另一种方法可以产生相同的结果:
/((- |ー).*($))+/gm
这种方法切换到多行模式,这意味着输入被视为单独的行。在这种模式下,您不会尝试匹配 \n
,因为它们不会出现;您只需将每行的末尾与 $
匹配。
答案 1 :(得分:-1)
您的代码过于复杂。试试这个:
1- 应用除有序列表之外的所有过滤器
2- 查找所有列表匹配
3- 将它们映射到 li
:
parse(markdown) {
const cleansedString = markdown
// Clean HTML brackets
.replaceAll('<', '<')
.replaceAll('>', '>')
// Change markdown links into html links
.replaceAll(/\[.*?\]\(.*?\)/g, function (match) {
return `<a href='${match.match(/(?<=\().*?(?=\))/)[0]}' target='_blank'>${match.match(/(?<=\[).*?(?=\])/)[0]}</a>`;
})
// Headings
.replaceAll(/(^|\n)# .*/g, function (match) {
return `<h1>${match.match(/(?<=# ).*/)}</h1>`
})
.replaceAll(/(^|\n)## .*/g, function (match) {
return `<h2>${match.match(/(?<=# ).*/)}</h2>`
})
.replaceAll(/(^|\n)### .*/g, function (match) {
return `<h3>${match.match(/(?<=# ).*/)}</h3>`
});
const listMatches = Array.from(cleansedString.matchAll(/((- |ー)(.*)($|\n))/g));
const listHtml = listMatches.map((matches) => `<li>${matches[3]}</li>`);
return `<ul>${listHtml.join('')}</ul>`;
}