caffeine-mc
Version:
Select, configure and extend your to-JavaScript compiler, with arbitrary code, on a per file bases from within the file.
307 lines (266 loc) • 11.9 kB
JavaScript
// Generated by CoffeeScript 1.12.7
(function() {
var ErrorWithInfo, ModuleResolver, Path, Promise, cacheable, currentSecond, dashCase, defineModule, dirReader, each, find, findSourceRootSync, isString, log, merge, mergeInto, normalizeName, peek, present, realRequire, ref, snakeCase, upperCamelCase, w,
slice = [].slice;
ref = require('art-standard-lib'), defineModule = ref.defineModule, peek = ref.peek, Promise = ref.Promise, dashCase = ref.dashCase, upperCamelCase = ref.upperCamelCase, ErrorWithInfo = ref.ErrorWithInfo, log = ref.log, merge = ref.merge, present = ref.present, find = ref.find, each = ref.each, w = ref.w, mergeInto = ref.mergeInto, currentSecond = ref.currentSecond, snakeCase = ref.snakeCase, isString = ref.isString;
Path = require('path');
dirReader = require('./DirReader');
cacheable = require('./WorkingCache').cacheable;
normalizeName = cacheable("normalizeName", upperCamelCase);
realRequire = eval('require');
findSourceRootSync = require('./SourceRoots').findSourceRootSync;
/*
2018-07-21 Optimization TODO:
I think if we simplify the semantics such that matches are defined as:
normalizeName(dirName) == normalizeName(moduleName)
AND
* this is the change:
normalizeName(fileName.split(".")[0]) == normalizeName(moduleName)
Then we can probably make much better use of caching:
Read the dir in and create a map:
normalizedName: name
(where normalizedName here means for files, we strip the extensions)
Then, we don't have to scan the dir every time!
NOTE: I think if we have >= 2 files which map to the same noramlized name
we encode that in the map somehow and can therefore raise the same
exception we already do.
*/
defineModule(module, ModuleResolver = (function() {
var getMatchingName, maybeCouldHaveCached;
function ModuleResolver() {}
/*
IN:
moduleBaseName: the string before the first '/'
modulePathArray: every other sub-string, split by '/'
This is only used to determine if there is addutional pathing
that must be resolved. It makes a difference what the
require path looks like.
*/
ModuleResolver.getNpmPackageName = function(moduleBaseName, modulePathArray) {
var a, absolutePath, b, name, ref1, requireString;
if (/^@/.test(moduleBaseName)) {
ref1 = moduleBaseName.split(/\//), a = ref1[0], b = ref1[1];
try {
absolutePath = Path.dirname(realRequire.resolve(name = "@" + (dashCase(a)) + "/" + (dashCase(b))));
} catch (error) {}
try {
if (absolutePath == null) {
absolutePath = Path.dirname(realRequire.resolve(name = "@" + (snakeCase(a)) + "/" + (snakeCase(b))));
}
} catch (error) {}
} else {
try {
absolutePath = Path.dirname(realRequire.resolve(name = dashCase(moduleBaseName)));
} catch (error) {}
try {
if (absolutePath == null) {
absolutePath = Path.dirname(realRequire.resolve(name = snakeCase(moduleBaseName)));
}
} catch (error) {}
}
try {
if (absolutePath == null) {
absolutePath = Path.dirname(realRequire.resolve(name = moduleBaseName));
}
} catch (error) {
throw new ErrorWithInfo("ModuleResolver: Could not find requested npm package: " + moduleBaseName, {
npmPackageNamesAttempted: [moduleBaseName, dashCase(moduleBaseName)]
});
}
if ((modulePathArray != null ? modulePathArray.length : void 0) > 0) {
requireString = name.split('/')[0];
absolutePath = findSourceRootSync(absolutePath);
} else {
requireString = name;
}
return {
requireString: requireString,
absolutePath: absolutePath
};
};
ModuleResolver.findModuleSync = function(moduleName, options) {
var _, absolutePath, base, denormalizedBase, denormalizedBase2, j, len, matchingName, mod, modulePathArray, ref1, ref2, ref3, requireString, sub;
if (/\//.test(moduleName)) {
ref1 = (function() {
var j, len, ref1, ref2, results;
ref2 = (ref1 = moduleName.split("/"), denormalizedBase = ref1[0], denormalizedBase2 = ref1[1], ref1);
results = [];
for (j = 0, len = ref2.length; j < len; j++) {
mod = ref2[j];
results.push(normalizeName(mod));
}
return results;
})(), base = ref1[0], modulePathArray = 2 <= ref1.length ? slice.call(ref1, 1) : [];
if (/^@/.test(moduleName)) {
base = "@" + base + "/" + modulePathArray[0];
denormalizedBase = denormalizedBase + "/" + denormalizedBase2;
ref2 = modulePathArray, _ = ref2[0], modulePathArray = 2 <= ref2.length ? slice.call(ref2, 1) : [];
}
} else {
denormalizedBase = moduleName;
}
ref3 = ModuleResolver._findModuleBaseSync(denormalizedBase, modulePathArray, options), requireString = ref3.requireString, absolutePath = ref3.absolutePath;
if (modulePathArray) {
for (j = 0, len = modulePathArray.length; j < len; j++) {
sub = modulePathArray[j];
if (matchingName = ModuleResolver._matchingNameInDirectorySync(sub, absolutePath, options)) {
absolutePath = Path.join(absolutePath, matchingName);
requireString = requireString + "/" + matchingName;
} else {
throw new ErrorWithInfo("Could not find pathed submodule inside npm package: " + requireString, {
npmPackage: requireString,
localNpmPackageLocation: absolutePath,
submodulePath: sub,
normalized: normalizeName(sub),
dirItems: dirReader.read(absolutePath)
});
}
}
}
return {
requireString: requireString,
absolutePath: absolutePath
};
};
ModuleResolver.findModule = function(moduleName, options) {
return Promise.then(function() {
return ModuleResolver.findModuleSync(moduleName, options);
});
};
maybeCouldHaveCached = {};
ModuleResolver._findModuleBaseSync = function(moduleBaseName, modulePathArray, options) {
var absolutePath, absoluteSourceFilePath, directory, e, matchingName, normalizedModuleName, requireString, shouldContinue, sourceDir, sourceFile, sourceFiles, sourceRoot;
normalizedModuleName = upperCamelCase(moduleBaseName);
if (options) {
sourceFile = options.sourceFile, sourceDir = options.sourceDir, sourceFiles = options.sourceFiles, sourceRoot = options.sourceRoot;
}
sourceFile || (sourceFile = sourceFiles != null ? sourceFiles[0] : void 0);
if (sourceFile || sourceDir) {
directory = sourceDir = dirReader.resolve(sourceDir || Path.dirname(sourceFile));
sourceRoot || (sourceRoot = findSourceRootSync(sourceDir));
sourceRoot = sourceRoot && dirReader.resolve(sourceRoot);
absoluteSourceFilePath = sourceFile && Path.join(sourceDir, Path.parse(sourceFile).name);
}
absolutePath = null;
shouldContinue = present(sourceRoot);
while (shouldContinue) {
if ((matchingName = ModuleResolver._matchingNameInDirectorySync(normalizedModuleName, directory, options)) && absoluteSourceFilePath !== (absolutePath = Path.join(directory, matchingName))) {
shouldContinue = false;
} else {
absolutePath = null;
if (directory === sourceRoot) {
if (normalizedModuleName === normalizeName(peek(sourceRoot.split("/")))) {
absolutePath = sourceRoot;
}
shouldContinue = false;
} else {
directory = Path.dirname(directory);
}
}
}
if (absolutePath) {
requireString = Path.relative(sourceDir, absolutePath);
switch (requireString) {
case "..":
case ".":
requireString = requireString + "/";
}
if (!requireString.match(/^\./)) {
requireString = "./" + requireString;
}
return {
requireString: requireString,
absolutePath: absolutePath
};
} else {
try {
return ModuleResolver.getNpmPackageName(moduleBaseName, modulePathArray);
} catch (error) {
e = error;
if (e.info) {
mergeInto(e.info, {
sourceDir: sourceDir,
sourceRoot: sourceRoot
});
}
throw e;
}
}
};
/*
Notes about "." names-with-dots.
Essentially, dots are treated as word-boundaries.
Files:
We need to manage extensions. Current rule:
Full match example: FooCaf matches foo.caf
PartialMatch must fully match on dot-boundaries:
Foo.BarFood.caf does NOT match FooBar, but does match FooBarFood
PartialMatch must match starting at the first character:
Foo.BarFood.caf does NOT match BarFood but does match Foo
Dirs:
Dirs must fully match:
Art.Foo.Bar matches ArtFooBar BUT NOT ArtFoo
Future:
I'd like to be able to treat "."s in dir-names as-if they were '/' (slashes)
Basically, this parallels how NeptuneNamespaces interprets them.
It should work identically to as-if there were nested dirs.
Given these files:
MyFile1.caf
Foo/Bar/MyFile2.caf
OR these files:
MyFile1.caf
Foo.Bar/MyFile2.caf
Then:
* inside MyFile1.caf
* this works:
&Foo/Bar/MyFile2
returns false or name, if it matches
*/
ModuleResolver.getMatchingName = getMatchingName = function(normalizedModuleName, name, isDir) {
var foundLegalStop, i, j, len, normalizedTestName, offset, ref1, stop, stops;
if (normalizedModuleName === (normalizedTestName = normalizeName(name))) {
return name;
} else if (!isDir) {
if (0 === normalizedTestName.indexOf(normalizedModuleName)) {
foundLegalStop = false;
offset = 0;
ref1 = stops = name.split('.');
for (i = j = 0, len = ref1.length; j < len; i = ++j) {
stop = ref1[i];
stop = normalizeName(stop);
offset += stop.length;
if (normalizedModuleName.length === offset) {
return stops.slice(0, i + 1).join('.');
}
}
}
return false;
}
};
ModuleResolver._matchingNameInDirectorySync = function(normalizedModuleName, directory, options) {
var j, len, matchingName, name, newMatchingName, ref1;
matchingName = null;
if (!isString(directory)) {
throw new ErrorWithInfo("Directory must be a string");
}
ref1 = dirReader.read(directory);
for (j = 0, len = ref1.length; j < len; j++) {
name = ref1[j];
if (newMatchingName = getMatchingName(normalizedModuleName, name, dirReader.isDir(Path.join(directory, name)))) {
if (matchingName && matchingName !== newMatchingName) {
throw new ErrorWithInfo("More than one matching module name with\na) different actual base-names (" + matchingName + " != " + newMatchingName + ") and\nb) for the same normalized name (" + normalizedModuleName + ")", {
directory: directory,
firstMatch: matchingName,
secondMatch: newMatchingName,
normalizedModuleName: normalizedModuleName
});
}
matchingName = newMatchingName;
}
}
return matchingName;
};
return ModuleResolver;
})());
}).call(this);
//# sourceMappingURL=ModuleResolver.js.map