Javascript 不解析嵌套 Bbcode

发布于 2024-08-24 15:44:19 字数 4985 浏览 5 评论 0原文

我编写了一个 Javascript bbcode,类似于我用来编写此消息的代码。它还包含一个实时预览框,如下所示。我目前面临的唯一问题是某些嵌套的 bbcode 无法解析。

例如:

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

解析不正确。

这是我目前的 JavaScript。

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);
}

这会翻转我所有的 bbcode 标签。引用标签存在问题,因为它有时不会翻转嵌套的引用标签或解析内部引用标签的内容。

如果有人能够提供解决方案,我将非常感激。谢谢你!

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,'<');
    txt = txt.replace(/>/g,'>');

    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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橘虞初梦 2024-08-31 15:44:19

三种解决方案:

  1. 编写一个解析器。这将产生最佳解决方案,但需要付出很大的努力。

  2. 查找 BBCode 解析库。质量可能与#1 一样好,而且简单得多。

  3. 在每个标签正则表达式的内部添加一个否定的前瞻并连续应用直到没有匹配。例如:

    \[引用\]((?:[^](?!\[引用\]))*?)\[\/引用\]
    

    这将捕获内部引用,然后在替换后捕获外部引用。不像其他两个那么干净,但可能是最快的修复。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文