Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 1 | /** |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 2 | * @license almond 0.3.3 Copyright jQuery Foundation and other contributors. |
| 3 | * Released under MIT license, http://github.com/requirejs/almond/LICENSE |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 4 | */ |
| 5 | //Going sloppy to avoid 'use strict' string cost, but strict practices should |
| 6 | //be followed. |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 7 | /*global setTimeout: false */ |
| 8 | |
| 9 | var requirejs, require, define; |
| 10 | (function (undef) { |
| 11 | var main, req, makeMap, handlers, |
| 12 | defined = {}, |
| 13 | waiting = {}, |
| 14 | config = {}, |
| 15 | defining = {}, |
| 16 | hasOwn = Object.prototype.hasOwnProperty, |
| 17 | aps = [].slice, |
| 18 | jsSuffixRegExp = /\.js$/; |
| 19 | |
| 20 | function hasProp(obj, prop) { |
| 21 | return hasOwn.call(obj, prop); |
| 22 | } |
| 23 | |
| 24 | /** |
| 25 | * Given a relative module name, like ./something, normalize it to |
| 26 | * a real name that can be mapped to a path. |
| 27 | * @param {String} name the relative name |
| 28 | * @param {String} baseName a real name that the name arg is relative |
| 29 | * to. |
| 30 | * @returns {String} normalized name |
| 31 | */ |
| 32 | function normalize(name, baseName) { |
| 33 | var nameParts, nameSegment, mapValue, foundMap, lastIndex, |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 34 | foundI, foundStarMap, starI, i, j, part, normalizedBaseParts, |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 35 | baseParts = baseName && baseName.split("/"), |
| 36 | map = config.map, |
| 37 | starMap = (map && map['*']) || {}; |
| 38 | |
| 39 | //Adjust any relative paths. |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 40 | if (name) { |
| 41 | name = name.split('/'); |
| 42 | lastIndex = name.length - 1; |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 43 | |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 44 | // If wanting node ID compatibility, strip .js from end |
| 45 | // of IDs. Have to do this here, and not in nameToUrl |
| 46 | // because node allows either .js or non .js to map |
| 47 | // to same file. |
| 48 | if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { |
| 49 | name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); |
| 50 | } |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 51 | |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 52 | // Starts with a '.' so need the baseName |
| 53 | if (name[0].charAt(0) === '.' && baseParts) { |
| 54 | //Convert baseName to array, and lop off the last part, |
| 55 | //so that . matches that 'directory' and not name of the baseName's |
| 56 | //module. For instance, baseName of 'one/two/three', maps to |
| 57 | //'one/two/three.js', but we want the directory, 'one/two' for |
| 58 | //this normalization. |
| 59 | normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); |
| 60 | name = normalizedBaseParts.concat(name); |
| 61 | } |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 62 | |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 63 | //start trimDots |
| 64 | for (i = 0; i < name.length; i++) { |
| 65 | part = name[i]; |
| 66 | if (part === '.') { |
| 67 | name.splice(i, 1); |
| 68 | i -= 1; |
| 69 | } else if (part === '..') { |
| 70 | // If at the start, or previous value is still .., |
| 71 | // keep them so that when converted to a path it may |
| 72 | // still work when converted to a path, even though |
| 73 | // as an ID it is less than ideal. In larger point |
| 74 | // releases, may be better to just kick out an error. |
| 75 | if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') { |
| 76 | continue; |
| 77 | } else if (i > 0) { |
| 78 | name.splice(i - 1, 2); |
| 79 | i -= 2; |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 80 | } |
| 81 | } |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 82 | } |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 83 | //end trimDots |
| 84 | |
| 85 | name = name.join('/'); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | //Apply map config if available. |
| 89 | if ((baseParts || starMap) && map) { |
| 90 | nameParts = name.split('/'); |
| 91 | |
| 92 | for (i = nameParts.length; i > 0; i -= 1) { |
| 93 | nameSegment = nameParts.slice(0, i).join("/"); |
| 94 | |
| 95 | if (baseParts) { |
| 96 | //Find the longest baseName segment match in the config. |
| 97 | //So, do joins on the biggest to smallest lengths of baseParts. |
| 98 | for (j = baseParts.length; j > 0; j -= 1) { |
| 99 | mapValue = map[baseParts.slice(0, j).join('/')]; |
| 100 | |
| 101 | //baseName segment has config, find if it has one for |
| 102 | //this name. |
| 103 | if (mapValue) { |
| 104 | mapValue = mapValue[nameSegment]; |
| 105 | if (mapValue) { |
| 106 | //Match, update name to the new value. |
| 107 | foundMap = mapValue; |
| 108 | foundI = i; |
| 109 | break; |
| 110 | } |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | if (foundMap) { |
| 116 | break; |
| 117 | } |
| 118 | |
| 119 | //Check for a star map match, but just hold on to it, |
| 120 | //if there is a shorter segment match later in a matching |
| 121 | //config, then favor over this star map. |
| 122 | if (!foundStarMap && starMap && starMap[nameSegment]) { |
| 123 | foundStarMap = starMap[nameSegment]; |
| 124 | starI = i; |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | if (!foundMap && foundStarMap) { |
| 129 | foundMap = foundStarMap; |
| 130 | foundI = starI; |
| 131 | } |
| 132 | |
| 133 | if (foundMap) { |
| 134 | nameParts.splice(0, foundI, foundMap); |
| 135 | name = nameParts.join('/'); |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | return name; |
| 140 | } |
| 141 | |
| 142 | function makeRequire(relName, forceSync) { |
| 143 | return function () { |
| 144 | //A version of a require function that passes a moduleName |
| 145 | //value for items that may need to |
| 146 | //look up paths relative to the moduleName |
| 147 | var args = aps.call(arguments, 0); |
| 148 | |
| 149 | //If first arg is not require('string'), and there is only |
| 150 | //one arg, it is the array form without a callback. Insert |
| 151 | //a null so that the following concat is correct. |
| 152 | if (typeof args[0] !== 'string' && args.length === 1) { |
| 153 | args.push(null); |
| 154 | } |
| 155 | return req.apply(undef, args.concat([relName, forceSync])); |
| 156 | }; |
| 157 | } |
| 158 | |
| 159 | function makeNormalize(relName) { |
| 160 | return function (name) { |
| 161 | return normalize(name, relName); |
| 162 | }; |
| 163 | } |
| 164 | |
| 165 | function makeLoad(depName) { |
| 166 | return function (value) { |
| 167 | defined[depName] = value; |
| 168 | }; |
| 169 | } |
| 170 | |
| 171 | function callDep(name) { |
| 172 | if (hasProp(waiting, name)) { |
| 173 | var args = waiting[name]; |
| 174 | delete waiting[name]; |
| 175 | defining[name] = true; |
| 176 | main.apply(undef, args); |
| 177 | } |
| 178 | |
| 179 | if (!hasProp(defined, name) && !hasProp(defining, name)) { |
| 180 | throw new Error('No ' + name); |
| 181 | } |
| 182 | return defined[name]; |
| 183 | } |
| 184 | |
| 185 | //Turns a plugin!resource to [plugin, resource] |
| 186 | //with the plugin being undefined if the name |
| 187 | //did not have a plugin prefix. |
| 188 | function splitPrefix(name) { |
| 189 | var prefix, |
| 190 | index = name ? name.indexOf('!') : -1; |
| 191 | if (index > -1) { |
| 192 | prefix = name.substring(0, index); |
| 193 | name = name.substring(index + 1, name.length); |
| 194 | } |
| 195 | return [prefix, name]; |
| 196 | } |
| 197 | |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 198 | //Creates a parts array for a relName where first part is plugin ID, |
| 199 | //second part is resource ID. Assumes relName has already been normalized. |
| 200 | function makeRelParts(relName) { |
| 201 | return relName ? splitPrefix(relName) : []; |
| 202 | } |
| 203 | |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 204 | /** |
| 205 | * Makes a name map, normalizing the name, and using a plugin |
| 206 | * for normalization if necessary. Grabs a ref to plugin |
| 207 | * too, as an optimization. |
| 208 | */ |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 209 | makeMap = function (name, relParts) { |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 210 | var plugin, |
| 211 | parts = splitPrefix(name), |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 212 | prefix = parts[0], |
| 213 | relResourceName = relParts[1]; |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 214 | |
| 215 | name = parts[1]; |
| 216 | |
| 217 | if (prefix) { |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 218 | prefix = normalize(prefix, relResourceName); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 219 | plugin = callDep(prefix); |
| 220 | } |
| 221 | |
| 222 | //Normalize according |
| 223 | if (prefix) { |
| 224 | if (plugin && plugin.normalize) { |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 225 | name = plugin.normalize(name, makeNormalize(relResourceName)); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 226 | } else { |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 227 | name = normalize(name, relResourceName); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 228 | } |
| 229 | } else { |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 230 | name = normalize(name, relResourceName); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 231 | parts = splitPrefix(name); |
| 232 | prefix = parts[0]; |
| 233 | name = parts[1]; |
| 234 | if (prefix) { |
| 235 | plugin = callDep(prefix); |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | //Using ridiculous property names for space reasons |
| 240 | return { |
| 241 | f: prefix ? prefix + '!' + name : name, //fullName |
| 242 | n: name, |
| 243 | pr: prefix, |
| 244 | p: plugin |
| 245 | }; |
| 246 | }; |
| 247 | |
| 248 | function makeConfig(name) { |
| 249 | return function () { |
| 250 | return (config && config.config && config.config[name]) || {}; |
| 251 | }; |
| 252 | } |
| 253 | |
| 254 | handlers = { |
| 255 | require: function (name) { |
| 256 | return makeRequire(name); |
| 257 | }, |
| 258 | exports: function (name) { |
| 259 | var e = defined[name]; |
| 260 | if (typeof e !== 'undefined') { |
| 261 | return e; |
| 262 | } else { |
| 263 | return (defined[name] = {}); |
| 264 | } |
| 265 | }, |
| 266 | module: function (name) { |
| 267 | return { |
| 268 | id: name, |
| 269 | uri: '', |
| 270 | exports: defined[name], |
| 271 | config: makeConfig(name) |
| 272 | }; |
| 273 | } |
| 274 | }; |
| 275 | |
| 276 | main = function (name, deps, callback, relName) { |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 277 | var cjsModule, depName, ret, map, i, relParts, |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 278 | args = [], |
| 279 | callbackType = typeof callback, |
| 280 | usingExports; |
| 281 | |
| 282 | //Use name if no relName |
| 283 | relName = relName || name; |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 284 | relParts = makeRelParts(relName); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 285 | |
| 286 | //Call the callback to define the module, if necessary. |
| 287 | if (callbackType === 'undefined' || callbackType === 'function') { |
| 288 | //Pull out the defined dependencies and pass the ordered |
| 289 | //values to the callback. |
| 290 | //Default to [require, exports, module] if no deps |
| 291 | deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; |
| 292 | for (i = 0; i < deps.length; i += 1) { |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 293 | map = makeMap(deps[i], relParts); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 294 | depName = map.f; |
| 295 | |
| 296 | //Fast path CommonJS standard dependencies. |
| 297 | if (depName === "require") { |
| 298 | args[i] = handlers.require(name); |
| 299 | } else if (depName === "exports") { |
| 300 | //CommonJS module spec 1.1 |
| 301 | args[i] = handlers.exports(name); |
| 302 | usingExports = true; |
| 303 | } else if (depName === "module") { |
| 304 | //CommonJS module spec 1.1 |
| 305 | cjsModule = args[i] = handlers.module(name); |
| 306 | } else if (hasProp(defined, depName) || |
| 307 | hasProp(waiting, depName) || |
| 308 | hasProp(defining, depName)) { |
| 309 | args[i] = callDep(depName); |
| 310 | } else if (map.p) { |
| 311 | map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); |
| 312 | args[i] = defined[depName]; |
| 313 | } else { |
| 314 | throw new Error(name + ' missing ' + depName); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | ret = callback ? callback.apply(defined[name], args) : undefined; |
| 319 | |
| 320 | if (name) { |
| 321 | //If setting exports via "module" is in play, |
| 322 | //favor that over return value and exports. After that, |
| 323 | //favor a non-undefined return value over exports use. |
| 324 | if (cjsModule && cjsModule.exports !== undef && |
| 325 | cjsModule.exports !== defined[name]) { |
| 326 | defined[name] = cjsModule.exports; |
| 327 | } else if (ret !== undef || !usingExports) { |
| 328 | //Use the return value from the function. |
| 329 | defined[name] = ret; |
| 330 | } |
| 331 | } |
| 332 | } else if (name) { |
| 333 | //May just be an object definition for the module. Only |
| 334 | //worry about defining if have a module name. |
| 335 | defined[name] = callback; |
| 336 | } |
| 337 | }; |
| 338 | |
| 339 | requirejs = require = req = function (deps, callback, relName, forceSync, alt) { |
| 340 | if (typeof deps === "string") { |
| 341 | if (handlers[deps]) { |
| 342 | //callback in this case is really relName |
| 343 | return handlers[deps](callback); |
| 344 | } |
| 345 | //Just return the module wanted. In this scenario, the |
| 346 | //deps arg is the module name, and second arg (if passed) |
| 347 | //is just the relName. |
| 348 | //Normalize module name, if it contains . or .. |
Akron | d666fbb | 2018-02-12 10:38:49 +0100 | [diff] [blame] | 349 | return callDep(makeMap(deps, makeRelParts(callback)).f); |
Nils Diewald | 0e6992a | 2015-04-14 20:13:52 +0000 | [diff] [blame] | 350 | } else if (!deps.splice) { |
| 351 | //deps is a config object, not an array. |
| 352 | config = deps; |
| 353 | if (config.deps) { |
| 354 | req(config.deps, config.callback); |
| 355 | } |
| 356 | if (!callback) { |
| 357 | return; |
| 358 | } |
| 359 | |
| 360 | if (callback.splice) { |
| 361 | //callback is an array, which means it is a dependency list. |
| 362 | //Adjust args if there are dependencies |
| 363 | deps = callback; |
| 364 | callback = relName; |
| 365 | relName = null; |
| 366 | } else { |
| 367 | deps = undef; |
| 368 | } |
| 369 | } |
| 370 | |
| 371 | //Support require(['a']) |
| 372 | callback = callback || function () {}; |
| 373 | |
| 374 | //If relName is a function, it is an errback handler, |
| 375 | //so remove it. |
| 376 | if (typeof relName === 'function') { |
| 377 | relName = forceSync; |
| 378 | forceSync = alt; |
| 379 | } |
| 380 | |
| 381 | //Simulate async callback; |
| 382 | if (forceSync) { |
| 383 | main(undef, deps, callback, relName); |
| 384 | } else { |
| 385 | //Using a non-zero value because of concern for what old browsers |
| 386 | //do, and latest browsers "upgrade" to 4 if lower value is used: |
| 387 | //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: |
| 388 | //If want a value immediately, use require('id') instead -- something |
| 389 | //that works in almond on the global level, but not guaranteed and |
| 390 | //unlikely to work in other AMD implementations. |
| 391 | setTimeout(function () { |
| 392 | main(undef, deps, callback, relName); |
| 393 | }, 4); |
| 394 | } |
| 395 | |
| 396 | return req; |
| 397 | }; |
| 398 | |
| 399 | /** |
| 400 | * Just drops the config on the floor, but returns req in case |
| 401 | * the config return value is used. |
| 402 | */ |
| 403 | req.config = function (cfg) { |
| 404 | return req(cfg); |
| 405 | }; |
| 406 | |
| 407 | /** |
| 408 | * Expose module registry for debugging and tooling |
| 409 | */ |
| 410 | requirejs._defined = defined; |
| 411 | |
| 412 | define = function (name, deps, callback) { |
| 413 | if (typeof name !== 'string') { |
| 414 | throw new Error('See almond README: incorrect module build, no module name'); |
| 415 | } |
| 416 | |
| 417 | //This module may not have dependencies |
| 418 | if (!deps.splice) { |
| 419 | //deps is not an array, so probably means |
| 420 | //an object literal or factory function for |
| 421 | //the value. Adjust args. |
| 422 | callback = deps; |
| 423 | deps = []; |
| 424 | } |
| 425 | |
| 426 | if (!hasProp(defined, name) && !hasProp(waiting, name)) { |
| 427 | waiting[name] = [name, deps, callback]; |
| 428 | } |
| 429 | }; |
| 430 | |
| 431 | define.amd = { |
| 432 | jQuery: true |
| 433 | }; |
| 434 | }()); |