text: /** @license MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
  
  /**
   * curl (cujo resource loader)
   * An AMD-compliant javascript module and resource loader
   *
   * curl is part of the cujo.js family of libraries (http://cujojs.com/)
   *
   * Licensed under the MIT License at:
   * 		http://www.opensource.org/licenses/mit-license.php
   *
   */
  (function (global) {
  //"use strict"; don't restore this until the config routine is refactored
  	var
  		version = '0.8.8',
  		curlName = 'curl',
  		defineName = 'define',
  		bootScriptAttr = 'data-curl-run',
  		bootScript,
  		userCfg,
  		prevCurl,
  		prevDefine,
  		doc = global.document,
  		head = doc && (doc['head'] || doc.getElementsByTagName('head')[0]),
  		// to keep IE from crying, we need to put scripts before any
  		// <base> elements, but after any <meta>. this should do it:
  		insertBeforeEl = head && head.getElementsByTagName('base')[0] || null,
  		// constants / flags
  		msgUsingExports = {},
  		msgFactoryExecuted = {},
  		// this is the list of scripts that IE is loading. one of these will
  		// be the "interactive" script. too bad IE doesn't send a readystatechange
  		// event to tell us exactly which one.
  		activeScripts = {},
  		// readyStates for IE6-9
  		readyStates = 'addEventListener' in global ? {} : { 'loaded': 1, 'complete': 1 },
  		// these are always handy :)
  		cleanPrototype = {},
  		toString = cleanPrototype.toString,
  		undef,
  		// local cache of resource definitions (lightweight promises)
  		cache = {},
  		// local url cache
  		urlCache = {},
  		// preload are files that must be loaded before any others
  		preload = false,
  		// net to catch anonymous define calls' arguments (non-IE browsers)
  		argsNet,
  		// RegExp's used later, pre-compiled here
  		dontAddExtRx = /\?|\.js\b/,
  		absUrlRx = /^\/|^[^:]+:\/\//,
  		findDotsRx = /(\.)(\.?)(?:$|\/([^\.\/]+.*)?)/g,
  		removeCommentsRx = /\/\*[\s\S]*?\*\/|\/\/.*?[\n\r]/g,
  		findRValueRequiresRx = /require\s*\(\s*(["'])(.*?[^\\])\1\s*\)|[^\\]?(["'])/g,
  		splitCommaSepRx = /\s*,\s*/,
  		cjsGetters,
  		core;
  
  	function noop () {}
  
  	function isType (obj, type) {
  		return toString.call(obj).indexOf('[object ' + type) == 0;
  	}
  
  	function normalizePkgDescriptor (descriptor, isPkg) {
  		var main;
  
  		descriptor.path = removeEndSlash(descriptor['path'] || descriptor['location'] || '');
  		if (isPkg) {
  			main = descriptor['main'] || './main';
  			if (!isRelUrl(main)) main = './' + main;
  			// trailing slashes trick reduceLeadingDots to see them as base ids
  			descriptor.main = reduceLeadingDots(main, descriptor.name + '/');
  		}
  		descriptor.config = descriptor['config'];
  
  		return descriptor;
  	}
  
  	function isRelUrl (it) {
  		return it.charAt(0) == '.';
  	}
  
  	function isAbsUrl (it) {
  		return absUrlRx.test(it);
  	}
  
  	function joinPath (path, file) {
  		return removeEndSlash(path) + '/' + file;
  	}
  
  	function removeEndSlash (path) {
  		return path && path.charAt(path.length - 1) == '/' ? path.substr(0, path.length - 1) : path;
  	}
  
  	function reduceLeadingDots (childId, baseId) {
  		// this algorithm is similar to dojo's compactPath, which interprets
  		// module ids of "." and ".." as meaning "grab the module whose name is
  		// the same as my folder or parent folder".  These special module ids
  		// are not included in the AMD spec but seem to work in node.js, too.
  		var removeLevels, normId, levels, isRelative, diff;
  
  		removeLevels = 1;
  		normId = childId;
  
  		// remove leading dots and count levels
  		if (isRelUrl(normId)) {
  			isRelative = true;
  			normId = normId.replace(findDotsRx, function (m, dot, doubleDot, remainder) {
  				if (doubleDot) removeLevels++;
  				return remainder || '';
  			});
  		}
  
  		if (isRelative) {
  			levels = baseId.split('/');
  			diff = levels.length - removeLevels;
  			if (diff < 0) {
  				// this is an attempt to navigate above parent module.
  				// maybe dev wants a url or something. punt and return url;
  				return childId;
  			}
  			levels.splice(diff, removeLevels);
  			// normId || [] prevents concat from adding extra "/" when
  			// normId is reduced to a blank string
  			return levels.concat(normId || []).join('/');
  		}
  		else {
  			return normId;
  		}
  	}
  
  	function pluginParts (id) {
  		var delPos = id.indexOf('!');
  		return {
  			resourceId: id.substr(delPos + 1),
  			// resourceId can be zero length
  			pluginId: delPos >= 0 && id.substr(0, delPos)
  		};
  	}
  
  	function Begetter () {}
  
  	function beget (parent, mixin) {
  		Begetter.prototype = parent || cleanPrototype;
  		var child = new Begetter();
  		Begetter.prototype = cleanPrototype;
  		for (var p in mixin) child[p] = mixin[p];
  		return child;
  	}
  
  	function Promise () {
  
  		var self, thens, complete;
  
  		self = this;
  		thens = [];
  
  		function then (resolved, rejected, progressed) {
  			// capture calls to callbacks
  			thens.push([resolved, rejected, progressed]);
  		}
  
  		function notify (which, arg) {
  			// complete all callbacks
  			var aThen, cb, i = 0;
  			while ((aThen = thens[i++])) {
  				cb = aThen[which];
  				if (cb) cb(arg);
  			}
  		}
  
  		complete = function promiseComplete (success, arg) {
  			// switch over to sync then()
  			then = success ?
  				function (resolved, rejected) { resolved && resolved(arg); } :
  				function (resolved, rejected) { rejected && rejected(arg); };
  			// we no longer throw during multiple calls to resolve or reject
  			// since we don't really provide useful information anyways.
  			complete = noop;
  			// complete all callbacks
  			notify(success ? 0 : 1, arg);
  			// no more notifications
  			notify = noop;
  			// release memory
  			thens = undef;
  		};
  
  		this.then = function (resolved, rejected, progressed) {
  			then(resolved, rejected, progressed);
  			return self;
  		};
  		this.resolve = function (val) {
  			self.resolved = val;
  			complete(true, val);
  		};
  		this.reject = function (ex) {
  			self.rejected = ex;
  			complete(false, ex);
  		};
  		this.progress = function (msg) {
  			notify(2, msg);
  		}
  
  	}
  
  	function isPromise (o) {
  		return o instanceof Promise || o instanceof CurlApi;
  	}
  
  	function when (promiseOrValue, callback, errback, progback) {
  		// we can't just sniff for then(). if we do, resources that have a
  		// then() method will make dependencies wait!
  		if (isPromise(promiseOrValue)) {
  			return promiseOrValue.then(callback, errback, progback);
  		}
  		else {
  			return callback(promiseOrValue);
  		}
  	}
  
  	/**
  	 * Returns a function that when executed, executes a lambda function,
  	 * but only executes it the number of times stated by howMany.
  	 * When done executing, it executes the completed function. Each callback
  	 * function receives the same parameters that are supplied to the
  	 * returned function each time it executes.  In other words, they
  	 * are passed through.
  	 * @private
  	 * @param howMany {Number} must be greater than zero
  	 * @param lambda {Function} executed each time
  	 * @param completed {Function} only executes once when the counter
  	 *   reaches zero
  	 * @returns {Function}
  	 */
  	function countdown (howMany, lambda, completed) {
  		var result;
  		return function () {
  			if (--howMany >= 0 && lambda) result = lambda.apply(undef, arguments);
  			// we want ==, not <=, since some callers expect call-once functionality
  			if (howMany == 0 && completed) completed(result);
  			return result;
  		}
  	}
  
  	core = {
  
  		/**
  		 * * reduceLeadingDots of id against parentId
  		 *		- if there are too many dots (path goes beyond parent), it's a url
  		 *			- return reduceLeadingDots of id against baseUrl + parentId;
  		 *	* if id is a url (starts with dots or slash or protocol)
  		 *		- pathInfo = { config: userCfg, url: url }
  		 *	* if not a url, id-to-id transform here.
  		 *		- main module expansion
  		 *		- plugin prefix expansion
  		 *		- coordinate main module expansion with plugin expansion
  		 *			- main module expansion happens first
  		 *		- future: other transforms?
  		 * @param id
  		 * @param parentId
  		 * @param cfg
  		 * @return {*}
  		 */
  		toAbsId: function (id, parentId, cfg) {
  			var absId, pluginId, parts;
  
  			absId = reduceLeadingDots(id, parentId);
  
  			// if this is still a relative path, it must be a url
  			// so just punt, otherwise...
  			if (isRelUrl(absId)) return absId;
  
  			// plugin id split
  			parts = pluginParts(absId);
  			pluginId = parts.pluginId;
  			absId = pluginId || parts.resourceId;
  
  			// main id expansion
  			if (absId in cfg.pathMap) {
  				absId = cfg.pathMap[absId].main || absId;
  			}
  
  			// plugin id expansion
  			if (pluginId) {
  				if (pluginId.indexOf('/') < 0 && !(pluginId in cfg.pathMap)) {
  					absId = joinPath(cfg.pluginPath, pluginId);
  				}
  				absId = absId + '!' + parts.resourceId;
  			}
  
  			return absId;
  		},
  
  		createContext: function (cfg, baseId, depNames, isPreload) {
  
  			var def;
  
  			def = new Promise();
  			def.id = baseId || ''; // '' == global
  			def.isPreload = isPreload;
  			def.depNames = depNames;
  			def.config = cfg;
  
  			// functions that dependencies will use:
  
  			function toAbsId (childId, checkPlugins) {
  				var absId, parts, plugin;
  
  				absId = core.toAbsId(childId, def.id, cfg);
  				if (!checkPlugins) return absId;
  
  				parts = pluginParts(absId);
  				if (!parts.pluginId) return absId;
  
  				plugin = cache[parts.pluginId];
  				// check if plugin supports the normalize method
  				if ('normalize' in plugin) {
  					// note: dojo/has may return falsey values (0, actually)
  					parts.resourceId = plugin['normalize'](parts.resourceId, toAbsId, def.config) || '';
  				}
  				else {
  					parts.resourceId = toAbsId(parts.resourceId);
  				}
  				return parts.pluginId + '!' + parts.resourceId;
  			}
  
  			function toUrl (n) {
  				// the AMD spec states that we should not append an extension
  				// in this function since it could already be appended.
  				// we need to use toAbsId in case this is a module id.
  				return core.resolvePathInfo(toAbsId(n, true), cfg).url;
  			}
  
  			function localRequire (ids, callback, errback) {
  				var cb, rvid, childDef, earlyExport;
  
  				// this is public, so send pure function
  				// also fixes issue #41
  				cb = callback && function () { callback.apply(undef, arguments[0]); };
  
  				// RValue require (CommonJS)
  				if (isType(ids, 'String')) {
  					if (cb) {
  						throw new Error('require(id, callback) not allowed');
  					}
  					// return resource
  					rvid = toAbsId(ids, true);
  					childDef = cache[rvid];
  					if (!(rvid in cache)) {
  						// this should only happen when devs attempt their own
  						// manual wrapping of cjs modules or get confused with
  						// the callback syntax:
  						throw new Error('Module not resolved: '  + rvid);
  					}
  					earlyExport = isPromise(childDef) && childDef.exports;
  					return earlyExport || childDef;
  				}
  				else {
  					when(core.getDeps(core.createContext(cfg, def.id, ids, isPreload)), cb, errback);
  				}
  			}
  
  			def.require = localRequire;
  			localRequire['toUrl'] = toUrl;
  			def.toAbsId = toAbsId;
  
  			return def;
  		},
  
  		createResourceDef: function (cfg, id, isPreload) {
  			var def, origResolve, execute;
  
  			def = core.createContext(cfg, id, undef, isPreload);
  			origResolve = def.resolve;
  
  			// using countdown to only execute definition function once
  			execute = countdown(1, function (deps) {
  				def.deps = deps;
  				try {
  					return core.executeDefFunc(def);
  				}
  				catch (ex) {
  					def.reject(ex);
  				}
  			});
  
  			// intercept resolve function to execute definition function
  			// before resolving
  			def.resolve = function resolve (deps) {
  				when(isPreload || preload, function () {
  					origResolve((cache[def.id] = urlCache[def.url] = execute(deps)));
  				});
  			};
  
  			// track exports
  			def.exportsReady = function executeFactory (deps) {
  				when(isPreload || preload, function () {
  					// only resolve early if we also use exports (to avoid
  					// circular dependencies). def.exports will have already
  					// been set by the getDeps loop before we get here.
  					if (def.exports) {
  						execute(deps);
  						def.progress(msgFactoryExecuted);
  					}
  				});
  			};
  
  			return def;
  		},
  
  		createPluginDef: function (cfg, id, resId, isPreload) {
  			var def;
  
  			// use resource id for local require and toAbsId
  			def = core.createContext(cfg, resId, undef, isPreload);
  
  			return def;
  		},
  
  		getCjsRequire: function (def) {
  			return def.require;
  		},
  
  		getCjsExports: function (def) {
  			return def.exports || (def.exports = {});
  		},
  
  		getCjsModule: function (def) {
  			var module = def.module;
  			if (!module) {
  				module = def.module = {
  					'id': def.id,
  					'uri': core.getDefUrl(def),
  					'exports': core.getCjsExports(def),
  					'config': function () { return def.config; }
  				};
  				module.exports = module['exports']; // oh closure compiler!
  			}
  			return module;
  		},
  
  		getDefUrl: function (def) {
  			// note: this is used by cjs module.uri
  			return def.url || (def.url = core.checkToAddJsExt(def.require['toUrl'](def.id), def.config));
  		},
  
  		/**
  		 * Sets the curl() and define() APIs.
  		 * @param [cfg] {Object|Null} set of config params. If missing or null,
  		 *   this function will set the default API!
  		 */
  		setApi: function (cfg) {
  			/*
  			scenarios:
  			1. global config sets apiName: "require"
  				- first call to config sets api
  				- second and later calls are ignored
  				- prevCurl cannot exist
  			2. no global config, first call to config() sets api
  				- first call to config has no api info
  				- second call to config sets api
  				- third and later calls must be ignored
  			3. global config that doesn't set api, first call does though
  				- same as #2
  			4. api info is never set
  				- how to know when to stop ignoring?
  
  			objectives:
  			1. fail before mistakenly overwriting global[curlName]
  			2. allow rename/relocate of curl() and define()
  			3. restore curl() if we overwrote it
  			 */
  
  			var apiName, defName, apiObj, defObj,
  				failMsg, okToOverwrite;
  
  			apiName = curlName;
  			defName = defineName;
  			apiObj = defObj = global;
  			failMsg = ' already exists';
  
  			// if we're not setting defaults
  			if (cfg) {
  				// is it ok to overwrite existing api functions?
  				okToOverwrite = cfg['overwriteApi'] || cfg.overwriteApi;
  				// allow dev to rename/relocate curl() to another object
  				apiName = cfg['apiName'] || cfg.apiName || apiName;
  				apiObj = cfg['apiContext'] || cfg.apiContext || apiObj;
  				// define() too
  				defName = cfg['defineName'] || cfg.defineName || defName;
  				defObj = cfg['defineContext'] || cfg.defineContext || defObj;
  
  				// curl() already existed, restore it if this is not a
  				// setDefaults pass. dev must be a good citizen and set
  				// apiName/apiContext (see below).
  				if (prevCurl && isType(prevCurl, 'Function')) {
  					// restore previous curl()
  					global[curlName] = prevCurl;
  				}
  				prevCurl = null; // don't check ever again
  				// ditto for define()
  				if (prevDefine && isType(prevDefine, 'Function')) {
  					// restore previous curl()
  					global[defineName] = prevDefine;
  				}
  				prevDefine = null; // don't check ever again
  
  				// check if we're mistakenly overwriting either api
  				// if we're configuring, and there's a curl(), and it's not
  				// ours -- and we're not explicitly overwriting -- throw!
  				// Note: if we're setting defaults, we *must* overwrite curl
  				// so that dev can configure it.  This is no different than
  				// noConflict()-type methods.
  				if (!okToOverwrite) {
  					if (apiObj[apiName] && apiObj[apiName] != _curl) {
  						throw new Error(apiName + failMsg);
  					}
  					// check if we're overwriting amd api
  					if (defObj[defName] && defObj[defName] != define) {
  						throw new Error(defName + failMsg);
  					}
  				}
  
  			}
  
  			// set curl api
  			apiObj[apiName] = _curl;
  
  			// set AMD public api: define()
  			defObj[defName] = define;
  
  		},
  
  		config: function (cfg) {
  			var prevCfg, newCfg, pluginCfgs, p;
  
  			// convert from closure-safe names
  			if ('baseUrl' in cfg) cfg.baseUrl = cfg['baseUrl'];
  			if ('main' in cfg) cfg.main = cfg['main'];
  			if ('preloads' in cfg) cfg.preloads = cfg['preloads'];
  			if ('pluginPath' in cfg) cfg.pluginPath = cfg['pluginPath'];
  			if ('dontAddFileExt' in cfg || cfg.dontAddFileExt) {
  				cfg.dontAddFileExt = new RegExp(cfg['dontAddFileExt'] || cfg.dontAddFileExt);
  			}
  
  			prevCfg = userCfg;
  			newCfg = beget(prevCfg, cfg);
  
  			// create object to hold path map.
  			// each plugin and package will have its own pathMap, too.
  			newCfg.pathMap = beget(prevCfg.pathMap);
  			pluginCfgs = cfg['plugins'] || {};
  			newCfg.plugins = beget(prevCfg.plugins);
  			newCfg.paths = beget(prevCfg.paths, cfg.paths);
  			newCfg.packages = beget(prevCfg.packages, cfg.packages);
  
  			// temporary arrays of paths. this will be converted to
  			// a regexp for fast path parsing.
  			newCfg.pathList = [];
  
  			// normalizes path/package info and places info on either
  			// the global cfg.pathMap or on a plugin-specific altCfg.pathMap.
  			// also populates a pathList on cfg or plugin configs.
  			function fixAndPushPaths (coll, isPkg) {
  				var id, pluginId, data, parts, currCfg, info;
  				for (var name in coll) {
  					data = coll[name];
  					if (isType(data, 'String')) data = {
  						path: coll[name]
  					};
  					// grab the package id, if specified. default to
  					// property name, if missing.
  					data.name = data.name || name;
  					currCfg = newCfg;
  					// check if this is a plugin-specific path
  					parts = pluginParts(removeEndSlash(data.name));
  					id = parts.resourceId;
  					pluginId = parts.pluginId;
  					if (pluginId) {
  						// plugin-specific path
  						currCfg = pluginCfgs[pluginId];
  						if (!currCfg) {
  							currCfg = pluginCfgs[pluginId] = beget(newCfg);
  							currCfg.pathMap = beget(newCfg.pathMap);
  							currCfg.pathList = [];
  						}
  						// remove plugin-specific path from coll
  						delete coll[name];
  					}
  					info = normalizePkgDescriptor(data, isPkg);
  					if (info.config) info.config = beget(newCfg, info.config);
  					info.specificity = id.split('/').length;
  					if (id) {
  						currCfg.pathMap[id] = info;
  						currCfg.pathList.push(id);
  					}
  					else {
  						// naked plugin name signifies baseUrl for plugin
  						// resources. baseUrl could be relative to global
  						// baseUrl.
  						currCfg.baseUrl = core.resolveUrl(data.path, newCfg);
  					}
  				}
  			}
  
  			// adds the path matching regexp onto the cfg or plugin cfgs.
  			function convertPathMatcher (cfg) {
  				var pathMap = cfg.pathMap;
  				cfg.pathRx = new RegExp('^(' +
  					cfg.pathList.sort(function (a, b) { return pathMap[b].specificity - pathMap[a].specificity; } )
  						.join('|')
  						.replace(/\/|\./g, '\\$&') +
  					')(?=\\/|$)'
  				);
  				delete cfg.pathList;
  			}
  
  			// fix all new packages, then paths (in case there are
  			// plugin-specific paths for a main module, such as wire!)
  			fixAndPushPaths(cfg['packages'], true);
  			fixAndPushPaths(cfg['paths'], false);
  
  			// process plugins after packages in case we already perform an
  			// id transform on a plugin (i.e. it's a package.main)
  			for (p in pluginCfgs) {
  				var absId = core.toAbsId(p + '!', '', newCfg);
  				newCfg.plugins[absId.substr(0, absId.length - 1)] = pluginCfgs[p];
  			}
  			pluginCfgs = newCfg.plugins;
  
  			// create search regex for each path map
  			for (p in pluginCfgs) {
  				// inherit full config
  				pluginCfgs[p] = beget(newCfg, pluginCfgs[p]);
  				var pathList = pluginCfgs[p].pathList;
  				if (pathList) {
  					pluginCfgs[p].pathList = pathList.concat(newCfg.pathList);
  					convertPathMatcher(pluginCfgs[p]);
  				}
  			}
  
  			// ugh, this is ugly, but necessary until we refactor this function
  			// copy previous pathMap items onto pathList
  			for (p in prevCfg.pathMap) {
  				if (!newCfg.pathMap.hasOwnProperty(p)) newCfg.pathList.push(p);
  			}
  
  			convertPathMatcher(newCfg);
  
  			return newCfg;
  
  		},
  
  		resolvePathInfo: function (absId, cfg) {
  			// searches through the configured path mappings and packages
  			var pathMap, pathInfo, path, pkgCfg;
  
  			pathMap = cfg.pathMap;
  
  			if (!isAbsUrl(absId)) {
  				path = absId.replace(cfg.pathRx, function (match) {
  					// TODO: remove fallbacks here since they should never need to happen
  					pathInfo = pathMap[match] || {};
  					pkgCfg = pathInfo.config;
  					return pathInfo.path || '';
  				});
  			}
  			else {
  				path = absId;
  			}
  
  			return {
  				config: pkgCfg || userCfg,
  				url: core.resolveUrl(path, cfg)
  			};
  		},
  
  		resolveUrl: function (path, cfg) {
  			var baseUrl = cfg.baseUrl;
  			return baseUrl && !isAbsUrl(path) ? joinPath(baseUrl, path) : path;
  		},
  
  		checkToAddJsExt: function (url, cfg) {
  			// don't add extension if a ? is found in the url (query params)
  			// i'd like to move this feature to a moduleLoader
  			return url + ((cfg || userCfg).dontAddFileExt.test(url) ? '' : '.js');
  		},
  
  		loadScript: function (def, success, failure) {
  			// script processing rules learned from RequireJS
  			// TODO: pass a validate function into loadScript to check if a success really is a success
  
  			// insert script
  			var el = doc.createElement('script');
  
  			// initial script processing
  			function process (ev) {
  				ev = ev || global.event;
  				// detect when it's done loading
  				// ev.type == 'load' is for all browsers except IE6-9
  				// IE6-9 need to use onreadystatechange and look for
  				// el.readyState in {loaded, complete} (yes, we need both)
  				if (ev.type == 'load' || readyStates[el.readyState]) {
  					delete activeScripts[def.id];
  					// release event listeners
  					el.onload = el.onreadystatechange = el.onerror = ''; // ie cries if we use undefined
  					success();
  				}
  			}
  
  			function fail (e) {
  				// some browsers send an event, others send a string,
  				// but none of them send anything useful, so just say we failed:
  				failure(new Error('Syntax or http error: ' + def.url));
  			}
  
  			// set type first since setting other properties could
  			// prevent us from setting this later
  			// actually, we don't even need to set this at all
  			//el.type = 'text/javascript';
  			// using dom0 event handlers instead of wordy w3c/ms
  			el.onload = el.onreadystatechange = process;
  			el.onerror = fail;
  			// js! plugin uses alternate mimetypes
  			el.type = def.mimetype || 'text/javascript';
  			// TODO: support other charsets?
  			el.charset = 'utf-8';
  			el.async = !def.order;
  			el.src = def.url;
  
  			// loading will start when the script is inserted into the dom.
  			// IE will load the script sync if it's in the cache, so
  			// indicate the current resource definition if this happens.
  			activeScripts[def.id] = el;
  
  			head.insertBefore(el, insertBeforeEl);
  
  			// the js! plugin uses this
  			return el;
  		},
  
  		extractCjsDeps: function (defFunc) {
  			// Note: ignores require() inside strings and comments
  			var source, ids = [], currQuote;
  			// prefer toSource (FF) since it strips comments
  			source = typeof defFunc == 'string' ?
  					 defFunc :
  					 defFunc.toSource ? defFunc.toSource() : defFunc.toString();
  			// remove comments, then look for require() or quotes
  			source.replace(removeCommentsRx, '').replace(findRValueRequiresRx, function (m, rq, id, qq) {
  				// if we encounter a string in the source, don't look for require()
  				if (qq) {
  					currQuote = currQuote == qq ? undef : currQuote;
  				}
  				// if we're not inside a quoted string
  				else if (!currQuote) {
  					ids.push(id);
  				}
  				return ''; // uses least RAM/CPU
  			});
  			return ids;
  		},
  
  		fixArgs: function (args) {
  			// resolve args
  			// valid combinations for define:
  			// (string, array, object|function) sax|saf
  			// (array, object|function) ax|af
  			// (string, object|function) sx|sf
  			// (object|function) x|f
  
  			var id, deps, defFunc, defFuncArity, len, cjs;
  
  			len = args.length;
  
  			defFunc = args[len - 1];
  			defFuncArity = isType(defFunc, 'Function') ? defFunc.length : -1;
  
  			if (len == 2) {
  				if (isType(args[0], 'Array')) {
  					deps = args[0];
  				}
  				else {
  					id = args[0];
  				}
  			}
  			else if (len == 3) {
  				id = args[0];
  				deps = args[1];
  			}
  
  			// Hybrid format: assume that a definition function with zero
  			// dependencies and non-zero arity is a wrapped CommonJS module
  			if (!deps && defFuncArity > 0) {
  				cjs = true;
  				deps = ['require', 'exports', 'module'].slice(0, defFuncArity).concat(core.extractCjsDeps(defFunc));
  			}
  
  			return {
  				id: id,
  				deps: deps || [],
  				res: defFuncArity >= 0 ? defFunc : function () { return defFunc; },
  				cjs: cjs
  			};
  		},
  
  		executeDefFunc: function (def) {
  			var resource, moduleThis;
  			// the force of AMD is strong so anything returned
  			// overrides exports.
  			// node.js assumes `this` === `exports` so we do that
  			// for all cjs-wrapped modules, just in case.
  			// also, use module.exports if that was set
  			// (node.js convention).
  			// note: if .module exists, .exports exists.
  			moduleThis = def.cjs ? def.exports : undef;
  			resource = def.res.apply(moduleThis, def.deps);
  			if (resource === undef && def.exports) {
  				// note: exports will equal module.exports unless
  				// module.exports was reassigned inside module.
  				resource = def.module ? (def.exports = def.module.exports) : def.exports;
  			}
  			return resource;
  		},
  
  		defineResource: function (def, args) {
  
  			def.res = args.res;
  			def.cjs = args.cjs;
  			def.depNames = args.deps;
  			core.getDeps(def);
  
  		},
  
  		getDeps: function (parentDef) {
  
  			var i, names, deps, len, dep, completed, name,
  				exportCollector, resolveCollector;
  
  			deps = [];
  			names = parentDef.depNames;
  			len = names.length;
  
  			if (names.length == 0) allResolved();
  
  			function collect (dep, index, alsoExport) {
  				deps[index] = dep;
  				if (alsoExport) exportCollector(dep, index);
  			}
  
  			// reducer-collectors
  			exportCollector = countdown(len, collect, allExportsReady);
  			resolveCollector = countdown(len, collect, allResolved);
  
  			// initiate the resolution of all dependencies
  			// Note: the correct handling of early exports relies on the
  			// fact that the exports pseudo-dependency is always listed
  			// before other module dependencies.
  			for (i = 0; i < len; i++) {
  				name = names[i];
  				// is this "require", "exports", or "module"?
  				if (name in cjsGetters) {
  					// a side-effect of cjsGetters is that the cjs
  					// property is also set on the def.
  					resolveCollector(cjsGetters[name](parentDef), i, true);
  					// if we are using the `module` or `exports` cjs variables,
  					// signal any waiters/parents that we can export
  					// early (see progress callback in getDep below).
  					// note: this may fire for `require` as well, if it
  					// is listed after `module` or `exports` in the deps list,
  					// but that is okay since all waiters will only record
  					// it once.
  					if (parentDef.exports) {
  						parentDef.progress(msgUsingExports);
  					}
  				}
  				// check for blanks. fixes #32.
  				// this helps support yepnope.js, has.js, and the has! plugin
  				else if (!name) {
  					resolveCollector(undef, i, true);
  				}
  				// normal module or plugin resource
  				else {
  					getDep(name, i);
  				}
  			}
  
  			return parentDef;
  
  			function getDep (name, index) {
  				var resolveOnce, exportOnce, childDef, earlyExport;
  
  				resolveOnce = countdown(1, function (dep) {
  					exportOnce(dep);
  					resolveCollector(dep, index);
  				});
  				exportOnce = countdown(1, function (dep) {
  					exportCollector(dep, index);
  				});
  
  				// get child def / dep
  				childDef = core.fetchDep(name, parentDef);
  
  				// check if childDef can export. if it can, then
  				// we missed the notification and it will never fire in the
  				// when() below.
  				earlyExport = isPromise(childDef) && childDef.exports;
  				if (earlyExport) {
  					exportOnce(earlyExport);
  				}
  
  				when(childDef,
  					resolveOnce,
  					parentDef.reject,
  					parentDef.exports && function (msg) {
  						// messages are only sent from childDefs that support
  						// exports, and we only notify parents that understand
  						// exports too.
  						if (childDef.exports) {
  							if (msg == msgUsingExports) {
  								// if we're using exports cjs variable on both sides
  								exportOnce(childDef.exports);
  							}
  							else if (msg == msgFactoryExecuted) {
  								resolveOnce(childDef.exports);
  							}
  						}
  					}
  				);
  			}
  
  			function allResolved () {
  				parentDef.resolve(deps);
  			}
  
  			function allExportsReady () {
  				parentDef.exportsReady && parentDef.exportsReady(deps);
  			}
  
  		},
  
  		fetchResDef: function (def) {
  
  			// ensure url is computed
  			core.getDefUrl(def);
  
  			core.loadScript(def,
  
  				function () {
  					var args = argsNet;
  					argsNet = undef; // reset it before we get deps
  
  					// if our resource was not explicitly defined with an id (anonymous)
  					// Note: if it did have an id, it will be resolved in the define()
  					if (def.useNet !== false) {
  
  						// if !args, nothing was added to the argsNet
  						if (!args || args.ex) {
  							def.reject(new Error(((args && args.ex) || 'define() missing or duplicated: ' + def.url)));
  						}
  						else {
  							core.defineResource(def, args);
  						}
  					}
  
  				},
  
  				def.reject
  
  			);
  
  			return def;
  
  		},
  
  		fetchDep: function (depName, parentDef) {
  			var toAbsId, isPreload, parentCfg, parts, absId, mainId, loaderId, pluginId,
  				resId, pathInfo, def, tempDef, resCfg;
  
  			toAbsId = parentDef.toAbsId;
  			isPreload = parentDef.isPreload;
  			parentCfg = parentDef.config || userCfg; // is this fallback necessary?
  
  			absId = toAbsId(depName);
  
  			if (absId in cache) {
  				// module already exists in cache
  				mainId = absId;
  			}
  			else {
  				// check for plugin loaderId
  				parts = pluginParts(absId);
  				resId = parts.resourceId;
  				// get id of first resource to load (which could be a plugin)
  				mainId = parts.pluginId || resId;
  				pathInfo = core.resolvePathInfo(mainId, parentCfg);
  			}
  
  			if (!(absId in cache)) {
  				resCfg = core.resolvePathInfo(resId, parentCfg).config;
  				if (parts.pluginId) {
  					loaderId = mainId;
  				}
  				else {
  					// get custom module loader from package config if not a plugin
  					// TODO: move config.moduleLoader to config.loader
  					loaderId = resCfg['moduleLoader'] || resCfg.moduleLoader
  						|| resCfg['loader'] || resCfg.loader;
  					if (loaderId) {
  						// TODO: allow transforms to have relative module ids?
  						// (we could do this by returning package location from
  						// resolvePathInfo. why not return all package info?)
  						resId = mainId;
  						mainId = loaderId;
  						pathInfo = core.resolvePathInfo(loaderId, parentCfg);
  					}
  				}
  			}
  
  			if (mainId in cache) {
  				def = cache[mainId];
  			}
  			else if (pathInfo.url in urlCache) {
  				def = cache[mainId] = urlCache[pathInfo.url];
  			}
  			else {
  				def = core.createResourceDef(resCfg, mainId, isPreload);
  				// TODO: can this go inside createResourceDef?
  				// TODO: can we pass pathInfo.url to createResourceDef instead?
  				def.url = core.checkToAddJsExt(pathInfo.url, pathInfo.config);
  				cache[mainId] = urlCache[pathInfo.url] = def;
  				core.fetchResDef(def);
  			}
  
  			// plugin or transformer
  			if (mainId == loaderId) {
  
  				// use plugin's config if specified
  				if (parts.pluginId && parentCfg.plugins[parts.pluginId]) {
  					resCfg = parentCfg.plugins[parts.pluginId];
  				}
  				// we need to use an anonymous promise until plugin tells
  				// us normalized id. then, we need to consolidate the promises
  				// below. Note: exports objects will be different between
  				// pre-normalized and post-normalized defs! does this matter?
  				// don't put this resource def in the cache because if the
  				// resId doesn't change, the check if this is a new
  				// normalizedDef (below) will think it's already being loaded.
  				tempDef = new Promise();
  
  				// wait for plugin resource def
  				when(def, function(plugin) {
  					var normalizedDef, fullId, dynamic;
  
  					dynamic = plugin['dynamic'];
  					// check if plugin supports the normalize method
  					if ('normalize' in plugin) {
  						// note: dojo/has may return falsey values (0, actually)
  						resId = plugin['normalize'](resId, toAbsId, def.config) || '';
  					}
  					else {
  						resId = toAbsId(resId);
  					}
  
  					// use the full id (loaderId + id) to id plugin resources
  					// so multiple plugins may each process the same resource
  					// resId could be blank if the plugin doesn't require any (e.g. "domReady!")
  					fullId = loaderId + '!' + resId;
  					normalizedDef = cache[fullId];
  
  					// if this is our first time fetching this (normalized) def
  					if (!(fullId in cache)) {
  
  						// because we're using resId, plugins, such as wire!,
  						// can use paths relative to the resource
  						normalizedDef = core.createPluginDef(resCfg, fullId, resId, isPreload);
  
  						// don't cache non-determinate "dynamic" resources
  						if (!dynamic) {
  							cache[fullId] = normalizedDef;
  						}
  
  						// curl's plugins prefer to receive a deferred,
  						// but to be compatible with AMD spec, we have to
  						// piggy-back on the callback function parameter:
  						var loaded = function (res) {
  							if (!dynamic) cache[fullId] = res;
  							normalizedDef.resolve(res);
  						};
  						loaded['resolve'] = loaded;
  						loaded['reject'] = loaded['error'] = normalizedDef.reject;
  
  						// load the resource!
  						plugin.load(resId, normalizedDef.require, loaded, resCfg);
  
  					}
  
  					// chain defs (resolve when plugin.load executes)
  					if (tempDef != normalizedDef) {
  						when(normalizedDef, tempDef.resolve, tempDef.reject, tempDef.progress);
  					}
  
  				}, tempDef.reject);
  
  			}
  
  			// return tempDef if this is a plugin-based resource
  			return tempDef || def;
  		},
  
  		getCurrentDefName: function () {
  			// IE6-9 mark the currently executing thread as "interactive"
  			// Note: Opera lies about which scripts are "interactive", so we
  			// just have to test for it. Opera provides a true browser test, not
  			// a UA sniff, thankfully.
  			// learned this trick from James Burke's RequireJS
  			var def;
  			if (!isType(global.opera, 'Opera')) {
  				for (var d in activeScripts) {
  					if (activeScripts[d].readyState == 'interactive') {
  						def = d;
  						break;
  					}
  				}
  			}
  			return def;
  		},
  
  		findScript: function (predicate) {
  			var i = 0, scripts, script;
  			scripts = doc && (doc.scripts || doc.getElementsByTagName('script'));
  			while (scripts && (script = scripts[i++])) {
  				if (predicate(script)) return script;
  			}
  		},
  
  		extractDataAttrConfig: function () {
  			var script, attr = '';
  			script = core.findScript(function (script) {
  				var run;
  				// find data-curl-run attr on script element
  				run = script.getAttribute(bootScriptAttr);
  				if (run) attr = run;
  				return run;
  			});
  			// removeAttribute is wonky (in IE6?) but this works
  			if (script) {
  				script.setAttribute(bootScriptAttr, '');
  			}
  			return attr;
  		},
  
  		bootScript: function () {
  			var urls = bootScript.split(splitCommaSepRx);
  			if (urls.length) {
  				load();
  			}
  			function load () {
  				// Note: IE calls success handler if it gets a 400+.
  				core.loadScript({ url: urls.shift() }, check, check);
  			}
  			function check () {
  				// check if run.js called curl() or curl.config()
  				if (bootScript) {
  					if (urls.length) {
  						// show an error message
  						core.nextTurn(fail);
  						// try next
  						load();
  					}
  					else fail('run.js script did not run.');
  				}
  			}
  			function fail (msg) {
  				throw new Error(msg || 'Primary run.js failed. Trying fallback.');
  			}
  		},
  
  		nextTurn: function (task) {
  			setTimeout(task, 0);
  		}
  
  	};
  
  	// hook-up cjs free variable getters
  	cjsGetters = {'require': core.getCjsRequire, 'exports': core.getCjsExports, 'module': core.getCjsModule};
  
  	function _curl (/* various */) {
  		var args, promise, cfg;
  
  		// indicate we're no longer waiting for a boot script
  		bootScript = '';
  
  		args = [].slice.call(arguments);
  
  		// extract config, if it's specified
  		if (isType(args[0], 'Object')) {
  			cfg = args.shift();
  			promise = _config(cfg);
  		}
  
  		return new CurlApi(args[0], args[1], args[2], promise);
  	}
  
  	function _config (cfg, callback, errback) {
  		var pPromise, main, fallback;
  
  		// indicate we're no longer waiting for a boot script
  		bootScript = '';
  
  		if (cfg) {
  			core.setApi(cfg);
  			userCfg = core.config(cfg);
  			// check for preloads
  			if ('preloads' in cfg) {
  				pPromise = new CurlApi(cfg['preloads'], undef, errback, preload, true);
  				// yes, this is hacky and embarrassing. now that we've got that
  				// settled... until curl has deferred factory execution, this
  				// is the only way to stop preloads from dead-locking when
  				// they have dependencies inside a bundle.
  				core.nextTurn(function () { preload = pPromise; });
  			}
  			// check for main module(s). all modules wait for preloads implicitly.
  			main = cfg['main'];
  			if (main) {
  				return new CurlApi(main, callback, errback);
  			}
  		}
  	}
  
  	// thanks to Joop Ringelberg for helping troubleshoot the API
  	function CurlApi (ids, callback, errback, waitFor, isPreload) {
  		var then, ctx;
  
  		ctx = core.createContext(userCfg, undef, [].concat(ids), isPreload);
  
  		this['then'] = this.then = then = function (resolved, rejected) {
  			when(ctx,
  				// return the dependencies as arguments, not an array
  				function (deps) {
  					if (resolved) resolved.apply(undef, deps);
  				},
  				// just throw if the dev didn't specify an error handler
  				function (ex) {
  					if (rejected) rejected(ex); else throw ex;
  				}
  			);
  			return this;
  		};
  
  		this['next'] = function (ids, cb, eb) {
  			// chain api
  			return new CurlApi(ids, cb, eb, ctx);
  		};
  
  		this['config'] = _config;
  
  		if (callback || errback) then(callback, errback);
  
  		// ensure next-turn so inline code can execute first
  		core.nextTurn(function () {
  			when(isPreload || preload, function () {
  				when(waitFor, function () { core.getDeps(ctx); }, errback);
  			});
  		});
  	}
  
  	_curl['version'] = version;
  	_curl['config'] = _config;
  
  	function _define (args) {
  
  		var id, def, pathInfo;
  
  		id = args.id;
  
  		if (id == undef) {
  			if (argsNet !== undef) {
  				argsNet = { ex: 'Multiple anonymous defines encountered' };
  			}
  			else if (!(id = core.getCurrentDefName())/* intentional assignment */) {
  				// anonymous define(), defer processing until after script loads
  				argsNet = args;
  			}
  		}
  		if (id != undef) {
  			// named define(), it is in the cache if we are loading a dependency
  			// (could also be a secondary define() appearing in a built file, etc.)
  			def = cache[id];
  			if (!(id in cache)) {
  				// id is an absolute id in this case, so we can get the config.
  				pathInfo = core.resolvePathInfo(id, userCfg);
  				def = core.createResourceDef(pathInfo.config, id);
  				cache[id] = def;
  			}
  			if (!isPromise(def)) throw new Error('duplicate define: ' + id);
  			// check if this resource has already been resolved
  			def.useNet = false;
  			core.defineResource(def, args);
  		}
  
  	}
  
  	function define () {
  		// wrap inner _define so it can be replaced without losing define.amd
  		var args = core.fixArgs(arguments);
  		_define(args);
  	}
  
  	// indicate our capabilities:
  	define['amd'] = { 'plugins': true, 'jQuery': true, 'curl': version };
  
  	// default configs
  	userCfg = {
  		baseUrl: '',
  		pluginPath: 'curl/plugin',
  		dontAddFileExt: dontAddExtRx,
  		paths: {},
  		packages: {},
  		plugins: {},
  		pathMap: {},
  		pathRx: /$^/
  	};
  
  	// handle pre-existing global
  	prevCurl = global[curlName];
  	prevDefine = global[defineName];
  
  	// only run config if there is something to config (perf saver?)
  	if (prevCurl && isType(prevCurl, 'Object')) {
  		// remove global curl object
  		global[curlName] = undef; // can't use delete in IE 6-8
  		// configure curl
  		_config(prevCurl);
  	}
  	else {
  		// set default api
  		core.setApi();
  	}
  
  	// look for "data-curl-run" directive
  	bootScript = core.extractDataAttrConfig();
  	// wait a bit in case curl.js is bundled into the boot script
  	if (bootScript) core.nextTurn(core.bootScript);
  
  	// allow curl to be a dependency
  	cache[curlName] = _curl;
  
  	// expose curl core for special plugins and modules
  	// Note: core overrides will only work in either of two scenarios:
  	// 1. the files are running un-compressed (Google Closure or Uglify)
  	// 2. the overriding module was compressed into the same file as curl.js
  	// Compiling curl and the overriding module separately won't work.
  	cache['curl/_privileged'] = {
  		'core': core,
  		'cache': cache,
  		'config': function () { return userCfg; },
  		'_define': _define,
  		'_curl': _curl,
  		'Promise': Promise
  	};
  
  }(this.window || (typeof global != 'undefined' && global) || this));
  /** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
  
  /**
   * curl debug plugin
   *
   * Licensed under the MIT License at:
   * 		http://www.opensource.org/licenses/mit-license.php
   *
   */
  
  /**
   * usage:
   *  curl({ preloads: ['curl/debug'] }, ['my/app'], function (myApp) {
   * 		// do stuff while logging debug messages
   * 	});
   *
   * TODO: warn when main module still has leading dots (normalizePackageDescriptor)
   * TODO: warn when a module id still has leading dots (toAbsId)
   * TODO: use curl/tdd/undefine module instead of quick-and-dirty method below
   * TODO: only add logging to some of the useful core functions
   *
   */
  define('curl/debug', ['require', 'curl/_privileged'], function (require, priv) {
  "use strict";
  
  	var cache, totalWaiting, prevTotal, origDefine;
  
  	if (typeof console == 'undefined') {
  		throw new Error('`console` object must be defined to use debug module.');
  	}
  
  	priv._curl['undefine'] = function (moduleId) { delete cache[moduleId]; };
  
  	cache = priv['cache'];
  
  	// add logging to core functions
  	for (var p in priv['core']) (function (name, orig) {
  		priv['core'][name] = function () {
  			var result;
  			console.log('curl ' + name + ' arguments:', arguments);
  			result = orig.apply(this, arguments);
  			console.log('curl ' + name + ' return:', result);
  			return result;
  		};
  	}(p, priv['core'][p]));
  
  	// add logging to define
  	origDefine = priv._define;
  	priv._define = function () {
  		console.log('curl define:', arguments);
  		return origDefine.apply(this, arguments);
  	};
  
  	// log cache stats periodically
  	totalWaiting = 0;
  
  	function count () {
  		totalWaiting = 0;
  		for (var p in cache) {
  			if (cache[p] instanceof priv['Promise']) totalWaiting++;
  		}
  	}
  	count();
  
  	function periodicLogger () {
  		count();
  		if (prevTotal != totalWaiting) {
  			console.log('curl: ********** modules waiting: ' + totalWaiting);
  			for (var p in cache) {
  				if (cache[p] instanceof priv['Promise']) {
  					console.log('curl: ********** module waiting: ' + p);
  				}
  			}
  		}
  		prevTotal = totalWaiting;
  		setTimeout(periodicLogger, 500);
  	}
  	periodicLogger();
  
  	return true;
  
  });
  