1

I'm building an application where users highlight and scroll to words in an article they write in search bar. articles come in a Markdown format and I'm using a Markdown-it to render article body.

It works well except for if the word they search for is part of an image URL. it applies regular expression to it and image breaks.

    applyHighlights() {
      let str = this.article.body
      let searchText = this.articleSearchAndLocate
      const regex = new RegExp(searchText, 'gi')
      let text = str
      if (this.articleSearchAndLocate == '') {
        return text
      } else {
        const newText = text.replace(
          regex,
          `<span id="searchResult" class="rounded-sm shadow-xl py-0.25 px-1 bg-accent font-semibold text-tint">$&</span>`
        )
        return newText
      }
    }

Is there a way to exclude applying regex if it's an Image URL ?

  • Can you give an example of a real input that's not working, the output you expected for it, and the output you're actually getting? What do you mean by "the image breaks" - how does it break? I suspect the problem is either that you haven't escaped searchText before putting it into a regex, or in your implementation of "articleSearchAndLocate" which isn't shown here. – Arcaeca Dec 26 '21 at 19:16
  • Hi Let's say this is an article body Ut quis voluptatem vitae ipsum. A numquam numquam et veritatis eos libero. ![photo-1638913662415-8c5f79b20656](https://images.unsplash.com/photo-1638913662415-8c5f79b20656) if I search using "photo" regex is applied to image alt and url and it becomes a string instead of being parsed by markdown it. The issue for me is I found how to exclude image structure `^(?:!\[(.*?)\]\((.*?)\))` but whenever I try to apply it, it gives me ** Invalid flags supplied to RegExp constructor '/^(?:!\[(.*?)\]\((.*?)\))/gi' ** – adhamfarrag Dec 26 '21 at 19:41
  • @Arcaeca I was doing it wrong.. but still can't figure it out how to add user input without markdown image syntax `![image-alt](image-link)` which could be traced using `(?:!\[(.*?)\]\((.*?)\))` – adhamfarrag Dec 26 '21 at 20:34

1 Answers1

1

You can use

applyHighlights() {
  let str = this.article.body
  let searchText = this.articleSearchAndLocate
  const regex = new RegExp('(!\\[[^\\][]*]\\([^()]*\\))|' + searchText.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi')
  let text = str
  if (this.articleSearchAndLocate == '') {
    return text
  } else {
    const newText = text.replace(
     regex, function(x, y) { return y ? y :
      '<span id="searchResult" class="rounded-sm shadow-xl py-0.25 px-1 bg-accent font-semibold text-tint">' + x + '</span>'; })
    return newText
  }
}

Here,

  • new RegExp('(!\\[[^\\][]*]\\([^()]*\\))|' + searchText.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi') - creates a regex like (!\[[^\][]*]\([^()]*\))|hello that matches and captures into Group 1 a string like ![desc](value), or it matches hellow (if the searchText is hello).
  • .replace(regex, function(x, y) { return y ? y : '<span id="searchResult" class="rounded-sm shadow-xl py-0.25 px-1 bg-accent font-semibold text-tint">' + x + '</span>'; }) means that if Group 1 (y) was matched, the return value is y itself as is (no replacement is peformed), else, the x (the whole match, searchText) is wrapped with a span tag
  • .replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') is necessary to support searchText that can contain special regex metacharacters, see Is there a RegExp.escape function in JavaScript?
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thanks for your approach to write this regex. But it didn't work. I'm trying to exclude markdown image tags not html img tags, something like this. https://www.regextester.com/95855 `![image-alt](image-url)` Tried replacing your regex with this one `const regex = new RegExp('^(?:!\[(.*?)\]\((.*?)\))|' + searchText.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi')` but it didn't work also. – adhamfarrag Dec 26 '21 at 23:01
  • @adhamfarrag I adjusted the pattern. Do not forget to double escape backslashes in regular string literals. – Wiktor Stribiżew Dec 26 '21 at 23:31