diff --git a/bin/sake.js b/bin/sake.js index 317d661..b8e856d 100755 --- a/bin/sake.js +++ b/bin/sake.js @@ -1,6 +1,10 @@ #!/usr/bin/env node -const { spawn } = require('child_process') -const path = require('path') +import { spawn } from 'node:child_process' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import resolve from 'resolve-bin' +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); /** * `sake` is simply a nice wrapper around `gulp`, designed to simplify using gulp @@ -17,7 +21,7 @@ const path = require('path') // The concat portion passes in any optional CLI args as well as the gulpfile from sake and // current workind directory. const args = [ - require('resolve-bin').sync('gulp') + resolve.sync('gulp') ].concat(process.argv.splice(2).concat([ '--gulpfile', path.join(__dirname, '../gulpfile.js'), '--cwd', process.cwd() diff --git a/gulpfile.js b/gulpfile.js index 19d580e..ec5dfe9 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,19 +1,22 @@ -'use strict' - -const gulp = require('gulp') -const path = require('path') -const fs = require('fs') -const minimist = require('minimist') -const log = require('fancy-log') -const _ = require('lodash') -const ForwardReference = require('undertaker-forward-reference') +import gulp from 'gulp' +import path from 'node:path' +import fs from 'node:fs' +import log from 'fancy-log' +import ForwardReference from 'undertaker-forward-reference' +import dotenv from 'dotenv' +import gulpPlugins from 'gulp-load-plugins' +import notifier from 'node-notifier' +import stripAnsi from 'strip-ansi' +import { fileURLToPath } from 'node:url' +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); // local .env file, overriding any global env variables let parentEnvPath = path.join('..', '.env') let envPath = fs.existsSync('.env') ? '.env' : (fs.existsSync(parentEnvPath) ? parentEnvPath : null) if (envPath) { - let result = require('dotenv').config({ path: envPath }) + let result = dotenv.config({ path: envPath }) log.warn(`Loading ENV variables from ${path.join(process.cwd(), envPath)}`) @@ -25,7 +28,7 @@ if (envPath) { // development .env file, overriding any global env variables, or repo/plugin specific variables let devEnv = path.join(__dirname, '.env') if (fs.existsSync(devEnv)) { - let result = require('dotenv').config({path: devEnv}) + let result = dotenv.config({path: devEnv}) log.warn('LOADING DEVELOPMENT ENV VARIABLES FROM ' + devEnv) @@ -37,116 +40,12 @@ if (fs.existsSync(devEnv)) { // enable forward-referencing tasks, see https://github.com/gulpjs/gulp/issues/1028 gulp.registry(ForwardReference()) -// define default config -let defaults = { - // sets up the plugin folder structure - paths: { - // Path to plugin source files - this is where the main plugin entry file is located. Set this to a dot (.) if the - // main plugin file and sake.config.js are in teh same directory. The path is relative to the current working directory. - // Mostly, this is the only path a plugin/repo needs to explicitly set - src: '.', - // where plugin assets are located, relative to `src` - assets: 'assets', - // where plugin CSS/SCSS assets are located, relative to `src` - css: 'assets/css', - // where plugin JS/COFFEE assets are located, relative to `src` - js: 'assets/js', - // where plugin image assets are located, relative to `src` - images: 'assets/img', - // where plugin font assets are located, relative to `src` - fonts: 'assets/fonts', - // the directory where plugin files are copied during the build task, relative to current working directory - build: 'build', - // path to the directory where production (WC and WP.org SVN) repos are cloned, may be an absolute path or relative to current working directory - tmp: '/tmp/sake', - // array of paths that should be excluded from the build - exclude: [] - }, - - // Task-specific settings, set the key to task name and provide any settings as needed. Since sake uses Gulp behind the scenes - // and Gulp prefers code over configuration, there isn't a lot to do here. As you can see, some of these values can be defined - // as environment variables, as this makes more sense - ie whether you want to use browsersync or not is specific tp your local - // dev environment and workflow, not to a particular repo. - tasks: { - makepot: { - reportBugsTo: 'https://woocommerce.com/my-account/marketplace-ticket-form/', - domainPath: 'i18n/languages' - }, - watch: { - useBrowserSync: process.env.USE_BROWSERSYNC || false - }, - browserSync: { - url: process.env.BROWSERSYNC_URL || 'plugins-skyverge.test' - } - }, - - // which framework version this plugin uses - valid values: 'v5', 'v4', or pass boolean `false` to indicate a non-frameworked plugin - framework: 'v5', - // which deploy type does this plugin use - either 'wc' or 'wp', defaults to 'wc', specify `null` or `false` for no automated deploy - deploy: 'wc', - // the e-commerce platform this plugin is for, 'wc' or 'edd' - platform: 'wc' -} - -// load local configuration -// TODO: allow passing in config file path or config as string (for multi-plugin repos?) -let localConfig = {} - -// support supplying a single / parent config file in multi-plugin repos -let parentConfigPath = path.join(process.cwd(), '../sake.config.js') -let found = false - -if (fs.existsSync(parentConfigPath)) { - log.warn('Found config file in parent folder') - localConfig = require(parentConfigPath) - found = true -} - -// load local, plugin-specific config file -let configFilePath = path.join(process.cwd(), 'sake.config.js') - -if (fs.existsSync(configFilePath)) { - localConfig = _.merge(localConfig, require(configFilePath)) - found = true -} - -if (!found) { - log.warn('Could not find local config file, using default config values.') -} - -let config = _.merge(defaults, localConfig) - -// parse CLI options -let options = minimist(process.argv.slice(2), { - boolean: ['minify'], - default: { - minify: true, - debug: false - } -}) - -const sake = require('./lib/sake')(config, options) - -sake.initConfig() - -let plugins = require('gulp-load-plugins')() - -// Attach browsersync as a plugin - not really a plugin, but it helps to -// pass around the browsersync instance between tasks. Unfortunately, we -// always have to load and create an instance of it, because gulp-if does not -// support lazy evaluation yet: https://github.com/robrich/gulp-if/issues/75 -plugins.browserSync = require('browser-sync').create() - -// load gulp plugins and tasks -require('fs').readdirSync(path.join(__dirname, 'tasks')).forEach((file) => { - require(path.join(__dirname, 'tasks', file))(gulp, plugins, sake) +// @link https://github.com/jackfranklin/gulp-load-plugins/issues/141#issuecomment-2373391177 +let plugins = gulpPlugins({ + config: path.resolve(__dirname, 'package.json') }) -gulp.task('default', gulp.series('compile')) - // show notification on task errors -const notifier = require('node-notifier') -const stripAnsi = require('strip-ansi') let loggedErrors = [] gulp.on('error', (event) => { @@ -161,3 +60,29 @@ gulp.on('error', (event) => { loggedErrors.push(event.error) } }) + +/************** Task Exports */ + +export * from './tasks/build.js' +export * from './tasks/bump.js' +export * from './tasks/bundle.js' +export * from './tasks/clean.js' +export * from './tasks/compile.js' +export * from './tasks/config.js' +export * from './tasks/copy.js' +export * from './tasks/decaffeinate.js' +export * from './tasks/deploy.js' +export * from './tasks/github.js' +export * from './tasks/imagemin.js' +export * from './tasks/lint.js' +export * from './tasks/makepot.js' +export * from './tasks/prerelease.js' +export * from './tasks/prompt.js' +export * from './tasks/scripts.js' +export * from './tasks/shell.js' +export * from './tasks/styles.js' +export * from './tasks/upfw.js' +export * from './tasks/validate.js' +export * from './tasks/watch.js' +export * from './tasks/wc.js' +export * from './tasks/zip.js' diff --git a/lib/config.js b/lib/config.js new file mode 100644 index 0000000..5f8e2e7 --- /dev/null +++ b/lib/config.js @@ -0,0 +1,91 @@ +import path from 'node:path' +import { existsSync } from 'node:fs' +import log from 'fancy-log' +import _ from 'lodash' +import { createRequire } from 'node:module' +const require = createRequire(import.meta.url); + +const buildSakeConfig = () => { + // define default config + let defaults = { + // sets up the plugin folder structure + paths: { + // Path to plugin source files - this is where the main plugin entry file is located. Set this to a dot (.) if the + // main plugin file and sake.config.js are in teh same directory. The path is relative to the current working directory. + // Mostly, this is the only path a plugin/repo needs to explicitly set + src: '.', + // where plugin assets are located, relative to `src` + assets: 'assets', + // where plugin CSS/SCSS assets are located, relative to `src` + css: 'assets/css', + // where plugin JS/COFFEE assets are located, relative to `src` + js: 'assets/js', + // where plugin image assets are located, relative to `src` + images: 'assets/img', + // where plugin font assets are located, relative to `src` + fonts: 'assets/fonts', + // the directory where plugin files are copied during the build task, relative to current working directory + build: 'build', + // path to the directory where production (WC and WP.org SVN) repos are cloned, may be an absolute path or relative to current working directory + tmp: '/tmp/sake', + // array of paths that should be excluded from the build + exclude: [] + }, + + // Task-specific settings, set the key to task name and provide any settings as needed. Since sake uses Gulp behind the scenes + // and Gulp prefers code over configuration, there isn't a lot to do here. As you can see, some of these values can be defined + // as environment variables, as this makes more sense - ie whether you want to use browsersync or not is specific tp your local + // dev environment and workflow, not to a particular repo. + tasks: { + makepot: { + reportBugsTo: 'https://woocommerce.com/my-account/marketplace-ticket-form/', + domainPath: 'i18n/languages' + }, + watch: { + useBrowserSync: process.env.USE_BROWSERSYNC || false + }, + browserSync: { + url: process.env.BROWSERSYNC_URL || 'plugins-skyverge.test' + } + }, + + // which framework version this plugin uses - valid values: 'v5', 'v4', or pass boolean `false` to indicate a non-frameworked plugin + framework: 'v5', + // which deploy type does this plugin use - either 'wc' or 'wp', defaults to 'wc', specify `null` or `false` for no automated deploy + deploy: 'wc', + // the e-commerce platform this plugin is for, 'wc' or 'edd' + platform: 'wc' + } + + // load local configuration + // TODO: allow passing in config file path or config as string (for multi-plugin repos?) + let localConfig = {} + + // support supplying a single / parent config file in multi-plugin repos + let parentConfigPath = path.join(process.cwd(), '../sake.config.js') + let found = false + + if (existsSync(parentConfigPath)) { + log.warn('Found config file in parent folder') + localConfig = require(parentConfigPath) + found = true + } + + // load local, plugin-specific config file + let configFilePath = path.join(process.cwd(), 'sake.config.js') + + if (existsSync(configFilePath)) { + localConfig = _.merge(localConfig, require(configFilePath)) + found = true + } + + if (!found) { + log.warn('Could not find local config file, using default config values.') + } + + return _.merge(defaults, localConfig) +} + +const sakeConfig = buildSakeConfig(); + +export default sakeConfig; diff --git a/lib/sake.js b/lib/sake.js index 4367b84..bf774b9 100644 --- a/lib/sake.js +++ b/lib/sake.js @@ -1,15 +1,34 @@ -const fs = require('fs') -const path = require('path') -const semver = require('semver') -const parseGitConfig = require('parse-git-config') -const parseGitHubUrl = require('parse-github-url') -const _ = require('lodash') -const _str = require('underscore.string') -const log = require('fancy-log') -const chalk = require('chalk') -const dottie = require('dottie') - -module.exports = (config, options) => { +import fs from 'node:fs'; +import path from 'node:path'; +import semver from 'semver'; +import parseGitConfig from 'parse-git-config'; +import parseGitHubUrl from 'parse-github-url'; +import _ from 'lodash'; +import _str from 'underscore.string'; +import log from 'fancy-log'; +import chalk from 'chalk'; +import dottie from 'dottie'; +import { createRequire } from 'node:module'; +const require = createRequire(import.meta.url); +import sakeConfig from './config.js' +import minimist from 'minimist' + +// parse CLI options +let options = minimist(process.argv.slice(2), { + boolean: ['minify'], + default: { + minify: true, + debug: false + } +}) + + +const sake = initializeSake(sakeConfig, options); +sake.initConfig(); + +export default sake; + +function initializeSake(config, options) { const exports = {} // current task(s) from CLI, ie for `npx sake clean build` this will result in ['clean', 'build'] const cliTasks = process.argv.slice(2, -4) @@ -363,7 +382,7 @@ module.exports = (config, options) => { lines = contents.split('== Changelog ==')[1].trim().split('\n') } - // get the plugin name from changelog - asuuming it will be on the 1st line + // get the plugin name from changelog - assuming it will be on the 1st line if (fileName === 'changelog.txt') { changelog.plugin_name = lines[0].replace(/\*/g, '').replace(/Changelog/, '').trim() } else { diff --git a/package-lock.json b/package-lock.json index 6944c6f..c0b19fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,10 +20,10 @@ "axios": "^1.7.9", "babel-loader": "^8.0.6", "browser-sync": "^3.0.3", - "chalk": "^4.0.0", + "chalk": "^5.4.1", "codename": "0.0.6", "cssnano": "^7.0.6", - "dateformat": "^4.6.3", + "dateformat": "^5.0.3", "del": "^6.1.1", "dotenv": "^16.4.7", "dottie": "^2.0.6", @@ -38,7 +38,7 @@ "gulp-eslint": "^4.0.2", "gulp-filter": "^5.1.0", "gulp-if": "^2.0.2", - "gulp-imagemin": "^6.2.0", + "gulp-imagemin": "^9.1.0", "gulp-load-plugins": "^2.0.7", "gulp-phplint": "^0.9.0", "gulp-postcss": "^10.0.0", @@ -63,7 +63,7 @@ "sass": "^1.83.4", "semver": "^7.7.1", "shelljs": "^0.8.5", - "strip-ansi": "^4.0.0", + "strip-ansi": "^7.1.0", "underscore.string": "^3.3.4", "undertaker-forward-reference": "^1.0.2", "webpack-stream": "^7.0.0" @@ -2320,14 +2320,34 @@ "dev": true, "license": "MIT" }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "license": "MIT" + }, "node_modules/@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.3.1.tgz", + "integrity": "sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==", "license": "MIT", - "optional": true, "engines": { - "node": ">=4" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@skyverge/eslint-config": { @@ -2349,6 +2369,12 @@ "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", "license": "MIT" }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -2396,15 +2422,11 @@ "license": "MIT", "peer": true }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "license": "MIT", - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } + "node_modules/@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -2419,12 +2441,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "license": "MIT" - }, "node_modules/@types/node": { "version": "22.13.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", @@ -2434,12 +2450,15 @@ "undici-types": "~6.20.0" } }, - "node_modules/@types/q": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", - "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==", + "node_modules/@types/vinyl": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", + "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", "license": "MIT", - "optional": true + "dependencies": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", @@ -2844,12 +2863,15 @@ } }, "node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "license": "MIT", "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -3056,16 +3078,6 @@ "node": ">=0.10.0" } }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-includes": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", @@ -3199,28 +3211,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.reduce": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.7.tgz", - "integrity": "sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-array-method-boxes-properly": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", @@ -3751,44 +3741,6 @@ "yallist": "^2.1.2" } }, - "node_modules/bin-build/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "license": "MIT", - "optional": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-build/node_modules/tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==", - "license": "MIT", - "optional": true, - "dependencies": { - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-build/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "optional": true, - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/bin-build/node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", @@ -3852,19 +3804,6 @@ "yallist": "^2.1.2" } }, - "node_modules/bin-check/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "license": "MIT", - "optional": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/bin-check/node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", @@ -3911,51 +3850,6 @@ "semver": "bin/semver" } }, - "node_modules/bin-version/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "license": "MIT", - "optional": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/bin-version/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "license": "MIT", - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/bin-version/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "license": "MIT", - "optional": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/bin-wrapper": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-4.1.0.tgz", @@ -3974,6 +3868,16 @@ "node": ">=6" } }, + "node_modules/bin-wrapper/node_modules/@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, "node_modules/bin-wrapper/node_modules/download": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", @@ -4116,16 +4020,6 @@ "node": ">=4" } }, - "node_modules/bin-wrapper/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/bin-wrapper/node_modules/prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -4277,72 +4171,170 @@ "stream-throttle": "^0.1.3" } }, - "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/browser-sync-ui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" + "color-convert": "^2.0.1" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/bs-recipes": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", - "integrity": "sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==", - "license": "ISC" - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/browser-sync-ui/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "node_modules/browser-sync-ui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/browser-sync-ui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/browser-sync/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/browser-sync/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/browser-sync/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/browser-sync/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-recipes": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", + "integrity": "sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==", + "license": "ISC" + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "license": "MIT", "optional": true, "dependencies": { @@ -4471,28 +4463,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==", + "node_modules/callsites": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.2.0.tgz", + "integrity": "sha512-kfzR4zzQtAE9PC7CzZsjl3aBNbXWuXiSeOCdLcPpBfGW8YuCqQHcRPFDbr/BPVmd3EEPVpuFzLyuT/cUhPr4OQ==", "license": "MIT", - "optional": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "node": ">=12.20" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/caniuse-api": { @@ -4544,54 +4524,29 @@ } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/change-file-extension": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/change-file-extension/-/change-file-extension-0.1.1.tgz", + "integrity": "sha512-lB0j9teu8JtDPDHRfU8pNH33w4wMu5bOaKoT4PxH+AKugBrIfpiJMTTKIm0TErNeJPkeQEgvH31YpccTwOKPRg==", "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, "node_modules/chardet": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", @@ -4811,59 +4766,6 @@ "node": ">= 0.12.0" } }, - "node_modules/coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/coa/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "optional": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -5180,12 +5082,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/console-stream": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", - "integrity": "sha512-QC/8l9e6ofi6nqZ5PawlDgzmMw3OxIXtvolBzap/F4UDBJlDaZRSNbL/lb41C29FcbSJncBFlJFj2WJoNyZRfQ==", - "optional": true - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -5199,6 +5095,18 @@ "node": ">= 0.6" } }, + "node_modules/convert-hrtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-5.0.0.tgz", + "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -5275,36 +5183,6 @@ "node": ">=4.8" } }, - "node_modules/cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", - "deprecated": "cross-spawn no longer requires a build toolchain, use it instead", - "license": "MIT", - "optional": true, - "dependencies": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - } - }, - "node_modules/cross-spawn-async/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "license": "ISC", - "optional": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/cross-spawn-async/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "license": "ISC", - "optional": true - }, "node_modules/cross-spawn/node_modules/semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", @@ -5366,56 +5244,46 @@ } }, "node_modules/css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "license": "BSD-2-Clause", "optional": true, "dependencies": { "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "node_modules/css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", - "license": "MIT", - "optional": true - }, - "node_modules/css-select/node_modules/css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", - "license": "BSD-2-Clause", - "optional": true, - "engines": { - "node": ">= 6" + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" }, "funding": { "url": "https://github.com/sponsors/fb55" } }, - "node_modules/css-select/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "node_modules/css-select/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "license": "BSD-2-Clause", "optional": true, "dependencies": { - "boolbase": "~1.0.0" + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "license": "MIT", "optional": true, "dependencies": { - "mdn-data": "2.0.4", + "mdn-data": "2.0.14", "source-map": "^0.6.1" }, "engines": { @@ -5554,50 +5422,6 @@ "node": ">=8.0.0" } }, - "node_modules/csso/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "license": "CC0-1.0", - "optional": true - }, - "node_modules/csso/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", - "license": "MIT", - "optional": true, - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/d": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", @@ -5669,12 +5493,12 @@ } }, "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.3.tgz", + "integrity": "sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==", "license": "MIT", "engines": { - "node": "*" + "node": ">=12.20" } }, "node_modules/debug": { @@ -5714,16 +5538,6 @@ "ms": "^2.1.1" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decode-uri-component": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", @@ -5883,6 +5697,16 @@ "node": ">=0.10.0" } }, + "node_modules/decompress-unzip/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress/node_modules/make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -5906,6 +5730,16 @@ "node": ">=4" } }, + "node_modules/decompress/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -6135,14 +5969,34 @@ } }, "node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "license": "MIT", "optional": true, "dependencies": { "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/domelementtype": { @@ -6173,22 +6027,62 @@ } }, "node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "license": "BSD-2-Clause", "optional": true, "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/domutils/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "node_modules/domutils/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "license": "BSD-2-Clause", - "optional": true + "optional": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.2.tgz", + "integrity": "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^3.8.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/dotenv": { "version": "16.4.7", @@ -6360,6 +6254,18 @@ "node": ">= 4.0.0" } }, + "node_modules/easy-transform-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/easy-transform-stream/-/easy-transform-stream-1.0.1.tgz", + "integrity": "sha512-ktkaa6XR7COAR3oj02CF3IOgz2m1hCaY3SfzvKT4Svt2MhHw9XCt+ncJNWfe2TGz31iqzNGZ8spdKQflj+Rlog==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eazy-logger": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-4.0.1.tgz", @@ -6371,6 +6277,55 @@ "node": ">= 0.8.0" } }, + "node_modules/eazy-logger/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eazy-logger/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eazy-logger/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eazy-logger/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6525,6 +6480,18 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -6541,7 +6508,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -6608,16 +6575,9 @@ "engines": { "node": ">= 0.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "license": "MIT", - "optional": true + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/es-define-property": { "version": "1.0.1", @@ -7764,45 +7724,111 @@ } }, "node_modules/exec-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.0.0.tgz", - "integrity": "sha512-i9jNtQdbwQ+6AScOdzSbjYLlnvZu9XNyrC8m11neHwbEYdXz/QZWriul+KkZ5kIqy89Gx6FrMnZFD450RZ20FQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", + "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", "license": "MIT", "optional": true, "dependencies": { - "execa": "^0.3.0", - "pify": "^2.3.0", - "tempfile": "^1.0.0" + "execa": "^0.7.0", + "p-finally": "^1.0.0", + "pify": "^3.0.0", + "rimraf": "^2.5.4", + "tempfile": "^2.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/execa": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.3.0.tgz", - "integrity": "sha512-7evPG+NsML0PuUTKprHnSDKBZXfouIuSLcc5WqJxnKBVpLMwrOZNPssiZIUHE6S7mW2pD+aPuVg4MNUcnqIwnA==", + "node_modules/exec-buffer/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", "license": "MIT", "optional": true, "dependencies": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/exec-buffer/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" }, "engines": { - "node": ">=0.12" + "node": ">=4" + } + }, + "node_modules/exec-buffer/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "license": "ISC", + "optional": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/exec-buffer/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" } }, - "node_modules/execa/node_modules/path-key": { + "node_modules/exec-buffer/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC", + "optional": true + }, + "node_modules/execa": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "license": "MIT", "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/executable": { @@ -7818,6 +7844,16 @@ "node": ">=4" } }, + "node_modules/executable/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/exit-code": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/exit-code/-/exit-code-1.0.2.tgz", @@ -7944,6 +7980,15 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-equals": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", + "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -7996,23 +8041,19 @@ "peer": true }, "node_modules/fast-xml-parser": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz", - "integrity": "sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "optional": true, "dependencies": { - "strnum": "^1.0.5" + "strnum": "^1.1.1" }, "bin": { "fxparser": "src/cli/cli.js" @@ -8071,12 +8112,49 @@ } }, "node_modules/file-type": { - "version": "12.4.2", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz", - "integrity": "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-19.6.0.tgz", + "integrity": "sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ==", "license": "MIT", + "dependencies": { + "get-stream": "^9.0.1", + "strtok3": "^9.0.1", + "token-types": "^6.0.0", + "uint8array-extras": "^1.3.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/file-type/node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-type/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/filename-reserved-regex": { @@ -8437,6 +8515,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/function-timeout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/function-timeout/-/function-timeout-1.0.2.tgz", + "integrity": "sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/function.prototype.name": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", @@ -8552,128 +8642,235 @@ "node": ">= 0.4" } }, - "node_modules/get-proxy": { + "node_modules/get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "license": "MIT", + "optional": true, + "dependencies": { + "npm-conf": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gettext-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz", + "integrity": "sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==", + "license": "MIT", + "dependencies": { + "encoding": "^0.1.12", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/gifsicle": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-5.3.0.tgz", + "integrity": "sha512-FJTpgdj1Ow/FITB7SVza5HlzXa+/lqEY0tHQazAJbuAdvyJtkH4wIdsR2K414oaTwRXHFLLF+tYbipj+OpYg+Q==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bin-build": "^3.0.0", + "bin-wrapper": "^4.0.0", + "execa": "^5.0.0" + }, + "bin": { + "gifsicle": "cli.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/imagemin/gisicle-bin?sponsor=1" + } + }, + "node_modules/gifsicle/node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "optional": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/gifsicle/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/gifsicle/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gifsicle/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gifsicle/node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT", + "optional": true + }, + "node_modules/gifsicle/node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", - "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", "optional": true, - "dependencies": { - "npm-conf": "^1.1.0" - }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/get-stdin": { + "node_modules/gifsicle/node_modules/npm-run-path": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "license": "MIT", "optional": true, + "dependencies": { + "path-key": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "license": "MIT", - "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "node_modules/gifsicle/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", + "optional": true, "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gettext-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz", - "integrity": "sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==", - "license": "MIT", - "dependencies": { - "encoding": "^0.1.12", - "safe-buffer": "^5.1.1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gifsicle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-4.0.1.tgz", - "integrity": "sha512-A/kiCLfDdV+ERV/UB+2O41mifd+RxH8jlRG8DMxZO84Bma/Fw0htqZ+hY2iaalLRNyUu7tYZQslqUBJxBggxbg==", - "hasInstallScript": true, + "node_modules/gifsicle/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", "optional": true, - "dependencies": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "execa": "^1.0.0", - "logalot": "^2.0.0" - }, - "bin": { - "gifsicle": "cli.js" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/gifsicle/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "node_modules/gifsicle/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", "optional": true, "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/gifsicle/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "node_modules/gifsicle/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/gifsicle/node_modules/npm-run-path": { + "node_modules/gifsicle/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "license": "MIT", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "optional": true, "dependencies": { - "path-key": "^2.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">=4" + "node": ">= 8" } }, "node_modules/git-config-path": { @@ -8851,33 +9048,58 @@ } }, "node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "license": "MIT", "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", + "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", "license": "MIT", "engines": { "node": ">= 4" } }, + "node_modules/globby/node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globule": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", @@ -9095,6 +9317,37 @@ "node": ">=8" } }, + "node_modules/gulp-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/gulp-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/gulp-cli/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -9106,6 +9359,24 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/gulp-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/gulp-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/gulp-cli/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -9420,6 +9691,15 @@ "ajv": "^5.0.0" } }, + "node_modules/gulp-eslint/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/gulp-eslint/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -9686,6 +9966,18 @@ "node": ">=4" } }, + "node_modules/gulp-eslint/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/gulp-eslint/node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -9835,107 +10127,61 @@ "node": ">= 0.10.0" } }, - "node_modules/gulp-imagemin": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/gulp-imagemin/-/gulp-imagemin-6.2.0.tgz", - "integrity": "sha512-luHT+8kUz60KGzjJLUFzaPjl4b38UQLj8BJGkpJACRjiVEuzjohMOmLagkgXs+Rs4vYaUBr9tt1F/vLizaxgGg==", - "license": "MIT", - "dependencies": { - "chalk": "^2.4.1", - "fancy-log": "^1.3.2", - "imagemin": "^7.0.0", - "plugin-error": "^1.0.1", - "plur": "^3.0.1", - "pretty-bytes": "^5.3.0", - "through2-concurrent": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "imagemin-gifsicle": "^6.0.1", - "imagemin-jpegtran": "^6.0.0", - "imagemin-optipng": "^7.0.0", - "imagemin-svgo": "^7.0.0" - }, - "peerDependencies": { - "gulp": ">=4" - }, - "peerDependenciesMeta": { - "gulp": { - "optional": true - } - } - }, - "node_modules/gulp-imagemin/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-imagemin/node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "license": "MIT", - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-imagemin/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/gulp-imagemin": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/gulp-imagemin/-/gulp-imagemin-9.1.0.tgz", + "integrity": "sha512-PmzTWoNrVMYVN4ObRdHyt6oer4mqxV53IbCDi3Q8EHeDZW0OzAuh6RlOtpd/R7PFmbDUk64q5P+L04fD9I5cVA==", "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "gulp-plugin-extras": "^1.0.0", + "imagemin": "^9.0.0", + "plur": "^5.1.0", + "pretty-bytes": "^6.1.1" + }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + }, + "optionalDependencies": { + "imagemin-gifsicle": "^7.0.0", + "imagemin-mozjpeg": "^10.0.0", + "imagemin-optipng": "^8.0.0", + "imagemin-svgo": "^10.0.1" + }, + "peerDependencies": { + "gulp": ">=4" + }, + "peerDependenciesMeta": { + "gulp": { + "optional": true + } } }, "node_modules/gulp-imagemin/node_modules/irregular-plurals": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", - "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", + "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/gulp-imagemin/node_modules/plur": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", - "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", "license": "MIT", "dependencies": { - "irregular-plurals": "^2.0.0" + "irregular-plurals": "^3.3.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/gulp-imagemin/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/gulp-load-plugins": { @@ -10171,6 +10417,23 @@ "node": ">=4" } }, + "node_modules/gulp-plugin-extras": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-plugin-extras/-/gulp-plugin-extras-1.1.0.tgz", + "integrity": "sha512-T0AXOEVoKYzLIBlwEZ7LtAx2w4ExIozIoxVeYEVLFbdxI7i0sWvFDq0F8mm47djixDF3vAqDPoyGwh3Sg/PWtQ==", + "license": "MIT", + "dependencies": { + "@types/vinyl": "^2.0.12", + "chalk": "^5.3.0", + "easy-transform-stream": "^1.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gulp-postcss": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-10.0.0.tgz", @@ -10900,13 +11163,6 @@ "node": ">=0.10.0" } }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "license": "ISC", - "optional": true - }, "node_modules/http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", @@ -10953,6 +11209,16 @@ "node": ">=8.0.0" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -10965,6 +11231,21 @@ "node": ">=0.10.0" } }, + "node_modules/identifier-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/identifier-regex/-/identifier-regex-1.0.0.tgz", + "integrity": "sha512-Rcy5cjBOM9iTR+Vwy0Llyip9u0cA99T1yiWOhDW/+PDaTQhyski0tMovsipQ/FRNDkudjLWusJ/IMVIlG5WZnQ==", + "license": "MIT", + "dependencies": { + "reserved-identifiers": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -10995,92 +11276,305 @@ } }, "node_modules/imagemin": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-7.0.1.tgz", - "integrity": "sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-9.0.0.tgz", + "integrity": "sha512-oFlmioXTIrDCNYiKUVPjzUzm8M/7X74WEO6v8NFjn3ZtxjArdVJiRRdbPpq/OG4BdwaHMUz8ej9Fp4AcaDzMnA==", "license": "MIT", "dependencies": { - "file-type": "^12.0.0", - "globby": "^10.0.0", - "graceful-fs": "^4.2.2", - "junk": "^3.1.0", - "make-dir": "^3.0.0", - "p-pipe": "^3.0.0", - "replace-ext": "^1.0.0" + "change-file-extension": "^0.1.1", + "environment": "^1.0.0", + "file-type": "^19.0.0", + "globby": "^14.0.1", + "junk": "^4.0.1", + "ow": "^2.0.0", + "p-pipe": "^4.0.0", + "slash": "^5.1.0", + "uint8array-extras": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imagemin-gifsicle": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-6.0.1.tgz", - "integrity": "sha512-kuu47c6iKDQ6R9J10xCwL0lgs0+sMz3LRHqRcJ2CRBWdcNmo3T5hUaM8hSZfksptZXJLGKk8heSAvwtSdB1Fng==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-7.0.0.tgz", + "integrity": "sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA==", "license": "MIT", "optional": true, "dependencies": { - "exec-buffer": "^3.0.0", - "gifsicle": "^4.0.0", + "execa": "^1.0.0", + "gifsicle": "^5.0.0", "is-gif": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/imagemin/imagemin-gifsicle?sponsor=1" + } + }, + "node_modules/imagemin-mozjpeg": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/imagemin-mozjpeg/-/imagemin-mozjpeg-10.0.0.tgz", + "integrity": "sha512-DK85QNOjS3/GzWYfNB3CACMZD10sIQgFDv1+WTOnZljgltQTEyATjdyUVyjKu5q4sCESQdwvwq7WEZzJ5fFjlg==", + "license": "MIT", + "optional": true, + "dependencies": { + "execa": "^6.0.0", + "is-jpg": "^3.0.0", + "mozjpeg": "^8.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "optional": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/imagemin-jpegtran": { + "node_modules/imagemin-mozjpeg/node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT", + "optional": true + }, + "node_modules/imagemin-mozjpeg/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/onetime": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/imagemin-jpegtran/-/imagemin-jpegtran-6.0.0.tgz", - "integrity": "sha512-Ih+NgThzqYfEWv9t58EItncaaXIHR0u9RuhKa8CtVBlMBvY0dCIxgQJQCfwImA4AV1PMfmUKlkyIHJjb7V4z1g==", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "license": "MIT", "optional": true, "dependencies": { - "exec-buffer": "^3.0.0", - "is-jpg": "^2.0.0", - "jpegtran-bin": "^4.0.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "optional": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/imagemin-optipng": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-7.1.0.tgz", - "integrity": "sha512-JNORTZ6j6untH7e5gF4aWdhDCxe3ODsSLKs/f7Grewy3ebZpl1ZsU+VUTPY4rzeHgaFA8GSWOoA8V2M3OixWZQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-8.0.0.tgz", + "integrity": "sha512-CUGfhfwqlPjAC0rm8Fy+R2DJDBGjzy2SkfyT09L8rasnF9jSoHFqJ1xxSZWK6HVPZBMhGPMxCTL70OgTHlLF5A==", "license": "MIT", "optional": true, "dependencies": { "exec-buffer": "^3.0.0", "is-png": "^2.0.0", - "optipng-bin": "^6.0.0" + "optipng-bin": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/imagemin-svgo": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-7.1.0.tgz", - "integrity": "sha512-0JlIZNWP0Luasn1HT82uB9nU9aa+vUj6kpT+MjPW11LbprXC+iC4HDwn1r4Q2/91qj4iy9tRZNsFySMlEpLdpg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-10.0.1.tgz", + "integrity": "sha512-v27/UTGkb3vrm5jvjsMGQ2oxaDfSOTBfJOgmFO2fYepx05bY1IqWCK13aDytVR+l9w9eOlq0NMCLbxJlghYb2g==", "license": "MIT", "optional": true, "dependencies": { - "is-svg": "^4.2.1", - "svgo": "^1.3.2" + "is-svg": "^4.3.1", + "svgo": "^2.5.0" }, "engines": { - "node": ">=6" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sindresorhus/imagemin-svgo?sponsor=1" } }, - "node_modules/imagemin/node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "node_modules/imagemin/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/immutable": { @@ -11127,19 +11621,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==", - "license": "MIT", - "optional": true, - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -11228,6 +11709,22 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/inquirer/node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -11514,7 +12011,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/is-async-function": { @@ -11702,19 +12199,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -11777,6 +12261,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-identifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-identifier/-/is-identifier-1.0.1.tgz", + "integrity": "sha512-HQ5v4rEJ7REUV54bCd2l5FaD299SGDEn2UPoVXaTHAyGviLq2menVUD2udi3trQ32uvB6LdAh/0ck2EuizrtpA==", + "license": "MIT", + "dependencies": { + "identifier-regex": "^1.0.0", + "super-regex": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -11787,13 +12287,16 @@ } }, "node_modules/is-jpg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-2.0.0.tgz", - "integrity": "sha512-ODlO0ruzhkzD3sdynIainVP5eoOFNN85rxA1+cwwnPe4dKyX0r5+hxNO5XpCrxlHcmb9vkOit9mhRD2JVuimHg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-3.0.0.tgz", + "integrity": "sha512-Vcd67KWHZblEKEBrtP25qLZ8wN9ICoAhl1pKUqD7SM7hf2qtuRl7loDgP5Zigh2oN/+7uj+KVyC0eRJvgOEFeQ==", "license": "MIT", "optional": true, "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-map": { @@ -12137,13 +12640,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "license": "MIT", - "optional": true - }, "node_modules/is-valid-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", @@ -12320,25 +12816,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jpegtran-bin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jpegtran-bin/-/jpegtran-bin-4.0.0.tgz", - "integrity": "sha512-2cRl1ism+wJUoYAYFt6O/rLBfpXNWG2dUWbgcEkTt5WGMnqI46eEro8T4C5zGROxKRqyKpCBSdHPvt5UYCtxaQ==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "logalot": "^2.0.0" - }, - "bin": { - "jpegtran": "cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -12492,12 +12969,15 @@ } }, "node_modules/junk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", - "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz", + "integrity": "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/keyv": { @@ -12624,23 +13104,6 @@ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", - "license": "MIT", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -12881,44 +13344,55 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/logalot": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", - "integrity": "sha512-Ah4CgdSRfeCJagxQhcVNMi9BfGYyEKLa6d7OA6xSbld/Hg3Cf2QiOa1mDpmG7Ve8LOH6DN3mdttzjQAvWTyVkw==", + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", - "optional": true, "dependencies": { - "figures": "^1.3.5", - "squeak": "^1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/logalot/node_modules/figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", - "optional": true, "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==", + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", - "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -12931,20 +13405,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -12955,25 +13415,6 @@ "node": ">=0.10.0" } }, - "node_modules/lpad-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", - "integrity": "sha512-MMIcFmmR9zlGZtBcFOows6c2COMekHCIFJz3ew/rRpKZ1wR4mXDPzvcVqLarux8M33X4TPSq2Jdw8WJj0q0KbQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "get-stdin": "^4.0.1", - "indent-string": "^2.1.0", - "longest": "^1.0.0", - "meow": "^3.3.0" - }, - "bin": { - "lpad-align": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -13040,16 +13481,6 @@ "node": ">=0.10.0" } }, - "node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/map-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", @@ -13082,9 +13513,9 @@ } }, "node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "license": "CC0-1.0", "optional": true }, @@ -13120,28 +13551,6 @@ "node": ">=4.3.0 <5.0.0 || >=5.10" } }, - "node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==", - "license": "MIT", - "optional": true, - "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/merge": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", @@ -13280,6 +13689,24 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mozjpeg": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-8.0.0.tgz", + "integrity": "sha512-Ca2Yhah9hG0Iutgsn8MOrAl37P9ThnKsJatjXoWdUO+8X8GeG/6ahvHZrTyqvbs6leMww1SauWUCao/L9qBuFQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bin-build": "^3.0.0", + "bin-wrapper": "^4.0.0" + }, + "bin": { + "mozjpeg": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -13444,29 +13871,6 @@ "node": ">=0.4.0" } }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "license": "BSD-2-Clause", - "optional": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -13560,26 +13964,16 @@ } }, "node_modules/npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", "license": "MIT", "optional": true, "dependencies": { - "path-key": "^1.0.0" + "path-key": "^2.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, "node_modules/nth-check": { @@ -13700,28 +14094,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.8.tgz", - "integrity": "sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==", - "license": "MIT", - "optional": true, - "dependencies": { - "array.prototype.reduce": "^1.0.6", - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "gopd": "^1.0.1", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.groupby": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", @@ -13860,22 +14232,21 @@ } }, "node_modules/optipng-bin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-6.0.0.tgz", - "integrity": "sha512-95bB4y8IaTsa/8x6QH4bLUuyvyOoGBCLDA7wOgDL8UFqJpSUh1Hob8JRJhit+wC1ZLN3tQ7mFt7KuBj0x8F2Wg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-7.0.1.tgz", + "integrity": "sha512-W99mpdW7Nt2PpFiaO+74pkht7KEqkXkeRomdWXfEz3SALZ6hns81y/pm1dsGZ6ItUIfchiNIP6ORDr1zETU1jA==", "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "logalot": "^2.0.0" + "bin-wrapper": "^4.0.0" }, "bin": { "optipng": "cli.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/ora": { @@ -13910,15 +14281,46 @@ "node": ">=8" } }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/ora/node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/ora/node_modules/cli-cursor": { @@ -13933,6 +14335,24 @@ "node": ">=8" } }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/ora/node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -14027,6 +14447,26 @@ "node": ">=0.10.0" } }, + "node_modules/ow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-2.0.0.tgz", + "integrity": "sha512-ESUigmGrdhUZ2nQSFNkeKSl6ZRPupXzprMs3yF9DYlNVpJ8XAjM/fI9RUZxA7PI1K9HQDCCvBo1jr/GEIo9joQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^6.3.0", + "callsites": "^4.1.0", + "dot-prop": "^8.0.2", + "environment": "^1.0.0", + "fast-equals": "^5.0.1", + "is-identifier": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", @@ -14143,12 +14583,12 @@ } }, "node_modules/p-pipe": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-3.1.0.tgz", - "integrity": "sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-4.0.0.tgz", + "integrity": "sha512-HkPfFklpZQPUKBFXzKFB6ihLriIHxnmuQdK9WmLDwe4hf2PdhhfWT/FJa+pc3bA1ywvKXtedxIRmd4Y7BTXE4w==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -14247,19 +14687,6 @@ "node": ">= 0.10" } }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -14362,6 +14789,19 @@ "node": ">=8" } }, + "node_modules/peek-readable": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.4.2.tgz", + "integrity": "sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -14394,13 +14834,13 @@ } }, "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/pinkie": { @@ -14521,16 +14961,6 @@ "node": ">=4" } }, - "node_modules/pkg-conf/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/pkg-conf/node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -15342,12 +15772,12 @@ } }, "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", "license": "MIT", "engines": { - "node": ">=6" + "node": "^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -15424,18 +15854,6 @@ "node": ">=6" } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, "node_modules/query-string": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", @@ -15523,77 +15941,6 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", - "license": "MIT", - "optional": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", - "license": "MIT", - "optional": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", - "license": "MIT", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -15667,20 +16014,6 @@ "node": ">= 0.10" } }, - "node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==", - "license": "MIT", - "optional": true, - "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -15818,19 +16151,6 @@ "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", "license": "ISC" }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==", - "license": "MIT", - "optional": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", @@ -15935,6 +16255,18 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, + "node_modules/reserved-identifiers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reserved-identifiers/-/reserved-identifiers-1.0.0.tgz", + "integrity": "sha512-h0bP2Katmvf3hv4Z3WtDl4+6xt/OglQ2Xa6TnhZ/Rm9/7IH1crXQqMwD4J2ngKBonVv+fB55zfGgNDAmsevLVQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -16750,13 +17082,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "license": "ISC", - "optional": true - }, "node_modules/schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", @@ -17489,131 +17814,20 @@ "license": "MIT" }, "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "license": "CC-BY-3.0", - "optional": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", - "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", - "license": "CC0-1.0", - "optional": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause" - }, - "node_modules/squeak": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", - "integrity": "sha512-YQL1ulInM+ev8nXX7vfXsCsDh6IqXlrremc1hzi77776BtpWgYJUMto3UM05GSAaGzJgWekszjoKDrVNB5XG+A==", - "license": "MIT", - "optional": true, - "dependencies": { - "chalk": "^1.0.0", - "console-stream": "^0.1.1", - "lpad-align": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/squeak/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", "license": "MIT", - "optional": true, "engines": { - "node": ">=0.8.0" + "node": ">= 0.10" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -17726,6 +17940,22 @@ "node": ">=8" } }, + "node_modules/standard/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/standard/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -17733,6 +17963,43 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/standard/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/standard/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/standard/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/standard/node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -18424,6 +18691,27 @@ "node": ">=4" } }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -18547,28 +18835,18 @@ } }, "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", - "license": "MIT", - "optional": true, - "dependencies": { - "is-utf8": "^0.2.0" + "node": ">=12" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-bom-string": { @@ -18600,20 +18878,14 @@ "node": ">=0.10.0" } }, - "node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "license": "MIT", "optional": true, - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/strip-json-comments": { @@ -18642,12 +18914,35 @@ } }, "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "license": "MIT", "optional": true }, + "node_modules/strtok3": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-9.1.1.tgz", + "integrity": "sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.3.1" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/stylehacks": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.4.tgz", @@ -18677,6 +18972,22 @@ "node": ">=4" } }, + "node_modules/super-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/super-regex/-/super-regex-1.0.0.tgz", + "integrity": "sha512-CY8u7DtbvucKuquCmOFEKhr9Besln7n9uN8eFbwcoGYWXOMW07u2o8njWaiXt11ylS3qoGF55pILjRmPlbodyg==", + "license": "MIT", + "dependencies": { + "function-timeout": "^1.0.1", + "time-span": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -18721,70 +19032,35 @@ } }, "node_modules/svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "license": "MIT", "optional": true, "dependencies": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" }, "bin": { "svgo": "bin/svgo" }, "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/svgo/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4" + "node": ">=10.13.0" } }, - "node_modules/svgo/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "license": "MIT", "optional": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 10" } }, "node_modules/table": { @@ -18892,26 +19168,29 @@ } }, "node_modules/tempfile": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", - "integrity": "sha512-NjT12fW6pSEKz1eVcADgaKfeM+XZ4+zSaqVz46XH7+CiEwcelnwtGWRRjF1p+xyW2PVgKKKS2UUw1LzRelntxg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==", "license": "MIT", "optional": true, "dependencies": { - "os-tmpdir": "^1.0.0", - "uuid": "^2.0.1" + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, "node_modules/tempfile/node_modules/uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "license": "MIT", - "optional": true + "optional": true, + "bin": { + "uuid": "bin/uuid" + } }, "node_modules/ternary-stream": { "version": "2.1.1", @@ -19120,15 +19399,6 @@ "xtend": "~4.0.1" } }, - "node_modules/through2-concurrent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-concurrent/-/through2-concurrent-2.0.0.tgz", - "integrity": "sha512-R5/jLkfMvdmDD+seLwN7vB+mhbqzWop5fAjx5IX8/yQq7VhBhzDmhXgaHAOnhnWkCpRMM7gToYHycB0CS/pd+A==", - "license": "MIT", - "dependencies": { - "through2": "^2.0.0" - } - }, "node_modules/tildify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", @@ -19142,6 +19412,21 @@ "node": ">=0.10.0" } }, + "node_modules/time-span": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz", + "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==", + "license": "MIT", + "dependencies": { + "convert-hrtime": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", @@ -19226,14 +19511,21 @@ "node": ">=0.6" } }, - "node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==", + "node_modules/token-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.0.tgz", + "integrity": "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==", "license": "MIT", - "optional": true, + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, "node_modules/trim-repeated": { @@ -19449,6 +19741,18 @@ "node": ">=0.8.0" } }, + "node_modules/uint8array-extras": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", + "integrity": "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -19606,6 +19910,18 @@ "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -19630,13 +19946,6 @@ "node": ">= 0.8" } }, - "node_modules/unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==", - "license": "MIT", - "optional": true - }, "node_modules/update-browserslist-db": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", @@ -19733,22 +20042,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "license": "MIT", - "optional": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/util/node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -19788,17 +20081,6 @@ "node": ">= 10.13.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "node_modules/value-or-function": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", diff --git a/package.json b/package.json index 043c797..f080a88 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "homepage": "https://www.skyverge.com/", "license": "GPL-3.0", "description": "SkyVerge WP/WC plugin build & deploy tool, a.k.a SkyMake", + "type": "module", "repository": { "type": "git", "url": "https://github.com/skyverge/sake.git" @@ -30,10 +31,10 @@ "axios": "^1.7.9", "babel-loader": "^8.0.6", "browser-sync": "^3.0.3", - "chalk": "^4.0.0", + "chalk": "^5.4.1", "codename": "0.0.6", "cssnano": "^7.0.6", - "dateformat": "^4.6.3", + "dateformat": "^5.0.3", "del": "^6.1.1", "dotenv": "^16.4.7", "dottie": "^2.0.6", @@ -48,8 +49,8 @@ "gulp-eslint": "^4.0.2", "gulp-filter": "^5.1.0", "gulp-if": "^2.0.2", - "gulp-imagemin": "^6.2.0", - "gulp-load-plugins": "^2.0.7", + "gulp-imagemin": "^9.1.0", + "gulp-load-plugins": "^2.0.8", "gulp-phplint": "^0.9.0", "gulp-postcss": "^10.0.0", "gulp-rename": "^1.4.0", @@ -73,7 +74,7 @@ "sass": "^1.83.4", "semver": "^7.7.1", "shelljs": "^0.8.5", - "strip-ansi": "^4.0.0", + "strip-ansi": "^7.1.0", "underscore.string": "^3.3.4", "undertaker-forward-reference": "^1.0.2", "webpack-stream": "^7.0.0" diff --git a/pipes/replace.js b/pipes/replace.js index 839d972..29f6b4b 100644 --- a/pipes/replace.js +++ b/pipes/replace.js @@ -1,47 +1,52 @@ -const lazypipe = require('lazypipe') - -// these pipes are not meant to be reusable - rather, they existy so that the bump:minreqs task would -// be easier to maintain without wrapping each individual replacement in gulp-if -module.exports = (plugins, sake) => { - const pipes = {} - - // replace minimum PHP version - pipes.minimum_php_version = lazypipe() - .pipe(plugins.replace, /MINIMUM_PHP_VERSION = .*\n/, `MINIMUM_PHP_VERSION = '${sake.options.minimum_php_version}';\n`) - - // replace minimum WP version - pipes.minimum_wp_version = lazypipe() - .pipe(plugins.replace, /('minimum_wp_version'[\s]*=>[\s]*)'([^']*)'/, (match, m) => `${m}'${sake.options.minimum_wp_version}'`) - .pipe(plugins.replace, /Requires at least: .*/, () => `Requires at least: ${sake.options.minimum_wp_version}`) - .pipe(plugins.replace, /MINIMUM_WP_VERSION = .*\n/, () => `MINIMUM_WP_VERSION = '${sake.options.minimum_wp_version}';\n`) - - // replace tested up to WP version - pipes.tested_up_to_wp_version = lazypipe() - .pipe(plugins.replace, /Tested up to: .*/, () => `Tested up to: ${sake.options.tested_up_to_wp_version}`) - - // replace minimum WC version - pipes.minimum_wc_version = lazypipe() - .pipe(plugins.replace, /('minimum_wc_version'[\s]*=>[\s]*)'([^']*)'/, (match, m) => `${m}'${sake.options.minimum_wc_version}'`) - .pipe(plugins.replace, /WC requires at least: .*/, () => `WC requires at least: ${sake.options.minimum_wc_version}`) - .pipe(plugins.replace, /MINIMUM_WC_VERSION = .*\n/, () => `MINIMUM_WC_VERSION = '${sake.options.minimum_wc_version}';\n`) - - // replace tested up to WC version - pipes.tested_up_to_wc_version = lazypipe() - .pipe(plugins.replace, /WC tested up to: .*/, () => `WC tested up to: ${sake.options.tested_up_to_wc_version}`) - - // replace FW version - pipes.framework_version = lazypipe() - .pipe(plugins.replace, /SkyVerge\\WooCommerce\\PluginFramework\\v[0-9]+_[0-9]+_[0-9]+/g, (match) => 'SkyVerge\\WooCommerce\\PluginFramework\\v' + sake.options.framework_version.replace(/\./g, '_')) - .pipe(plugins.replace, /SkyVerge\\\\WooCommerce\\\\PluginFramework\\\\v[0-9]+_[0-9]+_[0-9]+/g, (match) => 'SkyVerge\\\\WooCommerce\\\\PluginFramework\\\\v' + sake.options.framework_version.replace(/\./g, '_')) - - // replace FW version v4 and v5 - pipes.framework_version = lazypipe() - .pipe(plugins.replace, /SV_WC_Framework_Bootstrap::instance\(\)->register_plugin\( '([^']*)'/, () => `SV_WC_Framework_Bootstrap::instance()->register_plugin( '${sake.options.framework_version}'`) - .pipe(plugins.replace, /FRAMEWORK_VERSION = .*\n/, () => `FRAMEWORK_VERSION = '${sake.options.framework_version}';\n`) - - // replace FW backwards compatibility - pipes.backwards_compatible = lazypipe() - .pipe(plugins.replace, /('backwards_compatible'[\s]*=>[\s]*)'([^']*)'/, (match, m) => `${m}'${sake.options.backwards_compatible}'`) - - return pipes -} +import lazypipe from 'lazypipe'; +import replace from 'gulp-replace'; +import sake from '../lib/sake.js' + +/** + * Replaces the minimum PHP version + */ +export const replaceMinimumPhpVersion = lazypipe() + .pipe(replace, /MINIMUM_PHP_VERSION = .*\n/, `MINIMUM_PHP_VERSION = '${sake.options.minimum_php_version}';\n`) + +/** + * Replaces the minimum WP version + */ +export const replaceMinimumWpVersion = lazypipe() + .pipe(replace, /('minimum_wp_version'[\s]*=>[\s]*)'([^']*)'/, (match, m) => `${m}'${sake.options.minimum_wp_version}'`) + .pipe(replace, /Requires at least: .*/, () => `Requires at least: ${sake.options.minimum_wp_version}`) + .pipe(replace, /MINIMUM_WP_VERSION = .*\n/, () => `MINIMUM_WP_VERSION = '${sake.options.minimum_wp_version}';\n`) + +/** + * Replaces the tested-up-to WP version + */ +export const replaceTestedUptoWpVersion = lazypipe() + .pipe(replace, /Tested up to: .*/, () => `Tested up to: ${sake.options.tested_up_to_wp_version}`) + +/** + * Replaces the minimum WooCommerce version + */ +export const replaceMinimumWcVersion = lazypipe() + .pipe(replace, /('minimum_wc_version'[\s]*=>[\s]*)'([^']*)'/, (match, m) => `${m}'${sake.options.minimum_wc_version}'`) + .pipe(replace, /WC requires at least: .*/, () => `WC requires at least: ${sake.options.minimum_wc_version}`) + .pipe(replace, /MINIMUM_WC_VERSION = .*\n/, () => `MINIMUM_WC_VERSION = '${sake.options.minimum_wc_version}';\n`) + +/** + * Replaces the tested-up-to WooCommerce version + */ +export const replaceTestedUpToWcVersion = lazypipe() + .pipe(replace, /WC tested up to: .*/, () => `WC tested up to: ${sake.options.tested_up_to_wc_version}`) + +/** + * Replaces the framework version + */ +export const replaceFrameworkVersion = lazypipe() + .pipe(replace, /SkyVerge\\WooCommerce\\PluginFramework\\v[0-9]+_[0-9]+_[0-9]+/g, (match) => 'SkyVerge\\WooCommerce\\PluginFramework\\v' + sake.options.framework_version.replace(/\./g, '_')) + .pipe(replace, /SkyVerge\\\\WooCommerce\\\\PluginFramework\\\\v[0-9]+_[0-9]+_[0-9]+/g, (match) => 'SkyVerge\\\\WooCommerce\\\\PluginFramework\\\\v' + sake.options.framework_version.replace(/\./g, '_')) + .pipe(replace, /SV_WC_Framework_Bootstrap::instance\(\)->register_plugin\( '([^']*)'/, () => `SV_WC_Framework_Bootstrap::instance()->register_plugin( '${sake.options.framework_version}'`) + .pipe(replace, /FRAMEWORK_VERSION = .*\n/, () => `FRAMEWORK_VERSION = '${sake.options.framework_version}';\n`) + +/** + * Replaces the framework backwards compatible version + */ +export const replaceBackwardsCompatibleVersion = lazypipe() + .pipe(replace, /('backwards_compatible'[\s]*=>[\s]*)'([^']*)'/, (match, m) => `${m}'${sake.options.backwards_compatible}'`) diff --git a/pipes/scripts.js b/pipes/scripts.js index 9586fc4..bc36f1a 100644 --- a/pipes/scripts.js +++ b/pipes/scripts.js @@ -1,6 +1,14 @@ -const lazypipe = require('lazypipe') +import lazypipe from 'lazypipe'; +import babel from 'gulp-babel' +import gulpif from 'gulp-if' +import uglify from 'gulp-uglify' +import rename from 'gulp-rename' +import sourcemaps from 'gulp-sourcemaps' +import sake from '../lib/sake.js' +import { createRequire } from 'node:module'; +const require = createRequire(import.meta.url); -module.exports = (plugins, sake) => { +export function scriptPipes() { const pipes = {} // transpile, minify and write sourcemaps @@ -10,16 +18,16 @@ module.exports = (plugins, sake) => { // 3. We need to tell Babel to find the preset from this project, not from the current working directory, // see https://github.com/babel/babel-loader/issues/299#issuecomment-259713477. pipes.compileJs = lazypipe() - .pipe(plugins.babel, { presets: ['@babel/preset-env', '@babel/preset-react'].map(require.resolve) }) + .pipe(babel, { presets: ['@babel/preset-env', '@babel/preset-react'].map(require.resolve) }) .pipe(() => { // see https://github.com/OverZealous/lazypipe#using-with-more-complex-function-arguments-such-as-gulp-if - return plugins.if(sake.options.minify, plugins.uglify()) + return gulpif(sake.options.minify, uglify()) }) - .pipe(plugins.rename, { suffix: '.min' }) + .pipe(rename, { suffix: '.min' }) // ensure admin/ and frontend/ are removed from the source paths // see https://www.npmjs.com/package/gulp-sourcemaps#alter-sources-property-on-sourcemaps - .pipe(plugins.sourcemaps.mapSources, (sourcePath) => '../' + sourcePath) - .pipe(plugins.sourcemaps.write, '.', { includeContent: false }) + .pipe(sourcemaps.mapSources, (sourcePath) => '../' + sourcePath) + .pipe(sourcemaps.write, '.', { includeContent: false }) return pipes } diff --git a/tasks/build.js b/tasks/build.js index cf3ddac..81de017 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -1,16 +1,29 @@ -const _ = require('lodash') +import _ from 'lodash'; +import gulp from 'gulp' +import sake from '../lib/sake.js' +import { cleanBuildTask, cleanComposerTask } from './clean.js' +import { shellComposerInstallTask, shellComposerStatusTask } from './shell.js' +import { compile } from './compile.js' +import { copyBuildTask } from './copy.js' +import { bundleTask } from './bundle.js' -module.exports = (gulp, plugins, sake) => { - // main task for building the plugin: - // - cleans the build directory - // - compiles the plugin assets (linting where necessary) - // - bundles any external dependencies to the plugin assets - // - copies plugin files to the build directory - let tasks = ['clean:build', 'shell:composer_status', 'clean:composer', 'shell:composer_install', 'compile', 'bundle', 'copy:build'] +/** + * The main task for building the plugin: + * - Cleans the build directory + * - Compiles the plugin assets (linting where necessary) + * - Bundles any external dependencies to the plugin assets + * - Copies plugin files to the build directory + */ - if (sake.options['skip-composer']) { - tasks = _.without(tasks, 'shell:composer_status', 'clean:composer', 'shell:composer_install') - } +let tasks = [cleanBuildTask, shellComposerStatusTask, cleanComposerTask, shellComposerInstallTask, compile, bundleTask, copyBuildTask] - gulp.task('build', gulp.series(tasks)) +if (sake.options['skip-composer']) { + tasks = _.without(tasks, shellComposerStatusTask, cleanComposerTask, shellComposerInstallTask) +} + +const buildTask = gulp.series(tasks) +buildTask.displayName = 'build' + +export { + buildTask } diff --git a/tasks/bump.js b/tasks/bump.js index 8f706db..342e1c2 100644 --- a/tasks/bump.js +++ b/tasks/bump.js @@ -1,52 +1,69 @@ -module.exports = (gulp, plugins, sake) => { - const pipes = require('../pipes/replace.js')(plugins, sake) +import gulp from 'gulp' +import gulpif from 'gulp-if' +import replace from 'gulp-replace' +import * as sakeReplace from '../pipes/replace.js' +import sake from '../lib/sake.js' - // bumps the version in the main plugin file to match changelog.txt - gulp.task('bump', () => { - let pluginFiles = [`${sake.config.paths.src}/${sake.config.plugin.mainFile}`] +/** + * Bumps the version in the main plugin file to match changelog.txt + */ +const bumpTask = (done) => { + let pluginFiles = [`${sake.config.paths.src}/${sake.config.plugin.mainFile}`] - // also include the main Plugin class file - if (sake.config.framework === 'v5') { - pluginFiles.push(`${sake.config.paths.src}/includes/Plugin.php`) - } + // also include the main Plugin class file + if (sake.config.framework === 'v5') { + pluginFiles.push(`${sake.config.paths.src}/includes/Plugin.php`) + } - return gulp.src(pluginFiles, { base: sake.config.paths.src, allowEmpty: true }) - .pipe(plugins.replace(/ \* Version: [0-9]*.[0-9]*.[0-9]*(-[a-z]+.[0-9]+)*\n/, () => ' * Version: ' + sake.getPluginVersion() + '\n')) - .pipe(plugins.replace(/const VERSION = '[0-9]*.[0-9]*.[0-9]*(-[a-z]+.[0-9]+)*';/, () => "const VERSION = '" + sake.getPluginVersion() + "';")) - .pipe(gulp.dest(sake.config.paths.src)) - }) + return gulp.src(pluginFiles, { base: sake.config.paths.src, allowEmpty: true }) + .pipe(replace(/ \* Version: [0-9]*.[0-9]*.[0-9]*(-[a-z]+.[0-9]+)*\n/, () => ' * Version: ' + sake.getPluginVersion() + '\n')) + .pipe(replace(/const VERSION = '[0-9]*.[0-9]*.[0-9]*(-[a-z]+.[0-9]+)*';/, () => "const VERSION = '" + sake.getPluginVersion() + "';")) + .pipe(gulp.dest(sake.config.paths.src)) +} +bumpTask.displayName = 'bump' - // bumps the minimum requirements for the plugin - gulp.task('bump:minreqs', () => { - // helper to determine if a number is an integer - let isInt = (n) => { - return n % 1 === 0 - } +/** + * Bumps the minimum requirements for the plugin. + */ +const bumpMinReqsTask = (done) => { + // helper to determine if a number is an integer + let isInt = (n) => { + return n % 1 === 0 + } - // semver-ify versions passed in as integers - ['minimum_wp_version', 'tested_up_to_wp_version', 'minimum_wc_version', 'tested_up_to_wc_version', 'framework_version', 'backwards_compatible'].forEach((option) => { - if (sake.options[option] && isInt(sake.options[option])) { - sake.options[option] = parseFloat(sake.options[option]).toFixed(1) - } - }) - - return gulp.src([`${sake.config.paths.src}/${sake.config.plugin.mainFile}`, `${sake.config.paths.src}/readme.txt`]) - // note the need to cast the version optiosn to boolean, as passing a string version, - // such as '4.4.0' will not evaluate to true in gulp-if - .pipe(plugins.if(Boolean(sake.options.minimum_php_version), pipes.minimum_php_version())) - .pipe(plugins.if(Boolean(sake.options.minimum_wp_version), pipes.minimum_wp_version())) - .pipe(plugins.if(Boolean(sake.options.tested_up_to_wp_version), pipes.tested_up_to_wp_version())) - .pipe(plugins.if(Boolean(sake.options.minimum_wc_version), pipes.minimum_wc_version())) - .pipe(plugins.if(Boolean(sake.options.tested_up_to_wc_version), pipes.tested_up_to_wc_version())) - .pipe(plugins.if(Boolean(sake.options.framework_version), pipes.framework_version())) - .pipe(plugins.if(Boolean(sake.options.backwards_compatible && sake.config.framework === 'v4'), pipes.backwards_compatible())) - .pipe(gulp.dest(sake.config.paths.src)) + // semver-ify versions passed in as integers + ['minimum_wp_version', 'tested_up_to_wp_version', 'minimum_wc_version', 'tested_up_to_wc_version', 'framework_version', 'backwards_compatible'].forEach((option) => { + if (sake.options[option] && isInt(sake.options[option])) { + sake.options[option] = parseFloat(sake.options[option]).toFixed(1) + } }) - // bumps the v5 framework version in plugin files - gulp.task('bump:framework_version', () => { - return gulp.src([`${sake.config.paths.src}/**/*.php`, `!${sake.config.paths.src}/${sake.config.paths.framework.base}`]) - .pipe(plugins.if(Boolean(sake.options.framework_version), pipes.framework_version())) - .pipe(gulp.dest(sake.config.paths.src)) - }) + return gulp.src([`${sake.config.paths.src}/${sake.config.plugin.mainFile}`, `${sake.config.paths.src}/readme.txt`]) + // note the need to cast the version options to boolean, as passing a string version, + // such as '4.4.0' will not evaluate to true in gulp-if + .pipe(gulpif(Boolean(sake.options.minimum_php_version), sakeReplace.replaceMinimumPhpVersion())) + .pipe(gulpif(Boolean(sake.options.minimum_wp_version), sakeReplace.replaceMinimumWpVersion())) + .pipe(gulpif(Boolean(sake.options.tested_up_to_wp_version), sakeReplace.replaceTestedUptoWpVersion())) + .pipe(gulpif(Boolean(sake.options.minimum_wc_version), sakeReplace.replaceMinimumWcVersion())) + .pipe(gulpif(Boolean(sake.options.tested_up_to_wc_version), sakeReplace.replaceTestedUpToWcVersion())) + .pipe(gulpif(Boolean(sake.options.framework_version), sakeReplace.replaceFrameworkVersion())) + .pipe(gulpif(Boolean(sake.options.backwards_compatible && sake.config.framework === 'v4'), sakeReplace.replaceBackwardsCompatibleVersion())) + .pipe(gulp.dest(sake.config.paths.src)) +} +bumpMinReqsTask.displayName = 'bump:minreqs' + +/** + * Bumps the v5 framework version in plugin files + */ +const bumpFrameworkVersionTask = (done) => { + return gulp.src([`${sake.config.paths.src}/**/*.php`, `!${sake.config.paths.src}/${sake.config.paths.framework.base}`]) + .pipe(gulpif(Boolean(sake.options.framework_version), sakeReplace.replaceFrameworkVersion())) + .pipe(gulp.dest(sake.config.paths.src)) +} +bumpFrameworkVersionTask.displayName = 'bump:framework_version' + +export { + bumpTask, + bumpMinReqsTask, + bumpFrameworkVersionTask } diff --git a/tasks/bundle.js b/tasks/bundle.js index eed919e..2db61dd 100644 --- a/tasks/bundle.js +++ b/tasks/bundle.js @@ -1,85 +1,91 @@ -const log = require('fancy-log') -const fs = require('fs') -const path = require('path') -const shell = require('shelljs') +import log from 'fancy-log' +import fs from 'node:fs' +import path from 'node:path' +import shell from 'shelljs' +import sake from '../lib/sake.js' +import gulp from 'gulp' + +const processBundle = (bundleType, bundleArray, done) => { + // bail if no items to bundle + if (!bundleArray || !Array.isArray(bundleArray) || bundleArray.length === 0) { + log.info(`No external ${bundleType} to bundle.`) + done() + return + } + + log.info(`Bundling ${bundleType} dependencies.`) -module.exports = (gulp, plugins, sake) => { + // loop through each item and copy it over the designated destination folder in the local plugin file path + bundleArray.forEach((item) => { + const { source: packageName, file, destination } = item - gulp.task('bundle', (done) => { - let tasks = ['bundle:scripts', 'bundle:styles'] + // fetch the package name from node_modules + const packagePath = path.join('node_modules', packageName) - if (sake?.config?.bundle) { - // if there are items to bundle, make sure the dependencies are installed, or bail on error - log.info('Installing external dependencies...') + // check if the package exists + if (!fs.existsSync(packagePath)) { + sake.throwError(`Package '${packageName}' not found in node_modules.`) + done(`Package '${packageName}' not found in node_modules.`) + return + } - let npmInstall = shell.exec('npm install') + // copy the specified file to the destination path + const destinationFolder = path.join(destination) + const sourceFilePath = path.join(packagePath, file) + const destinationFilePath = path.join(destination, file) - if (npmInstall.code !== 0) { - sake.throwError(`Error during npm install: ${result.stderr ?? 'unknown error.'}`) - done(result.stderr) + try { + // create folder if it does not exist + if (!fs.existsSync(destinationFolder)) { + fs.mkdirSync(destinationFolder, { recursive: true }) + log.info(`Created destination folder for '${file}: '${destinationFolder}'.`) } - } - gulp.parallel(tasks)(done) + // copy into destination folder + fs.copyFileSync(sourceFilePath, destinationFilePath) + log.info(`Bundled '${file}' from '${packageName}' to '${destination}'.`) + } catch (error) { + sake.throwError(`Error copying '${file}' from '${sourceFilePath}' to '${destinationFilePath}': ${error.message ?? 'unknown error.'}`) + done(error) + } }) - const processBundle = (bundleType, bundleArray, done) => { - // bail if no items to bundle - if (!bundleArray || !Array.isArray(bundleArray) || bundleArray.length === 0) { - log.info(`No external ${bundleType} to bundle.`) - done() - return - } + done() +} - log.info(`Bundling ${bundleType} dependencies.`) +const bundleScriptsTask = (done) => { + const bundle = sake?.config?.bundle + processBundle('scripts', bundle?.scripts, done) +} +bundleScriptsTask.displayName = 'bundle:scripts' - // loop through each item and copy it over the designated destination folder in the local plugin file path - bundleArray.forEach((item) => { - const { source: packageName, file, destination } = item +const bundleStylesTask = (done) => { + const bundle = sake?.config?.bundle + processBundle('styles', bundle?.styles, done) +} +bundleStylesTask.displayName = 'bundle:styles' - // fetch the package name from node_modules - const packagePath = path.join('node_modules', packageName) +const bundleTask = (done) => { + let tasks = [bundleScriptsTask, bundleStylesTask] - // check if the package exists - if (!fs.existsSync(packagePath)) { - sake.throwError(`Package '${packageName}' not found in node_modules.`) - done(`Package '${packageName}' not found in node_modules.`) - return - } + if (sake?.config?.bundle) { + // if there are items to bundle, make sure the dependencies are installed, or bail on error + log.info('Installing external dependencies...') - // copy the specified file to the destination path - const destinationFolder = path.join(destination) - const sourceFilePath = path.join(packagePath, file) - const destinationFilePath = path.join(destination, file) - - try { - // create folder if it does not exist - if (!fs.existsSync(destinationFolder)) { - fs.mkdirSync(destinationFolder, { recursive: true }) - log.info(`Created destination folder for '${file}: '${destinationFolder}'.`) - } - - // copy into destination folder - fs.copyFileSync(sourceFilePath, destinationFilePath) - log.info(`Bundled '${file}' from '${packageName}' to '${destination}'.`) - } catch (error) { - sake.throwError(`Error copying '${file}' from '${sourceFilePath}' to '${destinationFilePath}': ${error.message ?? 'unknown error.'}`) - done(error) - } - }) + let npmInstall = shell.exec('npm install') - done() + if (npmInstall.code !== 0) { + sake.throwError(`Error during npm install: ${npmInstall.stderr ?? 'unknown error.'}`) + done(npmInstall.stderr) + } } - gulp.task('bundle:scripts', (done) => { - const bundle = sake?.config?.bundle - const scripts = bundle?.scripts - processBundle('scripts', scripts, done) - }) + gulp.parallel(tasks)(done) +} +bundleTask.displayName = 'bundle' - gulp.task('bundle:styles', (done) => { - const bundle = sake?.config?.bundle - const styles = bundle?.styles - processBundle('styles', styles, done) - }) +export { + bundleScriptsTask, + bundleStylesTask, + bundleTask } diff --git a/tasks/clean.js b/tasks/clean.js index 474972c..8ff23a8 100644 --- a/tasks/clean.js +++ b/tasks/clean.js @@ -1,66 +1,94 @@ -const path = require('path') -const del = require('del') +import path from 'node:path'; +import del from 'del'; +import sake from '../lib/sake.js' -module.exports = (gulp, plugins, sake) => { - let defaultOptions = { read: false, allowEmpty: true } +/** + * Clean dev directory from map files + */ +const cleanDevTask = (done) => { + return del([ + `${sake.config.paths.src}/${sake.config.paths.assets}/**/*.map` + ]) +} +cleanDevTask.displayName = 'clean:dev' - // clean dev dir from map files - gulp.task('clean:dev', () => { - return del([ - `${sake.config.paths.src}/${sake.config.paths.assets}/**/*.map` - ]) - }) +/** + * Clean composer packages + */ +const cleanComposerTask = (done) => { + return del([ + `${sake.config.paths.vendor}` + ]) +} +cleanComposerTask.displayName = 'clean:composer' - // clean composer packages - gulp.task('clean:composer', () => { - return del([ - `${sake.config.paths.vendor}` - ]) - }) +/** + * Clean/empty the build directory + */ +const cleanBuildTask = (done) => { + return del([ + `${sake.config.paths.build}/${sake.config.plugin.id}`, + `${sake.config.paths.build}/${sake.config.plugin.id}.*.zip` + ]) +} +cleanBuildTask.displayName = 'clean:build' - // clean (empty) build dir - gulp.task('clean:build', () => { - return del([ - `${sake.config.paths.build}/${sake.config.plugin.id}`, - `${sake.config.paths.build}/${sake.config.plugin.id}.*.zip` - ]) +/** + * Clean the WooCommerce repo directory + * This will automatically exclude any dotfiles, such as the .git directory + */ +const cleanWcRepoTask = (done) => { + return del([ + sake.getProductionRepoPath() + '**/*' + ], { + force: true // required to allow deleting outside of current working directory }) +} +cleanWcRepoTask.displayName = 'clean:wc_repo' - // clean WooCommerce repo dir - gulp.task('clean:wc_repo', () => { - // this will automatically exclude any dotfiles, such as the .git directory - return del([ - sake.getProductionRepoPath() + '**/*' - ], { - force: true // required to allow deleting outside of current working directory - }) +/** + * Delete prerelease + */ +const cleanPrereleaseTask = (done) => { + return del([ + sake.getPrereleasesPath() + sake.config.plugin.id + '*.zip', + sake.getPrereleasesPath() + sake.config.plugin.id + '*.txt' + ], { + force: true // required to allow deleting outside of current working directory }) +} +cleanPrereleaseTask.displayName = 'clean:prerelease' - // delete prerelease - gulp.task('clean:prerelease', () => { - return del([ - sake.getPrereleasesPath() + sake.config.plugin.id + '*.zip', - sake.getPrereleasesPath() + sake.config.plugin.id + '*.txt' - ], { - force: true // required to allow deleting outside of current working directory - }) +/** + * Clear WP repo trunk + */ +const cleanWpTrunkTask = (done) => { + return del([ + path.join(sake.getProductionRepoPath(), 'trunk') + ], { + force: true // required to allow deleting outside of current working directory }) +} +cleanWpTrunkTask.displayName = 'clean:wp_trunk' - // clear wp repo trunk - gulp.task('clean:wp_trunk', () => { - return del([ - path.join(sake.getProductionRepoPath(), 'trunk') - ], { - force: true // required to allow deleting outside of current working directory - }) +/** + * Clear WP repo assets + */ +const cleanWpAssetsTask = (done) => { + return del([ + path.join(sake.getProductionRepoPath(), 'assets') + ], { + force: true // required to allow deleting outside of current working directory }) +} +cleanWpAssetsTask.displayName = 'clean:wp_assets' - // clear wp repo trunk - gulp.task('clean:wp_assets', () => { - return del([ - path.join(sake.getProductionRepoPath(), 'assets') - ], { - force: true // required to allow deleting outside of current working directory - }) - }) +export { + cleanDevTask, + cleanComposerTask, + cleanBuildTask, + cleanWcRepoTask, + cleanPrereleaseTask, + cleanWpTrunkTask, + cleanWpAssetsTask } diff --git a/tasks/compile.js b/tasks/compile.js index 5d7c92a..1fb1de0 100644 --- a/tasks/compile.js +++ b/tasks/compile.js @@ -1,139 +1,173 @@ -const webpack = require('webpack-stream') -const fs = require('fs') -const path = require('path') -const sass = require('gulp-sass')(require('sass')) - -module.exports = (gulp, plugins, sake) => { - const pipes = require('../pipes/scripts.js')(plugins, sake) - - // compile plugin assets - gulp.task('compile', (done) => { - // default compile tasks - let tasks = ['lint:php', 'scripts', 'styles', 'imagemin'] - - // unless exclusively told not to, generate the POT file as well - if (!sake.options.skip_pot) { - tasks.push('makepot') - } - - gulp.parallel(tasks)(done) - }) - - /** Scripts */ - - // the main task to compile scripts - gulp.task('compile:scripts', gulp.parallel('compile:coffee', 'compile:js', 'compile:blocks')) - - // Note: ideally, we would only open a single stream of the script files, linting and compiling in the same - // stream/task, but unfortunately it looks like this is not possible, ast least not when reporting the - // lint errors - it results in no more files being passed down the stream, even if there were no lint errors. {IT 2018-03-14} - - // compile, transpile and minify coffee files - gulp.task('compile:coffee', () => { - if (! fs.existsSync(sake.config.paths.assetPaths.js)) { - return Promise.resolve() - } - - return gulp.src(`${sake.config.paths.assetPaths.js}/**/*.coffee`) - // plugins.if(() => sake.isWatching, plugins.newer({dest: sake.config.paths.assetPaths.js + '/**', ext: 'min.js'})), - .pipe(plugins.sourcemaps.init()) - // compile coffee files to JS - .pipe(plugins.coffee({ bare: false })) - // transpile & minify, write sourcemaps - .pipe(pipes.compileJs()) - .pipe(gulp.dest(sake.config.paths.assetPaths.js)) - .pipe(plugins.if(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, plugins.browserSync.stream.apply({ match: '**/*.js' }))) - }) - - // transpile and minify js files - gulp.task('compile:js', () => { - if (! fs.existsSync(sake.config.paths.assetPaths.js)) { - return Promise.resolve() - } - - return gulp.src(sake.config.paths.assetPaths.javascriptSources) - // plugins.if(() => sake.isWatching, plugins.newer({dest: sake.config.paths.assetPaths.js + '/**', ext: 'min.js'})), - .pipe(plugins.sourcemaps.init()) - // transpile & minify, write sourcemaps - .pipe(pipes.compileJs()) - .pipe(gulp.dest(sake.config.paths.assetPaths.js)) - .pipe(plugins.if(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, plugins.browserSync.stream.apply({ match: '**/*.js' }))) - }) - - // this task is specific for plugins that add one or more self-contained Gutenberg blocks in their assets to be transpiled from ES6 - gulp.task('compile:blocks', () => { - const i18nPath = `${process.cwd()}/i18n/languages/blocks/` - const blockPath = `${sake.config.paths.assetPaths.js}/blocks/src/` - const blockSrc = fs.existsSync(blockPath) ? fs.readdirSync(blockPath).filter(function (file) { - return file.match(/.*\.js$/) - }) : false - - if (!blockSrc || blockSrc[0].length <= 0) { - return Promise.resolve() - } else { - return gulp.src(sake.config.paths.assetPaths.blockSources) - .pipe(plugins.sourcemaps.init()) - .pipe(webpack({ - mode: 'production', - entry: `${blockPath}/${blockSrc[0]}`, - output: { - filename: path.basename(blockSrc[0], '.js') + '.min.js' - }, - externals: { - 'react': 'React', - 'react-dom': 'ReactDOM' - }, - module: { - rules: [{ - test: /\.js$/, - exclude: /node_modules/, - use: { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env', '@babel/preset-react'], - plugins: [ - ['@wordpress/babel-plugin-makepot', { 'output': `${i18nPath}${blockSrc[0].replace('.js', '.pot')}` }] - ] - } +import webpack from 'webpack-stream'; +import fs from 'node:fs'; +import path from 'node:path'; +import * as dartSaas from 'sass'; +import gulpSaas from 'gulp-sass'; +import autoprefixer from 'autoprefixer'; +import gulp from 'gulp' +import gulpif from 'gulp-if' +import coffee from 'gulp-coffee' +import sourcemaps from 'gulp-sourcemaps' +import cssnano from 'cssnano' +import postcss from 'gulp-postcss' +import browserSync from 'browser-sync' +import { scriptPipes } from '../pipes/scripts.js'; +import sake from '../lib/sake.js' +import rename from 'gulp-rename' +import { lintPhpTask } from './lint.js' +import { minifyImagesTask } from './imagemin.js' +import { makepotTask } from './makepot.js' +import { stylesTask } from './styles.js' +const sass = gulpSaas(dartSaas); + +/************************** Scripts */ + +/** + * Compile, transpile, and minify coffee scripts + */ +const compileCoffeeTask = (done) => { + if (! fs.existsSync(sake.config.paths.assetPaths.js)) { + return Promise.resolve() + } + + return gulp.src(`${sake.config.paths.assetPaths.js}/**/*.coffee`) + .pipe(sourcemaps.init()) + // compile coffee files to JS + .pipe(coffee({ bare: false })) + // transpile & minify, write sourcemaps + .pipe(scriptPipes().compileJs()) + .pipe(gulp.dest(sake.config.paths.assetPaths.js)) + .pipe(gulpif(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, browserSync.stream.apply({ match: '**/*.js' }))) +} +compileCoffeeTask.displayName = 'compile:coffee' + +/** + * Transpile and minify JS files + */ +const compileJsTask = (done) => { + if (! fs.existsSync(sake.config.paths.assetPaths.js)) { + return Promise.resolve() + } + + return gulp.src(sake.config.paths.assetPaths.javascriptSources) + // plugins.if(() => sake.isWatching, plugins.newer({dest: sake.config.paths.assetPaths.js + '/**', ext: 'min.js'})), + .pipe(sourcemaps.init()) + // transpile & minify, write sourcemaps + .pipe(scriptPipes().compileJs()) + .pipe(gulp.dest(sake.config.paths.assetPaths.js)) + .pipe(gulpif(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, browserSync.stream.apply({ match: '**/*.js' }))) +} +compileJsTask.displayName = 'compile:js' + +/** + * This task is specific for plugins that add one or more self-contained Gutenberg blocks in their assets to be transpiled from ES6 + */ +const compileBlocksTask = (done) => { + const i18nPath = `${process.cwd()}/i18n/languages/blocks/` + const blockPath = `${sake.config.paths.assetPaths.js}/blocks/src/` + const blockSrc = fs.existsSync(blockPath) ? fs.readdirSync(blockPath).filter(function (file) { + return file.match(/.*\.js$/) + }) : false + + if (!blockSrc || blockSrc[0].length <= 0) { + return Promise.resolve() + } else { + return gulp.src(sake.config.paths.assetPaths.blockSources) + .pipe(sourcemaps.init()) + .pipe(webpack({ + mode: 'production', + entry: `${blockPath}/${blockSrc[0]}`, + output: { + filename: path.basename(blockSrc[0], '.js') + '.min.js' + }, + externals: { + 'react': 'React', + 'react-dom': 'ReactDOM' + }, + module: { + rules: [{ + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: [ + ['@wordpress/babel-plugin-makepot', { 'output': `${i18nPath}${blockSrc[0].replace('.js', '.pot')}` }] + ] } - }] - } - })) - .pipe(gulp.dest(`${sake.config.paths.assetPaths.js}/blocks/`)) - .pipe(plugins.if(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, plugins.browserSync.stream.apply({ match: '**/*.js' }))) - } - }) - - /** Styles */ - - // main task for compiling styles - gulp.task('compile:styles', gulp.parallel('compile:scss')) - - // compile SCSS to CSS - gulp.task('compile:scss', () => { - if (! fs.existsSync(sake.config.paths.assetPaths.css)) { - return Promise.resolve() - } - - let cssPlugins = [require('autoprefixer')()] - - if (sake.options.minify) { - cssPlugins.push(require('cssnano')({ zindex: false })) - } - - return gulp.src([ - `${sake.config.paths.assetPaths.css}/**/*.scss`, - `!${sake.config.paths.assetPaths.css}/**/mixins.scss` // don't compile any mixins by themselves - ]) - .pipe(plugins.sourcemaps.init()) - .pipe(sass({ outputStyle: 'expanded' })) - .pipe(plugins.postcss(cssPlugins)) - .pipe(plugins.rename({ suffix: '.min' })) - // ensure admin/ and frontend/ are removed from the source paths - // see https://www.npmjs.com/package/gulp-sourcemaps#alter-sources-property-on-sourcemaps - .pipe(plugins.sourcemaps.mapSources((sourcePath) => '../' + sourcePath)) - .pipe(plugins.sourcemaps.write('.', { includeContent: false })) - .pipe(gulp.dest(`${sake.config.paths.src}/${sake.config.paths.css}`)) - .pipe(plugins.if(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, plugins.browserSync.stream({match: '**/*.css'}))) - }) + } + }] + } + })) + .pipe(gulp.dest(`${sake.config.paths.assetPaths.js}/blocks/`)) + .pipe(gulpif(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, browserSync.stream.apply({ match: '**/*.js' }))) + } +} +compileBlocksTask.displayName = 'compile:blocks' + +/************************** Styles */ + +/** + * Compile SCSS to CSS + */ +const compileScssTask = (done) => { + if (! fs.existsSync(sake.config.paths.assetPaths.css)) { + return Promise.resolve() + } + + let cssPlugins = [autoprefixer()] + + if (sake.options.minify) { + cssPlugins.push(cssnano({ zindex: false })) + } + + return gulp.src([ + `${sake.config.paths.assetPaths.css}/**/*.scss`, + `!${sake.config.paths.assetPaths.css}/**/mixins.scss` // don't compile any mixins by themselves + ]) + .pipe(sourcemaps.init()) + .pipe(sass({ outputStyle: 'expanded' })) + .pipe(postcss(cssPlugins)) + .pipe(rename({ suffix: '.min' })) + // ensure admin/ and frontend/ are removed from the source paths + // see https://www.npmjs.com/package/gulp-sourcemaps#alter-sources-property-on-sourcemaps + .pipe(sourcemaps.mapSources((sourcePath) => '../' + sourcePath)) + .pipe(sourcemaps.write('.', { includeContent: false })) + .pipe(gulp.dest(`${sake.config.paths.src}/${sake.config.paths.css}`)) + .pipe(gulpif(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, browserSync.stream({match: '**/*.css'}))) +} +compileScssTask.displayName = 'compile:scss' + +/************************** Parallels */ + +// The main task to compile scripts +const compileScripts = gulp.parallel(compileCoffeeTask, compileJsTask, compileBlocksTask) +compileScripts.displayName = 'compile:scripts' + +// The main task to compile styles +const compileStyles = gulp.parallel(compileScssTask) +compileStyles.displayName = 'compile:styles' + +// Compile all plugin assets +const compile = (done) => { + // default compile tasks + let tasks = [lintPhpTask, 'scripts', stylesTask, minifyImagesTask] // NOTE: do not import the `scripts` constant here, otherwise it creates a circular dependency + + // unless exclusively told not to, generate the POT file as well + if (!sake.options.skip_pot) { + tasks.push(makepotTask) + } + + gulp.parallel(tasks)(done) +} + +export { + compileCoffeeTask, + compileJsTask, + compileBlocksTask, + compileScssTask, + compileScripts, + compileStyles, + compile } diff --git a/tasks/config.js b/tasks/config.js index c31c64e..ef1a323 100644 --- a/tasks/config.js +++ b/tasks/config.js @@ -1,15 +1,18 @@ -const dottie = require('dottie') +import dottie from 'dottie'; +import sake from '../lib/sake.js' -module.exports = (gulp, plugins, sake) => { - // prints current sake.configuration - gulp.task('config', (done) => { - // pass --property=deploy.production to only see sake.config values for that propery - if (sake.options.property) { - console.log(dottie.get(sake.config, sake.options.property)) - } else { - console.log(sake.config) - } +const configTask = (done) => { + // pass --property=deploy.production to only see sake.config values for that property + if (sake.options.property) { + console.log(dottie.get(sake.config, sake.options.property)) + } else { + console.log(sake.config) + } - done() - }) + done() +} +configTask.displayName = 'config' + +export { + configTask } diff --git a/tasks/copy.js b/tasks/copy.js index e09b1a3..1e068ef 100644 --- a/tasks/copy.js +++ b/tasks/copy.js @@ -1,199 +1,228 @@ -const path = require('path') -const semver = require('semver') - -module.exports = (gulp, plugins, sake) => { - // copy files from source to build - gulp.task('copy:build', () => { - const filter = plugins.filter(['**/*.min.css', '**/*.min.js'], { restore: true }) - - let paths = [ - `${sake.config.paths.src}/**/*`, - - // skip the directory we're building everything into! - `!${sake.config.paths.build}{,/**}`, - - // skip .map files - `!${sake.config.paths.src}/${sake.config.paths.js}/**/*.map`, - `!${sake.config.paths.src}/${sake.config.paths.css}/**/*.map`, - - // skip coffee and unminified js files - `!${sake.config.paths.src}/${sake.config.paths.js}/**/*.coffee`, - `!${sake.config.paths.src}/${sake.config.paths.js}/**/*(!.min).js`, - `!${sake.config.paths.src}/${sake.config.paths.js}/blocks/src{,/**}`, - - // skip scss and unminified css files - `!${sake.config.paths.src}/${sake.config.paths.css}/**/*.scss`, - `!${sake.config.paths.src}/${sake.config.paths.css}/**/*(!.min).css`, - - // skip test files - `!${sake.config.paths.src}/**/tests{,/**}`, - `!${sake.config.paths.src}/**/.travis.yml`, - `!${sake.config.paths.src}/**/phpunit.xml`, - `!${sake.config.paths.src}/**/phpunit.travis.xml`, - `!${sake.config.paths.src}/**/docker-compose*.yml`, - `!${sake.config.paths.src}/**/wp-bootstrap.sh`, - `!${sake.config.paths.src}/phpcs.xml`, - - // skip composer and npm files - `!${sake.config.paths.src}/**/composer.json`, - `!${sake.config.paths.src}/**/composer.lock`, - `!${sake.config.paths.src}/**/options.json`, - `!${sake.config.paths.src}/**/package.json`, - `!${sake.config.paths.src}/**/package-lock.json`, - `!${sake.config.paths.src}/**/node_modules{,/**}`, - `!${sake.config.paths.src}/**/grunt{,/**}`, - - // skip misc files - `!${sake.config.paths.src}/**/modman`, - `!${sake.config.paths.src}/**/Gruntfile.js`, - `!${sake.config.paths.src}/**/sake.options.json`, - `!${sake.config.paths.src}/**/codeception*.*`, - `!${sake.config.paths.src}/**/*.zip`, - `!${sake.config.paths.src}/**/*.iml`, // IDE configuration - `!${sake.config.paths.src}/**/test.sh`, - `!${sake.config.paths.src}/**/readme.md`, - `!${sake.config.paths.src}/**/.{*}`, // any file starting with a dot - - // skip tartufo files - `!${sake.config.paths.src}/**/tool.tartufo`, - `!${sake.config.paths.src}/**/tartufo.toml`, - `!${sake.config.paths.src}/**/exclude-patterns.txt`, - - // skip codeowners files - `!${sake.config.paths.src}/**/CODEOWNERS`, - `!${sake.config.paths.src}/**/codeowners`, - - // skip whitesource files - `!${sake.config.paths.src}/**/.whitesource`, - - // skip manifest.xml - `!${sake.config.paths.src}/**/manifest.xml`, - - // skip build config files - `!${sake.config.paths.src}/**/sake.config.js`, - `!${sake.config.paths.src}/**/postcss.config.js`, - ] - - if (sake.config.framework) { - // skip common framework files - paths = paths.concat([ - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/*`, - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/grunt{,/**}`, - `${sake.config.paths.src}/${sake.config.paths.framework.base}/license.txt` - ]) - - if (sake.config.framework === 'v5') { - // skip sample loader file - paths.push(`!${sake.config.paths.src}/${sake.config.paths.framework.base}/woocommerce/woocommerce-framework-plugin-loader-sample.php`) - } +import path from 'node:path'; +import sake from '../lib/sake.js' +import gulp from 'gulp' +import replace from 'gulp-replace' +import rename from 'gulp-rename' +import gulpFilter from 'gulp-filter' + +/** + * Copy files from source to build + */ +const copyBuildTask = (done) => { + const filter = gulpFilter(['**/*.min.css', '**/*.min.js'], { restore: true }) + + let paths = [ + `${sake.config.paths.src}/**/*`, + + // skip the directory we're building everything into! + `!${sake.config.paths.build}{,/**}`, + + // skip .map files + `!${sake.config.paths.src}/${sake.config.paths.js}/**/*.map`, + `!${sake.config.paths.src}/${sake.config.paths.css}/**/*.map`, + + // skip coffee and unminified js files + `!${sake.config.paths.src}/${sake.config.paths.js}/**/*.coffee`, + `!${sake.config.paths.src}/${sake.config.paths.js}/**/*(!.min).js`, + `!${sake.config.paths.src}/${sake.config.paths.js}/blocks/src{,/**}`, + + // skip scss and unminified css files + `!${sake.config.paths.src}/${sake.config.paths.css}/**/*.scss`, + `!${sake.config.paths.src}/${sake.config.paths.css}/**/*(!.min).css`, + + // skip test files + `!${sake.config.paths.src}/**/tests{,/**}`, + `!${sake.config.paths.src}/**/.travis.yml`, + `!${sake.config.paths.src}/**/phpunit.xml`, + `!${sake.config.paths.src}/**/phpunit.travis.xml`, + `!${sake.config.paths.src}/**/docker-compose*.yml`, + `!${sake.config.paths.src}/**/wp-bootstrap.sh`, + `!${sake.config.paths.src}/phpcs.xml`, + + // skip composer and npm files + `!${sake.config.paths.src}/**/composer.json`, + `!${sake.config.paths.src}/**/composer.lock`, + `!${sake.config.paths.src}/**/options.json`, + `!${sake.config.paths.src}/**/package.json`, + `!${sake.config.paths.src}/**/package-lock.json`, + `!${sake.config.paths.src}/**/node_modules{,/**}`, + `!${sake.config.paths.src}/**/grunt{,/**}`, + + // skip misc files + `!${sake.config.paths.src}/**/modman`, + `!${sake.config.paths.src}/**/Gruntfile.js`, + `!${sake.config.paths.src}/**/sake.options.json`, + `!${sake.config.paths.src}/**/codeception*.*`, + `!${sake.config.paths.src}/**/*.zip`, + `!${sake.config.paths.src}/**/*.iml`, // IDE configuration + `!${sake.config.paths.src}/**/test.sh`, + `!${sake.config.paths.src}/**/readme.md`, + `!${sake.config.paths.src}/**/.{*}`, // any file starting with a dot + + // skip tartufo files + `!${sake.config.paths.src}/**/tool.tartufo`, + `!${sake.config.paths.src}/**/tartufo.toml`, + `!${sake.config.paths.src}/**/exclude-patterns.txt`, + + // skip codeowners files + `!${sake.config.paths.src}/**/CODEOWNERS`, + `!${sake.config.paths.src}/**/codeowners`, + + // skip whitesource files + `!${sake.config.paths.src}/**/.whitesource`, + + // skip manifest.xml + `!${sake.config.paths.src}/**/manifest.xml`, + + // skip build config files + `!${sake.config.paths.src}/**/sake.config.js`, + `!${sake.config.paths.src}/**/postcss.config.js`, + ] + + if (sake.config.framework) { + // skip common framework files + paths = paths.concat([ + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/*`, + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/grunt{,/**}`, + `${sake.config.paths.src}/${sake.config.paths.framework.base}/license.txt` + ]) - paths = paths.concat([ - // skip framework .map files - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.js}/**/*.map`, - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.js}/**/*.map`, - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.css}/**/*.map`, - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.css}/**/*.map`, - - // skip framework coffee files - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.js}/**/*.coffee`, - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.js}/**/*.coffee`, - - // skip framework scss files - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.css}/**/*.scss`, - `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.css}/**/*.scss` - ]) + if (sake.config.framework === 'v5') { + // skip sample loader file + paths.push(`!${sake.config.paths.src}/${sake.config.paths.framework.base}/woocommerce/woocommerce-framework-plugin-loader-sample.php`) } paths = paths.concat([ - // skip misc jilt promotions files - `!${sake.config.paths.vendor}/skyverge/wc-jilt-promotions/gulpfile.js`, - `!${sake.config.paths.vendor}/skyverge/wc-jilt-promotions/README.md` + // skip framework .map files + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.js}/**/*.map`, + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.js}/**/*.map`, + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.css}/**/*.map`, + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.css}/**/*.map`, + + // skip framework coffee files + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.js}/**/*.coffee`, + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.js}/**/*.coffee`, + + // skip framework scss files + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.general.css}/**/*.scss`, + `!${sake.config.paths.src}/${sake.config.paths.framework.base}/${sake.config.paths.framework.gateway.css}/**/*.scss` ]) + } - // skip copying composer dev packages - if (sake.config.composer) { - if (sake.config.composer['require-dev']) { - Object.keys(sake.config.composer['require-dev']).forEach((pkg) => { - // skip copying the dev package directory - let packagePath = path.join(sake.config.paths.vendor, pkg) - - // if there are no other non-dev packages from the same vendor, skip the folder for the vendor itself as well - let vendor = pkg.split('/')[0] - - if (!(sake.config.composer.require && Object.keys(sake.config.composer.require).some((pkg) => pkg.indexOf(vendor) > -1))) { - packagePath = path.join(sake.config.paths.vendor, vendor) - } - - paths.push(`!${packagePath}{,/**}`) - }) - } - - // skip copying binaries - paths.push(`!${sake.config.paths.vendor}/bin{,/**}`) - - // skip composer autoloader, unless required - if (!sake.config.autoload) { - paths = paths.concat([ - `!${sake.config.paths.vendor}/composer{,/**}`, - `!${sake.config.paths.vendor}/autoload.php` - ]) - } - } + paths = paths.concat([ + // skip misc jilt promotions files + `!${sake.config.paths.vendor}/skyverge/wc-jilt-promotions/gulpfile.js`, + `!${sake.config.paths.vendor}/skyverge/wc-jilt-promotions/README.md` + ]) - // skip the WP assets dir if it's in the root - if (sake.config.deploy.type === 'wp' && sake.config.paths.wpAssets) { - paths.push(`!${sake.config.paths.wpAssets}{,/**}`) - } + // skip copying composer dev packages + if (sake.config.composer) { + if (sake.config.composer['require-dev']) { + Object.keys(sake.config.composer['require-dev']).forEach((pkg) => { + // skip copying the dev package directory + let packagePath = path.join(sake.config.paths.vendor, pkg) + + // if there are no other non-dev packages from the same vendor, skip the folder for the vendor itself as well + let vendor = pkg.split('/')[0] - // skip any custom paths - if (Array.isArray(sake.config.paths.exclude) && sake.config.paths.exclude.length) { - sake.config.paths.exclude.forEach((path) => { - paths.push(`!${path}{,/**}`) + if (!(sake.config.composer.require && Object.keys(sake.config.composer.require).some((pkg) => pkg.indexOf(vendor) > -1))) { + packagePath = path.join(sake.config.paths.vendor, vendor) + } + + paths.push(`!${packagePath}{,/**}`) }) } - // encoding: false is required because otherwise images will become corrupted - // @link https://github.com/gulpjs/gulp/issues/2790 - return gulp.src(paths, { base: sake.config.paths.src, allowEmpty: true, encoding: false }) - .pipe(filter) - .pipe(plugins.replace(/\/\*# sourceMappingURL=.*?\*\/$/mg, '')) // remove source mapping references - TODO: consider skipping sourcemaps in compilers instead when running build/deploy tasks - .pipe(plugins.replace('\n', '')) // remove an extra line added by libsass/node-sass - .pipe(filter.restore) - .pipe(gulp.dest(`${sake.config.paths.build}/${sake.config.plugin.id}`)) - }) - - // copy plugin zip and changelog to prereleases folder - gulp.task('copy:prerelease', () => { - let filename = sake.config.deploy.type === 'wp' ? 'readme' : 'changelog' - - const filter = plugins.filter([`**/${filename}.txt`], { restore: true }) - - return gulp.src([ - `${sake.config.paths.build}/${sake.config.plugin.id}*.zip`, - `${sake.config.paths.build}/${sake.config.plugin.id}/${filename}.txt` - ]).pipe(filter) - .pipe(plugins.rename({ prefix: sake.config.plugin.id + '_' })) - .pipe(filter.restore) - .pipe(gulp.dest(sake.getPrereleasesPath())) - }) - - // copy files from build to WC repo folder - gulp.task('copy:wc_repo', () => { - return gulp.src(`${sake.config.paths.build}/${sake.config.plugin.id}/**/*`).pipe(gulp.dest(sake.getProductionRepoPath())) - }) - - // copy files from build to WP trunk folder - gulp.task('copy:wp_trunk', () => { - return gulp.src(`${sake.config.paths.build}/${sake.config.plugin.id}/**/*`).pipe(gulp.dest(path.join(sake.getProductionRepoPath(), 'trunk'))) - }) - - // copy files from build to WP assets folder - gulp.task('copy:wp_assets', () => { - return gulp.src(`${sake.config.paths.wpAssets}/**/*`).pipe(gulp.dest(path.join(sake.getProductionRepoPath(), 'assets'))) - }) - - // copy files from WP trunk to tag - gulp.task('copy:wp_tag', () => { - return gulp.src(path.join(sake.getProductionRepoPath(), 'trunk/**/*')).pipe(gulp.dest(path.join(sake.getProductionRepoPath(), 'tags', sake.getPluginVersion()))) - }) + // skip copying binaries + paths.push(`!${sake.config.paths.vendor}/bin{,/**}`) + + // skip composer autoloader, unless required + if (!sake.config.autoload) { + paths = paths.concat([ + `!${sake.config.paths.vendor}/composer{,/**}`, + `!${sake.config.paths.vendor}/autoload.php` + ]) + } + } + + // skip the WP assets dir if it's in the root + if (sake.config.deploy.type === 'wp' && sake.config.paths.wpAssets) { + paths.push(`!${sake.config.paths.wpAssets}{,/**}`) + } + + // skip any custom paths + if (Array.isArray(sake.config.paths.exclude) && sake.config.paths.exclude.length) { + sake.config.paths.exclude.forEach((path) => { + paths.push(`!${path}{,/**}`) + }) + } + + // encoding: false is required because otherwise images will become corrupted + // @link https://github.com/gulpjs/gulp/issues/2790 + return gulp.src(paths, { base: sake.config.paths.src, allowEmpty: true, encoding: false }) + .pipe(filter) + .pipe(replace(/\/\*# sourceMappingURL=.*?\*\/$/mg, '')) // remove source mapping references - TODO: consider skipping sourcemaps in compilers instead when running build/deploy tasks + .pipe(replace('\n', '')) // remove an extra line added by libsass/node-sass + .pipe(filter.restore) + .pipe(gulp.dest(`${sake.config.paths.build}/${sake.config.plugin.id}`)) +} +copyBuildTask.displayName = 'copy:build' + +/** + * Copy plugin zip and changelog to prereleases folder + */ +const copyPrereleaseTask = (done) => { + let filename = sake.config.deploy.type === 'wp' ? 'readme' : 'changelog' + + const filter = gulpFilter([`**/${filename}.txt`], { restore: true }) + + return gulp.src([ + `${sake.config.paths.build}/${sake.config.plugin.id}*.zip`, + `${sake.config.paths.build}/${sake.config.plugin.id}/${filename}.txt` + ]).pipe(filter) + .pipe(rename({ prefix: sake.config.plugin.id + '_' })) + .pipe(filter.restore) + .pipe(gulp.dest(sake.getPrereleasesPath())) +} +copyPrereleaseTask.displayName = 'copy:prerelease' + +/** + * Copy files from build to WC repo folder + */ +const copyWcRepoTask = (done) => { + return gulp.src(`${sake.config.paths.build}/${sake.config.plugin.id}/**/*`).pipe(gulp.dest(sake.getProductionRepoPath())) +} +copyWcRepoTask.displayName = 'copy:wc_repo' + +/** + * Copy files from build to WP trunk folder + */ +const copyWpTrunkTask = (done) => { + return gulp.src(`${sake.config.paths.build}/${sake.config.plugin.id}/**/*`).pipe(gulp.dest(path.join(sake.getProductionRepoPath(), 'trunk'))) +} +copyWpTrunkTask.displayName = 'copy:wp_trunk' + +/** + * Copy files from build to WP assets folder + */ +const copyWpAssetsTask = (done) => { + return gulp.src(`${sake.config.paths.wpAssets}/**/*`).pipe(gulp.dest(path.join(sake.getProductionRepoPath(), 'assets'))) +} +copyWpAssetsTask.displayName = 'copy:wp_assets' + +/** + * Copy files from WP trunk to tag + */ +const copyWpTagTask = (done) => { + return gulp.src(path.join(sake.getProductionRepoPath(), 'trunk/**/*')).pipe(gulp.dest(path.join(sake.getProductionRepoPath(), 'tags', sake.getPluginVersion()))) +} +copyWpTagTask.displayName = 'copy:wp_tag' + +export { + copyBuildTask, + copyPrereleaseTask, + copyWcRepoTask, + copyWpTrunkTask, + copyWpAssetsTask, + copyWpTagTask } diff --git a/tasks/decaffeinate.js b/tasks/decaffeinate.js index ee96a1e..5b9d52b 100644 --- a/tasks/decaffeinate.js +++ b/tasks/decaffeinate.js @@ -1,24 +1,38 @@ -const path = require('path') +import path from 'node:path'; +import sake from '../lib/sake.js' +import gulp from 'gulp' +import browserSync from 'browser-sync' +import coffee from 'gulp-coffee' +import gulpif from 'gulp-if' +import eslint from 'gulp-eslint' +import { fileURLToPath } from 'node:url' +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); -module.exports = (gulp, plugins, sake) => { - // converts CoffeeScripts to ES6 JavaScript without minification or further handling: - // this command should only be run once when converting an existing plugin CoffeeScript codebase to plain ES6 - gulp.task('decaffeinate', () => { - // use WordPress standards - overrideable by individual plugins that provide a .eslintrc file - // see https://github.com/WordPress-Coding-Standards/eslint-config-wordpress/blob/master/index.js - let esLintFile = sake.options['eslint-configFile'] ? path.join(process.cwd(), sake.options['eslint-configFile']) : path.join(__dirname, '../lib/lintfiles/.eslintrc') - let esLintOptions = { - configFile: esLintFile, - quiet: false, - fix: true - } +/** + * Converts CoffeeScripts to ES6 JavaScript without minification or further handling. + * This command should only be run once when converting an existing plugin CoffeeScript codebase to plain ES6. + */ +const decaffeinateTask = (done) => { + // use WordPress standards - overrideable by individual plugins that provide a .eslintrc file + // see https://github.com/WordPress-Coding-Standards/eslint-config-wordpress/blob/master/index.js + let esLintFile = sake.options['eslint-configFile'] ? path.join(process.cwd(), sake.options['eslint-configFile']) : path.join(__dirname, '../lib/lintfiles/.eslintrc') + let esLintOptions = { + configFile: esLintFile, + quiet: false, + fix: true + } - return gulp.src(`${sake.config.paths.assetPaths.js}/**/*.coffee`) - .pipe(plugins.coffee({ bare: true })) - .pipe(gulp.dest(sake.config.paths.assetPaths.js)) - .pipe(plugins.eslint(esLintOptions)) - .pipe(plugins.eslint.format('table')) - .pipe(gulp.dest(sake.config.paths.assetPaths.js)) - .pipe(plugins.if(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, plugins.browserSync.stream.apply({ match: '**/*.js' }))) - }) + return gulp.src(`${sake.config.paths.assetPaths.js}/**/*.coffee`) + .pipe(coffee({ bare: true })) + .pipe(gulp.dest(sake.config.paths.assetPaths.js)) + .pipe(eslint(esLintOptions)) + .pipe(eslint.format('table')) + .pipe(gulp.dest(sake.config.paths.assetPaths.js)) + .pipe(gulpif(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, browserSync.stream.apply({ match: '**/*.js' }))) +} +decaffeinateTask.displayName = 'decaffeinate' + +export { + decaffeinateTask } diff --git a/tasks/deploy.js b/tasks/deploy.js index 39bb2e2..a7d8fd4 100644 --- a/tasks/deploy.js +++ b/tasks/deploy.js @@ -1,385 +1,460 @@ -const fs = require('fs') -const log = require('fancy-log') -const dateFormat = require('dateformat') -const _ = require('lodash') -const chalk = require('chalk') -const axios = require('axios') - -module.exports = (gulp, plugins, sake) => { - let validatedEnvVariables = false +import fs from 'node:fs'; +import dateFormat from 'dateformat'; +import _ from 'lodash'; +import axios from 'axios'; +import log from 'fancy-log'; +import chalk from 'chalk'; +import sake from '../lib/sake.js' +import gulp from 'gulp' +import filter from 'gulp-filter' +import replace from 'gulp-replace' +import replaceTask from 'gulp-replace-task' +import { promptDeployTask, promptTestedReleaseZipTask, promptWcUploadTask } from './prompt.js' +import { bumpMinReqsTask, bumpTask } from './bump.js' +import { cleanPrereleaseTask, cleanWcRepoTask, cleanWpAssetsTask, cleanWpTrunkTask } from './clean.js' +import { buildTask } from './build.js' +import { + gitHubCreateDocsIssueTask, + gitHubCreateReleaseTask, + gitHubGetReleaseIssueTask, + gitHubGetWcIssuesTask +} from './github.js' +import { + shellGitEnsureCleanWorkingCopyTask, + shellGitPullWcRepoTask, + shellGitPushUpdateTask, + shellGitPushWcRepoTask, + shellGitUpdateWcRepoTask, shellSvnCheckoutTask, + shellSvnCommitAssetsTask, + shellSvnCommitTagTask, + shellSvnCommitTrunkTask +} from './shell.js' +import { zipTask } from './zip.js' +import { validateReadmeHeadersTask } from './validate.js' +import { lintScriptsTask, lintStylesTask } from './lint.js' +import { copyWcRepoTask, copyWpAssetsTask, copyWpTagTask, copyWpTrunkTask } from './copy.js' + +let validatedEnvVariables = false + +// TODO: consider setting these variables in the sake.config on load instead, and validating sake.config vars instead +// validate env variables before deploy +function validateEnvVariables () { + if (validatedEnvVariables) return + + let variables = ['GITHUB_API_KEY', 'GITHUB_USERNAME', 'SAKE_PRE_RELEASE_PATH'] + + if (sake.config.deploy.type === 'wc') { + variables = variables.concat(['WC_CONSUMER_KEY', 'WC_CONSUMER_SECRET']) + } - // TODO: consider setting these variables in the sake.config on load instead, and validating sake.config vars instead - // validate env variables before deploy - function validateEnvVariables () { - if (validatedEnvVariables) return + if (sake.config.deploy.type === 'wp') { + variables = variables.concat(['WP_SVN_USER']) + } - let variables = ['GITHUB_API_KEY', 'GITHUB_USERNAME', 'SAKE_PRE_RELEASE_PATH'] + sake.validateEnvironmentVariables(variables) +} - if (sake.config.deploy.type === 'wc') { - variables = variables.concat(['WC_CONSUMER_KEY', 'WC_CONSUMER_SECRET']) - } +/** + * Deploy the plugin + */ +const deployTask = (done) => { + validateEnvVariables() - if (sake.config.deploy.type === 'wp') { - variables = variables.concat(['WP_SVN_USER']) - } - - sake.validateEnvironmentVariables(variables) + if (!sake.isDeployable()) { + sake.throwError('Plugin is not deployable: \n * ' + sake.getChangelogErrors().join('\n * ')) } - // deploy the plugin - gulp.task('deploy', (done) => { - validateEnvVariables() - - if (!sake.isDeployable()) { - sake.throwError('Plugin is not deployable: \n * ' + sake.getChangelogErrors().join('\n * ')) - } - - // indicate that we are deploying - sake.options.deploy = true - // ensure scripts and styles are minified - sake.options.minify = true - - let tasks = [ - // preflight checks, will fail the deploy on errors - 'prompt:tested_release_zip', - 'deploy:preflight', - // ensure version is bumped - 'bump', - // fetch the latest WP/WC versions & bump the "tested up to" values - 'fetch_latest_wp_wc_versions', - 'bump:minreqs', - // prompt for the version to deploy as - 'prompt:deploy', - function (cb) { - if (sake.options.version === 'skip') { - log.error(chalk.red('Deploy skipped!')) - return done() - } - cb() - }, - // replace version number & date - 'replace:version', - // delete prerelease, if any - 'clean:prerelease', - // build the plugin - compiles and copies to build dir - 'build', - // ensure the required framework version is installed - 'deploy:validate_framework_version', - // grab issues to close with commit - 'github:get_rissue', - // rebuild plugin configuration (version number, etc) - function rebuildPluginConfig (cb) { - sake.buildPluginConfig() - cb() - }, - // git commit & push - 'shell:git_push_update', - // create the zip, which will be attached to the releases - 'compress', - // create releases, attaching the zip - 'deploy_create_releases' - ] - - if (sake.config.deploy.wooId && sake.config.deploy.type === 'wc') { - tasks.push('prompt:wc_upload') - } + // indicate that we are deploying + sake.options.deploy = true + // ensure scripts and styles are minified + sake.options.minify = true + + let tasks = [ + // preflight checks, will fail the deploy on errors + promptTestedReleaseZipTask, + deployPreflightTask, + // ensure version is bumped + bumpTask, + // fetch the latest WP/WC versions & bump the "tested up to" values + fetchLatestWpWcVersionsTask, + bumpMinReqsTask, + // prompt for the version to deploy as + promptDeployTask, + function (cb) { + if (sake.options.version === 'skip') { + log.error(chalk.red('Deploy skipped!')) + return done() + } + cb() + }, + // replace version number & date + replaceVersionTask, + // delete prerelease, if any + cleanPrereleaseTask, + // build the plugin - compiles and copies to build dir + buildTask, + // ensure the required framework version is installed + deployValidateFrameworkVersionTask, + // grab issues to close with commit + gitHubGetReleaseIssueTask, + // rebuild plugin configuration (version number, etc) + function rebuildPluginConfig (cb) { + sake.buildPluginConfig() + cb() + }, + // git commit & push + shellGitPushUpdateTask, + // create the zip, which will be attached to the releases + zipTask, + // create releases, attaching the zip + deployCreateReleasesTask, + ] + + if (sake.config.deploy.wooId && sake.config.deploy.type === 'wc') { + tasks.push(promptWcUploadTask) + } - if (sake.config.deploy.type === 'wp') { - tasks.push('deploy_to_wp_repo') - } + if (sake.config.deploy.type === 'wp') { + tasks.push(deployToWpRepoTask) + } - // finally, create a docs issue, if necessary - tasks.push('github:docs_issue') + // finally, create a docs issue, if necessary + tasks.push(gitHubCreateDocsIssueTask) - return gulp.series(tasks)(done) - }) + return gulp.series(tasks)(done) +} +deployTask.displayName = 'deploy' + +/** + * Run deploy preflight checks + */ +const deployPreflightTask = (done) => { + let tasks = [ + shellGitEnsureCleanWorkingCopyTask, + validateReadmeHeadersTask, + lintScriptsTask, + lintStylesTask + ] + + if (sake.config.deploy.type === 'wc') { + tasks.unshift(searchWtUpdateKeyTask) + } - // run deploy preflight checks - gulp.task('deploy:preflight', (done) => { - let tasks = [ - 'shell:git_ensure_clean_working_copy', - 'validate:readme_headers', - 'lint:scripts', - 'lint:styles' - ] - - if (sake.config.deploy.type === 'wc') { - tasks.unshift('search:wt_update_key') - } + gulp.parallel(tasks)(done) +} +deployPreflightTask.displayName = 'deploy:preflight' - gulp.parallel(tasks)(done) - }) +const deployValidateFrameworkVersionTask = (done) => { + if (sake.config.framework === 'v5' && sake.getFrameworkVersion() !== sake.getRequiredFrameworkVersion()) { + sake.throwError('Required framework version in composer.json (' + sake.getRequiredFrameworkVersion() + ') and installed framework version (' + sake.getFrameworkVersion() + ') do not match. Halting deploy.') + } - gulp.task('deploy:validate_framework_version', (done) => { - if (sake.config.framework === 'v5' && sake.getFrameworkVersion() !== sake.getRequiredFrameworkVersion()) { - sake.throwError('Required framework version in composer.json (' + sake.getRequiredFrameworkVersion() + ') and installed framework version (' + sake.getFrameworkVersion() + ') do not match. Halting deploy.') + done() +} +deployValidateFrameworkVersionTask.displayName = 'deploy:validate_framework_version' + +/** + * Internal task for making sure the WT updater keys have been set + */ +const searchWtUpdateKeyTask = (done) => { + fs.readFile(`${sake.config.paths.src}/${sake.config.plugin.mainFile}`, 'utf8', (err, data) => { + if (err) sake.throwError(err) + + // matches " * Woo: ProductId:ProductKey" in the main plugin file PHPDoc + const phpDocMatch = data.match(/\s*\*\s*Woo:\s*\d*:(.+)/ig) + // matches legacy woothemes_queue_update() usage in the main plugin file + const phpFuncMatch = data.match(/woothemes_queue_update\s*\(\s*plugin_basename\s*\(\s*__FILE__\s*\)\s*,\s*'(.+)'\s*,\s*'(\d+)'\s*\);/ig) + + // throw an error if no WT keys have been found with either method + if (!phpDocMatch && !phpFuncMatch) { + sake.throwError('WooThemes updater keys for the plugin have not been properly set ;(') } done() }) +} +searchWtUpdateKeyTask.displayName = 'search:wt_update_key' + +/** + * Internal task for replacing the version and date when deploying + */ +const replaceVersionTask = (done) => { + if (!sake.getVersionBump()) { + sake.throwError('No version replacement specified') + } - // internal task for making sure the WT updater keys have been set - gulp.task('search:wt_update_key', (done) => { - fs.readFile(`${sake.config.paths.src}/${sake.config.plugin.mainFile}`, 'utf8', (err, data) => { - if (err) sake.throwError(err) - - // matches " * Woo: ProductId:ProductKey" in the main plugin file PHPDoc - let phpDocMatch = data.match(/\s*\*\s*Woo:\s*\d*:(.+)/ig) - // matches legacy woothemes_queue_update() usage in the main plugin file - let phpFuncMatch = data.match(/woothemes_queue_update\s*\(\s*plugin_basename\s*\(\s*__FILE__\s*\)\s*,\s*'(.+)'\s*,\s*'(\d+)'\s*\);/ig) - - // throw an error if no WT keys have been found with either method - if (!phpDocMatch && !phpFuncMatch) { - sake.throwError('WooThemes updater keys for the plugin have not been properly set ;(') - } - - done() - }) - }) - - // internal task for replacing version and date when deploying - gulp.task('replace:version', () => { - if (!sake.getVersionBump()) { - sake.throwError('No version replacement specified') - } - - const versions = sake.getPrereleaseVersions(sake.getPluginVersion()) - const versionReplacements = versions.map(version => { - return { match: version, replacement: () => sake.getVersionBump() } - }) - - const filterChangelog = plugins.filter('**/{readme.md,readme.txt,changelog.txt}', { restore: true }) - const date = dateFormat(new Date(), 'yyyy.mm.dd') - - let paths = [ - `${sake.config.paths.src}/**/*.php`, - `${sake.config.paths.src}/readme.md`, - `${sake.config.paths.src}/readme.txt`, - `${sake.config.paths.src}/changelog.txt`, - `!${sake.config.paths.src}/*.json`, - `!${sake.config.paths.src}/*.xml`, - `!${sake.config.paths.src}/*.yml` - ] - - if (fs.existsSync(sake.config.paths.assetPaths.js)) { - paths.concat([ - `${sake.config.paths.assetPaths.js}/**/*.{coffee,js}`, - `!${sake.config.paths.assetPaths.js}/**/*.min.js`, - ]) - } - - if (fs.existsSync(sake.config.paths.assetPaths.css)) { - paths.concat([ - `${sake.config.paths.assetPaths.css}/**/*.scss`, - `${sake.config.paths.assetPaths.css}/**/*.css`, - ]) - } - - if (fs.existsSync(`!${sake.config.paths.src}/lib`)) { - paths.push(`!${sake.config.paths.src}/lib/**`) - } - - if (fs.existsSync(`!${sake.config.paths.src}/vendor`)) { - paths.push(`!${sake.config.paths.src}/vendor/**`) - } - - if (fs.existsSync(`!${sake.config.paths.src}/tests`)) { - paths.push(`!${sake.config.paths.src}/tests/**`) - } - - if (fs.existsSync(`!${sake.config.paths.src}/node_modules`)) { - paths.push(`!${sake.config.paths.src}/node_modules/**`) - } - - return gulp.src(paths, { base: './', allowEmpty: true }) - // unlike gulp-replace, gulp-replace-task supports multiple replacements - .pipe(plugins.replaceTask({ patterns: versionReplacements, usePrefix: false })) - .pipe(filterChangelog) - .pipe(plugins.replace(/[0-9]+\.nn\.nn/, date)) - .pipe(filterChangelog.restore) - .pipe(gulp.dest('./')) + const versions = sake.getPrereleaseVersions(sake.getPluginVersion()) + const versionReplacements = versions.map(version => { + return { match: version, replacement: () => sake.getVersionBump() } }) - /** - * Grab any issues to close with the deploy - */ - gulp.task('get_issues_to_close', (done) => { - let tasks = ['github:get_rissue'] - - if (sake.config.deploy.type === 'wc') { - tasks.push('github:get_wc_issues') - } + const filterChangelog = filter('**/{readme.md,readme.txt,changelog.txt}', { restore: true }) + const date = dateFormat(new Date(), 'yyyy.mm.dd') + + let paths = [ + `${sake.config.paths.src}/**/*.php`, + `${sake.config.paths.src}/readme.md`, + `${sake.config.paths.src}/readme.txt`, + `${sake.config.paths.src}/changelog.txt`, + `!${sake.config.paths.src}/*.json`, + `!${sake.config.paths.src}/*.xml`, + `!${sake.config.paths.src}/*.yml` + ] + + if (fs.existsSync(sake.config.paths.assetPaths.js)) { + paths.concat([ + `${sake.config.paths.assetPaths.js}/**/*.{coffee,js}`, + `!${sake.config.paths.assetPaths.js}/**/*.min.js`, + ]) + } - gulp.series(tasks)(done) - }) + if (fs.existsSync(sake.config.paths.assetPaths.css)) { + paths.concat([ + `${sake.config.paths.assetPaths.css}/**/*.scss`, + `${sake.config.paths.assetPaths.css}/**/*.css`, + ]) + } - /** - * Create releases for a deploy - * - * This task is especially useful if your deploy failed before the release - * creating step or you need to re-create the releases for some reason - */ - gulp.task('deploy_create_releases', (done) => { - // TODO: consider using async or similar to hide the anonymous tasks from gulp, see: https://github.com/gulpjs/gulp/issues/1143 - - let tasks = [ - function (cb) { - sake.options.owner = sake.config.deploy.dev.owner - sake.options.repo = sake.config.deploy.dev.name - sake.options.prefix_release_tag = sake.config.multiPluginRepo - cb() - }, - 'github:create_release' - ] - - return gulp.series(tasks)(done) - }) + if (fs.existsSync(`!${sake.config.paths.src}/lib`)) { + paths.push(`!${sake.config.paths.src}/lib/**`) + } - // main task for deploying the plugin after build to the production repo - gulp.task('deploy_to_production_repo', (done) => { - let tasks = [] - - if (sake.config.deploy.type === 'wc') { - tasks.push('deploy_to_wc_repo') - } else if (sake.config.deploy.type === 'wp') { - tasks.push('deploy_to_wp_repo') - } else { - log.warn(chalk.yellow('No deploy type set, skipping deploy to remote repo')) - return done() - } + if (fs.existsSync(`!${sake.config.paths.src}/vendor`)) { + paths.push(`!${sake.config.paths.src}/vendor/**`) + } - gulp.series(tasks)(done) - }) + if (fs.existsSync(`!${sake.config.paths.src}/tests`)) { + paths.push(`!${sake.config.paths.src}/tests/**`) + } - /** WooCommerce repo related tasks ****************************************/ + if (fs.existsSync(`!${sake.config.paths.src}/node_modules`)) { + paths.push(`!${sake.config.paths.src}/node_modules/**`) + } - // deploy to WC repo - gulp.task('deploy_to_wc_repo', (done) => { - validateEnvVariables() + return gulp.src(paths, { base: './', allowEmpty: true }) + // unlike gulp-replace, gulp-replace-task supports multiple replacements + .pipe(replaceTask({ patterns: versionReplacements, usePrefix: false })) + .pipe(filterChangelog) + .pipe(replace(/[0-9]+\.nn\.nn/, date)) + .pipe(filterChangelog.restore) + .pipe(gulp.dest('./')) +} +replaceVersionTask.displayName = 'replace:version' - gulp.series('copy_to_wc_repo', 'shell:git_push_wc_repo')(done) - }) +/** + * Grab any issues to close with the deploy + */ +const getIssuesToCloseTask = (done) => { + let tasks = [gitHubGetReleaseIssueTask] - /** - * Copy to WC repo - * - * Helper task which copies files to WC repo (used by update_wc_repo) - * - * Builds the plugin, pulls chances from the WC repo, cleans the local WC - * repo clone, and then copies built plugin to clone - */ - gulp.task('copy_to_wc_repo', (done) => { - validateEnvVariables() - - let tasks = [ - // copy files to build directory - 'build', - // ensure WC repo is up to date - 'shell:git_pull_wc_repo', - // clean the WC plugin dir - 'clean:wc_repo', - // copy files from build to WC repo directory - 'copy:wc_repo' - ] - - // no need to build when part of deploy process - if (sake.options.deploy) { - tasks.shift() - } + if (sake.config.deploy.type === 'wc') { + tasks.push(gitHubGetWcIssuesTask) + } - gulp.series(tasks)(done) - }) + gulp.series(tasks)(done) +} +getIssuesToCloseTask.displayName = 'get_issues_to_close' + +/** + * Create releases for a deploy + * + * This task is especially useful if your deploy failed before the release + * creating step or you need to re-create the releases for some reason + */ +const deployCreateReleasesTask = (done) => { + // TODO: consider using async or similar to hide the anonymous tasks from gulp, see: https://github.com/gulpjs/gulp/issues/1143 + + let tasks = [ + function (cb) { + sake.options.owner = sake.config.deploy.dev.owner + sake.options.repo = sake.config.deploy.dev.name + sake.options.prefix_release_tag = sake.config.multiPluginRepo + cb() + }, + gitHubCreateReleaseTask + ] + + return gulp.series(tasks)(done) +} +deployCreateReleasesTask.displayName = 'deploy_create_releases' + +/** + * Main task for deploying the plugin after build to the production repo + * @deprecated + */ +const deployToProductionRepoTask = (done) => { + let tasks = [] + + if (sake.config.deploy.type === 'wc') { + tasks.push(deployToWcRepoTask) + } else if (sake.config.deploy.type === 'wp') { + tasks.push(deployToWpRepoTask) + } else { + log.warn(chalk.yellow('No deploy type set, skipping deploy to remote repo')) + return done() + } - // TODO: do we need this anymore? - /** - * Update WC repo - * - * Builds and copies plugin to WC repo then pushes a general "Updating {plugin name}" - * commit. This is not a very useful task as it was created many moons ago to allow - * us to quickly fix issues with the deploy (such as extra files, etc). The - * task remains for posterity - */ - gulp.task('update_wc_repo', (done) => { - validateEnvVariables() - - gulp.series('copy_to_wc_repo', 'shell:git_update_wc_repo')(done) - }) + gulp.series(tasks)(done) +} +deployToProductionRepoTask.displayName = 'deploy_to_production_repo' - /** WP.org deploy related tasks ****************************************/ +/** WooCommerce repo related tasks ****************************************/ - gulp.task('deploy_to_wp_repo', (done) => { - let tasks = ['copy_to_wp_repo', 'shell:svn_commit_trunk'] +/** + * Deploy to WC repo + * @deprecated + */ +const deployToWcRepoTask = (done) => { + validateEnvVariables() - sake.options = _.merge({ - deployTag: true, - deployAssets: true - }, sake.options) + gulp.series(copyToWcRepoTask, shellGitPushWcRepoTask)(done) +} +deployToWcRepoTask.displayName = 'deploy_to_wc_repo' + +/** + * Copy to WC repo + * + * Helper task which copies files to WC repo (used by {@see updateWcRepoTask()}) + * + * Builds the plugin, pulls chances from the WC repo, cleans the local WC + * repo clone, and then copies built plugin to clone + * @deprecated + */ +const copyToWcRepoTask = (done) => { + validateEnvVariables() + + let tasks = [ + // copy files to build directory + buildTask, + // ensure WC repo is up to date + shellGitPullWcRepoTask, + // clean the WC plugin dir + cleanWcRepoTask, + // copy files from build to WC repo directory + copyWcRepoTask, + ] + + // no need to build when part of deploy process + if (sake.options.deploy) { + tasks.shift() + } - if (sake.options.deployTag) { - tasks.push('copy:wp_tag') - tasks.push('shell:svn_commit_tag') - } + gulp.series(tasks)(done) +} +copyToWcRepoTask.displayName = 'copy_to_wc_repo' + +/** + * @TODO: do we need this anymore? + * + * Update WC repo + * + * Builds and copies plugin to WC repo then pushes a general "Updating {plugin name}" + * commit. This is not a very useful task as it was created many moons ago to allow + * us to quickly fix issues with the deploy (such as extra files, etc). The + * task remains for posterity + * @deprecated + */ +const updateWcRepoTask = (done) => { + validateEnvVariables() + + gulp.series(copyToWcRepoTask, shellGitUpdateWcRepoTask)(done) +} +updateWcRepoTask.displayName = 'update_wc_repo' - if (sake.options.deployAssets) { - tasks.push('clean:wp_assets') - tasks.push('copy:wp_assets') - tasks.push('shell:svn_commit_assets') - } +/** WP.org deploy related tasks ****************************************/ - gulp.series(tasks)(done) - }) +const deployToWpRepoTask = (done) => { + let tasks = [copyToWpRepoTask, shellSvnCommitTrunkTask] - gulp.task('copy_to_wp_repo', (done) => { - let tasks = [ - // copy files to build directory - 'build', - // ensure WP repo is up to date - 'shell:svn_checkout', - // clean the WC plugin dir - 'clean:wp_trunk', - // copy files from build to WP repo directory - 'copy:wp_trunk' - ] - - // no need to build when part of deploy process - if (sake.options.deploy) { - tasks.shift() - } + sake.options = _.merge({ + deployTag: true, + deployAssets: true + }, sake.options) - gulp.series(tasks)(done) - }) + if (sake.options.deployTag) { + tasks.push(copyWpTagTask) + tasks.push(shellSvnCommitTagTask) + } - gulp.task('fetch_latest_wp_wc_versions', (done) => { - log.info('Fetching latest WP and WC versions') + if (sake.options.deployAssets) { + tasks.push(cleanWpAssetsTask) + tasks.push(copyWpAssetsTask) + tasks.push(shellSvnCommitAssetsTask) + } - let requests = [] + gulp.series(tasks)(done) +} +deployToWpRepoTask.displayName = 'deploy_to_wp_repo' + +const copyToWpRepoTask = (done) => { + let tasks = [ + // copy files to build directory + buildTask, + // ensure WP repo is up to date + shellSvnCheckoutTask, + // clean the WC plugin dir + cleanWpTrunkTask, + // copy files from build to WP repo directory + copyWpTrunkTask + ] + + // no need to build when part of deploy process + if (sake.options.deploy) { + tasks.shift() + } - // only fetch the latest if a version is specified - // this allows us to set to a version that isn't yet released - if (!sake.options.tested_up_to_wp_version) { - requests.push( - axios.get('https://api.wordpress.org/core/version-check/1.7/') - .then(res => { - sake.options.tested_up_to_wp_version = res.data.offers[0].version - }) - ) - } + gulp.series(tasks)(done) +} +copyToWpRepoTask.displayName = 'copy_to_wp_repo' + +const fetchLatestWpWcVersionsTask = (done) => { + log.info('Fetching latest WP and WC versions') + + let requests = [] + + // only fetch the latest if a version is specified + // this allows us to set to a version that isn't yet released + if (!sake.options.tested_up_to_wp_version) { + requests.push( + axios.get('https://api.wordpress.org/core/version-check/1.7/') + .then(res => { + sake.options.tested_up_to_wp_version = res.data.offers[0].version + }) + ) + } - if (sake.config.platform === 'wc' && !sake.options.tested_up_to_wc_version) { - requests.push( - axios.get('https://api.wordpress.org/plugins/info/1.0/woocommerce.json') - .then(res => { - if (res.data.error) { - throw res.data.error - } - - sake.options.tested_up_to_wc_version = res.data.version - }) - ) - } + if (sake.config.platform === 'wc' && !sake.options.tested_up_to_wc_version) { + requests.push( + axios.get('https://api.wordpress.org/plugins/info/1.0/woocommerce.json') + .then(res => { + if (res.data.error) { + throw res.data.error + } + + sake.options.tested_up_to_wc_version = res.data.version + }) + ) + } - axios.all(requests) - .then(() => done()) - .catch(err => sake.throwDeferredError('An error occurred when fetching latest WP / WC versions: ' + err.toString())) - }) + axios.all(requests) + .then(() => done()) + .catch(err => sake.throwDeferredError('An error occurred when fetching latest WP / WC versions: ' + err.toString())) +} +fetchLatestWpWcVersionsTask.displayName = 'fetch_latest_wp_wc_versions' + +export { + deployTask, + deployPreflightTask, + deployValidateFrameworkVersionTask, + searchWtUpdateKeyTask, + replaceVersionTask, + getIssuesToCloseTask, + deployCreateReleasesTask, + deployToProductionRepoTask, + deployToWcRepoTask, + copyToWcRepoTask, + updateWcRepoTask, + deployToWpRepoTask, + copyToWpRepoTask, + fetchLatestWpWcVersionsTask } diff --git a/tasks/github.js b/tasks/github.js index b76b67e..c26d0a0 100644 --- a/tasks/github.js +++ b/tasks/github.js @@ -1,320 +1,341 @@ -const { Octokit: GitHub } = require('@octokit/rest') -const inquirer = require('inquirer') -const fs = require('fs') -const path = require('path') -const async = require('async') -const chalk = require('chalk') -const codename = require('codename')() -const dateFormat = require('dateformat') -const log = require('fancy-log') - -module.exports = (gulp, plugins, sake) => { - let githubInstances = {} - - let getGithub = (target = 'dev') => { - if (!githubInstances[target]) { - githubInstances[target] = new GitHub({ - debug: false, - auth: process.env[`SAKE_${target.toUpperCase()}_GITHUB_API_KEY`] || process.env.GITHUB_API_KEY - }) - } +import { Octokit as GitHub } from '@octokit/rest' +import inquirer from 'inquirer' +import fs from 'node:fs' +import path from 'node:path' +import async from 'async' +import chalk from 'chalk' +import codename from 'codename' +import dateFormat from 'dateformat' +import log from 'fancy-log' +import sake from '../lib/sake.js' +import gulp from 'gulp' + +let githubInstances = {} + +let getGithub = (target = 'dev') => { + if (! githubInstances[target]) { + githubInstances[target] = new GitHub({ + debug: false, + auth: process.env[`SAKE_${target.toUpperCase()}_GITHUB_API_KEY`] || process.env.GITHUB_API_KEY + }) + } + + return githubInstances[target] +} + +const gitHubGetReleaseIssueTask = (done) => { + let owner = sake.config.deploy.dev.owner + let repo = sake.config.deploy.dev.name + let github = getGithub('dev') - return githubInstances[target] + let labels = ['release'] + + if (sake.config.multiPluginRepo) { + labels.push(sake.config.plugin.id.replace('woocommerce-', '')) } - gulp.task('github:get_rissue', (done) => { - let owner = sake.config.deploy.dev.owner - let repo = sake.config.deploy.dev.name - let github = getGithub('dev') + github.issues.listForRepo({ + owner: owner, + repo: repo, + state: 'open', + labels: labels.join(',') + }).then((result) => { + if (! result.data.length) { + done() + } else { + inquirer.prompt([{ + type: 'list', + name: 'issues_to_close', + message: 'Release issues exist for ' + sake.getPluginName() + '. Select an issue this release should close.', + choices: function () { + let choices = result.data.filter((result) => !result.pull_request).map((result) => { + return { + value: result.number, + name: 'Close issue #' + result.number + ': ' + result.html_url + } + }) - let labels = ['release'] + choices.push({ + value: 'none', + name: 'None'.red + }) - if (sake.config.multiPluginRepo) { - labels.push(sake.config.plugin.id.replace('woocommerce-', '')) + return choices + } + }]).then(function (answers) { + if (answers.issues_to_close === 'none') { + log.warn(chalk.yellow('No issues will be closed for release of ' + sake.getPluginName())) + } else { + sake.options.release_issue_to_close = answers.issues_to_close + } + done() + }) } + }).catch((err) => { + log.error(chalk.red('Could not get release issue: ' + err.toString())) + done() + }) +} +gitHubGetReleaseIssueTask.displayName = 'github:get_rissue' - github.issues.listForRepo({ - owner: owner, - repo: repo, - state: 'open', - labels: labels.join(',') - }).then((result) => { - if (!result.data.length) { +const gitHubGetWcIssuesTask = (done) => { + if (!sake.config.deploy.production) { + log.warn(chalk.yellow('No WC (production) repo configured for ' + sake.getPluginName() + ', skipping')) + return done() + } + + let owner = sake.config.deploy.production.owner + let repo = sake.config.deploy.production.name + let github = getGithub('production') + + github.issues.listForRepo({ + owner: owner, + repo: repo, + state: 'open' + }) + .then((result) => { + if (! result.data.length) { done() } else { inquirer.prompt([{ - type: 'list', + type: 'checkbox', name: 'issues_to_close', - message: 'Release issues exist for ' + sake.getPluginName() + '. Select an issue this release should close.', + message: 'Issues on WC repo exist for ' + sake.getPluginName() + '. Select an issue this release should close. To skip, press Enter without selecting anything.', choices: function () { - let choices = result.data.filter((result) => !result.pull_request).map((result) => { + return result.data.filter((result) => !result.pull_request).sort().map((result) => { return { value: result.number, name: 'Close issue #' + result.number + ': ' + result.html_url } }) - - choices.push({ - value: 'none', - name: 'None'.red - }) - - return choices } }]).then(function (answers) { if (answers.issues_to_close === 'none') { - log.warn(chalk.yellow('No issues will be closed for release of ' + sake.getPluginName())) + log.warn('No issues will be closed for release of ' + sake.getPluginName()) } else { - sake.options.release_issue_to_close = answers.issues_to_close + sake.options.wc_issues_to_close = answers.issues_to_close } done() }) } - }).catch((err) => { - log.error(chalk.red('Could not get release issue: ' + err.toString())) - done() }) - }) - - gulp.task('github:get_wc_issues', (done) => { - if (!sake.config.deploy.production) { - log.warn(chalk.yellow('No WC (production) repo configured for ' + sake.getPluginName() + ', skipping')) - return done() - } - - let owner = sake.config.deploy.production.owner - let repo = sake.config.deploy.production.name - let github = getGithub('production') - - github.issues.listForRepo({ - owner: owner, - repo: repo, - state: 'open' + .catch((err) => { + log.error(chalk.red('Could not get issues for WC repo: ' + err.toString())) + done() }) - .then((result) => { - if (!result.data.length) { - done() - } else { - inquirer.prompt([{ - type: 'checkbox', - name: 'issues_to_close', - message: 'Issues on WC repo exist for ' + sake.getPluginName() + '. Select an issue this release should close. To skip, press Enter without selecting anything.', - choices: function () { - let choices = result.data.filter((result) => !result.pull_request).sort().map((result) => { - return { - value: result.number, - name: 'Close issue #' + result.number + ': ' + result.html_url - } - }) - - return choices - } - }]).then(function (answers) { - if (answers.issues_to_close === 'none') { - log.warn('No issues will be closed for release of ' + sake.getPluginName()) - } else { - sake.options.wc_issues_to_close = answers.issues_to_close - } - done() - }) - } - }) - .catch((err) => { - log.error(chalk.red('Could not get issues for WC repo: ' + err.toString())) - done() - }) - }) - - // creates a docs issue for the plugin - gulp.task('github:docs_issue', (done) => { - if (!sake.config.deploy.docs) { - log.warn(chalk.yellow('No docs repo configured for ' + sake.getPluginName() + ', skipping')) - return done() - } +} +gitHubGetWcIssuesTask.displayName = 'github:get_wc_issues' + +/** + * Creates a docs issue for the plugin + */ +const gitHubCreateDocsIssueTask = (done) => { + if (! sake.config.deploy.docs) { + log.warn(chalk.yellow('No docs repo configured for ' + sake.getPluginName() + ', skipping')) + return done() + } - let owner = sake.config.deploy.docs.owner - let repo = sake.config.deploy.docs.name - let github = getGithub('docs') + let owner = sake.config.deploy.docs.owner + let repo = sake.config.deploy.docs.name + let github = getGithub('docs') - let message = 'Should a Docs issue be created for ' + sake.getPluginName() + '?' + let message = 'Should a Docs issue be created for ' + sake.getPluginName() + '?' - if (sake.pluginHasNewFeatures()) { - message += chalk.yellow('\n\nThe changelog below contains new features and/or tweaks.\nA docs issue should always be created for releases with new features or user-facing changes.') - } + if (sake.pluginHasNewFeatures()) { + message += chalk.yellow('\n\nThe changelog below contains new features and/or tweaks.\nA docs issue should always be created for releases with new features or user-facing changes.') + } - inquirer.prompt([{ - type: 'list', - name: 'create_docs_issue', - message: message + '\n\nChangelog: \n\n' + sake.getPluginChanges() + '\n\n', - choices: [{ - value: 1, - name: 'Yes -- create a docs issue' - }, { - value: 0, - name: "No -- don't create a docs issue!" - }], - default: sake.pluginHasNewFeatures() ? 0 : 1 - }]).then(function (answers) { - if (answers.create_docs_issue) { - github.issues.create({ - owner: owner, - repo: repo, - title: sake.getPluginName() + ': Updated to ' + sake.getPluginVersion(), - body: sake.getPluginChanges() + (sake.options.release_issue_to_close ? '\r\n\r\nSee ' + sake.config.deploy.dev.owner + '/' + sake.config.deploy.dev.name + '#' + sake.options.release_issue_to_close : ''), - labels: [sake.config.plugin.id.replace('woocommerce-', ''), 'docs', 'sales'] - }).then((result) => { - log(result) - log('Docs issue created!') + inquirer.prompt([{ + type: 'list', + name: 'create_docs_issue', + message: message + '\n\nChangelog: \n\n' + sake.getPluginChanges() + '\n\n', + choices: [{ + value: 1, + name: 'Yes -- create a docs issue' + }, { + value: 0, + name: "No -- don't create a docs issue!" + }], + default: sake.pluginHasNewFeatures() ? 0 : 1 + }]).then(function (answers) { + if (answers.create_docs_issue) { + github.issues.create({ + owner: owner, + repo: repo, + title: sake.getPluginName() + ': Updated to ' + sake.getPluginVersion(), + body: sake.getPluginChanges() + (sake.options.release_issue_to_close ? '\r\n\r\nSee ' + sake.config.deploy.dev.owner + '/' + sake.config.deploy.dev.name + '#' + sake.options.release_issue_to_close : ''), + labels: [sake.config.plugin.id.replace('woocommerce-', ''), 'docs', 'sales'] + }).then((result) => { + log(result) + log('Docs issue created!') - done() - }).catch(sake.throwError) - } else { - log.warn('No docs issue was created for ' + sake.getPluginName()) done() - } - }) - }) - - // creates a release for the plugin, attaching the build zip to it - gulp.task('github:create_release', (done) => { - let owner = sake.options.owner - let repo = sake.options.repo || sake.config.plugin.id - - if (!owner || !repo) { - log.warn(chalk.yellow('The owner or the slug of the repo for ' + sake.getPluginName() + ' are missing, skipping')) - return done() + }).catch(sake.throwError) + } else { + log.warn('No docs issue was created for ' + sake.getPluginName()) + done() } + }) +} +gitHubCreateDocsIssueTask.displayName = 'github:docs_issue' + +/** + * Creates a release for the plugin, attaching the build zip to it + */ +const gitHubCreateReleaseTask = (done) => { + let owner = sake.options.owner + let repo = sake.options.repo || sake.config.plugin.id + + if (! owner || ! repo) { + log.warn(chalk.yellow('The owner or the slug of the repo for ' + sake.getPluginName() + ' are missing, skipping')) + return done() + } - let github = getGithub(sake.options.owner === sake.config.deploy.production.owner ? 'production' : 'dev') + let github = getGithub(sake.options.owner === sake.config.deploy.production.owner ? 'production' : 'dev') - let version = sake.getPluginVersion() - let zipName = `${sake.config.plugin.id}.${version}.zip` - let zipPath = path.join(process.cwd(), sake.config.paths.build, zipName) - let tasks = [] + let version = sake.getPluginVersion() + let zipName = `${sake.config.plugin.id}.${version}.zip` + let zipPath = path.join(process.cwd(), sake.config.paths.build, zipName) + let tasks = [] - // prepare a zip if it doesn't already exist - if (!fs.existsSync(zipPath)) { - tasks.push(sake.options.deploy ? 'compress' : 'zip') - } + // prepare a zip if it doesn't already exist + if (! fs.existsSync(zipPath)) { + tasks.push(sake.options.deploy ? 'compress' : 'zip') + } - log(`Creating GH release ${version} for ${owner}/${repo}`) + log(`Creating GH release ${version} for ${owner}/${repo}`) - tasks.push(function (cb) { - github.repos.createRelease({ - owner: owner, - repo: repo, - tag_name: sake.options.prefix_release_tag ? sake.config.plugin.id + '-' + version : version, - name: sake.getPluginName(false) + ' v' + version, - body: sake.getPluginChanges() - }).then((result) => { - log('GH release created') + tasks.push(function (cb) { + github.repos.createRelease({ + owner: owner, + repo: repo, + tag_name: sake.options.prefix_release_tag ? sake.config.plugin.id + '-' + version : version, + name: sake.getPluginName(false) + ' v' + version, + body: sake.getPluginChanges() + }).then((result) => { + log('GH release created') - sake.options.release_url = result.data.html_url + sake.options.release_url = result.data.html_url - github.repos.uploadReleaseAsset({ - url: result.data.upload_url, - name: zipName, - data: fs.readFileSync(zipPath), - headers: { - 'content-type': 'application/zip', - 'content-length': fs.statSync(zipPath).size - } - }).then(() => { - log('Plugin zip uploaded') - cb() - }).catch((err) => { - sake.throwError('Uploading release ZIP failed: ' + err.toString()) - }) + github.repos.uploadReleaseAsset({ + url: result.data.upload_url, + name: zipName, + data: fs.readFileSync(zipPath), + headers: { + 'content-type': 'application/zip', + 'content-length': fs.statSync(zipPath).size + } + }).then(() => { + log('Plugin zip uploaded') + cb() }).catch((err) => { - sake.throwError('Creating GH release failed: ' + err.toString()) + sake.throwError('Uploading release ZIP failed: ' + err.toString()) }) + }).catch((err) => { + sake.throwError('Creating GH release failed: ' + err.toString()) }) - - gulp.series(tasks)(done) }) - // create release milestones for each tuesday - gulp.task('github:create_release_milestones', (done) => { - let year = sake.options.year || new Date().getFullYear() - let tuesdays = getTuesdays(year) + gulp.series(tasks)(done) +} +gitHubCreateReleaseTask.displayName = 'github:create_release' - createMilestones(tuesdays, done) +/** + * Create release milestones for each Tuesday + */ +const gitHubCreateReleaseMilestonesTask = (done) => { + let year = sake.options.year || new Date().getFullYear() + let tuesdays = getTuesdays(year) - // helper function to get all tuesdays of a year - function getTuesdays (y) { - // ensure year is an integer - y = parseInt(y, 10) + createMilestones(tuesdays, done) - let d = new Date(y, 0, 1) - let tuesdays = [] + // helper function to get all tuesdays of a year + function getTuesdays (y) { + // ensure year is an integer + y = parseInt(y, 10) - // get the first Tuesday in January - d.setDate(d.getDate() + (9 - d.getDay()) % 7) + let d = new Date(y, 0, 1) + let tuesdays = [] - while (y === d.getFullYear()) { - let date = new Date(d.getTime()) - tuesdays.push({ date: date, name: `Deploy on ${dateFormat(date, 'mm/dd')}` }) - d.setDate(d.getDate() + 7) - } + // get the first Tuesday in January + d.setDate(d.getDate() + (9 - d.getDay()) % 7) - return tuesdays + while (y === d.getFullYear()) { + let date = new Date(d.getTime()) + tuesdays.push({ date: date, name: `Deploy on ${dateFormat(date, 'mm/dd')}` }) + d.setDate(d.getDate() + 7) } - }) - // create monthly milestones - gulp.task('github:create_month_milestones', (done) => { - let year = sake.options.year || new Date().getFullYear() + return tuesdays + } +} +gitHubCreateReleaseMilestonesTask.displayName = 'github:create_release_milestones' - createMilestones(getMonthlyMilestones(year), done) +/** + * Create monthly milestones + */ +const gitHubCreateMonthMilestonesTask = (done) => { + let year = sake.options.year || new Date().getFullYear() - // helper to get all months in a year - function getMonthlyMilestones (y) { - // ensure year is an integer - y = parseInt(y, 10) + createMilestones(getMonthlyMilestones(year), done) - let months = [] + // helper to get all months in a year + function getMonthlyMilestones (y) { + // ensure year is an integer + y = parseInt(y, 10) - for (let i = 0; i < 12; i++) { - let d = new Date(y, i + 1, 0) - months.push({ date: d, name: dateFormat(d, 'mmmm yyyy') }) - } + let months = [] - return months + for (let i = 0; i < 12; i++) { + let d = new Date(y, i + 1, 0) + months.push({ date: d, name: dateFormat(d, 'mmmm yyyy') }) } - }) - // create a milestone for each date passed in - const createMilestones = (milestones, done) => { - let owner = sake.options.owner || sake.config.deploy.dev.owner - let repo = sake.options.repo || sake.config.deploy.dev.name - let github = getGithub(sake.options.owner === sake.config.deploy.production.owner ? 'production' : 'dev') + return months + } +} +gitHubCreateMonthMilestonesTask.displayName = 'github:create_month_milestones' - async.eachLimit(milestones, 5, function (milestone, cb) { - let description = codename.generate(['unique', 'alliterative', 'random'], ['adjectives', 'animals']).join(' ') - let formattedDate = dateFormat(milestone.date, 'yyyy-mm-dd') +// create a milestone for each date passed in +const createMilestones = (milestones, done) => { + let owner = sake.options.owner || sake.config.deploy.dev.owner + let repo = sake.options.repo || sake.config.deploy.dev.name + let github = getGithub(sake.options.owner === sake.config.deploy.production.owner ? 'production' : 'dev') - github.issues.createMilestone({ - owner: owner, - repo: repo, - title: milestone.name, - description: description, - due_on: milestone.date - }).then((result) => { - log.info(chalk.green(`Milestone ${description} for ${formattedDate} created!`)) - cb() - }).catch((err) => { - // format the error for readability - let formattedError = err - try { - if (err.message) { - err = JSON.parse(err.message) - } - formattedError = JSON.stringify(err, null, 2) - } catch (e) { } - log.error(chalk.red(`Error creating milestone ${description} for ${formattedDate}:`) + '\n' + formattedError) - }) - }, function (error) { - done(error) + async.eachLimit(milestones, 5, function (milestone, cb) { + let description = codename().generate(['unique', 'alliterative', 'random'], ['adjectives', 'animals']).join(' ') + let formattedDate = dateFormat(milestone.date, 'yyyy-mm-dd') + + github.issues.createMilestone({ + owner: owner, + repo: repo, + title: milestone.name, + description: description, + due_on: milestone.date + }).then((result) => { + log.info(chalk.green(`Milestone ${description} for ${formattedDate} created!`)) + cb() + }).catch((err) => { + // format the error for readability + let formattedError = err + try { + if (err.message) { + err = JSON.parse(err.message) + } + formattedError = JSON.stringify(err, null, 2) + } catch (e) { } + log.error(chalk.red(`Error creating milestone ${description} for ${formattedDate}:`) + '\n' + formattedError) }) - } + }, function (error) { + done(error) + }) +} + +export { + gitHubGetReleaseIssueTask, + gitHubGetWcIssuesTask, + gitHubCreateDocsIssueTask, + gitHubCreateReleaseTask, + gitHubCreateReleaseMilestonesTask, + gitHubCreateMonthMilestonesTask } diff --git a/tasks/imagemin.js b/tasks/imagemin.js index b2c637c..019d909 100644 --- a/tasks/imagemin.js +++ b/tasks/imagemin.js @@ -1,17 +1,25 @@ -const fs = require('fs') -const log = require('fancy-log') +import fs from 'node:fs'; +import log from 'fancy-log'; +import imagemin from 'gulp-imagemin' +import * as gulp from 'gulp' +import gulpif from 'gulp-if' +import sake from '../lib/sake.js' +import browserSync from 'browser-sync' -module.exports = (gulp, plugins, sake) => { - // optimize images - gulp.task('imagemin', () => { - if (! fs.existsSync(sake.config.paths.assetPaths.images)) { - log.info(`The directory ${sake.config.paths.assetPaths.images} does not exist.`) - return Promise.resolve() - } +const minifyImagesTask = (done) => { + if (! fs.existsSync(sake.config.paths.assetPaths.images)) { + log.info(`The directory ${sake.config.paths.assetPaths.images} does not exist.`) + return Promise.resolve() + } - return gulp.src(`${sake.config.paths.assetPaths.images}/**.*{png,jpg,gif,svg}`) - .pipe(plugins.imagemin()) - .pipe(gulp.dest(sake.config.paths.assetPaths.images)) - .pipe(plugins.if(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, plugins.browserSync.stream())) - }) + return gulp.src(`${sake.config.paths.assetPaths.images}/**.*{png,jpg,gif,svg}`) + .pipe(imagemin()) + .pipe(gulp.dest(sake.config.paths.assetPaths.images)) + .pipe(gulpif(() => sake.isWatching && sake.config.tasks.watch.useBrowserSync, browserSync.stream())) +} + +minifyImagesTask.displayName = 'imagemin' + +export { + minifyImagesTask } diff --git a/tasks/lint.js b/tasks/lint.js index f0022fd..8b3ed08 100644 --- a/tasks/lint.js +++ b/tasks/lint.js @@ -1,91 +1,112 @@ -const path = require('path') -const dottie = require('dottie') -const fs = require('fs') - -module.exports = (gulp, plugins, sake) => { - gulp.task('lint', gulp.parallel('lint:php', 'lint:scripts', 'lint:styles')) - - gulp.task('lint:php', (done) => { - let paths = [ - `${sake.config.paths.src}/**/*.php`, - `!${sake.config.paths.vendor}/**/*.php`, - `!**/node_modules/**/*.php` - ] - - // skip composer paths - if (sake.config.composer) { - let installerPaths = dottie.get(sake.config.composer, 'extra.installer-paths') - - if (installerPaths) { - Object.keys(installerPaths).forEach((vendorPath) => { - paths.push(`!${vendorPath}/**/*.php`) - }) - } - } +import path from 'node:path' +import dottie from 'dottie' +import fs from 'node:fs' +import * as gulp from 'gulp' +import sake from '../lib/sake.js' +import phplint from 'gulp-phplint' +import coffeelint from 'gulp-coffeelint' +import eslint from 'gulp-eslint' +import sassLint from 'gulp-sass-lint' +import { fileURLToPath } from 'node:url' +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const lintPhpTask = (done) => { + let paths = [ + `${sake.config.paths.src}/**/*.php`, + `!${sake.config.paths.vendor}/**/*.php`, + `!**/node_modules/**/*.php` + ] - return gulp.src(paths) - .pipe(plugins.phplint('', { skipPassedFiles: true, notify: false })) - .pipe(plugins.phplint.reporter((file) => { - let report = file.phplintReport || {} - // make sure to fail on first error - if (report.error) { - sake.throwError(`${report.message} on line ${report.line} of ${report.filename}`) - } - })) - }) - - // the main task to lint scripts - gulp.task('lint:scripts', gulp.parallel('lint:coffee', 'lint:js')) - - // lint coffee - gulp.task('lint:coffee', (done) => { - if (! fs.existsSync(sake.config.paths.assetPaths.js)) { - return Promise.resolve() + // skip composer paths + if (sake.config.composer) { + let installerPaths = dottie.get(sake.config.composer, 'extra.installer-paths') + + if (installerPaths) { + Object.keys(installerPaths).forEach((vendorPath) => { + paths.push(`!${vendorPath}/**/*.php`) + }) } + } - let coffeeLintFile = sake.options['coffeelint-file'] ? path.join(process.cwd(), sake.options['coffeelint-file']) : path.join(__dirname, '../lib/lintfiles/coffeelint.json') + return gulp.src(paths) + .pipe(phplint('', { skipPassedFiles: true, notify: false })) + .pipe(phplint.reporter((file) => { + let report = file.phplintReport || {} + // make sure to fail on first error + if (report.error) { + sake.throwError(`${report.message} on line ${report.line} of ${report.filename}`) + } + })) +} +lintPhpTask.displayName = 'lint:php' - return gulp.src(`${sake.config.paths.assetPaths.js}/**/*.coffee`) - .pipe(plugins.coffeelint(coffeeLintFile)) - .pipe(plugins.coffeelint.reporter()) - .pipe(plugins.coffeelint.reporter('fail')) // fail task on errors - .on('end', done) - .on('error', done) - }) +const lintCoffeeTask = (done) => { + if (! fs.existsSync(sake.config.paths.assetPaths.js)) { + return Promise.resolve() + } - // lint plain JS - gulp.task('lint:js', () => { - if (! fs.existsSync(sake.config.paths.assetPaths.js)) { - return Promise.resolve() - } + let coffeeLintFile = sake.options['coffeelint-file'] ? path.join(process.cwd(), sake.options['coffeelint-file']) : path.join(__dirname, '../lib/lintfiles/coffeelint.json') - // use WordPress standards - overrideable by individual plugins that provide a .eslintrc file - // see https://github.com/WordPress-Coding-Standards/eslint-config-wordpress/blob/master/index.js - let esLintFile = sake.options['eslint-configFile'] ? path.join(process.cwd(), sake.options['eslint-configFile']) : path.join(__dirname, '../lib/lintfiles/.eslintrc') - let esLintOptions = { - configFile: esLintFile, - quiet: false - } + return gulp.src(`${sake.config.paths.assetPaths.js}/**/*.coffee`) + .pipe(coffeelint(coffeeLintFile)) + .pipe(coffeelint.reporter()) + .pipe(coffeelint.reporter('fail')) // fail task on errors + .on('end', done) + .on('error', done) +} +lintCoffeeTask.displayName = 'lint:coffee' - return gulp.src(sake.config.paths.assetPaths.javascriptSources) - .pipe(plugins.eslint(esLintOptions)) - .pipe(plugins.eslint.format('table')) - }) +const lintJsTask = (done) => { + if (! fs.existsSync(sake.config.paths.assetPaths.js)) { + return Promise.resolve() + } - // main task for linting styles - gulp.task('lint:styles', gulp.parallel('lint:scss')) + // use WordPress standards - overrideable by individual plugins that provide a .eslintrc file + // see https://github.com/WordPress-Coding-Standards/eslint-config-wordpress/blob/master/index.js + let esLintFile = sake.options['eslint-configFile'] ? path.join(process.cwd(), sake.options['eslint-configFile']) : path.join(__dirname, '../lib/lintfiles/.eslintrc') + let esLintOptions = { + configFile: esLintFile, + quiet: false + } - // lint SCSS - gulp.task('lint:scss', (done) => { - if (! fs.existsSync(sake.config.paths.assetPaths.css)) { - return Promise.resolve() - } + return gulp.src(sake.config.paths.assetPaths.javascriptSources) + .pipe(eslint(esLintOptions)) + .pipe(eslint.format('table')) +} +lintJsTask.displayName = 'lint:js' + +const lintScssTask = (done) => { + if (! fs.existsSync(sake.config.paths.assetPaths.css)) { + return Promise.resolve() + } + + return gulp.src(`${sake.config.paths.assetPaths.css}/**/*.scss`) + .pipe(sassLint()) + .pipe(sassLint.failOnError()) // fail task on errors + // explicitly setting end and error event handlers will give us cleaner error logging + .on('end', done) + .on('error', done) +} +lintScssTask.displayName = 'lint:scss' + +// the main task to lint scripts +const lintScriptsTask = gulp.parallel(lintCoffeeTask, lintJsTask) +lintScriptsTask.displayName = 'lint:scripts' + +// the main task to lint styles +const lintStylesTask = gulp.parallel(lintScssTask) +lintStylesTask.displayName = 'lint:styles' + +const lintTask = gulp.parallel(lintPhpTask, lintScriptsTask, lintStylesTask) +lintTask.displayName = 'lint' - return gulp.src(`${sake.config.paths.assetPaths.css}/**/*.scss`) - .pipe(plugins.sassLint()) - .pipe(plugins.sassLint.failOnError()) // fail task on errors - // explicitly setting end and error event handlers will give us cleaner error logging - .on('end', done) - .on('error', done) - }) +export { + lintTask, + lintScriptsTask, + lintPhpTask, + lintCoffeeTask, + lintJsTask, + lintScssTask, + lintStylesTask } diff --git a/tasks/makepot.js b/tasks/makepot.js index 7ae0251..bc7330e 100644 --- a/tasks/makepot.js +++ b/tasks/makepot.js @@ -1,26 +1,29 @@ -const log = require('fancy-log') -const shell = require('shelljs') +import log from 'fancy-log' +import shell from 'shelljs' +import sake from '../lib/sake.js' -// generate POT files using wp cli -module.exports = (gulp, plugins, sake) => { - gulp.task('makepot', (done) => { - const options = sake.config.tasks.makepot - const domainPath = ( options.domainPath || 'i18n/languages' ) + '/' + sake.config.plugin.id + '.pot' - const excludedPaths = ['.github/.*', 'lib/.*', 'vendor/.*', 'tests/.*', 'node_modules/.*'] - const excluded = excludedPaths.map((path) => `--exclude="${path}"`).join(' ') - const headers = options.reportBugsTo ? `--headers='{"Report-Msgid-Bugs-To": "${options.reportBugsTo}"}'` : '' +const makepotTask = (done) => { + const options = sake.config.tasks.makepot + const domainPath = ( options.domainPath || 'i18n/languages' ) + '/' + sake.config.plugin.id + '.pot' + const excludedPaths = ['.github/.*', 'lib/.*', 'vendor/.*', 'tests/.*', 'node_modules/.*'] + const excluded = excludedPaths.map((path) => `--exclude="${path}"`).join(' ') + const headers = options.reportBugsTo ? `--headers='{"Report-Msgid-Bugs-To": "${options.reportBugsTo}"}'` : '' - log.info('Generating POT file...') + log.info('Generating POT file...') - let result = shell.exec(`wp i18n make-pot . ${domainPath} ${headers} ${excluded}`) + let result = shell.exec(`wp i18n make-pot . ${domainPath} ${headers} ${excluded}`) - if (result.code !== 0) { - sake.throwError(`Error while generating POT file: ${result.stderr ?? 'unknown error.'}`) - done(result.stderr) - } else { - log.info(result.stdout) - log.error(result.stderr) - done() - } - }) + if (result.code !== 0) { + sake.throwError(`Error while generating POT file: ${result.stderr ?? 'unknown error.'}`) + done(result.stderr) + } else { + log.info(result.stdout) + log.error(result.stderr) + done() + } +} +makepotTask.displayName = 'makepot' + +export { + makepotTask } diff --git a/tasks/prerelease.js b/tasks/prerelease.js index 84b9518..4421adb 100644 --- a/tasks/prerelease.js +++ b/tasks/prerelease.js @@ -1,36 +1,49 @@ -const fs = require('fs') - -module.exports = (gulp, plugins, sake) => { - // validate env variables before deploying a prerelease - function validateEnvVariables () { - let errors = [] - let prereleasePath = '' - - if (process.env.SAKE_PRE_RELEASE_PATH) { - prereleasePath = sake.resolvePath(process.env.SAKE_PRE_RELEASE_PATH) - } else { - errors.push('SAKE_PRE_RELEASE_PATH not set') - } - - if (prereleasePath && !fs.existsSync(prereleasePath)) { - errors.push(`SAKE_PRE_RELEASE_PATH is invalid - the path '${prereleasePath}' does not exist`) - } - - if (errors.length) { - sake.throwError('Environment variables missing or invalid: \n * ' + errors.join('\n * ')) - } +import fs from 'node:fs' +import sake from '../lib/sake.js' +import gulp from 'gulp' +import { bumpTask } from './bump.js' +import { zipTask } from './zip.js' +import { cleanBuildTask, cleanPrereleaseTask } from './clean.js' +import { copyPrereleaseTask } from './copy.js' + +// validate env variables before deploying a prerelease +function validateEnvVariables () { + let errors = [] + let prereleasePath = '' + + if (process.env.SAKE_PRE_RELEASE_PATH) { + prereleasePath = sake.resolvePath(process.env.SAKE_PRE_RELEASE_PATH) + } else { + errors.push('SAKE_PRE_RELEASE_PATH not set') } - // bumps the version in the main plugin file to match changelog.txt - gulp.task('prerelease', (done) => { - validateEnvVariables() + if (prereleasePath && !fs.existsSync(prereleasePath)) { + errors.push(`SAKE_PRE_RELEASE_PATH is invalid - the path '${prereleasePath}' does not exist`) + } + + if (errors.length) { + sake.throwError('Environment variables missing or invalid: \n * ' + errors.join('\n * ')) + } +} - if (!sake.isDeployable()) { - sake.throwError('Plugin is not deployable: \n * ' + sake.getChangelogErrors().join('\n * ')) - } +/** + * Bumps the version in the main plugin file to match changelog.txt + */ +const prereleaseTask = (done) => { + validateEnvVariables() + + if (!sake.isDeployable()) { + sake.throwError('Plugin is not deployable: \n * ' + sake.getChangelogErrors().join('\n * ')) + } + + gulp.series(bumpTask, zipTask, cleanPrereleaseTask, copyPrereleaseTask, cleanBuildTask)(done) +} +prereleaseTask.displayName = 'prerelease' - gulp.series('bump', 'zip', 'clean:prerelease', 'copy:prerelease', 'clean:build')(done) - }) +const preTask = gulp.parallel(prereleaseTask) +preTask.displayName = 'pre' - gulp.task('pre', gulp.parallel('prerelease')) +export { + prereleaseTask, + preTask } diff --git a/tasks/prompt.js b/tasks/prompt.js index 39fde3b..94f4392 100644 --- a/tasks/prompt.js +++ b/tasks/prompt.js @@ -1,126 +1,142 @@ -const inquirer = require('inquirer') -const semver = require('semver') -const log = require('fancy-log') -const chalk = require('chalk') -const _ = require('lodash') +import inquirer from 'inquirer' +import semver from 'semver' +import log from 'fancy-log' +import chalk from 'chalk' +import _ from 'lodash' +import sake from '../lib/sake.js' +import gulp from 'gulp' +import { wcDeployTask } from './wc.js' -module.exports = (gulp, plugins, sake) => { - // internal task for prompting the deploy version - gulp.task('prompt:deploy', (done) => { - let currentVersion = sake.getPluginVersion() +function filterIncrement (value) { + if (value[1] === 'custom') { + return 'custom' + } + + if (value[1] === 'skip') { + return 'skip' + } + + return semver.inc(value[0], value[1]) +} + +function getDefault () { + let value = 1 + + switch (sake.getDefaultIncrement()) { + case 'minor': + value = 2 + break + + case 'major': + value = 3 + break + } + + return value +} + +/** + * Internal task for prompting the deploy action + */ +const promptDeployTask = (done) => { + let currentVersion = sake.getPluginVersion() - inquirer.prompt([ - { - name: 'version', - type: 'list', - message: 'Plugin Changelog: \n' + sake.readChangelog() + '\n\nBump version from ' + chalk.cyan(currentVersion) + ' to:', - 'default': getDefault(), - choices: [ - { - value: [ currentVersion, 'prerelease' ], - name: chalk.yellow('Build: ' + sake.getPluginVersion('prerelease')) + + inquirer.prompt([ + { + name: 'version', + type: 'list', + message: 'Plugin Changelog: \n' + sake.readChangelog() + '\n\nBump version from ' + chalk.cyan(currentVersion) + ' to:', + 'default': getDefault(), + choices: [ + { + value: [ currentVersion, 'prerelease' ], + name: chalk.yellow('Build: ' + sake.getPluginVersion('prerelease')) + ' Unstable, betas, and release candidates.' - }, - { - value: [ currentVersion, 'patch' ], - name: chalk.yellow('Patch: ' + sake.getPluginVersion('patch')) + + }, + { + value: [ currentVersion, 'patch' ], + name: chalk.yellow('Patch: ' + sake.getPluginVersion('patch')) + ' Backwards-compatible bug fixes.' - }, - { - value: [ currentVersion, 'minor' ], - name: chalk.yellow('Minor: ' + sake.getPluginVersion('minor')) + + }, + { + value: [ currentVersion, 'minor' ], + name: chalk.yellow('Minor: ' + sake.getPluginVersion('minor')) + ' Add functionality in a backwards-compatible manner.' - }, - { - value: [ currentVersion, 'major' ], - name: chalk.yellow('Major: ' + sake.getPluginVersion('major')) + + }, + { + value: [ currentVersion, 'major' ], + name: chalk.yellow('Major: ' + sake.getPluginVersion('major')) + ' Incompatible API changes.' - }, - { - value: [ currentVersion, 'custom' ], - name: chalk.yellow('Custom: ?.?.?') + ' Specify version...' - }, - { - value: [ currentVersion, 'skip' ], - name: chalk.red('Skip this plugin') + ' This plugin will not be deployed' - } - ], - filter: filterIncrement - }, - { - name: 'version_custom', - type: 'input', - message: 'What specific version would you like', - when: function (answers) { - return _.values(answers).shift() === 'custom' }, - validate: function (value) { - var valid = semver.valid(value) && true - return valid || 'Must be a valid semver, such as 1.2.3-rc1. See ' + chalk.underline.blue('http://semver.org/') + ' for more details.' + { + value: [ currentVersion, 'custom' ], + name: chalk.yellow('Custom: ?.?.?') + ' Specify version...' + }, + { + value: [ currentVersion, 'skip' ], + name: chalk.red('Skip this plugin') + ' This plugin will not be deployed' } + ], + filter: filterIncrement + }, + { + name: 'version_custom', + type: 'input', + message: 'What specific version would you like', + when: function (answers) { + return _.values(answers).shift() === 'custom' + }, + validate: function (value) { + const valid = semver.valid(value) && true + return valid || 'Must be a valid semver, such as 1.2.3-rc1. See ' + chalk.underline.blue('https://semver.org/') + ' for more details.' } - ]).then(function (answers) { - sake.options = _.merge(sake.options, answers) - done() - }) - }) - - // internal task for prompting whether to upload the plugin to woo - gulp.task('prompt:wc_upload', (done) => { - inquirer.prompt([{ - type: 'confirm', - name: 'upload_to_wc', - message: 'Upload plugin to WooCommerce.com?' - }]).then((answers) => { - if (answers.upload_to_wc) { - gulp.series('wc:deploy')(done) - } else { - log.error(chalk.red('Skipped uploading to WooCommerce.com')) - done() - } - }) - }) - - // internal task for prompting whether the release has been tested - gulp.task('prompt:tested_release_zip', (done) => { - inquirer.prompt([{ - type: 'confirm', - name: 'tested_release_zip', - message: 'Has the generated zip file for this release been tested?' - }]).then((answers) => { - if (answers.tested_release_zip) { - done() - } else { - sake.throwError('Run npx sake zip to generate a zip of this release and test it on a WordPress installation.') - } - }) - }) - - function filterIncrement (value) { - if (value[1] === 'custom') { - return 'custom' } + ]).then(function (answers) { + sake.options = _.merge(sake.options, answers) + done() + }) +} +promptDeployTask.displayName = 'prompt:deploy' - if (value[1] === 'skip') { - return 'skip' +/** + * Internal task for prompting whether to upload the plugin to WooCommerce + */ +const promptWcUploadTask = (done) => { + inquirer.prompt([{ + type: 'confirm', + name: 'upload_to_wc', + message: 'Upload plugin to WooCommerce.com?' + }]).then((answers) => { + if (answers.upload_to_wc) { + gulp.series(wcDeployTask)(done) + } else { + log.error(chalk.red('Skipped uploading to WooCommerce.com')) + done() } + }) +} +promptWcUploadTask.displayName = 'prompt:wc_upload' - return semver.inc(value[0], value[1]) - } - - function getDefault () { - var value = 1 - - switch (sake.getDefaultIncrement()) { - case 'minor': - value = 2 - break - - case 'major': - value = 3 - break +/** + * Internal task for prompting whether the release has been tested + */ +const promptTestedReleaseZipTask = (done) => { + inquirer.prompt([{ + type: 'confirm', + name: 'tested_release_zip', + message: 'Has the generated zip file for this release been tested?' + }]).then((answers) => { + if (answers.tested_release_zip) { + done() + } else { + sake.throwError('Run npx sake zip to generate a zip of this release and test it on a WordPress installation.') } + }) +} +promptTestedReleaseZipTask.displayName = 'prompt:tested_release_zip' - return value - } +export { + promptDeployTask, + promptWcUploadTask, + promptTestedReleaseZipTask } diff --git a/tasks/scripts.js b/tasks/scripts.js index 216baf3..dab4199 100644 --- a/tasks/scripts.js +++ b/tasks/scripts.js @@ -1,18 +1,37 @@ -module.exports = (gulp, plugins, sake) => { - // main task for (optionally) linting and compiling scripts - gulp.task('scripts', (done) => { - let tasks = ['lint:scripts', 'compile:scripts'] - - // don't lint styles if they have already been linted, unless we're watching - if (!sake.isWatching && gulp.lastRun('lint:scripts')) { - tasks.shift() - } - - gulp.series(tasks)(done) - }) - - // type-specific script tasks - lints and then compiles - gulp.task('scripts:coffee', gulp.series('lint:coffee', 'compile:coffee')) - gulp.task('scripts:js', gulp.series('lint:js', 'compile:js')) - gulp.task('scripts:blocks', gulp.series('compile:blocks')) +import gulp from 'gulp' +import { lintCoffeeTask, lintJsTask, lintScriptsTask } from './lint.js' +import { compileBlocksTask, compileCoffeeTask, compileJsTask, compileScripts } from './compile.js' +import sake from '../lib/sake.js' + +/** + * The main task + */ +const scriptsTask = (done) => { + let tasks = [lintScriptsTask, compileScripts] + + // don't lint styles if they have already been linted, unless we're watching + if (! sake.isWatching && gulp.lastRun(lintScriptsTask)) { + tasks.shift() + } + + gulp.series(tasks)(done) +} +scriptsTask.displayName = 'scripts' + +/** type-specific script tasks - lints and then compiles */ + +const scriptsCoffee = gulp.series(lintCoffeeTask, compileCoffeeTask) +scriptsCoffee.displayName = 'scripts:coffee' + +const scriptsJs = gulp.series(lintJsTask, compileJsTask) +scriptsJs.displayName = 'scripts:js' + +const scriptsBlocks = gulp.series(compileBlocksTask) +scriptsBlocks.displayName = 'compile:blocks' + +export { + scriptsTask, + scriptsCoffee, + scriptsJs, + scriptsBlocks } diff --git a/tasks/shell.js b/tasks/shell.js index 7b15759..0299b56 100644 --- a/tasks/shell.js +++ b/tasks/shell.js @@ -1,263 +1,318 @@ -const fs = require('fs') -const path = require('path') -const log = require('fancy-log') -const shell = require('shelljs') -const _str = require('underscore.string') - -module.exports = (gulp, plugins, sake) => { - const awk = process.platform === 'win32' ? 'gawk' : 'awk' - const noRunIfEmpty = process.platform !== 'darwin' ? '--no-run-if-empty ' : '' - - // run a shell command, preserving output and failing the task on errors - const exec = (command, opts, done) => { - log.info('$ ' + command) - - if (typeof opts === 'function') { - done = opts - opts = {} - } - - shell.exec(command, opts, (code) => done(code > 0 ? 'Command failed [exit code ' + code + ']: ' + command : null)) +import fs from 'node:fs' +import path from 'node:path' +import log from 'fancy-log' +import shell from 'shelljs' +import _str from 'underscore.string' +import sake from '../lib/sake.js' +import gulp from 'gulp' + +const awk = process.platform === 'win32' ? 'gawk' : 'awk' +const noRunIfEmpty = process.platform !== 'darwin' ? '--no-run-if-empty ' : '' + +// run a shell command, preserving output and failing the task on errors +const exec = (command, opts, done) => { + log.info('$ ' + command) + + if (typeof opts === 'function') { + done = opts + opts = {} } - // update framework subtree - gulp.task('shell:update_framework', (done) => { - if (!sake.config.framework) { - sake.throwError('Not a frameworked plugin, aborting') - } - - let command = '' - - if (sake.config.framework === 'v4') { - let frameworkPath = path.join(process.cwd(), sake.config.paths.src, sake.config.paths.framework.base) - - if (fs.existsSync(frameworkPath)) { - let branch = sake.options.branch || 'legacy-v4' - let prefix = path.join((sake.config.multiPluginRepo ? sake.config.plugin.id : '.'), sake.config.paths.framework.base) - - command = [ - 'git fetch wc-plugin-framework ' + branch, - 'git status', - 'git subtree pull --prefix ' + prefix + ' wc-plugin-framework ' + branch + ' --squash', - 'echo subtree up to date!' - ] - - if (sake.config.multiPluginRepo) { - command.unshift('cd ../') - } + shell.exec(command, opts, (code) => done(code > 0 ? 'Command failed [exit code ' + code + ']: ' + command : null)) +} - command = command.join(' && ') - } else { - command = 'echo no subtree to update' - } - } +/** + * Update framework subtree + */ +const shellUpdateFrameworkTask = (done) => { + if (!sake.config.framework) { + sake.throwError('Not a frameworked plugin, aborting') + } - exec(command, done) - }) + let command = '' - // commit framework update - gulp.task('shell:update_framework_commit', (done) => { + if (sake.config.framework === 'v4') { let frameworkPath = path.join(process.cwd(), sake.config.paths.src, sake.config.paths.framework.base) - let command = '' if (fs.existsSync(frameworkPath)) { + let branch = sake.options.branch || 'legacy-v4' + let prefix = path.join((sake.config.multiPluginRepo ? sake.config.plugin.id : '.'), sake.config.paths.framework.base) + command = [ - 'git add -A', - 'git diff-index --quiet --cached HEAD || git commit -m "' + sake.config.plugin.name + ': Update framework to v' + sake.config.plugin.frameworkVersion + '"' - ].join(' && ') - } else { - // TODO: is this still necessary? {IT 2018-03-21} - command = [ - 'git add -A', - 'git diff-index --quiet --cached HEAD || git commit -m "' + sake.config.plugin.name + ': Update readme.txt"' + 'git fetch wc-plugin-framework ' + branch, + 'git status', + 'git subtree pull --prefix ' + prefix + ' wc-plugin-framework ' + branch + ' --squash', + 'echo subtree up to date!' ] - } - exec(command, done) - }) + if (sake.config.multiPluginRepo) { + command.unshift('cd ../') + } - // ensure the working copy (git tree) has no uncommited changes - gulp.task('shell:git_ensure_clean_working_copy', (done) => { - let command = [ - 'git diff-index --quiet HEAD' - ].join(' && ') + command = command.join(' && ') + } else { + command = 'echo no subtree to update' + } + } - shell.exec(command, (code) => { - if (!code) return done() + exec(command, done) +} +shellUpdateFrameworkTask.displayName = 'shell:update_framework' - shell.exec('git status', () => { - sake.throwError('Working copy is not clean!') - }) - }) - }) +/** + * Commit framework update + */ +const shellUpdateFrameworkCommitTask = (done) => { + let frameworkPath = path.join(process.cwd(), sake.config.paths.src, sake.config.paths.framework.base) + let command = '' - // commit and push update - gulp.task('shell:git_push_update', (done) => { - let command = [ + if (fs.existsSync(frameworkPath)) { + command = [ 'git add -A', - 'git commit -m "' + sake.config.plugin.name + ': ' + sake.getPluginVersion() + ' Versioning"' + (sake.options.release_issue_to_close ? ' -m "Closes #' + sake.options.release_issue_to_close + '"' : ''), - 'git push', - 'echo git up to date!' + 'git diff-index --quiet --cached HEAD || git commit -m "' + sake.config.plugin.name + ': Update framework to v' + sake.config.plugin.frameworkVersion + '"' ].join(' && ') + } else { + // TODO: is this still necessary? {IT 2018-03-21} + command = [ + 'git add -A', + 'git diff-index --quiet --cached HEAD || git commit -m "' + sake.config.plugin.name + ': Update readme.txt"' + ] + } - exec(command, done) - }) + exec(command, done) +} +shellUpdateFrameworkCommitTask.displayName = 'shell:update_framework_commit' - // pull updates from WC repo, or clone repo, if deploying for the first time - gulp.task('shell:git_pull_wc_repo', (done) => { - let command = [] +/** + * Ensure the working copy (git tree) has no uncommitted changes + */ +const shellGitEnsureCleanWorkingCopyTask = (done) => { + let command = [ + 'git diff-index --quiet HEAD' + ].join(' && ') - if (!fs.existsSync(sake.getProductionRepoPath())) { - // ensure that the tmp dir exists - if (!fs.existsSync(sake.config.paths.tmp)) { - shell.mkdir('-p', sake.config.paths.tmp) - } + shell.exec(command, (code) => { + if (!code) return done() - // repo does not exist yet - command = [ - 'cd ' + sake.config.paths.tmp, - 'git clone ' + sake.config.deploy.production.url - ] - } else { - // repo already exists - command = [ - 'cd ' + sake.getProductionRepoPath(), - 'git pull && git push' - ] - } - - shell.exec(command.join(' && '), (code, stdout, stderr) => { - // ignore missing ref error - this will happen when the remote repo is empty (for example, a new WC plugin) - // and we try to `git pull` - if (code === 1 && stderr.indexOf('Your configuration specifies to merge with the ref') > -1) { - return done() - } else { - return done(code > 0 ? 'Command failed [exit code ' + code + ']: ' + command : null) - } + shell.exec('git status', () => { + sake.throwError('Working copy is not clean!') }) }) +} +shellGitEnsureCleanWorkingCopyTask.displayName = 'shell:git_ensure_clean_working_copy' + +/** + * Commit and push update + */ +const shellGitPushUpdateTask = (done) => { + const command = [ + 'git add -A', + 'git commit -m "' + sake.config.plugin.name + ': ' + sake.getPluginVersion() + ' Versioning"' + (sake.options.release_issue_to_close ? ' -m "Closes #' + sake.options.release_issue_to_close + '"' : ''), + 'git push', + 'echo git up to date!' + ].join(' && ') + + exec(command, done) +} +shellGitPushUpdateTask.displayName = 'shell:git_push_update' - // commit and push update to WC repo - gulp.task('shell:git_push_wc_repo', (done) => { - let closeIssues = '' +/** + * Pull updates from WC repo, or clone repo, if deploying for the first time + * @deprecated We no longer use WC mirror repos + */ +const shellGitPullWcRepoTask = (done) => { + let command = [] - if (sake.options.wc_issues_to_close) { - closeIssues = ' -m "' + _str.capitalize(sake.options.wc_issues_to_close.map((issue) => `closes #${issue}`).join(', ')) + '"' + if (!fs.existsSync(sake.getProductionRepoPath())) { + // ensure that the tmp dir exists + if (!fs.existsSync(sake.config.paths.tmp)) { + shell.mkdir('-p', sake.config.paths.tmp) } - // always ensure to pull the repo, but bypass the missing ref error - gulp.series('shell:git_pull_wc_repo')((err) => { - if (err) sake.throwError(err) - - let command = [ - 'cd ' + sake.getProductionRepoPath(), - 'git add -A', - 'git commit -m "Update ' + sake.config.plugin.name + ' to ' + sake.getPluginVersion() + '"' + closeIssues, - 'git push' - ].join(' && ') + // repo does not exist yet + command = [ + 'cd ' + sake.config.paths.tmp, + 'git clone ' + sake.config.deploy.production.url + ] + } else { + // repo already exists + command = [ + 'cd ' + sake.getProductionRepoPath(), + 'git pull && git push' + ] + } - exec(command, done) - }) + shell.exec(command.join(' && '), (code, stdout, stderr) => { + // ignore missing ref error - this will happen when the remote repo is empty (for example, a new WC plugin) + // and we try to `git pull` + if (code === 1 && stderr.indexOf('Your configuration specifies to merge with the ref') > -1) { + return done() + } else { + return done(code > 0 ? 'Command failed [exit code ' + code + ']: ' + command : null) + } }) +} +shellGitPullWcRepoTask.displayName = 'shell:git_pull_wc_repo' + +/** + * Commit and push update to WC repo + * @deprecated We no longer use WC mirror repos + */ +const shellGitPushWcRepoTask = (done) => { + let closeIssues = '' + + if (sake.options.wc_issues_to_close) { + closeIssues = ' -m "' + _str.capitalize(sake.options.wc_issues_to_close.map((issue) => `closes #${issue}`).join(', ')) + '"' + } + + // always ensure to pull the repo, but bypass the missing ref error + gulp.series('shell:git_pull_wc_repo')((err) => { + if (err) sake.throwError(err) - // TODO: do we need this anymore? - // commit and push update, ver 2 - gulp.task('shell:git_update_wc_repo', (done) => { let command = [ 'cd ' + sake.getProductionRepoPath(), - 'git pull', 'git add -A', - 'git diff-index --quiet --cached HEAD || git commit -m "Updating ' + sake.config.plugin.name + '"', - 'git push', - 'echo WooCommerce repo up to date!' + 'git commit -m "Update ' + sake.config.plugin.name + ' to ' + sake.getPluginVersion() + '"' + closeIssues, + 'git push' ].join(' && ') exec(command, done) }) +} +shellGitPushWcRepoTask.displayName = 'shell:git_push_wc_repo' + +/** + * Commit and push update to WC repo, version 2 + * @deprecated We no longer use WooCommerce mirror repos + */ +const shellGitUpdateWcRepoTask = (done) => { + let command = [ + 'cd ' + sake.getProductionRepoPath(), + 'git pull', + 'git add -A', + 'git diff-index --quiet --cached HEAD || git commit -m "Updating ' + sake.config.plugin.name + '"', + 'git push', + 'echo WooCommerce repo up to date!' + ].join(' && ') + + exec(command, done) +} +shellGitUpdateWcRepoTask.displayName = 'shell:git_update_wc_repo' - // stash uncommitted changes - gulp.task('shell:git_stash', (done) => { - exec('git stash', done) - }) - - // apply latest stash - gulp.task('shell:git_stash_apply', (done) => { - exec('git stash apply', done) - }) - - gulp.task('shell:composer_status', (done) => { - if (fs.existsSync(path.join(process.cwd(), 'composer.json'))) { - exec('composer status -v', done) - } else { - log.info('No composer.json found, skipping composer status') - done() - } - }) - - gulp.task('shell:composer_install', (done) => { - if (fs.existsSync(path.join(process.cwd(), 'composer.json'))) { - exec('composer install --no-dev', done) - } else { - log.info('No composer.json found, skipping composer install') - done() - } - }) +/** + * Stash uncommitted changes + */ +const shellGitStashTask = (done) => { + exec('git stash', done) +} +shellGitStashTask.displayName = 'shell:git_stash' - gulp.task('shell:composer_update', (done) => { - if (fs.existsSync(path.join(process.cwd(), 'composer.json'))) { - exec('composer update --no-dev', done) - } else { - log.info('No composer.json found, skipping composer update') - done() - } - }) +/** + * Apply latest stash + */ +const shellGitStashApplyTask = (done) => { + exec('git stash apply', done) +} +shellGitStashApplyTask.displayName = 'shell:git_stash_apply' + +const shellComposerStatusTask = (done) => { + if (fs.existsSync(path.join(process.cwd(), 'composer.json'))) { + exec('composer status -v', done) + } else { + log.info('No composer.json found, skipping composer status') + done() + } +} +shellComposerStatusTask.displayName = 'shell:composer_status' + +const shellComposerInstallTask = (done) => { + if (fs.existsSync(path.join(process.cwd(), 'composer.json'))) { + exec('composer install --no-dev', done) + } else { + log.info('No composer.json found, skipping composer install') + done() + } +} +shellComposerInstallTask.displayName = 'shell:composer_install' + +const shellComposerUpdateTask = (done) => { + if (fs.existsSync(path.join(process.cwd(), 'composer.json'))) { + exec('composer update --no-dev', done) + } else { + log.info('No composer.json found, skipping composer update') + done() + } +} +shellComposerUpdateTask.displayName = 'shell:composer_update' - gulp.task('shell:svn_checkout', (done) => { - // ensure that the tmp dir exists - if (!fs.existsSync(sake.config.paths.tmp)) { - shell.mkdir('-p', sake.config.paths.tmp) - } +const shellSvnCheckoutTask = (done) => { + // ensure that the tmp dir exists + if (!fs.existsSync(sake.config.paths.tmp)) { + shell.mkdir('-p', sake.config.paths.tmp) + } - let command = 'svn co --force-interactive ' + sake.config.deploy.production.url + ' ' + sake.getProductionRepoPath() + let command = 'svn co --force-interactive ' + sake.config.deploy.production.url + ' ' + sake.getProductionRepoPath() - exec(command, done) - }) + exec(command, done) +} +shellSvnCheckoutTask.displayName = 'shell:svn_checkout' - gulp.task('shell:svn_commit_trunk', (done) => { - const commitMsg = 'Committing ' + sake.getPluginVersion() + ' to trunk' +const shellSvnCommitTrunkTask = (done) => { + const commitMsg = 'Committing ' + sake.getPluginVersion() + ' to trunk' - let command = [ - 'cd ' + path.join(sake.getProductionRepoPath(), 'trunk'), - 'svn status | ' + awk + " '/^[?]/{print $2}' | xargs " + noRunIfEmpty + 'svn add', - 'svn status | ' + awk + " '/^[!]/{print $2}' | xargs " + noRunIfEmpty + 'svn delete', - 'svn commit --force-interactive --username="' + sake.config.deploy.production.user + '" -m "' + commitMsg + '"' - ].join(' && ') + let command = [ + 'cd ' + path.join(sake.getProductionRepoPath(), 'trunk'), + 'svn status | ' + awk + " '/^[?]/{print $2}' | xargs " + noRunIfEmpty + 'svn add', + 'svn status | ' + awk + " '/^[!]/{print $2}' | xargs " + noRunIfEmpty + 'svn delete', + 'svn commit --force-interactive --username="' + sake.config.deploy.production.user + '" -m "' + commitMsg + '"' + ].join(' && ') - exec(command, done) - }) + exec(command, done) +} +shellSvnCommitTrunkTask.displayName = 'shell:svn_commit_trunk' - gulp.task('shell:svn_commit_tag', (done) => { - const commitMsg = 'Tagging ' + sake.getPluginVersion() +const shellSvnCommitTagTask = (done) => { + const commitMsg = 'Tagging ' + sake.getPluginVersion() - let command = [ - 'cd ' + path.join(sake.getProductionRepoPath(), 'tags', sake.getPluginVersion()), - 'svn add .', - 'svn commit --force-interactive --username="' + sake.config.deploy.production.user + '" -m "' + commitMsg + '"' - ].join(' && ') + let command = [ + 'cd ' + path.join(sake.getProductionRepoPath(), 'tags', sake.getPluginVersion()), + 'svn add .', + 'svn commit --force-interactive --username="' + sake.config.deploy.production.user + '" -m "' + commitMsg + '"' + ].join(' && ') - exec(command, done) - }) + exec(command, done) +} +shellSvnCommitTagTask.displayName = 'shell:svn_commit_tag' - gulp.task('shell:svn_commit_assets', (done) => { - const commitMsg = 'Committing assets for ' + sake.getPluginVersion() +const shellSvnCommitAssetsTask = (done) => { + const commitMsg = 'Committing assets for ' + sake.getPluginVersion() - let command = [ - 'cd ' + path.join(sake.getProductionRepoPath(), 'assets'), - 'svn status | ' + awk + " '/^[?]/{print $2}' | xargs " + noRunIfEmpty + 'svn add', - 'svn status | ' + awk + " '/^[!]/{print $2}' | xargs " + noRunIfEmpty + 'svn delete', - 'svn commit --force-interactive --username="' + sake.config.deploy.production.user + '" -m "' + commitMsg + '"' - ].join(' && ') + let command = [ + 'cd ' + path.join(sake.getProductionRepoPath(), 'assets'), + 'svn status | ' + awk + " '/^[?]/{print $2}' | xargs " + noRunIfEmpty + 'svn add', + 'svn status | ' + awk + " '/^[!]/{print $2}' | xargs " + noRunIfEmpty + 'svn delete', + 'svn commit --force-interactive --username="' + sake.config.deploy.production.user + '" -m "' + commitMsg + '"' + ].join(' && ') - exec(command, done) - }) + exec(command, done) +} +shellSvnCommitAssetsTask.displayName = 'shell:svn_commit_assets' + +export { + shellUpdateFrameworkTask, + shellUpdateFrameworkCommitTask, + shellGitEnsureCleanWorkingCopyTask, + shellGitPushUpdateTask, + shellGitPullWcRepoTask, + shellGitPushWcRepoTask, + shellGitUpdateWcRepoTask, + shellGitStashTask, + shellGitStashApplyTask, + shellComposerStatusTask, + shellComposerInstallTask, + shellComposerUpdateTask, + shellSvnCheckoutTask, + shellSvnCommitTrunkTask, + shellSvnCommitTagTask, + shellSvnCommitAssetsTask } diff --git a/tasks/styles.js b/tasks/styles.js index 52cc70c..14a3af3 100644 --- a/tasks/styles.js +++ b/tasks/styles.js @@ -1,13 +1,20 @@ -module.exports = (gulp, plugins, sake) => { - // main task for (optionally) linting and compiling styles - gulp.task('styles', (done) => { - let tasks = ['lint:styles', 'compile:styles'] - - // don't lint styles if they have already been linted, unless we're watching - if (!sake.isWatching && gulp.lastRun('lint:styles')) { - tasks.shift() - } - - gulp.series(tasks)(done) - }) +import gulp from 'gulp' +import sake from '../lib/sake.js' +import { lintStylesTask } from './lint.js' +import { compileStyles } from './compile.js' + +const stylesTask = (done) => { + let tasks = [lintStylesTask, compileStyles] + + // don't lint styles if they have already been linted, unless we're watching + if (!sake.isWatching && gulp.lastRun(lintStylesTask)) { + tasks.shift() + } + + gulp.series(tasks)(done) +} +stylesTask.displayName = 'styles' + +export { + stylesTask } diff --git a/tasks/upfw.js b/tasks/upfw.js index 8b76fb7..0597b63 100644 --- a/tasks/upfw.js +++ b/tasks/upfw.js @@ -1,48 +1,61 @@ -const fs = require('fs') -const path = require('path') -const dottie = require('dottie') - -module.exports = (gulp, plugins, sake) => { - // reload the framework version after updating the framework - gulp.task('set_framework_version', (done) => { - sake.config.plugin.frameworkVersion = sake.getFrameworkVersion() - done() - }) - - // update framework to a specific version or branch - // example use: `sake upfw` or `sake upfw --backwards_compatible=4.4 --minimum_wc_version=2.5.5 --tested_up_to_wc_version=2.7.0 --minimum_wp_version=4.1 --tested_up_to_wp_version=4.6` - gulp.task('upfw', (done) => { - let tasks = [ - 'set_framework_version', - 'bump:minreqs', - 'shell:update_framework_commit' - ] - - if (sake.config.framework === 'v4' && !dottie.get(sake.config.composer, 'require.skyverge/wc-plugin-framework')) { - tasks.unshift('shell:update_framework') - } - - if (sake.config.framework === 'v5') { - tasks.unshift('bump:framework_version') +import fs from 'node:fs' +import path from 'node:path' +import dottie from 'dottie' +import sake from '../lib/sake.js' +import gulp from 'gulp' +import { bumpFrameworkVersionTask, bumpMinReqsTask } from './bump.js' +import { shellComposerUpdateTask, shellUpdateFrameworkCommitTask, shellUpdateFrameworkTask } from './shell.js' + +/** + * Reload the framework version after updating the framework + */ +const setFrameworkVersionTask = (done) => { + sake.config.plugin.frameworkVersion = sake.getFrameworkVersion() + done() +} +setFrameworkVersionTask.displayName = 'set_framework_version' + +/** + * Update the framework to a specific version or branch + * example use: `sake upfw` or `sake upfw --backwards_compatible=4.4 --minimum_wc_version=2.5.5 --tested_up_to_wc_version=2.7.0 --minimum_wp_version=4.1 --tested_up_to_wp_version=4.6` + */ +const updateFrameworkTask = (done) => { + let tasks = [ + setFrameworkVersionTask, + bumpMinReqsTask, + shellUpdateFrameworkCommitTask + ] + + if (sake.config.framework === 'v4' && !dottie.get(sake.config.composer, 'require.skyverge/wc-plugin-framework')) { + tasks.unshift(shellUpdateFrameworkTask) + } + + if (sake.config.framework === 'v5') { + tasks.unshift(bumpFrameworkVersionTask) + } + + // update composer + if (!sake.options['skip-composer-update']) { + // ensure FW version to update to is specified + if (!sake.options.framework_version) { + sake.throwError('Framework version not specified') } - // update composer - if (!sake.options['skip-composer-update']) { - // ensure FW version to update to is specified - if (!sake.options.framework_version) { - sake.throwError('Framework version not specified') - } + dottie.set(sake.config.composer, 'require.skyverge/wc-plugin-framework', sake.options.framework_version) - dottie.set(sake.config.composer, 'require.skyverge/wc-plugin-framework', sake.options.framework_version) + // update composer.json + fs.writeFileSync(path.join(process.cwd(), 'composer.json'), JSON.stringify(sake.config.composer, null, ' ')) - // update composer.json - fs.writeFileSync(path.join(process.cwd(), 'composer.json'), JSON.stringify(sake.config.composer, null, ' ')) + tasks.unshift(shellComposerUpdateTask) + } else { + sake.options.framework_version = sake.config.plugin.frameworkVersion + } - tasks.unshift('shell:composer_update') - } else { - sake.options.framework_version = sake.config.plugin.frameworkVersion - } + gulp.series(tasks)(done) +} +updateFrameworkTask.displayName = 'upfw' - gulp.series(tasks)(done) - }) +export { + setFrameworkVersionTask, + updateFrameworkTask } diff --git a/tasks/validate.js b/tasks/validate.js index ad2d2a3..7826419 100644 --- a/tasks/validate.js +++ b/tasks/validate.js @@ -1,31 +1,36 @@ -const fs = require('fs') -const log = require('fancy-log') +import fs from 'node:fs' +import log from 'fancy-log' +import sake from '../lib/sake.js' -module.exports = (gulp, plugins, sake) => { - gulp.task('validate:readme_headers', (done) => { - fs.readFile(`${sake.config.paths.src}/readme.txt`, 'utf8', (err, data) => { - if (err) sake.throwError(err) +const validateReadmeHeadersTask = (done) => { + fs.readFile(`${sake.config.paths.src}/readme.txt`, 'utf8', (err, data) => { + if (err) sake.throwError(err) - let requiredHeaders = [ - 'License', - 'License URI', - ] + let requiredHeaders = [ + 'License', + 'License URI', + ] - if (sake.config.deploy.type === 'wp') { - requiredHeaders.push('Stable tag') - } - - requiredHeaders.forEach(headerName => { - log.info(`Validating readme.txt header ${headerName}`) - const regex = new RegExp(headerName + ':(.+)', 'ig') - const headerValue = data.match(regex) + if (sake.config.deploy.type === 'wp') { + requiredHeaders.push('Stable tag') + } - if (! headerValue) { - sake.throwError('Missing required header in readme.txt: ' + headerName) - } - }) + requiredHeaders.forEach(headerName => { + log.info(`Validating readme.txt header ${headerName}`) + const regex = new RegExp(headerName + ':(.+)', 'ig') + const headerValue = data.match(regex) - done() + if (! headerValue) { + sake.throwError('Missing required header in readme.txt: ' + headerName) + } }) + + done() }) } + +validateReadmeHeadersTask.displayName = 'validate:readme_headers' + +export { + validateReadmeHeadersTask +} diff --git a/tasks/watch.js b/tasks/watch.js index 870bd97..a90d975 100644 --- a/tasks/watch.js +++ b/tasks/watch.js @@ -1,43 +1,48 @@ -const log = require('fancy-log') +import log from 'fancy-log' +import browserSync from 'browser-sync' +import sake from '../lib/sake.js' +import gulp from 'gulp' -// watch files for changes and compile assets necessary -module.exports = (gulp, plugins, sake) => { - gulp.task('watch', () => { - // start browsersync if enabled - if (sake.config.tasks.watch.useBrowserSync) { - let port = null +const watchTask = (done) => { + // start browsersync if enabled + if (sake.config.tasks.watch.useBrowserSync) { + let port = null - const getPort = () => { - return port + const getPort = () => { + return port + } + + browserSync.init({ + proxy: { + target: sake.config.tasks.browserSync.url, + proxyReq: [(proxyReq) => { + proxyReq.setHeader('X-Forwarded-Host', 'localhost:' + getPort()) + }] + } + }, (err, bs) => { + if (err) { + log.error(err) } + port = bs.options.get('port') + }) + } - plugins.browserSync.init({ - proxy: { - target: sake.config.tasks.browserSync.url, - proxyReq: [(proxyReq) => { - proxyReq.setHeader('X-Forwarded-Host', 'localhost:' + getPort()) - }] - } - }, (err, bs) => { - if (err) { - log.error(err) - } - port = bs.options.get('port') - }) - } + // allow other tasks to check if the watch task is running + sake.isWatching = true - // allow other tasks to check if the watch task is running - sake.isWatching = true + // kick off the watchers + // TODO: consider breaking the pipes apart, so that we can only lint and compile the + // files that were actually changed (ie not all coffee files when only a single one was changed) {IT 2018-03-21} + gulp.watch(sake.config.paths.assetPaths.javascriptSources, gulp.parallel('scripts:js')) + gulp.watch(`${sake.config.paths.assetPaths.js}/**/*.coffee`, gulp.parallel('scripts:coffee')) + gulp.watch(`${sake.config.paths.assetPaths.css}/**/*.scss`, gulp.parallel('styles')) + // watching images will result in an endless loop, because imagemin changes the original files - a possible + // workaround would be to place all original images in a separate directory + // gulp.watch(`${sake.config.paths.assetPaths.images}/**.*{png,jpg,gif,svg}`, gulp.parallel('imagemin')) + // TODO: should we also watch for changes in PHP files and regenerate POT files and reload the browser? +} +watchTask.displayName = 'watch' - // kick off the watchers - // TODO: consider breaking the pipes apart, so that we can only lint and compile the - // files that were actually changed (ie not all coffee files when only a single one was changed) {IT 2018-03-21} - gulp.watch(sake.config.paths.assetPaths.javascriptSources, gulp.parallel('scripts:js')) - gulp.watch(`${sake.config.paths.assetPaths.js}/**/*.coffee`, gulp.parallel('scripts:coffee')) - gulp.watch(`${sake.config.paths.assetPaths.css}/**/*.scss`, gulp.parallel('styles')) - // watching images will result in an endless loop, because imagemin changes the original files - a possible - // workaround would be to place all original images in a separate directory - // gulp.watch(`${sake.config.paths.assetPaths.images}/**.*{png,jpg,gif,svg}`, gulp.parallel('imagemin')) - // TODO: should we also watch for changes in PHP files and regenerate POT files and reload the browser? - }) +export { + watchTask } diff --git a/tasks/wc.js b/tasks/wc.js index 3fd0392..62753dd 100644 --- a/tasks/wc.js +++ b/tasks/wc.js @@ -1,139 +1,156 @@ -const axios = require('axios') -const log = require('fancy-log') -const path = require('path') -const fs = require('fs') -const FormData = require('form-data'); -const semver = require('semver') - -module.exports = (gulp, plugins, sake) => { - const wcRoot = 'https://woocommerce.com/wp-json/wc/submission/runner/v1' - - let apiOptions = { - username: process.env.WC_USERNAME, - password: process.env.WC_APPLICATION_PASSWORD, - product_id: sake.config.deploy.wooId - } +import axios from 'axios' +import log from 'fancy-log' +import path from 'node:path' +import fs from 'node:fs' +import FormData from 'form-data' +import semver from 'semver' +import sake from '../lib/sake.js' +import { series as gulpSeries } from 'gulp' + +const wcRoot = 'https://woocommerce.com/wp-json/wc/submission/runner/v1' + +let apiOptions = { + username: process.env.WC_USERNAME, + password: process.env.WC_APPLICATION_PASSWORD, + product_id: sake.config.deploy.wooId +} - let getApiURL = (endpoint) => { - return `${wcRoot}/product/${endpoint}` - } +let getApiURL = (endpoint) => { + return `${wcRoot}/product/${endpoint}` +} - let formatError = (err) => { - return err.response ? `WC API: ${err.response.data.message} (${err.response.data.code})` : err - } +let formatError = (err) => { + return err.response ? `WC API: ${err.response.data.message} (${err.response.data.code})` : err +} - // internal task to validate whether the plugin can be deployed to woocommerce.com - gulp.task('wc:validate', done => { - log.info('Making sure plugin is deployable...') - - let url = getApiURL('deploy/status') - - if (sake.options.debug) { - log.info('GET: ', url) - } - - // record whether we've logged the response, to avoid logging it in both the `then()` and `catch()` blocks - let hasLoggedResponse = false; - - axios.post(url, apiOptions) - .then(res => { - if (sake.options.debug && ! hasLoggedResponse) { - log.info('Response:') - console.debug(res.data) - hasLoggedResponse = true; - } - - /* - * Note: We'll only end up here if there was a previous deployment in progress. If there's no deployment at - * all then we'll end up in the `catch()` block because Woo sends back a 400 status code for that, which is - * actually an error state. - */ - - if (res.data.code) { - throw `Unexpected response code from WC API (${res.data.code})` - } - - if (res.data.version && semver.gte(res.data.version, sake.getPluginVersion())) { - throw `Queued version for plugin is already higher than or equal to ${sake.getPluginVersion()}` - } - - log.info('Plugin can be deployed') - - done() - }) - .catch(err => { - if (sake.options.debug && err.response && ! hasLoggedResponse) { - log.info('Response:') - console.debug(err.response.data) - hasLoggedResponse = true; - } - - // NOTE: if there's no deployment in progress then it's a 400 status code, which is why we end up in this catch block! - if (err.response && err.response.data.code === 'submission_runner_no_deploy_in_progress') { - log.info('No previous upload in queue') - return done() - } - - sake.throwDeferredError(formatError(err)) - }) - }) +/** + * Internal task to validate whether the plugin can be deployed to WooCommerce.com + */ +const wcValidateTask = (done) => { + log.info('Making sure plugin is deployable...') - // internal task that handles the zip file upload - gulp.task('wc:upload', (done) => { - let version = sake.getPluginVersion() - let zipPath = path.join(process.cwd(), sake.config.paths.build, `${sake.config.plugin.id}.${version}.zip`) + let url = getApiURL('deploy/status') - log.info('Uploading plugin to woocommerce.com...') + if (sake.options.debug) { + log.info('GET: ', url) + } - let url = getApiURL('deploy') + // record whether we've logged the response, to avoid logging it in both the `then()` and `catch()` blocks + let hasLoggedResponse = false; - // record whether we've logged the response, to avoid logging it in both the `then()` and `catch()` blocks - let hasLoggedResponse = false; + axios.post(url, apiOptions) + .then(res => { + if (sake.options.debug && ! hasLoggedResponse) { + log.info('Response:') + console.debug(res.data) + hasLoggedResponse = true; + } - if (sake.options.debug) { - log.info('POST: ', url) - log.info('Using ZIP file: %s as %s', zipPath, `${sake.config.plugin.id}.zip`) - } + /* + * Note: We'll only end up here if there was a previous deployment in progress. If there's no deployment at + * all then we'll end up in the `catch()` block because Woo sends back a 400 status code for that, which is + * actually an error state. + */ - const formData = new FormData(); + if (res.data.code) { + throw `Unexpected response code from WC API (${res.data.code})` + } - // add all API options to the form - Object.keys(apiOptions) - .forEach(key => formData.append(key, apiOptions[key])); + if (res.data.version && semver.gte(res.data.version, sake.getPluginVersion())) { + throw `Queued version for plugin is already higher than or equal to ${sake.getPluginVersion()}` + } - // add file data - formData.append('file', fs.createReadStream(zipPath)); - formData.append('version', version); + log.info('Plugin can be deployed') - axios.post(url, formData, { - headers: formData.getHeaders() + done() }) - .then(res => { - if (sake.options.debug && ! hasLoggedResponse) { - log.info('Response:'); - console.debug(res.data); - hasLoggedResponse = true; - } - - if (! res.data.success) { - throw `WC API did not return a deployment status or deployment has failed` - } - - log.info('Plugin deployment created successfully') - - done() - }) - .catch(err => { - if (sake.options.debug && err.response && ! hasLoggedResponse) { - log.info('Response:') - console.debug(err.response.data) - hasLoggedResponse = true; - } - - throw err; - }) + .catch(err => { + if (sake.options.debug && err.response && ! hasLoggedResponse) { + log.info('Response:') + console.debug(err.response.data) + hasLoggedResponse = true; + } + + // NOTE: if there's no deployment in progress then it's a 400 status code, which is why we end up in this catch block! + if (err.response && err.response.data.code === 'submission_runner_no_deploy_in_progress') { + log.info('No previous upload in queue') + return done() + } + + sake.throwDeferredError(formatError(err)) + }) +} + +wcValidateTask.displayName = 'wc:validate' + +/** + * Internal task that handles the zip file upload + */ +const wcUploadTask = (done) => { + let version = sake.getPluginVersion() + let zipPath = path.join(process.cwd(), sake.config.paths.build, `${sake.config.plugin.id}.${version}.zip`) + + log.info('Uploading plugin to woocommerce.com...') + + let url = getApiURL('deploy') + + // record whether we've logged the response, to avoid logging it in both the `then()` and `catch()` blocks + let hasLoggedResponse = false; + + if (sake.options.debug) { + log.info('POST: ', url) + log.info('Using ZIP file: %s as %s', zipPath, `${sake.config.plugin.id}.zip`) + } + + const formData = new FormData(); + + // add all API options to the form + Object.keys(apiOptions) + .forEach(key => formData.append(key, apiOptions[key])); + + // add file data + formData.append('file', fs.createReadStream(zipPath)); + formData.append('version', version); + + axios.post(url, formData, { + headers: formData.getHeaders() }) + .then(res => { + if (sake.options.debug && ! hasLoggedResponse) { + log.info('Response:'); + console.debug(res.data); + hasLoggedResponse = true; + } + + if (! res.data.success) { + throw `WC API did not return a deployment status or deployment has failed` + } + + log.info('Plugin deployment created successfully') + + done() + }) + .catch(err => { + if (sake.options.debug && err.response && ! hasLoggedResponse) { + log.info('Response:') + console.debug(err.response.data) + hasLoggedResponse = true; + } + + throw err; + }) +} + +wcUploadTask.displayName = 'wc:upload' + +/** + * The main task to deploy woocommerce.com plugins + */ +const wcDeployTask = gulpSeries(wcValidateTask, wcUploadTask) +wcDeployTask.displayName = 'wc:deploy' - // the main task to deploy woocommerce.com plugins - gulp.task('wc:deploy', gulp.series('wc:validate', 'wc:upload')) +export { + wcValidateTask, + wcUploadTask, + wcDeployTask } diff --git a/tasks/zip.js b/tasks/zip.js index b639a1a..6133f70 100644 --- a/tasks/zip.js +++ b/tasks/zip.js @@ -1,17 +1,27 @@ -module.exports = (gulp, plugins, sake) => { - gulp.task('compress', () => { - let zipDest = sake.options.zipDest || sake.config.paths.build - let zipFileName = sake.config.plugin.id + '.' + sake.getPluginVersion() + '.zip' +import sake from '../lib/sake.js' +import gulp from 'gulp' +import zip from 'gulp-zip' +import { buildTask } from './build.js' - sake.config.paths.zipDest = sake.resolvePath(zipDest) +const zipTask = (done) => { + let zipDest = sake.options.zipDest || sake.config.paths.build + let zipFileName = sake.config.plugin.id + '.' + sake.getPluginVersion() + '.zip' - return gulp.src([ - `${sake.config.paths.build}/${sake.config.plugin.id}/**`, - `!${sake.config.paths.build}/${sake.config.plugin.id}/**/*.zip` - ], { nodir: true, base: sake.config.paths.build, encoding: false }) // exclude empty directories, include plugin dir in zip, no encoding because it breaks images - .pipe(plugins.zip(zipFileName)) - .pipe(gulp.dest(sake.config.paths.zipDest)) - }) + sake.config.paths.zipDest = sake.resolvePath(zipDest) - gulp.task('zip', gulp.series('build', 'compress')) + return gulp.src([ + `${sake.config.paths.build}/${sake.config.plugin.id}/**`, + `!${sake.config.paths.build}/${sake.config.plugin.id}/**/*.zip` + ], { nodir: true, base: sake.config.paths.build, encoding: false }) // exclude empty directories, include plugin dir in zip, no encoding because it breaks images + .pipe(zip(zipFileName)) + .pipe(gulp.dest(sake.config.paths.zipDest)) +} +zipTask.displayName = 'compress' + +const buildAndZip = gulp.series(buildTask, zipTask) +buildAndZip.displayName = 'zip' + +export { + zipTask, + buildAndZip }