Javascript Not Parsing Nested Bbcode

左心房为你撑大大i 提交于 2019-12-04 05:22:14

问题


I have coded a Javascript bbcode similar to the one I'm using to write this message. It also incorporates a live preview box like the one I see below. The only problem I'm facing at the moment is that some nested bbcode is not parsing.

For example:

[quote]
   [quote][/quote]
[/quote]

Is not parsing correctly.

This is my Javascript currently.

function preview() {

    var txt = $('#editor').val();
    txt = txt.replace(/</g,'&lt;');
    txt = txt.replace(/>/g,'&gt;');

    txt = txt.replace(/[\r\n]/g,'%lb%');

    var find    = [
                   /\[quote\](.*?)\[\/quote\]/gi,
                   /\[quote author="(.*?)" date="(.*?)"\](.*?)\[\/quote\]/gi,
                   /\[b\](.*?)\[\/b\]/gi,
                   /\[i\](.*?)\[\/i\]/gi,
                   /\[u\](.*?)\[\/u\]/gi,
                   /\[left\](.*?)\[\/left\]/gi,
                   /\[center\](.*?)\[\/center\]/gi,
                   /\[right\](.*?)\[\/right\]/gi,
                   /\[size=(10|12|24|30)](.*?)\[\/size\]/gi,
                   /\[font=(.*?)](.*?)\[\/font\]/gi,
                   /\[color=(.*?)](.*?)\[\/color\]/gi,
                   /\[url(?:\=?)(.*?)\](.*?)\[\/url\]/gi,
                   /\[email=(.*?)\](.*?)\[\/email\]/gi,
                   /\[email\](.*?)\[\/email\]/gi,
                   /\[img(.*?)\](.*?)\[\/img\]/gi,
                   /(?:%lb%|\s)*\[code(?:\=?)(?:.*?)\](?:%lb%|\s)*(.*?)(?:%lb%|\s)*\[\/code\](?:%lb%|\s)*/gi,

                   /\[list(.*?)\](.*?)\[\*\](.*?)(?:%lb%|\s)*(\[\*\].*?\[\/list\]|\[\/list\])/i,
                   /(?:%lb%|\s)*\[list\](?:%lb%|\s)*(.*?)(?:%lb%|\s)*\[\/list\](?:%lb%|\s)*/gi,
                   /(?:%lb%|\s)*\[list=(\d)\](?:%lb%|\s)*(.*?)(?:%lb%|\s)*\[\/list\](?:%lb%|\s)*/gi,
                   /(?:%lb%){3,}/g

                   ];
    var replace = [
                   '<blockquote><div class="quote"><div class="quote_body">$1</div></div></blockquote>',
                   '<blockquote><div class="quote"><div class="quote_author"><span class="quote_from">Quote from</span> <span class="author">$1</span> on <span class="date">$2</span></div><div class="quote_body">$3</div></div></blockquote>',
                   '<b>$1<\/b>',
                   '<i>$1<\/i>',
                   '<u>$1<\/u>',
                   '<div class="align_left">$1<\/div>',
                   '<div class="align_center">$1<\/div>',
                   '<div class="align_right">$1<\/div>',
                   '<span style="font-size:$1px;">$2</span>',
                   '<span style="font-family:$1;">$2</span>',
                   '<span style="color:$1;">$2</span>',
                   '<a href="$1">$2</a>',
                   '<a href="mailto:$1">$2</a>',
                   '<a href="mailto:$1">$1</a>',                   
                   '<img $1 src="$2" />',
                   '<pre><code>$1</code></pre>',
                   '[list$1]$2<li>$3</li>$4',
                   '<ul>$1</ul>',
                   '<ol start=$1>$2</ol>',
                   '%lb%%lb%'

                   ];

    // fix [*] so that they only work inside [/list]
    for(var i in find)
    {
        txt = txt.replace(find[i],replace[i]);
        if(i == 17) while(txt.match(find[i],replace[i])) txt = txt.replace(find[i],replace[i]);
    }

    // Fix Smilies
    txt = txt.replace(/%lb%/g,'<br />');
    txt = txt.replace(/\:\)/g, '<img class="smiley" src="/img/smilies/smile.gif">');
    txt = txt.replace(/\:-\)/g, '<img class="smiley" src="/img/smilies/happy.gif">');
    txt = txt.replace(/\:D/g, '<img class="smiley" src="/img/smilies/biggrin.gif">');
    txt = txt.replace(/\:\(/g, '<img class="smiley" src="/img/smilies/sad.gif">');
    txt = txt.replace(/8\)/g, '<img class="smiley" src="/img/smilies/cool.gif">');
    txt = txt.replace(/=O/g, '<img class="smiley" src="/img/smilies/surprised.gif">');
    txt = txt.replace(/\:-\|\|/g, '<img class="smiley" src="/img/smilies/mad.gif">');
    txt = txt.replace(/\:P/g, '<img class="smiley" src="/img/smilies/stongue.gif">');
    txt = txt.replace(/\}\-\(/g, '<img class="smiley" src="/img/smilies/confused.gif">');

    // Format Dates
    txt = txt.replace(/\d{10}/g, function($0) {
        var d = new Date($0*1000);
        var months = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
        return "" + months[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear() + ", " + (d.getHours()%12) + ":" + d.getMinutes() + " " + (d.getHours()<12 ? 'AM' : 'PM');
    });

    // Update the preview box
    $('.preview').html(txt);
}

This flips most all my bbcode tags. The quote tag is problematic in that it sometimes does not flip nested quote tags or parse the contents of the inner quote tags.

If anyone is able to offer a solution I would be very grateful. Thank you!


回答1:


Three solutions:

  1. Write a parser. This will produce the best solution but takes a non-trivial amount of effort.

  2. Find a BBCode parsing library. Probably as good as #1 in quality and substantially easier.

  3. Add a negative lookahead to the inside of each tag regex and continuously apply until no match. E.g.:

    \[quote\]((?:[^](?!\[quote\]))*?)\[\/quote\]
    

    This will capture the inner quote, then once its replaced, the outer one. Not nearly as clean as the other two but probably the quickest fix.



来源:https://stackoverflow.com/questions/2421264/javascript-not-parsing-nested-bbcode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!