mass Framework第四種模板函數

之前mass Framework擁有三種不同級別的處理字符串拼接的模板函數:format,tag, ejs, 現在又增加一種新的,不過它隻適應於後端node.js環境中(因為在瀏覽器環境中,操蛋的FF會把註釋全部去掉……)。它利用多行註釋來模擬其他動態語言的here document。以下就是它的實現,其實是一個模塊,內部依賴於lang模塊的format方法。

mass.define("here_document","lang",function(){
    //隻允許最前面出現一個 "\*" ,隻允許最後面出現一個 "*/" 
    mass.hereDoc = function(f) {
        var str = f.toString().
        replace(/^[^\/]+\/\*!?/, '').
        replace(/\*\/[^\/]+$/, '');
        if(arguments.length > 1){
            arguments[0] = str;
            return mass.format.apply(mass,arguments)
        }
        return str
    }
})

用法如下:

mass.require("here_document",function(){
    var a = mass.hereDoc(function(){/*
        var bbb = "ccc"
    */
    });
    console.log(a)//輸出 var bbb = "ccc"
});

還支持兩種形式的占位符,詳見這裡

mass.require("here_document",function(){
    var a = mass.hereDoc(function(){/*
        var #{0} = "ccc"
    */
    },"ddd");
    console.log(a)//輸出 var ddd = "ccc"
});

一些更具體的應用。比如我的手腳架模塊scaffold.js,要通過模型的名字生成相應的控制器與動作函數

for(var controller in mapper.controllers){
           var object = mapper.controllers[controller];
           //創建控制器
           var contents = ["mass.define(\"",controller ,"_controller\",function(){\n", "\treturn {\n"]
           //創建動作
           contents.push( object.actions.map(function(action){
               return "\t\t\""+action + "\":function(){}"
           }).join(",\n"));
           contents.push("\n\t}\n });") ;
           createFile(path.join("app","controllers", controller +"_controller.js") ,contents.join("") )
           //….
 
       }

比如一個控制器名為comments,擁有 "index","create", "new","edit","destroy", "update", "show"這七個動作。那麼它會生成一個comments_controller.js文件,裡面內容為

mass.define("comments_controller",function(){
    return {
        "index":function(){},
        "create":function(){},
        "new":function(){},
        "edit":function(){},
        "destroy":function(){},
        "update":function(){},
        "show":function(){}
    }
});

但上面寫不直接,換成here document是這樣寫的:

for(var controller in mapper.controllers){
    var object = mapper.controllers[controller];
    //創建控制器
    var contents = mass.hereDoc(function(){/*
    mass.define("#{0}_controller",function(){
        return {
           #{1}
        }
    });*/
        },controller,object.actions.map(function(action){ //創建動作
            return "\t\t\""+action + "\":function(){}"
        }).join(",\n"));
    createFile(path.join("app","controllers", controller +"_controller.js") ,contents )
 
}

在手腳架的另一處應用中,它表現得更加明顯:

原來寫法,需要轉義

createFile('app/controllers/application_controller.js',
'before(\'protect from forgery\', function () {\n    protectFromForgery(\'' + secret + '\');\n});\n')

here document的實現則是:

createFile('app/controllers/application_controller.js',  mass.hereDoc(function(){/*
before('protect from forgery',function(){
    protectFromForgery("#{0}")
}) */  
    },secret));

你能一眼就看出其最終輸出結果,這對維護代碼的人來說是福音啊!

 摘自 Ruby's Louvre
 

發佈留言