需要更简单的方法将嵌套自定义标签替换为HTML当量



我正在寻找一种用HTML等效物正确替换嵌套自定义标签的方法。例如,假设我们有以下文本:

This is {b:bold text}

应该变成:

This is <b>bold text</b>

我知道我可以 - 可能应该 - 使用具有"粗体"类的跨度,而不是旧的" b"标签,但是有一个原因我是为此目的而坚持使用" b"的原因这个示例。我可能有嵌套标签:

This is {b:bold text and {i:italic}}

应该变成:

This is <b>bold text and <i>italic</i></b>

但是,我有这些Regexes(我将其用于替换()函数):

/{b:([sS]*?)}/gm
/{i:([sS]*?)}/gm

然后结果将成为:

This is <b>bold text and <i>italic</b></i>

标签未正确嵌套。同样,在这种情况下,使用跨度可以解决此问题,但这与" ul"," li"," h1",...如果文本看起来像这样,贪婪的言论也会引起问题:

This is {b:bold text} and {i:italic}

因此,我当前的解决方案是首先使用数据物标签属性来替换所有内容,以指示其实际应该是什么,然后使用jQuery查找所有跨度节点,然后用适当的标签替换它们:

{h:This is a header}
becomes
<span data-tag='h1'>This is a header</span>
becomes
<h1>This is a header</h1>

它运行良好,但是我想知道是否有一种更简单的方法可以做到这一点。中间方法有点像胶带解决方案,我想"美化"它。

有什么建议?

一个简单的堆栈变长

function doReplace( str ) {
    var stack = [],
        ret = [],
        ch;
    for( var i = 0, l = str.length; i < l; ++i ) {
        var ch = str.charAt(i);
        if( ch === "{" ) {
            var pos = str.indexOf( ":", i+1);
            if( pos < 0 ) {
                throw new SyntaxError();
            }
            var tagName = str.substring( i + 1, pos);
            if( /[^A-Za-z0-9]/.test(tagName)) {
                throw new SyntaxError();
            }
            ret.push( "<" + tagName + ">" );
            stack.push( tagName);
            i+= tagName.length + 1;
        }
        else if( ch === "}" ) {
            if( !stack.length ) {
                throw new SyntaxError();
            }
            var tagName = stack.pop();
            ret.push( "</" + tagName + ">" );
        }
        else {
            ret.push( ch );
        }
    }
    if( stack.length ) {
        throw new SyntaxError();
    }
    return ret.join("");
}
doReplace( "This is {b:bold text {i:italic text{i:italic text{i:italic text{i:italic text{i:italic text{i:italic text}}}}}}}")
//"This is <b>bold text <i>italic text<i>italic text<i>italic text<i>italic text<i>italic text<i>italic text</i></i></i></i></i></i></b>"

ditch ditch the Regex并使用其中的许多模板工具之一,例如Mustache或T.Js。

编辑: 修复!

...但是,如果您避免生活中的这种简单性,这是用正则表达式进行的方法:

var rex = /{(b|i):([^{}]*)}/igm,
    parse = function(txt) {
        var cnt = 0,
            more = true;
        while (more) {
            txt = txt.replace(rex, function(match, $1, $2) {
                return "<" + $1 + ">" + $2 + "</" + $1 + ">";
            });
            more = rex.test(txt);
            cnt++;
        }
        return txt;
    };

因此,您致电parse并将其传递给您的字符串。它会递归地解析您的字符串,直到找不到其他标记为止。这个新的一个反向起作用,解析没有物品的项目,然后向外移动。

要实现您添加的H1示例,您可以使用{h1:This is the header}并将其添加到(b|i)子句中,或者在替换函数中使用switch语句,而不仅仅是返回$1。

这是jsfiddle。

最新更新