Skip to content

Commit

Permalink
added root option to explicitly limit file search, fix original impli…
Browse files Browse the repository at this point in the history
…ed directory limit, enforce source-maps, bump minor version
  • Loading branch information
benholloway committed Nov 4, 2015
1 parent 0b2a364 commit 1913c89
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 25 deletions.
20 changes: 8 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,14 @@ function resolveUrlLoader(content, sourceMap) {
sourceMap: false,
fail : false,
silent : false,
directory: null
root : null
});

// ensure directory is valid
if (options.directory) {
var resolvedDirectory = (typeof options.directory === 'string') && path.resolve(options.directory),
isValid = !!resolvedDirectory && fs.existsSync(resolvedDirectory);
if (isValid) {
options.directory = resolvedDirectory;
} else {
return handleException('"directory" option does not resolve to a valid path');
}
// validate root directory
var resolvedRoot = (typeof options.root === 'string') && path.resolve(options.root),
isValidRoot = !!resolvedRoot && fs.existsSync(resolvedRoot);
if (options.root && !isValidRoot) {
return handleException('"root" option does not resolve to a valid path');
}

// loader result is cacheable
Expand All @@ -62,7 +58,7 @@ function resolveUrlLoader(content, sourceMap) {

// sass-loader outputs source-map sources relative to output directory so start our search there
try {
relativeToAbsolute(sourceMap.sources, outputPath, options.directory);
relativeToAbsolute(sourceMap.sources, outputPath, resolvedRoot);
} catch (exception) {
return handleException('source-map error', exception.message);
}
Expand Down Expand Up @@ -188,7 +184,7 @@ function resolveUrlLoader(content, sourceMap) {

// remove query string or hash suffix
var uri = initialised.split(/[?#]/g).shift(),
absolute = uri && findFile.absolute(directory, uri, options.directory);
absolute = uri && findFile.absolute(directory, uri, resolvedRoot);

// use the absolute path (or default to initialised)
if (options.absolute) {
Expand Down
14 changes: 7 additions & 7 deletions lib/find-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ module.exports = {
* working directory, avoiding any other directories with a <code>package.json</code> or <code>bower.json</code>.
* @param {string} startPath The location of the uri declaration and the place to start the search from
* @param {string} uri The content of the url() statement, expected to be a relative file path
* @param {string} [directory] Optional directory to limit the search to
* @param {string} [limit] Optional directory to limit the search to
* @returns {string|null} <code>null</code> where not found else the absolute path to the file
*/
function absolute(startPath, uri, directory) {
var basePath = base(startPath, uri, directory);
function absolute(startPath, uri, limit) {
var basePath = base(startPath, uri, limit);
return !!basePath && path.resolve(basePath, uri);
}

Expand All @@ -26,13 +26,13 @@ function absolute(startPath, uri, directory) {
* working directory, avoiding any other directories with a <code>package.json</code> or <code>bower.json</code>.
* @param {string} startPath The location of the uri declaration and the place to start the search from
* @param {string} uri The content of the url() statement, expected to be a relative file path
* @param {string} [directory] Optional directory to limit the search to
* @param {string} [limit] Optional directory to limit the search to
* @returns {string|null} <code>null</code> where not found else the base path upon which the uri may be resolved
*/
function base(startPath, uri, directory) {
function base(startPath, uri, limit) {

// ensure we have some limit to the search
directory = directory && path.resolve(directory) || process.cwd();
limit = limit && path.resolve(limit) || process.cwd();

// ignore data uris and ensure we are at a valid start path
var absoluteStart = !(/^data\:/.test(uri)) && path.resolve(startPath);
Expand Down Expand Up @@ -103,7 +103,7 @@ function base(startPath, uri, directory) {
* @returns {boolean} True where a package.json or bower.json exists, else False
*/
function testWithinLimit(absolutePath) {
var relative = path.relative(directory, absolutePath);
var relative = path.relative(limit, absolutePath);
return !!relative && (relative.slice(0, 2) !== '..');
}
}
Expand Down
6 changes: 3 additions & 3 deletions lib/sources-relative-to-absolute.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ var findFile = require('./find-file');
* @throws {Error} On missing sources or inconsistent source base-path
* @param {Array} sources The source map sources array
* @param {string} defaultBasePath The base path to first try for relative URIs
* @param {string} [directory] Optional directory to limit the search to
* @param {string} [limit] Optional directory to limit the search to
* @returns {string} The base path common to all relative source URIs or the given path where all are absolute
*/
module.exports = function sourcesRelativeToAbsolute(sources, defaultBasePath, directory) {
module.exports = function sourcesRelativeToAbsolute(sources, defaultBasePath, limit) {
return sources
.map(sourceToAbsolute)
.filter(Boolean)
Expand All @@ -40,7 +40,7 @@ module.exports = function sourcesRelativeToAbsolute(sources, defaultBasePath, di
var location = value
.replace(/\b[\\\/]+\b/g, path.sep) // remove duplicate slashes (windows)
.replace(/^[\\\/]\./, '.'), // remove erroneous leading slash on relative paths
basePath = findFile.base(defaultBasePath, location, directory);
basePath = findFile.base(defaultBasePath, location, limit);

// file was found, now resolve the absolute path
if (basePath) {
Expand Down
6 changes: 3 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Where `...` is a hash of any of the following options.

* `fail` Syntax or source-map errors will result in an error.

* `directory` An optional directory which limits file search. Relative paths are permitted. Where omitted the `process.cwd()` is used and should be sufficient for most use cases.
* `root` An optional directory within which search may be performed. Relative paths are permitted. Where omitted `process.cwd()` is used and should be sufficient for most use cases.

Note that query parameters take precedence over programmatic parameters.

Expand All @@ -97,8 +97,8 @@ Each `url()` statement that implies an asset triggers a file search using node `

Usually the asset is found relative to the original source file. However in some cases there is no immediate match (*cough* bootstrap *cough*) and we so we start searching both deeper and shallower from the starting directory.

The search will always continue to full depth, however shallower paths must be limited to avoid the whole file system from being considered. Shallower paths will be considered while within the `directory` path until a `package.json` or `bower.json` file is encountered.
Shallower paths must be limited to avoid the whole file system from being considered. Progressively shallower paths within the `root` will be considered. Paths featuring a `package.json` or `bower.json` file will not be considered.

If the asset is not found then the `url()` statement will not be updated with a Webpack module-relative path. However if the `url()` statement has no source-map `source` information the loader will fail.

The loader will also fail when input source-map `sources` cannot all be resolved relative to some consistent path within `directory`.
The loader will also fail when input source-map `sources` cannot all be resolved relative to some consistent path within `root`.

0 comments on commit 1913c89

Please sign in to comment.