|
|
'use strict'; |
|
|
|
|
|
var fs = require('fs'), |
|
|
path = require('path'); |
|
|
|
|
|
var cache; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function enhancedRelative(from, to) { |
|
|
|
|
|
|
|
|
var relative = path.relative(from, to); |
|
|
|
|
|
|
|
|
var trailing = relative.replace(/^\.{2}[\\\/]/, ''), |
|
|
leading = to.replace(trailing, ''); |
|
|
|
|
|
|
|
|
var isInProject = (relative === trailing); |
|
|
if (isInProject) { |
|
|
return relative; |
|
|
} |
|
|
|
|
|
else { |
|
|
var splitTrailing = trailing.split(/[\\\/]/); |
|
|
|
|
|
|
|
|
for (var i = cache ? 2 : 1, foundPath = false; (i > 0) && !foundPath; i--) { |
|
|
|
|
|
|
|
|
cache = cache || indexLinkedModules(from); |
|
|
|
|
|
|
|
|
for (var j = 0; (j < splitTrailing.length) && !foundPath; j++) { |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
var linkedPackagePath = !!packageName && cache[packageName]; |
|
|
if (linkedPackagePath) { |
|
|
|
|
|
|
|
|
var remainingPath = path.join.apply(path, splitTrailing.slice(j + 1)); |
|
|
|
|
|
|
|
|
|
|
|
var linkedFilePath = path.join(linkedPackagePath, remainingPath), |
|
|
isValid = !!linkedFilePath && fs.existsSync(linkedFilePath) && |
|
|
fs.statSync(linkedFilePath).isFile(); |
|
|
|
|
|
|
|
|
foundPath = isValid && linkedFilePath; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cache = !!foundPath && cache; |
|
|
} |
|
|
|
|
|
|
|
|
return foundPath ? path.relative(from, foundPath) : relative; |
|
|
} |
|
|
} |
|
|
|
|
|
module.exports = enhancedRelative; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function indexLinkedModules(directory) { |
|
|
var buffer = listSymLinkedModules(directory), |
|
|
hash = {}; |
|
|
|
|
|
|
|
|
while (buffer.length > 0) { |
|
|
var modulePath = buffer.shift(), |
|
|
packageJsonPath = path.join(modulePath, 'package.json'), |
|
|
packageName = fs.existsSync(packageJsonPath) && require(packageJsonPath).name; |
|
|
if (packageName) { |
|
|
|
|
|
|
|
|
hash[packageName] = hash[packageName] || modulePath; |
|
|
|
|
|
|
|
|
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(); |
|
|
} |
|
|
} |
|
|
} |