1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | "use strict";
|
10 |
|
11 | var l = require('ergo-utils').log.module('ergo-api-build');
|
12 | var _ = require('ergo-utils')._;
|
13 | var fs = require('ergo-utils').fs.extend(require('fs-extra'));
|
14 | var path = require('path');
|
15 | var Promise = require('bluebird');
|
16 | var plugin_api = require('./plugin')
|
17 | var context = require('../lib/context');
|
18 | var FileInfo = require('../lib/fileinfo');
|
19 | const ignore = require('ignore');
|
20 |
|
21 |
|
22 | "dirExists,ensureDir,emptyDir,emptyDir,readFile,writeFile".split(',').forEach(function(fn) {
|
23 | fs[fn] = Promise.promisify(fs[fn])
|
24 | });
|
25 |
|
26 | function __load_ergoignoreFilter(dir) {
|
27 | const fname = '.ergoignore';
|
28 | return fs
|
29 | .readFile(path.join(dir, fname ), 'utf8')
|
30 | .catch(function(err) {
|
31 | l.vvlog(".ergoignore not found in '"+dir+"'");
|
32 | return '';
|
33 | })
|
34 | .then(function(data) {
|
35 | if (data.length>0)
|
36 | l.vlog("Loaded ignore file: '"+path.join(dir,fname)+"'");
|
37 | return ignore().add([fname, '.git', 'node_modules']).add(data.toString()).createFilter();
|
38 | });
|
39 | }
|
40 |
|
41 | function _walk(dir, fn, walkDirs) {
|
42 | return Promise.coroutine(function *() {
|
43 | var ignoreFilter = yield __load_ergoignoreFilter(dir);
|
44 | var filterFn = function(item) {
|
45 | var relItem = path.relative(dir, item)
|
46 | return ignoreFilter(relItem);
|
47 | }
|
48 | var p = Promise.resolve();
|
49 | var walkerP = new Promise(function(resolve) {
|
50 |
|
51 | function resolvall(result) {
|
52 | p.then(function() {
|
53 | l.vvlog("Directory traversal is complete. Result: " + result)
|
54 | resolve(true)
|
55 | });
|
56 | }
|
57 |
|
58 | fs.walk(dir, {filter:filterFn})
|
59 | .on('data', function (item) {
|
60 | var stats = item.stats;
|
61 | if (stats.isFile() || (walkDirs && stats.isDirectory() && item.path!=dir)) {
|
62 | p = p.then(function() {
|
63 | return fn(item);
|
64 | })
|
65 | }
|
66 | else if (!stats.isDirectory())
|
67 | l.vlogd("skipping " + item.path)
|
68 | })
|
69 | .on('end', function () {
|
70 |
|
71 |
|
72 | resolvall("OK");
|
73 | })
|
74 | .on('error', function(e) {
|
75 |
|
76 | resolvall("Failed to walk properly: \n" + _.niceStackTrace(e));
|
77 | })
|
78 | return true;
|
79 | });
|
80 | yield walkerP;
|
81 | yield p;
|
82 | })();
|
83 | };
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 | function _rightAlignRenderers(context) {
|
128 | var dummy_renderer = plugin_api.findRendererByName("dummy");
|
129 |
|
130 |
|
131 | var longest = 0;
|
132 | for (var i=0; i<context.files.length; i++)
|
133 | {
|
134 | var fi = context.files[i];
|
135 | longest = Math.max(longest, fi.renderers.length);
|
136 | }
|
137 |
|
138 | for (var i=0; i<context.files.length; i++)
|
139 | {
|
140 | var fi = context.files[i];
|
141 | if (fi.renderers.length<longest)
|
142 | fi.renderers = (new Array(longest - fi.renderers.length)).fill(dummy_renderer).concat(fi.renderers);
|
143 | }
|
144 | }
|
145 |
|
146 |
|
147 |
|
148 | function _loadAll(context) {
|
149 | return Promise.coroutine( function *() {
|
150 | for (var i=0; i<context.files.length; i++)
|
151 | {
|
152 | var fi = context.files[i];
|
153 | yield fi.loadOrCopy(context);
|
154 | }
|
155 | return true;
|
156 | })();
|
157 | }
|
158 |
|
159 | function _saveAll(context) {
|
160 | return Promise.coroutine( function *() {
|
161 | for (var i=0; i<context.files.length; i++)
|
162 | {
|
163 | var fi = context.files[i];
|
164 | yield fi.save(context);
|
165 | }
|
166 |
|
167 | yield plugin_api.saveAll(context)
|
168 | return true;
|
169 | })();
|
170 | }
|
171 |
|
172 | function _renderAll(context) {
|
173 | return Promise.coroutine( function *() {
|
174 | l.vlog("Loading...")
|
175 | yield _loadAll(context)
|
176 |
|
177 | _rightAlignRenderers(context);
|
178 |
|
179 | var keep_rendering = true;
|
180 | l.vlog("Rendering...")
|
181 | while(keep_rendering) {
|
182 | keep_rendering = false;
|
183 | for (var i=0; i<context.files.length; i++)
|
184 | {
|
185 | var fi = context.files[i];
|
186 | if (fi.renderNext(context))
|
187 | keep_rendering = true;
|
188 | }
|
189 | }
|
190 | l.vlog("Saving...")
|
191 | yield _saveAll(context);
|
192 | return true;
|
193 | })();
|
194 | }
|
195 |
|
196 |
|
197 |
|
198 |
|
199 | module.exports = function(options) {
|
200 | return Promise.coroutine(function *() {
|
201 | l.log("Building...")
|
202 | options = options || {};
|
203 | var context = require('./config').getContextSync(options.working_dir);
|
204 | context.mergeRuntimeOptions(options);
|
205 |
|
206 |
|
207 | var plugins_to_load = context.config.plugins || "{default}"
|
208 | _.toRealArray(plugins_to_load, ',').forEach(function(name) {
|
209 | plugin_api.loadPlugin(name, context)
|
210 | });
|
211 |
|
212 | l.vvlogd("Context is:\n"+l.dump(context));
|
213 |
|
214 | if (!(yield fs.dirExists(context.getSourcePath())))
|
215 | throw new Error("Missing source path: "+context.getSourcePath());
|
216 |
|
217 |
|
218 | yield fs.ensureDir(context.getOutPath());
|
219 |
|
220 | var rebuild = options.clean;
|
221 | |
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 | if (rebuild) {
|
233 |
|
234 |
|
235 |
|
236 | var _deleteFile = function(item) {
|
237 | l.vlog("Removing '"+item.path+"'...");
|
238 | fs.remove(item.path);
|
239 | }
|
240 | l.log("Cleaning '"+context.getOutPath()+"'...")
|
241 | yield _walk(context.getOutPath(), _deleteFile, true);
|
242 | }
|
243 |
|
244 | var _addFile = function(item) {
|
245 | if (!fs.isInDir(context.getOutPath(), item.path))
|
246 | return context.addFile(item.path, item.stats)
|
247 | .then(function() {
|
248 | return true;
|
249 | })
|
250 | return Promise.resolve(false);
|
251 | }
|
252 |
|
253 |
|
254 | l.log("Reading '"+context.getSourcePath()+"'...")
|
255 |
|
256 | if (fs.isInDir(context.getSourcePath(), context.getPartialsPath()))
|
257 | l.logw("Partials folder is inside the source folder. This can be problematic")
|
258 | else
|
259 | yield _walk(context.getPartialsPath(), _addFile);
|
260 |
|
261 | if (fs.isInDir(context.getSourcePath(), context.getLayoutsPath()))
|
262 | l.logw("Layouts folder is inside the source folder. This can be problematic")
|
263 | else
|
264 | yield _walk(context.getLayoutsPath(), _addFile);
|
265 |
|
266 | if (fs.isInDir(context.getSourcePath(), context.getThemePath()))
|
267 | l.logw("Theme folder is inside the source folder. This can be problematic")
|
268 | else {
|
269 | yield _walk(context.getThemePath(), _addFile);
|
270 | }
|
271 |
|
272 | yield _walk(context.getSourcePath(), _addFile);
|
273 |
|
274 |
|
275 | yield _renderAll(context);
|
276 |
|
277 | l.log("Done");
|
278 | return true;
|
279 | })();
|
280 | } |
\ | No newline at end of file |