Fix bin/publish: copy docs.dist from project root

Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-10-21 02:08:33 +00:00
commit f6fac6c4bc
79758 changed files with 10547827 additions and 0 deletions

74
node_modules/laravel-mix/src/Assert.js generated vendored Executable file
View File

@@ -0,0 +1,74 @@
let assert = require('assert');
let File = require('./File');
class Assert {
/**
* Assert that the call the mix.js() is valid.
*
* @param {any} entry
* @param {any} output
*/
static js(entry, output) {
assert(
typeof entry === 'string' || Array.isArray(entry),
'mix.js() is missing required parameter 1: entry'
);
assert(
typeof output === 'string',
'mix.js() is missing required parameter 2: output'
);
}
/**
* Assert that the calls to mix.sass() and mix.less() are valid.
*
* @param {string} type
* @param {string} src
* @param {string} output
*/
static preprocessor(type, src, output) {
assert(
typeof src === 'string',
`mix.${type}() is missing required parameter 1: src`
);
assert(
typeof output === 'string',
`mix.${type}() is missing required parameter 2: output`
);
}
/**
* Assert that calls to mix.combine() are valid.
*
* @param {string|string[]} src
* @param {File} output
*/
static combine(src, output) {
assert(
typeof src === 'string' || Array.isArray(src),
`mix.combine() requires a valid src string or array.`
);
assert(
output.isFile(),
'mix.combine() requires a full output file path as the second argument. Got ' +
output.path()
);
}
/**
* Assert that the given file exists.
*
* @param {string} file
*/
static exists(file) {
assert(
File.exists(file),
`Whoops, you are trying to compile ${file}, but that file does not exist.`
);
}
}
module.exports = Assert;

172
node_modules/laravel-mix/src/BabelConfig.js generated vendored Executable file
View File

@@ -0,0 +1,172 @@
const babel = require('@babel/core');
/**
* @typedef {string|string[]} BabelTargetsBrowserslist
* @typedef {Record<string,string> & {browsers: BabelTargetsBrowserslist}} BabelTargetsPerEngine
* @typedef {BabelTargetsBrowserslist | BabelTargetsPerEngine} BabelTargets
*/
/**
* @typedef {object} AdditionalBabelOptions
* @property {boolean} [cacheDirectory]
* @property {BabelTargets} [targets]
*/
/** @typedef {import("@babel/core").TransformOptions & AdditionalBabelOptions} BabelOptions */
class BabelConfig {
/**
*
* @param {import("./Mix")} [mix]
*/
constructor(mix) {
this.mix = mix || global.Mix;
}
/**
* Generate the appropriate Babel configuration for the build.
*
* @deprecated
*/
static generate() {
return new BabelConfig().generate();
}
/**
* Generate the appropriate Babel configuration for the build.
*/
generate() {
return this.mergeAll([
this.default(),
this.getCustomConfig(this.mix.config.babelConfig),
{
root: this.mix.paths.root(),
babelrc: true,
configFile: true,
babelrcRoots: ['.', this.mix.paths.root()]
}
]);
}
/**
* Fetch the user's .babelrc config file, if any.
*
* @param {string} path
* @deprecated
*/
fetchBabelRc(path) {
const File = require('./File');
return File.exists(path) ? JSON.parse(File.find(path).read()) : {};
}
/**
* Get the babel config setup when using mix.babelConfig()
*
* @internal
* @param {import('@babel/core').TransformOptions} customOptions
*/
getCustomConfig(customOptions) {
const config = babel.loadPartialConfig(customOptions);
return config ? config.options : {};
}
/**
* Merge babel configs
*
* @param {BabelOptions[]} configs
*/
mergeAll(configs) {
const options = configs.reduce((prev, current) => {
const presets = [...(prev.presets || []), ...(current.presets || [])].map(
preset => babel.createConfigItem(preset, { type: 'preset' })
);
const plugins = [...(prev.plugins || []), ...(current.plugins || [])].map(
preset => babel.createConfigItem(preset, { type: 'plugin' })
);
return Object.assign(prev, current, { presets, plugins });
});
// @ts-ignore TODO: fix type
options.plugins = this.filterConfigItems(options.plugins || []);
// @ts-ignore TODO: fix type
options.presets = this.filterConfigItems(options.presets || []);
return options;
}
/**
* Filter merged presets or plugins
*
* @internal
* @param {import("@babel/core").ConfigItem[]} items
* @returns {import("@babel/core").ConfigItem[]}
*/
filterConfigItems(items) {
/**
*
* @param {import("@babel/core").ConfigItem[]} unique
* @param {import("@babel/core").ConfigItem} item
*/
function dedupe(unique, item) {
if (item.file != null) {
const toDeleteIndex = unique.findIndex(
element =>
element.file &&
element.file.resolved === (item.file && item.file.resolved)
);
if (toDeleteIndex >= 0) {
unique.splice(toDeleteIndex, 1);
}
}
return [...unique, item];
}
/** @type {import("@babel/core").ConfigItem[]} */
let unique = [];
for (const configItem of items) {
unique = dedupe(unique, configItem);
}
return unique;
}
/** @deprecated */
static default() {
return new BabelConfig().default();
}
/**
* Fetch the default Babel configuration.
*
* @internal
* @returns {BabelOptions}
*/
default() {
return {
cacheDirectory: true,
presets: [
['@babel/preset-env', { modules: false, forceAllTransforms: true }]
],
plugins: [
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-object-rest-spread',
[
'@babel/plugin-transform-runtime',
{
helpers: false
}
]
]
};
}
}
module.exports = BabelConfig;

269
node_modules/laravel-mix/src/Chunks.js generated vendored Executable file
View File

@@ -0,0 +1,269 @@
let path = require('path');
/** @typedef {import("webpack").Module} Module */
/** @typedef {object} OptimizationSplitChunksCacheGroup */
/**
* @typedef {Object} CacheGroupsContext
* @property {import("webpack").ModuleGraph} moduleGraph
* @property {import("webpack").ChunkGraph} chunkGraph
*/
/** @typedef {any} CacheGroup */
/**
* @typedef {(module: import("webpack").Module, context: CacheGroupsContext) => boolean} ChunkTestCallback
* @typedef {undefined|boolean|string|RegExp|ChunkTestCallback} ChunkTest
*/
/**
* @typedef {(chunk: CacheGroup, id: string) => boolean} ChunkFindCallback
*/
class Chunks {
/** @type {Chunks|null} */
static _instance = null;
/**
*
* @param {import("./Mix")} mix
*/
constructor(mix) {
// TODO: Simplify in Mix 7 -- Here for backwards compat if a plugin creates this class directly
this.mix = mix || global.Mix;
/** @type {{[key: string]: CacheGroup}} */
this.chunks = {};
/** @type {import("./builder/Entry.js")|null} */
this.entry = null;
this.runtime = false;
}
/** @deprecated */
makeCurrent() {
Chunks._instance = this;
}
/**
* @deprecated
* @return {Chunks}
*/
static instance() {
return Chunks._instance || this.reset();
}
/**
* @deprecated
* @return {Chunks}
*/
static reset() {
return (Chunks._instance = new Chunks(global.Mix));
}
/**
*
* @param {string} id A unique identifier for this chunk. Multiple chunks with the same ID are merged.
* @param {string} path The output path for this chunk
* @param {ChunkTest|ChunkTest[]} test A test that tells webpack how to determine what to put in this chunk
* @param {Partial<CacheGroup>} attrs
*/
add(id, path, test, attrs = {}) {
this.create(id, path, attrs).addTo(id, test);
}
/**
*
* @param {string} id A unique identifier for this chunk. Multiple chunks with the same ID are merged.
* @param {string} path The output path for this chunk
* @param {Partial<OptimizationSplitChunksCacheGroup>} attrs
*/
create(id, path, attrs = {}) {
this.chunks[id] = this.chunks[id] || {
name: path,
...attrs
};
return this;
}
/**
*
* @param {string} idOrPath
* @param {ChunkTest|ChunkTest[]} test
*/
addTo(idOrPath, test) {
const chunk = this.find(idOrPath);
if (Array.isArray(test)) {
test = this._checkAllTests(test);
}
if (chunk.test) {
test = this._checkAnyTests([chunk.test, test]);
}
chunk.test = test;
return this;
}
/**
*
* @param {string|ChunkFindCallback} idOrPath
* @returns {CacheGroup|null}
*/
find(idOrPath) {
if (typeof idOrPath === 'string') {
if (this.chunks[idOrPath]) {
return this.chunks[idOrPath];
}
return this.find((_, id) => id === idOrPath);
}
const item = Object.entries(this.chunks).find(([id, chunk]) =>
idOrPath(chunk, id)
);
return item ? item[1] : null;
}
/**
* @returns {import('webpack').Configuration}
*/
config() {
return {
optimization: {
...this.runtimeChunk(),
...this.splitChunks()
}
};
}
runtimeChunk() {
if (!this.runtime || !this.entry) {
return {};
}
return {
runtimeChunk: {
name: path
.join(this.mix.config.runtimeChunkPath || this.entry.base, 'manifest')
.replace(/\\/g, '/')
}
};
}
splitChunks() {
return {
splitChunks: {
...this.cacheGroups()
}
};
}
cacheGroups() {
return {
cacheGroups: {
/** @type {false} */
default: false,
/** @type {false} */
defaultVendors: false,
...this.chunks
}
};
}
/**
* Check to see if a chunk should be included based on multiple tests
*
* This is for internal use only and may be changed or removed at any time
*
* @internal
*
* @param {(undefined|boolean|string|RegExp|Function)[]} tests
* @returns {ChunkTestCallback}
*/
_checkAllTests(tests) {
return (module, context) =>
tests.every(test => this._checkTest(test, module, context));
}
/**
* Check to see if a chunk should be included based on multiple tests
*
* This is for internal use only and may be changed or removed at any time
*
* @internal
*
* @param {(undefined|boolean|string|RegExp|Function)[]} tests
* @returns {ChunkTestCallback}
*/
_checkAnyTests(tests) {
return (module, context) =>
tests.some(test => this._checkTest(test, module, context));
}
/**
* Check to see if a chunk should be included
*
* NOTE: This repeats the code from the SplitChunksPlugin checkTest function
* This is for internal use only and may be changed or removed at any time
*
* @internal
*
* @param {undefined|boolean|string|RegExp|Function} test test option
* @param {import("webpack").Module} module the module
* @param {CacheGroupsContext} context context object
* @returns {boolean} true, if the module should be selected
*/
_checkTest(test, module, context) {
if (this._checkModuleTest(test, module, context)) {
return true;
}
const issuer = context.moduleGraph.getIssuer(module);
if (issuer) {
return this._checkTest(test, issuer, context);
}
return false;
}
/**
* Check to see if a chunk should be included
*
* NOTE: This repeats the code from the SplitChunksPlugin checkTest function
* This is for internal use only and may be changed or removed at any time
*
* @internal
*
* @param {undefined|boolean|string|RegExp|Function} test test option
* @param {import("webpack").Module} module the module
* @param {any} context context object
* @returns {boolean} true, if the module should be selected
*/
_checkModuleTest(test, module, context) {
if (test === undefined) return true;
if (typeof test === 'function') {
return test(module, context);
}
if (typeof test === 'boolean') return test;
if (typeof test === 'string') {
const name = module.nameForCondition();
return (name && name.startsWith(test)) || false;
}
if (test instanceof RegExp) {
const name = module.nameForCondition();
return (name && test.test(name)) || false;
}
return false;
}
}
module.exports.Chunks = Chunks;

103
node_modules/laravel-mix/src/Dependencies.js generated vendored Executable file
View File

@@ -0,0 +1,103 @@
let Log = require('./Log');
let PackageManager = require('./PackageManager');
let { PackageDependency } = require('./PackageDependency');
class Dependencies {
/** @type {PackageDependency[]} */
items = [];
requiresReload = false;
/**
* Create a new Dependencies instance.
*
* @param {import('./PackageDependency').Dependency[]} deps
*/
enqueue(deps, requiresReload = false) {
this.items.push(...deps.filter(dep => dep).map(PackageDependency.from));
this.requiresReload = this.requiresReload || requiresReload;
return this;
}
/**
* Install all dependencies that aren't available.
*/
async install() {
const packages = await this.installablePackages();
if (!packages.length) {
return;
}
await this.execute(this.buildInstallCommand(packages));
}
async installablePackages() {
const results = await Promise.all(
this.items.map(async dep => {
if (await dep.needsInstallation()) {
return dep;
}
return null;
})
);
return /** @type {PackageDependency[]} */ (results.filter(Boolean));
}
/**
* Execute the provided console command.
*
* @param {string} command
*/
async execute(command) {
Log.feedback(
'Additional dependencies must be installed. This will only take a moment.'
);
Log.feedback(`Running: ${command}`);
const childProcess = require('child_process');
const { promisify } = require('util');
await promisify(childProcess.exec)(command);
this.respond();
}
/**
* Build the dependency install command.
*
* @param {PackageDependency[]} deps
*/
buildInstallCommand(deps) {
const list = deps.map(dep => dep.package).join(' ');
switch (PackageManager.detect()) {
case 'npm':
return `npm install ${list} --save-dev --legacy-peer-deps`;
case 'yarn':
return `yarn add ${list} --dev`;
}
}
/**
* Complete the install process.
*/
respond() {
if (!this.requiresReload) {
return;
}
Log.feedback('Finished. Please run Mix again.');
if (process.env.NODE_ENV !== 'test') {
process.exit(1);
}
}
}
module.exports = Dependencies;

50
node_modules/laravel-mix/src/Dispatcher.js generated vendored Executable file
View File

@@ -0,0 +1,50 @@
/** @typedef {(...args: any) => void|Promise<void>} Handler */
const { concat } = require('lodash');
class Dispatcher {
/**
* Create a new Dispatcher instance.
*/
constructor() {
/** @type {Record<string, Handler[]>} */
this.events = {};
}
/**
* Listen for the given event.
*
* @param {string|string[]} events
* @param {Handler} handler
*/
listen(events, handler) {
events = concat([], events);
events.forEach(event => {
this.events[event] = (this.events[event] || []).concat(handler);
});
return this;
}
/**
* Trigger all handlers for the given event.
*
* @param {string} event
* @param {any} [data]
*/
async fire(event, data) {
if (!this.events[event]) return false;
return Promise.all(this.events[event].map(handler => handler(data)));
}
/**
* Fetch all registered event listeners.
*/
all() {
return this.events;
}
}
module.exports = Dispatcher;

10
node_modules/laravel-mix/src/Engine.js generated vendored Executable file
View File

@@ -0,0 +1,10 @@
const semver = require('semver');
const pkg = require('../package.json');
module.exports.assertSupportedNodeVersion = function assertSupportedNodeVersion() {
if (!semver.satisfies(process.versions.node, pkg.engines.node)) {
throw new Error(
`You are using an unsupported version of Node. Please update to at least Node v12.14`
);
}
};

422
node_modules/laravel-mix/src/File.js generated vendored Executable file
View File

