UNPKG

5.47 kBJavaScriptView Raw
1"use strict";
2
3const NativeModule = require("module");
4const path = require("path");
5
6/** @typedef {import("webpack").Compilation} Compilation */
7/** @typedef {import("webpack").Module} Module */
8/** @typedef {import("webpack").LoaderContext<any>} LoaderContext */
9
10/**
11 * @returns {boolean}
12 */
13function trueFn() {
14 return true;
15}
16
17/**
18 * @param {Compilation} compilation
19 * @param {string | number} id
20 * @returns {null | Module}
21 */
22function findModuleById(compilation, id) {
23 const {
24 modules,
25 chunkGraph
26 } = compilation;
27 for (const module of modules) {
28 const moduleId = typeof chunkGraph !== "undefined" ? chunkGraph.getModuleId(module) : module.id;
29 if (moduleId === id) {
30 return module;
31 }
32 }
33 return null;
34}
35
36/**
37 * @param {LoaderContext} loaderContext
38 * @param {string | Buffer} code
39 * @param {string} filename
40 * @returns {object}
41 */
42function evalModuleCode(loaderContext, code, filename) {
43 // @ts-ignore
44 const module = new NativeModule(filename, loaderContext);
45
46 // @ts-ignore
47 module.paths = NativeModule._nodeModulePaths(loaderContext.context); // eslint-disable-line no-underscore-dangle
48 module.filename = filename;
49 // @ts-ignore
50 module._compile(code, filename); // eslint-disable-line no-underscore-dangle
51
52 return module.exports;
53}
54
55/**
56 * @param {string} a
57 * @param {string} b
58 * @returns {0 | 1 | -1}
59 */
60function compareIds(a, b) {
61 if (typeof a !== typeof b) {
62 return typeof a < typeof b ? -1 : 1;
63 }
64 if (a < b) {
65 return -1;
66 }
67 if (a > b) {
68 return 1;
69 }
70 return 0;
71}
72
73/**
74 * @param {Module} a
75 * @param {Module} b
76 * @returns {0 | 1 | -1}
77 */
78function compareModulesByIdentifier(a, b) {
79 return compareIds(a.identifier(), b.identifier());
80}
81const MODULE_TYPE = "css/mini-extract";
82const AUTO_PUBLIC_PATH = "__mini_css_extract_plugin_public_path_auto__";
83const ABSOLUTE_PUBLIC_PATH = "webpack:///mini-css-extract-plugin/";
84const BASE_URI = "webpack://";
85const SINGLE_DOT_PATH_SEGMENT = "__mini_css_extract_plugin_single_dot_path_segment__";
86
87/**
88 * @param {string} str
89 * @returns {boolean}
90 */
91function isAbsolutePath(str) {
92 return path.posix.isAbsolute(str) || path.win32.isAbsolute(str);
93}
94const RELATIVE_PATH_REGEXP = /^\.\.?[/\\]/;
95
96/**
97 * @param {string} str
98 * @returns {boolean}
99 */
100function isRelativePath(str) {
101 return RELATIVE_PATH_REGEXP.test(str);
102}
103
104// TODO simplify for the next major release
105/**
106 * @param {LoaderContext} loaderContext
107 * @param {string} request
108 * @returns {string}
109 */
110function stringifyRequest(loaderContext, request) {
111 if (typeof loaderContext.utils !== "undefined" && typeof loaderContext.utils.contextify === "function") {
112 return JSON.stringify(loaderContext.utils.contextify(loaderContext.context || loaderContext.rootContext, request));
113 }
114 const splitted = request.split("!");
115 const {
116 context
117 } = loaderContext;
118 return JSON.stringify(splitted.map(part => {
119 // First, separate singlePath from query, because the query might contain paths again
120 const splittedPart = part.match(/^(.*?)(\?.*)/);
121 const query = splittedPart ? splittedPart[2] : "";
122 let singlePath = splittedPart ? splittedPart[1] : part;
123 if (isAbsolutePath(singlePath) && context) {
124 singlePath = path.relative(context, singlePath);
125 if (isAbsolutePath(singlePath)) {
126 // If singlePath still matches an absolute path, singlePath was on a different drive than context.
127 // In this case, we leave the path platform-specific without replacing any separators.
128 // @see https://github.com/webpack/loader-utils/pull/14
129 return singlePath + query;
130 }
131 if (isRelativePath(singlePath) === false) {
132 // Ensure that the relative path starts at least with ./ otherwise it would be a request into the modules directory (like node_modules).
133 singlePath = `./${singlePath}`;
134 }
135 }
136 return singlePath.replace(/\\/g, "/") + query;
137 }).join("!"));
138}
139
140/**
141 * @param {string} filename
142 * @param {string} outputPath
143 * @param {boolean} enforceRelative
144 * @returns {string}
145 */
146function getUndoPath(filename, outputPath, enforceRelative) {
147 let depth = -1;
148 let append = "";
149
150 // eslint-disable-next-line no-param-reassign
151 outputPath = outputPath.replace(/[\\/]$/, "");
152 for (const part of filename.split(/[/\\]+/)) {
153 if (part === "..") {
154 if (depth > -1) {
155 // eslint-disable-next-line no-plusplus
156 depth--;
157 } else {
158 const i = outputPath.lastIndexOf("/");
159 const j = outputPath.lastIndexOf("\\");
160 const pos = i < 0 ? j : j < 0 ? i : Math.max(i, j);
161 if (pos < 0) {
162 return `${outputPath}/`;
163 }
164 append = `${outputPath.slice(pos + 1)}/${append}`;
165
166 // eslint-disable-next-line no-param-reassign
167 outputPath = outputPath.slice(0, pos);
168 }
169 } else if (part !== ".") {
170 // eslint-disable-next-line no-plusplus
171 depth++;
172 }
173 }
174 return depth > 0 ? `${"../".repeat(depth)}${append}` : enforceRelative ? `./${append}` : append;
175}
176
177/**
178 *
179 * @param {string | function} value
180 * @returns {string}
181 */
182function stringifyLocal(value) {
183 return typeof value === "function" ? value.toString() : JSON.stringify(value);
184}
185module.exports = {
186 trueFn,
187 findModuleById,
188 evalModuleCode,
189 compareModulesByIdentifier,
190 MODULE_TYPE,
191 AUTO_PUBLIC_PATH,
192 ABSOLUTE_PUBLIC_PATH,
193 BASE_URI,
194 SINGLE_DOT_PATH_SEGMENT,
195 stringifyRequest,
196 stringifyLocal,
197 getUndoPath
198};
\No newline at end of file