UNPKG

23 kBJavaScriptView Raw
1var gulp = require("gulp");
2var $ = require('gulp-load-plugins')();
3var through = require("through2");
4var fs = require("fs");
5var Path = require("path");
6var events = require('events');
7// 创建 eventEmitter 对象
8var eventEmitter = new events.EventEmitter();
9/**
10 * 主要是开发时使用,实现对目录的监听、打包等
11 */
12var config = {
13 modulename: "starter",
14 browserify: {
15 public: {
16 entry: "main/main.js",
17 concatWith: "lib/ionic/js/ionic.bundle.min.js",
18 name: "concat.js",
19 mini: true
20 },
21 default: {
22 dest: "./"
23 },
24 deploy: {
25 dest: "dist"
26 }
27 },
28 grammer: {
29 default: {
30 "dev": "qianzhixiang"
31 },
32 deploy: {
33 "dev": "qianzhixiasdasdang"
34 },
35 public: {
36
37 }
38 },
39 less: {
40 public: {
41 src: "style.less",
42 concatWith: "lib/ionic/css/ionic.min.css",
43 dest: "./",
44 name: "style.css",
45 mini: true
46 // relaySrcPath: ""
47 },
48 default: {
49
50 },
51 deploy: {
52 dest: "dist"
53 }
54 },
55 static: {
56 deploy: {
57 src: ["lib/ionic/fonts/*", "index.html"],
58 dest: ["dist", "../../server/views"]
59 }
60 },
61 deploy: ["dist", "../../server/views"],
62 watch: ['style.less', 'main/**'],
63 angular: {
64 provider: {
65 directory: [/\-provider$/gi, /\-prvd/gi, /\-svc/gi],
66 file: [/\-provider/gi, /\-prvd/gi, /\-svc/gi],
67 },
68 controller: {
69 directory: [/\-controller/gi, /\-ctrl/gi],
70 file: [/\-controller/gi, /\-ctrl/gi],
71 },
72 config: {
73 directory: [/\-config/gi, /\-cfg/gi],
74 file: [/\-config/gi, /\-cfg/gi]
75 },
76 directive: {
77 directory: [/\-directive/gi, /\-direct/gi],
78 file: [/\-directive/gi, /\-direct/gi],
79 },
80 filter: {
81 directory: [/\-filter/gi, /\-flt/gi],
82 file: [/\-filter/gi, /\-flt/gi],
83
84 },
85 run: {
86 directory: [/\-run/gi],
87 file: [/\-run/gi]
88 },
89 factory: {
90 directory: [/\-factory/gi, /\-fct/gi, /\-services$/gi],
91 file: [/\-factory/gi, /\-fct/gi],
92 }
93 }
94}
95var watcher = function(name) {
96 var me = this;
97 me.name = name;
98 console.log("开始监听", name)
99 gulp.watch(name, function(file) {
100 if (me.isLegal(file)) {
101 // 是个合法的路径
102 var parse = me.parse(file.path);
103 if (parse.extname == ".html") {
104 // 将html转为js
105 used.html2js(file, function() {})
106 }
107 if (file.type == "added") {
108 if (parse.type == "directory") {
109 // 是个文件夹
110 me.initDirectory(file.path, function() {
111 // 建立完成
112 });
113 }
114 if (parse.type == "file") {
115 // 是个文件 文件有可能是我手动建立时添加的,这个同样的是会被监听到的,得防止这类的处理,否则browserify等处理就很重复
116 if (parse.extname == ".less") {
117 // 将less 添加到父目录
118 me.initParent(file.path, "style.less", function() {
119
120 }, true);
121 }
122 if (parse.extname == ".js") {
123 if (parse.filename !== "main") {
124 // 将js 添加到父目录
125 me.initParent(file.path, "main.js", function() {
126
127 }, true);
128 // 将内容写到js
129 console.log(parse.filename, "发生了改变!");
130 for (var i in config.angular) {
131 var item = config.angular[i];
132 var flag = 0;
133 for (var j in item.file) {
134 var reg = item.file[j];
135 if (reg.test(parse.filename)) {
136 reg.lastIndex = 0;
137 // 将`-`拼接起来的名称转为驼峰法的命名
138 var arr = parse.filename.split("-");
139 var str = arr[0] || "";
140 for (var k = 1; k < arr.length; k++) {
141 var p = arr[k];
142 p = p.replace(/\w/i, function(a, b) { return a.toUpperCase() })
143 str += p;
144 }
145 console.log("匹配到了", i)
146 // 匹配的上
147 i == "config" || i == "run" ?
148 fs.writeFileSync(file.path, "angular.module('" + config.modulename + "')\n ." + i + "(function(){\n \n})") :
149 fs.writeFileSync(file.path, "angular.module('" + config.modulename + "')\n ." + i + "('" + str + "',function(){\n \n})");
150 flag++;
151 break;
152 }
153 }
154 if (flag <= 0) {
155 // file没找到 到目录找
156 for (var j in item.directory) {
157 var reg = item.directory[j];
158 // 父目录
159 if (reg.test(parse.parent)) {
160 reg.lastIndex = 0;
161 var arr = parse.filename.split("-");
162 var str = arr[0] || "";
163 for (var k = 1; k < arr.length; k++) {
164 var p = arr[k];
165 p = p.replace(/\w/i, function(a, b) { return a.toUpperCase() })
166 str += p;
167 }
168 // 匹配的上
169 i == "config" || i == "run" ?
170 fs.writeFileSync(file.path, "angular.module('" + config.modulename + "')\n ." + i + "(function(){\n \n})") :
171 fs.writeFileSync(file.path, "angular.module('" + config.modulename + "')\n ." + i + "('" + str + "',function(){\n \n})");
172 flag++;
173 break;
174 }
175 }
176 }
177 if (flag > 0) {
178 break;
179 }
180 }
181 } else {
182 console.log("是main.js")
183 }
184 }
185 }
186 } else {
187 if (parse.type == "file") {
188 // 是个文件 文件有可能是我手动建立时添加的,这个同样的是会被监听到的,得防止这类的处理,否则browserify等处理就很重复
189 if (parse.extname == ".less") {
190 // 将less 添加到父目录
191 used.less(false, function() {
192
193 })
194 }
195 if (parse.extname == ".js") {
196 // 编译
197 used.browserify(false, function() {
198
199 })
200 }
201 }
202 }
203
204 }
205 })
206};
207watcher.prototype.isLegal = function(file) {
208 var me = this;
209 try {
210 var arr = me.name.split("*");
211 // 由于gulp-watch本身的bug,比如监听某个文件,其实他会监听当前所在的目录,容易出现bug
212 var watch_root = Path.join(process.cwd(), arr[0]);
213 // 判断是自己需要监听的目录
214 if (watch_root && file.path.indexOf(watch_root) >= 0) {
215 return true;
216 }
217 } catch (e) {
218 return false;
219 }
220 return false;
221};
222watcher.prototype.parse = function(path) {
223 var me = this;
224 var extname = Path.extname(path);
225 var dirname = Path.dirname(path);
226 return {
227 extname: extname,
228 dirname: dirname,
229 filename: Path.basename(path, extname),
230 parent: Path.basename(dirname),
231 type: me.getType(path)
232 }
233};
234watcher.prototype.getType = function(path) {
235 try {
236 var stat = fs.statSync(path);
237 if (stat.isFile()) {
238 return "file";
239 } else if (stat.isDirectory()) {
240 return "directory";
241 } else {
242 return null;
243 }
244 } catch (e) {
245 // 不存在
246 return null;
247 }
248 return null;
249};
250/**
251 * [initDirectory description] 去父目录加上require
252 * @param {[type]} path [description]
253 * @param {Function} cb [description]
254 * @return {[type]} [description]
255 */
256watcher.prototype.initDirectory = function(path, cb) {
257 var me = this;
258 cb = cb || function() {};
259 var js = Path.join(path, "main.js");
260 var less = Path.join(path, "style.less");
261 var flag = 0;
262 me.initParent(path, "main.js", function() {
263 flag++;
264 if (flag == 4) {
265 cb();
266 }
267 });
268 me.initParent(path, "style.less", function() {
269 flag++;
270 if (flag == 4) {
271 cb();
272 }
273 });
274 fs.writeFile(js, "angular.module('" + config.modulename + "')\n ", function() {
275 flag++;
276 if (flag == 4) {
277 cb();
278 }
279 });
280 fs.writeFile(less, "\n", function() {
281 flag++;
282 if (flag == 4) {
283 cb();
284 }
285 })
286 // 在父层级的main 以及 less 加上对应的后缀
287
288};
289watcher.prototype.initParent = function(path, filename, cb, isFile) {
290 var dirname = Path.dirname(path);
291 var basename = Path.basename(path);
292 var parent = isFile ? Path.join(dirname, filename) : Path.join(dirname, filename);
293 var extname = Path.extname(filename);
294 var pre = "";
295 if (fs.existsSync(parent)) {
296 var stream = gulp.src(parent)
297 if (!isFile) {
298 if (extname == ".js") {
299 stream = stream.pipe($.footer("require('./" + basename + Path.sep + filename + "');\n"))
300 };
301 if (extname == ".less") {
302 stream = stream.pipe($.footer("@import './" + basename + Path.sep + filename + "';\n"))
303 }
304 } else {
305 if (extname == ".js") {
306 stream = stream.pipe($.footer("require('./" + basename + "');\n"))
307 };
308 if (extname == ".less") {
309 stream = stream.pipe($.footer("@import './" + basename + "';\n"))
310 }
311 }
312 // .pipe($.footer(pre + "('./" + basename + Path.sep + filename + "')\n"))
313 stream.pipe(gulp.dest(dirname))
314 .on("end", function() {
315 cb();
316 })
317 } else {
318 console.log(parent, " is not exists")
319 }
320}
321var used = {
322 mix: (function(a, b) {
323 var mix = function(a, b) {
324 if (typeof b == "object" && !(b instanceof Array)) {
325 for (var i in b) {
326 if (!a.hasOwnProperty(i)) {
327 a[i] = b[i];
328 } else {
329 // 有
330 a[i] = mix(a[i], b[i]);
331 }
332 }
333 } else {
334 a = b;
335 }
336 return a;
337 };
338 return mix;
339 })(),
340 html2js: function(file, cb) {
341 var me = this;
342 cb = cb || function() {};
343 var dirname = Path.dirname(file.path);
344 var relative = Path.relative(process.cwd(), dirname) + "/";
345 gulp.src(file.path)
346 .pipe($.plumber({
347 errorHandler: me.errorHandler
348 }))
349 .pipe($.ngHtml2js({
350 moduleName: config.modulename,
351 prefix: relative,
352 standalone: true
353 }))
354 .pipe($.footer("module.exports='<%= name %>';", { name: relative + Path.basename(file.path) }))
355 .pipe(gulp.dest(dirname))
356 .on("end", function() {
357 cb();
358 })
359 },
360 browserify: function(isDeploy, cb) {
361 var me = this;
362 cb = cb || function() {};
363 console.log("browserify begin")
364 var rename = me.getPro(isDeploy, "browserify", "name")
365 var entry = me.getPro(isDeploy, "browserify", "entry")
366 var stream = gulp.src(entry)
367 .pipe($.plumber({
368 errorHandler: me.errorHandler
369 }))
370 .pipe($.browserify()) // browserify的操作
371 .pipe($.ngAnnotate()) // 加上依赖
372 // 匹配语法
373 .pipe(through.obj(function(file, enc, cb) {
374 file.contents = new Buffer(me.formatGrammer(file.contents.toString("utf8"), isDeploy));
375 this.push(file);
376 cb();
377 }))
378 // 压缩
379 if (me.getPro(isDeploy, "browserify", "mini")) {
380 stream = stream.pipe($.uglify())
381 }
382 stream = stream.pipe(through.obj(function(file, enc, cb) {
383 var contents = '';
384 var me_ = this;
385 // 打包合并
386 gulp.src(me.getPro(isDeploy, "browserify", "concatWith"))
387 .pipe($.concat("concat.js"))
388 .pipe(through.obj(function(f, e, c) {
389 contents += f.contents.toString("utf8");
390 file.contents = new Buffer(contents + file.contents);
391 // this.push(f)
392 c(null, f);
393
394 me_.push(file);
395 cb();
396 }))
397 }))
398 .pipe($.rename(rename))
399 var destPath = me.getPro(isDeploy, "browserify", "dest");
400 if (destPath instanceof Array) {
401 destPath.forEach(function(p) {
402 stream = stream.pipe(gulp.dest(p));
403 })
404 } else if (typeof destPath == "string") {
405 stream = stream.pipe(gulp.dest(destPath));
406 } else {
407 stream = stream.pipe(gulp.dest("./"));
408 }
409 stream.on("end", function() {
410 console.log("browserify end")
411 cb();
412 })
413 },
414 less: function(isDeploy, cb) {
415 var me = this;
416 console.log("less begin");
417 var stream = gulp.src(me.getPro(isDeploy, "less", "src"))
418 .pipe($.less());
419 if (me.getPro(isDeploy, "less", "mini")) {
420 stream = stream.pipe($.minifyCss())
421 }
422 // 合并
423 stream = stream.pipe(through.obj(function(file, enc, cb) {
424 var me_ = this;
425 gulp.src(me.getPro(isDeploy, "less", "concatWith"))
426 .pipe(through.obj(function(f, e, c) {
427 f.contents = new Buffer(me.transformCssPath(f.contents.toString("utf8"), f.path));
428 this.push(f);
429 c();
430 }))
431 .pipe($.concat(me.getPro(isDeploy, "less", "name")))
432 .pipe(through.obj(function(f, e, c) {
433 file.contents = new Buffer(f.contents.toString("utf8") + file.contents.toString("utf8"));
434 c();
435 me_.push(file);
436 cb();
437 }))
438 }))
439 // 存放在路径
440 var destPath = me.getPro(isDeploy, "less", "dest");
441 if (destPath instanceof Array) {
442 destPath.forEach(function(p) {
443 stream = stream.pipe(gulp.dest(p));
444 })
445 } else if (typeof destPath == "string") {
446 stream = stream.pipe(gulp.dest(destPath));
447 } else {
448 stream = stream.pipe(gulp.dest("./"));
449 }
450 stream.on("end", function() {
451 console.log("less end")
452 cb();
453 })
454 },
455 formatGrammer: function(content, isDeploy) {
456 var reg = /\$\{\s*([$_a-zA-Z0-9]+)\s*\}/gi;
457 content = content.replace(reg, function(content, cloak) {
458 var grammer;
459 if (isDeploy) {
460 // 发布环境
461 grammer = config.grammer.deploy;
462 } else {
463 // 非发布环境
464 grammer = config.grammer.default;
465 };
466 if (grammer.hasOwnProperty(cloak)) {
467 // 是否有对应的属性
468 return grammer[cloak];
469 } else {
470 return config.grammer.public[cloak];
471 }
472 })
473 return content;
474 },
475 errorHandler: function(err) {
476 console.log(err.toString());
477 },
478 getPro: function(isDeploy, type, pro) {
479 return isDeploy ?
480 (function() {
481 if (pro == "dest" && config.deploy) {
482 return config.deploy;
483 }
484 return (config[type]['deploy'][pro] ? config[type]['deploy'][pro] : config[type]['public'][pro]);
485 })() :
486 (config[type]['default'][pro] ? config[type]['default'][pro] : config[type]['public'][pro])
487 },
488 transformCssPath: function(content, path, point) {
489 var reg = /url\(([^\(\)]+)\)/gi;
490 var data_reg = /data\:.+/gi;
491 content = content.replace(reg, function(content, cloak) {
492 cloak = cloak.trim();
493 arr = cloak.match(data_reg);
494 if (!arr) {
495 var relativedir = Path.dirname(Path.relative(process.cwd(), path));
496 cloak = Path.join(relativedir, cloak);
497 }
498 return cloak;
499 })
500 return content;
501 },
502 mkdir: function(dir, mode) {
503 var pathTemp = '/';
504 dir.split(Path.sep).forEach(function(dirname) {
505 pathTemp = Path.join(pathTemp, dirname);
506 if (!fs.existsSync(pathTemp)) {
507 console.log("不存在", pathTemp)
508 // 不存在,新建
509 fs.mkdirSync(pathTemp, mode)
510 }
511 })
512 },
513 writeFileSync: function(file) {
514 var me = this;
515 var filepath = file.path;
516 var contents = file.contents.toString("utf8");
517 var dir = Path.dirname(filepath);
518 me.mkdir(dir);
519 fs.writeFileSync(filepath, contents);
520 },
521 del: (function() {
522 function iterator(url, dirs) {
523 var stat = fs.statSync(url);
524 if (stat.isDirectory()) {
525 dirs.unshift(url); //收集目录
526 inner(url, dirs);
527 } else if (stat.isFile()) {
528 fs.unlinkSync(url); //直接删除文件
529 }
530 }
531
532 function inner(path, dirs) {
533 var arr = fs.readdirSync(path);
534 for (var i = 0, el; el = arr[i++];) {
535 iterator(path + "/" + el, dirs);
536 }
537 }
538 return function(dir, cb) {
539 cb = cb || function() {};
540 var dirs = [];
541 try {
542 iterator(dir, dirs);
543 for (var i = 0, el; el = dirs[i++];) {
544 fs.rmdirSync(el); //一次性删除所有收集到的目录
545 }
546 cb()
547 } catch (e) { //如果文件或目录本来就不存在,fs.statSync会报错,不过我们还是当成没有异常发生
548 e.code === "ENOENT" ? cb() : cb(e);
549 }
550 }
551 })()
552};
553var auto = {
554 watchConfig: function(path) {
555
556 fs.watch(path, function(e, filename) {
557 delete require.cache[path];
558 var cfg = require(path);
559 used.mix(config, cfg);
560 })
561 },
562 start: function(cfg, func) {
563 var me = this;
564 var cfg_ = require(cfg);
565 used.mix(config, cfg_);
566 func = func || function() {};
567 gulp.task("default", function() {
568 var flag = 0;
569 me.watchConfig(cfg);
570 eventEmitter.on("relayend", function() {
571 if (config.watch) {
572 if (typeof config.watch == 'string') {
573 config.watch = [config.watch];
574 } else if (!(config.watch instanceof Array)) {
575 config.watch = []
576 }
577 }
578 config.watch.forEach(function(src) {
579 new watcher(src);
580 })
581 });
582 used.browserify(false, function() {
583 flag++;
584 if (flag == 2) {
585 eventEmitter.emit("relayend")
586 }
587 })
588 used.less(false, function() {
589 flag++;
590 if (flag == 2) {
591 eventEmitter.emit("relayend")
592 }
593 })
594 func()
595 });
596 gulp.task("deploy", function() {
597 var dest = [];
598 if (config.deploy) {
599 if (typeof config.deploy == "string") {
600 dest.push(config.deploy);
601 } else if (config.deploy instanceof Array) {
602 dest = config.deploy;
603 }
604 } else if (typeof config.static.deploy.dest == "string") {
605 dest.push(config.static.deploy.dest);
606 } else if (config.static.deploy.dest instanceof Array) {
607 dest = config.static.deploy.dest;
608 };
609 dest.forEach(function(destname) {
610 used.del(destname);
611 })
612 gulp.src(config.static.deploy.src)
613 .pipe(through.obj(function(file, enc, cb) {
614 var relative = Path.relative(process.cwd(), file.path);
615 dest.forEach(function(destname) {
616 var destPath = Path.join(Path.resolve(destname), relative);
617 file.path = destPath;
618 used.writeFileSync(file);
619 })
620 this.push(file);
621 cb();
622 }))
623 used.browserify(true, function() {
624
625 });
626 used.less(true, function() {
627
628 })
629 })
630 }
631}
632module.exports = auto;
\No newline at end of file