UNPKG

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