description and source-codefunction resolveUrlLoader(content, sourceMap) {
// details of the file being processed
var loader = this,
filePath = path.dirname(loader.resourcePath);
// webpack 1: prefer loader query, else options object
// webpack 2; prefer loader options
var options = defaults(loaderUtils.getOptions(loader), loader.options[camelcase(PACKAGE_NAME)], {
absolute : false,
sourceMap: false,
fail : false,
silent : false,
keepQuery: false,
debug : false,
root : null
});
// validate root directory
var resolvedRoot = (typeof options.root === 'string') && path.resolve(options.root) || undefined,
isValidRoot = resolvedRoot && fs.existsSync(resolvedRoot);
if (options.root && !isValidRoot) {
return handleException('"root" option does not resolve to a valid path');
}
// loader result is cacheable
loader.cacheable();
// incoming source-map
var sourceMapConsumer, contentWithMap, sourceRoot;
if (sourceMap) {
// support non-standard string encoded source-map (per less-loader)
if (typeof sourceMap === 'string') {
try {
sourceMap = JSON.parse(sourceMap);
}
catch (exception) {
return handleException('source-map error', 'cannot parse source-map string (from less-loader?)');
}
}
// Note the current sourceRoot before it is removed
// later when we go back to relative paths, we need to add it again
sourceRoot = sourceMap.sourceRoot;
// leverage adjust-sourcemap-loader's codecs to avoid having to make any assumptions about the sourcemap
// historically this is a regular source of breakage
var absSourceMap;
try {
absSourceMap = adjustSourceMap(this, {format: 'absolute'}, sourceMap);
}
catch (exception) {
return handleException('source-map error', exception.message);
}
// prepare the adjusted sass source-map for later look-ups
sourceMapConsumer = new SourceMapConsumer(absSourceMap);
// embed source-map in css for rework-css to use
contentWithMap = content + convert.fromObject(absSourceMap).toComment({multiline: true});
}
// absent source map
else {
contentWithMap = content;
}
// process
// rework-css will throw on css syntax errors
var useMap = loader.sourceMap || options.sourceMap,
reworked;
try {
reworked = rework(contentWithMap, {source: loader.resourcePath})
.use(reworkPlugin)
.toString({
sourcemap : useMap,
sourcemapAsObject: useMap
});
}
// fail gracefully
catch (exception) {
return handleException('CSS error', exception);
}
// complete with source-map
if (useMap) {
// source-map sources seem to be relative to the file being processed
absoluteToRelative(reworked.map.sources, path.resolve(filePath, sourceRoot || '.'));
// Set source root again
reworked.map.sourceRoot = sourceRoot;
// need to use callback when there are multiple arguments
loader.callback(null, reworked.code, reworked.map);
}
// complete without source-map
else {
return reworked;
}
/**
* Push an error for the given exception and return the original content.
* @param {string} label Summary of the error
* @param {string|Error} [exception] Optional extended error details
* @returns {string} The original CSS content
*/
function handleException(label, exception) {
var rest = (typeof exception === 'string') ? [exception] :
(exception instanceof Error) ? [exception.message, exception.stack.split('\n')[1].trim()] :
[];
var message = ' resolve-url-loader cannot operate: ' + [label].concat(rest).filter(Boolean).join('\n ');
if (options.fail) {
loader.emitError(message);
}
else if (!options.silent) {
loader.emitWarning(message);
}
return content;
}
/**
* Plugin for css rework that follows SASS transpilation
* @param {object} stylesheet AST for the CSS output from SASS
*/
function reworkPlugin(stylesheet) {
var URL_ ...