@@ -0,0 +1,422 @@
let os = require('os');
let md5 = require('md5');
let path = require('path');
let fs = require('fs-extra');
let Terser = require('terser');
let UglifyCss = require('clean-css');
const { escapeRegExp } = require('lodash');
class File {
/**
* Create a new instance.
*
* @param {string} filePath
*/
constructor(filePath) {
this.absolutePath = path.resolve(filePath);
this.filePath = this.relativePath();
this.segments = this.parse();
}
/** @internal */
refresh() {
this.segments = this.parse();
return this;
}
/**
* Static constructor.
*
* @param {string} file
*/
static find(file) {
return new File(file);
}
/**
* Get the size of the file.
*/
size() {
return fs.statSync(this.path()).size;
}
/**
* Determine if the given file exists.
*
* @param {string} file
*/
static exists(file) {
return fs.existsSync(file);
}
/**
* Determine if the given file exists.
*/
exists() {
return fs.existsSync(this.path());
}
normalizedOutputPath() {
let path = this.pathFromPublic(this.mix.config.publicPath);
path = File.stripPublicDir(path);
return path
.replace(/\.(js|css)$/, '')
.replace(/\\/g, '/')
.replace(/^\//, '');
}
/**
* Delete/Unlink the current file.
*/
delete() {
if (fs.existsSync(this.path())) {
fs.unlinkSync(this.path());
}
}
/**
* Get the name of the file.
*/
name() {
return this.segments.file;
}
/**
* Get the name of the file, minus the extension.
*/
nameWithoutExtension() {
return this.segments.name;
}
/**
* Get the extension of the file.
*/
extension() {
return this.segments.ext;
}
/**
* Get the absolute path to the file.
*/
path() {
return this.absolutePath;
}
/**
* Get the relative path to the file, from the project root.
*/
relativePath() {
return path.relative(this.mix.paths.root(), this.path());
}
/**
* Get the relative path to the file, from the project root.
*/
relativePathWithoutExtension() {
return path.relative(this.mix.paths.root(), this.pathWithoutExtension());
}
/**
* Get the absolute path to the file, minus the extension.
*/
pathWithoutExtension() {
return this.segments.pathWithoutExt;
}
/**
* Force the file's relative path to begin from the public path.
*
* @param {string|null} [publicPath]
*/
forceFromPublic(publicPath = null) {
publicPath = publicPath || this.mix.config.publicPath;
if (!this.relativePath().startsWith(publicPath)) {
return new File(path.join(publicPath, this.relativePath()));
}
return this;
}
/**
*
* @param {string} filePath
* @param {string|null} publicPath
*/
static stripPublicDir(filePath, publicPath = null) {
let publicDir = path.basename(publicPath || this.mix.config.publicPath);
publicDir = escapeRegExp(publicDir);
return filePath.replace(new RegExp(`^[/\\\\]?${publicDir}[/\\\\]`), '');
}
/**
* Get the path to the file, starting at the project's public dir.
*
* @param {string|null} [publicPath]
*/
pathFromPublic(publicPath) {
publicPath = publicPath || this.mix.config.publicPath;
let extra = this.filePath.startsWith(publicPath) ? publicPath : '';
// If the path starts with the public folder remove it
if (
this.filePath.startsWith(
path.normalize(`${publicPath}/${path.basename(publicPath)}`)
)
) {
extra += `/${path.basename(publicPath)}`;
}
return path.normalize(
'/' + path.relative(this.mix.paths.root(extra), this.path())
);
}
/**
* Get the path to the file without query string.
*/
pathWithoutQueryString() {
const queryStringIndex = this.path().indexOf('?');
return queryStringIndex < 0
? this.path()
: this.path().substr(0, queryStringIndex);
}
/**
* Get the base directory of the file.
*/
base() {
return this.segments.base;
}
/**
* Determine if the file is a directory.
*/
isDirectory() {
return this.segments.isDir;
}
/**
* Determine if the path is a file, and not a directory.
*/
isFile() {
return this.segments.isFile;
}
/**
* Write the given contents to the file.
*
* @param {string} body
*/
write(body) {
if (typeof body === 'object') {
body = JSON.stringify(body, null, 4);
}
body = body + os.EOL;
fs.writeFileSync(this.absolutePath, body);
return this;
}
/**
* Read the file's contents.
*/
read() {
return fs.readFileSync(this.pathWithoutQueryString(), 'utf8');
}
/**
* Calculate the proper version hash for the file.
*/
version() {
return md5(this.read());
}
/**
* Create all nested directories.
*/
makeDirectories() {
fs.mkdirSync(this.base(), { mode: 0o777, recursive: true });
return this;
}
/**
* Copy the current file to a new location.
*
* @param {string} destination
*/
copyTo(destination) {
fs.copySync(this.path(), destination);
return this;
}
/**
* Copy the current file to a new location.
*
* @param {string} destination
* @internal
*/
async copyToAsync(destination) {
await fs.copy(this.path(), destination, {
recursive: true
});
}
/**
* Minify the file, if it is CSS or JS.
*/
async minify() {
if (this.extension() === '.js') {
const output = await Terser.minify(
this.read(),
this.mix.config.terser.terserOptions
);
if (output.code !== undefined) {
this.write(output.code);
}
}
if (this.extension() === '.css') {
const output = await new UglifyCss(this.mix.config.cleanCss).minify(
this.read()
);
this.write(output.styles);
}
return this;
}
/**
* Rename the file.
*
* @param {string} to
*/
rename(to) {
to = path.join(this.base(), to);
fs.renameSync(this.path(), to);
return new File(to);
}
/**
* It can append to the current path.
*
* @param {string} append
*/
append(append) {
return new File(path.join(this.path(), append));
}
/**
* Determine if the file path contains the given text.
*
* @param {string} text
*/
contains(text) {
return this.path().includes(text);
}
/**
* Parse the file path.
*/
parse() {
let parsed = path.parse(this.absolutePath);
let isDir = this.checkIsDir(parsed);
return {
path: this.filePath,
absolutePath: this.absolutePath,
pathWithoutExt: path.join(parsed.dir, `${parsed.name}`),
isDir,
isFile: !isDir,
name: parsed.name,
ext: parsed.ext,
file: parsed.base,
base: parsed.dir
};
}
/**
* This is a bit more involved check to verify if a file is a directory
*
* @param {path.ParsedPath} parsed
* @private
*/
checkIsDir(parsed) {
// 1. If the file exists and is a directory
try {
return fs.lstatSync(this.absolutePath).isDirectory();
} catch (err) {
//
}
// 2. If the path ends in a slash
if (this.absolutePath.endsWith('/')) {
return true;
}
// 3. Pevious logic: No extension & does not end in a wildcard
return !parsed.ext && !parsed.name.endsWith('*');
}
/**
* @param {object} param0
* @param {boolean} [param0.hidden]
*
* @returns {Promise<File[]>}
*/
async listContentsAsync({ hidden = false }) {
const contents = await fs.promises.readdir(this.path(), {
withFileTypes: true
});
const files = await Promise.all(
contents.map(async entry => {
if (!hidden && entry.name.startsWith('.')) {
return [];
}
// We don't want to list any special devices
// symlinks, etc…
// TODO: This needs a test
if (!entry.isFile() && !entry.isDirectory()) {
return [];
}
let file = new File(`${this.path()}/${entry.name}`);
return entry.isDirectory() ? file.listContentsAsync({ hidden }) : [file];
})
);
return files.flat();
}
// TODO: Can we refactor this to remove the need for implicit global? Or does this one make sense to leave as is?
get mix() {
// TODO: Use warning-less version here
return global.Mix;
}
static get mix() {
// TODO: Use warning-less version here
return global.Mix;
}
}
module.exports = File;

158
node_modules/laravel-mix/src/FileCollection.js generated vendored Executable file
View File

@@ -0,0 +1,158 @@
let concat = require('concat');
let path = require('path');
let fs = require('fs-extra');
let babel = require('@babel/core');
let glob = require('glob');
let _ = require('lodash');
let { promisify } = require('util');
let Log = require('./Log');
let File = require('./File');
class FileCollection {
/**
* Create a new FileCollection instance.
*
* @param {string|string[]} files
*/
constructor(files = []) {
/** @type {string[]} */
this.files = _.concat([], files);
}
/**
* Fetch the underlying files.
*/
get() {
return this.files;
}
/**
* Merge all files in the collection into one.
*
* @param {File} output
* @param {boolean} wantsBabel
*/
async merge(output, wantsBabel = false) {
/** @type {string} */
// @ts-ignore
const contents = await concat(this.files, output.makeDirectories().path());
if (this.shouldCompileWithBabel(wantsBabel, output)) {
const code = this.babelify(contents);
if (code) {
output.write(code);
}
}
return new File(output.makeDirectories().path());
}
/**
* Determine if we should add a Babel pass to the concatenated file.
*
* @param {Boolean} wantsBabel
* @param {File} output
*/
shouldCompileWithBabel(wantsBabel, output) {
return wantsBabel && output.extension() === '.js';
}
/**
* Apply Babel to the given contents.
*
* @param {string} contents
*/
babelify(contents) {
let babelConfig = this.mix.config.babel();
delete babelConfig.cacheDirectory;
const result = babel.transform(contents, babelConfig);
return result && result.code;
}
/**
*
* @param {string|File|(string|File)[]} src
*/
async normalizeSourceFiles(src) {
// 1. Always work with an array of sources
let sources = Array.isArray(src) ? src : [src]
// 2. Ensure we're working with File objects
let files = sources.map(file => {
return typeof file === 'string'
? new File(file)
: file
})
let globAsync = promisify(glob)
// 3. Expand globs
let groups = await Promise.all(files.map(async file => {
if (! file.contains('*')) {
return [file]
}
let files = await globAsync(file.path(), { nodir: true });
if (!files.length) {
Log.feedback(`Notice: The ${file.path()} search produced no matches.`);
}
return files.map(filepath => new File(filepath))
}))
return groups.flat()
}
/**
* Copy the src files to the given destination.
*
* @param {File} destination
* @param {string[]|File} [src]
* @return {Promise<void>}
*/
async copyTo(destination, src = this.files) {
this.assets = this.assets || []
let sourceFiles = await this.normalizeSourceFiles(src)
let assets = [];
// Copy an array of files to the destination file/directory
// file -> file: no change in destination file name
// directory -> file: this is an error
// file -> directory: change name
// directory -> directory: don't change name
for (const file of sourceFiles) {
const dest =
file.isFile() &&
destination.isDirectory() &&
destination.name() !== file.name()
? destination.append(file.name())
: destination;
await file.copyToAsync(dest.path());
// TODO: Can we remove this? It's sync and also just shouldn't be necessary
dest.refresh();
if (dest.isDirectory()) {
assets.push(...(await dest.listContentsAsync({ hidden: false })));
} else {
assets.push(dest);
}
}
this.assets = assets;
}
get mix() {
return global.Mix;
}
}
module.exports = FileCollection;

75
node_modules/laravel-mix/src/HotReloading.js generated vendored Executable file
View File

@@ -0,0 +1,75 @@
let path = require('path');
let File = require('./File');
class HotReloading {
/**
*
* @param {import('./Mix')} mix
*/
constructor(mix) {
this.mix = mix;
}
record() {
this.clean();
if (!this.mix.config.hmr) {
return;
}
const { https, host, port } = this.mix.config.hmrOptions;
const protocol = https ? 'https' : 'http';
const url = `${protocol}://${host}:${port}`;
this.hotFile().write(url);
process.on('exit', () => this.clean());
process.on('SIGINT', () => this.clean());
process.on('SIGHUP', () => this.clean());
}
hotFile() {
return new File(path.join(this.mix.config.publicPath, 'hot'));
}
/** @deprecated */
http() {
return this.mix.config.hmrOptions.https ? 'https' : 'http';
}
/** @deprecated */
port() {
return this.mix.config.hmrOptions.port;
}
clean() {
this.hotFile().delete();
}
/** @deprecated */
static record() {
return new HotReloading(global.Mix).record();
}
/** @deprecated */
static hotFile() {
return new HotReloading(global.Mix).hotFile();
}
/** @deprecated */
static http() {
return new HotReloading(global.Mix).http();
}
/** @deprecated */
static port() {
return new HotReloading(global.Mix).port();
}
/** @deprecated */
static clean() {
return new HotReloading(global.Mix).clean();
}
}
module.exports = HotReloading;

158
node_modules/laravel-mix/src/Log.js generated vendored Executable file
View File

@@ -0,0 +1,158 @@
const chalk = require('chalk');
/**
* @typedef {object} LogMessage
* @property {string} text
* @property {'info' | 'warn' | 'error'} type
**/
/**
* @typedef {'default' | 'green' | 'red'} LogColor
**/
class Log {
/**
* Determine if we are in test mode.
*/
static testing = false;
/**
* All logged messages.
*
* @type {string[]}
*/
static fakedLogs = [];
/**
* Log basic info to the console.
*
* @param {string} message
* @param {LogColor} color
*/
static info(message, color = 'default') {
if (Log.testing) {
Log.fakedLogs.push(message);
return;
}
console.log(Log.colors()[color], message);
Log.reset();
}
/**
*
* @param {LogMessage} message
*/
static message(message) {
if (Log.testing) {
Log.fakedLogs.push(message.text);
return;
}
/** @type {string} */
let prefix = '';
if (message.type === 'info') {
prefix = ' INFO ';
} else if (message.type === 'warn') {
prefix = ' WARN ';
} else if (message.type === 'error') {
prefix = ' ERR ';
}
const line = message.text.replace(/\n/g, '\n' + ' '.repeat(prefix.length + 1));
if (message.type === 'info') {
console.warn(`${chalk.bgBlue.white(prefix)} ${chalk.white(line)}`);
} else if (message.type === 'warn') {
console.warn(`${chalk.bgYellow.black(prefix)} ${chalk.yellow(line)}`);
} else if (message.type === 'error') {
console.warn(`${chalk.bgRed.white(prefix)} ${chalk.red(line)}`);
}
}
/**
* Log feedback info to the console.
*
* @param {string} message
* @param {LogColor} color
*/
static feedback(message, color = 'green') {
Log.line('\t' + message, color);
}
/**
* Log error info to the console.
*
* @param {string} message
* @param {LogColor} color
*/
static error(message, color = 'red') {
Log.line(message, color);
}
/**
* Log a new line of info to the console.
*
* @param {string} message
* @param {LogColor} color
*/
static line(message, color = 'default') {
Log.info(message, color);
}
/**
* Reset the default color for future console.logs.
*/
static reset() {
console.log(Log.colors()['default'], '');
}
/**
* Enter testing mode.
*/
static fake() {
Log.testing = true;
}
/**
* Exit testing mode.
*/
static restore() {
Log.testing = false;
Log.fakedLogs = [];
}
/**
* Determine if the given message was logged.
*
* @param {string|string[]} messages
*/
static received(messages) {
messages = Array.isArray(messages) ? messages : [messages];
let result = messages.every(message =>
this.fakedLogs.some(log => log.includes(message))
);
this.restore();
return result;
}
/**
* The colors lookup table.
*/
static colors() {
return {
default: '\x1b[0m',
green: '\x1b[32m',
red: '\x1b[31m'
};
}
}
module.exports = Log;

172
node_modules/laravel-mix/src/Manifest.js generated vendored Executable file
View File

@@ -0,0 +1,172 @@
let collect = require('collect.js');
let path = require('path');
let File = require('./File');
let hasWarnedAboutManifestChange = false;
class Manifest {
/**
* Create a new Manifest instance.
*
* @param {string} name
* @param {import('./Mix.js')} [mix]
*/
constructor(name = 'mix-manifest.json', mix = undefined) {
this.mix = mix || global.Mix;
/** @type {Record<string, string>} */
this.manifest = {};
this.name = name;
}
/**
* Get the underlying manifest collection.
* @param {string|null} [file]
* @returns {string | Record<string, string>}
*/
get(file = null) {
if (file) {
return path.posix.join(
this.mix.config.publicPath,
this.manifest[this.normalizePath(file)]
);
}
return Object.fromEntries(
Object.entries(this.manifest).sort((a, b) => a[0].localeCompare(b[0]))
);
}
/**
* Add the given path to the manifest file.
*
* @param {string} filePath
*/
add(filePath) {
filePath = this.normalizePath(filePath);
let original = filePath.replace(/\?id=\w+/, '');
this.manifest[original] = filePath;
return this;
}
/**
* Add a new hashed key to the manifest.
*
* @param {string} file
*/
hash(file) {
let hash = new File(path.join(this.mix.config.publicPath, file)).version();
let filePath = this.normalizePath(file);
this.manifest[filePath] = filePath + '?id=' + hash;
return this;
}
/**
* Transform the Webpack stats into the shape we need.
*
* @param {object} stats
*/
transform(stats) {
this.flattenAssets(stats).forEach(this.add.bind(this));
return this;
}
/**
* Refresh the mix-manifest.js file.
*/
refresh() {
if (this.path() === null) {
return;
}
File.find(this.path()).makeDirectories().write(this.manifest);
}
/**
* Retrieve the JSON output from the manifest file.
*/
read() {
if (this.path() === null) {
return {};
}
return JSON.parse(File.find(this.path()).read());
}
/**
* Get the path to the manifest file.
*/
path() {
// Backwards compat for plugis that manually swapped out the manifest plugin with a different name
if (this.name !== 'mix-manifest.json') {
if (!hasWarnedAboutManifestChange) {
hasWarnedAboutManifestChange = true;
console.warn(
`You can now customize the name of the manifest using mix.options(${JSON.stringify(
{ manifest: this.name }
)}) instead of changing the manifest name directly.`
);
}
return path.join(this.mix.config.publicPath, this.name);
}
if (!this.mix.config.manifest) {
return null;
}
return path.join(this.mix.config.publicPath, this.mix.config.manifest);
}
/**
* Flatten the generated stats assets into an array.
*
* @param {Object} stats
*/
flattenAssets(stats) {
let assets = Object.assign({}, stats.assetsByChunkName);
// If there's a temporary mix.js chunk, we can safely remove it.
if (assets.mix) {
assets.mix = collect(assets.mix).except('mix.js').all();
}
return (
collect(assets)
.flatten()
// Don't add hot updates to manifest
.filter(name => name.indexOf('hot-update') === -1)
.all()
);
}
/**
* Prepare the provided path for processing.
*
* @param {string} filePath
*/
normalizePath(filePath) {
if (
this.mix.config.publicPath &&
filePath.startsWith(this.mix.config.publicPath)
) {
filePath = filePath.substring(this.mix.config.publicPath.length);
}
filePath = filePath.replace(/\\/g, '/');
if (!filePath.startsWith('/')) {
filePath = '/' + filePath;
}
return filePath;
}
}
module.exports = Manifest;

280
node_modules/laravel-mix/src/Mix.js generated vendored Executable file
View File

@@ -0,0 +1,280 @@
let { Chunks } = require('./Chunks');
let buildConfig = require('./config');
let ComponentRegistrar = require('./components/ComponentRegistrar');
let Components = require('./components/Components');
let Dependencies = require('./Dependencies');
let Dispatcher = require('./Dispatcher');
let Dotenv = require('dotenv');
let File = require('./File');
let HotReloading = require('./HotReloading');
let Manifest = require('./Manifest');
let Paths = require('./Paths');
let WebpackConfig = require('./builder/WebpackConfig');
let { Resolver } = require('./Resolver');
const Log = require('./Log');
/** @typedef {import("./tasks/Task")} Task */
class Mix {
/** @type {Mix|null} */
static _primary = null;
/** @type {Record<string, boolean>} */
static _hasWarned = {};
/**
* Create a new instance.
*/
constructor() {
/** @type {ReturnType<buildConfig>} */
this.config = buildConfig(this);
this.chunks = new Chunks(this);
this.components = new Components();
this.dispatcher = new Dispatcher();
this.manifest = new Manifest('mix-manifest.json', this);
this.paths = new Paths();
this.registrar = new ComponentRegistrar(this);
this.webpackConfig = new WebpackConfig(this);
this.hot = new HotReloading(this);
this.resolver = new Resolver();
this.dependencies = new Dependencies();
this.logger = Log;
/** @type {Task[]} */
this.tasks = [];
this.booted = false;
this.bundlingJavaScript = false;
/**
* @internal
* @type {boolean}
**/
this.initialized = false;
/**
* @internal
* @type {false | null | string | string[] | Record<string, string | string[]>}
*/
this.globalStyles = null;
/**
* @internal
* @type {boolean|string}
**/
this.extractingStyles = false;
}
/**
* @internal
*/
static get primary() {
return Mix._primary || (Mix._primary = new Mix());
}
/**
* @internal
*/
async build() {
if (!this.booted) {
console.warn(
'Mix was not set up correctly. Please ensure you import or require laravel-mix in your mix config.'
);
this.boot();
}
return this.webpackConfig.build();
}
/**
* @internal
*/
boot() {
if (this.booted) {
return this;
}
this.booted = true;
// Load .env
Dotenv.config();
// If we're using Laravel set the public path by default
if (this.sees('laravel')) {
this.config.publicPath = 'public';
}
this.listen('init', () => this.hot.record());
this.makeCurrent();
return this;
}
/**
* @internal
*/
async installDependencies() {
await this.dispatch('internal:gather-dependencies');
await this.dependencies.install();
}
/**
* @internal
*/
init() {
if (this.initialized) {
return;
}
this.initialized = true;
return this.dispatch('init', this);
}
/**
* @return {import("laravel-mix").Api}
*/
get api() {
if (!this._api) {
this._api = this.registrar.installAll();
// @ts-ignore
this._api.inProduction = () => this.config.production;
}
// @ts-ignore
return this._api;
}
/**
* Determine if the given config item is truthy.
*
* @param {string} tool
*/
isUsing(tool) {
// @ts-ignore
return !!this.config[tool];
}
/**
* Determine if Mix is executing in a production environment.
*/
inProduction() {
return this.config.production;
}
/**
* Determine if Mix should use HMR.
*/
isHot() {
return process.argv.includes('--hot');
}
/**
* Determine if Mix should watch files for changes.
*/
isWatching() {
return this.isHot() || process.argv.includes('--watch');
}
/**
* Determine if polling is used for file watching
*/
isPolling() {
const hasPollingOption = process.argv.some(arg =>
arg.includes('--watch-options-poll')
);
return this.isWatching() && hasPollingOption;
}
/**
* Determine if Mix sees a particular tool or framework.
*
* @param {string} tool
* @deprecated
*/
sees(tool) {
if (tool === 'laravel') {
return File.exists('./artisan');
}
return false;
}
/**
* Determine if the given npm package is installed.
*
* @param {string} npmPackage
* @deprecated
*/
seesNpmPackage(npmPackage) {
return this.resolver.has(npmPackage);
}
/**
* Queue up a new task.
*
* @param {Task} task
*/
addTask(task) {
this.tasks.push(task);
}
/**
* Listen for the given event.
*
* @param {string|string} event
* @param {import('./Dispatcher').Handler} callback
*/
listen(event, callback) {
this.dispatcher.listen(event, callback);
}
/**
* Dispatch the given event.
*
* @param {string} event
* @param {any | (() => any)} [data]
*/
async dispatch(event, data) {
if (typeof data === 'function') {
data = data();
}
return this.dispatcher.fire(event, data);
}
/**
* @param {string} name
* @internal
*/
resolve(name) {
return this.resolver.get(name);
}
/**
* @internal
*/
makeCurrent() {
// Set up some globals
// @ts-ignore
global.Config = this.config;
// @ts-ignore
global.Mix = this;
// @ts-ignore
global.webpackConfig = this.webpackConfig;
this.chunks.makeCurrent();
return this;
}
}
module.exports = Mix;

59
node_modules/laravel-mix/src/PackageDependency.js generated vendored Executable file
View File

@@ -0,0 +1,59 @@
/**
* @typedef {object} DependencyObject
* @property {string} package
* @property {(name: string) => boolean} [check]
*/
/**
* @typedef {string | DependencyObject} Dependency
*/
exports.PackageDependency = class PackageDependency {
/** @type {string} */
package;
/** @type {string} */
name;
/** @type {(name: string) => boolean | Promise<boolean>} */
checkFn;
/**
*
* @param {Dependency} dep
*/
static from(dep) {
const depObj = typeof dep === 'string' ? { package: dep } : dep;
return new PackageDependency(depObj.package, depObj.check);
}
/**
*
* @param {string} pkg
* @param {(name: string) => boolean} [checkFn]
*/
constructor(pkg, checkFn) {
this.package = pkg;
this.name = pkg.replace(/(?!^@)@.+$/, '');
this.checkFn = checkFn || (() => true);
}
async needsInstallation() {
return !(await this.isInstalled()) || !(await this.isValid());
}
async isInstalled() {
try {
require.resolve(this.name);
return true;
} catch (e) {
return false;
}
}
async isValid() {
return this.checkFn(this.name);
}
};

26
node_modules/laravel-mix/src/PackageManager.js generated vendored Executable file
View File

@@ -0,0 +1,26 @@
const File = require('./File');
const Paths = require('./Paths');
class PackageManager {
static detect() {
const execPath = process.env.npm_execpath || '';
if (
execPath.endsWith('yarn.js') ||
execPath.endsWith('yarn') ||
PackageManager.hasYarnLockFile()
) {
return 'yarn';
}
return 'npm';
}
static hasYarnLockFile() {
const paths = new Paths();
return File.exists(paths.root('yarn.lock'));
}
}
module.exports = PackageManager;

56
node_modules/laravel-mix/src/Paths.js generated vendored Executable file
View File

@@ -0,0 +1,56 @@
let path = require('path');
class Paths {
/**
* Create a new Paths instance.
*/
constructor() {
// TODO: Refactor setup to allow removing this check
if (process.env.NODE_ENV === 'test') {
this.rootPath = path.resolve(__dirname, '../');
} else {
this.rootPath = process.cwd();
}
}
/**
* Set the root path to resolve webpack.mix.js.
*
* @param {string} path
*/
setRootPath(path) {
this.rootPath = path;
return this;
}
/**
* Determine the path to the user's webpack.mix.js file.
*/
mix() {
const path = this.root(
process.env && process.env.MIX_FILE ? process.env.MIX_FILE : 'webpack.mix'
);
try {
require.resolve(`${path}.cjs`);
return `${path}.cjs`;
} catch (err) {
//
}
return path;
}
/**
* Determine the project root.
*
* @param {string} [append]
*/
root(append = '') {
return path.resolve(this.rootPath, append);
}
}
module.exports = Paths;

83
node_modules/laravel-mix/src/PostCssPluginsFactory.js generated vendored Executable file
View File

@@ -0,0 +1,83 @@
module.exports = class PostCssPluginsFactory {
/**
* Create a new instance.
* @param {import('./Mix.js')} context
*/
constructor(context) {
this.context = context;
/** @type {import('postcss').AcceptedPlugin[]} */
this.plugins = [];
}
/**
* Load all relevant PostCSS plugins.
*
* @param {import('postcss').AcceptedPlugin[] | undefined} plugins
*/
load(plugins = []) {
this.loadGlobalPlugins();
this.loadLocalPlugins(plugins);
this.loadAutoprefixer();
this.loadCssNano();
return this.plugins;
}
/**
* Load the user's postcss.config.js file, if any.
*
* @deprecated postcss-loader already does this on its own
*/
loadConfigFile() {
let postcssrc = require('postcss-load-config');
try {
this.plugins = [...this.plugins, ...postcssrc.sync().plugins];
} catch (e) {
// No postcss.config.js file exists.
}
}
/**
* Load any global postcss plugins that have been passed to Mix.
*/
loadGlobalPlugins() {
if (this.context.config.postCss && this.context.config.postCss.length) {
this.plugins = [...this.plugins, ...this.context.config.postCss];
}
}
/**
* Load any postcss plugins that were passed to the Mix command.
*
* @param {import('postcss').AcceptedPlugin[] | undefined} plugins
*/
loadLocalPlugins(plugins) {
if (plugins && plugins.length) {
this.plugins = [...this.plugins, ...plugins];
}
}
/**
* Add autoprefixer to the plugins list.
*/
loadAutoprefixer() {
if (this.context.config.autoprefixer) {
this.plugins.push(require('autoprefixer')(this.context.config.autoprefixer));
}
}
/**
* Add CSSNano to the plugins list.
*/
loadCssNano() {
if (this.context.config.production && this.context.config.cssNano !== false) {
this.plugins.push(
require('cssnano')({
preset: ['default', this.context.config.cssNano]
})
);
}
}
};

57
node_modules/laravel-mix/src/Resolver.js generated vendored Executable file
View File

@@ -0,0 +1,57 @@
class Resolver {
constructor() {
/** @type {Record<string, string>} */
this.aliases = {};
}
/**
*
* @param {string} name
*/
get(name) {
if (this.aliases[name] !== undefined) {
return this.aliases[name];
}
try {
return require.resolve(name);
} catch (err) {
return name;
}
}
/**
*
* @param {string} name
* @returns {boolean}
*/
has(name) {
if (this.aliases[name] !== undefined) {
return true;
}
try {
require.resolve(name);
return true;
} catch (e) {
return false;
}
}
/**
*
* @param {string} name
* @param {string} newName
* @internal
*/
alias(name, newName) {
this.aliases[name] = require.resolve(newName);
}
clear() {
this.aliases = {};
}
}
module.exports.Resolver = Resolver;

58
node_modules/laravel-mix/src/VueVersion.js generated vendored Executable file
View File

@@ -0,0 +1,58 @@
class VueVersion {
/**
*
* @param {import("./Mix")} mix
*/
constructor(mix) {
this.mix = mix;
}
/**
* Vue versions that are supported by Mix.
*
* @returns {number[]}
*/
supported() {
return [2, 3];
}
/**
* Detect and validate the current version of Vue for the build.
*
* @param {string|number|null|undefined} [version]
* @returns {number}
*/
detect(version) {
version = parseInt(`${version}`);
if (!version || isNaN(version)) {
try {
return this.detect(require(this.mix.resolve('vue')).version);
} catch (e) {
this.mix.logger.error(`${e}`);
this.fail();
}
}
if (this.supported().includes(version)) {
return version;
}
this.fail();
}
/**
* Abort and log that a supported version of Vue wasn't found.
* @returns {never}
*/
fail() {
this.mix.logger.error(
`We couldn't find a supported version of Vue in your project. ` +
`Please ensure that it's installed (npm install vue).`
);
throw new Error('Unable to detect vue version');
}
}
module.exports = VueVersion;

113
node_modules/laravel-mix/src/builder/Entry.js generated vendored Executable file
View File

@@ -0,0 +1,113 @@
let path = require('path');
let File = require('../File');
class Entry {
/**
* Create a new Entry instance.
* @param {import("../Mix")} mix
*/
constructor(mix) {
// TODO: Simplify in Mix 7 -- Here for backwards compat if a plugin creates this class directly
this.mix = mix || global.Mix;
/** @type {Record<string, string[]>} */
this.structure = {};
this.base = '';
}
/**
* Fetch the underlying entry structure.
*/
get() {
return this.structure;
}
/**
* Get the object keys for the structure.
*/
keys() {
return Object.keys(this.structure);
}
/**
* Add a key key-val pair to the structure.
*
* @param {string} key
* @param {any} val
*/
add(key, val) {
this.structure[key] = (this.structure[key] || []).concat(val);
return this;
}
/**
* Add a new key-val pair, based on a given output path.
*
* @param {any} val
* @param {File} output
* @param {File} fallback
*/
addFromOutput(val, output, fallback) {
output = this.normalizePath(output, fallback);
return this.add(this.createName(output), val);
}
/**
* Add a default entry script to the structure.
*/
addDefault() {
this.add('mix', new File(path.resolve(__dirname, 'mock-entry.js')).path());
}
hasDefault() {
return (this.structure.mix || []).some(path => path.includes('mock-entry.js'));
}
/**
* Build the proper entry name, based on a given output.
*
* @param {File} output
*/
createName(output) {
let name = output
.pathFromPublic(this.mix.config.publicPath)
.replace(/\.js$/, '')
.replace(/\\/g, '/');
this.base = path.parse(name).dir;
return name;
}
/**
* Normalize the given output path.
*
* @param {File} output
* @param {File} fallback
*/
normalizePath(output, fallback) {
// All output paths need to start at the project's public dir.
let pathFromPublicDir = output.pathFromPublic();
if (
!pathFromPublicDir.startsWith('/' + this.mix.config.publicPath) &&
!pathFromPublicDir.startsWith('\\' + this.mix.config.publicPath)
) {
output = new File(
path.join(this.mix.config.publicPath, output.pathFromPublic())
);
}
// If the output points to a directory, we'll grab a file name from the fallback src.
if (output.isDirectory()) {
output = new File(
path.join(output.filePath, fallback.nameWithoutExtension() + '.js')
);
}
return output;
}
}
module.exports = Entry;

291
node_modules/laravel-mix/src/builder/MergeSmart.js generated vendored Executable file
View File

@@ -0,0 +1,291 @@
// @ts-nocheck
// This code was taken from v4.2.2 of webpack-merge for backwards compatability.
// With minor modifications since Mix is not transpiled before running in Node.
// Sources:
// 1. https://github.com/survivejs/webpack-merge/blob/v4.2.2/src/index.js
// 2. https://github.com/survivejs/webpack-merge/blob/v4.2.2/src/join-arrays-smart.js
const { isEqual, mergeWith, differenceWith, unionWith } = require('lodash');
function isRule(key) {
return ['preLoaders', 'loaders', 'postLoaders', 'rules'].indexOf(key) >= 0;
}
const isArray = Array.isArray;
function uniteRules(rules, key, newRule, rule) {
if (
String(rule.test) !== String(newRule.test) ||
((newRule.enforce || rule.enforce) && rule.enforce !== newRule.enforce) ||
(newRule.include && !isSameValue(rule.include, newRule.include)) ||
(newRule.exclude && !isSameValue(rule.exclude, newRule.exclude))
) {
return false;
} else if (
!rule.test &&
!rule.include &&
!rule.exclude &&
(rule.loader && rule.loader.split('?')[0]) !==
(newRule.loader && newRule.loader.split('?')[0])
) {
// Don't merge the rule if there isn't any identifying fields and the loaders don't match
return false;
} else if ((rule.include || rule.exclude) && !newRule.include && !newRule.exclude) {
// Don't merge child without include/exclude to parent that has either
return false;
}
// apply the same logic for oneOf
if (rule.oneOf && newRule.oneOf) {
rule.oneOf = unionWith(
rule.oneOf,
newRule.oneOf,
uniteRules.bind(null, {}, 'oneOf')
);
return true;
}
// newRule.loader should always override use, loaders and oneOf
if (newRule.loader) {
const optionsKey = newRule.options ? 'options' : newRule.query && 'query';
delete rule.use;
delete rule.loaders;
delete rule.oneOf;
rule.loader = newRule.loader;
if (optionsKey) {
rule[optionsKey] = newRule[optionsKey];
}
} else if (newRule.oneOf) {
delete rule.use;
delete rule.loaders;
delete rule.loader;
rule.oneOf = newRule.oneOf;
} else if (
(rule.use || rule.loaders || rule.loader) &&
(newRule.use || newRule.loaders)
) {
const expandEntry = loader => (typeof loader === 'string' ? { loader } : loader);
// this is only here to avoid breaking existing tests
const unwrapEntry = entry =>
!entry.options && !entry.query ? entry.loader : entry;
let entries;
if (rule.loader) {
const optionsKey = rule.options ? 'options' : rule.query && 'query';
entries = [{ loader: rule.loader }];
if (optionsKey) {
entries[0][optionsKey] = rule[optionsKey];
}
delete rule.loader;
if (optionsKey) {
delete rule[optionsKey];
}
} else {
entries = [].concat(rule.use || rule.loaders).map(expandEntry);
}
const newEntries = [].concat(newRule.use || newRule.loaders).map(expandEntry);
const loadersKey = rule.use || newRule.use ? 'use' : 'loaders';
const resolvedKey = `${key}.${loadersKey}`;
switch (rules[resolvedKey]) {
case 'prepend':
rule[loadersKey] = [
...differenceWith(newEntries, entries, uniteEntries),
...entries
].map(unwrapEntry);
break;
case 'replace':
rule[loadersKey] = newRule.use || newRule.loaders;
break;
default:
rule[loadersKey] = combineEntries(newEntries, entries).map(unwrapEntry);
}
}
if (newRule.include) {
rule.include = newRule.include;
}
if (newRule.exclude) {
rule.exclude = newRule.exclude;
}
return true;
}
/**
* Check equality of two values using lodash's isEqual
* Arrays need to be sorted for equality checking
* but clone them first so as not to disrupt the sort order in tests
*/
function isSameValue(a, b) {
const [propA, propB] = [a, b].map(value =>
isArray(value) ? [...value].sort() : value
);
return isEqual(propA, propB);
}
function areEqualEntries(newEntry, entry) {
const loaderNameRe = /^([^?]+)/gi;
const [loaderName] = entry.loader.match(loaderNameRe);
const [newLoaderName] = newEntry.loader.match(loaderNameRe);
return loaderName === newLoaderName;
}
function uniteEntries(newEntry, entry) {
if (areEqualEntries(newEntry, entry)) {
// Replace query values with newer ones
mergeWith(entry, newEntry);
return true;
}
return false;
}
/* Combines entries and newEntries, while respecting the order of loaders in each.
Iterates through new entries. If the new entry also exists in existing entries,
we'll put in all of the loaders from existing entries that come before it (in case
those are pre-requisites). Any remaining existing entries are added at the end.
Since webpack processes right-to-left, we're working backwards through the arrays
*/
function combineEntries(newEntries, existingEntries) {
const resultSet = [];
// We're iterating through newEntries, this keeps track of where we are in the existingEntries
let existingEntriesIteratorIndex = existingEntries.length - 1;
for (let i = newEntries.length - 1; i >= 0; i -= 1) {
const currentEntry = newEntries[i];
const indexInExistingEntries = findLastIndexUsingComparinator(
existingEntries,
currentEntry,
areEqualEntries,
existingEntriesIteratorIndex
);
const hasEquivalentEntryInExistingEntries = indexInExistingEntries !== -1;
if (hasEquivalentEntryInExistingEntries) {
// If the same entry exists in existing entries, we should add all of the entries that
// come before to maintain order
for (
let j = existingEntriesIteratorIndex;
j > indexInExistingEntries;
j -= 1
) {
const existingEntry = existingEntries[j];
// If this entry also exists in new entries, we'll add as part of iterating through
// new entries so that if there's a conflict between existing entries and new entries,
// new entries order wins
const hasMatchingEntryInNewEntries =
findLastIndexUsingComparinator(
newEntries,
existingEntry,
areEqualEntries,
i
) !== -1;
if (!hasMatchingEntryInNewEntries) {
resultSet.unshift(existingEntry);
}
existingEntriesIteratorIndex -= 1;
}
uniteEntries(currentEntry, existingEntries[existingEntriesIteratorIndex]);
// uniteEntries mutates the second parameter to be a merged version, so that's what's pushed
resultSet.unshift(existingEntries[existingEntriesIteratorIndex]);
existingEntriesIteratorIndex -= 1;
} else {
const alreadyHasMatchingEntryInResultSet =
findLastIndexUsingComparinator(
resultSet,
currentEntry,
areEqualEntries
) !== -1;
if (!alreadyHasMatchingEntryInResultSet) {
resultSet.unshift(currentEntry);
}
}
}
// Add remaining existing entries
for (
existingEntriesIteratorIndex;
existingEntriesIteratorIndex >= 0;
existingEntriesIteratorIndex -= 1
) {
const existingEntry = existingEntries[existingEntriesIteratorIndex];
const alreadyHasMatchingEntryInResultSet =
findLastIndexUsingComparinator(resultSet, existingEntry, areEqualEntries) !==
-1;
if (!alreadyHasMatchingEntryInResultSet) {
resultSet.unshift(existingEntry);
}
}
return resultSet;
}
function findLastIndexUsingComparinator(
entries,
entryToFind,
comparinator,
startingIndex
) {
startingIndex = startingIndex || entries.length - 1;
for (let i = startingIndex; i >= 0; i -= 1) {
if (areEqualEntries(entryToFind, entries[i])) {
return i;
}
}
return -1;
}
const { mergeWithCustomize } = require('webpack-merge');
module.exports.mergeSmart = mergeWithCustomize({
customizeArray: (a, b, key) => {
if (isRule(key.split('.').slice(-1)[0])) {
return unionWith(a, b, uniteRules.bind(null, {}, key));
}
return null;
},
// Added by Mix to fix a regex merge bug
customizeObject: (a, b, key) => {
if (a instanceof RegExp) {
if (b instanceof RegExp) {
return b;
}
return a;
}
if (b instanceof RegExp) {
return b;
}
return null;
}
});

12
node_modules/laravel-mix/src/builder/MergeWebpackConfig.js generated vendored Executable file
View File

@@ -0,0 +1,12 @@
let { mergeSmart } = require('./MergeSmart');
/** @typedef {import('webpack').Configuration} Configuration */
/**
*
* @param {Configuration} configA
* @param {Configuration} configB
*/
module.exports = (configA, configB) => {
return mergeSmart(configA, configB);
};

197
node_modules/laravel-mix/src/builder/WebpackConfig.js generated vendored Executable file
View File

@@ -0,0 +1,197 @@
let path = require('path');
let Entry = require('./Entry');
let webpackRules = require('./webpack-rules');
let webpackPlugins = require('./webpack-plugins');
let webpackDefaultConfig = require('./webpack-default');
class WebpackConfig {
/**
* Create a new instance.
*
* @param {import("../Mix.js")} mix
*/
constructor(mix) {
this.mix = mix;
this.chunks = mix.chunks;
/** @type {ReturnType<webpackDefaultConfig>} */
this.webpackConfig = {};
}
/**
* Build the Webpack configuration object.
*/
async build() {
this.webpackConfig = webpackDefaultConfig(this.mix);
await this.buildEntry();
this.buildOutput();
this.configureHMR();
await this.buildRules();
await this.buildPlugins();
this.buildChunks();
// We'll announce that the core config object has been
// generated by Mix. At this point, any plugins may
// hook in and modify the config as necessary.
await this.mix.dispatch('configReady', this.webpackConfig);
// Rebuild the chunks as plugins may have added new ones
this.buildChunks();
// Finally, we'll make one last announcement for the user
// to hook into - using mix.override().
await this.mix.dispatch('configReadyForUser', this.webpackConfig);
// Rebuild the chunks as the user may have changed things
this.buildChunks();
return this.webpackConfig;
}
/**
* Build the entry object.
*/
async buildEntry() {
let entry = new Entry(this.mix);
if (!this.mix.bundlingJavaScript) {
entry.addDefault();
}
await this.mix.dispatch('loading-entry', entry);
this.webpackConfig.entry = entry.get();
}
/**
* Build the output object.
*/
buildOutput() {
this.webpackConfig.output = {
hashFunction: 'xxhash64',
path: path.resolve(this.mix.config.publicPath),
filename: '[name].js',
chunkFilename: pathData => {
let hasAbsolutePathChunkName =
pathData.chunk &&
pathData.chunk.name &&
pathData.chunk.name.startsWith('/');
if (
(this.mix.components.get('js') || this.mix.components.get('ts')) &&
!hasAbsolutePathChunkName
) {
let output = this.mix.components.get('ts')
? this.mix.components.get('ts').toCompile[0].output
: this.mix.components.get('js').toCompile[0].output;
return `${output.normalizedOutputPath()}/[name].js`;
}
return '[name].js';
},
publicPath: '/'
};
}
configureHMR() {
if (!this.mix.isUsing('hmr')) {
return;
}
// TODO: Centralize this code between HotReloading and here…
// It's duplicated
const { https, host, port } = this.mix.config.hmrOptions;
const protocol = https ? 'https' : 'http';
const url = `${protocol}://${host}:${port}/`;
this.webpackConfig.output = {
...this.webpackConfig.output,
publicPath: url
};
this.webpackConfig.devServer = {
host,
port,
client: {
webSocketURL: {
hostname: host,
pathname: '/ws',
port
}
},
liveReload: false,
https,
devMiddleware: {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
'Access-Control-Allow-Headers':
'X-Requested-With, Content-Type, Authorization'
}
},
/**
*
* @param {{app: import("express").Application}} param0
*/
onBeforeSetupMiddleware({ app }) {
app.use(function (req, _, next) {
// Something causes hot update chunks (except for the JSON payload)
// to start with a double slash
// e.g. GET http://localhost:8080//js/app.[hash].hot-update.js
// This causes loading those chunks to fail so we patch it up here
// This is super hacky and a proper solution should be found eventually
req.url = req.url.replace(/^\/\//, '/');
next();
});
},
...this.webpackConfig.devServer
};
}
/**
* Build the rules array.
*/
async buildRules() {
this.webpackConfig.module = this.webpackConfig.module || {};
this.webpackConfig.module.rules = this.webpackConfig.module.rules || [];
this.webpackConfig.module.rules.push(...webpackRules(this.mix));
await this.mix.dispatch('loading-rules', this.webpackConfig.module.rules);
}
/**
* Build the plugins array.
*/
async buildPlugins() {
this.webpackConfig.plugins = this.webpackConfig.plugins || [];
this.webpackConfig.plugins.push(...webpackPlugins(this.mix));
await this.mix.dispatch('loading-plugins', this.webpackConfig.plugins);
}
/**
* Build the resolve object.
*/
buildChunks() {
this.webpackConfig = require('./MergeWebpackConfig')(
this.webpackConfig,
this.mix.chunks.config()
);
}
}
module.exports = WebpackConfig;

0
node_modules/laravel-mix/src/builder/mock-entry.js generated vendored Executable file
View File

72
node_modules/laravel-mix/src/builder/webpack-default.js generated vendored Executable file
View File

@@ -0,0 +1,72 @@
let path = require('path');
let TerserPlugin = require('terser-webpack-plugin');
/**
*
* @param {import("../Mix")} mix
* @returns {import("webpack").Configuration & {devServer?: import("webpack").WebpackOptionsNormalized["devServer"]}}
*/
module.exports = function (mix) {
// TODO: Remove in Mix 7 -- Here for backwards compat if a plugin requires this file
mix = mix || global.Mix;
return {
context: mix.paths.root(),
mode: mix.inProduction() ? 'production' : 'development',
infrastructureLogging: mix.isWatching() ? { level: 'none' } : {},
entry: {},
output: {
assetModuleFilename: '[name][ext]?[hash]',
chunkFilename: '[name].[hash:5].js'
},
module: { rules: [] },
plugins: [],
resolve: {
extensions: ['*', '.wasm', '.mjs', '.js', '.jsx', '.json'],
roots: [path.resolve(mix.config.publicPath)]
},
stats: {
preset: 'errors-warnings',
performance: mix.inProduction()
},
performance: {
hints: false
},
optimization: mix.inProduction()
? {
providedExports: true,
sideEffects: true,
usedExports: true,
// @ts-ignore
minimizer: [new TerserPlugin(mix.config.terser)]
}
: {},
devtool: mix.config.sourcemaps,
// @ts-ignore
devServer: {
headers: {
'Access-Control-Allow-Origin': '*'
},
static: path.resolve(mix.config.publicPath),
historyApiFallback: true,
compress: true,
allowedHosts: 'all'
},
watchOptions: {
ignored: /node_modules/
}
};
};

57
node_modules/laravel-mix/src/builder/webpack-plugins.js generated vendored Executable file
View File

@@ -0,0 +1,57 @@
let MixDefinitionsPlugin = require('../webpackPlugins/MixDefinitionsPlugin');
let BuildCallbackPlugin = require('../webpackPlugins/BuildCallbackPlugin');
let CustomTasksPlugin = require('../webpackPlugins/CustomTasksPlugin');
let ManifestPlugin = require('../webpackPlugins/ManifestPlugin');
let MockEntryPlugin = require('../webpackPlugins/MockEntryPlugin');
let BuildOutputPlugin = require('../webpackPlugins/BuildOutputPlugin');
let WebpackBar = require('webpackbar');
/**
*
* @param {import("../Mix")} mix
*/
module.exports = function (mix) {
// TODO: Remove in Mix 7 -- Here for backwards compat if a plugin requires this file
mix = mix || global.Mix;
let plugins = [];
// If the user didn't declare any JS compilation, we still need to
// use a temporary script to force a compile. This plugin will
// handle the process of deleting the compiled script.
if (!mix.bundlingJavaScript) {
plugins.push(new MockEntryPlugin(mix));
}
// Activate support for Mix_ .env definitions.
plugins.push(
new MixDefinitionsPlugin(mix.paths.root('.env'), {
NODE_ENV: mix.inProduction()
? 'production'
: process.env.NODE_ENV || 'development'
})
);
// Handle the creation of the mix-manifest.json file.
plugins.push(new ManifestPlugin(mix));
// Handle all custom, non-webpack tasks.
plugins.push(new CustomTasksPlugin(mix));
// Notify the rest of our app when Webpack has finished its build.
plugins.push(new BuildCallbackPlugin(stats => mix.dispatch('build', stats)));
// Enable custom output when the Webpack build completes.
plugins.push(
new BuildOutputPlugin({
clearConsole: mix.config.clearConsole,
showRelated: true
})
);
if (process.env.NODE_ENV !== 'test') {
plugins.push(new WebpackBar({ name: 'Mix' }));
}
return plugins;
};

165
node_modules/laravel-mix/src/builder/webpack-rules.js generated vendored Executable file
View File

@@ -0,0 +1,165 @@
/**
*
* @param {import("../Mix")} mix
* @returns {import("webpack").RuleSetRule[]}
*/
module.exports = function (mix) {
// TODO: Remove in Mix 7 -- Here for backwards compat if a plugin requires this file
mix = mix || global.Mix;
return Array.from(buildRules(mix));
};
/**
* @param {string} filename
*/
function isFromPackageManager(filename) {
return /node_modules|bower_components/.test(filename);
}
/**
* @param {string} filename
* @param {string[]} dirs
*/
function normalizedPackageFilename(filename, dirs) {
const WINDOWS_PATH_SEPARATORS = /\\/g;
const patternTemplate = /((.*(node_modules|bower_components))|__DIRS__)\//g;
const vendoredPath = new RegExp(
patternTemplate.source.replace('__DIRS__', dirs.join('|')),
'g'
);
return filename.replace(WINDOWS_PATH_SEPARATORS, '/').replace(vendoredPath, '');
}
/**
*
* @param {import("../Mix")} mix
* @returns {Iterable<import("webpack").RuleSetRule>}
*/
function* buildRules(mix) {
/**
* @param {object} param0
* @param {boolean} [param0.when]
* @param {RegExp} param0.test
* @param {(data: *, meta: { dirs: Record<string, string>}) => string} param0.name
* @param {import("webpack").RuleSetUseItem[]} [param0.loaders]
* @returns {import("webpack").RuleSetRule[]}
**/
function asset({ when = true, test, name, loaders = [] }) {
if (!when) {
return [];
}
if (mix.config.assetModules) {
return [
{
test,
type: 'asset/resource',
generator: {
/**
*
* @param {any} pathData
* @returns
*/
filename: pathData =>
name(pathData, { dirs: mix.config.assetDirs }),
publicPath: mix.config.resourceRoot
},
use: loaders
}
];
}
return [
{
test,
use: [
{
loader: mix.resolve('file-loader'),
options: {
// we're somewhat mimic-ing the asset module API here to simply name resolution further down
/**
*
* @param {string} path
*/
name: path =>
name(
{ filename: path },
{
dirs:
mix.config.fileLoaderDirs ||
mix.config.assetDirs
}
).replace('[ext]', '.[ext]'),
publicPath: mix.config.resourceRoot
}
},
...loaders
]
}
];
}
// Add support for loading HTML files.
yield {
test: /\.html$/,
resourceQuery: { not: [/\?vue/i] },
use: [{ loader: mix.resolve('html-loader') }]
};
// Add support for loading images.
yield* asset({
when: !!mix.config.imgLoaderOptions,
// only include svg that doesn't have font in the path or file name by using negative lookahead
test: /(\.(png|jpe?g|gif|webp|avif)$|^((?!font).)*\.svg$)/,
loaders: [
{
loader: mix.resolve('img-loader'),
options: mix.config.imgLoaderOptions || {}
}
],
name: ({ filename }, { dirs }) => {
if (isFromPackageManager(filename)) {
filename = normalizedPackageFilename(filename, [
'images',
'image',
'img',
'assets'
]);
return `${dirs.images}/vendor/${filename}?[hash]`;
}
return `${dirs.images}/[name][ext]?[hash]`;
}
});
// Add support for loading fonts.
yield* asset({
test: /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/,
name: ({ filename }, { dirs }) => {
if (isFromPackageManager(filename)) {
filename = normalizedPackageFilename(filename, [
'fonts',
'font',
'assets'
]);
return `${dirs.fonts}/vendor/${filename}?[hash]`;
}
return `${dirs.fonts}/[name][ext]?[hash]`;
}
});
// Add support for loading cursor files.
yield* asset({
test: /\.(cur|ani)$/,
name: () => '[name][ext]?[hash]'
});
}

32
node_modules/laravel-mix/src/components/Alias.js generated vendored Executable file
View File

@@ -0,0 +1,32 @@
const { Component } = require('./Component');
module.exports = class Alias extends Component {
/** @type {Record<string, string | {raw: string}>} */
aliases = {};
/**
* Add resolution aliases to webpack's config
*
* @param {Record<string, string | {raw: string}>} paths
*/
register(paths) {
this.aliases = { ...this.aliases, ...paths };
}
/**
* @param {import('webpack').Configuration} config
**/
webpackConfig(config) {
config.resolve = config.resolve || {};
config.resolve.alias = config.resolve.alias || {};
for (const [alias, path] of Object.entries(this.aliases)) {
const resolvedPath =
typeof path === 'object' ? path.raw : this.context.paths.root(path);
config.resolve.alias[alias] = resolvedPath;
}
return config;
}
};

32
node_modules/laravel-mix/src/components/Autoload.js generated vendored Executable file
View File

@@ -0,0 +1,32 @@
const { concat } = require('lodash');
const { Component } = require('./Component');
module.exports = class Autoload extends Component {
/** @type {Record<string, string|string[]>} */
aliases = {};
/**
* Register the component.
*
* @param {Record<string, string>} libs
* @return {void}
*/
register(libs) {
Object.keys(libs).forEach(library => {
concat([], libs[library]).forEach(alias => {
this.aliases[alias] = library.includes('.')
? library.split('.')
: library;
});
});
}
/**
* webpack plugins to be appended to the master config.
*/
webpackPlugins() {
const { ProvidePlugin } = require('webpack');
return [new ProvidePlugin(this.aliases)];
}
};

View File

@@ -0,0 +1,8 @@
const { Component } = require('./Component');
/**
* @deprecated Instead extend `Component` and set `passive` to `true`
**/
module.exports = class AutomaticComponent extends Component {
passive = true;
};

10
node_modules/laravel-mix/src/components/BabelConfig.js generated vendored Executable file
View File

@@ -0,0 +1,10 @@
const { Component } = require('./Component');
module.exports = class BabelConfig extends Component {
/**
* @param {import('@babel/core').TransformOptions} config
*/
register(config) {
this.context.config.babelConfig = config;
}
};

13
node_modules/laravel-mix/src/components/Before.js generated vendored Executable file
View File

@@ -0,0 +1,13 @@
const { Component } = require('./Component');
module.exports = class Before extends Component {
/**
* Register the component.
*
* @param {() => void|Promise<void>} callback
* @return {void}
*/
register(callback) {
this.context.listen('init', callback);
}
};

75
node_modules/laravel-mix/src/components/BrowserSync.js generated vendored Executable file
View File

@@ -0,0 +1,75 @@
const { Component } = require('./Component');
/** @typedef {import('../../types/browsersync').Options} BrowserSyncOptions */
module.exports = class BrowserSync extends Component {
requiresReload = true;
/** @type {BrowserSyncOptions} */
userConfig = {};
/**
* Required dependencies for the component.
*/
dependencies() {
return ['browser-sync', 'browser-sync-webpack-plugin@^2.3.0'];
}
/**
* Register the component.
*
* @param {string|BrowserSyncOptions} userConfig
*/
register(userConfig) {
this.userConfig =
typeof userConfig == 'string' ? { proxy: userConfig } : userConfig;
}
/**
* webpack plugins to be appended to the master config.
*/
webpackPlugins() {
let BrowserSyncPlugin = require('browser-sync-webpack-plugin');
return [new BrowserSyncPlugin(this.config(), { reload: false })];
}
/**
* The regex used to determine where the Browsersync
* javascript snippet is injected onto each page.
*/
regex() {
return RegExp('(</body>|</pre>)(?!.*(</body>|</pre>))', 'is');
}
/**
* Build the BrowserSync configuration.
*/
config() {
let userConfig = this.userConfig;
let defaultConfig = {
host: 'localhost',
port: 3000,
proxy: 'app.test',
files: [
'app/**/*.php',
'resources/views/**/*.php',
`${this.context.config.publicPath || 'public'}/**/*.(js|css)`
],
snippetOptions: {
rule: {
match: this.regex(),
fn: function (snippet, match) {
return snippet + match;
}
}
}
};
if (userConfig && userConfig.server) {
delete defaultConfig.proxy;
}
return Object.assign(defaultConfig, userConfig);
}
};

23
node_modules/laravel-mix/src/components/Coffee.js generated vendored Executable file
View File

@@ -0,0 +1,23 @@
const JavaScript = require('./JavaScript');
module.exports = class Coffee extends JavaScript {
/**
* Required dependencies for the component.
*/
dependencies() {
return ['coffee-loader', 'coffeescript'].concat();
}
/**
* webpack rules to be appended to the master config.
*/
webpackRules() {
return [
{
test: /\.coffee$/,
use: [{ loader: this.context.resolve('coffee-loader') }]
},
...super.webpackRules()
];
}
};

77
node_modules/laravel-mix/src/components/Combine.js generated vendored Executable file
View File

@@ -0,0 +1,77 @@
const File = require('../File');
const Assert = require('../Assert');
const ConcatFilesTask = require('../tasks/ConcatenateFilesTask');
const { Component } = require('./Component');
const { concat } = require('lodash');
module.exports = class Combine extends Component {
/**
* The API name for the component.
*/
name() {
return ['combine', 'scripts', 'babel', 'styles', 'minify'];
}
/**
* Register the component.
*
* @param {string|string[]} src
* @param {string} [output]
* @param {boolean} babel
*/
register(src, output = '', babel = false) {
// Do we need to perform compilation?
babel = babel || this.caller === 'babel';
const sources = concat([], src);
const hasOutputPath = output !== undefined && output !== '';
if (hasOutputPath) {
this.context.addTask(
this.createTask({
src: sources,
dst: output,
babel
})
);
return;
}
if (this.caller !== 'minify') {
throw new Error(
`An output file path is required when using mix.${this.caller}()`
);
}
// We've we're minifying an array of files then the output is the same as the input with a .min extension added
for (const source of sources) {
this.context.addTask(
this.createTask({
src: source,
dst: source.replace(/\.([a-z]{2,})$/i, '.min.$1'),
babel
})
);
}
}
/**
* @param {object} param0
* @param {string|string[]} param0.src
* @param {string} param0.dst
* @param {boolean} param0.babel
*/
createTask({ src, dst, babel }) {
const output = new File(dst);
Assert.combine(src, output);
return new ConcatFilesTask({
src,
output,
babel,
ignore: [output.relativePath()]
});
}
};

66
node_modules/laravel-mix/src/components/Component.js generated vendored Executable file
View File

@@ -0,0 +1,66 @@
/**
* @abstract
* @internal (for now)
**/
class Component {
/** Whether or not to automatically register this component */
passive = false;
/** Whether or not this component requires dependency reloading */
requiresReload = false;
/**
* The name used to call this component.
*
* @deprecated
**/
caller = '';
/**
*
* @param {import("../Mix")} mix
*/
constructor(mix) {
this.context = mix;
}
/**
* Specifiy one or more dependencies that must
* be installed for this component to work
*
* @returns {import("../PackageDependency").Dependency[]}
**/
dependencies() {
return [];
}
/**
* Add rules to the webpack config
*
* @returns {import('webpack').RuleSetRule[]}
**/
webpackRules() {
return [];
}
/**
* Add plugins to the webpack config
*
* @returns {import('webpack').WebpackPluginInstance[]}
**/
webpackPlugins() {
return [];
}
/**
* Update the webpack config
*
* @param {import('webpack').Configuration} config
* @returns {import('webpack').Configuration}
**/
webpackConfig(config) {
return config;
}
}
module.exports.Component = Component;

239
node_modules/laravel-mix/src/components/ComponentRegistrar.js generated vendored Executable file
View File

@@ -0,0 +1,239 @@
let mergeWebpackConfig = require('../builder/MergeWebpackConfig');
const { Component } = require('./Component');
const { concat } = require('lodash');
let components = [
'JavaScript',
'Preact',
'React',
'Coffee',
'Define',
'TypeScript',
'Less',
'Sass',
'Stylus',
'PostCss',
'CssWebpackConfig',
'BrowserSync',
'Combine',
'Copy',
'Autoload',
'Alias',
'Vue',
'React',
'Preact',
'Version',
'Extend',
'Extract',
'Notifications',
'DisableNotifications',
'PurifyCss',
'LegacyNodePolyfills',
'WebpackConfig',
'DumpWebpackConfig',
'Then',
'Override',
'SourceMaps',
'SetPublicPath',
'SetResourceRoot',
'Options',
'When',
'BabelConfig',
'Before'
];
class ComponentRegistrar {
/**
*
* @param {import('../Mix')} [mix]
*/
constructor(mix) {
this.mix = mix || global.Mix;
this.components = {};
}
/**
* Install all default components.
*/
installAll() {
components.map(name => require(`./${name}`)).forEach(c => this.install(c));
return this.components;
}
/**
* Install a component.
*
* @param {import("laravel-mix").Component} ComponentDefinition
* @param {string[]} [names]
*/
install(ComponentDefinition, names) {
/** @type {import("laravel-mix").Component} */
let component;
// If we're extending from the internal `Component` class then we provide the mix API object
if (Object.prototype.isPrototypeOf.call(Component, ComponentDefinition)) {
// @ts-ignore
// This API is not finalized which is why we've restricted to to the internal component class for now
component = new ComponentDefinition(this.mix);
} else if (typeof ComponentDefinition === 'function') {
component = new ComponentDefinition();
} else {
component = ComponentDefinition;
}
this.registerComponent(component, names || this.getComponentNames(component));
this.mix.listen('internal:gather-dependencies', () => {
if (!component.activated && !component.passive) {
return;
}
if (!component.dependencies) {
return;
}
this.mix.dependencies.enqueue(
concat([], component.dependencies()),
component.requiresReload || false
);
});
this.mix.listen('init', () => {
if (!component.activated && !component.passive) {
return;
}
component.boot && component.boot();
component.babelConfig && this.applyBabelConfig(component);
this.mix.listen('loading-entry', entry => {
component.webpackEntry && component.webpackEntry(entry);
});
this.mix.listen('loading-rules', rules => {
component.webpackRules && this.applyRules(rules, component);
});
this.mix.listen('loading-plugins', plugins => {
component.webpackPlugins && this.applyPlugins(plugins, component);
});
this.mix.listen('configReady', config => {
component.webpackConfig && component.webpackConfig(config);
});
});
return this.components;
}
/**
*
* @param {*} component
* @returns {string[]}
*/
getComponentNames(component) {
if (typeof component.name === 'function') {
return concat([], component.name());
}
return [
component.constructor.name.replace(/^([A-Z])/, letter => letter.toLowerCase())
];
}
/**
* Register the component.
*
* @param {Component} component
* @param {string[]} names
*/
registerComponent(component, names) {
/**
*
* @param {string} name
*/
const register = name => {
this.components[name] = (...args) => {
this.mix.components.record(name, component);
component.caller = name;
component.register && component.register(...args);
component.activated = true;
return this.components;
};
// If we're dealing with a passive component that doesn't
// need to be explicitly triggered by the user, we'll
// call it now.
if (component.passive) {
this.components[name]();
}
// Components can optionally write to the Mix API directly.
if (component.mix) {
Object.keys(component.mix()).forEach(name => {
this.components[name] = component.mix()[name];
});
}
};
names.forEach(name => register(name));
}
/**
* Install the component's dependencies.
*
* @deprecated
*/
installDependencies() {
throw new Error(
'ComponentRegistrar.installDependencies is an implementation detail and no longer used'
);
}
/**
*
* Apply the Babel configuration for the component.
*
* @param {Component} component
*/
applyBabelConfig(component) {
this.mix.config.babelConfig = mergeWebpackConfig(
this.mix.config.babelConfig,
component.babelConfig()
);
}
/**
*
* Apply the webpack rules for the component.
*
* @param {import('webpack').RuleSetRule[]} rules
* @param {Component} component
*/
applyRules(rules, component) {
const newRules = component.webpackRules() || [];
rules.push(...concat(newRules));
}
/**
*
* Apply the webpack plugins for the component.
*
* @param {import('webpack').WebpackPluginInstance[]} plugins
* @param {Component} component
*/
applyPlugins(plugins, component) {
const newPlugins = component.webpackPlugins() || [];
plugins.push(...concat(newPlugins));
}
}
module.exports = ComponentRegistrar;

45
node_modules/laravel-mix/src/components/Components.js generated vendored Executable file
View File

@@ -0,0 +1,45 @@
class Components {
/**
* Create a new Components instance.
*/
constructor() {
/** @type {Record<string, any>} */
this.components = {};
}
/**
* Record a newly registered component.
*
* @param {string} name
* @param {any} component
*/
record(name, component) {
this.components[name] = component;
}
/**
* Retrieve a recorded component.
*
* @param {string} name
*/
get(name) {
return this.components[name];
}
/**
* Determine if the given component name has been registered.
* @param {string} name
*/
has(name) {
return name in this.components;
}
/**
* Retrieve all components.
*/
all() {
return this.components;
}
}
module.exports = Components;

22
node_modules/laravel-mix/src/components/Copy.js generated vendored Executable file
View File

@@ -0,0 +1,22 @@
const File = require('../File');
const CopyFilesTask = require('../tasks/CopyFilesTask');
const { Component } = require('./Component');
module.exports = class Copy extends Component {
/**
* The API name for the component.
*/
name() {
return ['copy', 'copyDirectory'];
}
/**
* Register the component.
*
* @param {any} from
* @param {string} to
*/
register(from, to) {
this.context.addTask(new CopyFilesTask({ from, to: new File(to) }));
}
};

299
node_modules/laravel-mix/src/components/CssWebpackConfig.js generated vendored Executable file
View File

@@ -0,0 +1,299 @@
let semver = require('semver');
let { concat, mapValues } = require('lodash');
let { Component } = require('./Component');
let MiniCssExtractPlugin = require('mini-css-extract-plugin');
let PostCssPluginsFactory = require('../PostCssPluginsFactory');
class CssWebpackConfig extends Component {
passive = true;
/** @returns {import('../Dependencies').DependencyObject[]} */
dependencies() {
this.requiresReload = true;
return [
{
package: 'postcss@^8.3.1',
check: name =>
semver.satisfies(require(`${name}/package.json`).version, '^8.3.1')
}
];
}
/**
* webpack rules to be appended to the master config.
*/
webpackRules() {
return [
{
command: 'css',
type: 'css',
test: /\.p?css$/
},
{
command: 'sass',
type: 'scss',
test: /\.scss$/,
loader: {
loader: this.context.resolve('sass-loader'),
options: {
sassOptions: {
precision: 8,
outputStyle: 'expanded'
}
}
}
},
{
command: 'sass',
type: 'sass',
test: /\.sass$/,
loader: {
loader: this.context.resolve('sass-loader'),
options: {
sassOptions: {
precision: 8,
outputStyle: 'expanded',
indentedSyntax: true
}
}
}
},
{
command: 'less',
type: 'less',
test: /\.less$/,
loader: { loader: this.context.resolve('less-loader') }
},
{
command: 'stylus',
type: 'stylus',
test: /\.styl(us)?$/,
loader: { loader: this.context.resolve('stylus-loader') }
}
].map(rule => this.createRule(rule));
}
/**
* Build up the appropriate loaders for the given rule.
*
* @param {import('webpack').RuleSetRule & {test: RegExp, command: string, type: string}} rule
* @returns {import('webpack').RuleSetRule}
*/
createRule(rule) {
return {
test: rule.test,
exclude: this.excludePathsFor(rule.command),
oneOf: [
{
// Ex: foo.css?module
resourceQuery: /module/,
use: this.createLoaderList(rule, {
mode: 'local',
auto: undefined,
localIdentName:
this.context.config.cssModuleIdentifier || '[hash:base64]'
})
},
{
// Ex: foo.css
// Ex: foo.module.css
use: this.createLoaderList(rule, {
mode: 'local',
auto: true,
localIdentName:
this.context.config.cssModuleIdentifier || '[hash:base64]'
})
}
]
};
}
/**
* Build up the appropriate loaders for the given rule.
*
* @param {import('webpack').RuleSetRule & {test: RegExp, command: string, type: string}} rule
* @param {object} useCssModules
* @returns {any[]}
*/
createLoaderList(rule, useCssModules) {
return [
...CssWebpackConfig.afterLoaders({
method: 'auto',
location: 'default',
context: this.context
}),
{
loader: this.context.resolve('css-loader'),
options: {
/**
* @param {string} url
**/
url: url => {
if (url.startsWith('/')) {
return false;
}
return this.context.config.processCssUrls;
},
modules: useCssModules
}
},
{
loader: this.context.resolve('postcss-loader'),
options: {
postcssOptions: {
plugins: new PostCssPluginsFactory(this.context).load(),
hideNothingWarning: true
}
}
},
rule.loader,
...CssWebpackConfig.beforeLoaders({
context: this.context,
type: rule.type,
injectGlobalStyles: true
})
].filter(Boolean);
}
/**
* Paths to be excluded from the loader.
*
* @param {string} command
*/
excludePathsFor(command) {
let exclusions = this.context.components.get(command);
if (command === 'css' || !exclusions) {
return [];
}
return exclusions.details.map(preprocessor => preprocessor.src.path());
}
/**
* webpack plugins to be appended to the master config.
*/
webpackPlugins() {
return [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name].css'
})
];
}
/**
* Gets a list of loaders to handle CSS
*
* This handles inlining or extraction of CSS based on context.
* The default is to inline styles
*
* @param {object} options
* @param {import('../Mix')} options.context The method to use when handling CSS.
* @param {"auto" | "inline" | "extract"} options.method The method to use when handling CSS.
* @param {"default" | "per-file"} options.location Where these loaders are applied. The `default` set or on a per-file basis (used by preprocessors).
*/
static afterLoaders({ context, method, location }) {
const loaders = [];
if (method === 'auto') {
// TODO: Fix
if (context.extractingStyles !== false) {
method = 'extract';
} else {
method = 'inline';
}
}
if (method === 'inline') {
if (this.wantsVueStyleLoader(context) && location === 'default') {
loaders.push({ loader: context.resolve('vue-style-loader') });
} else {
loaders.push({ loader: context.resolve('style-loader') });
}
} else if (method === 'extract') {
loaders.push({
loader: MiniCssExtractPlugin.loader,
options: {
esModule: true
}
});
} else {
throw new Error(
`Unknown css loader method '${method}'. Expected auto, inline, or extract.`
);
}
return loaders;
}
/**
* @private
* @param {import('../Mix')} context
**/
static wantsVueStyleLoader(context) {
const VueFeature = context.components.get('vue');
return VueFeature && VueFeature.options && VueFeature.options.useVueStyleLoader;
}
/**
* Gets a list of loaders to run
*
* This handles inlining or extraction of CSS based on context.
* The default is to inline styles
*
* @param {object} options
* @param {import('../Mix')} options.context
* @param {string} options.type The file type
* @param {boolean} options.injectGlobalStyles Whether or not to inject global styles
*/
static beforeLoaders({ context, type, injectGlobalStyles }) {
const loaders = [];
if (context.globalStyles && injectGlobalStyles) {
let resources =
CssWebpackConfig.normalizeGlobalStyles(context, context.globalStyles)[
type
] || [];
if (resources.length) {
loaders.push({
loader: context.resolve('sass-resources-loader'),
options: {
hoistUseStatements: true,
resources
}
});
}
}
return loaders;
}
/**
*
* @param {import('../Mix')} context
* @param {string | Record<string, string|string[]>} styles
*/
static normalizeGlobalStyles(context, styles) {
// Backwards compat with existing Vue globalStyles:
// A string only is supported for sass / scss.
if (typeof styles !== 'object') {
styles = {
sass: styles,
scss: styles
};
}
return mapValues(styles, files => {
files = concat([], files);
return files.map(file => context.paths.root(file));
});
}
}
module.exports = CssWebpackConfig;

