如何在忽略之前替换的主题标签的同时,用超链接替换内容可编辑的 div 中的所有主题标签?

How do I replace all hashtags in a contenteditable div with a hyperlink while ignoring previously replaced hashtags?

我正在构建主题标签转换器功能。每次用户点击输入或 space 时,我都需要检查用户的文本中是否有主题标签。我用这个正则表达式使用了以前的答案:

HTML

<div class="post-input-field" contenteditable="true">My favourite dish is <a href=#>#sushi</a>#but I also like #pizza. </div>

JQuery

/**
* Trigger when someone releases a key on the field where you can post remarks, posts or reactions
*/
$(document).on("keyup", ".post-input-field", function (event) {

   // if the user has pressed the spacebar (32) or the enter key (13)
   if (event.keyCode === 32 || event.keyCode === 13) {
      currentCommentText = currentCommentText.replace(/#(\w+)/g, "<a class='hashtag' href=" + url + " target='_blank'>$&</a>&nbsp;").replace("<br>", ""); //replace hashtags with a link

      textField.html(currentCommentText);
   }
});

如果用户将每个唯一的主题标签都写一次,这就可以正常工作。但是,当用户两次键入相同的主题标签时,它也会在先前获取的主题标签前面添加 link。

如您所见,#sushi 和#pizza 后面有几个 space。如果我放大并检查为什么会发生这种情况:

您可以看到正则表达式并没有真正发挥作用。我听说使用正则表达式替换 html 不是很理想。有没有办法检查话题标签,只替换文本中尚未转换的话题标签?

选项 1:

在再次进行替换之前从字符串中删除 HTML。只需将 HTML 放入空白 div 中,然后从中取出文本。

$(document).on("keyup", ".post-input-field", function (event) {
   if (event.keyCode === 32 || event.keyCode === 13) {
      var val = $(this).val();
      // strip html from val
      val = $('<div>').html(val).text();
      val = val.replace(/#(\w+)/g, "<a class='hashtag' href=#>$&</a>&nbsp;").replace("<br>", ""); 
      $(this).val(val);
   }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="post-input-field" contenteditable="true"></textarea>

选项 2:

(^|\s) 开始您的模式,这将仅匹配行开头的主题标签 (^) 或跟随一些空格的主题标签 (\s) - 这将导致它忽略已经在锚标记中的主题标签。然后,您必须替换替换字符串以包含第二个匹配组 (</code>)。</p> <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code"> <pre><code>$(document).on("keyup", ".post-input-field", function (event) { if (event.keyCode === 32 || event.keyCode === 13) { var val = $(this).val(); val = val.replace(/(^|\s)(#\w+)/g, " <a href=#></a>").replace("<br>", ""); $(this).val(val); } });

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="post-input-field" contenteditable="true"></textarea>

此正则表达式查找所有尚未包含在 hyperlink 中的主题标签。它还创建了两个组,我们可以使用它们来形成主题标签的 link。 https://regex101.com/r/EUNySg/13

/(?!\s*#\w+\s*<\/a>)(#(\w+))/g

JQuery

$(document).on("keyup", ".post-input-field", function (event) {
   if (event.keyCode === 32 || event.keyCode === 13) {
      let html = $(this).html();
      html = html.replace( /(?!\s*#\w+\s*<\/a>)(#(\w+))/g, "<a class='hashtag' href='https://google.com/'></a>&nbsp;").replace("<br>", ""); 
      $(this).html(html);
   }
});

您可以在下面看到所有#hashtag 都被突出显示,但#notahashtag 没有突出显示。