UNPKG

3.22 kBJavaScriptView Raw
1/**
2 * 此插件为 yog-view 的 swig 版本显现。
3 * 依赖 yog-view。
4 */
5var Readable = require('stream').Readable;
6var util = require('util');
7var Swig = require('swig').Swig;
8var loader = require('./lib/loader.js');
9var tags = [
10 "script",
11 "style",
12 "html",
13 "body",
14 "require",
15 "uri",
16 "widget",
17 "head",
18 "feature",
19 "featureelse",
20 "spage"
21];
22
23/**
24 * Opitions 说明
25 * - `view` 模板文件
26 * - `locals` 模板变量
27 * - `views` 模板根目录
28 * - `loader` 模板加载器,默认自带,可选。
29 *
30 * layer 参数,为 yog-view 的中间层,用来扩展模板能力。
31 * 比如通过 addScript, addStyle 添加的 js/css 会自动在页面开头结尾处才输出。
32 *
33 * 更多细节请查看 yog-view
34 *
35 * @return {Readable Stream}
36 */
37var SwigWrap = module.exports = function SwigWrap(options, layer) {
38
39 if (!(this instanceof SwigWrap)) {
40 return new SwigWrap(options, layer);
41 }
42
43 // 重写 loader, 让模板引擎,可以识别静态资源标示。如:example:static/lib/jquery.js
44 options.loader = options.loader || loader(layer, options.views);
45
46 var swig = this.swig = new Swig(options);
47 this.options = swig.options;
48
49 tags.forEach(function (tag) {
50 var t = require('./tags/' + tag);
51 swig.setTag(tag, t.parse, t.compile, t.ends, t.blockLevel || false);
52 });
53
54 Readable.call(this, null);
55 this.buzy = false;
56};
57
58util.inherits(SwigWrap, Readable);
59
60SwigWrap.prototype._read = function(n) {
61 if (!this.buzy && this.options.view) {
62 this.renderFile(this.options.view, this.options.locals);
63 }
64};
65
66// 不推荐直接调用
67// 最后在初始化 SwigWrap 的时候指定 view 已经 locals.
68// 此方法将会自动调用。
69SwigWrap.prototype.renderFile = function(view, options) {
70 var self = this;
71
72 if (this.buzy) return;
73 this.buzy = true;
74
75 // support chunk
76 this.swig.renderFile(view, options, function(error, output) {
77 if (error) {
78 return self.emit('error', error);
79 }
80
81 self.push(output);
82 self.push(null);
83 });
84};
85
86SwigWrap.prototype.destroy = function() {
87 this.swig = null;
88 this.removeAllListeners();
89};
90
91// 这个方法在 tags/widget.js 中调用。
92Swig.prototype._w = Swig.prototype._widget = function(layer, id, attr, options) {
93 var self = this;
94 var pathname = layer.resolve(id);
95
96 if (!layer.supportBigPipe() || !attr.mode || attr.mode === 'sync') {
97 layer.load(id);
98 return this.compileFile(pathname, options);
99 }
100
101 return function(locals) {
102 var container = attr['container'] || attr['for'];
103
104 layer.addPagelet({
105 container: container,
106 model: attr.model,
107 id: attr.id,
108 mode: attr.mode,
109 locals: locals,
110 view: pathname,
111 viewId: id,
112
113 compiled: function(locals) {
114 var fn = self.compileFile(pathname, options);
115 var layer = locals._yog;
116 layer && layer.load(id);
117 return fn.apply(this, arguments);
118 }
119 });
120
121 return container ? '' : '<div id="' + attr.id + '"></div>';
122 };
123};
\No newline at end of file