0

This

[b]this text is bold[/b]
[i]this text is [b]italic[/b][/i]

parse out to this (in html)

<b>this text is bold[/b]<br><i>this text is [b]italic</i></b>

this text is bold[/b]
this text is [b]italic

using this function

function bbcode(input){
return input
.replace(/\[b\]([^]*)\[\/b\]/ig, '<b>$1</b>')
.replace(/\[i\]([^]*)\[\/i\]/ig, '<i>$1</i>');
}

I figure there has to be a problem with the regular expression finding each set of tags, but it appears that only the first bold tag and the last bold end tag are being parsed. Any idea how this can be fixed?

6
  • Nested logic in regex is hard, specially in JS since it doesn't support recursion. Commented Jun 5, 2013 at 2:23
  • 2
    What are you expecting [^]* to capture? Unless I'm mistaken, it's exclusion is applying to nothing, so it's essentially the same as .*. You'll most likely want to make that clause non-greedy, by adding a ? to make it [^]*?. Or, you may wish to actually exclude characters. Commented Jun 5, 2013 at 2:25
  • Why not just replace [b] with <b>, [/b] with </b> and so on? Also, [^] has to be the most creative way to write . I've ever seen. Commented Jun 5, 2013 at 2:27
  • @Patashu Replacing each individual start/end will cause issues in the (rare) case that someone writes a start without an end, or vice versa. Commented Jun 5, 2013 at 2:29
  • I came to [^] as I was working off examples and regex syntax is difficult to get a hold of. Once I got something that worked I stopped fussing with it. Commented Jun 5, 2013 at 2:32

1 Answer 1

1
function bbcode(input){
    var b = /\[b\]([^[]*(?:\[(?!b\]|\/b\])[^[]*)*)\[\/b\]/ig;
    var i = /\[i\]([^[]*(?:\[(?!i\]|\/i\])[^[]*)*)\[\/i\]/ig;
    while (input.search(b) !== -1) {
        input = input.replace(b,'<b>$1</b>');
    }
    while (input.search(i) !== -1) {
        input = input.replace(i,'<i>$1</i>');
    }
    return input.replace(/\n/ig, '<br>');
}

BBCode:

[b]x[b]y[/b]z[/b]
[b]this text is bold[/b]
[i]this text is [b]italic[/b][/i]

Usage:

var string = '[b]x[b]y[/b]z[/b]\n[b]this text is bold[/b]\n[i]this text is [b]italic[/b][/i]';
console.log(bbcode(string));

Output:

<b>x<b>y</b>z</b><br><b>this text is bold</b><br><i>this text is <b>italic</b></i>

See DEMO.

Sign up to request clarification or add additional context in comments.

3 Comments

Does this work correctly if you have something like [b]x[b]y[/b]z[/b] with nested tags of the same type?
@Patashu It does not, but I believe that level of parsing goes beyond the scope of the question, so I'll be giving this answer my vote.
It is important to note that this will only work for limited number of nesting levels.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.