UNPKG

6.59 kBJavaScriptView Raw
1//-------------------------------------
2//-- Styles
3//-------------------------------------
4'use strict';
5
6// const debug = require('gulp-debug');
7const Fiber = require('fibers');
8const gulp = require('gulp');
9const autoprefixer = require('gulp-autoprefixer');
10const cache = require('gulp-cached');
11const cssnano = require('gulp-cssnano');
12const gulpif = require('gulp-if');
13const imagemin = require('gulp-imagemin');
14const insert = require('gulp-insert');
15const jsonsass = require('gulp-json-sass');
16const rename = require('gulp-rename');
17const gulpsass = require('gulp-sass');
18const sourcemaps = require('gulp-sourcemaps');
19const stylelint = require('gulp-stylelint');
20const cloneDeep = require('lodash.clonedeep');
21const pluralize = require('pluralize');
22const sass = require('sass');
23const jsonToScss = require('@absolunet/json-to-scss');
24const env = require('~/helpers/env');
25const flow = require('~/helpers/flow');
26const paths = require('~/helpers/paths');
27const toolbox = require('~/helpers/toolbox');
28const util = require('~/helpers/util');
29
30
31module.exports = () => {
32
33 //-- Inline images optimization
34 flow.createTask('styles-images', () => {
35 return gulp.src(paths.files.inline, { base: paths.directory.root })
36 .pipe(toolbox.plumber())
37 .pipe(imagemin())
38 .pipe(rename(util.assetsRename()))
39 .pipe(gulp.dest(paths.directory.cache))
40 ;
41 });
42
43
44 //-- Lint SCSS
45 flow.createTask('styles-lint', ({ taskName }) => {
46
47 let hasErrors = false;
48
49 return gulp.src(paths.files.stylesLint)
50 // .pipe(toolbox.plumber()) // skip cuz of watch
51
52 .pipe(cache('styles', { optimizeMemory: true }))
53
54 .pipe(stylelint({
55 configFile: paths.config.stylelint,
56 syntax: 'scss',
57 failAfterError: true,
58 reporters: [
59 {
60 formatter: (results) => {
61 hasErrors = false;
62
63 results.forEach((item) => {
64 if (item.warnings.length !== 0 || item.deprecations.length !== 0 || item.invalidOptionWarnings.length !== 0) {
65 delete cache.caches.styles[item.source];
66
67 if (!hasErrors) {
68 item.warnings.forEach((flag) => {
69 if (flag.severity === 'error') {
70 hasErrors = true;
71 }
72 });
73 }
74 }
75 });
76
77 if (!hasErrors) {
78 toolbox.log(taskName, `${pluralize('file', results.length, true)} linted`);
79 }
80 }
81 },
82 {
83 formatter: 'string',
84 console: true
85 },
86 {
87 formatter: () => {
88 flow.showDelayedLog(hasErrors);
89 }
90 }
91 ]
92 }))
93 ;
94 });
95
96
97 //-- Convert constants to SCSS
98 flow.createTask('styles-constants', ({ taskName }) => {
99 const streams = [];
100
101 for (const name of Object.keys(env.bundles)) {
102 const data = util.parseKonstan('styles', name, env.bundles[name].output);
103 data.bundle = `'${name}'`;
104
105 const konstanJson = JSON.stringify({ konstan: data });
106
107 /* eslint-disable function-paren-newline */
108 streams.push(
109 toolbox.vinylStream(paths.filename.konstanStyles, konstanJson)
110 .pipe(toolbox.plumber())
111 .pipe(jsonsass())
112 .pipe(insert.prepend(`${jsonToScss.convert(konstanJson)}\n\n`))
113 .pipe(gulp.dest(`${paths.directory.cacheStyles}/${name}`))
114 );
115 /* eslint-enable function-paren-newline */
116 }
117
118 return toolbox.mergeStreams(streams).on('finish', () => {
119 flow.skipOnWatch(taskName);
120 toolbox.log(taskName, `${pluralize('file', streams.length, true)} generated`);
121 });
122 });
123
124
125 //-- Compile
126 gulpsass.compiler = sass;
127
128 flow.createTask('styles-compile', ({ taskName }) => {
129 const sassFunctions = require(paths.config.sassFunctions); // eslint-disable-line global-require
130
131 const streams = [];
132
133 for (const name of Object.keys(env.bundles)) {
134 const bundle = env.bundles[name];
135
136 // For each collection
137 for (const collection of Object.keys(bundle.styles.collections)) {
138 const list = cloneDeep(bundle.styles.collections[collection]);
139
140 // Add konstan
141 list.unshift(`${paths.directory.cacheStyles}/${name}/${paths.filename.konstan}`);
142
143 // Require each file
144 list.forEach((file, i) => {
145 list[i] = `@import '${file}';`;
146 });
147
148 const toMinify = (bundle.styles.options.minify && !env.watching) || env.production;
149 const toSourcemaps = bundle.styles.options.sourcemaps && !env.production;
150 const filename = `${collection}.${paths.extension.build}`;
151 const filenameBuild = `${collection}.${paths.extension.stylesBuild}`;
152 const destination = `${bundle.output.build}/${paths.build.styles}`;
153 const source = `${util.getGeneratedBanner(name)}${list.join('\n')}\n`;
154
155 /* eslint-disable function-paren-newline */
156 streams.push(
157 toolbox.vinylStream(filename, source)
158 .pipe(toolbox.plumber())
159
160 .pipe(gulpif(toSourcemaps, sourcemaps.init()))
161
162 .pipe(
163 gulpsass({
164 fiber: Fiber,
165 includePaths: [paths.directory.root],
166 functions: sassFunctions
167 // sourcemaps (bundle.styles.options.sourcemaps)
168 })
169 .on('error', gulpsass.logError)
170 )
171
172 .pipe(autoprefixer({ overrideBrowserslist: bundle.styles.options.autoprefixer }))
173
174 .pipe(gulpif(toMinify, cssnano({ autoprefixer: false, discardUnused: false, mergeIdents: false, reduceIdents: false, zindex: false })))
175
176 .pipe(gulpif(toSourcemaps, sourcemaps.write('maps', {
177 includeContent: false,
178 sourceRoot: 'source'
179 })))
180
181 .pipe(gulp.dest(`${paths.directory.root}/${destination}`))
182
183 .on('finish', () => {
184 toolbox.log(taskName, `'${destination}/${filenameBuild}' written`, toolbox.filesize(`${paths.directory.root}/${destination}/${filenameBuild}`));
185 })
186 );
187 /* eslint-enable function-paren-newline */
188 }
189 }
190
191 return toolbox.mergeStreams(streams);
192
193 }, gulp.parallel('styles-lint', 'styles-constants'));
194
195
196
197
198
199
200 //-- Rebuild
201 flow.createSequence('styles', gulp.series('styles-images', 'styles-compile'), {
202 cleanPaths: [paths.directory.cacheInline],
203 cleanBundle: ({ name, bundle }) => {
204 const buildPath = `${paths.directory.root}/${bundle.output.build}/${paths.build.styles}`;
205 const cachePath = `${paths.directory.cacheStyles}/${name}`;
206
207 if (env.isScopeSubbundle) {
208 return Object.keys(bundle.styles.collections).map((collection) => {
209 return [
210 `${buildPath}/${collection}.${paths.extension.stylesBuild}`,
211 `${cachePath}/${collection}.${paths.extension.stylesBuild}`
212 ];
213 }).flat();
214 }
215
216 return [buildPath, cachePath];
217 }
218 });
219
220};