6

ネストされたカスタム タグを 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>

ただし、次の正規表現があります (replace() 関数で使用します)。

/\{b:([\s\S]*?)\}/gm
/\{i:([\s\S]*?)\}/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>

それはうまく機能しますが、これを行うより簡単な方法があるかどうか疑問に思っています。中間の方法は、少しガムテープのソリューションのように感じ、「美化」したいと考えています。

助言がありますか?

4

2 に答える 2

1

シンプルなスタックは長い道のりです

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>"
于 2012-12-20T19:26:09.447 に答える
0

Regex を捨てて、 Mustachet.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 の例を実装するには、代わりに usを句に{h1:This is the header}追加するか、$1 を返す代わりに replace 関数でステートメントを使用することができます。(b|i)switch

これがJSFiddleです。

于 2012-12-20T19:06:40.443 に答える