1
+ /*******************************
2
+ * Build Task
3
+ *******************************/
4
+
5
+ const
6
+ gulp = require ( 'gulp' ) ,
7
+
8
+ // node dependencies
9
+ console = require ( 'better-console' ) ,
10
+
11
+ // gulp dependencies
12
+ autoprefixer = require ( 'gulp-autoprefixer' ) ,
13
+ chmod = require ( 'gulp-chmod' ) ,
14
+ concatCSS = require ( 'gulp-concat-css' ) ,
15
+ dedupe = require ( 'gulp-dedupe' ) ,
16
+ flatten = require ( 'gulp-flatten' ) ,
17
+ gulpif = require ( 'gulp-if' ) ,
18
+ header = require ( 'gulp-header' ) ,
19
+ less = require ( 'gulp-less' ) ,
20
+ minifyCSS = require ( 'gulp-clean-css' ) ,
21
+ normalize = require ( 'normalize-path' ) ,
22
+ plumber = require ( 'gulp-plumber' ) ,
23
+ print = require ( 'gulp-print' ) . default ,
24
+ rename = require ( 'gulp-rename' ) ,
25
+ replace = require ( 'gulp-replace' ) ,
26
+ replaceExt = require ( 'replace-ext' ) ,
27
+ rtlcss = require ( 'gulp-rtlcss' ) ,
28
+
29
+ // config
30
+ config = require ( './../config/user' ) ,
31
+ docsConfig = require ( './../config/docs' ) ,
32
+ tasks = require ( '../config/tasks' ) ,
33
+ install = require ( '../config/project/install' ) ,
34
+
35
+ // shorthand
36
+ globs = config . globs ,
37
+ assets = config . paths . assets ,
38
+
39
+ banner = tasks . banner ,
40
+ filenames = tasks . filenames ,
41
+ comments = tasks . regExp . comments ,
42
+ log = tasks . log ,
43
+ settings = tasks . settings
44
+ ;
45
+
46
+ /**
47
+ * Builds the css
48
+ * @param src
49
+ * @param type
50
+ * @param compress
51
+ * @param config
52
+ * @param opts
53
+ * @return {* }
54
+ */
55
+ function build ( src , type , compress , config , opts ) {
56
+ let fileExtension ;
57
+ if ( type === 'rtl' && compress ) {
58
+ fileExtension = settings . rename . rtlMinCSS ;
59
+ } else if ( type === 'rtl' ) {
60
+ fileExtension = settings . rename . rtlCSS ;
61
+ } else if ( compress ) {
62
+ fileExtension = settings . rename . minCSS ;
63
+ }
64
+
65
+ return gulp . src ( src , opts )
66
+ . pipe ( plumber ( settings . plumber . less ) )
67
+ . pipe ( less ( settings . less ) )
68
+ . pipe ( autoprefixer ( settings . prefix ) )
69
+ . pipe ( gulpif ( type === 'rtl' , rtlcss ( ) ) )
70
+ . pipe ( replace ( comments . variables . in , comments . variables . out ) )
71
+ . pipe ( replace ( comments . license . in , comments . license . out ) )
72
+ . pipe ( replace ( comments . large . in , comments . large . out ) )
73
+ . pipe ( replace ( comments . small . in , comments . small . out ) )
74
+ . pipe ( replace ( comments . tiny . in , comments . tiny . out ) )
75
+ . pipe ( flatten ( ) )
76
+ . pipe ( replace ( config . paths . assets . source ,
77
+ compress ? config . paths . assets . compressed : config . paths . assets . uncompressed ) )
78
+ . pipe ( gulpif ( compress , minifyCSS ( settings . minify ) ) )
79
+ . pipe ( gulpif ( fileExtension , rename ( fileExtension ) ) )
80
+ . pipe ( gulpif ( config . hasPermissions , chmod ( config . parsedPermissions ) ) )
81
+ . pipe ( gulp . dest ( compress ? config . paths . output . compressed : config . paths . output . uncompressed ) )
82
+ . pipe ( print ( log . created ) )
83
+ ;
84
+ }
85
+
86
+ /**
87
+ * Packages the css files in dist
88
+ * @param {string } type - type of the css processing (none, rtl, docs)
89
+ * @param {boolean } compress - should the output be compressed
90
+ */
91
+ function pack ( type , compress ) {
92
+ const output = type === 'docs' ? docsConfig . paths . output : config . paths . output ;
93
+ const ignoredGlobs = type === 'rtl' ? globs . ignoredRTL + '.rtl.css' : globs . ignored + '.css' ;
94
+
95
+ let concatenatedCSS ;
96
+ if ( type === 'rtl' ) {
97
+ concatenatedCSS = compress ? filenames . concatenatedMinifiedRTLCSS : filenames . concatenatedRTLCSS ;
98
+ } else {
99
+ concatenatedCSS = compress ? filenames . concatenatedMinifiedCSS : filenames . concatenatedCSS ;
100
+ }
101
+
102
+ return gulp . src ( output . uncompressed + '/**/' + globs . components + ignoredGlobs )
103
+ . pipe ( plumber ( ) )
104
+ . pipe ( dedupe ( ) )
105
+ . pipe ( replace ( assets . uncompressed , assets . packaged ) )
106
+ . pipe ( concatCSS ( concatenatedCSS , settings . concatCSS ) )
107
+ . pipe ( gulpif ( config . hasPermissions , chmod ( config . parsedPermissions ) ) )
108
+ . pipe ( gulpif ( compress , minifyCSS ( settings . concatMinify ) ) )
109
+ . pipe ( header ( banner , settings . header ) )
110
+ . pipe ( gulp . dest ( output . packaged ) )
111
+ . pipe ( print ( log . created ) )
112
+ ;
113
+ }
114
+
115
+ function buildCSS ( src , type , config , opts , callback ) {
116
+ if ( ! install . isSetup ( ) ) {
117
+ console . error ( 'Cannot build CSS files. Run "gulp install" to set-up Semantic' ) ;
118
+ callback ( ) ;
119
+ return ;
120
+ }
121
+
122
+ if ( callback === undefined ) {
123
+ callback = opts ;
124
+ opts = config ;
125
+ config = type ;
126
+ type = src ;
127
+ src = config . paths . source . definitions + '/**/' + config . globs . components + '.less' ;
128
+ }
129
+
130
+ const buildUncompressed = ( ) => build ( src , type , false , config , opts ) ;
131
+ buildUncompressed . displayName = 'Building uncompressed CSS' ;
132
+
133
+ const buildCompressed = ( ) => build ( src , type , true , config , opts ) ;
134
+ buildCompressed . displayName = 'Building compressed CSS' ;
135
+
136
+ const packUncompressed = ( ) => pack ( type , false ) ;
137
+ packUncompressed . displayName = 'Packing uncompressed CSS' ;
138
+
139
+ const packCompressed = ( ) => pack ( type , true ) ;
140
+ packCompressed . displayName = 'Packing compressed CSS' ;
141
+
142
+ gulp . parallel (
143
+ gulp . series (
144
+ buildUncompressed ,
145
+ gulp . parallel ( packUncompressed , packCompressed )
146
+ ) ,
147
+ gulp . series ( buildCompressed )
148
+ ) ( callback ) ;
149
+ }
150
+
151
+ function rtlAndNormal ( src , callback ) {
152
+ if ( callback === undefined ) {
153
+ callback = src ;
154
+ src = config . paths . source . definitions + '/**/' + config . globs . components + '.less' ;
155
+ }
156
+
157
+ const rtl = ( callback ) => buildCSS ( src , 'rtl' , config , { } , callback ) ;
158
+ rtl . displayName = "CSS Right-To-Left" ;
159
+ const css = ( callback ) => buildCSS ( src , 'default' , config , { } , callback ) ;
160
+ css . displayName = "CSS" ;
161
+
162
+ if ( config . rtl === true || config . rtl === 'Yes' ) {
163
+ rtl ( callback ) ;
164
+ } else if ( config . rtl === 'both' ) {
165
+ gulp . series ( rtl , css ) ( callback ) ;
166
+ } else {
167
+ css ( callback ) ;
168
+ }
169
+ }
170
+
171
+ function docs ( src , callback ) {
172
+ if ( callback === undefined ) {
173
+ callback = src ;
174
+ src = config . paths . source . definitions + '/**/' + config . globs . components + '.less' ;
175
+ }
176
+
177
+ const func = ( callback ) => buildCSS ( src , 'docs' , config , { } , callback ) ;
178
+ func . displayName = "CSS Docs" ;
179
+
180
+ func ( callback ) ;
181
+ }
182
+
183
+ // Default tasks
184
+ module . exports = rtlAndNormal ;
185
+
186
+ // We keep the changed files in an array to call build with all of them at the same time
187
+ let timeout , files = [ ] ;
188
+
189
+ /**
190
+ * Watch changes in CSS files and call the correct build pipe
191
+ * @param type
192
+ * @param config
193
+ */
194
+ module . exports . watch = function ( type , config ) {
195
+ const method = type === 'docs' ? docs : rtlAndNormal ;
196
+
197
+ // Watch theme.config file
198
+ gulp . watch ( [
199
+ normalize ( config . paths . source . config ) ,
200
+ normalize ( config . paths . source . site + '/**/site.variables' ) ,
201
+ normalize ( config . paths . source . themes + '/**/site.variables' )
202
+ ] )
203
+ . on ( 'all' , function ( ) {
204
+ // Clear timeout and reset files
205
+ timeout && clearTimeout ( timeout ) ;
206
+ files = [ ] ;
207
+ return gulp . series ( method ) ( ) ;
208
+ } ) ;
209
+
210
+ // Watch any less / overrides / variables files
211
+ gulp . watch ( [
212
+ normalize ( config . paths . source . definitions + '/**/*.less' ) ,
213
+ normalize ( config . paths . source . site + '/**/*.{overrides,variables}' ) ,
214
+ normalize ( config . paths . source . themes + '/**/*.{overrides,variables}' )
215
+ ] )
216
+ . on ( 'all' , function ( event , path ) {
217
+ // We don't handle deleted files yet
218
+ if ( event === 'unlink' || event === 'unlinkDir' ) {
219
+ return ;
220
+ }
221
+
222
+ // Clear timeout
223
+ timeout && clearTimeout ( timeout ) ;
224
+
225
+ // Determine which LESS file has to be recompiled
226
+ let lessPath ;
227
+ if ( path . indexOf ( 'site.variables' ) !== - 1 ) {
228
+ return ;
229
+ } else if ( path . indexOf ( config . paths . source . themes ) !== - 1 ) {
230
+ console . log ( 'Change detected in packaged theme' ) ;
231
+ lessPath = replaceExt ( path , '.less' ) ;
232
+ lessPath = lessPath . replace ( tasks . regExp . theme , config . paths . source . definitions ) ;
233
+ } else if ( path . indexOf ( config . paths . source . site ) !== - 1 ) {
234
+ console . log ( 'Change detected in site theme' ) ;
235
+ lessPath = replaceExt ( path , '.less' ) ;
236
+ lessPath = lessPath . replace ( config . paths . source . site , config . paths . source . definitions ) ;
237
+ } else {
238
+ console . log ( 'Change detected in definition' ) ;
239
+ lessPath = path ;
240
+ }
241
+
242
+ // Add file to internal changed files array
243
+ if ( ! files . includes ( lessPath ) ) {
244
+ files . push ( lessPath ) ;
245
+ }
246
+
247
+ // Update timeout
248
+ timeout = setTimeout ( ( ) => {
249
+ // Copy files to build in another array
250
+ const buildFiles = [ ...files ] ;
251
+ // Call method
252
+ gulp . series ( ( callback ) => method ( buildFiles , callback ) ) ( ) ;
253
+ // Reset internal changed files array
254
+ files = [ ] ;
255
+ } , 1000 ) ;
256
+ } ) ;
257
+ } ;
258
+
259
+ // Expose build css method
260
+ module . exports . buildCSS = buildCSS ;
0 commit comments