58
node_modules/laravel-mix/src/components/Define.js generated vendored Executable file
View File

@@ -0,0 +1,58 @@
const { Component } = require('./Component');
/** @typedef {undefined | null | string | number | bigint | boolean} CodeValuePrimitive */
/** @typedef {() => CodeValuePrimitive} LazyCodeValue */
/** @typedef {CodeValuePrimitive | LazyCodeValue} CodeValue */
module.exports = class Define extends Component {
/**
* @type {Record<string, CodeValue>}
* @internal
**/
definitions = {};
/**
*
* @param {Record<string, CodeValue>} definitions
*/
register(definitions) {
this.definitions = {
...this.definitions,
...definitions
};
}
/** @internal */
get defaults() {
return {
'import.meta.env.PROD': () => this.context.api.inProduction(),
'import.meta.env.DEV': () => !this.context.api.inProduction()
};
}
/**
* @param {Record<string, CodeValue>} definitions
*/
resolve(definitions) {
for (const [key, value] of Object.entries(definitions)) {
if (typeof value === 'function') {
definitions[key] = value();
}
}
return definitions;
}
webpackPlugins() {
const { DefinePlugin } = require('webpack');
return [
new DefinePlugin(
this.resolve({
...this.defaults,
...this.definitions
})
)
];
}
};

