8889841cwebpack-protocol.js000066600000002343150513706730010372 0ustar00'use strict'; var projectRelative = require('./project-relative'); /** * Codec for relative paths with respect to the context directory, preceded by a webpack:// protocol. * @type {{name:string, decode: function, encode: function, root: function}} */ module.exports = { name : 'webpackProtocol', decode: decode, encode: encode, root : root }; /** * Decode the given uri. * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else the decoded path */ function decode(uri) { /* jshint validthis:true */ var analysis = /^webpack:\/{2}(.*)$/.exec(uri); return !!analysis && projectRelative.decode.call(this, analysis[1]); } /** * Encode the given file path. * @this {{options: object}} A loader or compilation * @param {string} absolute An absolute file path to encode * @returns {string} A uri */ function encode(absolute) { /* jshint validthis:true */ return 'webpack://' + projectRelative.encode.call(this, absolute); } /** * The source-map root where relevant. * @this {{options: object}} A loader or compilation * @returns {string|undefined} The source-map root applicable to any encoded uri */ function root() { } index.js000066600000000510150513706730006220 0ustar00module.exports = [ require('./webpack-protocol'), require('./webpack-bootstrap'), require('./bower-component'), require('./npm-module'), /* insert here any additional special character CODECs */ require('./output-relative'), require('./project-relative'), require('./source-relative'), require('./absolute') ];source-relative.js000066600000002700150513706730010225 0ustar00'use strict'; var path = require('path'), fs = require('fs'); /** * Codec for relative paths with respect to the context of the file being compiled. * @type {{name:string, decode: function, encode: function, root: function}} */ module.exports = { name : 'sourceRelative', decode: decode, encode: encode, root : root }; /** * Decode the given uri. * Any path with or without leading slash is tested against context directory. * Exclude module paths containing `~`. * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else the decoded path */ function decode(uri) { /* jshint validthis:true */ var base = this.context, absFile = !!base && path.normalize(path.join(base, uri)), isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile(); return isValid && absFile; } /** * Encode the given file path. * @this {{options: object}} A loader or compilation * @param {string} absolute An absolute file path to encode * @returns {string} A uri */ function encode(absolute) { /* jshint validthis:true */ return path.relative(this.context, absolute); } /** * The source-map root where relevant. * @this {{options: object}} A loader or compilation * @returns {string|undefined} The source-map root applicable to any encoded uri */ function root() { /* jshint validthis:true */ return this.context; } webpack-bootstrap.js000066600000000771150513706730010551 0ustar00'use strict'; /** * Codec for webpack generated bootstrap code. * @type {{name:string, decode:function, abstract:boolean}} */ module.exports = { name : 'webpackBootstrap', decode : decode, abstract: true }; /** * Validate the given uri (abstract). * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else True */ function decode(uri) { return /^webpack\/bootstrap\s+\w{20}$/.test(uri); } absolute.js000066600000002011150513706730006725 0ustar00'use strict'; var path = require('path'), fs = require('fs'); /** * Codec for absolute paths. * @type {{name:string, decode: function, encode: function, root: function}} */ module.exports = { name : 'absolute', decode: decode, encode: encode, root : root }; /** * Decode the given uri. * Any path with leading slash is tested in an absolute sense. * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else the decoded path */ function decode(uri) { return path.isAbsolute(uri) && fs.existsSync(uri) && fs.statSync(uri).isFile() && uri; } /** * Encode the given file path. * @this {{options: object}} A loader or compilation * @returns {string} A uri */ function encode(absolute) { return absolute; } /** * The source-map root where relevant. * @this {{options: object}} A loader or compilation * @returns {string|undefined} The source-map root applicable to any encoded uri */ function root() { } npm-module.js000066600000001745150513706730007201 0ustar00'use strict'; var path = require('path'), fs = require('fs'); var loaderUtils = require('loader-utils'); var getContextDirectory = require('./utility/get-context-directory'); /** * Codec for relative paths with respect to the context directory. * @type {{name:string, decode: function}} */ module.exports = { name : 'npmModule', decode: decode }; /** * Decode the given uri. * Include only module paths containing `~`. * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else the decoded path */ function decode(uri) { /* jshint validthis:true */ if (/~/.test(uri)) { var relative = loaderUtils.urlToRequest(uri), base = getContextDirectory.call(this), absFile = path.normalize(path.join(base, 'node_modules', relative)), isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile(); return isValid && absFile; } } utility/get-context-directory.js000066600000001013150513706730013056 0ustar00'use strict'; var path = require('path'); /** * Infer the compilation context directory from options. * Relative paths are resolved against process.cwd(). * @this {{options: object}} A loader or compilation * @returns {string} process.cwd() where not defined else the output path string */ function getContextDirectory() { /* jshint validthis:true */ var context = this.options ? this.options.context : null; return !!context && path.resolve(context) || process.cwd(); } module.exports = getContextDirectory; utility/get-output-directory.js000066600000001471150513706730012742 0ustar00'use strict'; var path = require('path'), fs = require('fs'); var getContextDirectory = require('./get-context-directory'); /** * Infer the compilation output directory from options. * Relative paths are resolved against the compilation context (or process.cwd() where not specified). * @this {{options: object}} A loader or compilation * @returns {undefined|string} The output path string, where defined */ function getOutputDirectory() { /* jshint validthis:true */ var base = this.options && this.options.output ? this.options.output.directory : null, absBase = !!base && path.resolve(getContextDirectory.call(this), base), isValid = !!absBase && fs.existsSync(absBase) && fs.statSync(absBase).isDirectory(); return isValid ? absBase : undefined; } module.exports = getOutputDirectory; utility/enhanced-relative.js000066600000010232150513706730012174 0ustar00'use strict'; var fs = require('fs'), path = require('path'); var cache; /** * Perform path.relative() but try to detect and correct sym-linked node modules. * @param {string} from The base path * @param {string} to The full path */ function enhancedRelative(from, to) { // relative path var relative = path.relative(from, to); // trailing is the relative path portion without any '../' var trailing = relative.replace(/^\.{2}[\\\/]/, ''), leading = to.replace(trailing, ''); // within project is what we want var isInProject = (relative === trailing); if (isInProject) { return relative; } // otherwise look at symbolic linked modules else { var splitTrailing = trailing.split(/[\\\/]/); // ensure failures can retry with fresh cache for (var i = cache ? 2 : 1, foundPath = false; (i > 0) && !foundPath; i--) { // ensure cache cache = cache || indexLinkedModules(from); // take elements from the trailing path and append them the the leading path in an attempt to find a package.json for (var j = 0; (j < splitTrailing.length) && !foundPath; j++) { // find the name of packages in the actual file location // start at the lowest concrete directory that appears in the relative path var packagePath = path.join.apply(path, [leading].concat(splitTrailing.slice(0, j + 1))), packageJsonPath = path.join(packagePath, 'package.json'), packageName = fs.existsSync(packageJsonPath) && require(packageJsonPath).name; // lookup any package name in the cache var linkedPackagePath = !!packageName && cache[packageName]; if (linkedPackagePath) { // the remaining portion of the trailing path, not including the package path var remainingPath = path.join.apply(path, splitTrailing.slice(j + 1)); // validate the remaining path in the linked location // failure implies we will keep trying nested sym-linked packages var linkedFilePath = path.join(linkedPackagePath, remainingPath), isValid = !!linkedFilePath && fs.existsSync(linkedFilePath) && fs.statSync(linkedFilePath).isFile(); // path is found where valid foundPath = isValid && linkedFilePath; } } // cache cannot be trusted if a file can't be found // set the cache to false to trigger its rebuild cache = !!foundPath && cache; } // the relative path should now be within the project return foundPath ? path.relative(from, foundPath) : relative; } } module.exports = enhancedRelative; /** * Make a hash of linked modules within the given directory by breadth-first search. * @param {string} directory A path to start searching * @returns {object} A collection of sym-linked paths within the project keyed by their package name */ function indexLinkedModules(directory) { var buffer = listSymLinkedModules(directory), hash = {}; // while there are items in the buffer while (buffer.length > 0) { var modulePath = buffer.shift(), packageJsonPath = path.join(modulePath, 'package.json'), packageName = fs.existsSync(packageJsonPath) && require(packageJsonPath).name; if (packageName) { // add this path keyed by package name, so long as it doesn't exist at a lower level hash[packageName] = hash[packageName] || modulePath; // detect nested module and push to the buffer (breadth-first) buffer.push.apply(buffer, listSymLinkedModules(modulePath)); } } return hash; function listSymLinkedModules(directory) { var modulesPath = path.join(directory, 'node_modules'), hasNodeModules = fs.existsSync(modulesPath) && fs.statSync(modulesPath).isDirectory(), subdirectories = !!hasNodeModules && fs.readdirSync(modulesPath) || []; return subdirectories .map(joinDirectory) .filter(testIsSymLink); function joinDirectory(subdirectory) { return path.join(modulesPath, subdirectory); } function testIsSymLink(directory) { return fs.lstatSync(directory).isSymbolicLink(); // must use lstatSync not statSync } } }bower-component.js000066600000000777150513706730010246 0ustar00'use strict'; /** * Codec for code generated by the Bower plugin. * @type {{name:string, decode:function, abstract:boolean}} */ module.exports = { name : 'bowerComponent', decode : decode, abstract: true }; /** * Validate the given uri (abstract). * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else True */ function decode(uri) { return /^\/?([\w-]+)\s+\(bower component\)$/.test(uri); } project-relative.js000066600000002675150513706730010406 0ustar00'use strict'; var path = require('path'), fs = require('fs'); var getContextDirectory = require('./utility/get-context-directory'), enhancedRelative = require('./utility/enhanced-relative'); /** * Codec for relative paths with respect to the context directory. * @type {{name:string, decode: function, encode: function, root: function}} */ module.exports = { name : 'projectRelative', decode: decode, encode: encode, root : getContextDirectory }; /** * Decode the given uri. * Any path with or without leading slash is tested against context directory. * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else the decoded path */ function decode(uri) { /* jshint validthis:true */ var base = getContextDirectory.call(this), absFile = path.normalize(path.join(base, uri)), isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile(); return isValid && absFile; } /** * Encode the given file path. * @this {{options: object}} A loader or compilation * @param {string} absolute An absolute file path to encode * @returns {string} A uri */ function encode(absolute) { /* jshint validthis:true */ var base = getContextDirectory.call(this); if (!base) { throw new Error('Cannot locate the Webpack project directory'); } else { return '/' + enhancedRelative(base, absolute); } } output-relative.js000066600000002564150513706730010275 0ustar00'use strict'; var path = require('path'), fs = require('fs'); var getOutputDirectory = require('./utility/get-output-directory'); /** * Codec for relative paths with respect to the output directory. * @type {{name:string, decode: function, encode: function, root: function}} */ module.exports = { name : 'outputRelative', decode: decode, encode: encode, root : getOutputDirectory }; /** * Decode the given uri. * Any path with or without leading slash is tested against context directory. * @this {{options: object}} A loader or compilation * @param {string} uri A source uri to decode * @returns {boolean|string} False where unmatched else the decoded path */ function decode(uri) { /* jshint validthis:true */ var base = getOutputDirectory.call(this), absFile = !!base && path.normalize(path.join(base, uri)), isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile(); return isValid && absFile; } /** * Encode the given file path. * @this {{options: object}} A loader or compilation * @param {string} absolute An absolute file path to encode * @returns {string} A uri */ function encode(absolute) { /* jshint validthis:true */ var base = getOutputDirectory.call(this); if (!base) { throw new Error('Cannot locate the Webpack output directory'); } else { return path.relative(base, absolute); } }