UNPKG

8.77 kBJavaScriptView Raw
1/*******************************
2 * Build Task
3 *******************************/
4
5const
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 */
55function 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 */
91function 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
115function 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 if (globs.individuals !== undefined && typeof src === 'string') {
131 const individuals = config.globs.individuals.replace('{','');
132 const components = config.globs.components.replace('}',',').concat(individuals);
133
134 src = config.paths.source.definitions + '/**/' + components + '.less';
135 }
136
137 const buildUncompressed = () => build(src, type, false, config, opts);
138 buildUncompressed.displayName = 'Building uncompressed CSS';
139
140 const buildCompressed = () => build(src, type, true, config, opts);
141 buildCompressed.displayName = 'Building compressed CSS';
142
143 const packUncompressed = () => pack(type, false);
144 packUncompressed.displayName = 'Packing uncompressed CSS';
145
146 const packCompressed = () => pack(type, true);
147 packCompressed.displayName = 'Packing compressed CSS';
148
149 gulp.parallel(
150 gulp.series(
151 buildUncompressed,
152 gulp.parallel(packUncompressed, packCompressed)
153 ),
154 gulp.series(buildCompressed)
155 )(callback);
156}
157
158function rtlAndNormal(src, callback) {
159 if (callback === undefined) {
160 callback = src;
161 src = config.paths.source.definitions + '/**/' + config.globs.components + '.less';
162 }
163
164 const rtl = (callback) => buildCSS(src, 'rtl', config, {}, callback);
165 rtl.displayName = "CSS Right-To-Left";
166 const css = (callback) => buildCSS(src, 'default', config, {}, callback);
167 css.displayName = "CSS";
168
169 if (config.rtl === true || config.rtl === 'Yes') {
170 rtl(callback);
171 } else if (config.rtl === 'both') {
172 gulp.series(rtl, css)(callback);
173 } else {
174 css(callback);
175 }
176}
177
178function docs(src, callback) {
179 if (callback === undefined) {
180 callback = src;
181 src = config.paths.source.definitions + '/**/' + config.globs.components + '.less';
182 }
183
184 const func = (callback) => buildCSS(src, 'docs', config, {}, callback);
185 func.displayName = "CSS Docs";
186
187 func(callback);
188}
189
190// Default tasks
191module.exports = rtlAndNormal;
192
193// We keep the changed files in an array to call build with all of them at the same time
194let timeout, files = [];
195
196/**
197 * Watch changes in CSS files and call the correct build pipe
198 * @param type
199 * @param config
200 */
201module.exports.watch = function (type, config) {
202 const method = type === 'docs' ? docs : rtlAndNormal;
203
204 // Watch theme.config file
205 gulp.watch([
206 normalize(config.paths.source.config),
207 normalize(config.paths.source.site + '/**/site.variables'),
208 normalize(config.paths.source.themes + '/**/site.variables')
209 ])
210 .on('all', function () {
211 // Clear timeout and reset files
212 timeout && clearTimeout(timeout);
213 files = [];
214 return gulp.series(method)();
215 });
216
217 // Watch any less / overrides / variables files
218 gulp.watch([
219 normalize(config.paths.source.definitions + '/**/*.less'),
220 normalize(config.paths.source.site + '/**/*.{overrides,variables}'),
221 normalize(config.paths.source.themes + '/**/*.{overrides,variables}')
222 ])
223 .on('all', function (event, path) {
224 // We don't handle deleted files yet
225 if (event === 'unlink' || event === 'unlinkDir') {
226 return;
227 }
228
229 // Clear timeout
230 timeout && clearTimeout(timeout);
231
232 // Determine which LESS file has to be recompiled
233 let lessPath;
234 if(path.indexOf('site.variables') !== -1) {
235 return;
236 } else if (path.indexOf(config.paths.source.themes) !== -1) {
237 console.log('Change detected in packaged theme');
238 lessPath = replaceExt(path, '.less');
239 lessPath = lessPath.replace(tasks.regExp.theme, config.paths.source.definitions);
240 } else if (path.indexOf(config.paths.source.site) !== -1) {
241 console.log('Change detected in site theme');
242 lessPath = replaceExt(path, '.less');
243 lessPath = lessPath.replace(config.paths.source.site, config.paths.source.definitions);
244 } else {
245 console.log('Change detected in definition');
246 lessPath = path;
247 }
248
249 // Add file to internal changed files array
250 if (!files.includes(lessPath)) {
251 files.push(lessPath);
252 }
253
254 // Update timeout
255 timeout = setTimeout(() => {
256 // Copy files to build in another array
257 const buildFiles = [...files];
258 // Call method
259 gulp.series((callback) => method(buildFiles, callback))();
260 // Reset internal changed files array
261 files = [];
262 }, 1000);
263 });
264};
265
266// Expose build css method
267module.exports.buildCSS = buildCSS;
\No newline at end of file