source: trip-planner-front/node_modules/resolve-url-loader/index.js@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 * MIT License http://opensource.org/licenses/MIT
3 * Author: Ben Holloway @bholloway
4 */
5'use strict';
6
7var os = require('os'),
8 path = require('path'),
9 fs = require('fs'),
10 util = require('util'),
11 loaderUtils = require('loader-utils'),
12 SourceMapConsumer = require('source-map').SourceMapConsumer;
13
14var adjustSourceMap = require('adjust-sourcemap-loader/lib/process');
15
16var valueProcessor = require('./lib/value-processor'),
17 joinFn = require('./lib/join-function'),
18 logToTestHarness = require('./lib/log-to-test-harness');
19
20const DEPRECATED_OPTIONS = {
21 engine: [
22 'DEP_RESOLVE_URL_LOADER_OPTION_ENGINE',
23 'the "engine" option is deprecated, "postcss" engine is the default, using "rework" engine is not advised'
24 ],
25 keepQuery: [
26 'DEP_RESOLVE_URL_LOADER_OPTION_KEEP_QUERY',
27 '"keepQuery" option has been removed, the query and/or hash are now always retained'
28 ],
29 absolute: [
30 'DEP_RESOLVE_URL_LOADER_OPTION_ABSOLUTE',
31 '"absolute" option has been removed, consider the "join" option if absolute paths must be processed'
32 ],
33 attempts: [
34 'DEP_RESOLVE_URL_LOADER_OPTION_ATTEMPTS',
35 '"attempts" option has been removed, consider the "join" option if search is needed'
36 ],
37 includeRoot: [
38 'DEP_RESOLVE_URL_LOADER_OPTION_INCLUDE_ROOT',
39 '"includeRoot" option has been removed, consider the "join" option if search is needed'
40 ],
41 fail: [
42 'DEP_RESOLVE_URL_LOADER_OPTION_FAIL',
43 '"fail" option has been removed'
44 ]
45};
46
47/**
48 * A webpack loader that resolves absolute url() paths relative to their original source file.
49 * Requires source-maps to do any meaningful work.
50 * @param {string} content Css content
51 * @param {object} sourceMap The source-map
52 * @returns {string|String}
53 */
54function resolveUrlLoader(content, sourceMap) {
55 /* jshint validthis:true */
56
57 // details of the file being processed
58 var loader = this;
59
60 // a relative loader.context is a problem
61 if (/^\./.test(loader.context)) {
62 return handleAsError(
63 'webpack misconfiguration',
64 'loader.context is relative, expected absolute'
65 );
66 }
67
68 // infer webpack version from new loader features
69 var isWebpackGte5 = 'getOptions' in loader && typeof loader.getOptions === 'function';
70
71 // webpack 1: prefer loader query, else options object
72 // webpack 2: prefer loader options
73 // webpack 3: deprecate loader.options object
74 // webpack 4: loader.options no longer defined
75 var rawOptions = loaderUtils.getOptions(loader),
76 options = Object.assign(
77 {
78 sourceMap: loader.sourceMap,
79 engine : 'postcss',
80 silent : false,
81 removeCR : os.EOL.includes('\r'),
82 root : false,
83 debug : false,
84 join : joinFn.defaultJoin
85 },
86 rawOptions
87 );
88
89 // maybe log options for the test harness
90 if (process.env.RESOLVE_URL_LOADER_TEST_HARNESS) {
91 logToTestHarness(
92 process[process.env.RESOLVE_URL_LOADER_TEST_HARNESS],
93 options
94 );
95 }
96
97 // deprecated options
98 var deprecatedItems = Object.entries(DEPRECATED_OPTIONS).filter(([key]) => key in rawOptions);
99 if (deprecatedItems.length) {
100 deprecatedItems.forEach(([, value]) => handleAsDeprecated(...value));
101 }
102
103 // validate join option
104 if (typeof options.join !== 'function') {
105 return handleAsError(
106 'loader misconfiguration',
107 '"join" option must be a Function'
108 );
109 } else if (options.join.length !== 2) {
110 return handleAsError(
111 'loader misconfiguration',
112 '"join" Function must take exactly 2 arguments (options, loader)'
113 );
114 }
115
116 // validate the result of calling the join option
117 var joinProper = options.join(options, loader);
118 if (typeof joinProper !== 'function') {
119 return handleAsError(
120 'loader misconfiguration',
121 '"join" option must itself return a Function when it is called'
122 );
123 } else if (joinProper.length !== 1) {
124 return handleAsError(
125 'loader misconfiguration',
126 '"join" Function must create a function that takes exactly 1 arguments (item)'
127 );
128 }
129
130 // validate root option
131 if (typeof options.root === 'string') {
132 var isValid = (options.root === '') ||
133 (path.isAbsolute(options.root) && fs.existsSync(options.root) && fs.statSync(options.root).isDirectory());
134
135 if (!isValid) {
136 return handleAsError(
137 'loader misconfiguration',
138 '"root" option must be an empty string or an absolute path to an existing directory'
139 );
140 }
141 } else if (options.root !== false) {
142 handleAsWarning(
143 'loader misconfiguration',
144 '"root" option must be string where used or false where unused'
145 );
146 }
147
148 // loader result is cacheable
149 loader.cacheable();
150
151 // incoming source-map
152 var sourceMapConsumer, absSourceMap;
153 if (sourceMap) {
154
155 // support non-standard string encoded source-map (per less-loader)
156 if (typeof sourceMap === 'string') {
157 try {
158 sourceMap = JSON.parse(sourceMap);
159 }
160 catch (exception) {
161 return handleAsError(
162 'source-map error',
163 'cannot parse source-map string (from less-loader?)'
164 );
165 }
166 }
167
168 // leverage adjust-sourcemap-loader's codecs to avoid having to make any assumptions about the sourcemap
169 // historically this is a regular source of breakage
170 try {
171 absSourceMap = adjustSourceMap(loader, {format: 'absolute'}, sourceMap);
172 }
173 catch (exception) {
174 return handleAsError(
175 'source-map error',
176 exception.message
177 );
178 }
179
180 // prepare the adjusted sass source-map for later look-ups
181 sourceMapConsumer = new SourceMapConsumer(absSourceMap);
182 } else {
183 handleAsWarning(
184 'webpack misconfiguration',
185 'webpack or the upstream loader did not supply a source-map'
186 );
187 }
188
189 // choose a CSS engine
190 var enginePath = /^[\w-]+$/.test(options.engine) && path.join(__dirname, 'lib', 'engine', options.engine + '.js');
191 var isValidEngine = fs.existsSync(enginePath);
192 if (!isValidEngine) {
193 return handleAsError(
194 'loader misconfiguration',
195 '"engine" option is not valid'
196 );
197 }
198
199 // allow engine to throw at initialisation
200 var engine;
201 try {
202 engine = require(enginePath);
203 } catch (error) {
204 return handleAsError(
205 'error initialising',
206 error
207 );
208 }
209
210 // process async
211 var callback = loader.async();
212 Promise
213 .resolve(engine(loader.resourcePath, content, {
214 outputSourceMap : !!options.sourceMap,
215 absSourceMap : absSourceMap,
216 sourceMapConsumer : sourceMapConsumer,
217 removeCR : options.removeCR,
218 transformDeclaration: valueProcessor({
219 join : joinProper,
220 root : options.root,
221 directory: path.dirname(loader.resourcePath)
222 })
223 }))
224 .catch(onFailure)
225 .then(onSuccess);
226
227 function onFailure(error) {
228 callback(encodeError('error processing CSS', error));
229 }
230
231 function onSuccess(result) {
232 if (result) {
233 // complete with source-map
234 // webpack4 and earlier: source-map sources are relative to the file being processed
235 // webpack5: source-map sources are relative to the project root but without a leading slash
236 if (options.sourceMap) {
237 var finalMap = adjustSourceMap(loader, {
238 format: isWebpackGte5 ? 'projectRelative' : 'sourceRelative'
239 }, result.map);
240 callback(null, result.content, finalMap);
241 }
242 // complete without source-map
243 else {
244 callback(null, result.content);
245 }
246 }
247 }
248
249 /**
250 * Trigger a node deprecation message for the given exception and return the original content.
251 * @param {string} code Deprecation code
252 * @param {string} message Deprecation message
253 * @returns {string} The original CSS content
254 */
255 function handleAsDeprecated(code, message) {
256 if (!options.silent) {
257 util.deprecate(() => undefined, message, code)();
258 }
259 return content;
260 }
261
262 /**
263 * Push a warning for the given exception and return the original content.
264 * @param {string} label Summary of the error
265 * @param {string|Error} [exception] Optional extended error details
266 * @returns {string} The original CSS content
267 */
268 function handleAsWarning(label, exception) {
269 if (!options.silent) {
270 loader.emitWarning(encodeError(label, exception));
271 }
272 return content;
273 }
274
275 /**
276 * Push a warning for the given exception and return the original content.
277 * @param {string} label Summary of the error
278 * @param {string|Error} [exception] Optional extended error details
279 * @returns {string} The original CSS content
280 */
281 function handleAsError(label, exception) {
282 loader.emitError(encodeError(label, exception));
283 return content;
284 }
285
286 function encodeError(label, exception) {
287 return new Error(
288 [
289 'resolve-url-loader',
290 ': ',
291 [label]
292 .concat(
293 (typeof exception === 'string') && exception ||
294 Array.isArray(exception) && exception ||
295 (exception instanceof Error) && [exception.message, exception.stack.split('\n')[1].trim()] ||
296 []
297 )
298 .filter(Boolean)
299 .join('\n ')
300 ].join('')
301 );
302 }
303}
304
305module.exports = Object.assign(resolveUrlLoader, joinFn);
Note: See TracBrowser for help on using the repository browser.