昨天只是簡單地驗證概念,今天先拿一個template引擎來測試一下。
swig模版引擎
swig是可以在node.js中運行的一個template引擎,他的速度相當快,而且功能也相當豐富,所以先拿它來測試一下。
swig的官網:
http://paularmstrong.github.com/swig/
線上說明:
https://github.com/paularmstrong/swig/tree/master/docs
文件是用markdown格式,雖然是放在github repository中,但是可以在線上直接瀏覽。
swig的使用很簡單,初始化之後,可以利用compileFile(filename)或是compile(string)兩個方法編譯template,這兩個方法會回傳編譯好的template物件,呼叫他的render(data obj)方法就可以產出結果。
template語法也很簡單,使用{{name}}就可以把透過render(data)傳入的物件的data.name引入。一些邏輯結構或判斷可以用內建的tag來做,例如{%for row in rows%},會處理data.rows陣列中的每一個元素,把它引入到從tag開始到{%endfor%}為止的內容中,變數名稱是{{row}}。
假設有一個template:
<title>{{title}}</title>
<table border="1" cellspacing="0" cellpadding="2">
{%for row in rows%}
<tr><td>{{row.name}}</td><td>{{row.email}}</td></tr>
{%endfor%}
</table>
然後render時使用的物件是:
{
title: 'swig template test',
rows: [
{name: 'test name1', email: 'name1@email.com'},
{name: 'test name2', email: 'name2@email.com'}
]
}
最後render的產出:
<title>swig template test</title>
<table border="1" cellspacing="0" cellpadding="2">
<tr><td>test name1</td><td>name1@email.com</td></tr>
<tr><td>test name2</td><td>name2@email.com</td></tr>
</table>
在route handler中使用swig
把昨天寫的程式稍微調整一下,就可以使用swig了。首先是views.js:
var swig = require('swig');
swig.init({
allowErrors: false,
autoescape: true,
encoding: 'utf8',
filters: {},
root: '.',
tags: {}
});
module.exports = {
"hello_mvc": function(cb) {
var view = swig.compileFile('tests/temp1.html');
this.render = function(data) {
cb(false, '/hello_mvc', {type:'text/html', data: view.render(data)});
};
}
};
models.js中的資料也需要稍微調整:
module.exports = {
"hello_mvc": function(view) {
var data = {
title: 'test swig template',
rows: [
{name: 'test name 1', email: 'name1@email.com'},
{name: 'test name 2', email: 'name2@email.com'}
]
};
this.execute = function() {
process.nextTick(function() {
view.render(data);
});
}
}
};
最後需要調整整合測試檔,setUp的部份:
.get('/hello_mvc', function (request, response, cb) {
var HelloModel = require('./models')['hello_mvc'];
var HelloView = require('./views')['hello_mvc'];
var m = new HelloModel(new HelloView(cb));
m.execute();
});
這部份沒有邏輯的變動,只是把測試資料以及views.js還有models.js移到tests資料夾中,並且調整名稱。實際做assertion的部份:
"test router hello_mvc": function(test) {
test.expect(6);
var req = this.http.request({
"host": "localhost",
"port": 8443,
"path": "/hello_mvc",
"method": "GET"
}, function(response) {
var result = [];
response.on('data', function(data) {
result.push(data);
});
response.on('end', function() {
var total = 0;
var entity = '';
for(var i=0; i<result.length; i++) {
total += result[i].length;
entity += result[i].toString('utf8');
}
test.equal(200, response.statusCode);
test.ok(entity.indexOf('test swig template')>-1);
test.ok(entity.indexOf('test name 1')>-1);
test.ok(entity.indexOf('test name 2')>-1);
test.ok(entity.indexOf('name1@email.com')>-1);
test.ok(entity.indexOf('name2@email.com')>-1);
test.done();
});
});
req.end();
}
因為輸出結果更複雜,所以用個多條件來做驗證。
接下來用ant integrate
做一下整合測試來看看結果:
Feng-Hsu-Pingteki-MacBook-Air:evolve fillano$ ant integrate
Buildfile: /Users/fillano/Dropbox/shared/evolve/build.xml
clear-lib-cov:
coverage-init:
integrate:
......
[exec] 3704::7: 6718720
[exec] 3704::/hello_mvc exists.
[exec] ok: test router hello_mvc
......
[exec]
[exec] OK: 20 assertions (229ms)
BUILD SUCCESSFUL
Total time: 2 seconds
OK,看起來整合其他的template引擎,這樣做也沒問題。接下來就要再看看model的部份了。
今天的範例檔fillano-evolve-v0.0.19-0-g74a4bbb.zip,目前版本是v0.0.19。