1 |
|
2 |
|
3 | import FinalModule = require('./FinalModule');
|
4 | import IGulp = require('./IGulp');
|
5 | import path = require('path');
|
6 | import fs = require('fs');
|
7 | import DependencyResolver = require('dependency-resolver');
|
8 |
|
9 | var wrap:(...args:any[])=>any = require('gulp-wrap');
|
10 | var concat:(...args:any[])=>any = require('gulp-concat');
|
11 | var tsc:(...args:any[])=>any = require('gulp-tsc');
|
12 | var uglify:(...args:any[])=>any = require('gulp-uglifyjs');
|
13 | var stylus:(...args:any[])=>any = require('gulp-stylus');
|
14 | var nib:(...args:any[])=>any = require('nib');
|
15 | var sourcemaps:any = require('gulp-sourcemaps');
|
16 | var runSequence:(...args:any[])=>any = require('run-sequence');
|
17 | var clean:any = require('gulp-clean');
|
18 |
|
19 | class FinalModules {
|
20 |
|
21 | private modules:{[name:string]:FinalModule} = {};
|
22 | private modulesInverted:DependencyResolver;
|
23 | private sequence:(...args:any[])=>any
|
24 |
|
25 | constructor(private modulesPath:string = 'public/src') {
|
26 | this.modulesInverted = new DependencyResolver();
|
27 | }
|
28 |
|
29 | public add(name:string, dependencies:string[] = []):void {
|
30 | this.modules[name] = new FinalModule(name, dependencies);
|
31 | this.modulesInverted.add(name);
|
32 | dependencies.forEach((dep:string):void => {
|
33 | this.modulesInverted.setDependency(dep, name);
|
34 | });
|
35 | }
|
36 |
|
37 | private map<T>(func:(mod:FinalModule)=>T):T[] {
|
38 | return Object.keys(this.modules).map((key:string):T => func(this.modules[key]));
|
39 | }
|
40 |
|
41 | public generateTasks(gulp:IGulp.Gulp):void {
|
42 | this.sequence = (<any>runSequence).use(gulp);
|
43 |
|
44 | //Check for circular dependencies:
|
45 | //sort() method will throw an error on circular dependencies
|
46 | this.modulesInverted.sort();
|
47 |
|
48 | this.map((mod:FinalModule):void => {
|
49 | gulp.task('fm:' + mod.name + ':html', this.getHtmlTask(gulp, mod));
|
50 | gulp.task('fm:' + mod.name + ':ts', mod.getDeps('fm:', ':ts'), this.getTsTask(gulp, mod));
|
51 | gulp.task('fm:' + mod.name + ':ts:standalone', this.getTsTask(gulp, mod));
|
52 | gulp.task('fm:' + mod.name + ':min', ['fm:' + mod.name + ':ts'], this.getMinTask(gulp, mod));
|
53 | gulp.task('fm:' + mod.name + ':min:standalone', [mod.name + ':ts:standalone'], this.getMinTask(gulp, mod));
|
54 | gulp.task('fm:' + mod.name + ':styl', this.getStylTask(gulp, mod));
|
55 | gulp.task('fm:' + mod.name + ':clean', this.getCleanTask(gulp, mod));
|
56 | gulp.task('fm:' + mod.name + ':watch:ts', this.getWatchTsTask(gulp, mod));
|
57 | gulp.task('fm:' + mod.name + ':watch:styl', this.getWatchStylTask(gulp, mod));
|
58 | gulp.task('fm:' + mod.name + ':watch:html', this.getWatchHtmlTask(gulp, mod));
|
59 | gulp.task('fm:' + mod.name + ':watch', [mod.name + ':watch:ts', mod.name + ':watch:styl', mod.name + ':watch:html']);
|
60 | });
|
61 |
|
62 | gulp.task('fm:html', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':html'));
|
63 | gulp.task('fm:ts', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':ts'));
|
64 | gulp.task('fm:min', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':min'));
|
65 | gulp.task('fm:styl', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':styl'));
|
66 | gulp.task('fm:clean', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':clean'));
|
67 | gulp.task('fm:watch:ts', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':watch:ts'));
|
68 | gulp.task('fm:watch:styl', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':watch:styl'));
|
69 | gulp.task('fm:watch:html', this.map((mod:FinalModule):string => 'fm:' + mod.name + ':watch:html'));
|
70 | gulp.task('fm:watch', ['fm:watch:ts', 'fm:watch:styl', 'fm:watch:html']);
|
71 | gulp.task('fm', ['fm:clean', 'fm:styl', 'fm:min', 'fm:html', 'fm:watch']);
|
72 | }
|
73 |
|
74 | private static varNameFilter(filePath:string):string {
|
75 | return path.basename(filePath, '.html')
|
76 | .replace(/[^a-zA-Z0-9\_\.]+/g, '-')
|
77 | .replace(/-([a-z])/g, function (g) {
|
78 | return g[1].toUpperCase();
|
79 | })
|
80 | .replace(/\-+/g, '');
|
81 | }
|
82 |
|
83 | private static escapeString(text:string):string {
|
84 | return text
|
85 | .replace(/\n/g, '')
|
86 | .replace(/\'/g, '\\\'');
|
87 | }
|
88 |
|
89 |
|
90 |
|
91 | private getWatchTsTask(gulp:IGulp.Gulp, mod:FinalModule):()=>void {
|
92 | return ():void => {
|
93 | gulp.watch(this.modulesPath + '/' + mod.name + '/src/**/*.ts', ():void => {
|
94 | var tasks:string[] = this.modulesInverted.resolve(mod.name)
|
95 | .reverse()
|
96 | .map((m:string):string => 'fm:' + m + ':min:standalone');
|
97 | this.sequence.apply(this.sequence, tasks);
|
98 | });
|
99 | };
|
100 | }
|
101 |
|
102 | private getCleanTask(gulp:IGulp.Gulp, mod:FinalModule):()=>NodeJS.ReadWriteStream {
|
103 | return ():NodeJS.ReadWriteStream => {
|
104 | return gulp
|
105 | .src(this.modulesPath + '/' + mod.name + '/build', {read: false})
|
106 | .pipe(clean());
|
107 | };
|
108 | }
|
109 |
|
110 | private getWatchStylTask(gulp:IGulp.Gulp, mod:FinalModule):()=>void {
|
111 | return ():void => {
|
112 | gulp.watch(this.modulesPath + '/' + mod.name + '/src/**/*.styl', ['fm:' + mod.name + ':styl']);
|
113 | };
|
114 | }
|
115 |
|
116 | private getWatchHtmlTask(gulp:IGulp.Gulp, mod:FinalModule):()=>void {
|
117 | return ():void => {
|
118 | gulp.watch(this.modulesPath + '/' + mod.name + '/src/**/*.html', ['fm:' + mod.name + ':html']);
|
119 | };
|
120 | }
|
121 |
|
122 | private getStylTask(gulp:IGulp.Gulp, mod:FinalModule):()=>NodeJS.ReadWriteStream {
|
123 | return ():NodeJS.ReadWriteStream => {
|
124 | return gulp.src([this.modulesPath + '/' + mod.name + '/src/**/*.styl'])
|
125 | .pipe(stylus({
|
126 | use: nib(),
|
127 | sourcemap: {
|
128 | inline: true,
|
129 | sourceRoot: '',
|
130 | basePath: 'css'
|
131 | }
|
132 | }))
|
133 | .pipe(sourcemaps.init({
|
134 | loadMaps: true
|
135 | }))
|
136 | .pipe(concat(mod.name + '.css'))
|
137 | .pipe(sourcemaps.write('.', {
|
138 | includeConent: false,
|
139 | sourceRoot: ''
|
140 | }))
|
141 | .pipe(gulp.dest(this.modulesPath + '/' + mod.name + '/build/'));
|
142 | };
|
143 | }
|
144 |
|
145 | private getMinTask(gulp:IGulp.Gulp, mod:FinalModule):()=>NodeJS.ReadWriteStream {
|
146 | return ():NodeJS.ReadWriteStream => {
|
147 |
|
148 | var inSourceMapPath:string = this.modulesPath + '/'
|
149 | + mod.name + '/build/' + mod.name + '.js.map';
|
150 |
|
151 | return gulp.src([this.modulesPath + '/' + mod.name + '/build/' + mod.name + '.js'])
|
152 | .pipe(uglify(mod.name + '.min.js', {
|
153 | outSourceMap: true,
|
154 | output: {
|
155 | source_map: {
|
156 | file: mod.name + '.min.js',
|
157 | root: '',
|
158 | orig: fs.readFileSync(inSourceMapPath).toString()
|
159 | }
|
160 | }
|
161 | }))
|
162 | .pipe(gulp.dest(this.modulesPath + '/' + mod.name + '/build/'));
|
163 | };
|
164 | }
|
165 |
|
166 | private getTsTask(gulp:IGulp.Gulp, mod:FinalModule):()=>NodeJS.ReadWriteStream {
|
167 | return ():NodeJS.ReadWriteStream => {
|
168 | var outDir = this.modulesPath + '/' + mod.name + '/build';
|
169 |
|
170 | return gulp.src([
|
171 | this.modulesPath + '/' + mod.name + '/src/**/*.ts',
|
172 | '!' + this.modulesPath + '/' + mod.name + '/src/**/*.d.ts'
|
173 | ])
|
174 | .pipe(tsc({
|
175 | emitError: false,
|
176 | module: 'amd',
|
177 | target: 'ES5',
|
178 | outDir: outDir,
|
179 | sourcemap: true,
|
180 | sourceRoot: '',
|
181 | declaration: true,
|
182 | out: mod.name + '.js'
|
183 | }))
|
184 | .pipe(gulp.dest(outDir));
|
185 | };
|
186 | }
|
187 |
|
188 | private getHtmlTask(gulp:IGulp.Gulp, mod:FinalModule):()=>NodeJS.ReadWriteStream {
|
189 | return ():NodeJS.ReadWriteStream => {
|
190 | var modNameSplit:string[] = mod.name.split('.');
|
191 | var modVarInit:string;
|
192 |
|
193 | var nameAlready:string = modNameSplit[0];
|
194 | modVarInit = 'var $name = $name || {};'.replace(/\$name/g, nameAlready);
|
195 |
|
196 | for (var i = 1; i < modNameSplit.length; i += 1) {
|
197 | nameAlready += '.' + modNameSplit[i];
|
198 | modVarInit += '\n$name = $name || {};'.replace(/\$name/g, nameAlready);
|
199 | }
|
200 |
|
201 | return gulp.src(this.modulesPath + '/' + mod.name + '/src/**/*.html')
|
202 | .pipe(wrap('<%=mod.name%>.html.<%= varName(file.path) %> = \'<%=escape(contents)%>\';', {
|
203 | mod: mod,
|
204 | varName: FinalModules.varNameFilter,
|
205 | escape: FinalModules.escapeString
|
206 | }))
|
207 | .pipe(concat(mod.name + '.html.js'))
|
208 | .pipe(wrap(
|
209 | modVarInit + '\n<%=mod.name%>.html = {};\n\n<%=contents%>',
|
210 | {mod: mod}
|
211 | ))
|
212 | .pipe(gulp.dest(this.modulesPath + '/' + mod.name + '/build'));
|
213 | };
|
214 | }
|
215 | }
|
216 |
|
217 | export = FinalModules;
|