How to match bold markdown if it isn't preceded with a backslash?

二次信任 提交于 2020-01-16 12:02:14

问题


I'm looking to match bolded markdown. Here are some examples:

qwer *asdf* zxcv matches *asdf*

qwer*asdf*zxcv matches *asdf*

qwer \*asdf* zxcv does not match

*qwer* asdf zxcv matches *qwer*

A negative look behind like this (?<!\\)\*(.*)\* works.

Except there is no browser support in Firefox, so I cannot use it.

Similarly, I can get very close with (^|[^\\])\*(.*)\*

The issue is that there are two capture groups, and I need the index of the second capture group, and Javascript only returns the index of the first capture group. I can bandaid it in this case by just adding 1, but in other cases this hack will not work.

My reasoning for doing this is that I'm trying to replace a small subset of Markdown with React components. As an example, I'm trying to convert this string:

qwer *asdf* zxcv *123*

Into this array:

[ "qwer ", <strong>asdf</strong>, " zxcv ", <strong>123</strong> ]

Where the second and fourth elements are created via JSX and included as array elements.


回答1:


You will also need to take into account that when a backslash occurs before an asterisk, it may be one that is itself escaped by a backslash, and in that case the asterisk should be considered the start of bold markup. Except if that one is also preceded by a backslash,...etc.

So I would suggest this regular expression:

((?:^|[^\\])(?:\\.)*)\*((\\.|[^*])*)\*

If the purpose is to replace these with tags, like <strong> ... </strong>, then just use JavaScript's replace as follows:

let s = String.raw`now *this is bold*, and \\*this too\\*, but \\\*this\* not`;
console.log(s);

let regex = /((?:^|[^\\])(?:\\.)*)\*((\\.|[^*])*)\*/g;
let res = s.replace(regex, "$1<strong>$2</strong>");
console.log(res);

If the bolded words should be converted to a React component and stored in an array with the other pieces of plain text, then you could use split and map:

let s = String.raw`now *this is bold*, and \\*this too\\*, but \\\*this\* not`;
console.log(s);

let regex = /((?:^|[^\\])(?:\\.)*)\*((?:\\.|[^*])*)\*/g;
let res = s.split(regex).map((s, i) =>
    i%3 === 2 ? React.createComponent("strong", {}, s) : s
);

Since there are two capture groups in the "delimiter" for the split call, one having the preceding character(s) and the second the word itself, every third item in the split result is a word to be bolded, hence the i%3 expression.




回答2:


This should do the trick:

/(?:^|[^\\])(\*[^*]+[^\\]\*)/

The only capturing group there is the string surrounded by *'s.



来源:https://stackoverflow.com/questions/59201967/how-to-match-bold-markdown-if-it-isnt-preceded-with-a-backslash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!