Index: frontend/node_modules/loader-runner/LICENSE
===================================================================
--- frontend/node_modules/loader-runner/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/loader-runner/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) Tobias Koppers @sokra
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: frontend/node_modules/loader-runner/README.md
===================================================================
--- frontend/node_modules/loader-runner/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/loader-runner/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,52 @@
+# loader-runner
+
+```js
+import { runLoaders } from "loader-runner";
+
+runLoaders(
+	{
+		resource: "/abs/path/to/file.txt?query",
+		// String: Absolute path to the resource (optionally including query string)
+
+		loaders: ["/abs/path/to/loader.js?query"],
+		// String[]: Absolute paths to the loaders (optionally including query string)
+		// {loader, options}[]: Absolute paths to the loaders with options object
+
+		context: { minimize: true },
+		// Additional loader context which is used as base context
+
+		processResource: (loaderContext, resourcePath, callback) => {
+			// ...
+		},
+		// Optional: A function to process the resource
+		// Must have signature function(context, path, function(err, buffer))
+		// By default readResource is used and the resource is added a fileDependency
+
+		readResource: fs.readFile.bind(fs),
+		// Optional: A function to read the resource
+		// Only used when 'processResource' is not provided
+		// Must have signature function(path, function(err, buffer))
+		// By default fs.readFile is used
+	},
+	(err, result) => {
+		// err: Error?
+		// result.result: [Buffer | String, SourceMap?, Meta?]
+		// The result as an array matching the arguments passed by the final normal loader
+		// (typically [content, sourceMap, meta])
+		// only available when no error occurred
+		// result.resourceBuffer: Buffer
+		// The raw resource as Buffer (useful for SourceMaps)
+		// only available when no error occurred
+		// result.cacheable: Bool
+		// Is the result cacheable or do it require reexecution?
+		// result.fileDependencies: String[]
+		// An array of paths (existing files) on which the result depends on
+		// result.missingDependencies: String[]
+		// An array of paths (not existing files) on which the result depends on
+		// result.contextDependencies: String[]
+		// An array of paths (directories) on which the result depends on
+	}
+);
+```
+
+More documentation following...
Index: frontend/node_modules/loader-runner/lib/LoaderLoadingError.js
===================================================================
--- frontend/node_modules/loader-runner/lib/LoaderLoadingError.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/loader-runner/lib/LoaderLoadingError.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,15 @@
+"use strict";
+
+class LoadingLoaderError extends Error {
+	constructor(message) {
+		super(message);
+		this.name = "LoaderRunnerError";
+
+		if (Error.captureStackTrace) {
+			// eslint-disable-next-line unicorn/no-useless-error-capture-stack-trace
+			Error.captureStackTrace(this, this.constructor);
+		}
+	}
+}
+
+module.exports = LoadingLoaderError;
Index: frontend/node_modules/loader-runner/lib/LoaderRunner.js
===================================================================
--- frontend/node_modules/loader-runner/lib/LoaderRunner.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/loader-runner/lib/LoaderRunner.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,543 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const { readFile } = require("fs");
+
+const loadLoader = require("./loadLoader");
+
+const HASH_ESCAPE_REGEXP = /#/g;
+
+// UTF-8 encoding of the BOM: EF BB BF
+const UTF8_BOM_0 = 0xef;
+const UTF8_BOM_1 = 0xbb;
+const UTF8_BOM_2 = 0xbf;
+
+function utf8BufferToString(buf) {
+	// Detect and skip the BOM at the buffer level to avoid materializing the
+	// prefix as JS string and then re-slicing it.
+	if (
+		buf.length >= 3 &&
+		buf[0] === UTF8_BOM_0 &&
+		buf[1] === UTF8_BOM_1 &&
+		buf[2] === UTF8_BOM_2
+	) {
+		return buf.toString("utf8", 3);
+	}
+	return buf.toString("utf8");
+}
+
+/**
+ * Escape `#` characters with a preceding `\0` byte. Short-circuits when the input contains no `#`, avoiding the regex scan for the common case.
+ * @param {string} str input string
+ * @returns {string} escaped string
+ */
+function escapeHash(str) {
+	return str.includes("#") ? str.replace(HASH_ESCAPE_REGEXP, "\0#") : str;
+}
+
+const PATH_QUERY_FRAGMENT_REGEXP =
+	/^((?:\0.|[^?#\0])*)(\?(?:\0.|[^#\0])*)?(#.*)?$/;
+const ZERO_ESCAPE_REGEXP = /\0(.)/g;
+
+/**
+ * @param {string} identifier identifier
+ * @returns {[string, string, string]} parsed identifier
+ */
+function parseIdentifier(identifier) {
+	// Fast path for inputs that don't use \0 escaping.
+	const firstEscape = identifier.indexOf("\0");
+
+	if (firstEscape < 0) {
+		const queryStart = identifier.indexOf("?");
+		const fragmentStart = identifier.indexOf("#");
+
+		if (fragmentStart < 0) {
+			if (queryStart < 0) {
+				// No fragment, no query
+				return [identifier, "", ""];
+			}
+
+			// Query, no fragment
+			return [
+				identifier.slice(0, queryStart),
+				identifier.slice(queryStart),
+				"",
+			];
+		}
+
+		if (queryStart < 0 || fragmentStart < queryStart) {
+			// Fragment, no query
+			return [
+				identifier.slice(0, fragmentStart),
+				"",
+				identifier.slice(fragmentStart),
+			];
+		}
+
+		// Query and fragment
+		return [
+			identifier.slice(0, queryStart),
+			identifier.slice(queryStart, fragmentStart),
+			identifier.slice(fragmentStart),
+		];
+	}
+
+	const match = PATH_QUERY_FRAGMENT_REGEXP.exec(identifier);
+
+	return [
+		match[1].replace(ZERO_ESCAPE_REGEXP, "$1"),
+		match[2] ? match[2].replace(ZERO_ESCAPE_REGEXP, "$1") : "",
+		match[3] || "",
+	];
+}
+
+function dirname(path) {
+	if (path === "/") return "/";
+	const i = path.lastIndexOf("/");
+	const j = path.lastIndexOf("\\");
+	const i2 = path.indexOf("/");
+	const j2 = path.indexOf("\\");
+	const idx = i > j ? i : j;
+	const idx2 = i > j ? i2 : j2;
+	if (idx < 0) return path;
+	if (idx === idx2) return path.slice(0, idx + 1);
+	return path.slice(0, idx);
+}
+
+function createLoaderObject(loader) {
+	const obj = {
+		path: null,
+		query: null,
+		fragment: null,
+		options: null,
+		ident: null,
+		normal: null,
+		pitch: null,
+		raw: null,
+		data: null,
+		pitchExecuted: false,
+		normalExecuted: false,
+	};
+	Object.defineProperty(obj, "request", {
+		enumerable: true,
+		get() {
+			return escapeHash(obj.path) + escapeHash(obj.query) + obj.fragment;
+		},
+		set(value) {
+			if (typeof value === "string") {
+				const [path, query, fragment] = parseIdentifier(value);
+				obj.path = path;
+				obj.query = query;
+				obj.fragment = fragment;
+				obj.options = undefined;
+				obj.ident = undefined;
+				return;
+			}
+
+			if (!value.loader) {
+				throw new Error(
+					`request should be a string or object with loader and options (${JSON.stringify(
+						value
+					)})`
+				);
+			}
+
+			const { loader: path, fragment, type, options, ident } = value;
+			obj.path = path;
+			obj.fragment = fragment || "";
+			obj.type = type;
+			obj.options = options;
+			obj.ident = ident;
+
+			if (options === null || options === undefined) {
+				obj.query = "";
+			} else if (typeof options === "string") {
+				obj.query = `?${options}`;
+			} else if (ident) {
+				obj.query = `??${ident}`;
+			} else if (typeof options === "object" && options.ident) {
+				obj.query = `??${options.ident}`;
+			} else {
+				obj.query = `?${JSON.stringify(options)}`;
+			}
+		},
+	});
+	obj.request = loader;
+	if (Object.preventExtensions) {
+		Object.preventExtensions(obj);
+	}
+	return obj;
+}
+
+function runSyncOrAsync(fn, context, args, callback) {
+	let isSync = true;
+	let isDone = false;
+	let isError = false; // internal error
+	let reportedError = false;
+
+	// eslint-disable-next-line func-name-matching
+	const innerCallback = (context.callback = function innerCallback(
+		...callbackArgs
+	) {
+		if (isDone) {
+			if (reportedError) return; // ignore
+			throw new Error("callback(): The callback was already called.");
+		}
+
+		isDone = true;
+		isSync = false;
+
+		try {
+			callback(...callbackArgs);
+		} catch (err) {
+			isError = true;
+			throw err;
+		}
+	});
+
+	context.async = function async() {
+		if (isDone) {
+			if (reportedError) return; // ignore
+			throw new Error("async(): The callback was already called.");
+		}
+
+		isSync = false;
+
+		return innerCallback;
+	};
+
+	try {
+		const result = (function LOADER_EXECUTION() {
+			return fn.apply(context, args);
+		})();
+		if (isSync) {
+			isDone = true;
+			if (result === undefined) return callback();
+			if (
+				result &&
+				typeof result === "object" &&
+				typeof result.then === "function"
+			) {
+				return result.then((r) => {
+					callback(null, r);
+				}, callback);
+			}
+			return callback(null, result);
+		}
+	} catch (err) {
+		if (isError) throw err;
+		if (isDone) {
+			// loader is already "done", so we cannot use the callback function
+			// for better debugging we print the error on the console
+			if (typeof err === "object" && err.stack) {
+				// eslint-disable-next-line no-console
+				console.error(err.stack);
+			} else {
+				// eslint-disable-next-line no-console
+				console.error(err);
+			}
+			return;
+		}
+		isDone = true;
+		reportedError = true;
+		callback(err);
+	}
+}
+
+function convertArgs(args, raw) {
+	if (!raw && Buffer.isBuffer(args[0])) {
+		args[0] = utf8BufferToString(args[0]);
+	} else if (raw && typeof args[0] === "string") {
+		args[0] = Buffer.from(args[0], "utf8");
+	}
+}
+
+function iterateNormalLoaders(options, loaderContext, args, callback) {
+	while (loaderContext.loaderIndex >= 0) {
+		const currentLoaderObject =
+			loaderContext.loaders[loaderContext.loaderIndex];
+
+		if (currentLoaderObject.normalExecuted) {
+			loaderContext.loaderIndex--;
+			continue;
+		}
+
+		const fn = currentLoaderObject.normal;
+		currentLoaderObject.normalExecuted = true;
+
+		if (!fn) continue;
+
+		convertArgs(args, currentLoaderObject.raw);
+
+		return runSyncOrAsync(fn, loaderContext, args, (err, ...nextArgs) => {
+			if (err) return callback(err);
+			iterateNormalLoaders(options, loaderContext, nextArgs, callback);
+		});
+	}
+
+	return callback(null, args);
+}
+
+function processResource(options, loaderContext, callback) {
+	// set loader index to last loader
+	loaderContext.loaderIndex = loaderContext.loaders.length - 1;
+
+	const { resourcePath } = loaderContext;
+
+	if (!resourcePath) {
+		return iterateNormalLoaders(options, loaderContext, [null], callback);
+	}
+
+	options.processResource(loaderContext, resourcePath, (err, ...args) => {
+		if (err) return callback(err);
+
+		// eslint-disable-next-line prefer-destructuring
+		options.resourceBuffer = args[0];
+
+		iterateNormalLoaders(options, loaderContext, args, callback);
+	});
+}
+
+function iteratePitchingLoaders(options, loaderContext, callback) {
+	// Iterative walk over already-pitched loaders without recursion.
+	while (loaderContext.loaderIndex < loaderContext.loaders.length) {
+		const currentLoaderObject =
+			loaderContext.loaders[loaderContext.loaderIndex];
+
+		if (currentLoaderObject.pitchExecuted) {
+			loaderContext.loaderIndex++;
+			continue;
+		}
+
+		return loadLoader(currentLoaderObject, (err) => {
+			if (err) {
+				loaderContext.cacheable(false);
+				return callback(err);
+			}
+			const fn = currentLoaderObject.pitch;
+			currentLoaderObject.pitchExecuted = true;
+			if (!fn) return iteratePitchingLoaders(options, loaderContext, callback);
+
+			runSyncOrAsync(
+				fn,
+				loaderContext,
+				[
+					loaderContext.remainingRequest,
+					loaderContext.previousRequest,
+					(currentLoaderObject.data = {}),
+				],
+				(pitchErr, ...args) => {
+					if (pitchErr) return callback(pitchErr);
+					// Determine whether to continue the pitching process based on
+					// argument values (as opposed to argument presence) in order
+					// to support synchronous and asynchronous usages. Inline loop
+					// avoids allocating a predicate closure per pitched loader.
+					let hasArg = false;
+					for (let i = 0; i < args.length; i++) {
+						if (args[i] !== undefined) {
+							hasArg = true;
+							break;
+						}
+					}
+					if (hasArg) {
+						loaderContext.loaderIndex--;
+						iterateNormalLoaders(options, loaderContext, args, callback);
+					} else {
+						iteratePitchingLoaders(options, loaderContext, callback);
+					}
+				}
+			);
+		});
+	}
+
+	// Reached the end: move on to processing the resource itself.
+	return processResource(options, loaderContext, callback);
+}
+
+/**
+ * Join loader requests into a single `!`-separated string for a range of loader indices.
+ * @param {object[]} loaders loader objects
+ * @param {number} start inclusive start index
+ * @param {number} end exclusive end index
+ * @param {string} resource resource string
+ * @returns {string} joined request
+ */
+function joinRequests(loaders, start, end, resource) {
+	let result = "";
+	for (let i = start; i < end; i++) {
+		result += `${loaders[i].request}!`;
+	}
+	return result + resource;
+}
+
+module.exports.getContext = function getContext(resource) {
+	const [path] = parseIdentifier(resource);
+	return dirname(path);
+};
+
+module.exports.runLoaders = function runLoaders(options, callback) {
+	// read options
+	const resource = options.resource || "";
+	const loaderContext = options.context || {};
+	const processResourceFn =
+		options.processResource ||
+		((readResource, context, res, cb) => {
+			context.addDependency(res);
+			readResource(res, cb);
+		}).bind(null, options.readResource || readFile);
+
+	const splittedResource = resource && parseIdentifier(resource);
+	const resourcePath = splittedResource ? splittedResource[0] : "";
+	const resourceQuery = splittedResource ? splittedResource[1] : "";
+	const resourceFragment = splittedResource ? splittedResource[2] : "";
+	const contextDirectory = resourcePath ? dirname(resourcePath) : null;
+
+	// execution state
+	let requestCacheable = true;
+	const fileDependencies = [];
+	const contextDependencies = [];
+	const missingDependencies = [];
+
+	// prepare loader objects
+	const loaders = (options.loaders || []).map(createLoaderObject);
+
+	loaderContext.context = contextDirectory;
+	loaderContext.loaderIndex = 0;
+	loaderContext.loaders = loaders;
+	loaderContext.resourcePath = resourcePath;
+	loaderContext.resourceQuery = resourceQuery;
+	loaderContext.resourceFragment = resourceFragment;
+	loaderContext.async = null;
+	loaderContext.callback = null;
+	loaderContext.cacheable = (flag) => {
+		if (flag === false) {
+			requestCacheable = false;
+		}
+	};
+	loaderContext.dependency = loaderContext.addDependency = (file) => {
+		fileDependencies.push(file);
+	};
+	loaderContext.addContextDependency = (context) => {
+		contextDependencies.push(context);
+	};
+	loaderContext.addMissingDependency = (context) => {
+		missingDependencies.push(context);
+	};
+	loaderContext.getDependencies = () => fileDependencies.slice();
+	loaderContext.getContextDependencies = () => contextDependencies.slice();
+	loaderContext.getMissingDependencies = () => missingDependencies.slice();
+	loaderContext.clearDependencies = () => {
+		fileDependencies.length = 0;
+		contextDependencies.length = 0;
+		missingDependencies.length = 0;
+		requestCacheable = true;
+	};
+	Object.defineProperty(loaderContext, "resource", {
+		enumerable: true,
+		get() {
+			return (
+				escapeHash(loaderContext.resourcePath) +
+				escapeHash(loaderContext.resourceQuery) +
+				loaderContext.resourceFragment
+			);
+		},
+		set(value) {
+			const splitted = value && parseIdentifier(value);
+			loaderContext.resourcePath = splitted ? splitted[0] : "";
+			loaderContext.resourceQuery = splitted ? splitted[1] : "";
+			loaderContext.resourceFragment = splitted ? splitted[2] : "";
+		},
+	});
+	Object.defineProperty(loaderContext, "request", {
+		enumerable: true,
+		get() {
+			return joinRequests(
+				loaders,
+				0,
+				loaders.length,
+				loaderContext.resource || ""
+			);
+		},
+	});
+	Object.defineProperty(loaderContext, "remainingRequest", {
+		enumerable: true,
+		get() {
+			return joinRequests(
+				loaders,
+				loaderContext.loaderIndex + 1,
+				loaders.length,
+				loaderContext.resource
+			);
+		},
+	});
+	Object.defineProperty(loaderContext, "currentRequest", {
+		enumerable: true,
+		get() {
+			return joinRequests(
+				loaders,
+				loaderContext.loaderIndex,
+				loaders.length,
+				loaderContext.resource
+			);
+		},
+	});
+	Object.defineProperty(loaderContext, "previousRequest", {
+		enumerable: true,
+		get() {
+			const end = loaderContext.loaderIndex;
+			if (end === 0) return "";
+			let result = loaders[0].request;
+			for (let i = 1; i < end; i++) {
+				result += `!${loaders[i].request}`;
+			}
+			return result;
+		},
+	});
+	Object.defineProperty(loaderContext, "query", {
+		enumerable: true,
+		get() {
+			const entry = loaders[loaderContext.loaderIndex];
+			return entry.options && typeof entry.options === "object"
+				? entry.options
+				: entry.query;
+		},
+	});
+	Object.defineProperty(loaderContext, "data", {
+		enumerable: true,
+		get() {
+			return loaders[loaderContext.loaderIndex].data;
+		},
+	});
+
+	// finish loader context
+	if (Object.preventExtensions) {
+		Object.preventExtensions(loaderContext);
+	}
+
+	const processOptions = {
+		resourceBuffer: null,
+		processResource: processResourceFn,
+	};
+	iteratePitchingLoaders(processOptions, loaderContext, (err, result) => {
+		if (err) {
+			return callback(err, {
+				cacheable: requestCacheable,
+				fileDependencies,
+				contextDependencies,
+				missingDependencies,
+			});
+		}
+		callback(null, {
+			result,
+			resourceBuffer: processOptions.resourceBuffer,
+			cacheable: requestCacheable,
+			fileDependencies,
+			contextDependencies,
+			missingDependencies,
+		});
+	});
+};
Index: frontend/node_modules/loader-runner/lib/loadLoader.js
===================================================================
--- frontend/node_modules/loader-runner/lib/loadLoader.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/loader-runner/lib/loadLoader.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,71 @@
+"use strict";
+
+const LoaderLoadingError = require("./LoaderLoadingError");
+
+let url;
+
+function handleResult(loader, module, callback) {
+	if (typeof module !== "function" && typeof module !== "object") {
+		return callback(
+			new LoaderLoadingError(
+				`Module '${loader.path}' is not a loader (export function or es6 module)`
+			)
+		);
+	}
+
+	loader.normal = typeof module === "function" ? module : module.default;
+	loader.pitch = module.pitch;
+	loader.raw = module.raw;
+
+	if (
+		typeof loader.normal !== "function" &&
+		typeof loader.pitch !== "function"
+	) {
+		return callback(
+			new LoaderLoadingError(
+				`Module '${loader.path}' is not a loader (must have normal or pitch function)`
+			)
+		);
+	}
+	callback();
+}
+
+function loadLoader(loader, callback) {
+	if (loader.type === "module") {
+		try {
+			if (url === undefined) url = require("url");
+
+			// eslint-disable-next-line n/no-unsupported-features/node-builtins
+			const loaderUrl = url.pathToFileURL(loader.path);
+			// Use `eval` so older parsers (and the main module resolver) don't
+			// need to recognize the dynamic `import()` syntax at load time.
+			// eslint-disable-next-line no-eval
+			const modulePromise = eval(
+				`import(${JSON.stringify(loaderUrl.toString())})`
+			);
+
+			modulePromise.then((module) => {
+				handleResult(loader, module, callback);
+			}, callback);
+		} catch (err) {
+			callback(err);
+		}
+		return;
+	}
+
+	let loadedModule;
+	try {
+		loadedModule = require(loader.path);
+	} catch (err) {
+		// It is possible for node to choke on a require if the FD descriptor
+		// limit has been reached. Give it a chance to recover by deferring.
+		if (err instanceof Error && err.code === "EMFILE") {
+			return setImmediate(loadLoader, loader, callback);
+		}
+		return callback(err);
+	}
+
+	return handleResult(loader, loadedModule, callback);
+}
+
+module.exports = loadLoader;
Index: frontend/node_modules/loader-runner/package.json
===================================================================
--- frontend/node_modules/loader-runner/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/loader-runner/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,57 @@
+{
+  "name": "loader-runner",
+  "version": "4.3.2",
+  "description": "Runs (webpack) loaders",
+  "keywords": ["webpack", "loader"],
+  "homepage": "https://github.com/webpack/loader-runner#readme",
+  "bugs": {
+    "url": "https://github.com/webpack/loader-runner/issues"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/webpack/loader-runner.git"
+  },
+  "funding": {
+    "type": "opencollective",
+    "url": "https://opencollective.com/webpack"
+  },
+  "license": "MIT",
+  "author": "Tobias Koppers @sokra",
+  "main": "lib/LoaderRunner.js",
+  "files": ["lib/", "bin/", "hot/", "web_modules/", "schemas/"],
+  "scripts": {
+    "lint": "npm run lint:code && npm run fmt:check",
+    "lint:code": "eslint --cache .",
+    "fmt": "npm run fmt:base -- --log-level warn --write",
+    "fmt:check": "npm run fmt:base -- --check",
+    "fmt:base": "prettier --cache --ignore-unknown .",
+    "fix": "npm run fix:code && npm run fmt",
+    "fix:code": "npm run lint:code -- --fix",
+    "pretest": "npm run lint",
+    "test": "npm run test:basic",
+    "test:basic": "mocha --reporter spec",
+    "test:cover": "nyc --reporter=lcov npm run test:basic"
+  },
+  "devDependencies": {
+    "@eslint/js": "^9.28.0",
+    "@eslint/markdown": "^8.0.1",
+    "@stylistic/eslint-plugin": "^5.2.3",
+    "globals": "^17.0.0",
+    "eslint": "^9.28.0",
+    "eslint-config-webpack": "^4.6.1",
+    "eslint-config-prettier": "^10.1.5",
+    "eslint-plugin-import": "^2.31.0",
+    "eslint-plugin-jest": "^29.15.2",
+    "eslint-plugin-jsdoc": "^62.9.0",
+    "eslint-plugin-n": "^17.19.0",
+    "eslint-plugin-prettier": "^5.4.1",
+    "eslint-plugin-unicorn": "^64.0.0",
+    "prettier": "^3.5.3",
+    "nyc": "^14.1.1",
+    "mocha": "^3.2.0",
+    "should": "^8.0.2"
+  },
+  "engines": {
+    "node": ">=6.11.5"
+  }
+}
