1 | let colors = require("colors");
|
2 | let util = require("./util");
|
3 | let File = require("./lib/file");
|
4 | let Path = require("path");
|
5 | let maker = require("./maker/maker");
|
6 | let hash = require("./lib/md5");
|
7 | let queue = require("./lib/queue");
|
8 | let isbinaryfile = require("isbinaryfile");
|
9 | let config = require("./config");
|
10 | let gzipSize = require('gzip-size');
|
11 | let ignore = require('ignore');
|
12 | let ora = require('ora');
|
13 |
|
14 | const THRIDPARTFOLDER = "node_modules";
|
15 | const IGNOREMODULES = ["fs", "path", "util", "http", "url", "zlib", "https", "events", "crypto", "adajs"];
|
16 | const MANIFESTKEYS = ["theme_color", "start_url", "short_name", "scope", "related_applications", "prefer_related_applications", "orientation", "name", "lang", "icons", "display", "dir", "description", "background_color"];
|
17 |
|
18 | class AdaBundler {
|
19 | constructor() {
|
20 | this.resultmap = [];
|
21 | this.resultmapcode = {};
|
22 | this.contentCache = {};
|
23 | }
|
24 |
|
25 | getFileCode(path) {
|
26 | if (!this.contentCache[path]) {
|
27 | return new Promise((resolve, reject) => {
|
28 | let file = new File(path), suffix = file.suffix();
|
29 | if (suffix === "html") {
|
30 | resolve(`module.exports=${JSON.stringify(file.readSync().replace(/\n/g, '').replace(/\r/g, '').replace(/\n\r/g, ''))}`);
|
31 | } else if (suffix === "less") {
|
32 | maker.lessCode(file.readSync()).then(code => {
|
33 | resolve(`module.exports={active:function(){var _a = document.createElement("style");_a.setAttribute("media", "screen");_a.setAttribute("type", "text/css");_a.appendChild(document.createTextNode(${JSON.stringify(code)}));document.head.appendChild(_a);}};`);
|
34 | });
|
35 | } else if (suffix === "icon") {
|
36 | maker.minifyIcon(file.readSync()).then(({name, code}) => {
|
37 | let result = `var active=function(){var c=document.getElementById("ada-icon-container");if(!c){var c=document.createElement("div");c.setAttribute("id","ada-icon-container");c.style.cssText="width:0;height:0;";document.body.appendChild(c);}if(!document.getElementById("${name}")){var a=document.createElement("div");a.innerHTML=${JSON.stringify(code)};c.appendChild(a.childNodes[0]);}};module.exports={active:function(){if(/complete|loaded|interactive/.test(window.document.readyState)){active();}else{window.addEventListener("DOMContentLoaded",function(){active();});}},getIconId:function(){return "${name}";}};`;
|
38 | resolve(result);
|
39 | });
|
40 | } else {
|
41 | let __code = file.readSync();
|
42 | if (__code.trim().length === 0) {
|
43 | resolve("module.exports={};");
|
44 | } else {
|
45 | if (path.indexOf("node_modules") === -1) {
|
46 | resolve(__code);
|
47 | } else {
|
48 | maker.babelCode(config, __code).then(content => {
|
49 | resolve(content);
|
50 | });
|
51 | }
|
52 | }
|
53 | }
|
54 | }).then((content) => {
|
55 | this.contentCache[path] = content;
|
56 | return content;
|
57 | });
|
58 | } else {
|
59 | return Promise.resolve(this.contentCache[path]);
|
60 | }
|
61 | }
|
62 |
|
63 | getDependenceInfo(path, code) {
|
64 | if (!this.resultmapcode[path]) {
|
65 | let paths = [];
|
66 | code = code.replace(/require\(.*?\)/g, (one) => {
|
67 | if (one.indexOf("${") === -1 && one.indexOf("+") === -1 && one.indexOf(".concat(") === -1) {
|
68 | let a = one.substring(8, one.length - 1).replace(/['|"|`]/g, "").trim();
|
69 | let _path = base.getFilePath(config, Path.resolve(path, "./../"), a);
|
70 | let index = this.resultmap.indexOf(_path);
|
71 | if (index === -1) {
|
72 | paths.push(_path);
|
73 | this.resultmap.push(_path);
|
74 | index = this.resultmap.length - 1;
|
75 | }
|
76 | return `require(${index})`;
|
77 | } else {
|
78 | return one;
|
79 | }
|
80 | });
|
81 | this.resultmapcode[path] = code;
|
82 | return paths;
|
83 | } else {
|
84 | return [];
|
85 | }
|
86 | }
|
87 |
|
88 | getCodeMap(path) {
|
89 | return this.getFileCode(path).then(code => {
|
90 | let tasks = this.getDependenceInfo(path, code).map(path => () => {
|
91 | return this.getCodeMap(path);
|
92 | });
|
93 | return queue(tasks);
|
94 | });
|
95 | }
|
96 |
|
97 | bundle(path, output, develop) {
|
98 | path = path.replace(/\\/g, "/");
|
99 | console.log("");
|
100 | if (!config.ada_autobundle) {
|
101 | console.log(` [ada_autobundle:false] ALWAYS BUNDLE ADA CORE`.grey);
|
102 | }
|
103 | let spinner = ora({
|
104 | color: "yellow",
|
105 | text: `NOW BUNDLING ADA CORE [${develop ? "DEVELOP" : "PUBLIC"} MODE]`
|
106 | }).start();
|
107 | return new File(`${config.projectPath}/node_modules/adajs/index.d.ts`).copyTo(`${config.projectPath}/node_modules/@types/adajs/index.d.ts`).then(() => {
|
108 | return this.getCodeMap(path).then(() => {
|
109 | let veison = require(Path.resolve(path, "./../package.json")).version;
|
110 | this.resultmap.push(path);
|
111 | let result = this.resultmap.map(path => {
|
112 | return `function(module,exports,require){${this.resultmapcode[path]}}`;
|
113 | });
|
114 | let commet = `/*! adajs[${develop ? "Develop" : "Publish"}] ${veison} https://github.com/topolr/ada | https://github.com/topolr/ada/blob/master/LICENSE */\n`;
|
115 | let code = `${commet}(function (map,moduleName) {var Installed={};var requireModule = function (index) {if (Installed[index]) {return Installed[index].exports;}var module = Installed[index] = {exports: {}};map[index].call(module.exports, module, module.exports, requireModule);return module.exports;};var mod=requireModule(map.length-1);window&&window.Ada.installModule(moduleName,mod);})([${result.join(",")}],"adajs");`;
|
116 | config.adaHash = hash.md5(code).substring(0, 10);
|
117 | code = code.replace(/\/ada\/sse/, `${config.server.protocol}://${config.server.host}${(config.server.port != 80 ? ":" + config.server.port : '')}/ada/sse`);
|
118 | return new File(output).write(code).then(() => {
|
119 | spinner.stop();
|
120 | process.stderr.clearLine();
|
121 | process.stderr.cursorTo(0);
|
122 | console.log(` BUNDLE ADA CORE DONE [${develop ? "DEVELOP" : "PUBLIC"} MODE GZIP:${util.getFileSizeAuto(gzipSize.sync(code))}]`.yellow);
|
123 | });
|
124 | });
|
125 | });
|
126 | }
|
127 | }
|
128 |
|
129 | let base = {
|
130 | logs: {},
|
131 | packageLogs: {},
|
132 | cache: {},
|
133 | doneMap: [],
|
134 | getUnIgnorePath(paths) {
|
135 | return paths.filter(path => {
|
136 | return !config.ignore.ignores("./" + path.substring(config.source_path.length));
|
137 | });
|
138 | },
|
139 | isBundleAda(develop) {
|
140 | let result = true;
|
141 | if (config.ada_autobundle) {
|
142 | let veison = require(Path.resolve(config.nmodule_path, "./adajs/package.json")).version;
|
143 | if (develop) {
|
144 | let adaFile = new File(Path.resolve(config.dist_path, "./ada.js"));
|
145 | if (adaFile.isExists()) {
|
146 | let content = adaFile.readSync();
|
147 | let r = content.match(/\*! adajs.*?\*/g);
|
148 | if (r) {
|
149 | let current_version = r[0].split(" ")[2];
|
150 | if (current_version && current_version.trim() === veison) {
|
151 | result = false;
|
152 | }
|
153 | }
|
154 | }
|
155 | } else {
|
156 | let k = new File(Path.resolve(config.dist_path)).subscan().filter(path => {
|
157 | let a = /ada\-[0-9a-z]+\.js/.test(path.replace(/\\/g, "/").split("/").pop());
|
158 | if (a) {
|
159 | let content = new File(path).readSync();
|
160 | let r = content.match(/\*! adajs.*?\*/g);
|
161 | if (r) {
|
162 | let current_version = r[0].split("")[2];
|
163 | return current_version && current_version.trim() === veison;
|
164 | }
|
165 | }
|
166 | });
|
167 | if (k.length > 0) {
|
168 | result = false;
|
169 | }
|
170 | }
|
171 | }
|
172 | return result;
|
173 | },
|
174 | getAllFiles() {
|
175 | return new File(config.source_path + "/").scan();
|
176 | },
|
177 | getAllSource() {
|
178 | let files = [];
|
179 | new File(config.source_path + "/").scan().forEach(path => {
|
180 | let suffix = new File(path).suffix();
|
181 | if (suffix === "js" || suffix === "ts") {
|
182 | files.push(path);
|
183 | }
|
184 | });
|
185 | return files;
|
186 | },
|
187 | getFilePath(config, filePath, path) {
|
188 | let __path = "", _path = "";
|
189 | if (path.substring(0, path.length - 3) === ".js") {
|
190 | path = path.substring(0, path.length - 3);
|
191 | }
|
192 | if (path.startsWith("./") || path.startsWith("../") || path.startsWith("/")) {
|
193 | __path = _path = Path.resolve(filePath, path).replace(/\\/g, "/");
|
194 | let _file = new File(_path);
|
195 | if (!_file.isExists() || _file.isFolder()) {
|
196 | _path = __path + ".ts";
|
197 | }
|
198 | _file = new File(_path);
|
199 | if (!_file.isExists() || _file.isFolder()) {
|
200 | _path = __path + ".js";
|
201 | }
|
202 | } else {
|
203 | __path = _path = Path.resolve(config.nmodule_path, path);
|
204 | _path = __path + ".ts";
|
205 | let file = new File(_path);
|
206 | if (!file.isExists()) {
|
207 | _path = __path + ".js";
|
208 | }
|
209 | file = new File(_path);
|
210 | if (!file.isExists()) {
|
211 | _path = __path;
|
212 | }
|
213 | file = new File(_path);
|
214 | if (file.isExists()) {
|
215 | if (!file.isFile()) {
|
216 | let _packagePath = Path.resolve(_path, "./package.json");
|
217 | let _packageFile = new File(_packagePath);
|
218 | if (_packageFile.isExists()) {
|
219 | _path = Path.resolve(_packagePath, "./../", JSON.parse(_packageFile.readSync()).main);
|
220 | } else {
|
221 | let __path = Path.resolve(_path, "./index.ts");
|
222 | if (!new File(__path).isExists()) {
|
223 | __path = Path.resolve(_path, "./index.js");
|
224 | }
|
225 | _path = __path;
|
226 | }
|
227 | }
|
228 | } else {
|
229 | _path = __path + ".ts";
|
230 | file = new File(_path);
|
231 | if (!file.isExists()) {
|
232 | _path = __path + ".js";
|
233 | }
|
234 | }
|
235 | }
|
236 | return _path.replace(/\\/g, "/");
|
237 | },
|
238 | getFileContent(config, filePath, path) {
|
239 | let _path = this.getFilePath(config, filePath, path);
|
240 | let _file = new File(_path);
|
241 | let hash = _file.hash();
|
242 | if (this.cache[_path] && this.cache[_path].hash === hash) {
|
243 | return Promise.resolve(Object.assign({}, this.cache[_path]));
|
244 | } else {
|
245 | return maker.parse(_file.suffix(), _path, _file.readSync(), config).then(content => {
|
246 | this.logs[_path] = "done";
|
247 | this.cache[_path] = {hash, content, path: _path, result: "done"};
|
248 | return {path: _path, content, result: "done"};
|
249 | }).catch(e => {
|
250 | this.logs[_path] = {
|
251 | name: e.name,
|
252 | message: e.message,
|
253 | stack: e.stack
|
254 | };
|
255 | if (_file.suffix() === "js" || _file.suffix() === "ts") {
|
256 | return {path: _path, content: `console.error(${JSON.stringify(e.message)})`, result: e}
|
257 | } else {
|
258 | return {path: _path, content: `${JSON.stringify(e.message)}`, result: e}
|
259 | }
|
260 | });
|
261 | }
|
262 | },
|
263 | getRequireInfo(config, filePath, path) {
|
264 | let _path = this.getFilePath(config, filePath, path);
|
265 | if(!config.ignore.ignores("./" + _path.substring(config.source_path.length))) {
|
266 | return this.getFileContent(config, filePath, path).then(info => {
|
267 | let currentPath = info.path;
|
268 | let at = {}, tasks = [], parseTasks = [], infoTasks = [], importsTasks = [];
|
269 | let entry = {};
|
270 | let result = {};
|
271 | let name = "";
|
272 | this.doneMap.push(currentPath);
|
273 | info.content = info.content.replace(/_adajs.view\)\(\{[\d\D]*?\)/g, str => {
|
274 | let map = str.substring(13, str.length - 1);
|
275 | let mapj = new Function(`return ${map};`)();
|
276 | ["template", "style"].forEach(key => {
|
277 | let value = mapj[key];
|
278 | if (value) {
|
279 | let path = Path.join(info.path, "./../", value).replace(/\\/g, "/");
|
280 | if (path.indexOf("node_modules") === -1) {
|
281 | value = path.substring(config.source_path.length);
|
282 | parseTasks.push({
|
283 | path: Path.resolve(config.dist_path, path.substring(config.source_path.length)),
|
284 | current: path,
|
285 | value
|
286 | });
|
287 | } else {
|
288 | value = `${THRIDPARTFOLDER}/${path.substring(config.nmodule_path.length)}`;
|
289 | parseTasks.push({
|
290 | path: Path.resolve(config.dist_path, `./${THRIDPARTFOLDER}/${path.substring(config.nmodule_path.length)}`),
|
291 | current: path,
|
292 | value
|
293 | });
|
294 | }
|
295 | mapj[key] = value;
|
296 | }
|
297 | });
|
298 | let __path = info.path.replace(/\\/g, "/");
|
299 | if (__path.indexOf("node_modules") === -1) {
|
300 | mapj.module = __path.substring(config.source_path.length);
|
301 | } else {
|
302 | mapj.module = `${THRIDPARTFOLDER}/${__path.substring(config.nmodule_path.length)}`;
|
303 | }
|
304 | let result = Reflect.ownKeys(mapj).map(key => {
|
305 | return `${key}:"${mapj[key]}"`;
|
306 | });
|
307 | return `_adajs.view)({${result.join(",")}})`;
|
308 | });
|
309 | info.content = info.content.replace(/require\(.*?\)/g, (str) => {
|
310 | let a = str.substring(8, str.length - 1).replace(/['|"|`]/g, "").trim();
|
311 | if (IGNOREMODULES.indexOf(a) === -1) {
|
312 | let m = this.getFilePath(config, Path.resolve(info.path, "./../"), a);
|
313 | if (this.doneMap.indexOf(m) === -1 && m !== currentPath) {
|
314 | infoTasks.push({
|
315 | filePath: Path.resolve(info.path, "./../"),
|
316 | path: a
|
317 | });
|
318 | }
|
319 | if (m.indexOf("node_modules") === -1) {
|
320 | return `require("${m.substring(config.source_path.length)}")`;
|
321 | } else {
|
322 | let name = `${THRIDPARTFOLDER}/${m.substring(config.nmodule_path.length)}`;
|
323 | return `require("${name}")`;
|
324 | }
|
325 | } else {
|
326 | return str;
|
327 | }
|
328 | });
|
329 | info.content = info.content.replace(/import\(.*?\)/g, (str) => {
|
330 | let a = str.substring(7, str.length - 1);
|
331 | if (a.startsWith("\"") || a.startsWith("'") || a.startsWith("`")) {
|
332 | a = a.replace(/['|"|`]/g, "").trim();
|
333 | if (IGNOREMODULES.indexOf(a) === -1) {
|
334 | let m = this.getFilePath(config, Path.resolve(info.path, "./../"), a);
|
335 | let name = "", value = "";
|
336 | if (m.indexOf("node_modules") === -1) {
|
337 | name = m.substring(config.source_path.length);
|
338 | value = `imports("${name}")`;
|
339 | } else {
|
340 | let name = `${THRIDPARTFOLDER}/${m.substring(config.nmodule_path.length)}`;
|
341 | value = `imports("${name}")`;
|
342 | }
|
343 | if (this.doneMap.indexOf(m) === -1 && m !== currentPath) {
|
344 | importsTasks.push({
|
345 | filePath: Path.resolve(info.path, "./../"),
|
346 | path: a,
|
347 | name
|
348 | });
|
349 | }
|
350 | return value;
|
351 | } else {
|
352 | return `imports(${a})`;
|
353 | }
|
354 | } else {
|
355 | return `imports(${a})`;
|
356 | }
|
357 | });
|
358 | if (info.path.indexOf("node_modules") !== -1) {
|
359 | name = `${THRIDPARTFOLDER}/${info.path.substring(config.nmodule_path.length)}`;
|
360 | let __path = Path.resolve(config.dist_path, `./${name}`);
|
361 | if (this.doneMap.indexOf(__path) === -1) {
|
362 | tasks.push({
|
363 | path: __path,
|
364 | content: info.content
|
365 | });
|
366 | }
|
367 | } else {
|
368 | name = info.path.substring(config.source_path.length);
|
369 | let __path = Path.resolve(config.dist_path, info.path.substring(config.source_path.length))
|
370 | if (this.doneMap.indexOf(__path) === -1) {
|
371 | tasks.push({
|
372 | path: __path,
|
373 | content: info.content
|
374 | });
|
375 | }
|
376 | }
|
377 | at[name] = info.content;
|
378 | return Promise.all(parseTasks.map(({path, current, content, value}) => {
|
379 | this.doneMap.push(path);
|
380 | return this.getFileContent(config, current, "./").then(({content}) => {
|
381 | at[value] = content;
|
382 | return new File(path).write(content);
|
383 | });
|
384 | }).concat(tasks.map(({path, content}) => {
|
385 | this.doneMap.push(path);
|
386 | return new File(path).write(content);
|
387 | })).concat(infoTasks.map(({filePath, path}) => {
|
388 | return this.getRequireInfo(config, filePath, path).then(b => {
|
389 | if(b) {
|
390 | let name = b.__name__;
|
391 | Object.keys(b[name]).forEach(key => {
|
392 | at[key] = b[name][key];
|
393 | });
|
394 | Object.keys(b).forEach(key => {
|
395 | if (key !== name) {
|
396 | result[key] = b[key];
|
397 | }
|
398 | });
|
399 | }
|
400 | });
|
401 | })).concat(importsTasks.map(({filePath, path, name}) => {
|
402 | return this.getRequireInfo(config, filePath, path).then(b => {
|
403 | if(b) {
|
404 | let name = b.__name__;
|
405 | result[name] = b[name];
|
406 | Object.keys(b).forEach(key => {
|
407 | if (key !== name) {
|
408 | result[key] = b[key];
|
409 | }
|
410 | });
|
411 | }
|
412 | });
|
413 | }))).then(() => {
|
414 | util.setProp(result, "__name__", name);
|
415 | result[name] = at;
|
416 | return result;
|
417 | });
|
418 | }).catch(e => console.log(e));
|
419 | }else{
|
420 | return Promise.resolve(null);
|
421 | }
|
422 | },
|
423 | bundleAda(develop = false) {
|
424 | if (this.isBundleAda(develop)) {
|
425 | return new AdaBundler().bundle(Path.resolve(config.nmodule_path, `./adajs/${develop ? "develop" : (config.super_ada ? "super" : "index")}.js`),
|
426 | Path.resolve(config.dist_path, "./ada.js"), develop).then(a => {
|
427 | return a;
|
428 | });
|
429 | } else {
|
430 | return Promise.resolve();
|
431 | }
|
432 | },
|
433 | getEntriesInfo(paths) {
|
434 | paths = this.getUnIgnorePath(paths);
|
435 | let info = {};
|
436 | let main = Path.resolve(config.base_path, config.main);
|
437 | return queue(paths.map(path => {
|
438 | return "./" + path.substring(config.source_path.length);
|
439 | }).map(entry => () => {
|
440 | return this.getRequireInfo(config, config.source_path, entry).then(_info => {
|
441 | if(_info) {
|
442 | Object.keys(_info).forEach(key => {
|
443 | info[key] = _info[key];
|
444 | });
|
445 | }
|
446 | });
|
447 | })
|
448 | ).then(() => {
|
449 | let mainEntry = null, otherEnteries = [];
|
450 | let _mainEntry = main.substring(config.source_path.length);
|
451 | Object.keys(info).forEach(key => {
|
452 | let result = {};
|
453 | Reflect.ownKeys(info[key]).forEach(path => {
|
454 | result[util.getMappedPath(path)] = {
|
455 | hash: hash.md5(info[key][path]).substring(0, 8),
|
456 | code: info[key][path]
|
457 | }
|
458 | });
|
459 | let _result = {
|
460 | code: result,
|
461 | key: util.getMappedPath("package-" + key.replace(/\//g, "-").replace(/\\/g, "-")),
|
462 | name: key
|
463 | };
|
464 | if (key === _mainEntry) {
|
465 | mainEntry = _result;
|
466 | } else {
|
467 | otherEnteries.push(_result);
|
468 | }
|
469 | });
|
470 | return {mainEntry, otherEnteries};
|
471 | });
|
472 | },
|
473 | getAppSourceInfo() {
|
474 | let main = Path.resolve(config.base_path, config.main);
|
475 | let info = {};
|
476 | let entries = [];
|
477 | if (config.entry_path) {
|
478 | entries = new File(Path.resolve(config.base_path, config.entry_path) + "/").subscan().filter(path => {
|
479 | let suffix = new File(path).suffix();
|
480 | return suffix === "js" || suffix === "ts";
|
481 | }).map(path => path.replace(/\\/g, "/").replace(/[\/]+/g, "/"));
|
482 | }
|
483 | return this.getEntriesInfo([main, ...entries]);
|
484 | },
|
485 | outputPWAFile(config) {
|
486 | let manifest = {};
|
487 | config = util.extend(true, {}, config);
|
488 | Reflect.ownKeys(config).filter(key => MANIFESTKEYS.indexOf(key) !== -1).forEach(key => {
|
489 | manifest[key] = config[key];
|
490 | });
|
491 |
|
492 | let worker = config.worker;
|
493 | let registCode = worker.beforeregist.toString().trim();
|
494 | let start = registCode.indexOf("{") + 1;
|
495 | let a = registCode.substring(start, registCode.length - 1);
|
496 | let c = a.substring(a.indexOf("."));
|
497 | let workerRegistCode = `if ('serviceWorker' in navigator) {navigator.serviceWorker.register('/serviceworker.js', { scope: '${worker.scope}' })${c}}`;
|
498 |
|
499 | let codes = Reflect.ownKeys(worker).filter(key => ["scope", "beforeregist"].indexOf(key) === -1).map(key => {
|
500 | let code = worker[key].toString();
|
501 | return `self.addEventListener('${key.substring(2)}', function${code.substring(code.indexOf("("))});`;
|
502 | });
|
503 |
|
504 | let page = config.page;
|
505 | page.meta.theme_color = config.theme_color;
|
506 | page.meta.description = config.description;
|
507 | page.meta.keywords = config.keywords;
|
508 | let metaContent = Reflect.ownKeys(page.meta).map(key => {
|
509 | return `<meta name="${key.replace(/_/g, "-")}" content="${page.meta[key]}">`;
|
510 | }).join("");
|
511 | let iconsContent = config.icons.map(info => {
|
512 | return `<link rel="apple-touch-icon-precomposed" sizes="${info.sizes}" href="${config.site_url + info.src}">`;
|
513 | }).join("");
|
514 | if (config.icons.length > 0) {
|
515 | iconsContent += `<link rel="shortcut icon" href="${config.site_url + config.icons[0].src}">`;
|
516 | }
|
517 | let styleContent = page.style.map(path => {
|
518 | return `<link rel="stylesheet" href="${path}">`;
|
519 | }).join("");
|
520 | let scriptContent = page.script.map(path => {
|
521 | return `<script src="${path}"></script>`;
|
522 | }).join("");
|
523 | let content = `<!DOCTYPE html><html><head><link rel="manifest" href="manifest.json"><meta charset="${page.charset}"><title>${config.name}</title>${metaContent}${iconsContent}${styleContent}${scriptContent}<script src="${config._adaPath}"></script><script>${config.regist_service ? workerRegistCode : ""}</script><script>Ada.boot(${JSON.stringify(config.ada)});</script></head><body></body></html>`;
|
524 | return Promise.all(config.icons.map(icon => {
|
525 | return new File(Path.resolve(config.source_path, icon.src)).copyTo(Path.resolve(config.dist_path, icon.src));
|
526 | })).then(() => {
|
527 | if (manifest.icons) {
|
528 | manifest.icons.forEach(icon => {
|
529 | icon.src = config.site_url + icon.src;
|
530 | });
|
531 | }
|
532 | Promise.all([
|
533 | new File(Path.resolve(config.index_path, "./manifest.json")).write(JSON.stringify(manifest)),
|
534 | maker.minifyCode(config, codes.join("")).then(content => {
|
535 | return new File(Path.resolve(config.index_path, "./serviceworker.js")).write(`'use strict';${content}`);
|
536 | }),
|
537 | new File(Path.resolve(config.index_path, "./index.html")).write(content)
|
538 | ]);
|
539 | });
|
540 | },
|
541 | hashFiles(map) {
|
542 | util.getAllSourcePaths(config.dist_path).forEach(path => {
|
543 | let suffix = new File(path).suffix();
|
544 | let a = path.substring(config.dist_path.length).replace(/\\/g, "/");
|
545 | let b = "";
|
546 | if (!isbinaryfile.sync(path)) {
|
547 | b = map[util.getMappedPath(a)];
|
548 | if (!b) {
|
549 | b = map[a.split(".").shift()];
|
550 | }
|
551 | }
|
552 | if (b) {
|
553 | new File(path).renameSync(Path.resolve(config.dist_path, util.getHashPath(a, b)));
|
554 | }
|
555 | });
|
556 | new File(Path.resolve(config.dist_path, "./ada.js")).renameSync(Path.resolve(config.dist_path, `./ada-${config.adaHash}.js`));
|
557 | },
|
558 | logResult() {
|
559 | let success = [], error = {};
|
560 | let maxLine = 10, _localLength = 0, _moduleLength = 0;
|
561 | Reflect.ownKeys(this.logs).forEach(key => {
|
562 | if (key.indexOf("node_modules") === -1) {
|
563 | _localLength += 1;
|
564 | } else {
|
565 | _moduleLength += 1;
|
566 | }
|
567 | if (this.logs[key] === "done") {
|
568 | success.push(key);
|
569 | } else {
|
570 | error[key] = this.logs[key].message;
|
571 | }
|
572 | });
|
573 | console.log("");
|
574 | console.log(` ${util.formatDate()} LOCAL[`, `${_localLength}`.yellow, `] NODE-MODULES[`, `${_moduleLength}`.yellow, `]`);
|
575 | let hasSuccess = false, hasError = false;
|
576 | if (success.length > 0) {
|
577 | hasSuccess = true;
|
578 | console.log(` COMPILED`.green, util.padEnd(" ", 37 + `${_localLength}`.length + `${_moduleLength}`.length, "-").grey);
|
579 | success.splice(0, maxLine).forEach((path, index) => {
|
580 | if (path.indexOf("node_modules") === -1) {
|
581 | console.log(` [${index + 1}]`.grey, `${path.substring(config.source_path.length)}`.cyan, `[local]`.grey);
|
582 | } else {
|
583 | console.log(` [${index + 1}]`.grey, `${path.substring(config.nmodule_path.length)}`.cyan, `[node_module]`.grey);
|
584 | }
|
585 | });
|
586 | if (success.length > maxLine) {
|
587 | console.log(` +[${success.length + maxLine}]...`.grey);
|
588 | }
|
589 | }
|
590 | let et = Reflect.ownKeys(error);
|
591 | if (et.length > 0) {
|
592 | hasError = true;
|
593 | console.log(` ERRORS`.red, util.padEnd(" ", 39 + `${_localLength}`.length + `${_moduleLength}`.length, "-").red);
|
594 | et.forEach((path, index) => {
|
595 | if (path.indexOf("node_modules") === -1) {
|
596 | console.log(` [${index + 1}] ${path.substring(config.source_path.length)}`.grey);
|
597 | } else {
|
598 | console.log(` [${index + 1}] ${path.substring(config.nmodule_path.length)}`.grey);
|
599 | }
|
600 | console.log(` ${error[path]}`.red);
|
601 | });
|
602 | }
|
603 | if (!hasSuccess && !hasError) {
|
604 | console.log(` - [NOTHING TO DISPLAY] -`.grey);
|
605 | }
|
606 | let _length = 0, __length = 0;
|
607 | Reflect.ownKeys(this.packageLogs).forEach(key => {
|
608 | if (key.length > _length) {
|
609 | _length = key.length;
|
610 | }
|
611 | let info = this.packageLogs[key];
|
612 | let _a = key.length + info.hash.length + info.size.length + info.key.length + info.gsize.length;
|
613 | if (_a > __length) {
|
614 | __length = _a;
|
615 | }
|
616 | });
|
617 | __length = __length + 16;
|
618 | console.log(` PACKAGES`.green, util.padEnd(" ", __length - 10, "-").grey);
|
619 | Reflect.ownKeys(this.packageLogs).forEach((key, index) => {
|
620 | let info = this.packageLogs[key];
|
621 | if (index === 0) {
|
622 | console.log(` [${info.key}]`.grey, `${util.padEnd(key, _length, " ")}`.green, `[${info.size} GZIP:${info.gsize}]`.yellow, `[${info.hash}]`.grey);
|
623 | } else {
|
624 | console.log(` [${info.key}]`.grey, `${util.padEnd(key, _length, " ")}`.cyan, `[${info.size} GZIP:${info.gsize}]`.yellow, `[${info.hash}]`.grey);
|
625 | }
|
626 | });
|
627 | },
|
628 | bundle() {
|
629 | let spinner = ora({
|
630 | color: "yellow",
|
631 | text: "Built Project"
|
632 | }).start();
|
633 | this.logs = {};
|
634 | this.doneMap.length = [];
|
635 | return this.getAppSourceInfo().then(({mainEntry, otherEnteries}) => {
|
636 | otherEnteries.forEach(file => {
|
637 | let r = {};
|
638 | Reflect.ownKeys(file.code).forEach(key => {
|
639 | if (!mainEntry.code[key]) {
|
640 | r[key] = file.code[key];
|
641 | }
|
642 | });
|
643 | file.code = r;
|
644 | });
|
645 | otherEnteries.unshift(mainEntry);
|
646 | let map = {}, packages = {};
|
647 | otherEnteries = otherEnteries.filter(file => {
|
648 | let inp = [];
|
649 | Reflect.ownKeys(file.code).forEach(key => {
|
650 | map[key] = file.code[key].hash;
|
651 | inp.push(file.code[key].hash);
|
652 | });
|
653 | if (inp.length > 1) {
|
654 | packages[file.key] = inp.join("|");
|
655 | return true;
|
656 | }
|
657 | });
|
658 |
|
659 | let ps = Promise.resolve();
|
660 | if (config.entry_auto) {
|
661 | ps = ps.then(() => {
|
662 | let allFiles = this.getAllSource(), _prentries = [];
|
663 | allFiles.forEach(path => {
|
664 | let a = util.getMappedPath(path.substring(config.source_path.length).replace(/\\/g, "/"));
|
665 | if (!map[a]) {
|
666 | _prentries.push(path);
|
667 | }
|
668 | });
|
669 | return this.getEntriesInfo(_prentries).then(({otherEnteries: _otherEnteries}) => {
|
670 | _otherEnteries.forEach(file => {
|
671 | let r = {};
|
672 | Reflect.ownKeys(file.code).forEach(key => {
|
673 | if (!mainEntry.code[key]) {
|
674 | r[key] = file.code[key];
|
675 | }
|
676 | });
|
677 | file.code = r;
|
678 | });
|
679 | let _realOtherEnteries = [];
|
680 | _otherEnteries.forEach(file => {
|
681 | let inp = [];
|
682 | Reflect.ownKeys(file.code).forEach(key => {
|
683 | map[key] = file.code[key].hash;
|
684 | inp.push(file.code[key].hash);
|
685 | });
|
686 | if (inp.length > 1) {
|
687 | packages[file.key] = inp.join("|");
|
688 | _realOtherEnteries.push(file);
|
689 | }
|
690 | });
|
691 | otherEnteries.push(..._realOtherEnteries);
|
692 | });
|
693 | });
|
694 | }
|
695 | ps = ps.then(() => {
|
696 | map.packages = packages;
|
697 | let tasks = otherEnteries.map(file => () => {
|
698 | let p = file.key;
|
699 | let c = `Ada.unpack(${JSON.stringify(file.code)})`;
|
700 | file.hash = hash.md5(map.packages[p].split("|").sort().join("|")).substring(0, 8);
|
701 | map[p] = file.hash;
|
702 | return new File(Path.resolve(config.dist_path, p) + ".js").write(c).then(() => {
|
703 | this.packageLogs[file.name] = {
|
704 | size: new File(Path.resolve(config.dist_path, p) + ".js").getFileSizeAuto(),
|
705 | key: p,
|
706 | hash: file.hash,
|
707 | gsize: util.getFileSizeAuto(gzipSize.sync(c))
|
708 | };
|
709 | });
|
710 | });
|
711 | tasks.push(() => {
|
712 | if (config.develop) {
|
713 | config._adaPath = config.site_url + "ada.js";
|
714 | } else {
|
715 | config._adaPath = `${config.site_url}ada-${config.adaHash}.js`;
|
716 | }
|
717 | config.ada = {
|
718 | basePath: config.site_url,
|
719 | root: Path.resolve(config.base_path, config.main).replace(/\\/g, "/").substring(config.source_path.length),
|
720 | map: map,
|
721 | develop: config.develop
|
722 | };
|
723 | if (!config.develop) {
|
724 | this.hashFiles(map);
|
725 | }
|
726 | return Promise.resolve();
|
727 | });
|
728 | tasks.push(() => {
|
729 | return this.outputPWAFile(config);
|
730 | });
|
731 | tasks.push(() => {
|
732 | return queue(this.getAllFiles().map(path => path.substring(config.source_path.length).replace(/\\/g, "/")).filter(path => {
|
733 | return map[util.getMappedPath(path)] === undefined;
|
734 | }).map(path => () => {
|
735 | return new File(Path.resolve(config.source_path, path)).copyTo(Path.resolve(config.dist_path, path));
|
736 | }));
|
737 | });
|
738 | return queue(tasks).then(() => {
|
739 | spinner.stop();
|
740 | this.logResult();
|
741 | return map;
|
742 | });
|
743 | });
|
744 | return ps;
|
745 | }).then(map => {
|
746 | if (config.complete) {
|
747 | config.complete();
|
748 | config.complete = null;
|
749 | }
|
750 | return {map, log: this.logs};
|
751 | }).catch(e => console.log(e));
|
752 | }
|
753 | };
|
754 |
|
755 | let action = {
|
756 | addFiles(files) {
|
757 | return base.bundle();
|
758 | },
|
759 | editFiles(files) {
|
760 | return base.bundle();
|
761 | },
|
762 | removeFiles(files) {
|
763 | return base.bundle();
|
764 | },
|
765 | publish() {
|
766 | return base.bundle();
|
767 | }
|
768 | };
|
769 |
|
770 | module.exports = function (option) {
|
771 | util.extend(true, config, option);
|
772 | config.base_path = config.base_path.replace(/\\/g, "/");
|
773 | config.dist_path = Path.join(config.base_path, config.dist_path).replace(/\\/g, "/");
|
774 | config.source_path = Path.join(config.base_path, config.source_path).replace(/\\/g, "/");
|
775 | config.nmodule_path = Path.resolve(config.projectPath, "./node_modules/").replace(/\\/g, "/") + "/";
|
776 | config.index_path = Path.resolve(config.base_path, config.index_path, "./../").replace(/\\/g, "/");
|
777 | config.ignore = ignore().add(config.ignore);
|
778 | if (config.site_url[config.site_url.length - 1] !== "/") {
|
779 | config.site_url = config.site_url + "/";
|
780 | }
|
781 | return maker.installAllDependence(config.source_path, config).then(() => {
|
782 | return base.bundleAda(config.develop).then(() => {
|
783 | return action;
|
784 | });
|
785 | });
|
786 | }; |
\ | No newline at end of file |