How to go through string and replace ** with <b></b>

Asked

Viewed 1,618 times

8

Lately I have used some systems that have the following function, when writing a text between ** it turns this text into bold for example:

Julio *Enrique* dos Santos

expected result will be:

Julio Henrique dos Santos

I thought about creating something similar using javascript and html, but I found many difficulties:

Div result:

<div id="text"></div>

Javascript and jQuery code:

var str = "Visit jsduflsd fjkdsufdsjlkfds djfuldsifjdlsk *jflusdlkfjdsds* jfdisufkljds!";
var res = str.replace("*", "<b>");
$("#text").html(res);

Unfortunately I couldn’t get out of there. He changes the first * by a <b>, but does not close it and has to be something flexible to do whenever it occurs in string. Is there any way? I thought about REGEX, but I don’t know if it would be possible.

  • Related answer: https://answall.com/a/98376/5878

  • Would be only 1 bold or could occur more than 1?

  • 1

    Opa Sam! would be more often, this at the end of the question :)

2 answers

10


Using regex:

var str = "*Visit* jsduflsd \\*fjkdsufdsjlkfds\\* djfuldsifjdlsk *jflusdlkfjdsds* jfdisufkljds!";
var res = (" "+str).replace(/([^\\])\*([^\*]*)([^\\])\*/g, "$1<b>$2$3</b>");
res = res.trim();
res = res.replace(/\\\*/g, "*");
document.write(res)

  • ( Starts the character capture
  • [^\\] Any character that is different from \
  • ) Closes the character capture
  • \* Begins with* to \ to escape
  • ( Starts the character capture
  • [^\*]* all characters different from * repeated 0 or many times
  • ) Closes the character capture
  • ( Starts the character capture
  • [^\\] Any character that is different from \
  • ) Closes the character capture
  • \* Ends with* to \ to escape
  • $1, $2 and $3 Serves to "glue" what was captured

Catch all the * not preceded by \ serves to escape them, but this requires that there be a character before the *, if the string starts with the bold markdown, it will fail because there is no previous character. To resolve this, a before ((" "+str)) and is taken away with trim. It is also necessary to "reset" this previous character, so the $1 and $2 After making the switch to the HTML tags then the escaped Markdowns are replaced (\* for *)

Example of more dynamic use:

String.prototype.markdown = function(caracter, tag) {
  return (" "+this).replace(new RegExp(`([^\\\\])\\${caracter.split('').join('\\')}([^\\${caracter.split('').join('\\')}]*)([^\\\\])\\${caracter.split('').join('\\')}`, 'g'), `$1<${tag}>$2$3</${tag}>`).trim().split(`\\${caracter}`).join(caracter);
}

document.querySelector('textarea').oninput = function() {
  document.querySelector('p').innerHTML = this.value.markdown('*', 'b').markdown('--', 'strike');
}
<textarea cols='75'>--riscado-- \--riscado\-- *negrito* \*negrito\*</textarea>

<p>

Of a space in the textarea to load with the example

  • 5

    My only suggestion would be to use the flag g in regex, to replace all occurrences and not just the first. /\*([^\*]*)\*/g

  • @fernandosavio very well remembered, updated the answer

  • I updated my answer with a more complete example

3

Regex is certainly the most practical and direct way to solve the problem as @Guilheremcostamilam has shown. The replace receiving a string like substitution works only for one substitution and not all, so it would not be possible to solve without regex.

The MDN clearly reinforces this point

If Pattern is a string, only the first Occurrence will be replaced

However, it would also be possible to solve it manually, even if it was much more laborious. To do so, you would have to have a boolean variable to know if you will add the start of the tag or end of the tag, and each time you find one * changes to start/close with the boolean. After each change you have to switch to boolean.

Example:

var str = "Visit *jsduflsd* fjkdsufdsjlkfds djfuldsifjdlsk *jflusdlkfjdsds* jfdisufkljds!";

let inicio = true, res = "";
for (let letra of str){
  if (letra === '*'){
    res += inicio ? "<b>": "</b>";
    inicio = !inicio;
  }
  else res += letra;
}

document.write(res);

If there is a possibility of a missing * without its pair and we don’t want you to be bold, then some additional concerns are already required, which will complicate and slightly increase the code.

Example:

var str = "Visit *jsduflsd* fjkdsufdsjlkfds djfuldsifjdlsk *jflusdlkfjdsds jfdisufkljds!";

let emBold = false, res = "", blocoBold ="";
for (let letra of str){
  if (letra === '*'){
    emBold = !emBold;
    if (emBold)
      blocoBold = "";
    else //só no fecho é que adiciona o bloco todo
      res += "<b>" + blocoBold + "</b>";
  }
  else {
    if (emBold)
      blocoBold += letra;
    else 
      res += letra;
  }
}

res += blocoBold;//adiciona o que ficou por fechar sem as tags
document.write(res);

  • The only problem is if the person "opened the bold" and did not close: example *negrito não fechado the rest of the page can be bold and break

  • @Guilhermecostamilam Well seen, who had not thought of this particular case. I edited the answer to contemplate also this situation in the same without regex.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.