2

So I have this function that I created that replaces special characters that are inside of a string. The main intent was to replace those special characters that were inside of the BBCode tag ([code=any]my code that I want to show[/code]), but at the time it didn't really matter if it replaced the rest of the string outside of the BBcode tag. But now I'm having problems with it replacing HTML tags that are outside of the BBcode tag. So I was trying to come up with a solution for this, but no luck so far.

The goal is to replace the special characters that are inside of the:

[code=any]some code inside of here[/code]

Also should mention that when I say code=any meaning it can be anything. It could be HTML,CSS,PHP,JS [a-z-A-Z-0-9].

so more like

[code=[a-z-A-Z-0-9]<h1>some html insode of the bbcode to be replace</h1>[/code]

My current function is simple. Just some basic regular expression is needed:

replaceSpecial : function(str) {

str = str.replace(/&/g, "&amp;");
str = str.replace(/>/g, "&gt;");
str = str.replace(/</g, "&lt;");
str = str.replace(/"/g, "&quot;");
str = str.replace(/'/g, "&#039;");

return str;
}

But how would I go about rewriting that so that it will only replace text that is inside of the: [code=any]some code inside here[/code] and that's it. If anyone has a solution for this, that would be awesome.

Thanks for your time, Jon W

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Jon W
  • 39
  • 6

2 Answers2

2

Do you want to extract the text inside a barcode and apply this regular expression, you can use exec to just apply the replace to what is inside the code, can use Capturing Groups and Backreferences see more link https://www.regular-expressions.info/refcapture.html

in this case, only get the text of inside the bbcode and process it

let code = "[code=any]<h1>hello and bye</h1>e[/code]";
//extract only texto inside bbcode
let match = /\[code\=any\](.+)\[\/code\]/g.exec(code)[1];
//get <h1>hello</h1>e
let replacement = myObj.replaceSpecial(match);

enter image description here

see https://regex101.com/r/KGCWmq/1

This would only be if you want to get, if you want to replace you can use the replace function.

var myObj = {
    replaceSpecial : function(str) {
        str = str.replace(/&/g, "&amp;");
        str = str.replace(/>/g, "&gt;");
        str = str.replace(/</g, "&lt;");
        str = str.replace(/"/g, "&quot;");
        str = str.replace(/'/g, "&#039;");
        return str;
    }
};
let code = "[code=any]<h1>hello and bye</h1>e[/code]";
let match = /\[code\=any\](.+)\[\/code\]/g.exec(code)[1];
let replacement = myObj.replaceSpecial(match);
let string = code.replace(/\[code\=any\](.+)\[\/code\]/,"[code=any]"+replacement+"[/code]")

UPDATED

According to the answer of Wiktor Stribiżew, the regular expression can be validated so that the bbcode is any

myObj = {
  replaceSpecial : function(str) {
     return str.replace(/&/g, "&amp;")
               .replace(/>/g, "&gt;")
               .replace(/</g, "&lt;")
               .replace(/"/g, "&quot;")
               .replace(/'/g, "&#039;");
  }
}

var s = '[code="HTML"]<h1>Hello</h1>[/code]';
var regex = /(\[code=[^\]]*])([^]*?)(\[\/code])/gi;
console.log( s.replace(regex, function($0, $group_match1, $group_match2, $group_match3) { return $group_match1 + myObj.replaceSpecial($group_match2) + $group_match3; }) );

I hope I have helped you and if it is not what you expect, make a comment and edit the question

  • 1
    Well, it would be nice if it was one whole function and it just turned the whole value after it was done replacing it. I'm trying to figure out how to make this work so its just one whole functions. I do believe that is pretty close though. – Jon W Mar 17 '19 at 04:52
  • 1
    That is exactly what I was trying to do though. – Jon W Mar 17 '19 at 04:57
  • 1
    Correct me if I'm wrong, but this will only work if the BBCode is exactly [code=any]some text[/code] right? In which case that won't work. The code can be HTML, CSS, PHP, JS, so really when I said any I mean anyone single word. – Jon W Mar 17 '19 at 05:12
  • You can use the expression mentioned in the following answer and it is divided into three groups /(\[code=[^\]]*])([^]*?)(\[\/code])/gi – Herman Andres Figueroa Mar 17 '19 at 14:52
  • I have updated my answer, based on the optimizations of the following answer – Herman Andres Figueroa Mar 17 '19 at 15:02
  • @WiktorStribiżew I apologized but at the time I was writing a similar solution, and that's why I mentioned you in the answer. – Herman Andres Figueroa Mar 20 '19 at 00:11
1

If you have no nested code tags you may use

/(\[code=[^\]]*])([^]*?)(\[\/code])/gi

Or, if you find issues with this regex performance, replace it with its equivalent that is written according to the unroll-the-loop principle:

/(\[code=[^\]]*])([^[]*(?:\[(?!\/code])[^[]*)*)(\[\/code])/gi

See the regex demo (and the optimized regex demo).

Details

  • (\[code=[^\]]*]) - Group 1: [code= and then any 0+ chars other than ] and then ]
  • ([^]*?) - Group 2: any 0 or more chars, as few as possible (*? is a *non-greedy quantifier)
  • (\[\/code]) - Group 3: [/code] substring.

Use it inside a String#replace like this:

function replaceSpecial(str) {
  return str.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}

var s = '[code="JS"]<p align="center">D&elete the "Go" \'icon\'.</h1>[/code]';
var regex = /(\[code=[^\]]*])([^]*?)(\[\/code])/gi;
console.log( s.replace(regex, function($0, $1, $2, $3) { return $1 + replaceSpecial($2) + $3; }) );

Note: if you ever have to exclude [code= in between the [code= and [/code], you will need to adjust the regex to

/(\[code=[^\]]*])([^[]*(?:\[(?!\/?code[\]=])[^[]*)*)(\[\/code])/gi

See this regex demo.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563