将引用语法转换为 HTML 的正则表达式
Regular expression for translating quoting syntax to HTML
我有一个针对我的用户的引用语法,类似于 SO:
So, Mike, you say:
>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
>Nam mi dui, porta non gravida id
>sodales venenatis tellus
But this makes no sense!
也可以有多个引号。我需要使用 JavaScript:
将其翻译成这样的 HTML 标记
So, Mike, you say:
<div class="quote">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nam mi dui, porta non gravida id
sodales venenatis tellus
</div>
But this makes no sense!
这是我想出的最好的,但它对每一行实施 HTML,而不是行块。
x = x.replace(/^&(amp;)?gt;([^\n]+)$/mg, "<div class=\"quote\"> </div>");
这样的正则表达式可以写吗?如果是,它会是什么样子?
这是试图用正则表达式操纵 HTML。 (我这么说是基于你正在搜索 >
的 HTML 实体而不是 >
的字面意思。)这几乎总是一个坏主意, 几乎 与尝试仅使用正则表达式解析 HTML 一样糟糕。 Obligatory Link.
您不能通过单个 replace
调用来完成此操作。但令我惊讶的是,您可以用两个或一个 outer 调用来完成,该调用使用函数回调来进行一堆内部调用。
这是两个调用版本:
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, '<div class="quote">***$&</div>');
x = x.replace(/(?:\*\*\*|^)(?:>|>|&gt;)/gm, '');
第一个查找带有引号标记的重复行系列,并将 div 标记包裹在它们周围。 (我在集合中包含了一个原始 >
,因此它会查找 >
、>
和 &gt;
[不过请参阅下面关于最后一个的注释]。)第二个删除引号。您不能在第一个 replace
中删除它们,因为您要替换整组行。另请注意,我必须为第一个标记添加前缀,因为一旦我们添加了 div 标记,它就不再位于一行的开头。
这是一个调用子调用的版本:
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, function(m) {
return '<div class="quote">' + m.replace(/^(?:>|>|&gt;)/gm, '') + '</div>';
});
它们有多强大?可能不是很多,请参阅上面答案的第一段。 :-)
旁注:您的正则表达式似乎正在寻找 &gt;
作为引号标记。我在上面保留了它,但是如果你的 HTML 中有 &gt;
,你就有 double-encoded HTML,这通常是一个指标其他地方的问题。
两次调用版本的实时示例,其中包含各种不同引号标记的变体:
function test(x) {
snippet.log("Before:");
snippet.log(x);
x = processString(x);
snippet.log("After:");
snippet.log(x);
document.body.appendChild(document.createElement('hr'));
}
function processString(x) {
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, '<div class="quote">***$&</div>');
x = x.replace(/(?:\*\*\*|^)(?:>|>|&gt;)/gm, '');
return x;
}
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
">Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
one-call-with-subcalls 版本的实例:
function test(x) {
snippet.log("Before:");
snippet.log(x);
x = processString(x);
snippet.log("After:");
snippet.log(x);
document.body.appendChild(document.createElement('hr'));
}
function processString(x) {
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, function(m) {
return '<div class="quote">' + m.replace(/^(?:>|>|&gt;)/gm, '') + '</div>';
});
return x;
}
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
">Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
这是如何完成的:匹配所有块,然后在回调函数内,拆分它并删除初始 >
并包装在 div
:
var s = 'So, Mike, you say:\n\n>Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n>Nam mi dui, porta non gravida id\n>sodales venenatis tellus\n\nBut this makes no sense!';
var res = s.replace(/^(?:(?:>|&(?:amp;)?gt;)[^\n]+)+/gm, function(m, grp1, grp2, offset, input) {
return m.split("\n").map(function(el) {
return '<div class="quote">' + el.replace(/(?:>|&(?:amp;)?gt;)/g,'') + "</div>";
}).join("\n");
});
alert(res);
我有一个针对我的用户的引用语法,类似于 SO:
So, Mike, you say:
>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
>Nam mi dui, porta non gravida id
>sodales venenatis tellus
But this makes no sense!
也可以有多个引号。我需要使用 JavaScript:
将其翻译成这样的 HTML 标记So, Mike, you say:
<div class="quote">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nam mi dui, porta non gravida id
sodales venenatis tellus
</div>
But this makes no sense!
这是我想出的最好的,但它对每一行实施 HTML,而不是行块。
x = x.replace(/^&(amp;)?gt;([^\n]+)$/mg, "<div class=\"quote\"> </div>");
这样的正则表达式可以写吗?如果是,它会是什么样子?
这是试图用正则表达式操纵 HTML。 (我这么说是基于你正在搜索 >
的 HTML 实体而不是 >
的字面意思。)这几乎总是一个坏主意, 几乎 与尝试仅使用正则表达式解析 HTML 一样糟糕。 Obligatory Link.
您不能通过单个 replace
调用来完成此操作。但令我惊讶的是,您可以用两个或一个 outer 调用来完成,该调用使用函数回调来进行一堆内部调用。
这是两个调用版本:
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, '<div class="quote">***$&</div>');
x = x.replace(/(?:\*\*\*|^)(?:>|>|&gt;)/gm, '');
第一个查找带有引号标记的重复行系列,并将 div 标记包裹在它们周围。 (我在集合中包含了一个原始 >
,因此它会查找 >
、>
和 &gt;
[不过请参阅下面关于最后一个的注释]。)第二个删除引号。您不能在第一个 replace
中删除它们,因为您要替换整组行。另请注意,我必须为第一个标记添加前缀,因为一旦我们添加了 div 标记,它就不再位于一行的开头。
这是一个调用子调用的版本:
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, function(m) {
return '<div class="quote">' + m.replace(/^(?:>|>|&gt;)/gm, '') + '</div>';
});
它们有多强大?可能不是很多,请参阅上面答案的第一段。 :-)
旁注:您的正则表达式似乎正在寻找 &gt;
作为引号标记。我在上面保留了它,但是如果你的 HTML 中有 &gt;
,你就有 double-encoded HTML,这通常是一个指标其他地方的问题。
两次调用版本的实时示例,其中包含各种不同引号标记的变体:
function test(x) {
snippet.log("Before:");
snippet.log(x);
x = processString(x);
snippet.log("After:");
snippet.log(x);
document.body.appendChild(document.createElement('hr'));
}
function processString(x) {
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, '<div class="quote">***$&</div>');
x = x.replace(/(?:\*\*\*|^)(?:>|>|&gt;)/gm, '');
return x;
}
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
">Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
one-call-with-subcalls 版本的实例:
function test(x) {
snippet.log("Before:");
snippet.log(x);
x = processString(x);
snippet.log("After:");
snippet.log(x);
document.body.appendChild(document.createElement('hr'));
}
function processString(x) {
x = x.replace(/^(?:(?:>|>|&gt;).*?[\r\n]+)+/gm, function(m) {
return '<div class="quote">' + m.replace(/^(?:>|>|&gt;)/gm, '') + '</div>';
});
return x;
}
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
">Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
test(
"So, Mike, you say:\n" +
"\n" +
">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"&gt;Nam mi dui, porta non gravida id\n" +
">sodales venenatis tellus\n" +
"\n" +
"But this makes no sense!\n"
);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
这是如何完成的:匹配所有块,然后在回调函数内,拆分它并删除初始 >
并包装在 div
:
var s = 'So, Mike, you say:\n\n>Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n>Nam mi dui, porta non gravida id\n>sodales venenatis tellus\n\nBut this makes no sense!';
var res = s.replace(/^(?:(?:>|&(?:amp;)?gt;)[^\n]+)+/gm, function(m, grp1, grp2, offset, input) {
return m.split("\n").map(function(el) {
return '<div class="quote">' + el.replace(/(?:>|&(?:amp;)?gt;)/g,'') + "</div>";
}).join("\n");
});
alert(res);