UNPKG

steal-tools

Version:

Futuristic build tools for ES6 Module applications.

1,820 lines (1,599 loc) 118 kB
(function(global){ // helpers var camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }); }, each = function( o, cb){ var i, len; // weak array detection, but we only use this internally so don't // pass it weird stuff if ( typeof o.length == 'number' && (o.length - 1) in o) { for ( i = 0, len = o.length; i < len; i++ ) { cb.call(o[i], o[i], i, o); } } else { for ( i in o ) { if(o.hasOwnProperty(i)){ cb.call(o[i], o[i], i, o); } } } return o; }, map = function(o, cb) { var arr = []; each(o, function(item, i){ arr[i] = cb(item, i); }); return arr; }, isString = function(o) { return typeof o == "string"; }, extend = function(d,s){ each(s, function(v, p){ d[p] = v; }); return d; }, dir = function(uri){ var lastSlash = uri.lastIndexOf("/"); //if no / slashes, check for \ slashes since it might be a windows path if(lastSlash === -1) lastSlash = uri.lastIndexOf("\\"); if(lastSlash !== -1) { return uri.substr(0, lastSlash); } else { return uri; } }, last = function(arr){ return arr[arr.length - 1]; }, parseURI = function(url) { var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@\/]*(?::[^:@\/]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); // authority = '//' + user + ':' + pass '@' + hostname + ':' port return (m ? { href : m[0] || '', protocol : m[1] || '', authority: m[2] || '', host : m[3] || '', hostname : m[4] || '', port : m[5] || '', pathname : m[6] || '', search : m[7] || '', hash : m[8] || '' } : null); }, joinURIs = function(base, href) { function removeDotSegments(input) { var output = []; input.replace(/^(\.\.?(\/|$))+/, '') .replace(/\/(\.(\/|$))+/g, '/') .replace(/\/\.\.$/, '/../') .replace(/\/?[^\/]*/g, function (p) { if (p === '/..') { output.pop(); } else { output.push(p); } }); return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); } href = parseURI(href || ''); base = parseURI(base || ''); return !href || !base ? null : (href.protocol || base.protocol) + (href.protocol || href.authority ? href.authority : base.authority) + removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) + (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + href.hash; }, relativeURI = function(base, path) { var uriParts = path.split("/"), baseParts = base.split("/"), result = []; while ( uriParts.length && baseParts.length && uriParts[0] == baseParts[0] ) { uriParts.shift(); baseParts.shift(); } for(var i = 0 ; i< baseParts.length-1; i++) { result.push("../"); } return "./" + result.join("") + uriParts.join("/"); }, fBind = Function.prototype.bind, isFunction = function(obj) { return !!(obj && obj.constructor && obj.call && obj.apply); }, isWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope, isNode = typeof process === "object" && {}.toString.call(process) === "[object process]", isBrowserWithWindow = !isNode && typeof window !== "undefined", isNW = isNode && (function(){ try { return require("nw.gui") !== "undefined"; } catch(e) { return false; } })(), isElectron = isNode && !!process.versions["electron"], isNode = isNode && !isNW && !isElectron, warn = typeof console === "object" ? fBind.call(console.warn, console) : function(){}; var filename = function(uri){ var lastSlash = uri.lastIndexOf("/"); //if no / slashes, check for \ slashes since it might be a windows path if(lastSlash === -1) lastSlash = uri.lastIndexOf("\\"); var matches = ( lastSlash == -1 ? uri : uri.substr(lastSlash+1) ).match(/^[\w-\s\.!]+/); return matches ? matches[0] : ""; }; var ext = function(uri){ var fn = filename(uri); var dot = fn.lastIndexOf("."); if(dot !== -1) { return fn.substr(dot+1); } else { return ""; } }; var pluginCache = {}; var normalize = function(unnormalizedName, loader){ var name = unnormalizedName; // Detech if this name contains a plugin part like: app.less!steal/less // and catch the plugin name so that when it is normalized we do not perform // Steal's normalization against it. var pluginIndex = name.lastIndexOf('!'); var pluginPart = ""; if (pluginIndex != -1) { // argumentName is the part before the ! var argumentName = name.substr(0, pluginIndex); var pluginName = name.substr(pluginIndex + 1); pluginPart = "!" + pluginName; // Set the name to the argument name so that we can normalize it alone. name = argumentName; } var last = filename(name), extension = ext(name); // if the name ends with / if( name[name.length -1] === "/" ) { return name+filename( name.substr(0, name.length-1) ) + pluginPart; } else if( !/^(\w+(?:s)?:\/\/|\.|file|\/)/.test(name) && // and doesn't end with a dot last.indexOf(".") === -1 ) { return name+"/"+last + pluginPart; } else { if(extension === "js") { return name.substr(0, name.lastIndexOf(".")) + pluginPart; } else { return name + pluginPart; } } }; var cloneSteal = function(System){ var loader = System || this.System; var steal = makeSteal(loader.clone()); steal.loader.set("@steal", steal.loader.newModule({ "default": steal, __useDefault: true })); steal.clone = cloneSteal; return steal; }; var makeSteal = function(System){ var addStealExtension = function (extensionFn) { if (typeof System !== "undefined" && isFunction(extensionFn)) { if (System._extensions) { System._extensions.push(extensionFn); } extensionFn(System); } }; System.set('@loader', System.newModule({ 'default': System, __useDefault: true })); System.set("less", System.newModule({ __useDefault: true, default: { fetch: function() { throw new Error( [ "steal-less plugin must be installed and configured properly", "See https://stealjs.com/docs/steal-less.html" ].join("\n") ); } } })); System.config({ map: { "@loader/@loader": "@loader", "@steal/@steal": "@steal" } }); var configPromise, devPromise, appPromise; var steal = function(){ var args = arguments; var afterConfig = function(){ var imports = []; var factory; each(args, function(arg){ if(isString(arg)) { imports.push( steal.System['import']( normalize(arg) ) ); } else if(typeof arg === "function") { factory = arg; } }); var modules = Promise.all(imports); if(factory) { return modules.then(function(modules) { return factory && factory.apply(null, modules); }); } else { return modules; } }; if(System.isEnv("production")) { return afterConfig(); } else { // wait until the config has loaded return configPromise.then(afterConfig,afterConfig); } }; System.set("@steal", System.newModule({ "default": steal, __useDefault:true })); var loaderClone = System.clone; System.clone = function(){ var loader = loaderClone.apply(this, arguments); loader.set("@loader", loader.newModule({ "default": loader, __useDefault: true })); loader.set("@steal", loader.newModule({ "default": steal, __useDefault: true })); return loader; }; // steal.System remains for backwards compat only steal.System = steal.loader = System; steal.parseURI = parseURI; steal.joinURIs = joinURIs; steal.normalize = normalize; steal.relativeURI = relativeURI; steal.addExtension = addStealExtension; // System-Ext // This normalize-hook does 2 things. // 1. with specify a extension in your config // you can use the "!" (bang) operator to load // that file with the extension // System.ext = {bar: "path/to/bar"} // foo.bar! -> foo.bar!path/to/bar // 2. if you load a javascript file e.g. require("./foo.js") // normalize will remove the ".js" to load the module addStealExtension(function (loader) { loader.ext = {}; var normalize = loader.normalize, endingExtension = /\.(\w+)!?$/; loader.normalize = function (name, parentName, parentAddress, pluginNormalize) { if (pluginNormalize) { return normalize.apply(this, arguments); } var matches = name.match(endingExtension); var outName = name; if (matches) { var hasBang = name[name.length - 1] === "!", ext = matches[1]; // load js-files nodd-like if (parentName && loader.configMain !== name && matches[0] === '.js') { outName = name.substr(0, name.lastIndexOf(".")); // matches ext mapping } else if (loader.ext[ext]) { outName = name + (hasBang ? "" : "!") + loader.ext[ext]; } } return normalize.call(this, outName, parentName, parentAddress); }; }); // Steal Locate Extension // normalize a given path e.g. // "path/to/folder/" -> "path/to/folder/folder" addStealExtension(function (loader) { var normalize = loader.normalize; var npmLike = /@.+#.+/; loader.normalize = function (name, parentName, parentAddress, pluginNormalize) { var lastPos = name.length - 1, secondToLast, folderName, newName = name; if (name[lastPos] === "/") { secondToLast = name.substring(0, lastPos).lastIndexOf("/"); folderName = name.substring(secondToLast + 1, lastPos); if (npmLike.test(folderName)) { folderName = folderName.substr(folderName.lastIndexOf("#") + 1); } newName += folderName; } return normalize.call(this, newName, parentName, parentAddress, pluginNormalize); }; }); // override loader.translate to rewrite 'locate://' & 'pkg://' path schemes found // in resources loaded by supporting plugins addStealExtension(function (loader) { /** * @hide * @function normalizeAndLocate * @description Run a module identifier through Normalize and Locate hooks. * @param {String} moduleName The module to run through normalize and locate. * @return {Promise} A promise to resolve when the address is found. */ var normalizeAndLocate = function(moduleName, parentName){ var loader = this; return Promise.resolve(loader.normalize(moduleName, parentName)) .then(function(name){ return loader.locate({name: name, metadata: {}}); }).then(function(address){ var outAddress = address; if(address.substr(address.length - 3) === ".js") { outAddress = address.substr(0, address.length - 3); } return outAddress; }); }; var relative = function(base, path){ var uriParts = path.split("/"), baseParts = base.split("/"), result = []; while ( uriParts.length && baseParts.length && uriParts[0] == baseParts[0] ) { uriParts.shift(); baseParts.shift(); } for(var i = 0 ; i< baseParts.length-1; i++) { result.push("../"); } return result.join("") + uriParts.join("/"); }; var schemePattern = /(locate):\/\/([a-z0-9/._@-]*)/ig, parsePathSchemes = function(source, parent) { var locations = []; source.replace(schemePattern, function(whole, scheme, path, index){ locations.push({ start: index, end: index+whole.length, name: path, postLocate: function(address){ return relative(parent, address); } }); }); return locations; }; var _translate = loader.translate; loader.translate = function(load){ var loader = this; // This only applies to plugin resources. if(!load.metadata.plugin) { return _translate.call(this, load); } // Use the translator if this file path scheme is supported by the plugin var locateSupport = load.metadata.plugin.locateScheme; if(!locateSupport) { return _translate.call(this, load); } // Parse array of module names var locations = parsePathSchemes(load.source, load.address); // no locations found if(!locations.length) { return _translate.call(this, load); } // normalize and locate all of the modules found and then replace those instances in the source. var promises = []; for(var i = 0, len = locations.length; i < len; i++) { promises.push( normalizeAndLocate.call(this, locations[i].name, load.name) ); } return Promise.all(promises).then(function(addresses){ for(var i = locations.length - 1; i >= 0; i--) { load.source = load.source.substr(0, locations[i].start) + locations[i].postLocate(addresses[i]) + load.source.substr(locations[i].end, load.source.length); } return _translate.call(loader, load); }); }; }); addStealExtension(function (loader) { loader._contextualModules = {}; loader.setContextual = function(moduleName, definer){ this._contextualModules[moduleName] = definer; }; var normalize = loader.normalize; loader.normalize = function(name, parentName){ var loader = this; var pluginLoader = loader.pluginLoader || loader; if (parentName) { var definer = this._contextualModules[name]; // See if `name` is a contextual module if (definer) { var localName = name + '/' + parentName; if(!loader.has(localName)) { // `definer` could be a function or could be a moduleName if (typeof definer === 'string') { definer = pluginLoader['import'](definer); } return Promise.resolve(definer) .then(function(modDefiner) { var definer = modDefiner; if (definer['default']) { definer = definer['default']; } var definePromise = Promise.resolve( definer.call(loader, parentName) ); return definePromise; }) .then(function(moduleDef){ loader.set(localName, loader.newModule(moduleDef)); return localName; }); } return Promise.resolve(localName); } } return normalize.apply(this, arguments); }; }); /** * Steal Script-Module Extension * * Add a steal-module script to the page and it will run after Steal has been * configured, e.g: * * <script type="text/steal-module">...</script> * <script type="steal-module">...</script> */ addStealExtension(function(loader) { // taken from https://github.com/ModuleLoader/es6-module-loader/blob/master/src/module-tag.js function completed() { document.removeEventListener("DOMContentLoaded", completed, false); window.removeEventListener("load", completed, false); ready(); } function ready() { var scripts = document.getElementsByTagName("script"); for (var i = 0; i < scripts.length; i++) { var script = scripts[i]; if (script.type == "steal-module" || script.type == "text/steal-module") { var source = script.innerHTML; if (/\S/.test(source)) { loader.module(source)["catch"](function(err) { setTimeout(function() { throw err; }); }); } } } } loader.loadScriptModules = function() { if (isBrowserWithWindow) { if (document.readyState === "complete") { setTimeout(ready); } else if (document.addEventListener) { document.addEventListener("DOMContentLoaded", completed, false); window.addEventListener("load", completed, false); } } }; }); // SystemJS Steal Format // Provides the Steal module format definition. addStealExtension(function (loader) { // Steal Module Format Detection RegEx // steal(module, ...) var stealRegEx = /(?:^\s*|[}{\(\);,\n\?\&]\s*)steal\s*\(\s*((?:"[^"]+"\s*,|'[^']+'\s*,\s*)*)/; // What we stole. var stealInstantiateResult; function createSteal(loader) { stealInstantiateResult = null; // ensure no NodeJS environment detection loader.global.module = undefined; loader.global.exports = undefined; function steal() { var deps = []; var factory; for( var i = 0; i < arguments.length; i++ ) { if (typeof arguments[i] === 'string') { deps.push( normalize(arguments[i]) ); } else { factory = arguments[i]; } } if (typeof factory !== 'function') { factory = (function(factory) { return function() { return factory; }; })(factory); } stealInstantiateResult = { deps: deps, execute: function(require, exports, moduleName) { var depValues = []; for (var i = 0; i < deps.length; i++) { depValues.push(require(deps[i])); } var output = factory.apply(loader.global, depValues); if (typeof output !== 'undefined') { return output; } } }; } loader.global.steal = steal; } var loaderInstantiate = loader.instantiate; loader.instantiate = function(load) { var loader = this; if (load.metadata.format === 'steal' || !load.metadata.format && load.source.match(stealRegEx)) { load.metadata.format = 'steal'; var oldSteal = loader.global.steal; createSteal(loader); loader.__exec(load); loader.global.steal = oldSteal; if (!stealInstantiateResult) { throw "Steal module " + load.name + " did not call steal"; } if (stealInstantiateResult) { load.metadata.deps = load.metadata.deps ? load.metadata.deps.concat(stealInstantiateResult.deps) : stealInstantiateResult.deps; load.metadata.execute = stealInstantiateResult.execute; } } return loaderInstantiate.call(loader, load); }; }); addStealExtension(function(loader) { var superTranspile = loader.transpile; var superDetermineFormat = loader._determineFormat; function prependDeps (loader, load, callback) { var meta = loader.meta[load.name]; if (meta && meta.deps && meta.deps.length) { var imports = meta.deps.map(callback).join('\n'); load.source = imports + "\n" + load.source; } } function createImport(dep) { return "import \"" + dep + "\";"; } function createRequire(dep) { return "require(\"" + dep + "\");"; } loader.transpile = function (load) { prependDeps(this, load, createImport); var result = superTranspile.apply(this, arguments); return result; } loader._determineFormat = function (load) { if(load.metadata.format === 'cjs') { prependDeps(this, load, createRequire); } var result = superDetermineFormat.apply(this, arguments); return result; }; }); addStealExtension(function applyTraceExtension(loader) { if(loader._extensions) { loader._extensions.push(applyTraceExtension); } loader._traceData = { loads: {}, parentMap: {} }; loader.getDependencies = function(moduleName){ var load = this.getModuleLoad(moduleName); return load ? load.metadata.dependencies : undefined; }; loader.getDependants = function(moduleName){ var deps = []; var pars = this._traceData.parentMap[moduleName] || {}; eachOf(pars, function(name) { deps.push(name); }); return deps; }; loader.getModuleLoad = function(moduleName){ return this._traceData.loads[moduleName]; }; loader.getBundles = function(moduleName, argVisited){ var visited = argVisited || {}; visited[moduleName] = true; var loader = this; var parentMap = loader._traceData.parentMap; var parents = parentMap[moduleName]; if(!parents) return [moduleName]; var bundles = []; eachOf(parents, function(parentName, value){ if(!visited[parentName]) bundles = bundles.concat(loader.getBundles(parentName, visited)); }); return bundles; }; loader._allowModuleExecution = {}; loader.allowModuleExecution = function(name){ var loader = this; return loader.normalize(name).then(function(name){ loader._allowModuleExecution[name] = true; }); }; function eachOf(obj, callback){ var name, val; for(name in obj) { callback(name, obj[name]); } } var normalize = loader.normalize; loader.normalize = function(name, parentName){ var normalizePromise = normalize.apply(this, arguments); if(parentName) { var parentMap = this._traceData.parentMap; return normalizePromise.then(function(name){ if(!parentMap[name]) { parentMap[name] = {}; } parentMap[name][parentName] = true; return name; }); } return normalizePromise; }; var emptyExecute = function(){ return loader.newModule({}); }; var passThroughModules = { traceur: true, babel: true }; var isAllowedToExecute = function(load){ return passThroughModules[load.name] || this._allowModuleExecution[load.name]; }; var map = [].map || function(callback){ var res = []; for(var i = 0, len = this.length; i < len; i++) { res.push(callback(this[i])); } return res; }; var esImportDepsExp = /import [\s\S]*?["'](.+)["']/g; var esExportDepsExp = /export .+ from ["'](.+)["']/g; var commentRegEx = /(?:(?:^|\s)\/\/(.+?)$)|(?:\/\*([\S\s]*?)\*\/)/gm; var stringRegEx = /(?:("|')[^\1\\\n\r]*(?:\\.[^\1\\\n\r]*)*\1|`[^`]*`)/g; function getESDeps(source) { var cleanSource = source.replace(commentRegEx, ""); esImportDepsExp.lastIndex = commentRegEx.lastIndex = esExportDepsExp.lastIndex = stringRegEx.lastIndex = 0; var match; var deps = []; var stringLocations = []; // track string for unminified source function inLocation(locations, match) { for (var i = 0; i < locations.length; i++) if (locations[i][0] < match.index && locations[i][1] > match.index) return true; return false; } function addDeps(exp) { while (match = exp.exec(cleanSource)) { // ensure we're not within a string location if (!inLocation(stringLocations, match)) { var dep = match[1]; deps.push(dep); } } } if (source.length / source.split('\n').length < 200) { while (match = stringRegEx.exec(cleanSource)) stringLocations.push([match.index, match.index + match[0].length]); } addDeps(esImportDepsExp); addDeps(esExportDepsExp); return deps; } var instantiate = loader.instantiate; loader.instantiate = function(load){ this._traceData.loads[load.name] = load; var loader = this; var instantiatePromise = Promise.resolve(instantiate.apply(this, arguments)); function finalizeResult(result){ var preventExecution = loader.preventModuleExecution && !isAllowedToExecute.call(loader, load); // deps either comes from the instantiate result, or if an // es6 module it was found in the transpile hook. var deps = result ? result.deps : load.metadata.deps; return Promise.all(map.call(deps, function(depName){ return loader.normalize(depName, load.name); })).then(function(dependencies){ load.metadata.deps = deps; load.metadata.dependencies = dependencies; if(preventExecution) { return { deps: deps, execute: emptyExecute }; } return result; }); } return instantiatePromise.then(function(result){ // This must be es6 if(!result) { var deps = getESDeps(load.source); load.metadata.deps = deps; } return finalizeResult(result); }); }; var transpile = loader.transpile; // Allow transpile to be memoized, but only once loader.transpile = function(load){ var transpiled = load.metadata.transpiledSource; if(transpiled) { delete load.metadata.transpiledSource; return Promise.resolve(transpiled); } return transpile.apply(this, arguments); }; loader.eachModule = function(cb){ for (var moduleName in this._loader.modules) { cb.call(this, moduleName, this.get(moduleName)); } }; }); // Steal JSON Format // Provides the JSON module format definition. addStealExtension(function (loader) { var jsonExt = /\.json$/i; var jsExt = /\.js$/i; // taken from prototypejs // https://github.com/sstephenson/prototype/blob/master/src/prototype/lang/string.js#L682-L706 function isJSON(json) { var str = json; if (!str) return false; str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); return (/^[\],:{}\s]*$/).test(str); } // if someone has a moduleName that is .json, make sure it loads a json file // no matter what paths might do var loaderLocate = loader.locate; loader.locate = function(load){ return loaderLocate.apply(this, arguments).then(function(address){ if(jsonExt.test(load.name)) { return address.replace(jsExt, ""); } return address; }); }; var transform = function(loader, load, data){ var fn = loader.jsonOptions && loader.jsonOptions.transform; if(!fn) return data; return fn.call(loader, load, data); }; // If we are in a build we should convert to CommonJS instead. if(isNode) { var loaderTranslate = loader.translate; loader.translate = function(load){ var address = load.metadata.address || load.address; if(jsonExt.test(address) && load.name.indexOf('!') === -1) { var parsed = parse(load); if(parsed) { parsed = transform(this, load, parsed); return "def" + "ine([], function(){\n" + "\treturn " + JSON.stringify(parsed) + "\n});"; } } return loaderTranslate.call(this, load); }; return; } var loaderInstantiate = loader.instantiate; loader.instantiate = function(load) { var loader = this, parsed; parsed = parse(load); if(parsed) { parsed = transform(loader, load, parsed); load.metadata.format = 'json'; load.metadata.execute = function(){ return parsed; }; } return loaderInstantiate.call(loader, load); }; return loader; // Attempt to parse a load as json. function parse(load){ if ((load.metadata.format === 'json' || !load.metadata.format) && isJSON(load.source)) { try { return JSON.parse(load.source); } catch(e) { warn("Error parsing " + load.address + ":", e); return {}; } } } }); // Steal Cache-Bust Extension // if enabled, Steal Cache-Bust will add a // cacheKey and cacheVersion to the required file address addStealExtension(function (loader) { var fetch = loader.fetch; loader.fetch = function(load) { var loader = this; if(loader.isEnv("production") && loader.cacheVersion) { var cacheVersion = loader.cacheVersion, cacheKey = loader.cacheKey || "version", cacheKeyVersion = cacheKey + "=" + cacheVersion; load.address = load.address + (load.address.indexOf('?') === -1 ? '?' : '&') + cacheKeyVersion; } return fetch.call(this, load); }; }); // Overwrites System.config with setter hooks var setterConfig = function(loader, configOrder, configSpecial){ var oldConfig = loader.config; loader.config = function(cfg){ var data = extend({},cfg); // check each special each(configOrder, function(name){ var special = configSpecial[name]; // if there is a setter and a value if(special.set && data[name]){ // call the setter var res = special.set.call(loader,data[name], cfg); // if the setter returns a value if(res !== undefined) { // set that on the loader loader[name] = res; } // delete the property b/c setting is done delete data[name]; } }); oldConfig.call(this, data); }; }; var setIfNotPresent = function(obj, prop, value){ if(!obj[prop]) { obj[prop] = value; } }; // steal.js's default configuration values System.configMain = "@config"; System.devBundle = "@empty"; System.depsBundle = "@empty"; System.paths[System.configMain] = "stealconfig.js"; System.env = (isWebWorker ? "worker" : "window") + "-development"; System.ext = Object.create(null); System.logLevel = 0; var cssBundlesNameGlob = "bundles/*.css", jsBundlesNameGlob = "bundles/*"; setIfNotPresent(System.paths,cssBundlesNameGlob, "dist/bundles/*css"); setIfNotPresent(System.paths,jsBundlesNameGlob, "dist/bundles/*.js"); var configSetter = function(order){ return { order: order, set: function(val){ var name = filename(val), root = dir(val); if(!isNode) { System.configPath = joinURIs( location.href, val); } System.configMain = name; System.paths[name] = name; this.config({ baseURL: (root === val ? "." : root) + "/" }); } } }, valueSetter = function(prop, order) { return { order: order, set: function(val) { this[prop] = val; } } }, booleanSetter = function(prop, order) { return { order: order, set: function(val) { this[prop] = !!val; } } }, fileSetter = function(prop, order) { return { order: order, set: function(val) { this[prop] = envPath(val); } }; }; // checks if we're running in node, then prepends the "file:" protocol if we are var envPath = function(pathVal) { var val = pathVal; if(isNode && !/^file:/.test(val)) { // If relative join with the current working directory if(val[0] === "." && (val[1] === "/" || (val[1] === "." && val[2] === "/"))) { val = require("path").join(process.cwd(), val); } if(!val) return val; return "file:" + val; } return val; }; var setToSystem = function(prop){ return { set: function(val){ if(typeof val === "object" && typeof steal.System[prop] === "object") { this[prop] = extend(this[prop] || {},val || {}); } else { this[prop] = val; } } }; }; var pluginPart = function(name) { var bang = name.lastIndexOf("!"); if(bang !== -1) { return name.substr(bang+1); } }; var pluginResource = function(name){ var bang = name.lastIndexOf("!"); if(bang !== -1) { return name.substr(0, bang); } }; var addProductionBundles = function(){ // we don't want add the main bundled module if steal is bundled inside! if(this.loadBundles && this.main && !this.stealBundled) { var main = this.main, bundlesDir = this.bundlesName || "bundles/", mainBundleName = bundlesDir+main; setIfNotPresent(this.meta, mainBundleName, {format:"amd"}); // If the configMain has a plugin like package.json!npm, // plugin has to be defined prior to importing. var plugin = pluginPart(System.configMain); var bundle = [main, System.configMain]; if(plugin){ System.set(plugin, System.newModule({})); } plugin = pluginPart(main); if(plugin) { var resource = pluginResource(main); bundle.push(plugin); bundle.push(resource); mainBundleName = bundlesDir+resource.substr(0, resource.indexOf(".")); } this.bundles[mainBundleName] = bundle; } }; var setEnvsConfig = function(){ if(this.envs) { var envConfig = this.envs[this.env]; if(envConfig) { this.config(envConfig); } } }; var setupLiveReload = function(){ if(this.liveReloadInstalled) { var loader = this; this["import"]("live-reload", { name: "@@steal" }).then(function(reload){ reload(loader.configMain, function(){ setEnvsConfig.call(loader); }); }); } }; var specialConfigOrder = []; var envsSpecial = { map: true, paths: true, meta: true }; var specialConfig = { instantiated: { order: 1, set: function(val){ var loader = this; each(val || {}, function(value, name){ loader.set(name, loader.newModule(value)); }); } }, envs: { order: 2, set: function(val){ // envs should be set, deep var envs = this.envs; if(!envs) envs = this.envs = {}; each(val, function(cfg, name){ var env = envs[name]; if(!env) env = envs[name] = {}; each(cfg, function(val, name){ if(envsSpecial[name] && env[name]) { extend(env[name], val); } else { env[name] = val; } }); }); } }, env: { order: 3, set: function(val){ this.env = val; if(this.isEnv("production")) { this.loadBundles = true; } } }, loadBundles: booleanSetter("loadBundles", 4), stealBundled: booleanSetter("stealBundled", 5), // System.config does not like being passed arrays. bundle: { order: 6, set: function(val){ System.bundle = val; } }, bundlesPath: { order: 7, set: function(val){ this.paths[cssBundlesNameGlob] = val+"/*css"; this.paths[jsBundlesNameGlob] = val+"/*.js"; return val; } }, meta: { order: 8, set: function(cfg){ var loader = this; each(cfg || {}, function(value, name){ if(typeof value !== "object") { return; } var cur = loader.meta[name]; if(cur && cur.format === value.format) { // Keep the deps, if we have any var deps = value.deps; extend(value, cur); if(deps) { value.deps = deps; } } }); extend(this.meta, cfg); } }, configMain: valueSetter("configMain", 9), config: configSetter(10), configPath: configSetter(11), baseURL: fileSetter("baseURL", 12), main: valueSetter("main", 13), // this gets called with the __dirname steal is in // directly called from steal-tools stealPath: { order: 14, set: function(identifier, cfg) { var dirname = envPath(identifier); var parts = dirname.split("/"); // steal keeps this around to make things easy no matter how you are using it. setIfNotPresent(this.paths,"@dev", dirname+"/ext/dev.js"); setIfNotPresent(this.paths,"npm", dirname+"/ext/npm.js"); setIfNotPresent(this.paths,"npm-extension", dirname+"/ext/npm-extension.js"); setIfNotPresent(this.paths,"npm-utils", dirname+"/ext/npm-utils.js"); setIfNotPresent(this.paths,"npm-crawl", dirname+"/ext/npm-crawl.js"); setIfNotPresent(this.paths,"npm-load", dirname+"/ext/npm-load.js"); setIfNotPresent(this.paths,"npm-convert", dirname+"/ext/npm-convert.js"); setIfNotPresent(this.paths,"semver", dirname+"/ext/semver.js"); setIfNotPresent(this.paths,"bower", dirname+"/ext/bower.js"); setIfNotPresent(this.paths,"live-reload", dirname+"/ext/live-reload.js"); setIfNotPresent(this.paths,"steal-clone", dirname+"/ext/steal-clone.js"); this.paths["traceur"] = dirname+"/ext/traceur.js"; this.paths["traceur-runtime"] = dirname+"/ext/traceur-runtime.js"; this.paths["babel"] = dirname+"/ext/babel.js"; this.paths["babel-runtime"] = dirname+"/ext/babel-runtime.js"; setIfNotPresent(this.meta,"traceur",{"exports":"traceur"}); // steal-clone is contextual so it can override modules using relative paths this.setContextual('steal-clone', 'steal-clone'); if(isNode) { if(this.configMain === "@config" && last(parts) === "steal") { parts.pop(); if(last(parts) === "node_modules") { this.configMain = "package.json!npm"; parts.pop(); } } if(this.isEnv("production") || this.loadBundles) { addProductionBundles.call(this); } } else { // make sure we don't set baseURL if it already set if(!cfg.baseURL && !cfg.config && !cfg.configPath) { // if we loading steal.js and it is located in node_modules or bower_components // we rewrite the baseURL relative to steal.js (one directory up!) // we do this because, normaly our app is located as a sibling folder to // node_modules or bower_components if ( last(parts) === "steal" ) { parts.pop(); var isFromPackage = false; if ( last(parts) === cfg.bowerPath || last(parts) === "bower_components" ) { System.configMain = "bower.json!bower"; addProductionBundles.call(this); parts.pop(); isFromPackage = true; } if (last(parts) === "node_modules") { System.configMain = "package.json!npm"; addProductionBundles.call(this); parts.pop(); isFromPackage = true; } if(!isFromPackage) { parts.push("steal"); } } this.config({ baseURL: parts.join("/")+"/"}); } } System.stealPath = dirname; } }, stealURL: { order: 15, // http://domain.com/steal/steal.js?moduleName,env& set: function(url, cfg) { var urlParts = url.split("?"), path = urlParts.shift(), paths = path.split("/"), lastPart = paths.pop(), stealPath = paths.join("/"), platform = this.getPlatform() || (isWebWorker ? "worker" : "window"); System.stealURL = path; // if steal is bundled or we are loading steal.production // we always are in production environment if((this.stealBundled && this.stealBundled === true) || ((lastPart.indexOf("steal.production") > -1) || (lastPart.indexOf("steal-sans-promises.production") > -1) && !cfg.env)) { this.config({ env: platform+"-production" }); } if(this.isEnv("production") || this.loadBundles) { addProductionBundles.call(this); } specialConfig.stealPath.set.call(this,stealPath, cfg); } }, devBundle: { order: 16, set: function(dirname, cfg) { var path = (dirname === true) ? "dev-bundle" : dirname; if (path) { this.devBundle = path; } } }, depsBundle: { order: 17, set: function(dirname, cfg) { var path = (dirname === true) ? "dev-bundle" : dirname; if (path) { this.depsBundle = path; } } } }; /* make a setter order currently: instantiated envs env loadBundles stealBundled bundle bundlesPath meta config configPath baseURL main stealPath stealURL */ each(specialConfig, function(setter, name){ if(!setter.order) { specialConfigOrder.push(name) }else{ specialConfigOrder.splice(setter.order, 0, name); } }); // special setter config setterConfig(System, specialConfigOrder, specialConfig); steal.config = function(cfg){ if(typeof cfg === "string") { return this.loader[cfg]; } else { this.loader.config(cfg); } }; // Steal Env Extension // adds some special environment functions to the loader addStealExtension(function (loader) { loader.getEnv = function(){ var envParts = (this.env || "").split("-"); // Fallback to this.env for legacy return envParts[1] || this.env; }; loader.getPlatform = function(){ var envParts = (this.env || "").split("-"); return envParts.length === 2 ? envParts[0] : undefined; }; loader.isEnv = function(name){ return this.getEnv() === name; }; loader.isPlatform = function(name){ return this.getPlatform() === name; }; }); // get config by the URL query // like ?main=foo&env=production // formally used for Webworkers var getQueryOptions = function(url) { var queryOptions = {}, urlRegEx = /Url$/, urlParts = url.split("?"), path = urlParts.shift(), search = urlParts.join("?"), searchParts = search.split("&"), paths = path.split("/"), lastPart = paths.pop(), stealPath = paths.join("/"); if(searchParts.length && searchParts[0].length) { var searchPart; for(var i =0; i < searchParts.length; i++) { searchPart = searchParts[i]; var paramParts = searchPart.split("="); if(paramParts.length > 1) { var optionName = camelize(paramParts[0]); // make options uniform e.g. baseUrl => baseURL optionName = optionName.replace(urlRegEx, "URL") queryOptions[optionName] = paramParts.slice(1).join("="); } } } return queryOptions; }; // extract the script tag options var getScriptOptions = function (script) { var scriptOptions = {}, urlRegEx = /Url$/; scriptOptions.stealURL = script.src; each(script.attributes, function(attr){ var nodeName = attr.nodeName || attr.name; // get option, remove "data" and camelize var optionName = camelize( nodeName.indexOf("data-") === 0 ? nodeName.replace("data-","") : nodeName ); // make options uniform e.g. baseUrl => baseURL optionName = optionName.replace(urlRegEx, "URL") scriptOptions[optionName] = (attr.value === "") ? true : attr.value; }); // main source within steals script is deprecated // and will be removed in future releases var source = script.innerHTML; if(/\S/.test(source)){ scriptOptions.mainSource = source; } // script config ever wins! return extend(getQueryOptions(script.src), scriptOptions); }; // get steal URL // if we are in a browser, we need to know which script is steal // to extract the script tag options => getScriptOptions() var getUrlOptions = function (){ return new Promise(function(resolve, reject){ // for Workers get options from steal query if (isWebWorker) { resolve(extend({ stealURL: location.href }, getQueryOptions(location.href))); return; } else if(isBrowserWithWindow || isNW || isElectron) { // if the browser supports currentScript, use it! if (document.currentScript) { // get options from script tag and query resolve(getScriptOptions(document.currentScript)); return; } // assume the last script on the page is the one loading steal.js else { var scripts = document.scripts; if (scripts.length) { resolve(getScriptOptions(scripts[scripts.length - 1])); } } } else { // or the only option is where steal is. resolve({ stealPath: __dirname }); } }) }; // configure and startup steal // load the main module(s) if everything is configured steal.startup = function(startupConfig){ var steal = this; var loader = this.loader; var configResolve; var configReject; configPromise = new Promise(function(resolve, reject){ configResolve = resolve; configReject = reject; }); appPromise = getUrlOptions().then(function(urlOptions) { var config; if (typeof startupConfig === 'object') { // the url options are the source of truth config = extend(startupConfig, urlOptions); } else { config = urlOptions; } // set the config loader.config(config); setEnvsConfig.call(loader); // we only load things with force = true if (loader.loadBundles) { if (!loader.main && loader.isEnv("production") && !loader.stealBundled) { // prevent this warning from being removed by Uglify warn("Attribute 'main' is required in production environment. Please add it to the script tag."); } loader["import"](loader.configMain) .then(configResolve, configReject); return configPromise.then(function (cfg) { setEnvsConfig.call(loader); loader._configLoaded = true; return loader.main ? loader["import"](loader.main) : cfg; }); } else { // devBundle includes the same modules as "depsBundle and it also // includes the @config graph, so it should be loaded before of // configMain loader["import"](loader.devBundle) .then(function() { return loader["import"](loader.configMain); }) .then(function() { // depsBundle includes the dependencies in the node_modules // folder so it has to be loaded after configMain finished // loading return loader["import"](loader.depsBundle); }) .then(configResolve, configReject); devPromise = configPromise.then(function () { setEnvsConfig.call(loader); setupLiveReload.call(loader); loader._configLoaded = true; // If a configuration was passed to startup we'll use that to overwrite // what was loaded in stealconfig.js // This means we call it twice, but that's ok if (config) { loader.config(config); } return loader["import"]("@dev"); }); return devPromise.then(function () { // if there's a main, get it, otherwise, we are just loading // the config. if (!loader.main || loader.localLoader) { return configPromise; } var main = loader.main; if (typeof main === "string") { main = [main]; } return Promise.all(map(main, function (main) { return loader["import"](main); })); }); } }).then(function(main){ if(loader.mainSource) { return loader.module(loader.mainSource); } // load script modules they are tagged as // text/steal-module loader.loadScriptModules(); return main; }); return appPromise; }; steal.done = function(){ return appPromise; }; System.setContextual("@node-require", function(name){ if(isNode) { var nodeRequire = require; var load = {name: name, metadata: {}}; return this.locate(load).then(function(address){ var url = address.replace("file:", ""); return { "default": function(specifier){ var resolve = nodeRequire("resolve"); var res = resolve.sync(specifier, { basedir: nodeRequire("path").dirname(url) }); return nodeRequire(res); }, __useDefault: true }; }); } else { return { "default": function(){}, __useDefault: true } } }); steal["import"] = function(){ var names = arguments; var loader = this.System; function afterConfig(){ var imports = []; each(names, function(name){ imports.push(loader["import"](name)); }); if(imports.length > 1) { return Promise.all(imports); } else { return imports[0]; } } if(!configPromise) { // In Node a main isn't required, but we still want // to call startup() to do autoconfiguration, // so setting to empty allows this to work. if(!loader.main) { loader.main = "@empty"; } steal.startup(); } return configPromise.then(afterConfig); }; steal.setContextual = fBind.call(System.setContextual, System); steal.isEnv = fBind.call(System.isEnv, System); steal.isPlatform = fBind.call(System.isPlatform, System); return steal; }; /* * StealJS base extension * * **src/base/base.js** is an autogenerated file; any change should be * made to the source files in **src/base/lib/*.js** */ (function($__global) { $__global.upgradeSystemLoader = function() { $__global.upgradeSystemLoader = undefined; // indexOf polyfill for IE var indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) if (this[i] === item) return i; return -1; } var isWindows = typeof process != 'undefined' && !!process.platform.match(/^win/); // Absolute URL parsing, from https://gist.github.com/Yaffle/1088850 function parseURI(url) { var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@\/?#]*(?::[^:@\/?#]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); // authority = '//' + user + ':' + pass '@' + hostname + ':' port return (m ? { href : m[0] || '', protocol : m[1] || '', authority: m[2] || '', host : m[3] || '', hostname : m[4] || '', port : m[5] || '', pathname : m[6] || '', search : m[7] || '', hash : m[8] || '' } : null); } function toAbsoluteURL(inBase, inHref) { var base = inBase; var href = inHref; function removeDotSegments(input) { var output = []; input.replace(/^(\.\.?(\/|$))+/, '') .replace(/\/(\.(\/|$))+/g, '/') .replace(/\/\.\.$/, '/../') .replace(/\/?[^\/]*/g, function (p) { if (p === '/..') output.pop(); else output.push(p); }); return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); } if (isWindows) href = href.replace(/\\/g, '/'); href = parseURI(href || ''); base = parseURI(base || ''); return !href || !base ? null : (href.protocol || base.protocol) + (href.protocol || href.authority ? href.authority : base.authority) + removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) + (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + href.hash; } // clone the original System loader var System; (function() { var originalSystem = $__global.System; System = $__global.System = new LoaderPolyfill(originalSystem); System.baseURL = originalSystem.baseURL; System.paths = { '*': '*.js' }; System.originalSystem = originalSystem; })(); System.noConflict = function() { $__global.SystemJS = System; $__global.System = System.originalSystem; } var getOwnPropertyDescriptor = true; try { Object.getOwnPropertyDescriptor({ a: 0 }, 'a'); } catch(e) { getOwnPropertyDescriptor = false; } var defineProperty; (function () { try { if (!!Object.defineProperty({}, 'a', {})) defineProperty = Object.defineProperty; } catch (e) { defineProperty = function(obj, prop, opt) { try { obj[prop] = opt.value || opt.get.call(obj); } catch(e) {} } } })(); // converts any module.exports object into an object ready for SystemJS.newModule function getESModule(exports) { var esModule = {}; // don't trigger getters/setters in environments that support them if ((typeof exports == 'object' || typeof exports == 'function') && exports !== $__global) { if (getOwnPropertyDescriptor) { for (var p in exports) { // The default property is copied to esModule later on if (p === 'default') continue; defineOrCopyProperty(esModule, exports, p); } } else { extend(esModule, exports); } } esModule['default'] = exports; definePrope