View File

@@ -0,0 +1,22 @@
const { Component } = require('./Component');
module.exports = class DisableNotifications extends Component {
/**
* The API name for the component.
*/
name() {
return ['disableNotifications', 'disableSuccessNotifications'];
}
/**
* Register the component.
*/
register() {
const enabled = this.caller === 'disableSuccessNotifications' ? ['failure'] : [];
this.context.config.notifications = {
onSuccess: enabled.includes('success'),
onFailure: enabled.includes('failure')
};
}
};

47
node_modules/laravel-mix/src/components/DumpWebpackConfig.js generated vendored Executable file
View File

@@ -0,0 +1,47 @@
const { Component } = require('./Component');
module.exports = class DumpWebpackConfig extends Component {
/**
* The optional name to be used when called by Mix.
*/
name() {
return ['dumpWebpackConfig', 'dump'];
}
/**
* Register the component.
*/
register() {
this.context.listen('configReadyForUser', config => {
this.context.logger.info(this.circularStringify(config));
});
}
/**
*
* @param {any} item
*/
circularStringify(item) {
const cache = new Set();
return JSON.stringify(
item,
(_, value) => {
if (value instanceof RegExp) {
return value.toString();
}
if (typeof value === 'object' && value !== null) {
if (cache.has(value)) {
return undefined;
}
cache.add(value);
}
return value;
},
2
);
}
};

