UNPKG

systemjs

Version:

System loader extension for flexible AMD & CommonJS support

153 lines (124 loc) 4.04 kB
/* 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 map(loader) { loader.map = loader.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; } var loaderNormalize = loader.normalize; loader.normalize = function(name, parentName, parentAddress) { var loader = this; if (!loader.map) loader.map = {}; var isPackage = false; if (name.substr(name.length - 1, 1) == '/') { isPackage = true; name += '#'; } return Promise.resolve(loaderNormalize.call(loader, name, parentName, parentAddress)) .then(function(name) { name = applyMap(name, parentName, loader); // Normalize "module/" into "module/module" // Convenient for packages if (isPackage) { var nameParts = name.split('/'); nameParts.pop(); var pkgName = nameParts.pop(); nameParts.push(pkgName); nameParts.push(pkgName); name = nameParts.join('/'); } return name; }); } }