mirror of
https://github.com/systemjs/systemjs.git
synced 2026-01-18 14:53:14 +00:00
138 lines
3.5 KiB
JavaScript
138 lines
3.5 KiB
JavaScript
/*
|
|
SystemJS map support
|
|
|
|
Provides map configuration through
|
|
System.map['jquery'] = 'some/module/map'
|
|
|
|
As well as contextual map config through
|
|
System.map['bootstrap'] = {
|
|
jquery: 'some/module/map2'
|
|
}
|
|
|
|
Note that this applies for subpaths, just like RequireJS
|
|
|
|
jquery -> 'some/module/map'
|
|
jquery/path -> 'some/module/map/path'
|
|
bootstrap -> 'bootstrap'
|
|
|
|
Inside any module name of the form 'bootstrap' or 'bootstrap/*'
|
|
jquery -> 'some/module/map2'
|
|
jquery/p -> 'some/module/map2/p'
|
|
|
|
Maps are carefully applied from most specific contextual map, to least specific global map
|
|
*/
|
|
(function() {
|
|
|
|
hookConstructor(function(constructor) {
|
|
return function() {
|
|
constructor.call(this);
|
|
this.map = {};
|
|
};
|
|
});
|
|
|
|
// return if prefix parts (separated by '/') match the name
|
|
// eg prefixMatch('jquery/some/thing', 'jquery') -> true
|
|
// prefixMatch('jqueryhere/', 'jquery') -> false
|
|
function prefixMatch(name, prefix) {
|
|
if (name.length < prefix.length)
|
|
return false;
|
|
if (name.substr(0, prefix.length) != prefix)
|
|
return false;
|
|
if (name[prefix.length] && name[prefix.length] != '/')
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// get the depth of a given path
|
|
// eg pathLen('some/name') -> 2
|
|
function pathLen(name) {
|
|
var len = 1;
|
|
for (var i = 0, l = name.length; i < l; i++)
|
|
if (name[i] === '/')
|
|
len++;
|
|
return len;
|
|
}
|
|
|
|
function doMap(name, matchLen, map) {
|
|
return map + name.substr(matchLen);
|
|
}
|
|
|
|
// given a relative-resolved module name and normalized parent name,
|
|
// apply the map configuration
|
|
function applyMap(name, parentName, loader) {
|
|
var curMatch, curMatchLength = 0;
|
|
var curParent, curParentMatchLength = 0;
|
|
var tmpParentLength, tmpPrefixLength;
|
|
var subPath;
|
|
var nameParts;
|
|
|
|
// first find most specific contextual match
|
|
if (parentName) {
|
|
for (var p in loader.map) {
|
|
var curMap = loader.map[p];
|
|
if (typeof curMap != 'object')
|
|
continue;
|
|
|
|
// most specific parent match wins first
|
|
if (!prefixMatch(parentName, p))
|
|
continue;
|
|
|
|
tmpParentLength = pathLen(p);
|
|
if (tmpParentLength <= curParentMatchLength)
|
|
continue;
|
|
|
|
for (var q in curMap) {
|
|
// most specific name match wins
|
|
if (!prefixMatch(name, q))
|
|
continue;
|
|
tmpPrefixLength = pathLen(q);
|
|
if (tmpPrefixLength <= curMatchLength)
|
|
continue;
|
|
|
|
curMatch = q;
|
|
curMatchLength = tmpPrefixLength;
|
|
curParent = p;
|
|
curParentMatchLength = tmpParentLength;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if we found a contextual match, apply it now
|
|
if (curMatch)
|
|
return doMap(name, curMatch.length, loader.map[curParent][curMatch]);
|
|
|
|
// now do the global map
|
|
for (var p in loader.map) {
|
|
var curMap = loader.map[p];
|
|
if (typeof curMap != 'string')
|
|
continue;
|
|
|
|
if (!prefixMatch(name, p))
|
|
continue;
|
|
|
|
var tmpPrefixLength = pathLen(p);
|
|
|
|
if (tmpPrefixLength <= curMatchLength)
|
|
continue;
|
|
|
|
curMatch = p;
|
|
curMatchLength = tmpPrefixLength;
|
|
}
|
|
|
|
if (curMatch)
|
|
return doMap(name, curMatch.length, loader.map[curMatch]);
|
|
|
|
return name;
|
|
}
|
|
|
|
hook('normalize', function(normalize) {
|
|
return function(name, parentName, parentAddress) {
|
|
var loader = this;
|
|
return Promise.resolve(normalize.call(loader, name, parentName, parentAddress))
|
|
.then(function(name) {
|
|
return applyMap(name, parentName, loader);
|
|
});
|
|
};
|
|
});
|
|
})();
|