You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
5.2 KiB
215 lines
5.2 KiB
"use strict"; |
|
|
|
const NativeModule = require("module"); |
|
|
|
const path = require("path"); |
|
/** @typedef {import("webpack").Compilation} Compilation */ |
|
|
|
/** @typedef {import("webpack").Module} Module */ |
|
|
|
/** @typedef {import("webpack").LoaderContext<any>} LoaderContext */ |
|
|
|
/** |
|
* @returns {boolean} |
|
*/ |
|
|
|
|
|
function trueFn() { |
|
return true; |
|
} |
|
/** |
|
* @param {Compilation} compilation |
|
* @param {string | number} id |
|
* @returns {null | Module} |
|
*/ |
|
|
|
|
|
function findModuleById(compilation, id) { |
|
const { |
|
modules, |
|
chunkGraph |
|
} = compilation; |
|
|
|
for (const module of modules) { |
|
const moduleId = typeof chunkGraph !== "undefined" ? chunkGraph.getModuleId(module) : module.id; |
|
|
|
if (moduleId === id) { |
|
return module; |
|
} |
|
} |
|
|
|
return null; |
|
} |
|
/** |
|
* @param {LoaderContext} loaderContext |
|
* @param {string | Buffer} code |
|
* @param {string} filename |
|
* @returns {object} |
|
*/ |
|
|
|
|
|
function evalModuleCode(loaderContext, code, filename) { |
|
// @ts-ignore |
|
const module = new NativeModule(filename, loaderContext); // @ts-ignore |
|
|
|
module.paths = NativeModule._nodeModulePaths(loaderContext.context); // eslint-disable-line no-underscore-dangle |
|
|
|
module.filename = filename; // @ts-ignore |
|
|
|
module._compile(code, filename); // eslint-disable-line no-underscore-dangle |
|
|
|
|
|
return module.exports; |
|
} |
|
/** |
|
* @param {string} a |
|
* @param {string} b |
|
* @returns {0 | 1 | -1} |
|
*/ |
|
|
|
|
|
function compareIds(a, b) { |
|
if (typeof a !== typeof b) { |
|
return typeof a < typeof b ? -1 : 1; |
|
} |
|
|
|
if (a < b) { |
|
return -1; |
|
} |
|
|
|
if (a > b) { |
|
return 1; |
|
} |
|
|
|
return 0; |
|
} |
|
/** |
|
* @param {Module} a |
|
* @param {Module} b |
|
* @returns {0 | 1 | -1} |
|
*/ |
|
|
|
|
|
function compareModulesByIdentifier(a, b) { |
|
return compareIds(a.identifier(), b.identifier()); |
|
} |
|
|
|
const MODULE_TYPE = "css/mini-extract"; |
|
const AUTO_PUBLIC_PATH = "__mini_css_extract_plugin_public_path_auto__"; |
|
const ABSOLUTE_PUBLIC_PATH = "webpack:///mini-css-extract-plugin/"; |
|
const BASE_URI = "webpack://"; |
|
const SINGLE_DOT_PATH_SEGMENT = "__mini_css_extract_plugin_single_dot_path_segment__"; |
|
/** |
|
* @param {string} str |
|
* @returns {boolean} |
|
*/ |
|
|
|
function isAbsolutePath(str) { |
|
return path.posix.isAbsolute(str) || path.win32.isAbsolute(str); |
|
} |
|
|
|
const RELATIVE_PATH_REGEXP = /^\.\.?[/\\]/; |
|
/** |
|
* @param {string} str |
|
* @returns {boolean} |
|
*/ |
|
|
|
function isRelativePath(str) { |
|
return RELATIVE_PATH_REGEXP.test(str); |
|
} // TODO simplify for the next major release |
|
|
|
/** |
|
* @param {LoaderContext} loaderContext |
|
* @param {string} request |
|
* @returns {string} |
|
*/ |
|
|
|
|
|
function stringifyRequest(loaderContext, request) { |
|
if (typeof loaderContext.utils !== "undefined" && typeof loaderContext.utils.contextify === "function") { |
|
return JSON.stringify(loaderContext.utils.contextify(loaderContext.context || loaderContext.rootContext, request)); |
|
} |
|
|
|
const splitted = request.split("!"); |
|
const { |
|
context |
|
} = loaderContext; |
|
return JSON.stringify(splitted.map(part => { |
|
// First, separate singlePath from query, because the query might contain paths again |
|
const splittedPart = part.match(/^(.*?)(\?.*)/); |
|
const query = splittedPart ? splittedPart[2] : ""; |
|
let singlePath = splittedPart ? splittedPart[1] : part; |
|
|
|
if (isAbsolutePath(singlePath) && context) { |
|
singlePath = path.relative(context, singlePath); |
|
|
|
if (isAbsolutePath(singlePath)) { |
|
// If singlePath still matches an absolute path, singlePath was on a different drive than context. |
|
// In this case, we leave the path platform-specific without replacing any separators. |
|
// @see https://github.com/webpack/loader-utils/pull/14 |
|
return singlePath + query; |
|
} |
|
|
|
if (isRelativePath(singlePath) === false) { |
|
// Ensure that the relative path starts at least with ./ otherwise it would be a request into the modules directory (like node_modules). |
|
singlePath = `./${singlePath}`; |
|
} |
|
} |
|
|
|
return singlePath.replace(/\\/g, "/") + query; |
|
}).join("!")); |
|
} |
|
/** |
|
* @param {string} filename |
|
* @param {string} outputPath |
|
* @param {boolean} enforceRelative |
|
* @returns {string} |
|
*/ |
|
|
|
|
|
function getUndoPath(filename, outputPath, enforceRelative) { |
|
let depth = -1; |
|
let append = ""; // eslint-disable-next-line no-param-reassign |
|
|
|
outputPath = outputPath.replace(/[\\/]$/, ""); |
|
|
|
for (const part of filename.split(/[/\\]+/)) { |
|
if (part === "..") { |
|
if (depth > -1) { |
|
// eslint-disable-next-line no-plusplus |
|
depth--; |
|
} else { |
|
const i = outputPath.lastIndexOf("/"); |
|
const j = outputPath.lastIndexOf("\\"); |
|
const pos = i < 0 ? j : j < 0 ? i : Math.max(i, j); |
|
|
|
if (pos < 0) { |
|
return `${outputPath}/`; |
|
} |
|
|
|
append = `${outputPath.slice(pos + 1)}/${append}`; // eslint-disable-next-line no-param-reassign |
|
|
|
outputPath = outputPath.slice(0, pos); |
|
} |
|
} else if (part !== ".") { |
|
// eslint-disable-next-line no-plusplus |
|
depth++; |
|
} |
|
} |
|
|
|
return depth > 0 ? `${"../".repeat(depth)}${append}` : enforceRelative ? `./${append}` : append; |
|
} |
|
|
|
module.exports = { |
|
trueFn, |
|
findModuleById, |
|
evalModuleCode, |
|
compareModulesByIdentifier, |
|
MODULE_TYPE, |
|
AUTO_PUBLIC_PATH, |
|
ABSOLUTE_PUBLIC_PATH, |
|
BASE_URI, |
|
SINGLE_DOT_PATH_SEGMENT, |
|
stringifyRequest, |
|
getUndoPath |
|
}; |