Понимаю что тема старая
но раз уж всплыла, то вот мой вариант. Здесь в упрощенном виде, только самые простые теги, чтобы нагляднее была идея. А идея вот в чем: когда натыкаемся на открывающий тег, кладем его в стек. Если встретили закрывающий, то проверяем его соответствие верхушке стека, если не соответствует, оставляем бб-код, иначе ставим закрывающий и убираем со стека. В конце, если что-то осталось на стеке, добиваем "закрывашками".
var parseBB = function(str) {
if (!str) { return str; }
var rx = /\[(\/?)(b|i|u|s)\s*\]/gi;
var stack = [];
str = str.replace(rx, function(m, close, tag) {
tag = tag.toLowerCase();
if (close) {
if (!stack.length || (stack[stack.length - 1] !== tag)) {
return m;
}
stack.pop();
} else {
stack.push(tag);
}
return "<" + close + tag + ">";
});
if (stack.length) {
str = str + stack.reverse().map(function(tag) {
return "</" + tag + ">";
}).join("");
}
return str;
};