1 | (function(){
|
2 |
|
3 | var
|
4 | watch = require( 'watch-tree-maintained' ),
|
5 | async = require( 'asyncjs' ),
|
6 | fs = require( 'fs' ),
|
7 | colorize = require( 'colorize' ),
|
8 | console = colorize.console,
|
9 | util = require( 'util' ),
|
10 | path = require( 'path' ),
|
11 | inspect = util.inspect,
|
12 | plugins = require('./plugins'),
|
13 | _ = require('underscore'),
|
14 | VERSION = require('../package.json').version;
|
15 |
|
16 | module.exports.plugins = plugins;
|
17 | module.exports.Compiler = Compiler;
|
18 | module.exports.VERSION = VERSION;
|
19 |
|
20 | function Compiler( rootDir, outputDir, watchMode, watchOpts ) {
|
21 | this.rootDir = rootDir;
|
22 | this.outputDir = outputDir;
|
23 | this.watchMode = !!watchMode;
|
24 | this.rules = [];
|
25 | this.watchOpts = watchOpts || {};
|
26 | this.waitTime = 100;
|
27 | return this;
|
28 | }
|
29 |
|
30 | var levelColorMap = {
|
31 | 'error' : 'red',
|
32 | 'success' : 'green',
|
33 | 'msg' : 'plain',
|
34 | 'info' : 'cyan',
|
35 | 'warn' : 'yellow'
|
36 | };
|
37 |
|
38 | Compiler.prototype.log = function( level, coloredPart, plainPart ) {
|
39 | var color = levelColorMap[level],
|
40 | outputString = colorize.ansify("#" + color + "[" + coloredPart + "]") + (plainPart ? ": " + plainPart : "");
|
41 | util.log( outputString );
|
42 | };
|
43 |
|
44 | Compiler.prototype.start = function() {
|
45 | var that = this,
|
46 | watchMode = that.watchMode,
|
47 | rootDir = that.rootDir,
|
48 | outputDir = that.outputDir;
|
49 | this.log('success', 'Auton v' + VERSION + ' starting...');
|
50 | var opts = _.extend({
|
51 | 'sample-rate' : 5,
|
52 | 'ignore' : new RegExp('/[._]')
|
53 | }, this.watchOpts);
|
54 | var watcher = watch.watchTree(rootDir, opts);
|
55 |
|
56 | var _compile = function(path){ return that._compile(path); };
|
57 | var _delete = function(path){ return that._delete(path); };
|
58 |
|
59 | watcher.on( 'filePreexisted', _compile );
|
60 | watcher.on( 'fileCreated', _compile );
|
61 | watcher.on( 'fileModified', _compile );
|
62 | watcher.on( 'fileDeleted', _delete );
|
63 | watcher.on( 'allPreexistingFilesReported', function(){
|
64 | if (watchMode) {
|
65 | that.log('info', "Entering watch mode");
|
66 | } else {
|
67 | that.log('info', "All files scanned");
|
68 | watcher.end();
|
69 | }
|
70 | });
|
71 | };
|
72 |
|
73 | Compiler.prototype.addRule = function( test, outputFilenameFunction, ruleList ) {
|
74 | this.rules.push({
|
75 | test: test,
|
76 | outputFilenameFunction: outputFilenameFunction,
|
77 | ruleList: ruleList
|
78 | });
|
79 | };
|
80 |
|
81 | Compiler.prototype.copy = function( test ) {
|
82 | this.rules.push({
|
83 | test: test,
|
84 | outputFilenameFunction: function(type, filePath){ return (type === 'original' || type === '__age_check__') ? filePath : null; },
|
85 | ruleList: [plugins.read, plugins.save]
|
86 | });
|
87 | };
|
88 |
|
89 | Compiler.prototype.ignore = function( test ) {
|
90 | this.rules.push({
|
91 | test: test,
|
92 | ignore: true,
|
93 | });
|
94 | };
|
95 |
|
96 | function checkTest( test, target ) {
|
97 | if (test instanceof RegExp && test.test(target) ) {
|
98 | return true;
|
99 | }
|
100 | else if (typeof test === 'function' && test(target) === true) {
|
101 | return true;
|
102 | }
|
103 | else if (typeof test === 'string' && test === target) {
|
104 | return true;
|
105 | }
|
106 | }
|
107 |
|
108 |
|
109 |
|
110 | Compiler.prototype._compile = function(path) {
|
111 | path = path.replace(this.rootDir + "/", "");
|
112 | for (i = 0, len = this.rules.length; i < len; i++) {
|
113 | var rule = this.rules[i];
|
114 | if (checkTest( rule.test, path )) {
|
115 | if (rule.ignore) {
|
116 | return;
|
117 | }
|
118 | this._runChain( path, rule, rule.ruleList );
|
119 | return;
|
120 | }
|
121 | }
|
122 |
|
123 | this.log( 'warn', "Skipped", path );
|
124 | };
|
125 |
|
126 | Compiler.prototype._delete = function(path) {
|
127 |
|
128 | };
|
129 |
|
130 | Compiler.prototype._runChain = function(file, rule, functions) {
|
131 | var args = {
|
132 | compiler: this,
|
133 | rule: rule,
|
134 | path: file,
|
135 | save: { },
|
136 | savedFilenames: [ ]
|
137 | },
|
138 | makeCyan = function(x){ return colorize.ansify("#cyan[" + x + "]"); },
|
139 | go = function() {
|
140 | async.list(functions).call(args).end(function(e){
|
141 | if (e) {
|
142 | args.compiler.log( 'error', "Error in "+file, "\n" + e.toString() + "\n" );
|
143 | } else {
|
144 | if (args.savedFilenames.length) {
|
145 | args.compiler.log( 'success', file, "Saved " + args.savedFilenames.map(makeCyan).join(', ') );
|
146 | } else {
|
147 | args.compiler.log( 'success', file, 'OK!' );
|
148 | }
|
149 |
|
150 | }
|
151 | });
|
152 | };
|
153 |
|
154 | var ageCheckFilename = rule.outputFilenameFunction( '__age_check__', file );
|
155 | if (ageCheckFilename) {
|
156 | var infile = path.join( this.rootDir, file ),
|
157 | outfile = path.join( this.outputDir, ageCheckFilename );
|
158 | fs.stat( infile, function(err, infileStats){
|
159 | if (err) {
|
160 | args.compiler.log( 'error', 'couldnt stat '+infile, err);
|
161 | return;
|
162 | }
|
163 | fs.exists( outfile, function(exists){
|
164 | if (exists) {
|
165 | fs.stat( outfile, function(err, outfileStats){
|
166 | if (err) {
|
167 | args.compiler.log( 'error', 'couldnt stat '+outfile, err);
|
168 | return;
|
169 | }
|
170 |
|
171 | if (Date.parse(infileStats.mtime) > Date.parse(outfileStats.mtime)) {
|
172 | setTimeout( go, args.compiler.waitTime );
|
173 | }
|
174 | });
|
175 | } else {
|
176 | setTimeout( go, args.compiler.waitTime );
|
177 | }
|
178 |
|
179 | });
|
180 | });
|
181 | } else {
|
182 | setTimeout( go, args.compiler.waitTime );
|
183 | }
|
184 | };
|
185 |
|
186 |
|
187 | })();
|