123
node_modules/laravel-mix/src/components/Example.js generated vendored Executable file
View File

@@ -0,0 +1,123 @@
/**
* This file represents an example component interface
* for Mix. All new components can be "inserted" into
* Mix, like so:
*
* // webpack.mix.js
*
* mix.extend('foo', new Example());
*
* mix.foo();
*/
const { Component } = require('./Component');
module.exports = class Example {
/**
* The optional name to be used when called by Mix.
* Defaults to the class name, lowercased.
*
* Ex: mix.example();
*
* @return {string|string[]}
*/
name() {
// Example:
// return 'example';
// return ['example', 'alias'];
}
/**
* All dependencies that should be installed by Mix.
*
* @return {string[]}
*/
dependencies() {
// Example:
// return ['typeScript', 'ts'];
}
/**
* Register the component.
*
* When your component is called, all user parameters
* will be passed to this method.
*
* Ex: register(src, output) {}
* Ex: mix.yourPlugin('src/path', 'output/path');
*
* @param {any} ...params
* @return {void}
*
*/
register() {
// Example:
// this.config = { proxy: arg };
}
/**
* Boot the component. This method is triggered after the
* user's webpack.mix.js file has executed.
*/
boot() {
// Example:
// if (this.context.config.foo) {}
}
/**
* Append to the master Mix webpack entry object.
*
* @param {Entry} entry
* @return {void}
*/
webpackEntry(entry) {
// Example:
// entry.add('foo', 'bar');
}
/**
* Rules to be merged with the master webpack loaders.
*
* @return {any[]}
*/
webpackRules() {
// Example:
// return {
// test: /\.less$/,
// loaders: ['...']
// });
}
/**
* Plugins to be merged with the master webpack config.
*
* @return {any[]}
*/
webpackPlugins() {
// Example:
// return new webpack.ProvidePlugin(this.aliases);
}
/**
* Override the generated webpack configuration.
*
* @param {import("webpack").Configuration} webpackConfig
* @return {void}
*/
webpackConfig(webpackConfig) {
// Example:
// webpackConfig.resolve.extensions.push('.ts', '.tsx');
}
/**
* Babel config to be merged with Mix's defaults.
*
* @return {import("@babel/core").TransformOptions}
*/
babelConfig() {
// Example:
// return { presets: ['@babel/preset-react'] };
}
};
// Usage:
// mix.extend('example', new Example());

59
node_modules/laravel-mix/src/components/Extend.js generated vendored Executable file
View File

@@ -0,0 +1,59 @@
const { concat } = require('lodash');
const { Component } = require('./Component');
const { createFunctionalComponent } = require('./FunctionalComponent');
/**
* @typedef {import('../../types/component').ClassComponent} ClassComponent
* @typedef {import('../../types/component').ComponentInterface} ComponentInterface
* @typedef {import('../../types/component').FunctionalComponent} FunctionalComponent
* @typedef {import('../../types/component').InstallableComponent} InstallableComponent
* @typedef {import('../../types/component').Component} MixComponent
**/
module.exports = class Extend extends Component {
/**
* Register the component.
*
* @param {string | string[] | FunctionalComponent} name
* @param {Component} component
*/
register(name, component) {
if (typeof name === 'function') {
return this.context.registrar.install(component);
}
const names = concat([], name);
if (this.looksLikeSimpleCallback(component)) {
return this.context.registrar.install(
createFunctionalComponent(names, component)
);
}
return this.context.registrar.install(component, names);
}
/**
* Register the component.
*
* @param {MixComponent} component
* @returns {component is FunctionalComponent} component
*/
looksLikeSimpleCallback(component) {
if (typeof component !== 'function') {
return false;
}
if (!component.prototype) {
return true;
}
return (
typeof component.prototype.name !== 'function' &&
typeof component.prototype.register !== 'function' &&
typeof component.prototype.boot !== 'function' &&
typeof component.prototype.mix !== 'function' &&
typeof component.prototype.dependencies !== 'function'
);
}
};

129
node_modules/laravel-mix/src/components/Extract.js generated vendored Executable file
View File

