UNPKG

3.69 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 debuglog = require('debuglog')('yog-swig');
10var tags = [
11 "script",
12 "style",
13 "html",
14 "body",
15 "require",
16 "uri",
17 "widget",
18 "head",
19 "feature",
20 "featureelse",
21 "spage"
22];
23
24var swigInstance;
25
26/**
27 * Opitions 说明
28 * - `views` 模板根目录
29 * - `loader` 模板加载器,默认自带,可选。
30 *
31 * 更多细节请查看 yog-view
32 *
33 */
34var SwigWrap = module.exports = function SwigWrap(app, options) {
35
36 if (swigInstance) {
37 debuglog('use swig instance cache');
38 this.swig = swigInstance;
39 return;
40 }
41
42 debuglog('init swig instance');
43
44 options = options || {};
45
46 // 重写 loader, 让模板引擎,可以识别静态资源标示。如:example:static/lib/jquery.js
47 options.loader = options.loader || loader(app, options.views, options.encoding);
48
49 var swig = this.swig = swigInstance = new Swig(options);
50
51 // 加载内置扩展
52 tags.forEach(function (tag) {
53 var t = require('./tags/' + tag);
54 swig.setTag(tag, t.parse, t.compile, t.ends, t.blockLevel || false);
55 });
56
57 // 加载用户扩展
58 options.tags && Object.keys(options.tags).forEach(function (name) {
59 var t = options.tags[name];
60 swig.setTag(name, t.parse, t.compile, t.ends, t.blockLevel || false);
61 });
62
63 options.filters && Object.keys(options.filters).forEach(function (name) {
64 var t = options.filters[name];
65 swig.setFilter(name, t);
66 });
67};
68
69SwigWrap.prototype.cleanCache = function () {
70 this.swig.invalidateCache();
71};
72
73SwigWrap.prototype.makeStream = function (view, locals) {
74 debuglog('create [%s] render stream', view);
75 return new EngineStream(this.swig, view, locals);
76};
77
78var EngineStream = function (swig, view, locals) {
79 this.swig = swig;
80 this.view = view;
81 this.locals = locals;
82 this.reading = false;
83 Readable.call(this);
84};
85
86util.inherits(EngineStream, Readable);
87
88EngineStream.prototype._read = function () {
89 var self = this;
90 var state = self._readableState;
91 if (this.reading) {
92 return;
93 }
94 this.reading = true;
95 debuglog('start render [%s]', this.view);
96 this.swig.renderFile(this.view, this.locals, function (error, output) {
97 if (error) {
98 debuglog('render [%s] failed', self.view);
99 return self.emit('error', error);
100 }
101 debuglog('render [%s] succ', self.view);
102 self.push(output);
103 self.push(null);
104 });
105};
106
107// 扩展swig内置函数,用于提供bigpipe支持
108Swig.prototype._w = Swig.prototype._widget = function (layer, id, attr, options) {
109 var self = this;
110 var pathname = layer.resolve(id);
111
112 if (!layer.supportBigPipe() || !attr.mode || attr.mode === 'sync' || layer.isPagelet) {
113 layer.load(id);
114 return this.compileFile(pathname, options);
115 }
116
117 return function (locals) {
118 var container = attr['container'] || attr['for'];
119
120 layer.addPagelet({
121 container: container,
122 model: attr.model,
123 id: attr.id,
124 mode: attr.mode,
125 locals: locals,
126 view: pathname,
127 viewId: id,
128
129 compiled: function (locals) {
130 var fn = self.compileFile(pathname, options);
131 locals._yog.load(id);
132 return fn.apply(this, arguments);
133 }
134 });
135
136 return container ? '' : '<div id="' + attr.id + '"></div>';
137 };
138};
\No newline at end of file