用于将引用语法转换为HTML的正则表达式

时间:2015-09-03 09:50:18

标签: javascript regex quoting

我的用户有一个引用语法,类似于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\"> $2 </div>");

是否可以编写这样的正则表达式?如果是,它会是什么样子?

2 个答案:

答案 0 :(得分:1)

这是试图用正则表达式操纵HTML。 (我说这是基于你为>搜索HTML实体的事实,而不是>的字面意思。)这几乎总是一个坏主意,几乎与尝试使用正则表达式解析HTML一样糟糕。 Obligatory Link

您只能通过一次replace来拨打电话。但令我惊讶的是,你可以使用两个,或者使用一个函数回调来进行一系列内部调用的外部调用。

这是双通话版本:

x = x.replace(/^(?:(?:>|&gt;|&amp;gt;).*?[\r\n]+)+/gm, '<div class="quote">***$&</div>');
x = x.replace(/(?:\*\*\*|^)(?:>|&gt;|&amp;gt;)/gm, '');

第一个发现带有引号标记的行的重复系列,并在它们周围包裹div标记。 (我在集合中添加了原始>,因此它会查找>&gt;&amp;gt; [请参阅下面有关最后一个的说明]。)第二个删除引号标记。您无法在第一个replace中删除它们,因为您要替换整组线路。另请注意,我必须在第一个标记前加上前缀,因为一旦我们添加了div标记,它就不再在行的开头了。

这是一次调用suballs版本:

x = x.replace(/^(?:(?:>|&gt;|&amp;gt;).*?[\r\n]+)+/gm, function(m) {
  return '<div class="quote">' + m.replace(/^(?:>|&gt;|&amp;gt;)/gm, '') + '</div>';
});

他们有多强大?可能不是很明显,请看上面答案的第一段。 : - )

旁注:您的正则表达式似乎在寻找&amp;gt;作为引号标记。我已保留上述内容,但如果您的HTML中有&amp;gt;,则表示双重编码 HTML,这通常是其他地方问题的指示。

两个调用版本的实例,其中包含各种不同引号标记的变体:

&#13;
&#13;
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;|&amp;gt;).*?[\r\n]+)+/gm, '<div class="quote">***$&</div>');
  x = x.replace(/(?:\*\*\*|^)(?:>|&gt;|&amp;gt;)/gm, '');
  return x;
}

test(
  "So, Mike, you say:\n" +
  "\n" +
  ">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
  "&amp;gt;Nam mi dui, porta non gravida id\n" +
  "&gt;sodales venenatis tellus\n" +
  "\n" +
  "But this makes no sense!\n"
);
test(
  "So, Mike, you say:\n" +
  "\n" +
  "&amp;gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
  ">Nam mi dui, porta non gravida id\n" +
  "&gt;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" +
  "&amp;gt;Nam mi dui, porta non gravida id\n" +
  ">sodales venenatis tellus\n" +
  "\n" +
  "But this makes no sense!\n"
);
&#13;
<!-- 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>
&#13;
&#13;
&#13;

一次调用子版本的实例:

&#13;
&#13;
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;|&amp;gt;).*?[\r\n]+)+/gm, function(m) {
    return '<div class="quote">' + m.replace(/^(?:>|&gt;|&amp;gt;)/gm, '') + '</div>';
  });
  return x;
}

test(
  "So, Mike, you say:\n" +
  "\n" +
  ">Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
  "&amp;gt;Nam mi dui, porta non gravida id\n" +
  "&gt;sodales venenatis tellus\n" +
  "\n" +
  "But this makes no sense!\n"
);
test(
  "So, Mike, you say:\n" +
  "\n" +
  "&amp;gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
  ">Nam mi dui, porta non gravida id\n" +
  "&gt;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" +
  "&amp;gt;Nam mi dui, porta non gravida id\n" +
  ">sodales venenatis tellus\n" +
  "\n" +
  "But this makes no sense!\n"
);
&#13;
<!-- 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>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

以下是如何完成的:匹配所有块然后在回调函数中,拆分它并删除初始>并包裹在div中:

&#13;
&#13;
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);
&#13;
&#13;
&#13;