@@ -0,0 +1,129 @@
const path = require('path');
const File = require('../File');
const { Component } = require('./Component');
/** @typedef {import('../../types/extract').Extraction} Extraction */
/** @typedef {import('../../types/extract').ExtractConfig} ExtractConfig */
/** @typedef {import('../builder/Entry')} Entry */
module.exports = class Extract extends Component {
/** @type {Entry|null} */
entry = null;
/** @type {Extraction[]} */
extractions = [];
/**
* The name of the component.
*
* mix.extract() or mix.extractVendor()
*/
name() {
return ['extract', 'extractVendors'];
}
/**
* Register the component.
*
* @param {ExtractConfig} [config]
* @param {string} [output]
*/
register(config = null, output = null) {
this.context.chunks.runtime = true;
this.extractions.push(this.normalizeExtraction(config, output));
}
/**
* Assets to append to the webpack entry.
*
* @param {Entry} entry
*/
webpackEntry(entry) {
this.entry = entry;
this.context.chunks.entry = entry;
if (!this.context.bundlingJavaScript) {
throw new Error('You must compile JS to extract vendor code');
}
this.extractions.forEach(extraction => {
const path = this.extractionPath(extraction.to);
const isDefaultVendorChunk =
extraction.to === null ||
extraction.to === undefined ||
extraction.test.source ===
'(?<!node_modules)[\\\\/]node_modules[\\\\/]()';
this.context.chunks.add(
`vendor${this.extractions.indexOf(extraction)}`,
path.replace(/\.js$/, ''),
extraction.test,
{
chunks: 'all',
enforce: true,
priority: isDefaultVendorChunk ? -10 : 0
}
);
});
}
extractionPath(outputPath) {
if (outputPath) {
return new File(outputPath).normalizedOutputPath();
}
return path.join(this.entry.base, 'vendor').replace(/\\/g, '/');
}
/**
*
* @param {ExtractConfig|null} [config]
* @param {string} [output]
* @returns {Extraction}
*/
normalizeExtraction(config = null, output = null) {
config = config || {};
if (typeof config === 'string') {
if (output !== null || !config.endsWith('.js')) {
throw new Error(
'mix.extract(string) expects a file path as its only argument'
);
}
config = { to: config };
} else if (typeof config === 'function') {
config = { test: config };
} else if (Array.isArray(config)) {
config = { test: this.buildLibraryRegex(config) };
}
return {
to: output || null,
...config,
test: config.test || this.buildLibraryRegex(config.libraries || [])
};
}
/**
*
* @param {string[]|RegExp} libraries
*/
buildLibraryRegex(libraries = []) {
let pattern = '(?<!node_modules)[\\\\/]node_modules[\\\\/]';
let extra = '';
if (Array.isArray(libraries)) {
extra = libraries.map(lib => `${lib}[\\\\/]`).join('|');
} else if (libraries instanceof RegExp) {
extra = libraries.source;
} else {
throw new Error(
`Unexpected type [${typeof libraries}] passed to mix.extract({ libraries: … }). ` +
`You may pass either an array of strings or a regular expression.`
);
}
return new RegExp(`${pattern}(${extra})`, 'i');
}
};

View File

@@ -0,0 +1,34 @@
/** @typedef {import('../../types/component').ClassComponent} ClassComponent */
/** @typedef {import('../../types/component').FunctionalComponent} FunctionalComponent */
/**
* @param {string[]} names
* @param {FunctionalComponent} component
* @returns {ClassComponent}
*/
exports.createFunctionalComponent = function createFunctionalComponent(names, component) {
return class {
/** @type {any[]} */
args = [];
name() {
return names;
}
/**
*
* @param {...any} args
*/
register(...args) {
this.args = args;
}
/**
*
* @param {import('webpack').Configuration} config
*/
webpackConfig(config) {
component.call(this, config, ...this.args);
}
};
};

71
node_modules/laravel-mix/src/components/JavaScript.js generated vendored Executable file
View File

@@ -0,0 +1,71 @@
const glob = require('glob');
const File = require('../File');
const Assert = require('../Assert');
const { Component } = require('./Component');
module.exports = class JavaScript extends Component {
/** @type {{entry: File[], output: File}[]} */
toCompile = [];
/**
* The API name for the component.
*/
name() {
let name = this.constructor.name.toLowerCase();
return [name === 'javascript' ? 'js' : name];
}
/**
* Register the component.
*
* @param {any} entry
* @param {string} output
*/
register(entry, output) {
if (typeof entry === 'string' && entry.includes('*')) {
entry = glob.sync(entry);
}
Assert.js(entry, output);
entry = [].concat(entry).map(file => new File(file));
this.toCompile.push({ entry, output: new File(output) });
this.context.bundlingJavaScript = true;
}
/**
* Assets to append to the webpack entry.
*
* @param {import('../builder/Entry')} entry
*/
webpackEntry(entry) {
this.toCompile.forEach(js => {
entry.addFromOutput(
js.entry.map(file => file.path()),
js.output,
js.entry[0]
);
});
}
/**
* webpack rules to be appended to the master config.
*/
webpackRules() {
return [
{
test: /\.(cjs|mjs|jsx?|tsx?)$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: this.context.resolve('babel-loader'),
options: this.context.config.babel()
}
]
}
];
}
};

View File

@@ -0,0 +1,50 @@
const { Component } = require('./Component');
module.exports = class LegacyNodePolyfills extends Component {
passive = true;
dependencies() {
return this.context.config.legacyNodePolyfills ? ['process', 'buffer'] : [];
}
webpackPlugins() {
if (!this.context.config.legacyNodePolyfills) {
return [];
}
const { ProvidePlugin } = require('webpack');
return [
new ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
process: 'process/browser.js'
})
];
}
/**
*
* @returns {import('webpack').Configuration}
*/
webpackConfig() {
if (!this.context.config.legacyNodePolyfills) {
return {
resolve: {
fallback: {
Buffer: false,
process: false
}
}
};
}
return {
resolve: {
fallback: {
buffer: this.context.resolve('buffer/'),
process: this.context.resolve('process/browser.js')
}
}
};
}
};

26
node_modules/laravel-mix/src/components/Less.js generated vendored Executable file
View File

@@ -0,0 +1,26 @@
const Preprocessor = require('./Preprocessor');
module.exports = class Less extends Preprocessor {
/**
* Required dependencies for the component.
*/
dependencies() {
return ['less-loader', 'less'];
}
/**
* Register the component.
*
* @param {any} src
* @param {string} output
* @param {any} pluginOptions
* @param {import('postcss').AcceptedPlugin[]} postCssPlugins
*/
register(src, output, pluginOptions = {}, postCssPlugins = []) {
return this.preprocess('less', src, output, pluginOptions, postCssPlugins);
}
chunkRegex() {
return /\.(css|less)$/;
}
};

40
node_modules/laravel-mix/src/components/Notifications.js generated vendored Executable file
View File

@@ -0,0 +1,40 @@
const { Component } = require('./Component');
module.exports = class Notifications extends Component {
passive = true;
/**
* webpack plugins to be appended to the master config.
*/
webpackPlugins() {
if (!this.enabled) {
return [];
}
if (process.env.DISABLE_NOTIFICATIONS === '1') {
return [];
}
const WebpackNotifierPlugin = require('webpack-notifier');
return [
new WebpackNotifierPlugin({
appID: 'Laravel Mix',
title: 'Laravel Mix',
alwaysNotify: this.context.config.notifications.onSuccess,
timeout: false,
hint: process.platform === 'linux' ? 'int:transient:1' : undefined,
contentImage: this.context.paths.root(
'node_modules/laravel-mix/icons/laravel.png'
)
})
];
}
get enabled() {
const { notifications } = this.context.config;
return notifications && (notifications.onSuccess || notifications.onFailure);
}
};

63
node_modules/laravel-mix/src/components/Options.js generated vendored Executable file
View File

@@ -0,0 +1,63 @@
const { Component } = require('./Component');
module.exports = class Options extends Component {
/**
* @param {Record<string, any>} options
*/
register(options) {
this.context.config.merge(options);
this.messages(options).forEach(msg => this.context.logger.message(msg));
}
/**
*
* @param {any} options
*/
messages(options) {
/** @type {import("../Log").LogMessage[]} */
const messages = [];
if ('extractVueStyles' in options) {
messages.push({
type: 'warn',
text: 'The option extractVueStyles has been moved. Please pass the extractStyles option to mix.vue() instead.'
});
}
if ('globalVueStyles' in options) {
messages.push({
type: 'warn',
text: 'The option globalVueStyles has been moved. Please pass the globalStyles option to mix.vue() instead.'
});
}
if ('extractVueStyles' in options || 'globalVueStyles' in options) {
messages.push({
type: 'info',
text: `Example:\n${this.buildVueExample(options)}`
});
}
return messages;
}
/**
*
* @param {any} options
* @returns {string}
*/
buildVueExample(options) {
const props = {};
if ('extractVueStyles' in options) {
props['extractStyles'] = options.extractVueStyles;
}
if ('globalVueStyles' in options) {
props['globalStyles'] = options.globalVueStyles;
}
return `mix.vue(${JSON.stringify(props, null, 2)}})`;
}
};

11
node_modules/laravel-mix/src/components/Override.js generated vendored Executable file
View File

@@ -0,0 +1,11 @@
const { Component } = require('./Component');
module.exports = class Override extends Component {
/**
*
* @param {()=>void|Promise<void>} callback
*/
register(callback) {
this.context.listen('configReadyForUser', callback);
}
};

67
node_modules/laravel-mix/src/components/PostCss.js generated vendored Executable file
View File

@@ -0,0 +1,67 @@
const Assert = require('../Assert');
const File = require('../File');
const Preprocessor = require('./Preprocessor');
module.exports = class PostCss extends Preprocessor {
/**
* The Mix API name for the component.
*/
name() {
return ['postCss', 'css'];
}
/**
* Register the component.
*
* @param {any} src
* @param {string} output
* @param {import('postcss').AcceptedPlugin[] | Record<string, any>} pluginOptions
* @param {import('postcss').AcceptedPlugin[]} postCssPlugins
*/
register(src, output, pluginOptions = {}, postCssPlugins = []) {
// Backwards compat with earlier versions of Mix
if (Array.isArray(pluginOptions) && postCssPlugins.length === 0) {
postCssPlugins = pluginOptions;
pluginOptions = {};
}
if (!Array.isArray(postCssPlugins)) {
postCssPlugins = [postCssPlugins];
}
Assert.preprocessor('postCss', src, output);
const srcFile = new File(src);
const outputFile = this.normalizeOutput(
new File(output),
srcFile.nameWithoutExtension() + '.css'
);
this.details.push({
type: 'postCss',
src: srcFile,
output: outputFile,
pluginOptions,
postCssPlugins
});
// Register a split chunk that takes everything generated
// by this file and puts it in a separate file
// We use a output-specific chunk name so we don't accidentally merge multiple files
this._addChunks(
`styles-${outputFile.relativePathWithoutExtension()}`,
srcFile,
outputFile
);
}
/**
* Override the generated webpack configuration.
* @param {import('webpack').Configuration} config
*/
webpackConfig(config) {
config.module.rules.find(rule => rule.test.toString() === '/\\.p?css$/').exclude =
this.details.map(postCss => postCss.src.path());
}
};

31
node_modules/laravel-mix/src/components/Preact.js generated vendored Executable file
View File

@@ -0,0 +1,31 @@
const { Component } = require('./Component');
module.exports = class Preact extends Component {
/**
* Required dependencies for the component.
*/
dependencies() {
return ['babel-preset-preact'];
}
register() {
if (
arguments.length === 2 &&
typeof arguments[0] === 'string' &&
typeof arguments[1] === 'string'
) {
throw new Error(
'mix.preact() is now a feature flag. Use mix.js(source, destination).preact() instead'
);
}
}
/**
* Babel config to be merged with Mix's defaults.
*/
babelConfig() {
return {
presets: ['preact']
};
}
};

245
node_modules/laravel-mix/src/components/Preprocessor.js generated vendored Executable file
View File

@@ -0,0 +1,245 @@
const Assert = require('../Assert');
const path = require('path');
const File = require('../File');
const CssWebpackConfig = require('./CssWebpackConfig');
const PostCssPluginsFactory = require('../PostCssPluginsFactory');
/** @typedef {import('../builder/Entry')} Entry */
/**
* @typedef {object} Detail
* @property {string} type
* @property {File} src
* @property {File} output
* @property {any} pluginOptions
* @property {any[]} postCssPlugins
* @property {boolean} [processUrls]
*/
const { Component } = require('./Component');
module.exports = class Preprocessor extends Component {
/** @type {Detail[]} */
details = [];
/**
* Assets to append to the webpack entry.
*
* @param {Entry} entry
*/
webpackEntry(entry) {
this.details.forEach(detail => {
entry.add(entry.keys()[0], detail.src.path());
});
}
/**
* webpack rules to be appended to the master config.
*/
webpackRules() {
return this.details.map(preprocessor => ({
test: preprocessor.src.path(),
use: this.webpackLoaders(preprocessor)
}));
}
/**
* Fetch all necessary webpack loaders.
*
* @param {Detail} preprocessor
*/
webpackLoaders(preprocessor) {
let processUrls = this.shouldProcessUrls(preprocessor);
/** @type {import('webpack').RuleSetRule[]} */
let loaders = [
...CssWebpackConfig.afterLoaders({
context: this.context,
method: 'extract',
location: 'per-file'
}),
{
loader: this.context.resolve('css-loader'),
options: {
/**
*
* @param {string} url
*/
url: url => {
if (url.startsWith('/')) {
return false;
}
return processUrls;
},
sourceMap: this.context.isUsing('sourcemaps'),
importLoaders: 1
}
},
{
loader: this.context.resolve('postcss-loader'),
options: this.postCssLoaderOptions(preprocessor)
}
];
if (preprocessor.type === 'sass' && processUrls) {
loaders.push({
loader: this.context.resolve('resolve-url-loader'),
options: {
sourceMap: true
}
});
}
if (preprocessor.type !== 'postCss') {
loaders.push({
loader: `${preprocessor.type}-loader`,
options: this.loaderOptions(preprocessor, processUrls)
});
}
loaders.push(
...CssWebpackConfig.beforeLoaders({
context: this.context,
type: preprocessor.type,
injectGlobalStyles: false
})
);
return loaders;
}
/**
* Prepare the preprocessor plugin options.
*
* @param {Detail} preprocessor
* @param {Boolean} processUrls
*/
loaderOptions(preprocessor, processUrls) {
return Object.assign(preprocessor.pluginOptions, {
sourceMap:
preprocessor.type === 'sass' && processUrls
? true
: this.context.isUsing('sourcemaps')
});
}
/**
* Generate the options object for the PostCSS Loader.
*
* @param {Detail} preprocessor
*/
postCssLoaderOptions(preprocessor) {
return {
sourceMap: this.context.isUsing('sourcemaps'),
postcssOptions: {
plugins: new PostCssPluginsFactory(this.context).load(
preprocessor.postCssPlugins
),
hideNothingWarning: true
}
};
}
/**
* Register a generic CSS preprocessor.
*
* @param {string} type
* @param {string} src
* @param {string} output
* @param {object} pluginOptions
* @param {import('postcss').AcceptedPlugin[]} postCssPlugins
*/
preprocess(type, src, output, pluginOptions = {}, postCssPlugins = []) {
Assert.preprocessor(type, src, output);
const srcFile = new File(src);
const outputFile = this.normalizeOutput(
new File(output),
srcFile.nameWithoutExtension() + '.css'
);
this.details.push({
type: this.constructor.name.toLowerCase(),
src: srcFile,
output: outputFile,
pluginOptions,
postCssPlugins
});
this._addChunks(
`styles-${outputFile.relativePathWithoutExtension()}`,
srcFile,
outputFile
);
return this;
}
/**
* Determine whether to apply url preprocessing.
*
* @param {Detail} preprocessor
* @returns {boolean}
*/
shouldProcessUrls(preprocessor) {
const processUrls =
preprocessor.pluginOptions.processUrls !== undefined
? preprocessor.pluginOptions.processUrls
: this.context.config.processCssUrls;
delete preprocessor.pluginOptions.processUrls;
return processUrls;
}
/**
* Generate a full output path, using a fallback
* file name, if a directory is provided.
*
* @param {File} output
* @param {string} fallbackName
*/
normalizeOutput(output, fallbackName) {
if (output.isDirectory()) {
output = new File(path.join(output.filePath, fallbackName));
}
return output;
}
chunkRegex() {
return /\.p?css$/;
}
/**
* Add the necessary chunks for this preprocessor
*
* This method is for internal use only for now.
*
* @internal
*
* @param {string} name
* @param {File} src
* @param {File} output
*/
_addChunks(name, src, output) {
const tests = [
// 1. Ensure the file is a CSS file
this.chunkRegex(),
// 2. Ensure that just this file is included in this chunk
// _or any dependencies_
src.path()
];
const attrs = {
chunks: 'all',
enforce: true,
type: 'css/mini-extract'
};
this.context.chunks.add(name, output.normalizedOutputPath(), tests, attrs);
}
};

18
node_modules/laravel-mix/src/components/PurifyCss.js generated vendored Executable file
View File

@@ -0,0 +1,18 @@
const { Component } = require('./Component');
module.exports = class PurifyCss extends Component {
passive = true;
/**
* Required dependencies for the component.
*/
dependencies() {
if (this.context.config.purifyCss) {
throw new Error(
'PurifyCSS support is no longer available. We recommend using PurgeCss + postCss instead.'
);
}
return [];
}
};

182
node_modules/laravel-mix/src/components/React.js generated vendored Executable file
View File

