Match a set of characters but ignore it if followed by or proceeded by another set of characters

Okay, so I get more and more annoyed that JavaScript doesn’t have negative lookbehind :frowning: However, I think this can be done, but I’m struggling to find a clean solution.

Here is the code to start with

  function replaceChecklist(text) {
    text = text || "";
    text = text.replace(/\[\s?\]/ig, '<span class="chcklst-box fa fa-square-o"></span>');
    text = text.replace(/\[_\]/ig, '<span class="chcklst-box fa fa-square"></span>');
    text = text.replace(/\[-\]/ig, '<span class="chcklst-box fa fa-minus-square-o"></span>');
    text = text.replace(/\[x\]/ig, '<span class="chcklst-box checked fa fa-check-square"></span>');
    text = text.replace(/\[\*\]/ig, '<span class="chcklst-box checked fa fa-check-square-o"></span>');
    return text;

Here is the input and expected output

[] output <span class="chcklst-box fa fa-square-o"></span>
[ ] output <span class="chcklst-box fa fa-square-o"></span>
[_] output <span class="chcklst-box fa fa-square"></span>
[-] output <span class="chcklst-box fa fa-minus-square-o"></span>
[x] output <span class="chcklst-box checked fa fa-check-square"></span>
[*] output <span class="chcklst-box checked fa fa-check-square-o"></span>

Here are the false positive matches that are messing up markdown

![](myimage.jpg) outputs !<span class="chcklst-box fa fa-square-o"></span>(myimage.jpg)

Okay, so now you see my problem, what is the best way to correct this behavior?

I thought about running a match on ![]( but that just tells me if it exists anywhere in the text, but there may be instances of [], [_], et al that still need to be replaced. Another option would be to remove the ? on the \s but that would break existing functionality. :frowning:

So what ideas do you have for solving this? Bonus points go to whoever can do it using only a single regex, but if I need to add additional conditionals around the code, I at least have the option.


I tried this \[\s?\][^(] and it comes close. Other than it doesn’t support [] by itself, you must have a space or non ( following it. And it ignores the fact that it can’t have a proceeding ! which is what actually denotes the image tag in markdown.

Edit 2:

This is much closer ([^\!]|^)\[\s?\] and the proceeding text is far more important than the (myimage.jpg) match. But I still think there is a better solution out there.

Yes - negative lookbehind :frowning:

The only possible substitute I can think of could be a monster memory hog.

Get the position in the string, then run through again and if found negate.

Definitely wouldn’t be as nice as a one-liner regex.

Yeah, closest solution to that is the ([^\!]|^)\[\s?\]. It actually works pretty well for all of the use cases I’ve thrown at it. I’m about to test it in the actual application to see if it holds up there.

Ugh, nm, that has a nasty consequence of removing line breaks. :frowning: So that method won’t work either.

Okay, I think I solved it. After thinking about it a bit more, I simply needed to replace the generated output with the ! again.

I simply had to add at the very end

    text = text.replace(/!<span class="chcklst-box (checked )?(fa fa-(square-o|square|minus-square-o|check-square|check-square-o))"><\/span>/ig, "![]");

That way it takes the false positive and swaps it back to the image markdown syntax. :smile:

1 Like

Ah. Why are you attempting Markdown parsing in Javascript?
Isn’t there an API (microservice) you could call on for the dirty work?

It is a plugin for Discourse, it actually isn’t attempting markdown parsing, but rather correcting the fact that JavaScript doesn’t have negative lookbehinds, so it is converting more instances of than it should and I need to revert those false positives.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.