frontend-tasks
Version:
Frontend Tasks is a wrapper around gulp for most of the normal use cases for simple and modern frontend development
2,078 lines • 57.5 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var browserSyncModule = require('browser-sync');
var del = require('del');
var gulp = require('gulp');
var flatten = require('gulp-flatten');
var merge = require('merge-stream');
var plumber = require('gulp-plumber');
var postcss = require('gulp-postcss');
var sourcemaps = require('gulp-sourcemaps');
var notify = require('gulp-notify');
var gulpIf = require('gulp-if');
var path$1 = require('path');
var through = require('through2');
var fs = require('fs');
var crypto = require('crypto');
var glob = require('glob-all');
var environments = require('gulp-environments');
var rollup = require('rollup');
var resolve = require('rollup-plugin-node-resolve');
var babel = require('rollup-plugin-babel');
var rollupPluginTerser = require('rollup-plugin-terser');
var cleanup = require('rollup-plugin-cleanup');
var postcss$1 = require('rollup-plugin-postcss');
var commonjs = require('rollup-plugin-commonjs');
var util = require('util');
var zlib = require('zlib');
var stylelint = require('stylelint');
var eslint = require('gulp-eslint');
var childProcess = require('child_process');
var log = require('fancy-log');
var svgSprite = require('gulp-svg-sprite');
const browserSyncInstance = browserSyncModule.create();
const browserSync = (options) => {
return () => {
browserSyncInstance.init({
ui: { port: parseInt(process.env.BROWSER_SYNC_UI_PORT, 10) || 3000 },
host: process.env.BROWSER_SYNC_HOST || 'localhost',
port: parseInt(process.env.BROWSER_SYNC_PORT, 10) || 3002,
proxy: process.env.BROWSER_SYNC_PROXY || 'http://localhost:3001/',
open: false,
...options,
});
};
};
const clean = (options) => {
return () => {
return del(options.directories);
};
};
clean.description = `cleans the given directories`;
const copyTask = (src, dest) => {
return gulp.src(src).pipe(flatten()).pipe(gulp.dest(dest));
};
const copy = (options) => {
return () => {
const streams = [];
options.paths.forEach((path) => {
streams.push(copyTask(path.src, path.dest));
});
return merge(streams);
};
};
copy.description = `copies files from src to dest`;
const defaultOptions = {
name: 'hash-manifest.json',
replace: false,
versionPattern: '[name]?version=[hash]',
formatter: (name) => name,
};
function md5(string) {
return crypto.createHash('md5').update(string).digest('hex');
}
function tryRequire(file) {
try {
return JSON.parse(fs.readFileSync(file, 'utf-8'));
} catch (err) {
if (err.code === 'ENOENT') return null;
throw err;
}
}
function mkdirPath(dest) {
const dir = path$1.dirname(dest);
try {
fs.readdirSync(dir);
} catch (err) {
mkdirPath(dir);
fs.mkdirSync(dir);
}
}
function generateVersionString(versionPattern, name, hash) {
return versionPattern.replace('[name]', name).replace('[hash]', hash);
}
function addToManifest(keyFilePath, valueFilePath, code, options) {
const manifest = tryRequire(options.name) || {};
manifest[`${keyFilePath}`] = generateVersionString(options.versionPattern, valueFilePath, md5(code));
mkdirPath(options.name);
fs.writeFileSync(options.name, JSON.stringify(manifest, null, 4), 'utf8');
}
function hash (options = {}) {
options = { ...defaultOptions, ...options };
return through.obj((chunk, enc, cb) => {
const chunkPath = chunk.path.replace(chunk.cwd + path$1.sep, '');
if (!chunkPath.includes('.map')) {
const fileName = options.formatter(chunkPath.split(path$1.sep).join('/'));
const code = chunk.contents;
addToManifest(fileName, fileName, code, options);
}
cb(null, chunk);
});
}
let config = {
projectTitle: 'frontend-tasks',
showNotifications: true,
versionManifest: false,
};
const css = (options = {}) => {
return () => {
return gulp
.src(options.src)
.pipe(
plumber({
errorHandler: function (error) {
if (config.showNotifications) {
notify.onError({
title: config.projectTitle + ' - CSS Error',
message: error.toString(),
})(error);
}
this.emit('end');
},
}),
)
.pipe(sourcemaps.init())
.pipe(postcss())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(options.dest))
.pipe(gulpIf(config.versionManifest !== false, hash(config.versionManifest)));
};
};
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function unwrapExports (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var estreeWalker_umd = createCommonjsModule(function (module, exports) {
(function (global, factory) {
factory(exports) ;
}(commonjsGlobal, function (exports) {
function walk ( ast, ref) {
var enter = ref.enter;
var leave = ref.leave;
visit( ast, null, enter, leave );
}
var context = {
skip: function () { return context.shouldSkip = true; },
shouldSkip: false
};
var childKeys = {};
var toString = Object.prototype.toString;
function isArray ( thing ) {
return toString.call( thing ) === '[object Array]';
}
function visit ( node, parent, enter, leave, prop, index ) {
if ( !node ) return;
if ( enter ) {
context.shouldSkip = false;
enter.call( context, node, parent, prop, index );
if ( context.shouldSkip ) return;
}
var keys = childKeys[ node.type ] || (
childKeys[ node.type ] = Object.keys( node ).filter( function ( key ) { return typeof node[ key ] === 'object'; } )
);
var key, value, i, j;
i = keys.length;
while ( i-- ) {
key = keys[i];
value = node[ key ];
if ( isArray( value ) ) {
j = value.length;
while ( j-- ) {
visit( value[j], node, enter, leave, key, j );
}
}
else if ( value && value.type ) {
visit( value, node, enter, leave, key, null );
}
}
if ( leave ) {
leave( node, parent, prop, index );
}
}
exports.walk = walk;
}));
});
var concatMap = function (xs, fn) {
var res = [];
for (var i = 0; i < xs.length; i++) {
var x = fn(xs[i], i);
if (isArray(x)) res.push.apply(res, x);
else res.push(x);
}
return res;
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
var balancedMatch = balanced;
function balanced(a, b, str) {
if (a instanceof RegExp) a = maybeMatch(a, str);
if (b instanceof RegExp) b = maybeMatch(b, str);
var r = range(a, b, str);
return r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + a.length, r[1]),
post: str.slice(r[1] + b.length)
};
}
function maybeMatch(reg, str) {
var m = str.match(reg);
return m ? m[0] : null;
}
balanced.range = range;
function range(a, b, str) {
var begs, beg, left, right, result;
var ai = str.indexOf(a);
var bi = str.indexOf(b, ai + 1);
var i = ai;
if (ai >= 0 && bi > 0) {
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i == ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
} else if (begs.length == 1) {
result = [ begs.pop(), bi ];
} else {
beg = begs.pop();
if (beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length) {
result = [ left, right ];
}
}
return result;
}
var braceExpansion = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balancedMatch('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str) {
if (!str)
return [];
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.substr(0, 2) === '{}') {
str = '\\{\\}' + str.substr(2);
}
return expand(escapeBraces(str), true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, isTop) {
var expansions = [];
var m = balancedMatch('{', '}', str);
if (!m || /\$$/.test(m.pre)) return [str];
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,.*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand(str);
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], false).map(embrace);
if (n.length === 1) {
var post = m.post.length
? expand(m.post, false)
: [''];
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, false)
: [''];
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length);
var incr = n.length == 3
? Math.abs(numeric(n[2]))
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y); i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = concatMap(n, function(el) { return expand(el, false) });
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
return expansions;
}
var minimatch_1 = minimatch;
minimatch.Minimatch = Minimatch;
var path = { sep: '/' };
try {
path = path$1;
} catch (er) {}
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
var plTypes = {
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
'?': { open: '(?:', close: ')?' },
'+': { open: '(?:', close: ')+' },
'*': { open: '(?:', close: ')*' },
'@': { open: '(?:', close: ')' }
};
// any single thing other than /
// don't need to escape / when using new RegExp()
var qmark = '[^/]';
// * => any number of characters
var star = qmark + '*?';
// ** when dots are allowed. Anything goes, except .. and .
// not (^ or / followed by one or two dots followed by $ or /),
// followed by anything, any number of times.
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?';
// not a ^ or / followed by a dot,
// followed by anything, any number of times.
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?';
// characters that need to be escaped in RegExp.
var reSpecials = charSet('().*{}+?[]^$\\!');
// "abc" -> { a:true, b:true, c:true }
function charSet (s) {
return s.split('').reduce(function (set, c) {
set[c] = true;
return set
}, {})
}
// normalizes slashes.
var slashSplit = /\/+/;
minimatch.filter = filter;
function filter (pattern, options) {
options = options || {};
return function (p, i, list) {
return minimatch(p, pattern, options)
}
}
function ext (a, b) {
a = a || {};
b = b || {};
var t = {};
Object.keys(b).forEach(function (k) {
t[k] = b[k];
});
Object.keys(a).forEach(function (k) {
t[k] = a[k];
});
return t
}
minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch
var orig = minimatch;
var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options))
};
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
};
return m
};
Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch
};
function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {};
// shortcut: comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
return false
}
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p)
}
function Minimatch (pattern, options) {
if (!(this instanceof Minimatch)) {
return new Minimatch(pattern, options)
}
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {};
pattern = pattern.trim();
// windows support: need to use /, not \
if (path.sep !== '/') {
pattern = pattern.split(path.sep).join('/');
}
this.options = options;
this.set = [];
this.pattern = pattern;
this.regexp = null;
this.negate = false;
this.comment = false;
this.empty = false;
// make the set of regexps etc.
this.make();
}
Minimatch.prototype.debug = function () {};
Minimatch.prototype.make = make;
function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern;
var options = this.options;
// empty patterns and comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
this.comment = true;
return
}
if (!pattern) {
this.empty = true;
return
}
// step 1: figure out negation, etc.
this.parseNegate();
// step 2: expand braces
var set = this.globSet = this.braceExpand();
if (options.debug) this.debug = console.error;
this.debug(this.pattern, set);
// step 3: now we have a set, so turn each one into a series of path-portion
// matching patterns.
// These will be regexps, except in the case of "**", which is
// set to the GLOBSTAR object for globstar behavior,
// and will not contain any / characters
set = this.globParts = set.map(function (s) {
return s.split(slashSplit)
});
this.debug(this.pattern, set);
// glob --> regexps
set = set.map(function (s, si, set) {
return s.map(this.parse, this)
}, this);
this.debug(this.pattern, set);
// filter out everything that didn't compile properly.
set = set.filter(function (s) {
return s.indexOf(false) === -1
});
this.debug(this.pattern, set);
this.set = set;
}
Minimatch.prototype.parseNegate = parseNegate;
function parseNegate () {
var pattern = this.pattern;
var negate = false;
var options = this.options;
var negateOffset = 0;
if (options.nonegate) return
for (var i = 0, l = pattern.length
; i < l && pattern.charAt(i) === '!'
; i++) {
negate = !negate;
negateOffset++;
}
if (negateOffset) this.pattern = pattern.substr(negateOffset);
this.negate = negate;
}
// Brace expansion:
// a{b,c}d -> abd acd
// a{b,}c -> abc ac
// a{0..3}d -> a0d a1d a2d a3d
// a{b,c{d,e}f}g -> abg acdfg acefg
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
//
// Invalid sets are not expanded.
// a{2..}b -> a{2..}b
// a{b}c -> a{b}c
minimatch.braceExpand = function (pattern, options) {
return braceExpand(pattern, options)
};
Minimatch.prototype.braceExpand = braceExpand;
function braceExpand (pattern, options) {
if (!options) {
if (this instanceof Minimatch) {
options = this.options;
} else {
options = {};
}
}
pattern = typeof pattern === 'undefined'
? this.pattern : pattern;
if (typeof pattern === 'undefined') {
throw new TypeError('undefined pattern')
}
if (options.nobrace ||
!pattern.match(/\{.*\}/)) {
// shortcut. no need to expand.
return [pattern]
}
return braceExpansion(pattern)
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
// pattern, split on '/', and then turned into a regular expression.
// A regexp is made at the end which joins each array with an
// escaped /, and another full one which joins each regexp with |.
//
// Following the lead of Bash 4.1, note that "**" only has special meaning
// when it is the *only* thing in a path portion. Otherwise, any series
// of * is equivalent to a single *. Globstar behavior is enabled by
// default, and can be disabled by setting options.noglobstar.
Minimatch.prototype.parse = parse;
var SUBPARSE = {};
function parse (pattern, isSub) {
if (pattern.length > 1024 * 64) {
throw new TypeError('pattern is too long')
}
var options = this.options;
// shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR
if (pattern === '') return ''
var re = '';
var hasMagic = !!options.nocase;
var escaping = false;
// ? => one single character
var patternListStack = [];
var negativeLists = [];
var stateChar;
var inClass = false;
var reClassStart = -1;
var classStart = -1;
// . and .. never match anything that doesn't start with .,
// even when options.dot is set.
var patternStart = pattern.charAt(0) === '.' ? '' // anything
// not (start or / followed by . or .. followed by / or end)
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
: '(?!\\.)';
var self = this;
function clearStateChar () {
if (stateChar) {
// we had some state-tracking character
// that wasn't consumed by this pass.
switch (stateChar) {
case '*':
re += star;
hasMagic = true;
break
case '?':
re += qmark;
hasMagic = true;
break
default:
re += '\\' + stateChar;
break
}
self.debug('clearStateChar %j %j', stateChar, re);
stateChar = false;
}
}
for (var i = 0, len = pattern.length, c
; (i < len) && (c = pattern.charAt(i))
; i++) {
this.debug('%s\t%s %s %j', pattern, i, re, c);
// skip over any that are escaped.
if (escaping && reSpecials[c]) {
re += '\\' + c;
escaping = false;
continue
}
switch (c) {
case '/':
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
case '\\':
clearStateChar();
escaping = true;
continue
// the various stateChar values
// for the "extglob" stuff.
case '?':
case '*':
case '+':
case '@':
case '!':
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c);
// all of those are literals inside a class, except that
// the glob [!a] means [^a] in regexp
if (inClass) {
this.debug(' in class');
if (c === '!' && i === classStart + 1) c = '^';
re += c;
continue
}
// if we already have a stateChar, then it means
// that there was something like ** or +? in there.
// Handle the stateChar, then proceed with this one.
self.debug('call clearStateChar %j', stateChar);
clearStateChar();
stateChar = c;
// if extglob is disabled, then +(asdf|foo) isn't a thing.
// just clear the statechar *now*, rather than even diving into
// the patternList stuff.
if (options.noext) clearStateChar();
continue
case '(':
if (inClass) {
re += '(';
continue
}
if (!stateChar) {
re += '\\(';
continue
}
patternListStack.push({
type: stateChar,
start: i - 1,
reStart: re.length,
open: plTypes[stateChar].open,
close: plTypes[stateChar].close
});
// negation is (?:(?!js)[^/]*)
re += stateChar === '!' ? '(?:(?!(?:' : '(?:';
this.debug('plType %j %j', stateChar, re);
stateChar = false;
continue
case ')':
if (inClass || !patternListStack.length) {
re += '\\)';
continue
}
clearStateChar();
hasMagic = true;
var pl = patternListStack.pop();
// negation is (?:(?!js)[^/]*)
// The others are (?:<pattern>)<type>
re += pl.close;
if (pl.type === '!') {
negativeLists.push(pl);
}
pl.reEnd = re.length;
continue
case '|':
if (inClass || !patternListStack.length || escaping) {
re += '\\|';
escaping = false;
continue
}
clearStateChar();
re += '|';
continue
// these are mostly the same in regexp and glob
case '[':
// swallow any state-tracking char before the [
clearStateChar();
if (inClass) {
re += '\\' + c;
continue
}
inClass = true;
classStart = i;
reClassStart = re.length;
re += c;
continue
case ']':
// a right bracket shall lose its special
// meaning and represent itself in
// a bracket expression if it occurs
// first in the list. -- POSIX.2 2.8.3.2
if (i === classStart + 1 || !inClass) {
re += '\\' + c;
escaping = false;
continue
}
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i);
try {
RegExp('[' + cs + ']');
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE);
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]';
hasMagic = hasMagic || sp[1];
inClass = false;
continue
}
}
// finish up the class.
hasMagic = true;
inClass = false;
re += c;
continue
default:
// swallow any state char that wasn't consumed
clearStateChar();
if (escaping) {
// no need
escaping = false;
} else if (reSpecials[c]
&& !(c === '^' && inClass)) {
re += '\\';
}
re += c;
} // switch
} // for
// handle the case where we left a class open.
// "[abc" is valid, equivalent to "\[abc"
if (inClass) {
// split where the last [ was, and escape it
// this is a huge pita. We now have to re-walk
// the contents of the would-be class to re-translate
// any characters that were passed through as-is
cs = pattern.substr(classStart + 1);
sp = this.parse(cs, SUBPARSE);
re = re.substr(0, reClassStart) + '\\[' + sp[0];
hasMagic = hasMagic || sp[1];
}
// handle the case where we had a +( thing at the *end*
// of the pattern.
// each pattern list stack adds 3 chars, and we need to go through
// and escape any | chars that were passed through as-is for the regexp.
// Go through and escape them, taking care not to double-escape any
// | chars that were already escaped.
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
var tail = re.slice(pl.reStart + pl.open.length);
this.debug('setting tail', re, pl);
// maybe some even number of \, then maybe 1 \, followed by a |
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
if (!$2) {
// the | isn't already escaped, so escape it.
$2 = '\\';
}
// need to escape all those slashes *again*, without escaping the
// one that we need for escaping the | character. As it works out,
// escaping an even number of slashes can be done by simply repeating
// it exactly after itself. That's why this trick works.
//
// I am sorry that you have to see this.
return $1 + $1 + $2 + '|'
});
this.debug('tail=%j\n %s', tail, tail, pl, re);
var t = pl.type === '*' ? star
: pl.type === '?' ? qmark
: '\\' + pl.type;
hasMagic = true;
re = re.slice(0, pl.reStart) + t + '\\(' + tail;
}
// handle trailing things that only matter at the very end.
clearStateChar();
if (escaping) {
// trailing \\
re += '\\\\';
}
// only need to apply the nodot start if the re starts with
// something that could conceivably capture a dot
var addPatternStart = false;
switch (re.charAt(0)) {
case '.':
case '[':
case '(': addPatternStart = true;
}
// Hack to work around lack of negative lookbehind in JS
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
// like 'a.xyz.yz' doesn't match. So, the first negative
// lookahead, has to look ALL the way ahead, to the end of
// the pattern.
for (var n = negativeLists.length - 1; n > -1; n--) {
var nl = negativeLists[n];
var nlBefore = re.slice(0, nl.reStart);
var nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
var nlLast = re.slice(nl.reEnd - 8, nl.reEnd);
var nlAfter = re.slice(nl.reEnd);
nlLast += nlAfter;
// Handle nested stuff like *(*.js|!(*.json)), where open parens
// mean that we should *not* include the ) in the bit that is considered
// "after" the negated section.
var openParensBefore = nlBefore.split('(').length - 1;
var cleanAfter = nlAfter;
for (i = 0; i < openParensBefore; i++) {
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
}
nlAfter = cleanAfter;
var dollar = '';
if (nlAfter === '' && isSub !== SUBPARSE) {
dollar = '$';
}
var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast;
re = newRe;
}
// if the re is not "" at this point, then we need to make sure
// it doesn't match against an empty path part.
// Otherwise a/* will match a/, which it should not.
if (re !== '' && hasMagic) {
re = '(?=.)' + re;
}
if (addPatternStart) {
re = patternStart + re;
}
// parsing just a piece of a larger pattern.
if (isSub === SUBPARSE) {
return [re, hasMagic]
}
// skip the regexp for non-magical patterns
// unescape anything in it, though, so that it'll be
// an exact match against a file etc.
if (!hasMagic) {
return globUnescape(pattern)
}
var flags = options.nocase ? 'i' : '';
try {
var regExp = new RegExp('^' + re + '$', flags);
} catch (er) {
// If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line
// mode, but it's not a /m regex.
return new RegExp('$.')
}
regExp._glob = pattern;
regExp._src = re;
return regExp
}
minimatch.makeRe = function (pattern, options) {
return new Minimatch(pattern, options || {}).makeRe()
};
Minimatch.prototype.makeRe = makeRe;
function makeRe () {
if (this.regexp || this.regexp === false) return this.regexp
// at this point, this.set is a 2d array of partial
// pattern strings, or "**".
//
// It's better to use .match(). This function shouldn't
// be used, really, but it's pretty convenient sometimes,
// when you just want to work with a regex.
var set = this.set;
if (!set.length) {
this.regexp = false;
return this.regexp
}
var options = this.options;
var twoStar = options.noglobstar ? star
: options.dot ? twoStarDot
: twoStarNoDot;
var flags = options.nocase ? 'i' : '';
var re = set.map(function (pattern) {
return pattern.map(function (p) {
return (p === GLOBSTAR) ? twoStar
: (typeof p === 'string') ? regExpEscape(p)
: p._src
}).join('\\\/')
}).join('|');
// must match entire pattern
// ending in a * or ** will make it less strict.
re = '^(?:' + re + ')$';
// can match anything, as long as it's not this.
if (this.negate) re = '^(?!' + re + ').*$';
try {
this.regexp = new RegExp(re, flags);
} catch (ex) {
this.regexp = false;
}
return this.regexp
}
minimatch.match = function (list, pattern, options) {
options = options || {};
var mm = new Minimatch(pattern, options);
list = list.filter(function (f) {
return mm.match(f)
});
if (mm.options.nonull && !list.length) {
list.push(pattern);
}
return list
};
Minimatch.prototype.match = match;
function match (f, partial) {
this.debug('match', f, this.pattern);
// short-circuit in the case of busted things.
// comments, etc.
if (this.comment) return false
if (this.empty) return f === ''
if (f === '/' && partial) return true
var options = this.options;
// windows: need to use /, not \
if (path.sep !== '/') {
f = f.split(path.sep).join('/');
}
// treat the test path as a set of pathparts.
f = f.split(slashSplit);
this.debug(this.pattern, 'split', f);
// just ONE of the pattern sets in this.set needs to match
// in order for it to be valid. If negating, then just one
// match means that we have failed.
// Either way, return on the first hit.
var set = this.set;
this.debug(this.pattern, 'set', set);
// Find the basename of the path by looking for the last non-empty segment
var filename;
var i;
for (i = f.length - 1; i >= 0; i--) {
filename = f[i];
if (filename) break
}
for (i = 0; i < set.length; i++) {
var pattern = set[i];
var file = f;
if (options.matchBase && pattern.length === 1) {
file = [filename];
}
var hit = this.matchOne(file, pattern, partial);
if (hit) {
if (options.flipNegate) return true
return !this.negate
}
}
// didn't get any hits. this is success if it's a negative
// pattern, failure otherwise.
if (options.flipNegate) return false
return this.negate
}
// set partial to true to test if, for example,
// "/a/b" matches the start of "/*/b/*/d"
// Partial means, if you run out of file before you run
// out of pattern, then that's fine, as long as all
// the parts match.
Minimatch.prototype.matchOne = function (file, pattern, partial) {
var options = this.options;
this.debug('matchOne',
{ 'this': this, file: file, pattern: pattern });
this.debug('matchOne', file.length, pattern.length);
for (var fi = 0,
pi = 0,
fl = file.length,
pl = pattern.length
; (fi < fl) && (pi < pl)
; fi++, pi++) {
this.debug('matchOne loop');
var p = pattern[pi];
var f = file[fi];
this.debug(pattern, p, f);
// should be impossible.
// some invalid regexp stuff in the set.
if (p === false) return false
if (p === GLOBSTAR) {
this.debug('GLOBSTAR', [pattern, p, f]);
// "**"
// a/**/b/**/c would match the following:
// a/b/x/y/z/c
// a/x/y/z/b/c
// a/b/x/b/x/c
// a/b/c
// To do this, take the rest of the pattern after
// the **, and see if it would match the file remainder.
// If so, return success.
// If not, the ** "swallows" a segment, and try again.
// This is recursively awful.
//
// a/**/b/**/c matching a/b/x/y/z/c
// - a matches a
// - doublestar
// - matchOne(b/x/y/z/c, b/**/c)
// - b matches b
// - doublestar
// - matchOne(x/y/z/c, c) -> no
// - matchOne(y/z/c, c) -> no
// - matchOne(z/c, c) -> no
// - matchOne(c, c) yes, hit
var fr = fi;
var pr = pi + 1;
if (pr === pl) {
this.debug('** at the end');
// a ** at the end will just swallow the rest.
// We have found a match.
// however, it will not swallow /.x, unless
// options.dot is set.
// . and .. are *never* matched by **, for explosively
// exponential reasons.
for (; fi < fl; fi++) {
if (file[fi] === '.' || file[fi] === '..' ||
(!options.dot && file[fi].charAt(0) === '.')) return false
}
return true
}
// ok, let's see if we can swallow whatever we can.
while (fr < fl) {
var swallowee = file[fr];
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
// XXX remove this slice. Just pass the start index.
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
this.debug('globstar found match!', fr, fl, swallowee);
// found a match.
return true
} else {
// can't swallow "." or ".." ever.
// can only swallow ".foo" when explicitly asked.
if (swallowee === '.' || swallowee === '..' ||
(!options.dot && swallowee.charAt(0) === '.')) {
this.debug('dot detected!', file, fr, pattern, pr);
break
}
// ** swallows a segment, and continue.
this.debug('globstar swallow a segment, and continue');
fr++;
}
}
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
if (fr === fl) return true
}
return false
}
// something other than **
// non-magic patterns just have to match exactly
// patterns with magic have been turned into regexps.
var hit;
if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase();
} else {
hit = f === p;
}
this.debug('string match', p, f, hit);
} else {
hit = f.match(p);
this.debug('pattern match', p, f, hit);
}
if (!hit) return false
}
// Note: ending in / means that we'll get a final ""
// at the end of the pattern. This can only match a
// corresponding "" at the end of the file.
// If the file ends in /, then it can only match a
// a pattern that ends in /, unless the pattern just
// doesn't have any more for it. But, a/b/ should *not*
// match "a/b/*", even though "" matches against the
// [^/]*? pattern, except in partial mode, where it might
// simply not be reached yet.
// However, a/b/ should still satisfy a/*
// now either we fell off the end of the pattern, or we're done.
if (fi === fl && pi === pl) {
// ran out of pattern and filename at the same time.
// an exact hit!
return true
} else if (fi === fl) {
// ran out of file, but still had pattern left.
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '');
return emptyFileEnd
}
// should be unreachable.
throw new Error('wtf?')
};
// replace stuff like \* with *
function globUnescape (s) {
return s.replace(/\\(.)/g, '$1')
}
function regExpEscape (s) {
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}
var pluginutils_cjs = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, '__esModule', { value: true });
function basename ( path ) {
return path.split( /(\/|\\)/ ).pop();
}
function extname ( path ) {
var match = /\.[^\.]+$/.exec( basename( path ) );
if ( !match ) return '';
return match[0];
}
function addExtension ( filename, ext ) {
if ( ext === void 0 ) ext = '.js';
if ( !extname( filename ) ) filename += ext;
return filename;
}
var blockDeclarations = {
'const': true,
'let': true
};
var extractors = {
Identifier: function Identifier ( names, param ) {
names.push( param.name );
},
ObjectPattern: function ObjectPattern ( names, param ) {
param.properties.forEach( function (prop) {
extractors[ prop.key.type ]( names, prop.key );
});
},
ArrayPattern: function ArrayPattern ( names, param ) {
param.elements.forEach( function (element) {
if ( element ) extractors[ element.type ]( names, element );
});
},
RestElement: function RestElement ( names, param ) {
extractors[ param.argument.type ]( names, param.argument );
},
AssignmentPattern: function AssignmentPattern ( names, param ) {
return extractors[ param.left.type ]( names, param.left );
}
};
function extractNames ( param ) {
var names = [];
extractors[ param.type ]( names, param );
return names;
}
var Scope = function Scope ( options ) {
var this$1 = this;
options = options || {};
this.parent = options.parent;
this.isBlockScope = !!options.block;
this.declarations = Object.create( null );
if ( options.params ) {
options.params.forEach( function (param) {
extractNames( param ).forEach( function (name) {
this$1.declarations[ name ] = true;
});
});
}
};
Scope.prototype.addDeclaration = function addDeclaration ( node, isBlockDeclaration, isVar ) {
var this$1 = this;
if ( !isBlockDeclaration && this.isBlockScope ) {
// it's a `var` or function node, and this
// is a block scope, so we need to go up
this.parent.addDeclaration( node, isBlockDeclaration, isVar );
} else {
extractNames( node.id ).forEach( function (name) {
this$1.declarations[ name ] = true;
});
}
};
Scope.prototype.contains = function contains ( name ) {
return this.declarations[ name ] ||
( this.parent ? this.parent.contains( name ) : false );
};
function attachScopes ( ast, propertyName ) {
if ( propertyName === void 0 ) propertyName = 'scope';
var scope = new Scope();
estreeWalker_umd.walk( ast, {
enter: function enter ( node, parent ) {
// function foo () {...}
// class Foo {...}
if ( /(Function|Class)Declaration/.test( node.type ) ) {
scope.addDeclaration( node, false, false );
}
// var foo = 1
if ( node.type === 'VariableDeclaration' ) {
var isBlockDeclaration = blockDeclarations[ node.kind ];
node.declarations.forEach( function (declaration) {
scope.addDeclaration( declaration, isBlockDeclaration, true );
});
}
var newScope;
// create new function scope
if ( /Function/.test( node.type ) ) {
newScope = new Scope({
parent: scope,
block: false,
params: node.params
});
// named function expressions - the name is considered
// part of the function's scope
if ( node.type === 'FunctionExpression' && node.id ) {
newScope.addDeclaration( node, false, false );
}
}
// create new block scope
if ( node.type === 'BlockStatement' && !/Function/.test( parent.type ) ) {
newScope = new Scope({
parent: scope,
block: true
});
}
// catch clause has its own block scope
if ( node.type === 'CatchClause' ) {
newScope = new Scope({
parent: scope,
params: [ node.param ],
block: true
});
}
if ( newScope ) {
Object.defineProperty( node, propertyName, {
value: newScope,
configurable: true
});
scope = newScope;
}
},
leave: function leave ( node ) {
if ( node[ propertyName ] ) scope = scope.parent;
}
});
return scope;
}
function ensureArray ( thing ) {
if ( Array.isArray( thing ) ) return thing;
if ( thing == undefined ) return [];
return [ thing ];
}
function createFilter ( include, exclude ) {
include = ensureArray( include ).map( function (id) { return path$1.resolve( id ); } ).map( function (id) { return new minimatch_1.Minimatch(id); } );
exclude = ensureArray( exclude ).map( function (id) { return path$1.resolve( id ); } ).map( function (id) { return new minimatch_1.Minimatch(id); } );
return function ( id ) {
if ( typeof id !== 'string' ) return false;
if ( /\0/.test( id ) ) return false;
var included = !include.length;
id = id.split(path$1.sep).join('/');
include.forEach( function (minimatch) {
if ( minimatch.match( id ) ) included = true;
});
exclude.forEach( function (minimatch) {
if ( minimatch.match( id ) ) included = false;
});
return included;
};
}
var reservedWords = 'break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield enum await implements package protected static interface private public'.split( ' ' );
var builtins = 'arguments Infinity NaN undefined null true false eval uneval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Symbol Error EvalError InternalError RangeError ReferenceError SyntaxError TypeError URIError Number Math Date String RegExp Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Map Set WeakMap WeakSet SIMD ArrayBuffer DataView JSON Promise Generator GeneratorFunction Reflect Proxy Intl'.split( ' ' );
var blacklisted = Object.create( null );
reservedWords.concat( builtins ).forEach( function (word) { return blacklisted[ word ] = true; } );
function makeLegalIdentifier ( str ) {
str = str
.replace( /-(\w)/g, function ( _, letter ) { return letter.toUpperCase(); } )
.replace( /[^$_a-zA-Z0-9]/g, '_' );
if ( /\d/.test( str[0] ) || blacklisted[ str ] ) str = "_" + str;
return str;
}
exports.addExtension = addExtension;
exports.attachScopes = attachScopes;
exports.createFilter = createFilter;
exports.makeLegalIdentifier = makeLegalIdentifier;
});
unwrapExports(pluginutils_cjs);
var pluginutils_cjs_1 = pluginutils_cjs.addExtension;
var pluginutils_cjs_2 = pluginutils_cjs.attachScopes;
var pluginutils_cjs_3 = pluginutils_cjs.createFilter;
var pluginutils_cjs_4 = pluginutils_cjs.makeLegalIdentifier;
function toDataUrl (code) {
var mime = 'image/svg+xml';
var buffer = Buffer.from(code, 'utf-8');
var encoded = buffer.toString('base64');
return ("'data:" + mime + ";base64," + encoded + "'")
}
function svg (options) {
if ( options === void 0 ) options = {};
var filter = pluginutils_cjs.createFilter(options.include, options.exclude);
return {
name: 'svg',
transform: function transform (code, id) {
if (!filter(id) || path$1.extname(id) !== '.svg') {
return null
}
var content = code.trim();
var encoded = options.base64 ? toDataUrl(content) : JSON.stringify(content);
return { code: ("export default " + encoded), map: { mappings: '' } }
}
}
}
var rollupPluginSvg_cjs = svg;
const isFunction = (arg) => typeof arg === 'function';
const isRegExp = (arg) => Object.prototype.toString.call(arg) === '[object RegExp]';
const readFilePromise = util.promisify(fs.readFile);
const writeFilePromise = util.promisify(fs.writeFile);
// functionality partially copied from rollup
/**
* copied from https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L450
*/
function isOutputChunk(file) {
return typeof file.code === 'string';
}
/**
* Gets the string/buffer content from a file object.
* Important for adding source map comments
*
* Copied partially from rollup.writeOutputFile
* https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L454
*/
function getOutputFileContent(outputFileName, outputFile, outputOptions) {
if (isOutputChunk(outputFile)) {
let source;
source = outputFile.code;
if (outputOptions.sourcemap && outputFile.map) {
const url = outputOptions.sourcemap === 'inline'
? outputFile.map.toUrl()
: `${path$1.basename(outputFileName)}.map`;
// https://github.com/rollup/rollup/blob/master/src/utils/sourceMappingURL.ts#L1
source += `//# source` + `MappingURL=${url}\n`;
}
return source;
}
else {
if (rollup.VERSION < '1.0.0') {
return outputFile;
}
return typeof outputFile.source === 'string'
? outputFile.source
: // just to be sure, as it is typed string | Uint8Array in rollup 2.0.0
Buffer.from(outputFile.source);
}
}
// actual plugin code
function gzipPlugin(options = {}) {
if (rollup.VERSION < '0.60.0') {
console.error('[rollup-plugin-gzip] This plugin supports rollup version >0.60.0!');
console.error('For older rollup versions, please use version 1.x of this plugin.');
}
// check for old options
if ('algorithm' in options) {
console.warn('[rollup-plugin-gzip] The "algorithm" option is not supported any more! ' +
'Use "customCompression" instead to specify a different compression algorithm.');
}
if ('options' in options) {
console.warn('[rollup-plugin-gzip] The "options" option was renamed to "gzipOptions"!');
}
if ('additional' in options) {
console.warn('[rollup-plugin-gzip] The "additional" option was renamed to "additionalFiles"!');
}
if ('delay' in options) {
console.warn('[rollup-plugin-gzip] The "delay" option was renamed to "additionalFilesDelay"!');
}
const compressGzip = fileContent => {
return new Promise((resolve, reject) => {
zlib.gzip(fileContent, options.gzipOptions || {}, (err, result) => {
if (err) {
reject(err);
}
else {
resolve(result);
}
});
});
};
const doCompress = options.customCompression || compressGzip;
const mapFileName = isFunction(options.fileName)
? options.fileName
: (fileName) => fileName + (options.fileName || '.gz');
const plugin = {
name: 'gzip',
generateBundle(outputOptions, bundle, isWrite) {
if (!isWrite)
return;
return Promise.all(Object.keys(bundle)
.map(fileName => {
const fileEntry = bundle[fileName];
// file name filter option check
const fileNameFilter = options.filter || /\.(js|mjs|json|css|html)$/;
if (isRegExp(fileNameFilter) &&
!fileName.match(fileNameFilter)) {
return Promise.resolve();
}
if (isFunction(fileNameFilter) &&
!fileNameFilter(fileName)) {
return Promise.resolve();
}
const fileContent = getOutputFileContent(fileName, fileEntry, outputOptions);
// minSize option check
if (options.minSize &&
options.minSize > fileContent.length) {
return Promise.resolve();
}
return Promise.resolve(doCompress(fileContent))
.then(compressedContent => {
const compressedFileName = mapFileName(fileName);
if (rollup.VERSION < '1.0.0') {
bundle[compressedFileName] = compressedContent;
}
else {
bundle[compressedFileName] = {
type: 'asset',
fileName: compressedFileName,
isAsset: true,
source: compressedContent,
};
}
})
.catch((err) => {
console.error(err);
return Promise.reject('[rollup-plugin-gzip] Error compressing file ' +
fileName);
});
})
.concat([
(() => {
if (!options.additionalFiles ||
!options.additionalFiles.length)
return Promise.resolve();
const compressAdditionalFiles = () => Promise.all(options.additionalFiles.map(filePath => readFilePromise(filePath)
.then(fileContent => doCompress(fileContent))
.then(compressedContent => {
return writeFilePromise(mapFileName(filePath), compressedContent);
})
.catch((err) => {
return Promise.reject('[rollup-plugin-gzip] Error compressing additional file ' +
filePath +
'. Please check the spelling of your configured additionalFiles. ' +
'You might also have to increase the value of the additionalFilesDelay option.');
})));
// additional files can be processed outside of rollup after a delay
// for older plugins or plugins that write to disk (curcumventing rollup) without awaiting
const additionalFilesDelay = options.additionalFilesDelay ||
(rollup.VERSION >= '2.0.0' ? 0 : 2000);
if (additionalFilesDelay) {
setTimeout(compressAdditionalFiles, additionalFilesDelay);
return Promise.resolve();
}
else {
return compressAdditionalFiles();
}
})(),
]));
},
};
return plugin;
}
function hash$1(options = {}) {
options = { ...defaultOptions, ...options };
return {
name: 'hash-version-manifest',
renderChunk: function (code, chunk, outputOptions) {
const filePath = options.formatter(outputOptions.dir.split(path$1.sep).join('/'));
// if outputOptions.entryFileNames contains [hash] we need to extract it from the path for the key in the manifest
const fileExtension = chunk.fileName.split('.').pop();
const keyFileName = `${filePath}${chunk.name}.${fileExtension}`;
const valueFileName = `${filePath}${chunk.fileName}`;
if (chunk.isEntry && !valueFileName.includes('.map')) {
addToManifest(keyFileName, valueFileName, code, options);
}
},
};
}
const isDev = environments.development;
const isProd = environments.production;
const rollupJS = async (inputOptions = {}, outputOptions = {}, babelOptions = {}) => {
inputOptions = Object.assign(
{
input: 'src/main.js',
plugins: [
babel(babelOptions),
resolve(),
postcss$1(),
rollupPluginSvg_cjs(),
commonjs(),
config.versionManifest !== false && hash$1(config.versionManifest),
isProd() && cleanup({}),
isProd() && rollupPluginTerser.terser(),
isProd() && gzipPlugin(),
],
},
inputOptions,
);
outputOptions = Object.assign(
{
dir: 'public',
entryFileNames: '[name].js',
format: 'es',
sourcemap: true,
},
outputOptions,
);
if (isDev() && outputOptions['format'] === 'es') {
return new Promise((resolve) => {
const watcher = rollup.watch({
...inputOptions,
output: [outputOptions],
watch: {
clearScreen: true,
},
});
watcher.on('event', (event) => {
if (!config.showNotifications) return;
if (event.code === 'START') {
notify({ title: config.projectTitle, message: 'Starting "es6"...' }).write('');
}
if (event.code === 'BUNDLE_END') {
notify({
title: config.projectTitle,
message: 'Finished "es6" after ' + (event.duration / 1000).toFixed(2) + ' s',
}).write('');
}
if (event.code === 'END') {
resolve();
}
if (event.code === 'ERROR' || event.code === 'FATAL') {
console.log('rollup watch ERROR', event);
notify.onError({
title: config.projectTitle,
message: 'JS ERROR|FATAL',
});
}
});
});
} else {
const bundle = await rollup.rollup(inputOptions);
return await bundle.write(outputOptions);
}
};
rollupJS.description = `compile scripts using rollup with babel and code splitting`;
const isDev$1 = environments.development;
const isProd$1 = environments.production;
const js = (options = { outputOptions: {}, babelOptions: {} }) => {
return () => {
return rollupJS(
{
input: glob.sync(options.src),
},
{
dir: options.dest,
entryFileNames: '[name].js',
format: 'es',
sourcemap: true,
...options.outputOptions,
},
{
babelrc: true,
...options.babelOptions,
},
);
};
};
const lintCSS = (options) => {
return () => {
return gulp.src(options.src).pipe(postcss([stylelint]));
};
};
lintCSS.description = `lint styles using stylelint`;
const lintJS = (options) => {
return () => {
return gulp
.src(options.src)
.pipe(
eslint({
configFile: options.configFile || '.eslintrc',
useEslintrc: true,
}),
)
.pipe(eslint.format())
.pipe(eslint.failAfterError());
};
};
lintJS.description = `lint scripts using eslint`;
const spawn = childProcess.spawn;
const run = (options) => {
return (cb) => {
const cmd = spawn(options.cmd, options.args, { stdio: 'inherit' });
cmd.on('close', function (code) {
log(options.cmd + ' exited with code ' + code);
cb(code);
});
cmd.on('error', function (error) {
log.error(options.cmd + ' errored with msg: ' + error);
cb(error);
});
};
};
const svgTask = (src, dest) => {
return gulp
.src(src)
.pipe(svgSprite({ mode: { symbol: true } }))
.pipe(gulp.dest(dest));
};
const svg$1 = (options) => {
return () => {
const streams = options.paths.map((path) => {
return svgTask(path.src, path.dest);
});
return merge(streams);
};
};
svg$1.description = `generates an svg sprite from all *.svg files in src and saves it in dest`;
const watch = (options) => {
return () => {
notify({ title: config.projectTitle, message: 'Watching for changes...' }).write('');
options.paths.forEach((path) => {
gulp.watch(path.src, path.tasks)
.on('change', function () {
if (config.showNotifications) {
notify({ title: config.projectTitle, message: path.changeMessage || 'Change' }).write('');
}
})
.on('error', function (error) {
if (config.showNotifications) {
notify.onError({
title: config.projectTitle,
message: path.errorMessage || 'Error: ' + error.message,
});
}
});
});
};
};
const options = (options = {}) => {
Object.assign(config, options);
};
const tasks = {
browserSync,
clean,
copy,
css,
js,
lintCSS,
lintJS,
run,
svg: svg$1,
watch,
};
// API
// tasks.clean({ directories: [] });
// tasks.copy({ paths: [] });
// tasks.js({ src, destination });
// tasks.css({ src, destination });
// tasks.run({ cmd: 'ls', args: ['-la'] });
// tasks.svg({ paths: [] });
// tasks.browserSync({ files: [] });
// options({
// projectTitle: 'frontend-tasks',
// showNotifications: true,
// generateVersionManifest: false,
// });
exports.options = options;
exports.tasks = tasks;