@@ -0,0 +1,182 @@
const semver = require('semver');
const { Component } = require('./Component');
const File = require('../File');
module.exports = class React extends Component {
/** @type {import('laravel-mix').ReactConfig} */
options = {
extractStyles: false
};
/**
* Required dependencies for the component.
*/
dependencies() {
const dependencies = ['@babel/preset-react'];
if (this.supportsFastRefreshing()) {
return dependencies.concat([
{
package: '@pmmmwh/react-refresh-webpack-plugin@^0.5.0-rc.0',
check: name =>
semver.satisfies(
require(`${name}/package.json`).version,
'^0.5.0-rc.0'
)
},
'react-refresh'
]);
}
return dependencies;
}
/**
* Register the component.
*
* @param {import('laravel-mix').ReactConfig} options
*/
register(options = {}) {
if (
arguments.length === 2 &&
typeof arguments[0] === 'string' &&
typeof arguments[1] === 'string'
) {
throw new Error(
'mix.react() is now a feature flag. Use mix.js(source, destination).react() instead'
);
}
this.options = Object.assign(this.options, options);
this.context.extractingStyles =
this.context.extractingStyles || !!this.options.extractStyles;
}
/**
* webpack plugins to be appended to the master config.
*/
webpackPlugins() {
if (!this.supportsFastRefreshing()) {
return [];
}
const ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
return [new ReactRefreshPlugin({ overlay: { sockPath: 'ws' } })];
}
/**
* Babel config to be merged with Mix's defaults.
*/
babelConfig() {
const plugins = this.supportsFastRefreshing()
? [this.context.resolve('react-refresh/babel')]
: [];
return {
presets: [['@babel/preset-react', { runtime: 'automatic' }]],
plugins
};
}
/**
* Determine if the React version supports fast refreshing.
*/
supportsFastRefreshing() {
return (
this.context.isHot() && semver.satisfies(this.library().version, '>=16.9.0')
);
}
/**
* Load the currently installed React library.
*/
library() {
return require('react');
}
/**
* Update CSS chunks to extract React styles
*/
updateChunks() {
if (this.options.extractStyles === false) {
return;
}
this.context.chunks.add(
'styles-js',
this.styleChunkName(),
[/.(j|t)s$/, module => module.type === 'css/mini-extract'],
{
chunks: 'all',
enforce: true,
type: 'css/mini-extract'
}
);
this.context.chunks.add(
'styles-jsx',
this.styleChunkName(),
[/.(j|t)sx?$/, module => module.type === 'css/mini-extract'],
{
chunks: 'all',
enforce: true,
type: 'css/mini-extract'
}
);
}
/**
* Override the generated webpack configuration.
*
* @param {Object} config
*/
webpackConfig(config) {
this.updateChunks();
return config;
}
/**
* Get the name of the style chunk.
*
* @returns {string}
*/
styleChunkName() {
// If the user set extractStyles: true, we'll try
// to append the React styles to an existing CSS chunk.
if (this.options.extractStyles === true) {
let chunk = this.context.chunks.find((chunk, id) => id.startsWith('styles-'));
if (chunk) {
return chunk.name;
}
}
return this.extractFile().relativePathWithoutExtension();
}
/**
* Get a new File instance for the extracted file.
*
* @returns {File}
*/
extractFile() {
return new File(this.extractFileName());
}
/**
* Determine the extract file name.
*
* @return {string}
*/
extractFileName() {
let fileName =
typeof this.options.extractStyles === 'string'
? this.options.extractStyles
: '/css/react-styles.css';
return fileName.replace(this.context.config.publicPath, '').replace(/^\//, '');
}
};

59
node_modules/laravel-mix/src/components/Sass.js generated vendored Executable file
View File

@@ -0,0 +1,59 @@
const Preprocessor = require('./Preprocessor');
module.exports = class Sass extends Preprocessor {
/**
* Required dependencies for the component.
*/
dependencies() {
this.requiresReload = true;
const deps = ['sass-loader@^12.1.0', 'sass'];
if (this.context.config.processCssUrls) {
deps.push('resolve-url-loader@^5.0.0');
}
return deps;
}
/**
* Register the component.
*
* @param {any} src
* @param {string} output
* @param {Record<string, any>} pluginOptions
* @param {import('postcss').AcceptedPlugin[]} postCssPlugins
*/
register(src, output, pluginOptions = {}, postCssPlugins = []) {
return this.preprocess(
'sass',
src,
output,
this.pluginOptions(pluginOptions),
postCssPlugins
);
}
/**
* Build the plugin options for sass-loader.
*
* @param {Object} pluginOptions
* @returns {Object}
*/
pluginOptions(pluginOptions) {
return Object.assign(
{
sassOptions: {
precision: 8,
outputStyle: 'expanded'
}
},
pluginOptions,
{ sourceMap: true }
);
}
chunkRegex() {
return /\.(css|s[ac]ss)$/;
}
};

11
node_modules/laravel-mix/src/components/SetPublicPath.js generated vendored Executable file
View File

@@ -0,0 +1,11 @@
const path = require('path');
const { Component } = require('./Component');
module.exports = class SetPublicPath extends Component {
/**
* @param {string} defaultPath
*/
register(defaultPath) {
this.context.config.publicPath = path.normalize(defaultPath.replace(/\/$/, ''));
}
};

10
node_modules/laravel-mix/src/components/SetResourceRoot.js generated vendored Executable file
View File

@@ -0,0 +1,10 @@
const { Component } = require('./Component');
module.exports = class SetResourceRoot extends Component {
/**
* @param {string} path
*/
register(path) {
this.context.config.resourceRoot = path;
}
};

18
node_modules/laravel-mix/src/components/SourceMaps.js generated vendored Executable file
View File

@@ -0,0 +1,18 @@
const { Component } = require('./Component');
module.exports = class SourceMaps extends Component {
register(
generateForProduction = true,
devType = 'eval-source-map',
productionType = 'source-map'
) {
/** @type {string|false} */
let type = devType;
if (this.context.api.inProduction()) {
type = generateForProduction ? productionType : false;
}
this.context.config.sourcemaps = type;
}
};

28
node_modules/laravel-mix/src/components/Stylus.js generated vendored Executable file
View File

@@ -0,0 +1,28 @@
let Preprocessor = require('./Preprocessor');
class Stylus extends Preprocessor {
/**
* Required dependencies for the component.
*/
dependencies() {
return ['stylus', 'stylus-loader'];
}
/**
* Register the component.
*
* @param {any} src
* @param {string} output
* @param {Record<string, any>} pluginOptions
* @param {import('postcss').AcceptedPlugin[]} postCssPlugins
*/
register(src, output, pluginOptions = {}, postCssPlugins = []) {
return this.preprocess('stylus', src, output, pluginOptions, postCssPlugins);
}
chunkRegex() {
return /\.(css|styl(us)?)$/;
}
}
module.exports = Stylus;

17
node_modules/laravel-mix/src/components/Then.js generated vendored Executable file
View File

@@ -0,0 +1,17 @@
const { Component } = require('./Component');
module.exports = class Then extends Component {
/**
* The API name for the component.
*/
name() {
return ['then', 'after'];
}
/**
* @param {() => void | Promise<void>} callback
*/
register(callback) {
this.context.listen('build', callback);
}
};

67
node_modules/laravel-mix/src/components/TypeScript.js generated vendored Executable file
View File

@@ -0,0 +1,67 @@
const JavaScript = require('./JavaScript');
class TypeScript extends JavaScript {
/** @type {Record<string, any>} */
options = {};
/**
* The API name for the component.
*/
name() {
return ['typeScript', 'ts'];
}
/**
* Register the component.
*
* @param {any} entry
* @param {string} output
* @param {Record<string, any>} options
*/
register(entry, output, options = {}) {
super.register(entry, output);
this.options = options;
}
/**
* Required dependencies for the component.
*/
dependencies() {
return ['ts-loader', 'typescript'].concat();
}
/**
* webpack rules to be appended to the master config.
*/
webpackRules() {
return [
...super.webpackRules(),
{
test: /\.tsx?$/,
loader: this.context.resolve('ts-loader'),
exclude: /node_modules/,
options: Object.assign(
{},
// TODO: Maybe move to Vue plugin?
{ appendTsSuffixTo: [/\.vue$/] },
this.options
)
}
];
}
/**
* Override the generated webpack configuration.
*
* @param {import('webpack').Configuration} config
*/
webpackConfig(config) {
config.resolve = config.resolve || {};
config.resolve.extensions = config.resolve.extensions || [];
config.resolve.extensions.push('.ts', '.tsx');
return config;
}
}
module.exports = TypeScript;

14
node_modules/laravel-mix/src/components/Version.js generated vendored Executable file
View File

@@ -0,0 +1,14 @@
const { concat } = require('lodash');
const VersionFilesTask = require('../tasks/VersionFilesTask');
const { Component } = require('./Component');
module.exports = class Version extends Component {
/**
* Register the component.
*
* @param {string|string[]} paths
*/
register(paths = []) {
this.context.addTask(new VersionFilesTask({ files: concat([], paths) }));
}
};

250
node_modules/laravel-mix/src/components/Vue.js generated vendored Executable file
View File

@@ -0,0 +1,250 @@
const { Component } = require('./Component');
const File = require('../File');
const VueVersion = require('../VueVersion');
const AppendVueStylesPlugin = require('../webpackPlugins/Css/AppendVueStylesPlugin');
module.exports = class Vue extends Component {
version = 2;
/**
* @type {import('laravel-mix').VueConfig} options
*/
options = {
version: undefined,
runtimeOnly: false,
options: null,
globalStyles: null,
extractStyles: false,
useVueStyleLoader: false
};
/**
* Register the component.
*
* @param {import('laravel-mix').VueConfig} options
*/
register(options = {}) {
if (
arguments.length === 2 &&
typeof arguments[0] === 'string' &&
typeof arguments[1] === 'string'
) {
throw new Error(
'mix.vue() is a feature flag. Use mix.js(source, destination).vue() instead'
);
}
Object.assign(this.options, options);
this.version = new VueVersion(this.context).detect(this.options.version);
if (this.options.globalStyles !== undefined) {
this.context.globalStyles = this.options.globalStyles;
}
if (this.options.extractStyles !== undefined) {
this.context.extractingStyles =
this.context.extractingStyles || !!this.options.extractStyles;
}
this.addDefines();
this.context.api.alias({
vue$: {
raw: this.aliasPath()
}
});
}
/**
* Required dependencies for the component.
*/
dependencies() {
this.requiresReload = true;
let dependencies = [
this.version === 2 ? 'vue-template-compiler' : '@vue/compiler-sfc',
this.version === 2 ? 'vue-loader@^15.9.8' : 'vue-loader@^16.2.0'
];
if (this.options.extractStyles && this.options.globalStyles) {
dependencies.push('sass-resources-loader');
}
return dependencies;
}
/**
* Override the generated webpack configuration.
*
* @param {import('webpack').Configuration} config
*/
webpackConfig(config) {
config.module = config.module || {};
config.module.rules = config.module.rules || [];
config.resolve = config.resolve || {};
config.resolve.extensions = config.resolve.extensions || [];
// push -> unshift to combat vue loader webpack 5 bug
config.module.rules.unshift({
test: /\.vue$/,
use: [
{
loader: this.context.resolve('vue-loader'),
options: this.options.options || this.context.config.vue || {}
}
]
});
// Alias Vue to its ESM build if the user has not already given an alias
config.resolve.extensions.push('.vue');
// Disable es modules for file-loader on Vue 2
if (this.version === 2) {
for (const rule of config.module.rules || []) {
if (typeof rule !== 'object') {
continue;
}
let loaders = rule.use || [];
if (!Array.isArray(loaders)) {
continue;
}
for (const loader of loaders) {
if (typeof loader !== 'object') {
continue;
}
// TODO: This isn't the best check
// We should check that the loader itself is correct
// Not that file-loader is anywhere in it's absolute path
// As this can produce false positives
if (
loader.loader &&
loader.loader.includes('file-loader') &&
loader.options
) {
// @ts-ignore
loader.options.esModule = false;
}
}
}
}
this.updateChunks();
return config;
}
aliasPath() {
if (this.version === 2) {
return this.options.runtimeOnly
? 'vue/dist/vue.runtime.esm.js'
: 'vue/dist/vue.esm.js';
}
return this.options.runtimeOnly
? 'vue/dist/vue.runtime.esm-bundler.js'
: 'vue/dist/vue.esm-bundler.js';
}
/**
* webpack plugins to be appended to the master config.
*/
webpackPlugins() {
let { VueLoaderPlugin } = require(this.context.resolve('vue-loader'));
return [new VueLoaderPlugin(), new AppendVueStylesPlugin()];
}
/**
* Update CSS chunks to extract vue styles
*/
updateChunks() {
if (this.options.extractStyles === false) {
return;
}
this.context.chunks.add(
'styles-vue',
this.styleChunkName(),
[/.vue$/, module => module.type === 'css/mini-extract'],
{
chunks: 'all',
enforce: true,
type: 'css/mini-extract'
}
);
this.context.chunks.add(
'styles-jsx',
this.styleChunkName(),
[/.jsx$/, module => module.type === 'css/mini-extract'],
{
chunks: 'all',
enforce: true,
type: 'css/mini-extract'
}
);
}
/**
* Get the name of the style chunk.
*
* @returns {string}
*/
styleChunkName() {
// If the user set extractStyles: true, we'll try
// to append the Vue styles to an existing CSS chunk.
if (this.options.extractStyles === true) {
let chunk = this.context.chunks.find((chunk, id) => id.startsWith('styles-'));
if (chunk) {
return chunk.name;
}
}
return this.extractFile().relativePathWithoutExtension();
}
/**
* Get a new File instance for the extracted file.
*
* @returns {File}
*/
extractFile() {
return new File(this.extractFileName());
}
/**
* Determine the extract file name.
*
* @return {string}
*/
extractFileName() {
let fileName =
typeof this.options.extractStyles === 'string'
? this.options.extractStyles
: '/css/vue-styles.css';
return fileName.replace(this.context.config.publicPath, '').replace(/^\//, '');
}
/**
* Determine the extract file name.
*
* @internal
*/
addDefines() {
if (this.version === 2) {
return;
}
this.context.api.define({
__VUE_OPTIONS_API__: 'true',
__VUE_PROD_DEVTOOLS__: 'false'
});
}
};

22
node_modules/laravel-mix/src/components/WebpackConfig.js generated vendored Executable file
View File

@@ -0,0 +1,22 @@
const { Component } = require('./Component');
/** @typedef {import('webpack').Configuration} Configuration */
/** @typedef {import('webpack')} webpack */
module.exports = class WebpackConfig extends Component {
/**
*
* @param {((webpack: webpack, config: Configuration) => Configuration) | Configuration} config
*/
register(config) {
const merge = require('../builder/MergeWebpackConfig');
const webpack = require('webpack');
this.context.api.override(webpackConfig => {
config =
typeof config === 'function' ? config(webpack, webpackConfig) : config;
Object.assign(webpackConfig, merge(webpackConfig, config));
});
}
};

14
node_modules/laravel-mix/src/components/When.js generated vendored Executable file
View File

@@ -0,0 +1,14 @@
const { Component } = require('./Component');
module.exports = class When extends Component {
/**
*
* @param {boolean} condition
* @param {(api: import("laravel-mix").Api) => void} callback
*/
register(condition, callback) {
if (condition) {
callback(this.context.api);
}
}
};

268
node_modules/laravel-mix/src/config.js generated vendored Executable file
View File

@@ -0,0 +1,268 @@
// @ts-check
const yargs = require('yargs/yargs');
/** @typedef {import("@babel/core").TransformOptions} BabelConfig */
/**
*
* @param {import("./Mix")} mix
*/
module.exports = function (mix) {
// TODO: Remove in Mix 7 -- Here for backwards compat if a plugin requires this file
mix = mix || global.Mix;
const argv = yargs(process.argv.slice(2))
.options({
https: { type: 'boolean', default: false },
hmrPort: { type: 'string', default: '8080' },
p: { type: 'boolean', default: false },
hot: { type: 'boolean', default: false }
})
.parseSync();
return {
/**
* Determine if webpack should be triggered in a production environment.
*
* @type {Boolean}
*/
production: process.env.NODE_ENV === 'production' || argv.p,
/**
* Determine if we should enable hot reloading.
*
* @type {Boolean}
*/
hmr: argv.hot,
/**
* Hostname and port used for the hot reload module
*/
hmrOptions: {
https: argv.https,
host: 'localhost',
port: argv.hmrPort
},
/**
* PostCSS plugins to be applied to compiled CSS.
*
* See: https://github.com/postcss/postcss/blob/master/docs/plugins.md
*
* @type {import('postcss').AcceptedPlugin[]}
*/
postCss: [],
/**
* Determine if we should enable autoprefixer by default.
* May be set to false to disable it.
*
* @type {false|import('autoprefixer').Options}
*/
autoprefixer: {},
/**
* The public path for the build.
*
* @type {String}
*/
publicPath: '',
/**
* The path for the runtime chunk (`manifest.js`).
*
* Defaults to being placed next to compiled JS files.
*
* @type {String|null}
*/
runtimeChunkPath: null,
/**
* Determine if error notifications should be displayed for each build.
*
* @type {false | {onSuccess: boolean, onFailure: boolean}}
*/
notifications: {
onSuccess: true,
onFailure: true
},
/**
* Determine if sourcemaps should be created for the build.
*
* @type {false | string}
*/
sourcemaps: false,
/**
* The resource root for the build.
*
* @type {String}
*/
resourceRoot: '/',
/**
* Image Loader defaults.
* See: https://github.com/thetalecrafter/img-loader#options
*
* @type {Object}
*/
imgLoaderOptions: {
enabled: true,
gifsicle: {},
mozjpeg: {},
optipng: {},
svgo: {}
},
/**
* File Loader directory defaults.
*
* @deprecated Use `assetModules: true` and `assetDirs` instead
* @type {{images: string, fonts: string}}
*/
fileLoaderDirs: {
images: 'images',
fonts: 'fonts'
},
/**
* Use Webpack asset modules instead of File Loader.
*
* @type {Boolean}
*/
assetModules: false,
/**
* Asset directory defaults.
*
* @type {{images: string, fonts: string}}
*/
assetDirs: {
images: 'images',
fonts: 'fonts'
},
/**
* The Babel configuration to use when compiling
*/
babel: function () {
const BabelConfig = require('./BabelConfig');
return new BabelConfig(mix).generate();
},
/**
* Determine if CSS relative url()s should be resolved by webpack.
* Disabling this can improve performance greatly.
*
* @type {Boolean}
*/
processCssUrls: true,
/**
* Terser-specific settings for Webpack.
*
* See: https://github.com/webpack-contrib/terser-webpack-plugin#options
*
* @type {import('../types/terser').TerserPluginOptions}
*/
terser: {
parallel: true,
terserOptions: {
compress: true,
output: {
comments: false
}
}
},
/**
* cssnano-specific settings for Webpack.
* Disabled if set to false.
*
* See: https://cssnano.co/docs/optimisations
*
* @type {false|Object}
*/
cssNano: {},
/**
* CleanCss-specific settings for Webpack.
*
* See: https://github.com/clean-css/clean-css#constructor-options
*
* @type {Object}
*/
cleanCss: {},
/**
* Custom Webpack-specific configuration to merge/override Mix's.
*
* @type {Object}
*/
webpackConfig: {},
/**
* Custom Babel configuration to be merged with Mix's defaults.
*
* @type {BabelConfig}
*/
babelConfig: {},
/**
* Determine if Mix should ask the friendly errors plugin to
* clear the console before outputting the results or not.
*
* https://github.com/geowarin/friendly-errors-webpack-plugin#options
*
* @type {Boolean}
*/
clearConsole: true,
/**
* Enable legacy node -> browser polyfills for things like `process` and `Buffer`.
*
* @type {Boolean}
*/
legacyNodePolyfills: true,
/**
* Options to pass to vue-loader
*
* @deprecated Use `.vue({options: {…}})` instead
*
* @type {any}
*/
vue: {},
/**
* The name / path to the mix manifest.
* The path is relative to the public path.
*
* Set to `false` to disable manifest generation.
*
* @type {string | false}
*/
manifest: `mix-manifest.json`,
/**
* Sets the css module identifier pattern
*
* For more information see https://github.com/webpack-contrib/css-loader/tree/v5.2.7#localidentname
*/
cssModuleIdentifier: '[hash:base64]',
/**
* Merge the given options with the current defaults.
*
* @param {Record<string, any>} options
*/
merge(options) {
Object.keys(options).forEach(key => {
this[key] = options[key];
});
}
};
};

74
node_modules/laravel-mix/src/helpers.js generated vendored Executable file
View File

@@ -0,0 +1,74 @@
/**
* Generic tap function.
* @deprecated
**/
Object.defineProperty(global, 'tap', {
/**
* @template T
* @param {T} val
* @param {(val: T) => void} callback
* @returns {T}
*/
value(val, callback) {
callback(val);
return val;
}
});
/**
* Add tap to arrays.
* @deprecated
**/
if (!Object.prototype.hasOwnProperty.call(Array, 'tap')) {
Object.defineProperty(Array.prototype, 'tap', {
/**
* @param {(arr: self) => void} callback
* @returns {self}
*/
value(callback) {
if (this.length) {
callback(this);
}
return this;
}
});
}
/**
* Add wrap to arrays.
* @deprecated
**/
if (!Object.prototype.hasOwnProperty.call(Array, 'wrap')) {
Object.defineProperty(Array, 'wrap', {
/**
* @template T
* @param {T|T[]} value
* @returns {T[]}
*/
value(value) {
if (Array.isArray(value)) {
return value;
}
return [value];
}
});
}
/**
* Flatten an array.
* @deprecated
**/
Object.defineProperty(global, 'flatten', {
/**
* @template T
* @param {T[]} arr
* @returns {T[]}
*/
value(arr) {
// @ts-ignore
return [].concat.apply([], Object.values(arr));
}
});

20
node_modules/laravel-mix/src/index.js generated vendored Executable file
View File

@@ -0,0 +1,20 @@
const Mix = require('./Mix');
require('./helpers');
/*
|--------------------------------------------------------------------------
| Welcome to Laravel Mix!
|--------------------------------------------------------------------------
|
| Laravel Mix provides a clean, fluent API for defining basic webpack
| build steps for your Laravel application. Mix supports a variety
| of common CSS and JavaScript pre-processors out of the box.
|
*/
let mix = Mix.primary;
mix.boot();
module.exports = mix.api;

41
node_modules/laravel-mix/src/tasks/ConcatenateFilesTask.js generated vendored Executable file
View File

@@ -0,0 +1,41 @@
let Task = require('./Task');
let FileCollection = require('../FileCollection');
const { FileGlob } = require('./FileGlob');
/** @typedef {import('../File')} File */
/**
* @extends {Task<{ src: string|string[], output: File, babel: boolean, ignore?: string[] }>}
*/
class ConcatenateFilesTask extends Task {
/**
* Run the task.
*/
run() {
return this.merge();
}
/**
* Merge the files into one.
*/
async merge() {
const files = await FileGlob.expand(this.data.src, {
ignore: this.data.ignore || []
});
this.files = new FileCollection(files);
return this.files
.merge(this.data.output, this.data.babel)
.then(this.assets.push.bind(this.assets));
}
/**
* Handle when a relevant source file is changed.
*/
onChange() {
return this.merge();
}
}
module.exports = ConcatenateFilesTask;

46
node_modules/laravel-mix/src/tasks/CopyFilesTask.js generated vendored Executable file
View File

@@ -0,0 +1,46 @@
let Task = require('./Task');
let FileCollection = require('../FileCollection');
let Log = require('../Log');
const path = require('path');
const File = require('../File');
/**
* @extends {Task<{ from: string|string[], to: File }>}
*/
class CopyFilesTask extends Task {
/**
* Run the task.
*/
async run() {
let copy = this.data;
this.files = new FileCollection(copy.from);
await this.files.copyTo(copy.to);
this.assets = this.files.assets;
}
/**
* Handle when a relevant source file is changed.
*
* @param {string} updatedFile
*/
async onChange(updatedFile) {
let destination = this.data.to;
// If we're copying a src directory recursively, we have to calculate
// the correct destination path, based on the src directory tree.
if (!Array.isArray(this.data.from) && new File(this.data.from).isDirectory()) {
destination = destination.append(
path.normalize(updatedFile).replace(path.normalize(this.data.from), '')
);
}
Log.feedback(`Copying ${updatedFile} to ${destination.path()}`);
await this.files.copyTo(destination, new File(updatedFile));
}
}
module.exports = CopyFilesTask;

56
node_modules/laravel-mix/src/tasks/FileGlob.js generated vendored Executable file
View File

@@ -0,0 +1,56 @@
let path = require('path');
let glob = require('glob');
let File = require('../File');
let { promisify } = require('util');
let { concat } = require('lodash');
let globAsync = promisify(glob);
/** @internal */
module.exports.FileGlob = class FileGlob {
/**
* Find all relevant files matching the given source path.
*
* @param {string|string[]} src
* @param {{ ignore?: string[] }} options
* @returns {Promise<string[]>}
*/
static async expand(src, { ignore = [] } = {}) {
const paths = concat([], src);
const results = await Promise.all(
paths.map(async srcPath => {
const result = await this.find(srcPath);
if (!result.isDir && result.matches.length === 0) {
return [srcPath];
}
return result.matches;
})
);
const filepaths = results.flatMap(files => files);
return filepaths.filter(filepath => {
return !ignore.includes(filepath);
});
}
/**
*
* @internal
* @param {string} src
* @returns {Promise<{isDir: boolean, matches: string[]}>}
*/
static async find(src) {
const isDir = File.find(src).isDirectory();
const pattern = isDir ? path.join(src, '**/*') : src;
const matches = await globAsync(pattern, { nodir: true });
return {
isDir,
matches
};
}
};

71
node_modules/laravel-mix/src/tasks/Task.js generated vendored Executable file
View File

@@ -0,0 +1,71 @@
let chokidar = require('chokidar');
let FileCollection = require('../FileCollection');
/** @typedef {import('../File')} File */
/**
* @template {object} TData
*/
class Task {
/**
* Create a new task instance.
*
* @param {TData} data
*/
constructor(data) {
/** @type {TData} */
this.data = data;
/** @type {File[]} */
this.assets = [];
/** @type {FileCollection} */
this.files = new FileCollection();
this.isBeingWatched = false;
}
/**
* Watch all relevant files for changes.
*
* @param {boolean} usePolling
*/
watch(usePolling = false) {
if (this.isBeingWatched) return;
let files = this.files.get();
let watcher = chokidar
.watch(files, { usePolling, persistent: true })
.on('change', this.onChange.bind(this));
// Workaround for issue with atomic writes.
// See https://github.com/paulmillr/chokidar/issues/591
if (!usePolling) {
watcher.on('raw', event => {
if (event === 'rename') {
watcher.unwatch(files);
watcher.add(files);
}
});
}
this.isBeingWatched = true;
}
/**
*/
run() {
throw new Error('Task.run is an abstract method. Please override it.');
}
/**
*
* @abstract
* @param {string} filepath
*/
onChange(filepath) {
throw new Error('Task.onChange is an abstract method. Please override it.');
}
}
module.exports = Task;

48
node_modules/laravel-mix/src/tasks/VersionFilesTask.js generated vendored Executable file
View File

@@ -0,0 +1,48 @@
let Task = require('./Task');
let File = require('../File');
let FileCollection = require('../FileCollection');
const { FileGlob } = require('./FileGlob');
/**
* @extends {Task<{ files: string[] }>}
*/
class VersionFilesTask extends Task {
/**
* Run the task.
*/
async run() {
const fileGroups = await Promise.all(
this.data.files.map(async filepath => {
const relativePath = new File(filepath).forceFromPublic().relativePath();
return FileGlob.expand(relativePath);
})
);
const files = fileGroups.flat();
this.files = new FileCollection(files);
this.assets = files.map(filepath => {
const file = new File(filepath);
this.mix.manifest.hash(file.pathFromPublic());
return file;
});
}
/**
* Handle when a relevant source file is changed.
*
* @param {string} updatedFile
*/
onChange(updatedFile) {
this.mix.manifest.hash(new File(updatedFile).pathFromPublic()).refresh();
}
get mix() {
return global.Mix;
}
}
module.exports = VersionFilesTask;

View File

@@ -0,0 +1,23 @@
class BuildCallbackPlugin {
/**
* Create a new plugin instance.
*
* @param {(stats: import("webpack").Stats) => any|Promise<any>} callback
*/
constructor(callback) {
this.callback = callback;
}
/**
* Apply the plugin.
*
* @param {import("webpack").Compiler} compiler
*/
apply(compiler) {
compiler.hooks.done.tapPromise('BuildCallbackPlugin', async stats => {
return await this.callback(stats);
});
}
}
module.exports = BuildCallbackPlugin;

View File

@@ -0,0 +1,236 @@
const _ = require('lodash');
const chalk = require('chalk');
const Table = require('cli-table3');
const readline = require('readline');
const stripAnsi = require('strip-ansi');
const { formatSize } = require('webpack/lib/SizeFormatHelpers');
const { version } = require('../../package.json');
/**
* @typedef {object} BuildOutputOptions
* @property {boolean} clearConsole
* @property {boolean} showRelated
**/
/**
* @typedef {object} StatsAsset
* @property {string} name
* @property {number} size
* @property {StatsAsset[]|{}} related
**/
/**
* @typedef {object} StatsData
* @property {StatsAsset[]} assets
**/
class BuildOutputPlugin {
/**
*
* @param {BuildOutputOptions} options
*/
constructor(options) {
this.options = options;
this.patched = false;
}
/**
* Apply the plugin.
*
* @param {import("webpack").Compiler} compiler
*/
apply(compiler) {
// TODO: Refactor setup to allow removing this check
if (process.env.NODE_ENV === 'test') {
return;
}
compiler.hooks.done.tap('BuildOutputPlugin', stats => {
if (stats.hasErrors()) {
return false;
}
if (this.options.clearConsole) {
this.clearConsole();
}
let data = stats.toJson({
assets: true,
builtAt: true,
hash: true,
performance: true,
relatedAssets: this.options.showRelated
});
this.heading(`Laravel Mix v${version}`);
console.log(chalk.green.bold(`✔ Compiled Successfully in ${data.time}ms`));
if (data.assets.length) {
console.log(this.statsTable(data));
}
});
}
/**
* Print a block section heading.
*
* @param {string} text
*/
heading(text) {
console.log();
console.log(chalk.bgBlue.white.bold(this.section(text)));
console.log();
}
/**
* Create a block section.
*
* @param {string} text
*/
section(text) {
const padLength = 3;
const padding = ' '.repeat(padLength);
text = `${padding}${text}${padding}`;
const line = ' '.repeat(text.length);
return `${line}\n${text}\n${line}`;
}
/**
* Generate the stats table.
*
* @param {StatsData} data
* @returns {string}
*/
statsTable(data) {
const assets = this.sortAssets(data);
const table = new Table({
head: [chalk.bold('File'), chalk.bold('Size')],
colWidths: [35],
colAligns: ['right'],
style: {
head: [],
compact: true
}
});
for (const asset of assets) {
table.push([chalk.green(asset.name), formatSize(asset.size)]);
}
this.extendTableWidth(table);
this.monkeyPatchTruncate();
return table.toString();
}
/**
*
* @param {StatsData} data
*/
sortAssets(data) {
let assets = data.assets;
assets = _.flatMap(assets, asset => [
asset,
...(Array.isArray(asset.related) ? asset.related : [])
]);
assets = _.orderBy(assets, ['name', 'size'], ['asc', 'asc']);
return assets;
}
/**
* Clear the entire screen.
*/
clearConsole() {
const blank = '\n'.repeat(process.stdout.rows);
console.log(blank);
readline.cursorTo(process.stdout, 0, 0);
readline.clearScreenDown(process.stdout);
}
/**
* Extend the width of the table
*
* Currently only increases the file column size
*
* @param {import("cli-table3").Table} table
* @param {number|null} targetWidth
* @param {number} maxWidth
*/
extendTableWidth(table, targetWidth = null, maxWidth = Infinity) {
targetWidth = targetWidth === null ? process.stdout.columns : targetWidth;
if (!targetWidth) {
return;
}
const tableWidth = this.calculateTableWidth(table);
const fileColIncrease = Math.min(targetWidth - tableWidth, maxWidth - tableWidth);
if (fileColIncrease <= 0) {
return;
}
// @ts-ignore
table.options.colWidths[0] += fileColIncrease;
}
// Yeah, I know.
monkeyPatchTruncate() {
if (this.patched) {
return;
}
this.patched = true;
// @ts-ignore
const utils = require('cli-table3/src/utils');
const oldTruncate = utils.truncate;
// cli-table3 can only do truncation at the end
// We want the asset name to be truncated at the beginning if it's too long
// FIXME: We really should set truncation location via a paramter or something
// (or PR support for alignment-based truncation)
/**
*
* @param {string} str
* @param {number} desiredLength
* @param {string} truncateChar
*/
utils.truncate = (str, desiredLength, truncateChar) => {
if (stripAnsi(str).length > desiredLength) {
str = `${str.substr(-desiredLength + 2)}`;
}
return oldTruncate(str, desiredLength, truncateChar);
};
}
/**
* Calculate the width of the CLI Table
*
* `table.width` does not report the correct width
* because it includes ANSI control characters
*
* @internal
* @param {import("cli-table3").Table} table
*/
calculateTableWidth(table) {
const firstRow = table.toString().split('\n')[0];
return stripAnsi(firstRow).length;
}
}
module.exports = BuildOutputPlugin;

View File

@@ -0,0 +1,67 @@
// @ts-check
/**
* This plugin ensures that vue styles are always appended to the end of CSS files
*/
class AppendVueStylesPlugin {
/** @param {import("webpack").Compiler} compiler */
apply(compiler) {
const name = 'AppendVueStylesPlugin';
compiler.hooks.compilation.tap(name, compilation => {
compilation.hooks.optimizeChunks.tap(name, chunks => {
this.reorderModules(compilation.chunkGraph, chunks);
});
});
}
/**
*
* @param {import("webpack").ChunkGraph} graph
* @param {Iterable<import("webpack").Chunk>} chunks
*/
reorderModules(graph, chunks) {
const queue = this.collectCssChunks(graph, chunks);
// Find the last module in the bundle
let largestIndex = 0;
for (const { module, group } of queue) {
largestIndex = Math.max(largestIndex, group.getModulePostOrderIndex(module));
}
// Push all vue assets after it in their original order
for (const { module, group } of queue) {
if (module.identifier().includes('?vue')) {
group.setModulePostOrderIndex(
module,
largestIndex + group.getModulePostOrderIndex(module)
);
}
}
}
/**
* @param {import("webpack").ChunkGraph} graph
* @param {Iterable<import("webpack").Chunk>} chunks
*/
collectCssChunks(graph, chunks) {
const queue = [];
for (const chunk of chunks) {
for (const module of graph.getChunkModulesIterable(chunk)) {
if (module.type !== 'css/mini-extract') {
continue;
}
for (const group of chunk.groupsIterable) {
queue.push({ module, chunk, group });
}
}
}
return queue;
}
}
module.exports = AppendVueStylesPlugin;

View File

@@ -0,0 +1,115 @@
let Log = require('../Log');
let collect = require('collect.js');
class CustomTasksPlugin {
/**
*
* @param {import('../Mix')} mix
*/
constructor(mix) {
this.mix = mix || global.Mix;
}
/**
* Apply the plugin.
*
* @param {import("webpack").Compiler} compiler
*/
apply(compiler) {
compiler.hooks.done.tapPromise(this.constructor.name, async stats => {
await this.runTasks(stats);
if (this.mix.components.get('version') && !this.mix.isUsing('hmr')) {
this.applyVersioning();
}
if (this.mix.inProduction()) {
await this.minifyAssets();
}
if (this.mix.isWatching()) {
this.mix.tasks.forEach(task => task.watch(this.mix.isPolling()));
}
this.mix.manifest.refresh();
});
}
/**
* Add asset to the webpack stats.
*
* @param {import("../File")} asset
* @param {import("webpack").Stats} stats
*/
async addAsset(asset, stats) {
// Skip adding directories to the manifest
// TODO: We should probably add the directory but skip hashing
if (asset.isDirectory()) {
return;
}
const path = asset.pathFromPublic();
// Add the asset to the manifest
this.mix.manifest.add(path);
// Update the Webpack assets list for better terminal output.
stats.compilation.assets[path] = {
size: () => asset.size(),
emitted: true
};
}
/**
* Execute potentially asynchronous tasks sequentially.
*
* @param stats
*/
async runTasks(stats) {
let assets = []
for (const task of this.mix.tasks) {
await Promise.resolve(task.run());
assets.push(...task.assets)
}
await Promise.allSettled(assets.map(asset => this.addAsset(asset, stats)));
}
/**
* Minify the given asset file.
*/
async minifyAssets() {
const assets = collect(this.mix.tasks)
.where('constructor.name', '!==', 'VersionFilesTask')
.where('constructor.name', '!==', 'CopyFilesTask')
.flatMap(({ assets }) => assets);
const tasks = assets.map(async asset => {
try {
await asset.minify();
} catch (e) {
Log.error(
`Whoops! We had trouble minifying "${asset.relativePath()}". ` +
`Perhaps you need to use mix.babel() instead?`
);
throw e;
}
});
await Promise.allSettled(tasks);
}
/**
* Version all files that are present in the manifest.
*/
applyVersioning() {
for (const [key, value] of Object.entries(this.mix.manifest.get())) {
this.mix.manifest.hash(key)
}
}
}
module.exports = CustomTasksPlugin;

View File

@@ -0,0 +1,28 @@
class ManifestPlugin {
/**
*
* @param {import("../Mix")} mix
*/
constructor(mix) {
// TODO: Simplify in Mix 7 -- Here for backwards compat if a plugin creates this class directly
this.mix = mix || global.Mix;
}
/**
* Apply the plugin.
*
* @param {import("webpack").Compiler} compiler
*/
apply(compiler) {
compiler.hooks.emit.tapAsync('ManifestPlugin', (curCompiler, callback) => {
let stats = curCompiler.getStats().toJson();
// Handle the creation of the mix-manifest.json file.
this.mix.manifest.transform(stats).refresh();
callback();
});
}
}
module.exports = ManifestPlugin;

View File

@@ -0,0 +1,84 @@
let dotenv = require('dotenv');
let expand = require('dotenv-expand');
/** @internal */
class MixDefinitionsPlugin {
/**
*
* @param {string} envPath
* @param {Record<string, string>} [additionalEnv]
*/
constructor(envPath, additionalEnv = {}) {
this.envPath = envPath;
this.additionalEnv = additionalEnv;
}
/**
*
* @param {import('webpack').Compiler} compiler
*/
apply(compiler) {
this.plugin.apply(compiler);
}
/**
* Build all MIX_ definitions for Webpack's DefinePlugin.
*/
get env() {
// Load .env, if it exists, into process.env
expand(dotenv.config({ path: this.envPath }));
// Take everything from process.env that beings with MIX_
const regex = /^MIX_/i;
const existing = Object.fromEntries(
Object.entries(process.env).filter(([key]) => regex.test(key))
);
// Merge in env vaiues from:
// - process.env
// - the .env file
// - the additional env provided to the plugin
return {
...existing,
...this.additionalEnv
};
}
/**
* Build up the necessary definitions and add them to the DefinePlugin.
*/
get plugin() {
const { EnvironmentPlugin } = require('webpack');
return new EnvironmentPlugin(this.env);
}
/**
* Build all MIX_ definitions for Webpack's DefinePlugin.
* This is no longer used but here for backwards compat.
*
* @deprecated
* @param {Record<string, string>} additionalEnv
*/
getDefinitions(additionalEnv) {
return Object.fromEntries(
Object.entries({ ...this.env, ...additionalEnv }).map(([key, value]) => {
return [`process.env.${key}`, JSON.stringify(value)];
})
);
}
/**
* Build up the necessary definitions and add them to the DefinePlugin.
*
* Here for backwards compat only
* @deprecated
* @param {Record<string, string>} additionalEnv
*/
static build(additionalEnv) {
return new MixDefinitionsPlugin(global.Mix.paths.root('.env'), additionalEnv)
.plugin;
}
}
module.exports = MixDefinitionsPlugin;

View File

@@ -0,0 +1,41 @@
let File = require('../File');
let path = require('path');
class MockEntryPlugin {
/**
* @param {import('../Mix')} mix
*/
constructor(mix) {
// TODO: Remove in Mix 7 -- Here for backwards compat if a plugin requires this file
this.mix = mix || global.Mix;
}
/**
* Handle the deletion of the temporary mix.js
* output file that was generated by webpack.
*
* This file is created when the user hasn't
* requested any JavaScript compilation, but
* webpack still requires an entry.
*
* @param {import("webpack").Compiler} compiler
*/
apply(compiler) {
compiler.hooks.done.tap('MockEntryPlugin', stats => {
const assets = stats.toJson().assets || [];
const temporaryOutputFile = assets.find(asset => asset.name === 'mix.js');
if (!temporaryOutputFile) {
return;
}
delete stats.compilation.assets[temporaryOutputFile.name];
File.find(
path.resolve(this.mix.config.publicPath, temporaryOutputFile.name)
).delete();
});
}
}
module.exports = MockEntryPlugin;