Format text as like WhatsApp or stackoverflow (Replace symbols to style as bold, italic, and strikethrough in text)

679 Views Asked by At
*this text is bold*, 
_this text is italic_, 
~this text is strikethrough~. 
~_*this text is bold, italic and strike-through*_~

I want these text to be presented as,

<b>this text is bold</b>, 
<i>this text is italic</i>, 
<s>this text is strikethrough</s>. 
<s><i><b>this text is bold, italic and strike-through</b></i></s>

I have tried this regex and It works for a combination of symbols (*, _, ~).

text
    .replace(/(?:\*)(?:(?!\s))((?:(?!\*|\n).)+)(?:\*)/g, '<b>$1</b>')
    .replace(/(?:_)(?:(?!\s))((?:(?!\n|_).)+)(?:_)/g, '<i>$1</i>')
    .replace(/(?:~)(?:(?!\s))((?:(?!\n|~).)+)(?:~)/g, '<s>$1</s>');

But as per WhatsApp's rules. It does not work all the time. For example, using some specific characters (, : ; space _ ~ . \n * _ ~) at the beginning of the block, it allows the block to be bold/ italic. But using different character will restricts the block from being bold/ italic/ strike-through.

*this text is bold* -> <b>this text is bold</b>
,*this text is bold* -> ,<b>this text is bold</b>
@*this text is not bold* -> @*this text is not bold* (Unchanged! will not be bold.)

Also, there are some other conditions. Using more than 2 symbols (* _ ~) will restrict the block from being bold/ italic.

**this text is bold** -> <b>*this text is bold*</b>
***this text is not bold** -> ***this text is not bold** (unchanged! will not be bold!)

I want to handle all those WhatsApp conditions. Can I do this using regex?

1

There are 1 best solutions below

1
Reilas On

You can try the following.

Although, if the text contains any of those characters, it will produce an unexpected result.

var string = `
These should pass
  *this text is bold*, 
  _this text is italic_, 
  ~this text is strikethrough~. 
  ~_*this text is bold, italic and strike-through*_~

And, these should fail
  _ example_
  {*example*}
  example*
  example*
`;

string = string.replace(/(?<![{[?}\]])\*(?!\s)(.+?)\*/g, '<b>$1</b>');
string = string.replace(/(?<![{[?}\]])_(?!\s)(.+?)_/g, '<i>$1</i>');
string = string.replace(/(?<![{[?}\]])~(?!\s)(.+?)~/g, '<s>$1</s>');

console.log(string);