Rather than using dangerouslySetInnerHTML
, I'm trying to manually parse a small subset of Markdown and transform them into React components. I need to this because I have some custom components that I will also need to render in the message field, so I will need to be turning these into React components anyway. Also it avoids the possibility of an XSS attack.
My original idea was just to split the message on space and conditionally turn each token into a React component, similar to this:
matchMarkdown(part) {
let match = part.match(/(^|[^\\])(\*)(.*)(\*)/g); // match on *asdf* but not \*asdf*
if (match !== null) {
return <strong> {match[3]}</strong>;
}
match = part.match(/(^|[^\\])(_)(.*)(_)/); // match on _qwer_ but not \_qwer_
if (match !== null) {
return <em> {match[3]}</em>;
}
return " " + part;
}
convertMarkdownToComponents() {
let parts = this.state.body.split(" ");
return (
<div>
{parts.map(this.matchMarkdown)}
</div>
);
}
And this almost works, except for the problem that it is splitting on spaces only. For example, it will work on this message:
the _quick_ *brown* fox
but not on this message:
the _quick_*brown* fox
because there is no space separating the tokens. I'd like that message to turn into something like this:
the quick brown fox
I'm looking to have it work even without spaces, and not sure how. Also, the current solution seems pretty brittle regarding spaces preceding everything. Any advice?