1 | var ComponentBase = require('./ComponentBase.js'),
|
2 | pathUtils = require('../lib/utils/path.js'),
|
3 | path = require('path'),
|
4 | mkdirp = require('mkdirp'),
|
5 | fs = require('fs'),
|
6 | async = require('async'),
|
7 | glob = require('glob');
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | function Component(options){
|
14 | ComponentBase.call(this, options);
|
15 |
|
16 | this.id = options.id;
|
17 | this.buildPath = path.join(__dirname, '../public/_built/' + this.id);
|
18 | this.standaloneCssPath = path.join(this.buildPath + '/standalone.css');
|
19 | this.standaloneCssPublicPath = '/_built/' + this.id + '/standalone.css';
|
20 | this.resourcePaths = {};
|
21 | this.cache = {};
|
22 | this.partialRegistered = false;
|
23 | this.missingPartial = false;
|
24 | this.baseDependencies = [];
|
25 |
|
26 | }
|
27 | Component.prototype = Object.create(ComponentBase.prototype);
|
28 |
|
29 |
|
30 | Component.prototype.build = function(callback) {
|
31 | async.series([
|
32 |
|
33 | this.cacheResourcePathes.bind(this),
|
34 | this.cacheResources.bind(this),
|
35 |
|
36 | mkdirp.bind(null, this.buildPath),
|
37 |
|
38 |
|
39 | this.resolveDependencies.bind(this),
|
40 |
|
41 |
|
42 |
|
43 | this.buildStandaloneCss.bind(this),
|
44 |
|
45 |
|
46 |
|
47 | this.registerPartial.bind(this),
|
48 |
|
49 | ], callback);
|
50 |
|
51 | };
|
52 |
|
53 | Component.prototype.rebuild = function(callback) {
|
54 | this.build(callback);
|
55 | };
|
56 |
|
57 | Component.prototype.resolveDependencies = function(callback) {
|
58 | var dependencies = [],
|
59 | m,
|
60 | re = /\{\{> ?([a-zA-Z\/\-_]+)/gm;
|
61 |
|
62 | while ((m = re.exec(this.cache.html)) !== null) {
|
63 | if (m.index === re.lastIndex) {
|
64 | re.lastIndex++;
|
65 | }
|
66 |
|
67 | if(dependencies.indexOf(m[1]) === -1){
|
68 | dependencies.push(m[1]);
|
69 | }
|
70 | }
|
71 |
|
72 | if(this.isBaseCss){
|
73 | this.dependencies = dependencies;
|
74 | }else{
|
75 | this.dependencies = this.baseDependencies.concat(dependencies);
|
76 | }
|
77 |
|
78 |
|
79 | if(this.dependencies.length > 0){
|
80 | this.dsf.whenLoaded(this.dependencies, this.addDependencies.bind(this, callback));
|
81 | }else{
|
82 | callback();
|
83 | }
|
84 |
|
85 | };
|
86 |
|
87 | Component.prototype.addDependencies = function(callback) {
|
88 | var dependecyCss = '';
|
89 | this.dependencies.forEach(function(dependencyId){
|
90 | var dependency = this.dsf.getComponent(dependencyId);
|
91 | if(dependency.isBaseCss){
|
92 | return;
|
93 | }
|
94 | dependecyCss+='\n\n/* dependency: '+dependencyId+' */\n' + dependency.getCss(true) + '\n';
|
95 |
|
96 |
|
97 | }, this);
|
98 | this.cache.cssDependencies = dependecyCss;
|
99 |
|
100 | callback();
|
101 | };
|
102 |
|
103 | Component.prototype.registerPartial = function(callback) {
|
104 | this.dsf.getHandlebars().registerPartial(this.id, this.cache.html || '');
|
105 | callback();
|
106 | };
|
107 |
|
108 | Component.prototype.cacheResourcePathes = function(callback) {
|
109 | var self = this;
|
110 | async.map(['css','html','config'], this.getResourcePaths.bind(this), function(err, paths){
|
111 |
|
112 | self.resourcePaths.css = paths[0];
|
113 | self.resourcePaths.html = paths[1][0];
|
114 | self.resourcePaths.config = paths[2][0];
|
115 |
|
116 | callback();
|
117 | });
|
118 | };
|
119 | Component.prototype.getResourcePaths = function(type, callback) {
|
120 | glob(this.getGlobPath(type), function(err, files){
|
121 | if(err) throw err;
|
122 |
|
123 | callback(null, files);
|
124 | });
|
125 | };
|
126 |
|
127 | Component.prototype.cacheResources = function(callback) {
|
128 | async.parallel([
|
129 | this.cacheCss.bind(this),
|
130 | this.cacheHtml.bind(this),
|
131 | this.cacheConfig.bind(this)
|
132 | ], callback);
|
133 |
|
134 | };
|
135 |
|
136 | Component.prototype.cacheCss = function(cacheCssCallback) {
|
137 | var self = this;
|
138 | async.map(this.resourcePaths.css, fs.readFile, function(err, files){
|
139 | if(err) throw err;
|
140 | async.reduce(files, '', function(memo, item, callback){
|
141 | callback(null, memo + '\n' + item.toString());
|
142 | }, function(err, css){
|
143 | if(err) throw err;
|
144 | self.cache.css = css;
|
145 | cacheCssCallback();
|
146 | });
|
147 | });
|
148 |
|
149 | };
|
150 |
|
151 |
|
152 | Component.prototype.cacheHtml = function(callback) {
|
153 | var self = this;
|
154 |
|
155 | if(this.resourcePaths.html){
|
156 | fs.readFile(this.resourcePaths.html, function(err, file){
|
157 | var html = file.toString();
|
158 | self.cache.html = html;
|
159 | self.cache.tpl = self.dsf.getHandlebars().compile(html);
|
160 | callback();
|
161 | });
|
162 | }else{
|
163 | self.cache.html = '';
|
164 | callback();
|
165 | }
|
166 |
|
167 | };
|
168 |
|
169 | Component.prototype.cacheConfig = function(callback) {
|
170 | if(this.resourcePaths.config){
|
171 | try{
|
172 | this.cache.config = require(path.join(this.absPath, this.resourcePaths.config));
|
173 | }catch(err){
|
174 | this.cache.config = {};
|
175 | }
|
176 |
|
177 | }
|
178 | callback();
|
179 | };
|
180 |
|
181 | Component.prototype.buildStandaloneCss = function(callback) {
|
182 | var baseCss = this.isBaseCss ? '' : this.dsf.getBaseCss(),
|
183 | componentCss = this.getCss(),
|
184 | dependecyCss = this.cache.cssDependencies || '';
|
185 | css = baseCss + componentCss + dependecyCss;
|
186 |
|
187 | fs.writeFile(this.standaloneCssPath, css, callback);
|
188 | };
|
189 |
|
190 | Component.prototype.getCss = function(withDependencies) {
|
191 | return this.cache.css + ((withDependencies && this.cache.cssDependencies) ? this.cache.cssDependencies : '');
|
192 | };
|
193 |
|
194 | Component.prototype.render = function(context) {
|
195 | if(this.cache.tpl){
|
196 | return this.cache.tpl(context || (this.cache.config ? this.cache.config : {}));
|
197 | }
|
198 | return '';
|
199 | };
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | module.exports = Component;
|