1
+ gulp = require ' gulp'
2
+
3
+ _ = require ' lodash'
4
+ bg = require ' gulp-bg'
5
+ bump = require ' gulp-bump'
6
+ chai = require ' chai'
7
+ closureCompiler = require ' gulp-closure-compiler'
8
+ closureDeps = require ' gulp-closure-deps'
9
+ coffee = require ' gulp-coffee'
10
+ coffee2closure = require ' gulp-coffee2closure'
11
+ concat = require ' gulp-concat'
12
+ cond = require ' gulp-cond'
13
+ diContainer = require ' gulp-closure-dicontainer'
14
+ esteWatch = require ' este-watch'
15
+ eventStream = require ' event-stream'
16
+ filter = require ' gulp-filter'
17
+ fs = require ' fs'
18
+ git = require ' gulp-git'
19
+ gulpReact = require ' gulp-react'
20
+ gutil = require ' gulp-util'
21
+ jsdom = require (' jsdom' ).jsdom
22
+ livereload = require ' gulp-livereload'
23
+ minifyCss = require ' gulp-minify-css'
24
+ mocha = require ' gulp-mocha'
25
+ path = require ' path'
26
+ plumber = require ' gulp-plumber'
27
+ react = require ' react'
28
+ rename = require ' gulp-rename'
29
+ requireUncache = require ' require-uncache'
30
+ sinon = require ' sinon'
31
+ size = require ' gulp-size'
32
+ stylus = require ' gulp-stylus'
33
+
34
+ module .exports = class GulpEste
35
+
36
+ constructor : (@dirname , @production , @depsPrefix ) ->
37
+ @globals = Object .keys global
38
+
39
+ changedFilePath : null
40
+ globals : null
41
+ liveReloadServer : null
42
+
43
+ # NOTE: gulp-stylus doesn't report fileName on error. Waiting for Gulp 4.
44
+ stylus : (paths ) ->
45
+ streams = paths .map (path) =>
46
+ gulp .src path, base : ' .'
47
+ .pipe stylus set : [' include css' ]
48
+ .on ' error' , (err ) -> gutil .log err .message
49
+ .pipe gulp .dest ' .'
50
+ .pipe rename (path ) ->
51
+ path .dirname = path .dirname .replace ' /css' , ' /build'
52
+ return
53
+ .pipe cond @production , minifyCss ()
54
+ .pipe gulp .dest ' .'
55
+ eventStream .merge streams...
56
+ # NOTE: Ensure watch isn't stopped on error. Waiting for Gulp 4.
57
+ # github.com/gulpjs/gulp/issues/258.
58
+ return
59
+
60
+ coffee : (paths ) ->
61
+ gulp .src @changedFilePath ? paths, base : ' .'
62
+ .pipe plumber ()
63
+ .pipe coffee bare : true
64
+ .on ' error' , (err ) -> gutil .log err .message
65
+ .pipe coffee2closure ()
66
+ .pipe gulp .dest ' .'
67
+
68
+ # NOTE: gulp-react doesn't report fileName on error. Waiting for Gulp 4.
69
+ react : (paths ) ->
70
+ gulp .src @changedFilePath ? paths, base : ' .'
71
+ .pipe plumber ()
72
+ .pipe gulpReact harmony : true
73
+ .on ' error' , (err ) -> gutil .log err .message
74
+ .pipe gulp .dest ' .'
75
+
76
+ deps : (paths ) ->
77
+ gulp .src paths
78
+ .pipe closureDeps fileName : ' deps0.js' , prefix : @depsPrefix
79
+ .pipe gulp .dest ' tmp'
80
+
81
+ unitTest : (baseJsDir , paths ) ->
82
+ nodejsPath = path .join baseJsDir, ' bootstrap/nodejs'
83
+ changedFilePath = @changedFilePath
84
+
85
+ if changedFilePath
86
+ # Ensure changedFilePath is _test.js file.
87
+ if ! / _test\. js$ / .test changedFilePath
88
+ changedFilePath = changedFilePath .replace ' .js' , ' _test.js'
89
+ return if not fs .existsSync changedFilePath
90
+
91
+ # Clean global variables created during test. For instance: goog and este.
92
+ Object .keys (global ).forEach (key) =>
93
+ return if @globals .indexOf (key) > - 1
94
+ delete global [key]
95
+
96
+ # Global aliases for tests.
97
+ global .assert = chai .assert ;
98
+ global .sinon = sinon
99
+
100
+ # Mock browser, add React.
101
+ doc = jsdom ()
102
+ global .window = doc .parentWindow
103
+ global .document = doc .parentWindow .document
104
+ global .navigator = doc .parentWindow .navigator
105
+ global .React = react
106
+
107
+ # Server-side Google Closure, refreshed for each test.
108
+ requireUncache path .resolve nodejsPath
109
+ requireUncache path .resolve ' tmp/deps0.js'
110
+ require path .resolve nodejsPath
111
+ require path .resolve ' tmp/deps0.js'
112
+
113
+ # Auto-require Closure dependencies.
114
+ autoRequire = (file ) =>
115
+ jsPath = file .path .replace ' _test.js' , ' .js'
116
+ return false if not fs .existsSync jsPath
117
+ relativePath = path .join @depsPrefix , jsPath .replace @dirname , ' '
118
+ namespaces = goog .dependencies_ .pathToNames [relativePath];
119
+ namespace = Object .keys (namespaces)[0 ]
120
+ goog .require namespace if namespace
121
+ true
122
+
123
+ gulp .src changedFilePath ? paths
124
+ .pipe filter autoRequire
125
+ .pipe mocha reporter : ' dot' , ui : ' tdd'
126
+
127
+ diContainer : (baseJsDir , diContainers ) ->
128
+ streams = for container, i in diContainers
129
+ gulp .src ' tmp/deps0.js'
130
+ .pipe diContainer
131
+ baseJsDir : baseJsDir
132
+ fileName : container .name .toLowerCase ().replace (' .' , ' ' ) + ' .js'
133
+ name : container .name
134
+ resolve : container .resolve
135
+ .pipe gulp .dest ' tmp'
136
+ .pipe closureDeps prefix : @depsPrefix , fileName : " deps#{ i+ 1 } .js"
137
+ .pipe gulp .dest ' tmp'
138
+ eventStream .merge streams...
139
+
140
+ concatDeps : ->
141
+ gulp .src ' tmp/deps?.js'
142
+ .pipe concat ' deps.js'
143
+ .pipe gulp .dest ' tmp'
144
+
145
+ concatAll : (object ) ->
146
+ streams = for buildPath, src of object
147
+ src = if @production
148
+ src .production .concat buildPath
149
+ else
150
+ src .development
151
+ gulp .src src
152
+ .pipe concat path .basename buildPath
153
+ .pipe cond @production , closureCompiler
154
+ compilerPath : ' bower_components/closure-compiler/compiler.jar'
155
+ fileName : path .basename buildPath
156
+ compilerFlags : warning_level : ' QUIET'
157
+ .pipe cond @production , size showFiles : true , gzip : true
158
+ .pipe gulp .dest path .dirname buildPath
159
+ eventStream .merge streams...
160
+
161
+ liveReloadNotify : ->
162
+ return if ! @changedFilePath
163
+ @liveReloadServer .changed @changedFilePath
164
+
165
+ liveReloadServer : ->
166
+ @liveReloadServer = livereload ()
167
+ return
168
+
169
+ shouldCreateDeps : ->
170
+ closureDeps .changed @changedFilePath
171
+
172
+ shouldNotify : ->
173
+ ! @production && @changedFilePath
174
+
175
+ setNodeEnv : ->
176
+ process .env [' NODE_ENV' ] = if @production
177
+ ' production'
178
+ else
179
+ ' development'
180
+
181
+ compile : (paths , dest , customOptions ) ->
182
+ options =
183
+ fileName : ' app.js'
184
+ compilerFlags :
185
+ closure_entry_point : ' app.main'
186
+ compilation_level : ' ADVANCED_OPTIMIZATIONS'
187
+ define : [
188
+ " goog.DEBUG=#{ @production == ' debug' } "
189
+ ]
190
+ extra_annotation_name : ' jsx'
191
+ only_closure_dependencies : true
192
+ output_wrapper : ' (function(){%output%})();'
193
+ warning_level : ' VERBOSE'
194
+
195
+ if @production == ' debug'
196
+ # Debug and formatting makes compiled code readable.
197
+ options .compilerFlags .debug = true
198
+ options .compilerFlags .formatting = ' PRETTY_PRINT'
199
+
200
+ _ .merge options, customOptions, (a , b ) ->
201
+ return a .concat b if Array .isArray a
202
+
203
+ gulp .src paths
204
+ .pipe closureCompiler options
205
+ .on ' error' , (err ) -> gutil .log err .message
206
+ .pipe size showFiles : true , gzip : true
207
+ .pipe gulp .dest dest
208
+
209
+ getExterns : (dir ) ->
210
+ fs .readdirSync dir
211
+ .filter (file) -> / \. js$ / .test file
212
+ .filter (file) ->
213
+ # Remove Stdio because it does not compile.
214
+ # TODO(steida): Fork and fix these externs.
215
+ file not in [' stdio.js' ]
216
+ .map (file) -> path .join dir, file
217
+
218
+ watch : (dirs , mapExtensionToTask , gulpStartCallback ) ->
219
+ watch = esteWatch dirs, (e ) =>
220
+ @changedFilePath = path .resolve e .filepath
221
+ task = mapExtensionToTask[e .extension ]
222
+ if task
223
+ gulpStartCallback task
224
+ else
225
+ @changedFilePath = null
226
+ watch .start ()
227
+
228
+ bg : (cmd , args ) ->
229
+ bg cmd, args
230
+
231
+ bump : (paths , yargs , done ) ->
232
+ args = yargs .alias (' m' , ' minor' ).argv
233
+ type = args .major && ' major' || args .minor && ' minor' || ' patch'
234
+
235
+ gulp .src paths
236
+ .pipe bump type : type
237
+ .pipe gulp .dest ' ./'
238
+ .on ' end' , =>
239
+ version = require (path .join @dirname , ' package' ).version
240
+ message = " Bump #{ version} "
241
+ gulp .src paths
242
+ .pipe git .add ()
243
+ .pipe git .commit message
244
+ .on ' end' , ->
245
+ git .push ' origin' , ' master' , {}, ->
246
+ git .tag version, message, {}, ->
247
+ git .push ' origin' , ' master' , args : ' --tags' , done
248
+ return
0 commit comments