1 |
|
2 |
|
3 |
|
4 |
|
5 | var Readable = require('stream').Readable;
|
6 | var util = require('util');
|
7 | var Swig = require('swig').Swig;
|
8 | var loader = require('./lib/loader.js');
|
9 | var debuglog = require('debuglog')('yog-swig');
|
10 | var 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 |
|
24 | var swigInstance;
|
25 |
|
26 | var 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 |
|
34 | util.inherits(EngineStream, Readable);
|
35 |
|
36 | EngineStream.prototype._read = function () {
|
37 | var self = this;
|
38 |
|
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 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 | var 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 |
|
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 |
|
98 | SwigWrap.prototype.cleanCache = function () {
|
99 | this.swig.invalidateCache();
|
100 | };
|
101 |
|
102 | SwigWrap.prototype.makeStream = function (view, locals) {
|
103 | debuglog('create [%s] render stream', view);
|
104 | return new EngineStream(this.swig, view, locals);
|
105 | };
|
106 |
|
107 |
|
108 |
|
109 | Swig.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 | };
|