forked from rthaut/deviantART-Filter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgulpfile.js
294 lines (247 loc) · 9.85 KB
/
gulpfile.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/* global require */
const gulp = require('gulp');
const pkg = require('./package.json');
const cfg = require('./gulp.config.json');
// additional native gulp packages
const del = require('del');
const fs = require('fs');
const path = require('path');
const merge = require('merge-stream');
// load all plugins from package development dependencies
const $ = require('gulp-load-plugins')({
'scope': ['devDependencies'],
'pattern': ['*'],
'rename': {
'gulp-angular-embed-templates': 'embedTemplates',
'gulp-if': 'gulpIf',
'rollup-stream': 'rollup',
'vinyl-buffer': 'buffer',
'vinyl-source-stream': 'source',
},
'postRequireTransforms': {
'uglify': uglify => require('gulp-uglify/composer')(require('uglify-es'), console)
}
});
// TODO: the minify process should attempt to concatenate all of the linked components for the pages (ala useref?)
// TODO: all functions should be named to avoid <anonymous> in output - the build functions (after linting) are the problematic ones
/* ==================== HELPER FUNCTIONS ==================== */
/**
* Get the names of all immediate folders within the supplied directory
* @param {string} dir the path to the directory
* @returns {string[]} the names of immediate folders within the directory
*/
function folders(dir) {
return fs.readdirSync(dir).filter(file => fs.statSync(path.join(dir, file)).isDirectory());
}
/**
* Lints all JavaScript files within the supplied directory
* @param {string} dir the path to the directory
* @param {Boolean} [fix=true] indicates if eslint should attempt to fix errors
* @param {Boolean} [failOnError=true] indicates if eslint should fail if there are any unfixed errors
*/
function lint(dir, fix = true, failOnError = true) {
return $.pump([
gulp.src(`${dir}/**/*.js`),
$.eslint({
'fix': fix
}),
$.eslint.format(),
$.gulpIf(failOnError, $.eslint.failOnError()),
]);
}
/* ==================== BUILD TASKS ==================== */
gulp.task('clean', () => {
return del(['./dist/*'])
.catch((error) => {
console.error(error);
});
});
gulp.task('minify', () => {
return $.pump([
gulp.src(['./dist/**/*.{css,js}', '!./dist/*/vendor/**/*', '!./dist/**/*.min.*', ]),
$.gulpIf(['**/*.css'], $.postcss()), // options are loaded from postcss.config.js automatically
$.gulpIf(['**/*.js'], $.uglify(cfg.plugin_options.uglify)),
// TODO: the filenames SHOULD include .min, but we would need to update the paths in both the HTML files and the manifests
//$.rename({ 'suffix': '.min' }),
$.header(fs.readFileSync('./src/banner.txt', 'utf8'), {
'pkg': pkg
}),
gulp.dest('./dist'),
]);
});
// ==========================================
// build & lint tasks, broken into components
// ==========================================
gulp.task('lint:components', () => {
return lint(cfg.source_folders.components, true, false);
});
gulp.task('build:components', gulp.series('lint:components', () => {
return merge(folders(cfg.source_folders.components).map((folder) => {
return $.pump([
gulp.src([`${cfg.source_folders.components}/${folder}/**/*.js`]),
$.embedTemplates(),
$.concat(folder + '.js'),
...Object.keys(cfg.supported_browsers).map(browser => gulp.dest(`./dist/${browser}/components`)),
]);
}));
}));
gulp.task('lint:helpers', () => {
return lint(cfg.source_folders.helpers, true, false);
});
gulp.task('build:images', () => {
return $.pump([
gulp.src(['./images/**/*.{png,svg}']),
...Object.keys(cfg.supported_browsers).map(browser => gulp.dest(`./dist/${browser}/images`)),
]);
});
/**
* Creates multiple resized PNG versions of the SVG logo files
*/
gulp.task('build:logos', () => {
//TODO: handle the icons/sizes defined in page_action.default_icon for Edge
const manifest = JSON.parse(fs.readFileSync(`${cfg.source_folders.manifests}/manifest.shared.json`));
const icons = manifest.icons;
return merge(Object.keys(icons).map((size) => {
const file = path.basename(icons[size], '.png').replace(/\-\d+/, '');
return $.pump([
gulp.src([`./images/logo/${file}.svg`]),
$.svg2png({
'width': size,
'height': size
}),
$.rename(icons[size]), // the name includes the relative path structure (from the manifest to the icon)
...Object.keys(cfg.supported_browsers).map(browser => gulp.dest(`./dist/${browser}`)),
]);
}));
});
gulp.task('build:less', () => {
return merge(Object.keys(cfg.supported_browsers).map((browser) => {
return $.pump([
gulp.src([`${cfg.source_folders.less}/*.less`]),
$.less(cfg.plugin_options.less),
$.replace(/browser-extension\:\/\//gm, cfg.supported_browsers[browser].protocol),
gulp.dest(`./dist/${browser}/css`),
]);
}));
});
gulp.task('build:locales', () => {
return merge(folders(cfg.source_folders.locales).map((folder) => {
return $.pump([
gulp.src([`${cfg.source_folders.locales}/${folder}/**/*.json`]),
$.mergeJson({ 'fileName': 'messages.json' }),
...Object.keys(cfg.supported_browsers).map(browser => gulp.dest(`./dist/${browser}/_locales/${folder}`)),
]);
}));
});
gulp.task('build:manifest', () => {
return merge(Object.keys(cfg.supported_browsers).map((browser) => {
return $.pump([
gulp.src([
`${cfg.source_folders.manifests}/manifest.shared.json`,
`${cfg.source_folders.manifests}/manifest.${browser}.json`,
]),
$.mergeJson({ 'fileName': 'manifest.json' }),
$.ejs({ 'pkg': pkg }),
gulp.dest(`./dist/${browser}`),
]);
}));
});
gulp.task('lint:pages', () => {
return lint(cfg.source_folders.pages, true, false);
});
gulp.task('build:pages', gulp.series('lint:pages', () => {
return merge(folders(cfg.source_folders.pages).map((folder) => {
return $.pump([
// TODO: invoking useref prevents this entire task from properly ending, so any dependent tasks do not complete properly (like the 'watch' task, which just stops completely...)
//gulp.src([`${_folders.pages}/${folder}/**/*.html`]),
//$.useref(),
// TODO: if/whe useref works, this line must be removed (useref passes the HTML files and all assets through the stream)
gulp.src([`${cfg.source_folders.pages}/${folder}/**/*.*`]),
// TODO: maybe use gulp-html-replace to only inject the browser polyfill for Chrome (or remove it for Firefox)? then the manifest for Firefox can probably omit the polyfill script completely
...Object.keys(cfg.supported_browsers).map(browser => gulp.dest(`./dist/${browser}/pages/${folder}`)),
]);
}));
}));
gulp.task('lint:scripts', gulp.series('lint:helpers', () => {
return lint(cfg.source_folders.scripts, true, false);
}));
gulp.task('build:scripts', gulp.series('lint:scripts', () => {
const tokens = $.ini.parse(fs.readFileSync('.config.ini', 'utf-8'));
return merge(folders(cfg.source_folders.scripts).map((folder) => {
return $.pump([
$.rollup({
'input': `${cfg.source_folders.scripts}/${folder}/index.js`,
'format': 'iife',
'name': pkg.title.replace(/\s/g, ''),
'external': [
'idb'
],
'globals': {
'idb': 'idb'
}
}),
$.source(folder + '.js'),
$.buffer(),
$.tokenReplace({
'global': tokens,
'preserveUnknownTokens': true
}),
...Object.keys(cfg.supported_browsers).map(browser => gulp.dest(`./dist/${browser}/scripts`)),
]);
}));
}));
gulp.task('build:vendor', () => {
return $.pump([
gulp.src(cfg.vendor_files),
...Object.keys(cfg.supported_browsers).map(browser => gulp.dest(`./dist/${browser}/vendor`)),
]);
});
// ========================
// package/distribute tasks
// ========================
gulp.task('zip', () => {
return merge(Object.keys(cfg.supported_browsers).map((browser) => {
return $.pump([
gulp.src([`./dist/${browser}/**/*`, '!Thumbs.db']),
$.zip(`${pkg.name}-${browser}.zip`),
gulp.dest('./dist'),
]);
}));
});
// =========================
// primary development tasks
// =========================
gulp.task('lint', gulp.parallel(
'lint:components',
'lint:helpers',
'lint:pages',
'lint:scripts'
));
gulp.task('build', gulp.parallel(
'build:images',
'build:logos',
'build:less',
'build:locales',
'build:manifest',
'build:components',
'build:pages',
'build:scripts',
'build:vendor'
));
gulp.task('watch', (callback) => {
// TODO: it would be nice to only rebuild the modified files per watch, but that requires a way to pass them to the build task
gulp.watch(`${cfg.source_folders.locales}/**/*`, gulp.task('build:locales'));
gulp.watch(`${cfg.source_folders.manifests}/**/*`, gulp.task('build:manifest'));
gulp.watch(`${cfg.source_folders.components}/**/*`, gulp.task('build:components'));
gulp.watch(`${cfg.source_folders.less}/**/*`, gulp.task('build:less'));
gulp.watch(`${cfg.source_folders.pages}/**/*`, gulp.task('build:pages'));
gulp.watch([
`${cfg.source_folders.helpers}/**/*.js`,
`${ cfg.source_folders.scripts }/**/*.js`,
], gulp.task('build:scripts'));
callback();
});
gulp.task('debug', gulp.series('build', 'watch'));
gulp.task('package', gulp.series('clean', 'build', 'minify', 'zip'));
// default task (alias debug)
gulp.task('default', gulp.task('debug'));