diff options
author | Florian Dold <florian.dold@gmail.com> | 2016-02-29 18:03:02 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2016-02-29 18:03:02 +0100 |
commit | c962e9402123900c53967c14cf809ea10576cdb8 (patch) | |
tree | e7df9cfdd6fceae30fb99c8ec6be5e07c8b153a8 /lib/vendor | |
parent | 30ee3320c788129b258ed8b42f4fc63d28431e2f (diff) |
restructure
Diffstat (limited to 'lib/vendor')
-rw-r--r-- | lib/vendor/URI.js | 2162 | ||||
l--------- | lib/vendor/jed.js | 1 | ||||
-rw-r--r-- | lib/vendor/lodash.core.min.js | 29 | ||||
-rw-r--r-- | lib/vendor/mithril.js | 2132 | ||||
-rw-r--r-- | lib/vendor/system-csp-production.src.js | 4155 |
5 files changed, 8479 insertions, 0 deletions
diff --git a/lib/vendor/URI.js b/lib/vendor/URI.js new file mode 100644 index 000000000..c041b4304 --- /dev/null +++ b/lib/vendor/URI.js @@ -0,0 +1,2162 @@ +/*! + * URI.js - Mutating URLs + * + * Version: 1.17.0 + * + * Author: Rodney Rehm + * Web: http://medialize.github.io/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * GPL v3 http://opensource.org/licenses/GPL-3.0 + * + */ +(function (root, factory) { + 'use strict'; + // https://github.com/umdjs/umd/blob/master/returnExports.js + if (typeof exports === 'object') { + // Node + module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains')); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['./punycode', './IPv6', './SecondLevelDomains'], factory); + } else { + // Browser globals (root is window) + root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root); + } +}(this, function (punycode, IPv6, SLD, root) { + 'use strict'; + /*global location, escape, unescape */ + // FIXME: v2.0.0 renamce non-camelCase properties to uppercase + /*jshint camelcase: false */ + + // save current URI variable, if any + var _URI = root && root.URI; + + function URI(url, base) { + var _urlSupplied = arguments.length >= 1; + var _baseSupplied = arguments.length >= 2; + + // Allow instantiation without the 'new' keyword + if (!(this instanceof URI)) { + if (_urlSupplied) { + if (_baseSupplied) { + return new URI(url, base); + } + + return new URI(url); + } + + return new URI(); + } + + if (url === undefined) { + if (_urlSupplied) { + throw new TypeError('undefined is not a valid argument for URI'); + } + + if (typeof location !== 'undefined') { + url = location.href + ''; + } else { + url = ''; + } + } + + this.href(url); + + // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor + if (base !== undefined) { + return this.absoluteTo(base); + } + + return this; + } + + URI.version = '1.17.0'; + + var p = URI.prototype; + var hasOwn = Object.prototype.hasOwnProperty; + + function escapeRegEx(string) { + // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963 + return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); + } + + function getType(value) { + // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value + if (value === undefined) { + return 'Undefined'; + } + + return String(Object.prototype.toString.call(value)).slice(8, -1); + } + + function isArray(obj) { + return getType(obj) === 'Array'; + } + + function filterArrayValues(data, value) { + var lookup = {}; + var i, length; + + if (getType(value) === 'RegExp') { + lookup = null; + } else if (isArray(value)) { + for (i = 0, length = value.length; i < length; i++) { + lookup[value[i]] = true; + } + } else { + lookup[value] = true; + } + + for (i = 0, length = data.length; i < length; i++) { + /*jshint laxbreak: true */ + var _match = lookup && lookup[data[i]] !== undefined + || !lookup && value.test(data[i]); + /*jshint laxbreak: false */ + if (_match) { + data.splice(i, 1); + length--; + i--; + } + } + + return data; + } + + function arrayContains(list, value) { + var i, length; + + // value may be string, number, array, regexp + if (isArray(value)) { + // Note: this can be optimized to O(n) (instead of current O(m * n)) + for (i = 0, length = value.length; i < length; i++) { + if (!arrayContains(list, value[i])) { + return false; + } + } + + return true; + } + + var _type = getType(value); + for (i = 0, length = list.length; i < length; i++) { + if (_type === 'RegExp') { + if (typeof list[i] === 'string' && list[i].match(value)) { + return true; + } + } else if (list[i] === value) { + return true; + } + } + + return false; + } + + function arraysEqual(one, two) { + if (!isArray(one) || !isArray(two)) { + return false; + } + + // arrays can't be equal if they have different amount of content + if (one.length !== two.length) { + return false; + } + + one.sort(); + two.sort(); + + for (var i = 0, l = one.length; i < l; i++) { + if (one[i] !== two[i]) { + return false; + } + } + + return true; + } + + function trimSlashes(text) { + var trim_expression = /^\/+|\/+$/g; + return text.replace(trim_expression, ''); + } + + URI._parts = function() { + return { + protocol: null, + username: null, + password: null, + hostname: null, + urn: null, + port: null, + path: null, + query: null, + fragment: null, + // state + duplicateQueryParameters: URI.duplicateQueryParameters, + escapeQuerySpace: URI.escapeQuerySpace + }; + }; + // state: allow duplicate query parameters (a=1&a=1) + URI.duplicateQueryParameters = false; + // state: replaces + with %20 (space in query strings) + URI.escapeQuerySpace = true; + // static properties + URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i; + URI.idn_expression = /[^a-z0-9\.-]/i; + URI.punycode_expression = /(xn--)/i; + // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care? + URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; + // credits to Rich Brown + // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 + // specification: http://www.ietf.org/rfc/rfc4291.txt + URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; + // expression used is "gruber revised" (@gruber v2) determined to be the + // best solution in a regex-golf we did a couple of ages ago at + // * http://mathiasbynens.be/demo/url-regex + // * http://rodneyrehm.de/t/url-regex.html + URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig; + URI.findUri = { + // valid "scheme://" or "www." + start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi, + // everything up to the next whitespace + end: /[\s\r\n]|$/, + // trim trailing punctuation captured by end RegExp + trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/ + }; + // http://www.iana.org/assignments/uri-schemes.html + // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports + URI.defaultPorts = { + http: '80', + https: '443', + ftp: '21', + gopher: '70', + ws: '80', + wss: '443' + }; + // allowed hostname characters according to RFC 3986 + // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded + // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - + URI.invalid_hostname_characters = /[^a-zA-Z0-9\.-]/; + // map DOM Elements to their URI attribute + URI.domAttributes = { + 'a': 'href', + 'blockquote': 'cite', + 'link': 'href', + 'base': 'href', + 'script': 'src', + 'form': 'action', + 'img': 'src', + 'area': 'href', + 'iframe': 'src', + 'embed': 'src', + 'source': 'src', + 'track': 'src', + 'input': 'src', // but only if type="image" + 'audio': 'src', + 'video': 'src' + }; + URI.getDomAttribute = function(node) { + if (!node || !node.nodeName) { + return undefined; + } + + var nodeName = node.nodeName.toLowerCase(); + // <input> should only expose src for type="image" + if (nodeName === 'input' && node.type !== 'image') { + return undefined; + } + + return URI.domAttributes[nodeName]; + }; + + function escapeForDumbFirefox36(value) { + // https://github.com/medialize/URI.js/issues/91 + return escape(value); + } + + // encoding / decoding according to RFC3986 + function strictEncodeURIComponent(string) { + // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent + return encodeURIComponent(string) + .replace(/[!'()*]/g, escapeForDumbFirefox36) + .replace(/\*/g, '%2A'); + } + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + URI.iso8859 = function() { + URI.encode = escape; + URI.decode = unescape; + }; + URI.unicode = function() { + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + }; + URI.characters = { + pathname: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig, + map: { + // -._~!'()* + '%24': '$', + '%26': '&', + '%2B': '+', + '%2C': ',', + '%3B': ';', + '%3D': '=', + '%3A': ':', + '%40': '@' + } + }, + decode: { + expression: /[\/\?#]/g, + map: { + '/': '%2F', + '?': '%3F', + '#': '%23' + } + } + }, + reserved: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig, + map: { + // gen-delims + '%3A': ':', + '%2F': '/', + '%3F': '?', + '%23': '#', + '%5B': '[', + '%5D': ']', + '%40': '@', + // sub-delims + '%21': '!', + '%24': '$', + '%26': '&', + '%27': '\'', + '%28': '(', + '%29': ')', + '%2A': '*', + '%2B': '+', + '%2C': ',', + '%3B': ';', + '%3D': '=' + } + } + }, + urnpath: { + // The characters under `encode` are the characters called out by RFC 2141 as being acceptable + // for usage in a URN. RFC2141 also calls out "-", ".", and "_" as acceptable characters, but + // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also + // note that the colon character is not featured in the encoding map; this is because URI.js + // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it + // should not appear unencoded in a segment itself. + // See also the note above about RFC3986 and capitalalized hex digits. + encode: { + expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig, + map: { + '%21': '!', + '%24': '$', + '%27': '\'', + '%28': '(', + '%29': ')', + '%2A': '*', + '%2B': '+', + '%2C': ',', + '%3B': ';', + '%3D': '=', + '%40': '@' + } + }, + // These characters are the characters called out by RFC2141 as "reserved" characters that + // should never appear in a URN, plus the colon character (see note above). + decode: { + expression: /[\/\?#:]/g, + map: { + '/': '%2F', + '?': '%3F', + '#': '%23', + ':': '%3A' + } + } + } + }; + URI.encodeQuery = function(string, escapeQuerySpace) { + var escaped = URI.encode(string + ''); + if (escapeQuerySpace === undefined) { + escapeQuerySpace = URI.escapeQuerySpace; + } + + return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped; + }; + URI.decodeQuery = function(string, escapeQuerySpace) { + string += ''; + if (escapeQuerySpace === undefined) { + escapeQuerySpace = URI.escapeQuerySpace; + } + + try { + return URI.decode(escapeQuerySpace ? string.replace(/\+/g, '%20') : string); + } catch(e) { + // we're not going to mess with weird encodings, + // give up and return the undecoded original string + // see https://github.com/medialize/URI.js/issues/87 + // see https://github.com/medialize/URI.js/issues/92 + return string; + } + }; + // generate encode/decode path functions + var _parts = {'encode':'encode', 'decode':'decode'}; + var _part; + var generateAccessor = function(_group, _part) { + return function(string) { + try { + return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) { + return URI.characters[_group][_part].map[c]; + }); + } catch (e) { + // we're not going to mess with weird encodings, + // give up and return the undecoded original string + // see https://github.com/medialize/URI.js/issues/87 + // see https://github.com/medialize/URI.js/issues/92 + return string; + } + }; + }; + + for (_part in _parts) { + URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]); + URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]); + } + + var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) { + return function(string) { + // Why pass in names of functions, rather than the function objects themselves? The + // definitions of some functions (but in particular, URI.decode) will occasionally change due + // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure + // that the functions we use here are "fresh". + var actualCodingFunc; + if (!_innerCodingFuncName) { + actualCodingFunc = URI[_codingFuncName]; + } else { + actualCodingFunc = function(string) { + return URI[_codingFuncName](URI[_innerCodingFuncName](string)); + }; + } + + var segments = (string + '').split(_sep); + + for (var i = 0, length = segments.length; i < length; i++) { + segments[i] = actualCodingFunc(segments[i]); + } + + return segments.join(_sep); + }; + }; + + // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions. + URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment'); + URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment'); + URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode'); + URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode'); + + URI.encodeReserved = generateAccessor('reserved', 'encode'); + + URI.parse = function(string, parts) { + var pos; + if (!parts) { + parts = {}; + } + // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment] + + // extract fragment + pos = string.indexOf('#'); + if (pos > -1) { + // escaping? + parts.fragment = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + + // extract query + pos = string.indexOf('?'); + if (pos > -1) { + // escaping? + parts.query = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + + // extract protocol + if (string.substring(0, 2) === '//') { + // relative-scheme + parts.protocol = null; + string = string.substring(2); + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + pos = string.indexOf(':'); + if (pos > -1) { + parts.protocol = string.substring(0, pos) || null; + if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) { + // : may be within the path + parts.protocol = undefined; + } else if (string.substring(pos + 1, pos + 3) === '//') { + string = string.substring(pos + 3); + + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + string = string.substring(pos + 1); + parts.urn = true; + } + } + } + + // what's left must be the path + parts.path = string; + + // and we're done + return parts; + }; + URI.parseHost = function(string, parts) { + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + // https://github.com/medialize/URI.js/pull/233 + string = string.replace(/\\/g, '/'); + + // extract host:port + var pos = string.indexOf('/'); + var bracketPos; + var t; + + if (pos === -1) { + pos = string.length; + } + + if (string.charAt(0) === '[') { + // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6 + // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts + // IPv6+port in the format [2001:db8::1]:80 (for the time being) + bracketPos = string.indexOf(']'); + parts.hostname = string.substring(1, bracketPos) || null; + parts.port = string.substring(bracketPos + 2, pos) || null; + if (parts.port === '/') { + parts.port = null; + } + } else { + var firstColon = string.indexOf(':'); + var firstSlash = string.indexOf('/'); + var nextColon = string.indexOf(':', firstColon + 1); + if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) { + // IPv6 host contains multiple colons - but no port + // this notation is actually not allowed by RFC 3986, but we're a liberal parser + parts.hostname = string.substring(0, pos) || null; + parts.port = null; + } else { + t = string.substring(0, pos).split(':'); + parts.hostname = t[0] || null; + parts.port = t[1] || null; + } + } + + if (parts.hostname && string.substring(pos).charAt(0) !== '/') { + pos++; + string = '/' + string; + } + + return string.substring(pos) || '/'; + }; + URI.parseAuthority = function(string, parts) { + string = URI.parseUserinfo(string, parts); + return URI.parseHost(string, parts); + }; + URI.parseUserinfo = function(string, parts) { + // extract username:password + var firstSlash = string.indexOf('/'); + var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1); + var t; + + // authority@ must come before /path + if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { + t = string.substring(0, pos).split(':'); + parts.username = t[0] ? URI.decode(t[0]) : null; + t.shift(); + parts.password = t[0] ? URI.decode(t.join(':')) : null; + string = string.substring(pos + 1); + } else { + parts.username = null; + parts.password = null; + } + + return string; + }; + URI.parseQuery = function(string, escapeQuerySpace) { + if (!string) { + return {}; + } + + // throw out the funky business - "?"[name"="value"&"]+ + string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, ''); + + if (!string) { + return {}; + } + + var items = {}; + var splits = string.split('&'); + var length = splits.length; + var v, name, value; + + for (var i = 0; i < length; i++) { + v = splits[i].split('='); + name = URI.decodeQuery(v.shift(), escapeQuerySpace); + // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters + value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null; + + if (hasOwn.call(items, name)) { + if (typeof items[name] === 'string' || items[name] === null) { + items[name] = [items[name]]; + } + + items[name].push(value); + } else { + items[name] = value; + } + } + + return items; + }; + + URI.build = function(parts) { + var t = ''; + + if (parts.protocol) { + t += parts.protocol + ':'; + } + + if (!parts.urn && (t || parts.hostname)) { + t += '//'; + } + + t += (URI.buildAuthority(parts) || ''); + + if (typeof parts.path === 'string') { + if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') { + t += '/'; + } + + t += parts.path; + } + + if (typeof parts.query === 'string' && parts.query) { + t += '?' + parts.query; + } + + if (typeof parts.fragment === 'string' && parts.fragment) { + t += '#' + parts.fragment; + } + return t; + }; + URI.buildHost = function(parts) { + var t = ''; + + if (!parts.hostname) { + return ''; + } else if (URI.ip6_expression.test(parts.hostname)) { + t += '[' + parts.hostname + ']'; + } else { + t += parts.hostname; + } + + if (parts.port) { + t += ':' + parts.port; + } + + return t; + }; + URI.buildAuthority = function(parts) { + return URI.buildUserinfo(parts) + URI.buildHost(parts); + }; + URI.buildUserinfo = function(parts) { + var t = ''; + + if (parts.username) { + t += URI.encode(parts.username); + + if (parts.password) { + t += ':' + URI.encode(parts.password); + } + + t += '@'; + } + + return t; + }; + URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) { + // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html + // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed + // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax! + // URI.js treats the query string as being application/x-www-form-urlencoded + // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type + + var t = ''; + var unique, key, i, length; + for (key in data) { + if (hasOwn.call(data, key) && key) { + if (isArray(data[key])) { + unique = {}; + for (i = 0, length = data[key].length; i < length; i++) { + if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) { + t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace); + if (duplicateQueryParameters !== true) { + unique[data[key][i] + ''] = true; + } + } + } + } else if (data[key] !== undefined) { + t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace); + } + } + } + + return t.substring(1); + }; + URI.buildQueryParameter = function(name, value, escapeQuerySpace) { + // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded + // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization + return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : ''); + }; + + URI.addQuery = function(data, name, value) { + if (typeof name === 'object') { + for (var key in name) { + if (hasOwn.call(name, key)) { + URI.addQuery(data, key, name[key]); + } + } + } else if (typeof name === 'string') { + if (data[name] === undefined) { + data[name] = value; + return; + } else if (typeof data[name] === 'string') { + data[name] = [data[name]]; + } + + if (!isArray(value)) { + value = [value]; + } + + data[name] = (data[name] || []).concat(value); + } else { + throw new TypeError('URI.addQuery() accepts an object, string as the name parameter'); + } + }; + URI.removeQuery = function(data, name, value) { + var i, length, key; + + if (isArray(name)) { + for (i = 0, length = name.length; i < length; i++) { + data[name[i]] = undefined; + } + } else if (getType(name) === 'RegExp') { + for (key in data) { + if (name.test(key)) { + data[key] = undefined; + } + } + } else if (typeof name === 'object') { + for (key in name) { + if (hasOwn.call(name, key)) { + URI.removeQuery(data, key, name[key]); + } + } + } else if (typeof name === 'string') { + if (value !== undefined) { + if (getType(value) === 'RegExp') { + if (!isArray(data[name]) && value.test(data[name])) { + data[name] = undefined; + } else { + data[name] = filterArrayValues(data[name], value); + } + } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) { + data[name] = undefined; + } else if (isArray(data[name])) { + data[name] = filterArrayValues(data[name], value); + } + } else { + data[name] = undefined; + } + } else { + throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter'); + } + }; + URI.hasQuery = function(data, name, value, withinArray) { + if (typeof name === 'object') { + for (var key in name) { + if (hasOwn.call(name, key)) { + if (!URI.hasQuery(data, key, name[key])) { + return false; + } + } + } + + return true; + } else if (typeof name !== 'string') { + throw new TypeError('URI.hasQuery() accepts an object, string as the name parameter'); + } + + switch (getType(value)) { + case 'Undefined': + // true if exists (but may be empty) + return name in data; // data[name] !== undefined; + + case 'Boolean': + // true if exists and non-empty + var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name]); + return value === _booly; + + case 'Function': + // allow complex comparison + return !!value(data[name], name, data); + + case 'Array': + if (!isArray(data[name])) { + return false; + } + + var op = withinArray ? arrayContains : arraysEqual; + return op(data[name], value); + + case 'RegExp': + if (!isArray(data[name])) { + return Boolean(data[name] && data[name].match(value)); + } + + if (!withinArray) { + return false; + } + + return arrayContains(data[name], value); + + case 'Number': + value = String(value); + /* falls through */ + case 'String': + if (!isArray(data[name])) { + return data[name] === value; + } + + if (!withinArray) { + return false; + } + + return arrayContains(data[name], value); + + default: + throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter'); + } + }; + + + URI.commonPath = function(one, two) { + var length = Math.min(one.length, two.length); + var pos; + + // find first non-matching character + for (pos = 0; pos < length; pos++) { + if (one.charAt(pos) !== two.charAt(pos)) { + pos--; + break; + } + } + + if (pos < 1) { + return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : ''; + } + + // revert to last / + if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') { + pos = one.substring(0, pos).lastIndexOf('/'); + } + + return one.substring(0, pos + 1); + }; + + URI.withinString = function(string, callback, options) { + options || (options = {}); + var _start = options.start || URI.findUri.start; + var _end = options.end || URI.findUri.end; + var _trim = options.trim || URI.findUri.trim; + var _attributeOpen = /[a-z0-9-]=["']?$/i; + + _start.lastIndex = 0; + while (true) { + var match = _start.exec(string); + if (!match) { + break; + } + + var start = match.index; + if (options.ignoreHtml) { + // attribut(e=["']?$) + var attributeOpen = string.slice(Math.max(start - 3, 0), start); + if (attributeOpen && _attributeOpen.test(attributeOpen)) { + continue; + } + } + + var end = start + string.slice(start).search(_end); + var slice = string.slice(start, end).replace(_trim, ''); + if (options.ignore && options.ignore.test(slice)) { + continue; + } + + end = start + slice.length; + var result = callback(slice, start, end, string); + string = string.slice(0, start) + result + string.slice(end); + _start.lastIndex = start + result.length; + } + + _start.lastIndex = 0; + return string; + }; + + URI.ensureValidHostname = function(v) { + // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986) + // they are not part of DNS and therefore ignored by URI.js + + if (v.match(URI.invalid_hostname_characters)) { + // test punycode + if (!punycode) { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-] and Punycode.js is not available'); + } + + if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + } + }; + + // noConflict + URI.noConflict = function(removeAll) { + if (removeAll) { + var unconflicted = { + URI: this.noConflict() + }; + + if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') { + unconflicted.URITemplate = root.URITemplate.noConflict(); + } + + if (root.IPv6 && typeof root.IPv6.noConflict === 'function') { + unconflicted.IPv6 = root.IPv6.noConflict(); + } + + if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') { + unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict(); + } + + return unconflicted; + } else if (root.URI === this) { + root.URI = _URI; + } + + return this; + }; + + p.build = function(deferBuild) { + if (deferBuild === true) { + this._deferred_build = true; + } else if (deferBuild === undefined || this._deferred_build) { + this._string = URI.build(this._parts); + this._deferred_build = false; + } + + return this; + }; + + p.clone = function() { + return new URI(this); + }; + + p.valueOf = p.toString = function() { + return this.build(false)._string; + }; + + + function generateSimpleAccessor(_part){ + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ''; + } else { + this._parts[_part] = v || null; + this.build(!build); + return this; + } + }; + } + + function generatePrefixAccessor(_part, _key){ + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ''; + } else { + if (v !== null) { + v = v + ''; + if (v.charAt(0) === _key) { + v = v.substring(1); + } + } + + this._parts[_part] = v; + this.build(!build); + return this; + } + }; + } + + p.protocol = generateSimpleAccessor('protocol'); + p.username = generateSimpleAccessor('username'); + p.password = generateSimpleAccessor('password'); + p.hostname = generateSimpleAccessor('hostname'); + p.port = generateSimpleAccessor('port'); + p.query = generatePrefixAccessor('query', '?'); + p.fragment = generatePrefixAccessor('fragment', '#'); + + p.search = function(v, build) { + var t = this.query(v, build); + return typeof t === 'string' && t.length ? ('?' + t) : t; + }; + p.hash = function(v, build) { + var t = this.fragment(v, build); + return typeof t === 'string' && t.length ? ('#' + t) : t; + }; + + p.pathname = function(v, build) { + if (v === undefined || v === true) { + var res = this._parts.path || (this._parts.hostname ? '/' : ''); + return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res; + } else { + if (this._parts.urn) { + this._parts.path = v ? URI.recodeUrnPath(v) : ''; + } else { + this._parts.path = v ? URI.recodePath(v) : '/'; + } + this.build(!build); + return this; + } + }; + p.path = p.pathname; + p.href = function(href, build) { + var key; + + if (href === undefined) { + return this.toString(); + } + + this._string = ''; + this._parts = URI._parts(); + + var _URI = href instanceof URI; + var _object = typeof href === 'object' && (href.hostname || href.path || href.pathname); + if (href.nodeName) { + var attribute = URI.getDomAttribute(href); + href = href[attribute] || ''; + _object = false; + } + + // window.location is reported to be an object, but it's not the sort + // of object we're looking for: + // * location.protocol ends with a colon + // * location.query != object.search + // * location.hash != object.fragment + // simply serializing the unknown object should do the trick + // (for location, not for everything...) + if (!_URI && _object && href.pathname !== undefined) { + href = href.toString(); + } + + if (typeof href === 'string' || href instanceof String) { + this._parts = URI.parse(String(href), this._parts); + } else if (_URI || _object) { + var src = _URI ? href._parts : href; + for (key in src) { + if (hasOwn.call(this._parts, key)) { + this._parts[key] = src[key]; + } + } + } else { + throw new TypeError('invalid input'); + } + + this.build(!build); + return this; + }; + + // identification accessors + p.is = function(what) { + var ip = false; + var ip4 = false; + var ip6 = false; + var name = false; + var sld = false; + var idn = false; + var punycode = false; + var relative = !this._parts.urn; + + if (this._parts.hostname) { + relative = false; + ip4 = URI.ip4_expression.test(this._parts.hostname); + ip6 = URI.ip6_expression.test(this._parts.hostname); + ip = ip4 || ip6; + name = !ip; + sld = name && SLD && SLD.has(this._parts.hostname); + idn = name && URI.idn_expression.test(this._parts.hostname); + punycode = name && URI.punycode_expression.test(this._parts.hostname); + } + + switch (what.toLowerCase()) { + case 'relative': + return relative; + + case 'absolute': + return !relative; + + // hostname identification + case 'domain': + case 'name': + return name; + + case 'sld': + return sld; + + case 'ip': + return ip; + + case 'ip4': + case 'ipv4': + case 'inet4': + return ip4; + + case 'ip6': + case 'ipv6': + case 'inet6': + return ip6; + + case 'idn': + return idn; + + case 'url': + return !this._parts.urn; + + case 'urn': + return !!this._parts.urn; + + case 'punycode': + return punycode; + } + + return null; + }; + + // component specific input validation + var _protocol = p.protocol; + var _port = p.port; + var _hostname = p.hostname; + + p.protocol = function(v, build) { + if (v !== undefined) { + if (v) { + // accept trailing :// + v = v.replace(/:(\/\/)?$/, ''); + + if (!v.match(URI.protocol_expression)) { + throw new TypeError('Protocol "' + v + '" contains characters other than [A-Z0-9.+-] or doesn\'t start with [A-Z]'); + } + } + } + return _protocol.call(this, v, build); + }; + p.scheme = p.protocol; + p.port = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v !== undefined) { + if (v === 0) { + v = null; + } + + if (v) { + v += ''; + if (v.charAt(0) === ':') { + v = v.substring(1); + } + + if (v.match(/[^0-9]/)) { + throw new TypeError('Port "' + v + '" contains characters other than [0-9]'); + } + } + } + return _port.call(this, v, build); + }; + p.hostname = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v !== undefined) { + var x = {}; + var res = URI.parseHost(v, x); + if (res !== '/') { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + + v = x.hostname; + } + return _hostname.call(this, v, build); + }; + + // compound accessors + p.origin = function(v, build) { + var parts; + + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + var protocol = this.protocol(); + var authority = this.authority(); + if (!authority) return ''; + return (protocol ? protocol + '://' : '') + this.authority(); + } else { + var origin = URI(v); + this + .protocol(origin.protocol()) + .authority(origin.authority()) + .build(!build); + return this; + } + }; + p.host = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + return this._parts.hostname ? URI.buildHost(this._parts) : ''; + } else { + var res = URI.parseHost(v, this._parts); + if (res !== '/') { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + + this.build(!build); + return this; + } + }; + p.authority = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + return this._parts.hostname ? URI.buildAuthority(this._parts) : ''; + } else { + var res = URI.parseAuthority(v, this._parts); + if (res !== '/') { + throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]'); + } + + this.build(!build); + return this; + } + }; + p.userinfo = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined) { + if (!this._parts.username) { + return ''; + } + + var t = URI.buildUserinfo(this._parts); + return t.substring(0, t.length -1); + } else { + if (v[v.length-1] !== '@') { + v += '@'; + } + + URI.parseUserinfo(v, this._parts); + this.build(!build); + return this; + } + }; + p.resource = function(v, build) { + var parts; + + if (v === undefined) { + return this.path() + this.search() + this.hash(); + } + + parts = URI.parse(v); + this._parts.path = parts.path; + this._parts.query = parts.query; + this._parts.fragment = parts.fragment; + this.build(!build); + return this; + }; + + // fraction accessors + p.subdomain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + // convenience, return "www" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ''; + } + + // grab domain and add another segment + var end = this._parts.hostname.length - this.domain().length - 1; + return this._parts.hostname.substring(0, end) || ''; + } else { + var e = this._parts.hostname.length - this.domain().length; + var sub = this._parts.hostname.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(sub)); + + if (v && v.charAt(v.length - 1) !== '.') { + v += '.'; + } + + if (v) { + URI.ensureValidHostname(v); + } + + this._parts.hostname = this._parts.hostname.replace(replace, v); + this.build(!build); + return this; + } + }; + p.domain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + + // convenience, return "example.org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ''; + } + + // if hostname consists of 1 or 2 segments, it must be the domain + var t = this._parts.hostname.match(/\./g); + if (t && t.length < 2) { + return this._parts.hostname; + } + + // grab tld and add another segment + var end = this._parts.hostname.length - this.tld(build).length - 1; + end = this._parts.hostname.lastIndexOf('.', end -1) + 1; + return this._parts.hostname.substring(end) || ''; + } else { + if (!v) { + throw new TypeError('cannot set domain empty'); + } + + URI.ensureValidHostname(v); + + if (!this._parts.hostname || this.is('IP')) { + this._parts.hostname = v; + } else { + var replace = new RegExp(escapeRegEx(this.domain()) + '$'); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + + this.build(!build); + return this; + } + }; + p.tld = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + + // return "org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ''; + } + + var pos = this._parts.hostname.lastIndexOf('.'); + var tld = this._parts.hostname.substring(pos + 1); + + if (build !== true && SLD && SLD.list[tld.toLowerCase()]) { + return SLD.get(this._parts.hostname) || tld; + } + + return tld; + } else { + var replace; + + if (!v) { + throw new TypeError('cannot set TLD empty'); + } else if (v.match(/[^a-zA-Z0-9-]/)) { + if (SLD && SLD.is(v)) { + replace = new RegExp(escapeRegEx(this.tld()) + '$'); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } else { + throw new TypeError('TLD "' + v + '" contains characters other than [A-Z0-9]'); + } + } else if (!this._parts.hostname || this.is('IP')) { + throw new ReferenceError('cannot set TLD on non-domain host'); + } else { + replace = new RegExp(escapeRegEx(this.tld()) + '$'); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + + this.build(!build); + return this; + } + }; + p.directory = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined || v === true) { + if (!this._parts.path && !this._parts.hostname) { + return ''; + } + + if (this._parts.path === '/') { + return '/'; + } + + var end = this._parts.path.length - this.filename().length - 1; + var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : ''); + + return v ? URI.decodePath(res) : res; + + } else { + var e = this._parts.path.length - this.filename().length; + var directory = this._parts.path.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(directory)); + + // fully qualifier directories begin with a slash + if (!this.is('relative')) { + if (!v) { + v = '/'; + } + + if (v.charAt(0) !== '/') { + v = '/' + v; + } + } + + // directories always end with a slash + if (v && v.charAt(v.length - 1) !== '/') { + v += '/'; + } + + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + this.build(!build); + return this; + } + }; + p.filename = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ''; + } + + var pos = this._parts.path.lastIndexOf('/'); + var res = this._parts.path.substring(pos+1); + + return v ? URI.decodePathSegment(res) : res; + } else { + var mutatedDirectory = false; + + if (v.charAt(0) === '/') { + v = v.substring(1); + } + + if (v.match(/\.?\//)) { + mutatedDirectory = true; + } + + var replace = new RegExp(escapeRegEx(this.filename()) + '$'); + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + + if (mutatedDirectory) { + this.normalizePath(build); + } else { + this.build(!build); + } + + return this; + } + }; + p.suffix = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ''; + } + + var filename = this.filename(); + var pos = filename.lastIndexOf('.'); + var s, res; + + if (pos === -1) { + return ''; + } + + // suffix may only contain alnum characters (yup, I made this up.) + s = filename.substring(pos+1); + res = (/^[a-z0-9%]+$/i).test(s) ? s : ''; + return v ? URI.decodePathSegment(res) : res; + } else { + if (v.charAt(0) === '.') { + v = v.substring(1); + } + + var suffix = this.suffix(); + var replace; + + if (!suffix) { + if (!v) { + return this; + } + + this._parts.path += '.' + URI.recodePath(v); + } else if (!v) { + replace = new RegExp(escapeRegEx('.' + suffix) + '$'); + } else { + replace = new RegExp(escapeRegEx(suffix) + '$'); + } + + if (replace) { + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + } + + this.build(!build); + return this; + } + }; + p.segment = function(segment, v, build) { + var separator = this._parts.urn ? ':' : '/'; + var path = this.path(); + var absolute = path.substring(0, 1) === '/'; + var segments = path.split(separator); + + if (segment !== undefined && typeof segment !== 'number') { + build = v; + v = segment; + segment = undefined; + } + + if (segment !== undefined && typeof segment !== 'number') { + throw new Error('Bad segment "' + segment + '", must be 0-based integer'); + } + + if (absolute) { + segments.shift(); + } + + if (segment < 0) { + // allow negative indexes to address from the end + segment = Math.max(segments.length + segment, 0); + } + + if (v === undefined) { + /*jshint laxbreak: true */ + return segment === undefined + ? segments + : segments[segment]; + /*jshint laxbreak: false */ + } else if (segment === null || segments[segment] === undefined) { + if (isArray(v)) { + segments = []; + // collapse empty elements within array + for (var i=0, l=v.length; i < l; i++) { + if (!v[i].length && (!segments.length || !segments[segments.length -1].length)) { + continue; + } + + if (segments.length && !segments[segments.length -1].length) { + segments.pop(); + } + + segments.push(trimSlashes(v[i])); + } + } else if (v || typeof v === 'string') { + v = trimSlashes(v); + if (segments[segments.length -1] === '') { + // empty trailing elements have to be overwritten + // to prevent results such as /foo//bar + segments[segments.length -1] = v; + } else { + segments.push(v); + } + } + } else { + if (v) { + segments[segment] = trimSlashes(v); + } else { + segments.splice(segment, 1); + } + } + + if (absolute) { + segments.unshift(''); + } + + return this.path(segments.join(separator), build); + }; + p.segmentCoded = function(segment, v, build) { + var segments, i, l; + + if (typeof segment !== 'number') { + build = v; + v = segment; + segment = undefined; + } + + if (v === undefined) { + segments = this.segment(segment, v, build); + if (!isArray(segments)) { + segments = segments !== undefined ? URI.decode(segments) : undefined; + } else { + for (i = 0, l = segments.length; i < l; i++) { + segments[i] = URI.decode(segments[i]); + } + } + + return segments; + } + + if (!isArray(v)) { + v = (typeof v === 'string' || v instanceof String) ? URI.encode(v) : v; + } else { + for (i = 0, l = v.length; i < l; i++) { + v[i] = URI.encode(v[i]); + } + } + + return this.segment(segment, v, build); + }; + + // mutating query string + var q = p.query; + p.query = function(v, build) { + if (v === true) { + return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + } else if (typeof v === 'function') { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + var result = v.call(this, data); + this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + this.build(!build); + return this; + } else if (v !== undefined && typeof v !== 'string') { + this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + this.build(!build); + return this; + } else { + return q.call(this, v, build); + } + }; + p.setQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + + if (typeof name === 'string' || name instanceof String) { + data[name] = value !== undefined ? value : null; + } else if (typeof name === 'object') { + for (var key in name) { + if (hasOwn.call(name, key)) { + data[key] = name[key]; + } + } + } else { + throw new TypeError('URI.addQuery() accepts an object, string as the name parameter'); + } + + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + if (typeof name !== 'string') { + build = value; + } + + this.build(!build); + return this; + }; + p.addQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + URI.addQuery(data, name, value === undefined ? null : value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + if (typeof name !== 'string') { + build = value; + } + + this.build(!build); + return this; + }; + p.removeQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + URI.removeQuery(data, name, value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace); + if (typeof name !== 'string') { + build = value; + } + + this.build(!build); + return this; + }; + p.hasQuery = function(name, value, withinArray) { + var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace); + return URI.hasQuery(data, name, value, withinArray); + }; + p.setSearch = p.setQuery; + p.addSearch = p.addQuery; + p.removeSearch = p.removeQuery; + p.hasSearch = p.hasQuery; + + // sanitizing URLs + p.normalize = function() { + if (this._parts.urn) { + return this + .normalizeProtocol(false) + .normalizePath(false) + .normalizeQuery(false) + .normalizeFragment(false) + .build(); + } + + return this + .normalizeProtocol(false) + .normalizeHostname(false) + .normalizePort(false) + .normalizePath(false) + .normalizeQuery(false) + .normalizeFragment(false) + .build(); + }; + p.normalizeProtocol = function(build) { + if (typeof this._parts.protocol === 'string') { + this._parts.protocol = this._parts.protocol.toLowerCase(); + this.build(!build); + } + + return this; + }; + p.normalizeHostname = function(build) { + if (this._parts.hostname) { + if (this.is('IDN') && punycode) { + this._parts.hostname = punycode.toASCII(this._parts.hostname); + } else if (this.is('IPv6') && IPv6) { + this._parts.hostname = IPv6.best(this._parts.hostname); + } + + this._parts.hostname = this._parts.hostname.toLowerCase(); + this.build(!build); + } + + return this; + }; + p.normalizePort = function(build) { + // remove port of it's the protocol's default + if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) { + this._parts.port = null; + this.build(!build); + } + + return this; + }; + p.normalizePath = function(build) { + var _path = this._parts.path; + if (!_path) { + return this; + } + + if (this._parts.urn) { + this._parts.path = URI.recodeUrnPath(this._parts.path); + this.build(!build); + return this; + } + + if (this._parts.path === '/') { + return this; + } + + _path = URI.recodePath(_path); + + var _was_relative; + var _leadingParents = ''; + var _parent, _pos; + + // handle relative paths + if (_path.charAt(0) !== '/') { + _was_relative = true; + _path = '/' + _path; + } + + // handle relative files (as opposed to directories) + if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') { + _path += '/'; + } + + // resolve simples + _path = _path + .replace(/(\/(\.\/)+)|(\/\.$)/g, '/') + .replace(/\/{2,}/g, '/'); + + // remember leading parents + if (_was_relative) { + _leadingParents = _path.substring(1).match(/^(\.\.\/)+/) || ''; + if (_leadingParents) { + _leadingParents = _leadingParents[0]; + } + } + + // resolve parents + while (true) { + _parent = _path.search(/\/\.\.(\/|$)/); + if (_parent === -1) { + // no more ../ to resolve + break; + } else if (_parent === 0) { + // top level cannot be relative, skip it + _path = _path.substring(3); + continue; + } + + _pos = _path.substring(0, _parent).lastIndexOf('/'); + if (_pos === -1) { + _pos = _parent; + } + _path = _path.substring(0, _pos) + _path.substring(_parent + 3); + } + + // revert to relative + if (_was_relative && this.is('relative')) { + _path = _leadingParents + _path.substring(1); + } + + this._parts.path = _path; + this.build(!build); + return this; + }; + p.normalizePathname = p.normalizePath; + p.normalizeQuery = function(build) { + if (typeof this._parts.query === 'string') { + if (!this._parts.query.length) { + this._parts.query = null; + } else { + this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)); + } + + this.build(!build); + } + + return this; + }; + p.normalizeFragment = function(build) { + if (!this._parts.fragment) { + this._parts.fragment = null; + this.build(!build); + } + + return this; + }; + p.normalizeSearch = p.normalizeQuery; + p.normalizeHash = p.normalizeFragment; + + p.iso8859 = function() { + // expect unicode input, iso8859 output + var e = URI.encode; + var d = URI.decode; + + URI.encode = escape; + URI.decode = decodeURIComponent; + try { + this.normalize(); + } finally { + URI.encode = e; + URI.decode = d; + } + return this; + }; + + p.unicode = function() { + // expect iso8859 input, unicode output + var e = URI.encode; + var d = URI.decode; + + URI.encode = strictEncodeURIComponent; + URI.decode = unescape; + try { + this.normalize(); + } finally { + URI.encode = e; + URI.decode = d; + } + return this; + }; + + p.readable = function() { + var uri = this.clone(); + // removing username, password, because they shouldn't be displayed according to RFC 3986 + uri.username('').password('').normalize(); + var t = ''; + if (uri._parts.protocol) { + t += uri._parts.protocol + '://'; + } + + if (uri._parts.hostname) { + if (uri.is('punycode') && punycode) { + t += punycode.toUnicode(uri._parts.hostname); + if (uri._parts.port) { + t += ':' + uri._parts.port; + } + } else { + t += uri.host(); + } + } + + if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') { + t += '/'; + } + + t += uri.path(true); + if (uri._parts.query) { + var q = ''; + for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) { + var kv = (qp[i] || '').split('='); + q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace) + .replace(/&/g, '%26'); + + if (kv[1] !== undefined) { + q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace) + .replace(/&/g, '%26'); + } + } + t += '?' + q.substring(1); + } + + t += URI.decodeQuery(uri.hash(), true); + return t; + }; + + // resolving relative and absolute URLs + p.absoluteTo = function(base) { + var resolved = this.clone(); + var properties = ['protocol', 'username', 'password', 'hostname', 'port']; + var basedir, i, p; + + if (this._parts.urn) { + throw new Error('URNs do not have any generally defined hierarchical components'); + } + + if (!(base instanceof URI)) { + base = new URI(base); + } + + if (!resolved._parts.protocol) { + resolved._parts.protocol = base._parts.protocol; + } + + if (this._parts.hostname) { + return resolved; + } + + for (i = 0; (p = properties[i]); i++) { + resolved._parts[p] = base._parts[p]; + } + + if (!resolved._parts.path) { + resolved._parts.path = base._parts.path; + if (!resolved._parts.query) { + resolved._parts.query = base._parts.query; + } + } else if (resolved._parts.path.substring(-2) === '..') { + resolved._parts.path += '/'; + } + + if (resolved.path().charAt(0) !== '/') { + basedir = base.directory(); + basedir = basedir ? basedir : base.path().indexOf('/') === 0 ? '/' : ''; + resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path; + resolved.normalizePath(); + } + + resolved.build(); + return resolved; + }; + p.relativeTo = function(base) { + var relative = this.clone().normalize(); + var relativeParts, baseParts, common, relativePath, basePath; + + if (relative._parts.urn) { + throw new Error('URNs do not have any generally defined hierarchical components'); + } + + base = new URI(base).normalize(); + relativeParts = relative._parts; + baseParts = base._parts; + relativePath = relative.path(); + basePath = base.path(); + + if (relativePath.charAt(0) !== '/') { + throw new Error('URI is already relative'); + } + + if (basePath.charAt(0) !== '/') { + throw new Error('Cannot calculate a URI relative to another relative URI'); + } + + if (relativeParts.protocol === baseParts.protocol) { + relativeParts.protocol = null; + } + + if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) { + return relative.build(); + } + + if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) { + return relative.build(); + } + + if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) { + relativeParts.hostname = null; + relativeParts.port = null; + } else { + return relative.build(); + } + + if (relativePath === basePath) { + relativeParts.path = ''; + return relative.build(); + } + + // determine common sub path + common = URI.commonPath(relativePath, basePath); + + // If the paths have nothing in common, return a relative URL with the absolute path. + if (!common) { + return relative.build(); + } + + var parents = baseParts.path + .substring(common.length) + .replace(/[^\/]*$/, '') + .replace(/.*?\//g, '../'); + + relativeParts.path = (parents + relativeParts.path.substring(common.length)) || './'; + + return relative.build(); + }; + + // comparing URIs + p.equals = function(uri) { + var one = this.clone(); + var two = new URI(uri); + var one_map = {}; + var two_map = {}; + var checked = {}; + var one_query, two_query, key; + + one.normalize(); + two.normalize(); + + // exact match + if (one.toString() === two.toString()) { + return true; + } + + // extract query string + one_query = one.query(); + two_query = two.query(); + one.query(''); + two.query(''); + + // definitely not equal if not even non-query parts match + if (one.toString() !== two.toString()) { + return false; + } + + // query parameters have the same length, even if they're permuted + if (one_query.length !== two_query.length) { + return false; + } + + one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace); + two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace); + + for (key in one_map) { + if (hasOwn.call(one_map, key)) { + if (!isArray(one_map[key])) { + if (one_map[key] !== two_map[key]) { + return false; + } + } else if (!arraysEqual(one_map[key], two_map[key])) { + return false; + } + + checked[key] = true; + } + } + + for (key in two_map) { + if (hasOwn.call(two_map, key)) { + if (!checked[key]) { + // two contains a parameter not present in one + return false; + } + } + } + + return true; + }; + + // state + p.duplicateQueryParameters = function(v) { + this._parts.duplicateQueryParameters = !!v; + return this; + }; + + p.escapeQuerySpace = function(v) { + this._parts.escapeQuerySpace = !!v; + return this; + }; + + return URI; +})); diff --git a/lib/vendor/jed.js b/lib/vendor/jed.js new file mode 120000 index 000000000..181c64459 --- /dev/null +++ b/lib/vendor/jed.js @@ -0,0 +1 @@ +../../node_modules/jed/jed.js
\ No newline at end of file diff --git a/lib/vendor/lodash.core.min.js b/lib/vendor/lodash.core.min.js new file mode 100644 index 000000000..062e55d49 --- /dev/null +++ b/lib/vendor/lodash.core.min.js @@ -0,0 +1,29 @@ +/** + * @license + * lodash 4.0.0 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE + * Build: `lodash core -o ./dist/lodash.core.js` + */ +;(function(){function n(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function t(n,t,r){for(var e=-1,u=n.length;++e<u;){var o=n[e],i=t(o);if(null!=i&&(c===ln?i===i:r(i,c)))var c=i,f=o}return f}function r(n,t,r){var e;return r(n,function(n,r,u){return t(n,r,u)?(e=n,false):void 0}),e}function e(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function u(n,t){return w(t,function(t){return n[t]})}function o(n){return n&&n.Object===Object?n:null}function i(n){return vn[n]; +}function c(n){var t=false;if(null!=n&&typeof n.toString!="function")try{t=!!(n+"")}catch(r){}return t}function f(n,t){return n=typeof n=="number"||hn.test(n)?+n:-1,n>-1&&0==n%1&&(null==t?9007199254740991:t)>n}function a(n){if(Z(n)&&!Vn(n)){if(n instanceof l)return n;if(En.call(n,"__wrapped__")){var t=new l(n.__wrapped__,n.__chain__);return t.__actions__=k(n.__actions__),t}}return new l(n)}function l(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function p(n,t,r,e){return n===ln||H(n,xn[r])&&!En.call(e,r)?t:n; +}function s(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function");return setTimeout(function(){n.apply(ln,r)},t)}function h(n,t){var r=true;return $n(n,function(n,e,u){return r=!!t(n,e,u)}),r}function v(n,t){var r=[];return $n(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function y(t,r,e,u){u||(u=[]);for(var o=-1,i=t.length;++o<i;){var c=t[o];Z(c)&&Q(c)&&(e||Vn(c)||L(c))?r?y(c,r,e,u):n(u,c):e||(u[u.length]=c)}return u}function _(n,t){return n&&qn(n,t,un)}function g(n,t){return v(t,function(t){ +return W(n[t])})}function b(n,t,r,e,u){return n===t?true:null==n||null==t||!Y(n)&&!Z(t)?n!==n&&t!==t:j(n,t,b,r,e,u)}function j(n,t,r,e,u,o){var i=Vn(n),f=Vn(t),a="[object Array]",l="[object Array]";i||(a=kn.call(n),"[object Arguments]"==a&&(a="[object Object]")),f||(l=kn.call(t),"[object Arguments]"==l&&(l="[object Object]"));var p="[object Object]"==a&&!c(n),f="[object Object]"==l&&!c(t);return!(l=a==l)||i||p?2&u||(a=p&&En.call(n,"__wrapped__"),f=f&&En.call(t,"__wrapped__"),!a&&!f)?l?(o||(o=[]),(a=C(o,function(t){ +return t[0]===n}))&&a[1]?a[1]==t:(o.push([n,t]),t=(i?R:$)(n,t,r,e,u,o),o.pop(),t)):false:r(a?n.value():n,f?t.value():t,e,u,o):I(n,t,a)}function d(n){var t=typeof n;return"function"==t?n:null==n?fn:("object"==t?O:E)(n)}function m(n){n=null==n?n:Object(n);var t,r=[];for(t in n)r.push(t);return r}function w(n,t){var r=-1,e=Q(n)?Array(n.length):[];return $n(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function O(n){var t=un(n),r=t.length;return function(e){if(null==e)return!r;for(e=Object(e);r--;){var u=t[r];if(!(u in e&&b(n[u],e[u],ln,true)))return false; +}return true}}function x(n,t){return n=Object(n),J(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function E(n){return function(t){return null==t?ln:t[n]}}function A(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e<u;)r[e]=n[e+t];return r}function k(n){return A(n,0,n.length)}function N(n,t){var r;return $n(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function S(t,r){return J(r,function(t,r){return r.func.apply(r.thisArg,n([t],r.args))},t); +}function T(n,t,r,e){r||(r={});for(var u=-1,o=t.length;++u<o;){var i=t[u],c=e?e(r[i],n[i],i,r,n):n[i],f=r,a=f[i];(!H(a,c)||H(a,xn[i])&&!En.call(f,i)||c===ln&&!(i in f))&&(f[i]=c)}return r}function F(n){return V(function(t,r){var e=-1,u=r.length,o=u>1?r[u-1]:ln,o=typeof o=="function"?(u--,o):ln;for(t=Object(t);++e<u;){var i=r[e];i&&n(t,i,o)}return t})}function B(n){return function(){var t=arguments,r=In(n.prototype),t=n.apply(r,t);return Y(t)?t:r}}function D(n,t,r){function e(){for(var o=-1,i=arguments.length,c=-1,f=r.length,a=Array(f+i),l=this&&this!==wn&&this instanceof e?u:n;++c<f;)a[c]=r[c]; +for(;i--;)a[c++]=arguments[++o];return l.apply(t,a)}if(typeof n!="function")throw new TypeError("Expected a function");var u=B(n);return e}function R(n,t,r,e,u,o){var i=-1,c=1&u,f=n.length,a=t.length;if(f!=a&&!(2&u&&a>f))return false;for(a=true;++i<f;){var l=n[i],p=t[i];if(void 0!==ln){a=false;break}if(c){if(!N(t,function(n){return l===n||r(l,n,e,u,o)})){a=false;break}}else if(l!==p&&!r(l,p,e,u,o)){a=false;break}}return a}function I(n,t,r){switch(r){case"[object Boolean]":case"[object Date]":return+n==+t;case"[object Error]": +return n.name==t.name&&n.message==t.message;case"[object Number]":return n!=+n?t!=+t:n==+t;case"[object RegExp]":case"[object String]":return n==t+""}return false}function $(n,t,r,e,u,o){var i=2&u,c=1&u,f=un(n),a=f.length,l=un(t);if(a!=l.length&&!i)return false;for(var p=a;p--;){var s=f[p];if(!(i?s in t:En.call(t,s))||!c&&s!=l[p])return false}for(c=true;++p<a;){var s=f[p],l=n[s],h=t[s];if(void 0!==ln||l!==h&&!r(l,h,e,u,o)){c=false;break}i||(i="constructor"==s)}return c&&!i&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)), +c}function q(n){var t=n?n.length:ln;if(X(t)&&(Vn(n)||tn(n)||L(n))){n=String;for(var r=-1,e=Array(t);++r<t;)e[r]=n(r);t=e}else t=null;return t}function M(n){var t=n&&n.constructor;return n===(typeof t=="function"&&t.prototype||xn)}function z(n){return n?n[0]:ln}function C(n,t){return r(n,d(t),$n)}function G(n,t){return $n(n,typeof t=="function"?t:fn)}function J(n,t,r){return e(n,d(t),r,3>arguments.length,$n)}function P(n){return null==n?0:(n=Q(n)?n:un(n),n.length)}function U(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function"); +return n=Hn(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=ln),r}}function V(n){var t;if(typeof n!="function")throw new TypeError("Expected a function");return t=Rn(t===ln?n.length-1:Hn(t),0),function(){for(var r=arguments,e=-1,u=Rn(r.length-t,0),o=Array(u);++e<u;)o[e]=r[t+e];for(u=Array(t+1),e=-1;++e<t;)u[e]=r[e];return u[t]=o,n.apply(this,u)}}function H(n,t){return n===t||n!==n&&t!==t}function K(n,t){return n>t}function L(n){return Z(n)&&Q(n)&&En.call(n,"callee")&&(!Fn.call(n,"callee")||"[object Arguments]"==kn.call(n)); +}function Q(n){return null!=n&&!(typeof n=="function"&&W(n))&&X(Mn(n))}function W(n){return n=Y(n)?kn.call(n):"","[object Function]"==n||"[object GeneratorFunction]"==n}function X(n){return typeof n=="number"&&n>-1&&0==n%1&&9007199254740991>=n}function Y(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function Z(n){return!!n&&typeof n=="object"}function nn(n){return typeof n=="number"||Z(n)&&"[object Number]"==kn.call(n)}function tn(n){return typeof n=="string"||!Vn(n)&&Z(n)&&"[object String]"==kn.call(n); +}function rn(n,t){return t>n}function en(n){return typeof n=="string"?n:null==n?"":n+""}function un(n){var t=M(n);if(!t&&!Q(n))return Dn(Object(n));var r,e=q(n),u=!!e,e=e||[],o=e.length;for(r in n)!En.call(n,r)||u&&("length"==r||f(r,o))||t&&"constructor"==r||e.push(r);return e}function on(n){for(var t=-1,r=M(n),e=m(n),u=e.length,o=q(n),i=!!o,o=o||[],c=o.length;++t<u;){var a=e[t];i&&("length"==a||f(a,c))||"constructor"==a&&(r||!En.call(n,a))||o.push(a)}return o}function cn(n){return n?u(n,un(n)):[]; +}function fn(n){return n}function an(t,r,e){var u=un(r),o=g(r,u);null!=e||Y(r)&&(o.length||!u.length)||(e=r,r=t,t=this,o=g(r,un(r)));var i=Y(e)&&"chain"in e?e.chain:true,c=W(t);return $n(o,function(e){var u=r[e];t[e]=u,c&&(t.prototype[e]=function(){var r=this.__chain__;if(i||r){var e=t(this.__wrapped__);return(e.__actions__=k(this.__actions__)).push({func:u,args:arguments,thisArg:t}),e.__chain__=r,e}return u.apply(t,n([this.value()],arguments))})}),t}var ln,pn=/[&<>"'`]/g,sn=RegExp(pn.source),hn=/^(?:0|[1-9]\d*)$/,vn={ +"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},yn={"function":true,object:true},_n=yn[typeof exports]&&exports&&!exports.nodeType?exports:null,gn=yn[typeof module]&&module&&!module.nodeType?module:null,bn=o(yn[typeof self]&&self),jn=o(yn[typeof window]&&window),dn=gn&&gn.exports===_n?_n:null,mn=o(yn[typeof this]&&this),wn=o(_n&&gn&&typeof global=="object"&&global)||jn!==(mn&&mn.window)&&jn||bn||mn||Function("return this")(),On=Array.prototype,xn=Object.prototype,En=xn.hasOwnProperty,An=0,kn=xn.toString,Nn=wn._,Sn=wn.f,Tn=Sn?Sn.g:ln,Fn=xn.propertyIsEnumerable,Bn=wn.isFinite,Dn=Object.keys,Rn=Math.max,In=function(){ +function n(){}return function(t){if(Y(t)){n.prototype=t;var r=new n;n.prototype=ln}return r||{}}}(),$n=function(n,t){return function(r,e){if(null==r)return r;if(!Q(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}(_),qn=function(n){return function(t,r,e){var u=-1,o=Object(t);e=e(t);for(var i=e.length;i--;){var c=e[n?i:++u];if(false===r(o[c],c,o))break}return t}}();Tn&&!Fn.call({valueOf:1},"valueOf")&&(m=function(n){n=Tn(n);for(var t,r=[];!(t=n.next()).done;)r.push(t.value); +return r});var Mn=E("length"),zn=V(function(t,r){y(r);var e=Vn(t)?t:[Object(t)];return n(k(e),cn)}),Cn=V(function(n,t,r){var e=typeof t=="function";return w(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})}),Gn=Date.now,Jn=V(function(n,t,r){return D(n,t,r)}),Pn=V(function(n,t){return s(n,1,t)}),Un=V(function(n,t,r){return s(n,Kn(t)||0,r)}),Vn=Array.isArray,Hn=Number,Kn=Number,Ln=F(function(n,t){T(t,un(t),n)}),Qn=F(function(n,t){T(t,on(t),n)}),Wn=F(function(n,t,r){T(t,on(t),n,r)}),Xn=V(function(n){ +return n.push(ln,p),Wn.apply(ln,n)}),Yn=V(function(n,t){return null==n?{}:x(n,y(t))}),Zn=d;l.prototype=In(a.prototype),l.prototype.constructor=l,a.assignIn=Qn,a.before=U,a.bind=Jn,a.chain=function(n){return n=a(n),n.__chain__=true,n},a.compact=function(n){return v(n,Boolean)},a.concat=zn,a.create=function(n,t){var r=In(n);return t?Ln(r,t):r},a.defaults=Xn,a.defer=Pn,a.delay=Un,a.filter=function(n,t){return v(n,d(t))},a.flatten=function(n){return n&&n.length?y(n):[]},a.flattenDeep=function(n){return n&&n.length?y(n,true):[]; +},a.invokeMap=Cn,a.iteratee=Zn,a.keys=un,a.map=function(n,t){return w(n,d(t))},a.mixin=an,a.negate=function(n){if(typeof n!="function")throw new TypeError("Expected a function");return function(){return!n.apply(this,arguments)}},a.once=function(n){return U(2,n)},a.pick=Yn,a.slice=function(n,t,r){return n&&n.length?A(n,t,r):[]},a.sortBy=function(n,t){var r=0;return t=d(t),w(w(n,function(n,e,u){return{c:n,b:r++,a:t(n,e,u)}}).sort(function(n,t){var r;n:{r=n.a;var e=t.a;if(r!==e){var u=null===r,o=r===ln,i=r===r,c=null===e,f=e===ln,a=e===e; +if(r>e&&!c||!i||u&&!f&&a||o&&a){r=1;break n}if(e>r&&!u||!a||c&&!o&&i||f&&i){r=-1;break n}}r=0}return r||n.b-t.b}),E("c"))},a.tap=function(n,t){return t(n),n},a.thru=function(n,t){return t(n)},a.toArray=function(n){return Q(n)?n.length?k(n):[]:cn(n)},a.values=cn,a.each=G,a.extend=Qn,an(a,a),a.clone=function(n){return Y(n)?Vn(n)?k(n):T(n,un(n)):n},a.escape=function(n){return(n=en(n))&&sn.test(n)?n.replace(pn,i):n},a.every=function(n,t,r){return t=r?ln:t,h(n,d(t))},a.find=C,a.forEach=G,a.has=function(n,t){ +return null!=n&&En.call(n,t)},a.head=z,a.identity=fn,a.indexOf=function(n,t,r){var e=n?n.length:0;r=typeof r=="number"?0>r?Rn(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++r<e;){var o=n[r];if(u?o===t:o!==o)return r}return-1},a.isArguments=L,a.isArray=Vn,a.isBoolean=function(n){return true===n||false===n||Z(n)&&"[object Boolean]"==kn.call(n)},a.isDate=function(n){return Z(n)&&"[object Date]"==kn.call(n)},a.isEmpty=function(n){return!Z(n)||W(n.splice)?!P(n):!un(n).length},a.isEqual=function(n,t){return b(n,t)}, +a.isFinite=function(n){return typeof n=="number"&&Bn(n)},a.isFunction=W,a.isNaN=function(n){return nn(n)&&n!=+n},a.isNull=function(n){return null===n},a.isNumber=nn,a.isObject=Y,a.isRegExp=function(n){return Y(n)&&"[object RegExp]"==kn.call(n)},a.isString=tn,a.isUndefined=function(n){return n===ln},a.last=function(n){var t=n?n.length:0;return t?n[t-1]:ln},a.max=function(n){return n&&n.length?t(n,fn,K):ln},a.min=function(n){return n&&n.length?t(n,fn,rn):ln},a.noConflict=function(){return wn._=Nn,this; +},a.noop=function(){},a.now=Gn,a.reduce=J,a.result=function(n,t,r){return t=null==n?ln:n[t],t===ln&&(t=r),W(t)?t.call(n):t},a.size=P,a.some=function(n,t,r){return t=r?ln:t,N(n,d(t))},a.uniqueId=function(n){var t=++An;return en(n)+t},a.first=z,an(a,function(){var n={};return _(a,function(t,r){En.call(a.prototype,r)||(n[r]=t)}),n}(),{chain:false}),a.VERSION="4.0.0",$n("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:On)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n); +a.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),a.prototype.toJSON=a.prototype.valueOf=a.prototype.value=function(){return S(this.__wrapped__,this.__actions__)},(jn||bn||{})._=a,typeof define=="function"&&typeof define.amd=="object"&&define.amd? define(function(){return a}):_n&&gn?(dn&&((gn.exports=a)._=a),_n._=a):wn._=a}).call(this);
\ No newline at end of file diff --git a/lib/vendor/mithril.js b/lib/vendor/mithril.js new file mode 100644 index 000000000..d023ac34c --- /dev/null +++ b/lib/vendor/mithril.js @@ -0,0 +1,2132 @@ +;(function (global, factory) { // eslint-disable-line + "use strict" + /* eslint-disable no-undef */ + var m = factory(global) + if (typeof module === "object" && module != null && module.exports) { + module.exports = m + } else if (typeof define === "function" && define.amd) { + define(function () { return m }) + } else { + global.m = m + } + /* eslint-enable no-undef */ +})(typeof window !== "undefined" ? window : {}, function (global, undefined) { // eslint-disable-line + "use strict" + + m.version = function () { + return "v0.2.2-rc.1" + } + + var hasOwn = {}.hasOwnProperty + var type = {}.toString + + function isFunction(object) { + return typeof object === "function" + } + + function isObject(object) { + return type.call(object) === "[object Object]" + } + + function isString(object) { + return type.call(object) === "[object String]" + } + + var isArray = Array.isArray || function (object) { + return type.call(object) === "[object Array]" + } + + function noop() {} + + /* eslint-disable max-len */ + var voidElements = /^(AREA|BASE|BR|COL|COMMAND|EMBED|HR|IMG|INPUT|KEYGEN|LINK|META|PARAM|SOURCE|TRACK|WBR)$/ + /* eslint-enable max-len */ + + // caching commonly used variables + var $document, $location, $requestAnimationFrame, $cancelAnimationFrame + + // self invoking function needed because of the way mocks work + function initialize(mock) { + $document = mock.document + $location = mock.location + $cancelAnimationFrame = mock.cancelAnimationFrame || mock.clearTimeout + $requestAnimationFrame = mock.requestAnimationFrame || mock.setTimeout + } + + // testing API + m.deps = function (mock) { + initialize(global = mock || window) + return global + } + + m.deps(global) + + /** + * @typedef {String} Tag + * A string that looks like -> div.classname#id[param=one][param2=two] + * Which describes a DOM node + */ + + function parseTagAttrs(cell, tag) { + var classes = [] + var parser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[.+?\])/g + var match + + while ((match = parser.exec(tag))) { + if (match[1] === "" && match[2]) { + cell.tag = match[2] + } else if (match[1] === "#") { + cell.attrs.id = match[2] + } else if (match[1] === ".") { + classes.push(match[2]) + } else if (match[3][0] === "[") { + var pair = /\[(.+?)(?:=("|'|)(.*?)\2)?\]/.exec(match[3]) + cell.attrs[pair[1]] = pair[3] || (pair[2] ? "" : true) + } + } + + return classes + } + + function getVirtualChildren(args, hasAttrs) { + var children = hasAttrs ? args.slice(1) : args + + if (children.length === 1 && isArray(children[0])) { + return children[0] + } else { + return children + } + } + + function assignAttrs(target, attrs, classes) { + var classAttr = "class" in attrs ? "class" : "className" + + for (var attrName in attrs) { + if (hasOwn.call(attrs, attrName)) { + if (attrName === classAttr && + attrs[attrName] != null && + attrs[attrName] !== "") { + classes.push(attrs[attrName]) + // create key in correct iteration order + target[attrName] = "" + } else { + target[attrName] = attrs[attrName] + } + } + } + + if (classes.length) target[classAttr] = classes.join(" ") + } + + /** + * + * @param {Tag} The DOM node tag + * @param {Object=[]} optional key-value pairs to be mapped to DOM attrs + * @param {...mNode=[]} Zero or more Mithril child nodes. Can be an array, + * or splat (optional) + */ + function m(tag, pairs) { + for (var args = [], i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i] + } + + if (isObject(tag)) return parameterize(tag, args) + + if (!isString(tag)) { + throw new Error("selector in m(selector, attrs, children) should " + + "be a string") + } + + var hasAttrs = pairs != null && isObject(pairs) && + !("tag" in pairs || "view" in pairs || "subtree" in pairs) + + var attrs = hasAttrs ? pairs : {} + var cell = { + tag: "div", + attrs: {}, + children: getVirtualChildren(args, hasAttrs) + } + + assignAttrs(cell.attrs, attrs, parseTagAttrs(cell, tag)) + return cell + } + + function forEach(list, f) { + for (var i = 0; i < list.length && !f(list[i], i++);) { + // function called in condition + } + } + + function forKeys(list, f) { + forEach(list, function (attrs, i) { + return (attrs = attrs && attrs.attrs) && + attrs.key != null && + f(attrs, i) + }) + } + // This function was causing deopts in Chrome. + function dataToString(data) { + // data.toString() might throw or return null if data is the return + // value of Console.log in some versions of Firefox (behavior depends on + // version) + try { + if (data != null && data.toString() != null) return data + } catch (e) { + // silently ignore errors + } + return "" + } + + // This function was causing deopts in Chrome. + function injectTextNode(parentElement, first, index, data) { + try { + insertNode(parentElement, first, index) + first.nodeValue = data + } catch (e) { + // IE erroneously throws error when appending an empty text node + // after a null + } + } + + function flatten(list) { + // recursively flatten array + for (var i = 0; i < list.length; i++) { + if (isArray(list[i])) { + list = list.concat.apply([], list) + // check current index again and flatten until there are no more + // nested arrays at that index + i-- + } + } + return list + } + + function insertNode(parentElement, node, index) { + parentElement.insertBefore(node, + parentElement.childNodes[index] || null) + } + + var DELETION = 1 + var INSERTION = 2 + var MOVE = 3 + + function handleKeysDiffer(data, existing, cached, parentElement) { + forKeys(data, function (key, i) { + existing[key = key.key] = existing[key] ? { + action: MOVE, + index: i, + from: existing[key].index, + element: cached.nodes[existing[key].index] || + $document.createElement("div") + } : {action: INSERTION, index: i} + }) + + var actions = [] + for (var prop in existing) if (hasOwn.call(existing, prop)) { + actions.push(existing[prop]) + } + + var changes = actions.sort(sortChanges) + var newCached = new Array(cached.length) + + newCached.nodes = cached.nodes.slice() + + forEach(changes, function (change) { + var index = change.index + if (change.action === DELETION) { + clear(cached[index].nodes, cached[index]) + newCached.splice(index, 1) + } + if (change.action === INSERTION) { + var dummy = $document.createElement("div") + dummy.key = data[index].attrs.key + insertNode(parentElement, dummy, index) + newCached.splice(index, 0, { + attrs: {key: data[index].attrs.key}, + nodes: [dummy] + }) + newCached.nodes[index] = dummy + } + + if (change.action === MOVE) { + var changeElement = change.element + var maybeChanged = parentElement.childNodes[index] + if (maybeChanged !== changeElement && changeElement !== null) { + parentElement.insertBefore(changeElement, + maybeChanged || null) + } + newCached[index] = cached[change.from] + newCached.nodes[index] = changeElement + } + }) + + return newCached + } + + function diffKeys(data, cached, existing, parentElement) { + var keysDiffer = data.length !== cached.length + + if (!keysDiffer) { + forKeys(data, function (attrs, i) { + var cachedCell = cached[i] + return keysDiffer = cachedCell && + cachedCell.attrs && + cachedCell.attrs.key !== attrs.key + }) + } + + if (keysDiffer) { + return handleKeysDiffer(data, existing, cached, parentElement) + } else { + return cached + } + } + + function diffArray(data, cached, nodes) { + // diff the array itself + + // update the list of DOM nodes by collecting the nodes from each item + forEach(data, function (_, i) { + if (cached[i] != null) nodes.push.apply(nodes, cached[i].nodes) + }) + // remove items from the end of the array if the new array is shorter + // than the old one. if errors ever happen here, the issue is most + // likely a bug in the construction of the `cached` data structure + // somewhere earlier in the program + forEach(cached.nodes, function (node, i) { + if (node.parentNode != null && nodes.indexOf(node) < 0) { + clear([node], [cached[i]]) + } + }) + + if (data.length < cached.length) cached.length = data.length + cached.nodes = nodes + } + + function buildArrayKeys(data) { + var guid = 0 + forKeys(data, function () { + forEach(data, function (attrs) { + if ((attrs = attrs && attrs.attrs) && attrs.key == null) { + attrs.key = "__mithril__" + guid++ + } + }) + return 1 + }) + } + + function isDifferentEnough(data, cached, dataAttrKeys) { + if (data.tag !== cached.tag) return true + + if (dataAttrKeys.sort().join() !== + Object.keys(cached.attrs).sort().join()) { + return true + } + + if (data.attrs.id !== cached.attrs.id) { + return true + } + + if (data.attrs.key !== cached.attrs.key) { + return true + } + + if (m.redraw.strategy() === "all") { + return !cached.configContext || cached.configContext.retain !== true + } + + if (m.redraw.strategy() === "diff") { + return cached.configContext && cached.configContext.retain === false + } + + return false + } + + function maybeRecreateObject(data, cached, dataAttrKeys) { + // if an element is different enough from the one in cache, recreate it + if (isDifferentEnough(data, cached, dataAttrKeys)) { + if (cached.nodes.length) clear(cached.nodes) + + if (cached.configContext && + isFunction(cached.configContext.onunload)) { + cached.configContext.onunload() + } + + if (cached.controllers) { + forEach(cached.controllers, function (controller) { + if (controller.onunload) controller.onunload({preventDefault: noop}); + }); + } + } + } + + function getObjectNamespace(data, namespace) { + if (data.attrs.xmlns) return data.attrs.xmlns + if (data.tag === "svg") return "http://www.w3.org/2000/svg" + if (data.tag === "math") return "http://www.w3.org/1998/Math/MathML" + return namespace + } + + var pendingRequests = 0 + m.startComputation = function () { pendingRequests++ } + m.endComputation = function () { + if (pendingRequests > 1) { + pendingRequests-- + } else { + pendingRequests = 0 + m.redraw() + } + } + + function unloadCachedControllers(cached, views, controllers) { + if (controllers.length) { + cached.views = views + cached.controllers = controllers + forEach(controllers, function (controller) { + if (controller.onunload && controller.onunload.$old) { + controller.onunload = controller.onunload.$old + } + + if (pendingRequests && controller.onunload) { + var onunload = controller.onunload + controller.onunload = noop + controller.onunload.$old = onunload + } + }) + } + } + + function scheduleConfigsToBeCalled(configs, data, node, isNew, cached) { + // schedule configs to be called. They are called after `build` finishes + // running + if (isFunction(data.attrs.config)) { + var context = cached.configContext = cached.configContext || {} + + // bind + configs.push(function () { + return data.attrs.config.call(data, node, !isNew, context, + cached) + }) + } + } + + function buildUpdatedNode( + cached, + data, + editable, + hasKeys, + namespace, + views, + configs, + controllers + ) { + var node = cached.nodes[0] + + if (hasKeys) { + setAttributes(node, data.tag, data.attrs, cached.attrs, namespace) + } + + cached.children = build( + node, + data.tag, + undefined, + undefined, + data.children, + cached.children, + false, + 0, + data.attrs.contenteditable ? node : editable, + namespace, + configs + ) + + cached.nodes.intact = true + + if (controllers.length) { + cached.views = views + cached.controllers = controllers + } + + return node + } + + function handleNonexistentNodes(data, parentElement, index) { + var nodes + if (data.$trusted) { + nodes = injectHTML(parentElement, index, data) + } else { + nodes = [$document.createTextNode(data)] + if (!parentElement.nodeName.match(voidElements)) { + insertNode(parentElement, nodes[0], index) + } + } + + var cached + + if (typeof data === "string" || + typeof data === "number" || + typeof data === "boolean") { + cached = new data.constructor(data) + } else { + cached = data + } + + cached.nodes = nodes + return cached + } + + function reattachNodes( + data, + cached, + parentElement, + editable, + index, + parentTag + ) { + var nodes = cached.nodes + if (!editable || editable !== $document.activeElement) { + if (data.$trusted) { + clear(nodes, cached) + nodes = injectHTML(parentElement, index, data) + } else if (parentTag === "textarea") { + // <textarea> uses `value` instead of `nodeValue`. + parentElement.value = data + } else if (editable) { + // contenteditable nodes use `innerHTML` instead of `nodeValue`. + editable.innerHTML = data + } else { + // was a trusted string + if (nodes[0].nodeType === 1 || nodes.length > 1 || + (nodes[0].nodeValue.trim && + !nodes[0].nodeValue.trim())) { + clear(cached.nodes, cached) + nodes = [$document.createTextNode(data)] + } + + injectTextNode(parentElement, nodes[0], index, data) + } + } + cached = new data.constructor(data) + cached.nodes = nodes + return cached + } + + function handleTextNode( + cached, + data, + index, + parentElement, + shouldReattach, + editable, + parentTag + ) { + if (!cached.nodes.length) { + return handleNonexistentNodes(data, parentElement, index) + } else if (cached.valueOf() !== data.valueOf() || shouldReattach) { + return reattachNodes(data, cached, parentElement, editable, index, + parentTag) + } else { + return (cached.nodes.intact = true, cached) + } + } + + function getSubArrayCount(item) { + if (item.$trusted) { + // fix offset of next element if item was a trusted string w/ more + // than one html element + // the first clause in the regexp matches elements + // the second clause (after the pipe) matches text nodes + var match = item.match(/<[^\/]|\>\s*[^<]/g) + if (match != null) return match.length + } else if (isArray(item)) { + return item.length + } + return 1 + } + + function buildArray( + data, + cached, + parentElement, + index, + parentTag, + shouldReattach, + editable, + namespace, + configs + ) { + data = flatten(data) + var nodes = [] + var intact = cached.length === data.length + var subArrayCount = 0 + + // keys algorithm: sort elements without recreating them if keys are + // present + // + // 1) create a map of all existing keys, and mark all for deletion + // 2) add new keys to map and mark them for addition + // 3) if key exists in new list, change action from deletion to a move + // 4) for each key, handle its corresponding action as marked in + // previous steps + + var existing = {} + var shouldMaintainIdentities = false + + forKeys(cached, function (attrs, i) { + shouldMaintainIdentities = true + existing[cached[i].attrs.key] = {action: DELETION, index: i} + }) + + buildArrayKeys(data) + if (shouldMaintainIdentities) { + cached = diffKeys(data, cached, existing, parentElement) + } + // end key algorithm + + var cacheCount = 0 + // faster explicitly written + for (var i = 0, len = data.length; i < len; i++) { + // diff each item in the array + var item = build( + parentElement, + parentTag, + cached, + index, + data[i], + cached[cacheCount], + shouldReattach, + index + subArrayCount || subArrayCount, + editable, + namespace, + configs) + + if (item !== undefined) { + intact = intact && item.nodes.intact + subArrayCount += getSubArrayCount(item) + cached[cacheCount++] = item + } + } + + if (!intact) diffArray(data, cached, nodes) + return cached + } + + function makeCache(data, cached, index, parentIndex, parentCache) { + if (cached != null) { + if (type.call(cached) === type.call(data)) return cached + + if (parentCache && parentCache.nodes) { + var offset = index - parentIndex + var end = offset + (isArray(data) ? data : cached.nodes).length + clear( + parentCache.nodes.slice(offset, end), + parentCache.slice(offset, end)) + } else if (cached.nodes) { + clear(cached.nodes, cached) + } + } + + cached = new data.constructor() + // if constructor creates a virtual dom element, use a blank object as + // the base cached node instead of copying the virtual el (#277) + if (cached.tag) cached = {} + cached.nodes = [] + return cached + } + + function constructNode(data, namespace) { + if (data.attrs.is) { + if (namespace == null) { + return $document.createElement(data.tag, data.attrs.is) + } else { + return $document.createElementNS(namespace, data.tag, + data.attrs.is) + } + } else if (namespace == null) { + return $document.createElement(data.tag) + } else { + return $document.createElementNS(namespace, data.tag) + } + } + + function constructAttrs(data, node, namespace, hasKeys) { + if (hasKeys) { + return setAttributes(node, data.tag, data.attrs, {}, namespace) + } else { + return data.attrs + } + } + + function constructChildren( + data, + node, + cached, + editable, + namespace, + configs + ) { + if (data.children != null && data.children.length > 0) { + return build( + node, + data.tag, + undefined, + undefined, + data.children, + cached.children, + true, + 0, + data.attrs.contenteditable ? node : editable, + namespace, + configs) + } else { + return data.children + } + } + + function reconstructCached( + data, + attrs, + children, + node, + namespace, + views, + controllers + ) { + var cached = { + tag: data.tag, + attrs: attrs, + children: children, + nodes: [node] + } + + unloadCachedControllers(cached, views, controllers) + + if (cached.children && !cached.children.nodes) { + cached.children.nodes = [] + } + + // edge case: setting value on <select> doesn't work before children + // exist, so set it again after children have been created + if (data.tag === "select" && "value" in data.attrs) { + setAttributes(node, data.tag, {value: data.attrs.value}, {}, + namespace) + } + + return cached + } + + function getController(views, view, cachedControllers, controller) { + var controllerIndex + + if (m.redraw.strategy() === "diff" && views) { + controllerIndex = views.indexOf(view) + } else { + controllerIndex = -1 + } + + if (controllerIndex > -1) { + return cachedControllers[controllerIndex] + } else if (isFunction(controller)) { + return new controller() + } else { + return {} + } + } + + var unloaders = [] + + function updateLists(views, controllers, view, controller) { + if (controller.onunload != null) { + unloaders.push({ + controller: controller, + handler: controller.onunload + }) + } + + views.push(view) + controllers.push(controller) + } + + var forcing = false + function checkView(data, view, cached, cachedControllers, controllers, views) { + var controller = getController(cached.views, view, cachedControllers, data.controller) + var key = data && data.attrs && data.attrs.key + data = pendingRequests === 0 || forcing || cachedControllers && cachedControllers.indexOf(controller) > -1 ? data.view(controller) : {tag: "placeholder"} + if (data.subtree === "retain") return data; + data.attrs = data.attrs || {} + data.attrs.key = key + updateLists(views, controllers, view, controller) + return data + } + + function markViews(data, cached, views, controllers) { + var cachedControllers = cached && cached.controllers + + while (data.view != null) { + data = checkView( + data, + data.view.$original || data.view, + cached, + cachedControllers, + controllers, + views) + } + + return data + } + + function buildObject( // eslint-disable-line max-statements + data, + cached, + editable, + parentElement, + index, + shouldReattach, + namespace, + configs + ) { + var views = [] + var controllers = [] + + data = markViews(data, cached, views, controllers) + + if (data.subtree === "retain") return cached + + if (!data.tag && controllers.length) { + throw new Error("Component template must return a virtual " + + "element, not an array, string, etc.") + } + + data.attrs = data.attrs || {} + cached.attrs = cached.attrs || {} + + var dataAttrKeys = Object.keys(data.attrs) + var hasKeys = dataAttrKeys.length > ("key" in data.attrs ? 1 : 0) + + maybeRecreateObject(data, cached, dataAttrKeys) + + if (!isString(data.tag)) return + + var isNew = cached.nodes.length === 0 + + namespace = getObjectNamespace(data, namespace) + + var node + if (isNew) { + node = constructNode(data, namespace) + // set attributes first, then create children + var attrs = constructAttrs(data, node, namespace, hasKeys) + + var children = constructChildren(data, node, cached, editable, + namespace, configs) + + cached = reconstructCached( + data, + attrs, + children, + node, + namespace, + views, + controllers) + } else { + node = buildUpdatedNode( + cached, + data, + editable, + hasKeys, + namespace, + views, + configs, + controllers) + } + + if (isNew || shouldReattach === true && node != null) { + insertNode(parentElement, node, index) + } + + // The configs are called after `build` finishes running + scheduleConfigsToBeCalled(configs, data, node, isNew, cached) + + return cached + } + + function build( + parentElement, + parentTag, + parentCache, + parentIndex, + data, + cached, + shouldReattach, + index, + editable, + namespace, + configs + ) { + /* + * `build` is a recursive function that manages creation/diffing/removal + * of DOM elements based on comparison between `data` and `cached` the + * diff algorithm can be summarized as this: + * + * 1 - compare `data` and `cached` + * 2 - if they are different, copy `data` to `cached` and update the DOM + * based on what the difference is + * 3 - recursively apply this algorithm for every array and for the + * children of every virtual element + * + * The `cached` data structure is essentially the same as the previous + * redraw's `data` data structure, with a few additions: + * - `cached` always has a property called `nodes`, which is a list of + * DOM elements that correspond to the data represented by the + * respective virtual element + * - in order to support attaching `nodes` as a property of `cached`, + * `cached` is *always* a non-primitive object, i.e. if the data was + * a string, then cached is a String instance. If data was `null` or + * `undefined`, cached is `new String("")` + * - `cached also has a `configContext` property, which is the state + * storage object exposed by config(element, isInitialized, context) + * - when `cached` is an Object, it represents a virtual element; when + * it's an Array, it represents a list of elements; when it's a + * String, Number or Boolean, it represents a text node + * + * `parentElement` is a DOM element used for W3C DOM API calls + * `parentTag` is only used for handling a corner case for textarea + * values + * `parentCache` is used to remove nodes in some multi-node cases + * `parentIndex` and `index` are used to figure out the offset of nodes. + * They're artifacts from before arrays started being flattened and are + * likely refactorable + * `data` and `cached` are, respectively, the new and old nodes being + * diffed + * `shouldReattach` is a flag indicating whether a parent node was + * recreated (if so, and if this node is reused, then this node must + * reattach itself to the new parent) + * `editable` is a flag that indicates whether an ancestor is + * contenteditable + * `namespace` indicates the closest HTML namespace as it cascades down + * from an ancestor + * `configs` is a list of config functions to run after the topmost + * `build` call finishes running + * + * there's logic that relies on the assumption that null and undefined + * data are equivalent to empty strings + * - this prevents lifecycle surprises from procedural helpers that mix + * implicit and explicit return statements (e.g. + * function foo() {if (cond) return m("div")} + * - it simplifies diffing code + */ + data = dataToString(data) + if (data.subtree === "retain") return cached + cached = makeCache(data, cached, index, parentIndex, parentCache) + + if (isArray(data)) { + return buildArray( + data, + cached, + parentElement, + index, + parentTag, + shouldReattach, + editable, + namespace, + configs) + } else if (data != null && isObject(data)) { + return buildObject( + data, + cached, + editable, + parentElement, + index, + shouldReattach, + namespace, + configs) + } else if (!isFunction(data)) { + return handleTextNode( + cached, + data, + index, + parentElement, + shouldReattach, + editable, + parentTag) + } else { + return cached + } + } + + function sortChanges(a, b) { + return a.action - b.action || a.index - b.index + } + + function copyStyleAttrs(node, dataAttr, cachedAttr) { + for (var rule in dataAttr) if (hasOwn.call(dataAttr, rule)) { + if (cachedAttr == null || cachedAttr[rule] !== dataAttr[rule]) { + node.style[rule] = dataAttr[rule] + } + } + + for (rule in cachedAttr) if (hasOwn.call(cachedAttr, rule)) { + if (!hasOwn.call(dataAttr, rule)) node.style[rule] = "" + } + } + + function shouldUseSetAttribute(attrName) { + return attrName !== "list" && + attrName !== "style" && + attrName !== "form" && + attrName !== "type" && + attrName !== "width" && + attrName !== "height" + } + + function setSingleAttr( + node, + attrName, + dataAttr, + cachedAttr, + tag, + namespace + ) { + if (attrName === "config" || attrName === "key") { + // `config` isn't a real attribute, so ignore it + return true + } else if (isFunction(dataAttr) && attrName.slice(0, 2) === "on") { + // hook event handlers to the auto-redrawing system + node[attrName] = autoredraw(dataAttr, node) + } else if (attrName === "style" && dataAttr != null && + isObject(dataAttr)) { + // handle `style: {...}` + copyStyleAttrs(node, dataAttr, cachedAttr) + } else if (namespace != null) { + // handle SVG + if (attrName === "href") { + node.setAttributeNS("http://www.w3.org/1999/xlink", + "href", dataAttr) + } else { + node.setAttribute( + attrName === "className" ? "class" : attrName, + dataAttr) + } + } else if (attrName in node && shouldUseSetAttribute(attrName)) { + // handle cases that are properties (but ignore cases where we + // should use setAttribute instead) + // + // - list and form are typically used as strings, but are DOM + // element references in js + // + // - when using CSS selectors (e.g. `m("[style='']")`), style is + // used as a string, but it's an object in js + // + // #348 don't set the value if not needed - otherwise, cursor + // placement breaks in Chrome + try { + if (tag !== "input" || node[attrName] !== dataAttr) { + node[attrName] = dataAttr + } + } catch (e) { + node.setAttribute(attrName, dataAttr) + } + } + else node.setAttribute(attrName, dataAttr) + } + + function trySetAttr( + node, + attrName, + dataAttr, + cachedAttr, + cachedAttrs, + tag, + namespace + ) { + if (!(attrName in cachedAttrs) || (cachedAttr !== dataAttr)) { + cachedAttrs[attrName] = dataAttr + try { + return setSingleAttr( + node, + attrName, + dataAttr, + cachedAttr, + tag, + namespace) + } catch (e) { + // swallow IE's invalid argument errors to mimic HTML's + // fallback-to-doing-nothing-on-invalid-attributes behavior + if (e.message.indexOf("Invalid argument") < 0) throw e + } + } else if (attrName === "value" && tag === "input" && + node.value !== dataAttr) { + // #348 dataAttr may not be a string, so use loose comparison + node.value = dataAttr + } + } + + function setAttributes(node, tag, dataAttrs, cachedAttrs, namespace) { + for (var attrName in dataAttrs) if (hasOwn.call(dataAttrs, attrName)) { + if (trySetAttr( + node, + attrName, + dataAttrs[attrName], + cachedAttrs[attrName], + cachedAttrs, + tag, + namespace)) { + continue + } + } + return cachedAttrs + } + + function clear(nodes, cached) { + for (var i = nodes.length - 1; i > -1; i--) { + if (nodes[i] && nodes[i].parentNode) { + try { + nodes[i].parentNode.removeChild(nodes[i]) + } catch (e) { + /* eslint-disable max-len */ + // ignore if this fails due to order of events (see + // http://stackoverflow.com/questions/21926083/failed-to-execute-removechild-on-node) + /* eslint-enable max-len */ + } + cached = [].concat(cached) + if (cached[i]) unload(cached[i]) + } + } + // release memory if nodes is an array. This check should fail if nodes + // is a NodeList (see loop above) + if (nodes.length) { + nodes.length = 0 + } + } + + function unload(cached) { + if (cached.configContext && isFunction(cached.configContext.onunload)) { + cached.configContext.onunload() + cached.configContext.onunload = null + } + if (cached.controllers) { + forEach(cached.controllers, function (controller) { + if (isFunction(controller.onunload)) { + controller.onunload({preventDefault: noop}) + } + }) + } + if (cached.children) { + if (isArray(cached.children)) forEach(cached.children, unload) + else if (cached.children.tag) unload(cached.children) + } + } + + function appendTextFragment(parentElement, data) { + try { + parentElement.appendChild( + $document.createRange().createContextualFragment(data)) + } catch (e) { + parentElement.insertAdjacentHTML("beforeend", data) + } + } + + function injectHTML(parentElement, index, data) { + var nextSibling = parentElement.childNodes[index] + if (nextSibling) { + var isElement = nextSibling.nodeType !== 1 + var placeholder = $document.createElement("span") + if (isElement) { + parentElement.insertBefore(placeholder, nextSibling || null) + placeholder.insertAdjacentHTML("beforebegin", data) + parentElement.removeChild(placeholder) + } else { + nextSibling.insertAdjacentHTML("beforebegin", data) + } + } else { + appendTextFragment(parentElement, data) + } + + var nodes = [] + + while (parentElement.childNodes[index] !== nextSibling) { + nodes.push(parentElement.childNodes[index]) + index++ + } + + return nodes + } + + function autoredraw(callback, object) { + return function (e) { + e = e || event + m.redraw.strategy("diff") + m.startComputation() + try { + return callback.call(object, e) + } finally { + endFirstComputation() + } + } + } + + var html + var documentNode = { + appendChild: function (node) { + if (html === undefined) html = $document.createElement("html") + if ($document.documentElement && + $document.documentElement !== node) { + $document.replaceChild(node, $document.documentElement) + } else { + $document.appendChild(node) + } + + this.childNodes = $document.childNodes + }, + + insertBefore: function (node) { + this.appendChild(node) + }, + + childNodes: [] + } + + var nodeCache = [] + var cellCache = {} + + m.render = function (root, cell, forceRecreation) { + if (!root) { + throw new Error("Ensure the DOM element being passed to " + + "m.route/m.mount/m.render is not undefined.") + } + var configs = [] + var id = getCellCacheKey(root) + var isDocumentRoot = root === $document + var node + + if (isDocumentRoot || root === $document.documentElement) { + node = documentNode + } else { + node = root + } + + if (isDocumentRoot && cell.tag !== "html") { + cell = {tag: "html", attrs: {}, children: cell} + } + + if (cellCache[id] === undefined) clear(node.childNodes) + if (forceRecreation === true) reset(root) + + cellCache[id] = build( + node, + null, + undefined, + undefined, + cell, + cellCache[id], + false, + 0, + null, + undefined, + configs) + + forEach(configs, function (config) { config() }) + } + + function getCellCacheKey(element) { + var index = nodeCache.indexOf(element) + return index < 0 ? nodeCache.push(element) - 1 : index + } + + m.trust = function (value) { + value = new String(value) // eslint-disable-line no-new-wrappers + value.$trusted = true + return value + } + + function gettersetter(store) { + function prop() { + if (arguments.length) store = arguments[0] + return store + } + + prop.toJSON = function () { + return store + } + + return prop + } + + m.prop = function (store) { + if ((store != null && isObject(store) || isFunction(store)) && + isFunction(store.then)) { + return propify(store) + } + + return gettersetter(store) + } + + var roots = [] + var components = [] + var controllers = [] + var lastRedrawId = null + var lastRedrawCallTime = 0 + var computePreRedrawHook = null + var computePostRedrawHook = null + var topComponent + var FRAME_BUDGET = 16 // 60 frames per second = 1 call per 16 ms + + function parameterize(component, args) { + function controller() { + /* eslint-disable no-invalid-this */ + return (component.controller || noop).apply(this, args) || this + /* eslint-enable no-invalid-this */ + } + + if (component.controller) { + controller.prototype = component.controller.prototype + } + + function view(ctrl) { + var currentArgs = [ctrl].concat(args) + for (var i = 1; i < arguments.length; i++) { + currentArgs.push(arguments[i]) + } + + return component.view.apply(component, currentArgs) + } + + view.$original = component.view + var output = {controller: controller, view: view} + if (args[0] && args[0].key != null) output.attrs = {key: args[0].key} + return output + } + + m.component = function (component) { + for (var args = [], i = 1; i < arguments.length; i++) { + args.push(arguments[i]) + } + + return parameterize(component, args) + } + + function checkPrevented(component, root, index, isPrevented) { + if (!isPrevented) { + m.redraw.strategy("all") + m.startComputation() + roots[index] = root + var currentComponent + + if (component) { + currentComponent = topComponent = component + } else { + currentComponent = topComponent = component = {controller: noop} + } + + var controller = new (component.controller || noop)() + + // controllers may call m.mount recursively (via m.route redirects, + // for example) + // this conditional ensures only the last recursive m.mount call is + // applied + if (currentComponent === topComponent) { + controllers[index] = controller + components[index] = component + } + endFirstComputation() + if (component === null) { + removeRootElement(root, index) + } + return controllers[index] + } else if (component == null) { + removeRootElement(root, index) + } + } + + m.mount = m.module = function (root, component) { + if (!root) { + throw new Error("Please ensure the DOM element exists before " + + "rendering a template into it.") + } + + var index = roots.indexOf(root) + if (index < 0) index = roots.length + + var isPrevented = false + var event = { + preventDefault: function () { + isPrevented = true + computePreRedrawHook = computePostRedrawHook = null + } + } + + forEach(unloaders, function (unloader) { + unloader.handler.call(unloader.controller, event) + unloader.controller.onunload = null + }) + + if (isPrevented) { + forEach(unloaders, function (unloader) { + unloader.controller.onunload = unloader.handler + }) + } else { + unloaders = [] + } + + if (controllers[index] && isFunction(controllers[index].onunload)) { + controllers[index].onunload(event) + } + + return checkPrevented(component, root, index, isPrevented) + } + + function removeRootElement(root, index) { + roots.splice(index, 1) + controllers.splice(index, 1) + components.splice(index, 1) + reset(root) + nodeCache.splice(getCellCacheKey(root), 1) + } + + var redrawing = false + m.redraw = function (force) { + if (redrawing) return + redrawing = true + if (force) forcing = true + + try { + // lastRedrawId is a positive number if a second redraw is requested + // before the next animation frame + // lastRedrawID is null if it's the first redraw and not an event + // handler + if (lastRedrawId && !force) { + // when setTimeout: only reschedule redraw if time between now + // and previous redraw is bigger than a frame, otherwise keep + // currently scheduled timeout + // when rAF: always reschedule redraw + if ($requestAnimationFrame === global.requestAnimationFrame || + new Date() - lastRedrawCallTime > FRAME_BUDGET) { + if (lastRedrawId > 0) $cancelAnimationFrame(lastRedrawId) + lastRedrawId = $requestAnimationFrame(redraw, FRAME_BUDGET) + } + } else { + redraw() + lastRedrawId = $requestAnimationFrame(function () { + lastRedrawId = null + }, FRAME_BUDGET) + } + } finally { + redrawing = forcing = false + } + } + + m.redraw.strategy = m.prop() + function redraw() { + if (computePreRedrawHook) { + computePreRedrawHook() + computePreRedrawHook = null + } + forEach(roots, function (root, i) { + var component = components[i] + if (controllers[i]) { + var args = [controllers[i]] + m.render(root, + component.view ? component.view(controllers[i], args) : "") + } + }) + // after rendering within a routed context, we need to scroll back to + // the top, and fetch the document title for history.pushState + if (computePostRedrawHook) { + computePostRedrawHook() + computePostRedrawHook = null + } + lastRedrawId = null + lastRedrawCallTime = new Date() + m.redraw.strategy("diff") + } + + function endFirstComputation() { + if (m.redraw.strategy() === "none") { + pendingRequests-- + m.redraw.strategy("diff") + } else { + m.endComputation() + } + } + + m.withAttr = function (prop, withAttrCallback, callbackThis) { + return function (e) { + e = e || event + /* eslint-disable no-invalid-this */ + var currentTarget = e.currentTarget || this + var _this = callbackThis || this + /* eslint-enable no-invalid-this */ + var target = prop in currentTarget ? + currentTarget[prop] : + currentTarget.getAttribute(prop) + withAttrCallback.call(_this, target) + } + } + + // routing + var modes = {pathname: "", hash: "#", search: "?"} + var redirect = noop + var isDefaultRoute = false + var routeParams, currentRoute + + m.route = function (root, arg1, arg2, vdom) { // eslint-disable-line + // m.route() + if (arguments.length === 0) return currentRoute + // m.route(el, defaultRoute, routes) + if (arguments.length === 3 && isString(arg1)) { + redirect = function (source) { + var path = currentRoute = normalizeRoute(source) + if (!routeByValue(root, arg2, path)) { + if (isDefaultRoute) { + throw new Error("Ensure the default route matches " + + "one of the routes defined in m.route") + } + + isDefaultRoute = true + m.route(arg1, true) + isDefaultRoute = false + } + } + + var listener = m.route.mode === "hash" ? + "onhashchange" : + "onpopstate" + + global[listener] = function () { + var path = $location[m.route.mode] + if (m.route.mode === "pathname") path += $location.search + if (currentRoute !== normalizeRoute(path)) redirect(path) + } + + computePreRedrawHook = setScroll + global[listener]() + + return + } + + // config: m.route + if (root.addEventListener || root.attachEvent) { + var base = m.route.mode !== "pathname" ? $location.pathname : "" + root.href = base + modes[m.route.mode] + vdom.attrs.href + if (root.addEventListener) { + root.removeEventListener("click", routeUnobtrusive) + root.addEventListener("click", routeUnobtrusive) + } else { + root.detachEvent("onclick", routeUnobtrusive) + root.attachEvent("onclick", routeUnobtrusive) + } + + return + } + // m.route(route, params, shouldReplaceHistoryEntry) + if (isString(root)) { + var oldRoute = currentRoute + currentRoute = root + + var args = arg1 || {} + var queryIndex = currentRoute.indexOf("?") + var params + + if (queryIndex > -1) { + params = parseQueryString(currentRoute.slice(queryIndex + 1)) + } else { + params = {} + } + + for (var i in args) if (hasOwn.call(args, i)) { + params[i] = args[i] + } + + var querystring = buildQueryString(params) + var currentPath + + if (queryIndex > -1) { + currentPath = currentRoute.slice(0, queryIndex) + } else { + currentPath = currentRoute + } + + if (querystring) { + currentRoute = currentPath + + (currentPath.indexOf("?") === -1 ? "?" : "&") + + querystring + } + + var replaceHistory = + (arguments.length === 3 ? arg2 : arg1) === true || + oldRoute === root + + if (global.history.pushState) { + var method = replaceHistory ? "replaceState" : "pushState" + computePreRedrawHook = setScroll + computePostRedrawHook = function () { + global.history[method](null, $document.title, + modes[m.route.mode] + currentRoute) + } + redirect(modes[m.route.mode] + currentRoute) + } else { + $location[m.route.mode] = currentRoute + redirect(modes[m.route.mode] + currentRoute) + } + } + } + + m.route.param = function (key) { + if (!routeParams) { + throw new Error("You must call m.route(element, defaultRoute, " + + "routes) before calling m.route.param()") + } + + if (!key) { + return routeParams + } + + return routeParams[key] + } + + m.route.mode = "search" + + function normalizeRoute(route) { + return route.slice(modes[m.route.mode].length) + } + + function routeByValue(root, router, path) { + routeParams = {} + + var queryStart = path.indexOf("?") + if (queryStart !== -1) { + routeParams = parseQueryString( + path.substr(queryStart + 1, path.length)) + path = path.substr(0, queryStart) + } + + // Get all routes and check if there's + // an exact match for the current path + var keys = Object.keys(router) + var index = keys.indexOf(path) + + if (index !== -1){ + m.mount(root, router[keys [index]]) + return true + } + + for (var route in router) if (hasOwn.call(router, route)) { + if (route === path) { + m.mount(root, router[route]) + return true + } + + var matcher = new RegExp("^" + route + .replace(/:[^\/]+?\.{3}/g, "(.*?)") + .replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$") + + if (matcher.test(path)) { + /* eslint-disable no-loop-func */ + path.replace(matcher, function () { + var keys = route.match(/:[^\/]+/g) || [] + var values = [].slice.call(arguments, 1, -2) + forEach(keys, function (key, i) { + routeParams[key.replace(/:|\./g, "")] = + decodeURIComponent(values[i]) + }) + m.mount(root, router[route]) + }) + /* eslint-enable no-loop-func */ + return true + } + } + } + + function routeUnobtrusive(e) { + e = e || event + if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return + + if (e.preventDefault) { + e.preventDefault() + } else { + e.returnValue = false + } + + var currentTarget = e.currentTarget || e.srcElement + var args + + if (m.route.mode === "pathname" && currentTarget.search) { + args = parseQueryString(currentTarget.search.slice(1)) + } else { + args = {} + } + + while (currentTarget && !/a/i.test(currentTarget.nodeName)) { + currentTarget = currentTarget.parentNode + } + + // clear pendingRequests because we want an immediate route change + pendingRequests = 0 + m.route(currentTarget[m.route.mode] + .slice(modes[m.route.mode].length), args) + } + + function setScroll() { + if (m.route.mode !== "hash" && $location.hash) { + $location.hash = $location.hash + } else { + global.scrollTo(0, 0) + } + } + + function buildQueryString(object, prefix) { + var duplicates = {} + var str = [] + + for (var prop in object) if (hasOwn.call(object, prop)) { + var key = prefix ? prefix + "[" + prop + "]" : prop + var value = object[prop] + + if (value === null) { + str.push(encodeURIComponent(key)) + } else if (isObject(value)) { + str.push(buildQueryString(value, key)) + } else if (isArray(value)) { + var keys = [] + duplicates[key] = duplicates[key] || {} + /* eslint-disable no-loop-func */ + forEach(value, function (item) { + /* eslint-enable no-loop-func */ + if (!duplicates[key][item]) { + duplicates[key][item] = true + keys.push(encodeURIComponent(key) + "=" + + encodeURIComponent(item)) + } + }) + str.push(keys.join("&")) + } else if (value !== undefined) { + str.push(encodeURIComponent(key) + "=" + + encodeURIComponent(value)) + } + } + return str.join("&") + } + + function parseQueryString(str) { + if (str === "" || str == null) return {} + if (str.charAt(0) === "?") str = str.slice(1) + + var pairs = str.split("&") + var params = {} + + forEach(pairs, function (string) { + var pair = string.split("=") + var key = decodeURIComponent(pair[0]) + var value = pair.length === 2 ? decodeURIComponent(pair[1]) : null + if (params[key] != null) { + if (!isArray(params[key])) params[key] = [params[key]] + params[key].push(value) + } + else params[key] = value + }) + + return params + } + + m.route.buildQueryString = buildQueryString + m.route.parseQueryString = parseQueryString + + function reset(root) { + var cacheKey = getCellCacheKey(root) + clear(root.childNodes, cellCache[cacheKey]) + cellCache[cacheKey] = undefined + } + + m.deferred = function () { + var deferred = new Deferred() + deferred.promise = propify(deferred.promise) + return deferred + } + + function propify(promise, initialValue) { + var prop = m.prop(initialValue) + promise.then(prop) + prop.then = function (resolve, reject) { + return propify(promise.then(resolve, reject), initialValue) + } + + prop.catch = prop.then.bind(null, null) + return prop + } + // Promiz.mithril.js | Zolmeister | MIT + // a modified version of Promiz.js, which does not conform to Promises/A+ + // for two reasons: + // + // 1) `then` callbacks are called synchronously (because setTimeout is too + // slow, and the setImmediate polyfill is too big + // + // 2) throwing subclasses of Error cause the error to be bubbled up instead + // of triggering rejection (because the spec does not account for the + // important use case of default browser error handling, i.e. message w/ + // line number) + + var RESOLVING = 1 + var REJECTING = 2 + var RESOLVED = 3 + var REJECTED = 4 + + function Deferred(onSuccess, onFailure) { + var self = this + var state = 0 + var promiseValue = 0 + var next = [] + + self.promise = {} + + self.resolve = function (value) { + if (!state) { + promiseValue = value + state = RESOLVING + + fire() + } + + return self + } + + self.reject = function (value) { + if (!state) { + promiseValue = value + state = REJECTING + + fire() + } + + return self + } + + self.promise.then = function (onSuccess, onFailure) { + var deferred = new Deferred(onSuccess, onFailure) + + if (state === RESOLVED) { + deferred.resolve(promiseValue) + } else if (state === REJECTED) { + deferred.reject(promiseValue) + } else { + next.push(deferred) + } + + return deferred.promise + } + + function finish(type) { + state = type || REJECTED + next.map(function (deferred) { + if (state === RESOLVED) { + deferred.resolve(promiseValue) + } else { + deferred.reject(promiseValue) + } + }) + } + + function thennable(then, success, failure, notThennable) { + if (((promiseValue != null && isObject(promiseValue)) || + isFunction(promiseValue)) && isFunction(then)) { + try { + // count protects against abuse calls from spec checker + var count = 0 + then.call(promiseValue, function (value) { + if (count++) return + promiseValue = value + success() + }, function (value) { + if (count++) return + promiseValue = value + failure() + }) + } catch (e) { + m.deferred.onerror(e) + promiseValue = e + failure() + } + } else { + notThennable() + } + } + + function fire() { + // check if it's a thenable + var then + try { + then = promiseValue && promiseValue.then + } catch (e) { + m.deferred.onerror(e) + promiseValue = e + state = REJECTING + return fire() + } + + if (state === REJECTING) { + m.deferred.onerror(promiseValue) + } + + thennable(then, function () { + state = RESOLVING + fire() + }, function () { + state = REJECTING + fire() + }, function () { + try { + if (state === RESOLVING && isFunction(onSuccess)) { + promiseValue = onSuccess(promiseValue) + } else if (state === REJECTING && isFunction(onFailure)) { + promiseValue = onFailure(promiseValue) + state = RESOLVING + } + } catch (e) { + m.deferred.onerror(e) + promiseValue = e + return finish() + } + + if (promiseValue === self) { + promiseValue = TypeError() + finish() + } else { + thennable(then, function () { + finish(RESOLVED) + }, finish, function () { + finish(state === RESOLVING && RESOLVED) + }) + } + }) + } + } + + m.deferred.onerror = function (e) { + if (type.call(e) === "[object Error]" && + !e.constructor.toString().match(/ Error/)) { + pendingRequests = 0 + throw e + } + } + + m.sync = function (args) { + var deferred = m.deferred() + var outstanding = args.length + var results = new Array(outstanding) + var method = "resolve" + + function synchronizer(pos, resolved) { + return function (value) { + results[pos] = value + if (!resolved) method = "reject" + if (--outstanding === 0) { + deferred.promise(results) + deferred[method](results) + } + return value + } + } + + if (args.length > 0) { + forEach(args, function (arg, i) { + arg.then(synchronizer(i, true), synchronizer(i, false)) + }) + } else { + deferred.resolve([]) + } + + return deferred.promise + } + + function identity(value) { return value } + + function handleJsonp(options) { + var callbackKey = "mithril_callback_" + + new Date().getTime() + "_" + + (Math.round(Math.random() * 1e16)).toString(36) + + var script = $document.createElement("script") + + global[callbackKey] = function (resp) { + script.parentNode.removeChild(script) + options.onload({ + type: "load", + target: { + responseText: resp + } + }) + global[callbackKey] = undefined + } + + script.onerror = function () { + script.parentNode.removeChild(script) + + options.onerror({ + type: "error", + target: { + status: 500, + responseText: JSON.stringify({ + error: "Error making jsonp request" + }) + } + }) + global[callbackKey] = undefined + + return false + } + + script.onload = function () { + return false + } + + script.src = options.url + + (options.url.indexOf("?") > 0 ? "&" : "?") + + (options.callbackKey ? options.callbackKey : "callback") + + "=" + callbackKey + + "&" + buildQueryString(options.data || {}) + + $document.body.appendChild(script) + } + + function createXhr(options) { + var xhr = new global.XMLHttpRequest() + xhr.open(options.method, options.url, true, options.user, + options.password) + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (xhr.status >= 200 && xhr.status < 300) { + options.onload({type: "load", target: xhr}) + } else { + options.onerror({type: "error", target: xhr}) + } + } + } + + if (options.serialize === JSON.stringify && + options.data && + options.method !== "GET") { + xhr.setRequestHeader("Content-Type", + "application/json; charset=utf-8") + } + + if (options.deserialize === JSON.parse) { + xhr.setRequestHeader("Accept", "application/json, text/*") + } + + if (isFunction(options.config)) { + var maybeXhr = options.config(xhr, options) + if (maybeXhr != null) xhr = maybeXhr + } + + var data = options.method === "GET" || !options.data ? "" : options.data + + if (data && !isString(data) && data.constructor !== global.FormData) { + throw new Error("Request data should be either be a string or " + + "FormData. Check the `serialize` option in `m.request`") + } + + xhr.send(data) + return xhr + } + + function ajax(options) { + if (options.dataType && options.dataType.toLowerCase() === "jsonp") { + return handleJsonp(options) + } else { + return createXhr(options) + } + } + + function bindData(options, data, serialize) { + if (options.method === "GET" && options.dataType !== "jsonp") { + var prefix = options.url.indexOf("?") < 0 ? "?" : "&" + var querystring = buildQueryString(data) + options.url += (querystring ? prefix + querystring : "") + } else { + options.data = serialize(data) + } + } + + function parameterizeUrl(url, data) { + var tokens = url.match(/:[a-z]\w+/gi) + + if (tokens && data) { + forEach(tokens, function (token) { + var key = token.slice(1) + url = url.replace(token, data[key]) + delete data[key] + }) + } + + return url + } + + m.request = function (options) { + if (options.background !== true) m.startComputation() + var deferred = new Deferred() + var isJSONP = options.dataType && + options.dataType.toLowerCase() === "jsonp" + + var serialize, deserialize, extract + + if (isJSONP) { + serialize = options.serialize = + deserialize = options.deserialize = identity + + extract = function (jsonp) { return jsonp.responseText } + } else { + serialize = options.serialize = options.serialize || JSON.stringify + + deserialize = options.deserialize = + options.deserialize || JSON.parse + extract = options.extract || function (xhr) { + if (xhr.responseText.length || deserialize !== JSON.parse) { + return xhr.responseText + } else { + return null + } + } + } + + options.method = (options.method || "GET").toUpperCase() + options.url = parameterizeUrl(options.url, options.data) + bindData(options, options.data, serialize) + options.onload = options.onerror = function (ev) { + try { + ev = ev || event + var response = deserialize(extract(ev.target, options)) + if (ev.type === "load") { + if (options.unwrapSuccess) { + response = options.unwrapSuccess(response, ev.target) + } + + if (isArray(response) && options.type) { + forEach(response, function (res, i) { + response[i] = new options.type(res) + }) + } else if (options.type) { + response = new options.type(response) + } + + deferred.resolve(response) + } else { + if (options.unwrapError) { + response = options.unwrapError(response, ev.target) + } + + deferred.reject(response) + } + } catch (e) { + deferred.reject(e) + } finally { + if (options.background !== true) m.endComputation() + } + } + + ajax(options) + deferred.promise = propify(deferred.promise, options.initialValue) + return deferred.promise + } + + return m +}) diff --git a/lib/vendor/system-csp-production.src.js b/lib/vendor/system-csp-production.src.js new file mode 100644 index 000000000..0887780ca --- /dev/null +++ b/lib/vendor/system-csp-production.src.js @@ -0,0 +1,4155 @@ +/* + * SystemJS v0.19.17 + */ +(function() { +function bootstrap() {(function(__global) { + + var isWorker = typeof window == 'undefined' && typeof self != 'undefined' && typeof importScripts != 'undefined'; + var isBrowser = typeof window != 'undefined' && typeof document != 'undefined'; + var isWindows = typeof process != 'undefined' && typeof process.platform != 'undefined' && !!process.platform.match(/^win/); + + if (!__global.console) + __global.console = { assert: function() {} }; + + // IE8 support + var indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, thisLen = this.length; i < thisLen; i++) { + if (this[i] === item) { + return i; + } + } + return -1; + }; + + 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) {} + } + } + })(); + + function addToError(err, msg) { + var newErr; + if (err instanceof Error) { + newErr = new Error(err.message, err.fileName, err.lineNumber); + if (isBrowser) { + newErr.message = err.message + '\n\t' + msg; + newErr.stack = err.stack; + } + else { + // node errors only look correct with the stack modified + newErr.message = err.message; + newErr.stack = err.stack + '\n\t' + msg; + } + } + else { + newErr = err + '\n\t' + msg; + } + + return newErr; + } + + function __eval(source, debugName, context) { + try { + new Function(source).call(context); + } + catch(e) { + throw addToError(e, 'Evaluating ' + debugName); + } + } + + var baseURI; + // environent baseURI detection + if (typeof document != 'undefined' && document.getElementsByTagName) { + baseURI = document.baseURI; + + if (!baseURI) { + var bases = document.getElementsByTagName('base'); + baseURI = bases[0] && bases[0].href || window.location.href; + } + + // sanitize out the hash and querystring + baseURI = baseURI.split('#')[0].split('?')[0]; + baseURI = baseURI.substr(0, baseURI.lastIndexOf('/') + 1); + } + else if (typeof process != 'undefined' && process.cwd) { + baseURI = 'file://' + (isWindows ? '/' : '') + process.cwd() + '/'; + if (isWindows) + baseURI = baseURI.replace(/\\/g, '/'); + } + else if (typeof location != 'undefined') { + baseURI = __global.location.href; + } + else { + throw new TypeError('No environment baseURI'); + } + + var URL = __global.URLPolyfill || __global.URL; +/* +********************************************************************************************* + + Dynamic Module Loader Polyfill + + - Implemented exactly to the former 2014-08-24 ES6 Specification Draft Rev 27, Section 15 + http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#august_24_2014_draft_rev_27 + + - Functions are commented with their spec numbers, with spec differences commented. + + - Spec bugs are commented in this code with links. + + - Abstract functions have been combined where possible, and their associated functions + commented. + + - Realm implementation is entirely omitted. + +********************************************************************************************* +*/ + +function Module() {} +// http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag +defineProperty(Module.prototype, 'toString', { + value: function() { + return 'Module'; + } +}); +function Loader(options) { + this._loader = { + loaderObj: this, + loads: [], + modules: {}, + importPromises: {}, + moduleRecords: {} + }; + + // 26.3.3.6 + defineProperty(this, 'global', { + get: function() { + return __global; + } + }); + + // 26.3.3.13 realm not implemented +} + +(function() { + +// Some Helpers + +// logs a linkset snapshot for debugging +/* function snapshot(loader) { + console.log('---Snapshot---'); + for (var i = 0; i < loader.loads.length; i++) { + var load = loader.loads[i]; + var linkSetLog = ' ' + load.name + ' (' + load.status + '): '; + + for (var j = 0; j < load.linkSets.length; j++) { + linkSetLog += '{' + logloads(load.linkSets[j].loads) + '} '; + } + console.log(linkSetLog); + } + console.log(''); +} +function logloads(loads) { + var log = ''; + for (var k = 0; k < loads.length; k++) + log += loads[k].name + (k != loads.length - 1 ? ' ' : ''); + return log; +} */ + + +/* function checkInvariants() { + // see https://bugs.ecmascript.org/show_bug.cgi?id=2603#c1 + + var loads = System._loader.loads; + var linkSets = []; + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + console.assert(load.status == 'loading' || load.status == 'loaded', 'Each load is loading or loaded'); + + for (var j = 0; j < load.linkSets.length; j++) { + var linkSet = load.linkSets[j]; + + for (var k = 0; k < linkSet.loads.length; k++) + console.assert(loads.indexOf(linkSet.loads[k]) != -1, 'linkSet loads are a subset of loader loads'); + + if (linkSets.indexOf(linkSet) == -1) + linkSets.push(linkSet); + } + } + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + for (var j = 0; j < linkSets.length; j++) { + var linkSet = linkSets[j]; + + if (linkSet.loads.indexOf(load) != -1) + console.assert(load.linkSets.indexOf(linkSet) != -1, 'linkSet contains load -> load contains linkSet'); + + if (load.linkSets.indexOf(linkSet) != -1) + console.assert(linkSet.loads.indexOf(load) != -1, 'load contains linkSet -> linkSet contains load'); + } + } + + for (var i = 0; i < linkSets.length; i++) { + var linkSet = linkSets[i]; + for (var j = 0; j < linkSet.loads.length; j++) { + var load = linkSet.loads[j]; + + for (var k = 0; k < load.dependencies.length; k++) { + var depName = load.dependencies[k].value; + var depLoad; + for (var l = 0; l < loads.length; l++) { + if (loads[l].name != depName) + continue; + depLoad = loads[l]; + break; + } + + // loading records are allowed not to have their dependencies yet + // if (load.status != 'loading') + // console.assert(depLoad, 'depLoad found'); + + // console.assert(linkSet.loads.indexOf(depLoad) != -1, 'linkset contains all dependencies'); + } + } + } +} */ + + // 15.2.3 - Runtime Semantics: Loader State + + // 15.2.3.11 + function createLoaderLoad(object) { + return { + // modules is an object for ES5 implementation + modules: {}, + loads: [], + loaderObj: object + }; + } + + // 15.2.3.2 Load Records and LoadRequest Objects + + // 15.2.3.2.1 + function createLoad(name) { + return { + status: 'loading', + name: name, + linkSets: [], + dependencies: [], + metadata: {} + }; + } + + // 15.2.3.2.2 createLoadRequestObject, absorbed into calling functions + + // 15.2.4 + + // 15.2.4.1 + function loadModule(loader, name, options) { + return new Promise(asyncStartLoadPartwayThrough({ + step: options.address ? 'fetch' : 'locate', + loader: loader, + moduleName: name, + // allow metadata for import https://bugs.ecmascript.org/show_bug.cgi?id=3091 + moduleMetadata: options && options.metadata || {}, + moduleSource: options.source, + moduleAddress: options.address + })); + } + + // 15.2.4.2 + function requestLoad(loader, request, refererName, refererAddress) { + // 15.2.4.2.1 CallNormalize + return new Promise(function(resolve, reject) { + resolve(loader.loaderObj.normalize(request, refererName, refererAddress)); + }) + // 15.2.4.2.2 GetOrCreateLoad + .then(function(name) { + var load; + if (loader.modules[name]) { + load = createLoad(name); + load.status = 'linked'; + // https://bugs.ecmascript.org/show_bug.cgi?id=2795 + load.module = loader.modules[name]; + return load; + } + + for (var i = 0, l = loader.loads.length; i < l; i++) { + load = loader.loads[i]; + if (load.name != name) + continue; + console.assert(load.status == 'loading' || load.status == 'loaded', 'loading or loaded'); + return load; + } + + load = createLoad(name); + loader.loads.push(load); + + proceedToLocate(loader, load); + + return load; + }); + } + + // 15.2.4.3 + function proceedToLocate(loader, load) { + proceedToFetch(loader, load, + Promise.resolve() + // 15.2.4.3.1 CallLocate + .then(function() { + return loader.loaderObj.locate({ name: load.name, metadata: load.metadata }); + }) + ); + } + + // 15.2.4.4 + function proceedToFetch(loader, load, p) { + proceedToTranslate(loader, load, + p + // 15.2.4.4.1 CallFetch + .then(function(address) { + // adjusted, see https://bugs.ecmascript.org/show_bug.cgi?id=2602 + if (load.status != 'loading') + return; + load.address = address; + + return loader.loaderObj.fetch({ name: load.name, metadata: load.metadata, address: address }); + }) + ); + } + + var anonCnt = 0; + + // 15.2.4.5 + function proceedToTranslate(loader, load, p) { + p + // 15.2.4.5.1 CallTranslate + .then(function(source) { + if (load.status != 'loading') + return; + + return Promise.resolve(loader.loaderObj.translate({ name: load.name, metadata: load.metadata, address: load.address, source: source })) + + // 15.2.4.5.2 CallInstantiate + .then(function(source) { + load.source = source; + return loader.loaderObj.instantiate({ name: load.name, metadata: load.metadata, address: load.address, source: source }); + }) + + // 15.2.4.5.3 InstantiateSucceeded + .then(function(instantiateResult) { + if (instantiateResult === undefined) { + load.address = load.address || '<Anonymous Module ' + ++anonCnt + '>'; + + // instead of load.kind, use load.isDeclarative + load.isDeclarative = true; + return transpile.call(loader.loaderObj, load) + .then(function(transpiled) { + // Hijack System.register to set declare function + var curSystem = __global.System; + var curRegister = curSystem.register; + curSystem.register = function(name, deps, declare) { + if (typeof name != 'string') { + declare = deps; + deps = name; + } + // store the registered declaration as load.declare + // store the deps as load.deps + load.declare = declare; + load.depsList = deps; + } + // empty {} context is closest to undefined 'this' we can get + __eval(transpiled, load.address, {}); + curSystem.register = curRegister; + }); + } + else if (typeof instantiateResult == 'object') { + load.depsList = instantiateResult.deps || []; + load.execute = instantiateResult.execute; + load.isDeclarative = false; + } + else + throw TypeError('Invalid instantiate return value'); + }) + // 15.2.4.6 ProcessLoadDependencies + .then(function() { + load.dependencies = []; + var depsList = load.depsList; + + var loadPromises = []; + for (var i = 0, l = depsList.length; i < l; i++) (function(request, index) { + loadPromises.push( + requestLoad(loader, request, load.name, load.address) + + // 15.2.4.6.1 AddDependencyLoad (load is parentLoad) + .then(function(depLoad) { + + // adjusted from spec to maintain dependency order + // this is due to the System.register internal implementation needs + load.dependencies[index] = { + key: request, + value: depLoad.name + }; + + if (depLoad.status != 'linked') { + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + addLoadToLinkSet(linkSets[i], depLoad); + } + + // console.log('AddDependencyLoad ' + depLoad.name + ' for ' + load.name); + // snapshot(loader); + }) + ); + })(depsList[i], i); + + return Promise.all(loadPromises); + }) + + // 15.2.4.6.2 LoadSucceeded + .then(function() { + // console.log('LoadSucceeded ' + load.name); + // snapshot(loader); + + console.assert(load.status == 'loading', 'is loading'); + + load.status = 'loaded'; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + updateLinkSetOnLoad(linkSets[i], load); + }); + }) + // 15.2.4.5.4 LoadFailed + ['catch'](function(exc) { + load.status = 'failed'; + load.exception = exc; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) { + linkSetFailed(linkSets[i], load, exc); + } + + console.assert(load.linkSets.length == 0, 'linkSets not removed'); + }); + } + + // 15.2.4.7 PromiseOfStartLoadPartwayThrough absorbed into calling functions + + // 15.2.4.7.1 + function asyncStartLoadPartwayThrough(stepState) { + return function(resolve, reject) { + var loader = stepState.loader; + var name = stepState.moduleName; + var step = stepState.step; + + if (loader.modules[name]) + throw new TypeError('"' + name + '" already exists in the module table'); + + // adjusted to pick up existing loads + var existingLoad; + for (var i = 0, l = loader.loads.length; i < l; i++) { + if (loader.loads[i].name == name) { + existingLoad = loader.loads[i]; + + if (step == 'translate' && !existingLoad.source) { + existingLoad.address = stepState.moduleAddress; + proceedToTranslate(loader, existingLoad, Promise.resolve(stepState.moduleSource)); + } + + // a primary load -> use that existing linkset if it is for the direct load here + // otherwise create a new linkset unit + if (existingLoad.linkSets.length && existingLoad.linkSets[0].loads[0].name == existingLoad.name) + return existingLoad.linkSets[0].done.then(function() { + resolve(existingLoad); + }); + } + } + + var load = existingLoad || createLoad(name); + + load.metadata = stepState.moduleMetadata; + + var linkSet = createLinkSet(loader, load); + + loader.loads.push(load); + + resolve(linkSet.done); + + if (step == 'locate') + proceedToLocate(loader, load); + + else if (step == 'fetch') + proceedToFetch(loader, load, Promise.resolve(stepState.moduleAddress)); + + else { + console.assert(step == 'translate', 'translate step'); + load.address = stepState.moduleAddress; + proceedToTranslate(loader, load, Promise.resolve(stepState.moduleSource)); + } + } + } + + // Declarative linking functions run through alternative implementation: + // 15.2.5.1.1 CreateModuleLinkageRecord not implemented + // 15.2.5.1.2 LookupExport not implemented + // 15.2.5.1.3 LookupModuleDependency not implemented + + // 15.2.5.2.1 + function createLinkSet(loader, startingLoad) { + var linkSet = { + loader: loader, + loads: [], + startingLoad: startingLoad, // added see spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + loadingCount: 0 + }; + linkSet.done = new Promise(function(resolve, reject) { + linkSet.resolve = resolve; + linkSet.reject = reject; + }); + addLoadToLinkSet(linkSet, startingLoad); + return linkSet; + } + // 15.2.5.2.2 + function addLoadToLinkSet(linkSet, load) { + if (load.status == 'failed') + return; + + console.assert(load.status == 'loading' || load.status == 'loaded', 'loading or loaded on link set'); + + for (var i = 0, l = linkSet.loads.length; i < l; i++) + if (linkSet.loads[i] == load) + return; + + linkSet.loads.push(load); + load.linkSets.push(linkSet); + + // adjustment, see https://bugs.ecmascript.org/show_bug.cgi?id=2603 + if (load.status != 'loaded') { + linkSet.loadingCount++; + } + + var loader = linkSet.loader; + + for (var i = 0, l = load.dependencies.length; i < l; i++) { + if (!load.dependencies[i]) + continue; + + var name = load.dependencies[i].value; + + if (loader.modules[name]) + continue; + + for (var j = 0, d = loader.loads.length; j < d; j++) { + if (loader.loads[j].name != name) + continue; + + addLoadToLinkSet(linkSet, loader.loads[j]); + break; + } + } + // console.log('add to linkset ' + load.name); + // snapshot(linkSet.loader); + } + + // linking errors can be generic or load-specific + // this is necessary for debugging info + function doLink(linkSet) { + var error = false; + try { + link(linkSet, function(load, exc) { + linkSetFailed(linkSet, load, exc); + error = true; + }); + } + catch(e) { + linkSetFailed(linkSet, null, e); + error = true; + } + return error; + } + + // 15.2.5.2.3 + function updateLinkSetOnLoad(linkSet, load) { + // console.log('update linkset on load ' + load.name); + // snapshot(linkSet.loader); + + console.assert(load.status == 'loaded' || load.status == 'linked', 'loaded or linked'); + + linkSet.loadingCount--; + + if (linkSet.loadingCount > 0) + return; + + // adjusted for spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + var startingLoad = linkSet.startingLoad; + + // non-executing link variation for loader tracing + // on the server. Not in spec. + /***/ + if (linkSet.loader.loaderObj.execute === false) { + var loads = [].concat(linkSet.loads); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + load.module = !load.isDeclarative ? { + module: _newModule({}) + } : { + name: load.name, + module: _newModule({}), + evaluated: true + }; + load.status = 'linked'; + finishLoad(linkSet.loader, load); + } + return linkSet.resolve(startingLoad); + } + /***/ + + var abrupt = doLink(linkSet); + + if (abrupt) + return; + + console.assert(linkSet.loads.length == 0, 'loads cleared'); + + linkSet.resolve(startingLoad); + } + + // 15.2.5.2.4 + function linkSetFailed(linkSet, load, exc) { + var loader = linkSet.loader; + var requests; + + checkError: + if (load) { + if (linkSet.loads[0].name == load.name) { + exc = addToError(exc, 'Error loading ' + load.name); + } + else { + for (var i = 0; i < linkSet.loads.length; i++) { + var pLoad = linkSet.loads[i]; + for (var j = 0; j < pLoad.dependencies.length; j++) { + var dep = pLoad.dependencies[j]; + if (dep.value == load.name) { + exc = addToError(exc, 'Error loading ' + load.name + ' as "' + dep.key + '" from ' + pLoad.name); + break checkError; + } + } + } + exc = addToError(exc, 'Error loading ' + load.name + ' from ' + linkSet.loads[0].name); + } + } + else { + exc = addToError(exc, 'Error linking ' + linkSet.loads[0].name); + } + + + var loads = linkSet.loads.concat([]); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + + // store all failed load records + loader.loaderObj.failed = loader.loaderObj.failed || []; + if (indexOf.call(loader.loaderObj.failed, load) == -1) + loader.loaderObj.failed.push(load); + + var linkIndex = indexOf.call(load.linkSets, linkSet); + console.assert(linkIndex != -1, 'link not present'); + load.linkSets.splice(linkIndex, 1); + if (load.linkSets.length == 0) { + var globalLoadsIndex = indexOf.call(linkSet.loader.loads, load); + if (globalLoadsIndex != -1) + linkSet.loader.loads.splice(globalLoadsIndex, 1); + } + } + linkSet.reject(exc); + } + + // 15.2.5.2.5 + function finishLoad(loader, load) { + // add to global trace if tracing + if (loader.loaderObj.trace) { + if (!loader.loaderObj.loads) + loader.loaderObj.loads = {}; + var depMap = {}; + load.dependencies.forEach(function(dep) { + depMap[dep.key] = dep.value; + }); + loader.loaderObj.loads[load.name] = { + name: load.name, + deps: load.dependencies.map(function(dep){ return dep.key }), + depMap: depMap, + address: load.address, + metadata: load.metadata, + source: load.source, + kind: load.isDeclarative ? 'declarative' : 'dynamic' + }; + } + // if not anonymous, add to the module table + if (load.name) { + console.assert(!loader.modules[load.name], 'load not in module table'); + loader.modules[load.name] = load.module; + } + var loadIndex = indexOf.call(loader.loads, load); + if (loadIndex != -1) + loader.loads.splice(loadIndex, 1); + for (var i = 0, l = load.linkSets.length; i < l; i++) { + loadIndex = indexOf.call(load.linkSets[i].loads, load); + if (loadIndex != -1) + load.linkSets[i].loads.splice(loadIndex, 1); + } + load.linkSets.splice(0, load.linkSets.length); + } + + function doDynamicExecute(linkSet, load, linkError) { + try { + var module = load.execute(); + } + catch(e) { + linkError(load, e); + return; + } + if (!module || !(module instanceof Module)) + linkError(load, new TypeError('Execution must define a Module instance')); + else + return module; + } + + // 26.3 Loader + + // 26.3.1.1 + // defined at top + + // importPromises adds ability to import a module twice without error - https://bugs.ecmascript.org/show_bug.cgi?id=2601 + function createImportPromise(loader, name, promise) { + var importPromises = loader._loader.importPromises; + return importPromises[name] = promise.then(function(m) { + importPromises[name] = undefined; + return m; + }, function(e) { + importPromises[name] = undefined; + throw e; + }); + } + + Loader.prototype = { + // 26.3.3.1 + constructor: Loader, + // 26.3.3.2 + define: function(name, source, options) { + // check if already defined + if (this._loader.importPromises[name]) + throw new TypeError('Module is already loading.'); + return createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({ + step: 'translate', + loader: this._loader, + moduleName: name, + moduleMetadata: options && options.metadata || {}, + moduleSource: source, + moduleAddress: options && options.address + }))); + }, + // 26.3.3.3 + 'delete': function(name) { + var loader = this._loader; + delete loader.importPromises[name]; + delete loader.moduleRecords[name]; + return loader.modules[name] ? delete loader.modules[name] : false; + }, + // 26.3.3.4 entries not implemented + // 26.3.3.5 + get: function(key) { + if (!this._loader.modules[key]) + return; + doEnsureEvaluated(this._loader.modules[key], [], this); + return this._loader.modules[key].module; + }, + // 26.3.3.7 + has: function(name) { + return !!this._loader.modules[name]; + }, + // 26.3.3.8 + 'import': function(name, parentName, parentAddress) { + if (typeof parentName == 'object') + parentName = parentName.name; + + // run normalize first + var loaderObj = this; + + // added, see https://bugs.ecmascript.org/show_bug.cgi?id=2659 + return Promise.resolve(loaderObj.normalize(name, parentName)) + .then(function(name) { + var loader = loaderObj._loader; + + if (loader.modules[name]) { + doEnsureEvaluated(loader.modules[name], [], loader._loader); + return loader.modules[name].module; + } + + return loader.importPromises[name] || createImportPromise(loaderObj, name, + loadModule(loader, name, {}) + .then(function(load) { + delete loader.importPromises[name]; + return evaluateLoadedModule(loader, load); + })); + }); + }, + // 26.3.3.9 keys not implemented + // 26.3.3.10 + load: function(name) { + var loader = this._loader; + if (loader.modules[name]) + return Promise.resolve(); + return loader.importPromises[name] || createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({ + step: 'locate', + loader: loader, + moduleName: name, + moduleMetadata: {}, + moduleSource: undefined, + moduleAddress: undefined + })) + .then(function() { + delete loader.importPromises[name]; + })); + }, + // 26.3.3.11 + module: function(source, options) { + var load = createLoad(); + load.address = options && options.address; + var linkSet = createLinkSet(this._loader, load); + var sourcePromise = Promise.resolve(source); + var loader = this._loader; + var p = linkSet.done.then(function() { + return evaluateLoadedModule(loader, load); + }); + proceedToTranslate(loader, load, sourcePromise); + return p; + }, + // 26.3.3.12 + newModule: function (obj) { + if (typeof obj != 'object') + throw new TypeError('Expected object'); + + var m = new Module(); + + var pNames = []; + if (Object.getOwnPropertyNames && obj != null) + pNames = Object.getOwnPropertyNames(obj); + else + for (var key in obj) + pNames.push(key); + + for (var i = 0; i < pNames.length; i++) (function(key) { + defineProperty(m, key, { + configurable: false, + enumerable: true, + get: function () { + return obj[key]; + } + }); + })(pNames[i]); + + return m; + }, + // 26.3.3.14 + set: function(name, module) { + if (!(module instanceof Module)) + throw new TypeError('Loader.set(' + name + ', module) must be a module'); + this._loader.modules[name] = { + module: module + }; + }, + // 26.3.3.15 values not implemented + // 26.3.3.16 @@iterator not implemented + // 26.3.3.17 @@toStringTag not implemented + + // 26.3.3.18.1 + normalize: function(name, referrerName, referrerAddress) { + return name; + }, + // 26.3.3.18.2 + locate: function(load) { + return load.name; + }, + // 26.3.3.18.3 + fetch: function(load) { + }, + // 26.3.3.18.4 + translate: function(load) { + return load.source; + }, + // 26.3.3.18.5 + instantiate: function(load) { + } + }; + + var _newModule = Loader.prototype.newModule; +/* + * ES6 Module Declarative Linking Code - Dev Build Only + */ + function link(linkSet, linkError) { + + var loader = linkSet.loader; + + if (!linkSet.loads.length) + return; + + var loads = linkSet.loads.concat([]); + + for (var i = 0; i < loads.length; i++) { + var load = loads[i]; + + var module = doDynamicExecute(linkSet, load, linkError); + if (!module) + return; + load.module = { + name: load.name, + module: module + }; + load.status = 'linked'; + + finishLoad(loader, load); + } + } + + function evaluateLoadedModule(loader, load) { + console.assert(load.status == 'linked', 'is linked ' + load.name); + return load.module.module; + } + + function doEnsureEvaluated() {} + + function transpile() { + throw new TypeError('ES6 transpilation is only provided in the dev module loader build.'); + } +})();/* +********************************************************************************************* + + System Loader Implementation + + - Implemented to https://github.com/jorendorff/js-loaders/blob/master/browser-loader.js + + - <script type="module"> supported + +********************************************************************************************* +*/ + +var System; + +function SystemLoader() { + Loader.call(this); + this.paths = {}; +} + +// NB no specification provided for System.paths, used ideas discussed in https://github.com/jorendorff/js-loaders/issues/25 +function applyPaths(paths, name) { + // most specific (most number of slashes in path) match wins + var pathMatch = '', wildcard, maxWildcardPrefixLen = 0; + + // check to see if we have a paths entry + for (var p in paths) { + var pathParts = p.split('*'); + if (pathParts.length > 2) + throw new TypeError('Only one wildcard in a path is permitted'); + + // exact path match + if (pathParts.length == 1) { + if (name == p) + return paths[p]; + + // support trailing / in paths rules + else if (name.substr(0, p.length - 1) == p.substr(0, p.length - 1) && (name.length < p.length || name[p.length - 1] == p[p.length - 1]) && paths[p][paths[p].length - 1] == '/') + return paths[p].substr(0, paths[p].length - 1) + (name.length > p.length ? '/' + name.substr(p.length) : ''); + } + // wildcard path match + else { + var wildcardPrefixLen = pathParts[0].length; + if (wildcardPrefixLen >= maxWildcardPrefixLen && + name.substr(0, pathParts[0].length) == pathParts[0] && + name.substr(name.length - pathParts[1].length) == pathParts[1]) { + maxWildcardPrefixLen = wildcardPrefixLen; + pathMatch = p; + wildcard = name.substr(pathParts[0].length, name.length - pathParts[1].length - pathParts[0].length); + } + } + } + + var outPath = paths[pathMatch]; + if (typeof wildcard == 'string') + outPath = outPath.replace('*', wildcard); + + return outPath; +} + +// inline Object.create-style class extension +function LoaderProto() {} +LoaderProto.prototype = Loader.prototype; +SystemLoader.prototype = new LoaderProto(); +// SystemJS Loader Class and Extension helpers + +function SystemJSLoader() { + SystemLoader.call(this); + + systemJSConstructor.call(this); +} + +// inline Object.create-style class extension +function SystemProto() {}; +SystemProto.prototype = SystemLoader.prototype; +SystemJSLoader.prototype = new SystemProto(); +SystemJSLoader.prototype.constructor = SystemJSLoader; + +// remove ESML instantiate +SystemJSLoader.prototype.instantiate = function() {}; + +var systemJSConstructor; + +function hook(name, hook) { + SystemJSLoader.prototype[name] = hook(SystemJSLoader.prototype[name] || function() {}); +} +function hookConstructor(hook) { + systemJSConstructor = hook(systemJSConstructor || function() {}); +} + +function dedupe(deps) { + var newDeps = []; + for (var i = 0, l = deps.length; i < l; i++) + if (indexOf.call(newDeps, deps[i]) == -1) + newDeps.push(deps[i]) + return newDeps; +} + +function group(deps) { + var names = []; + var indices = []; + for (var i = 0, l = deps.length; i < l; i++) { + var index = indexOf.call(names, deps[i]); + if (index === -1) { + names.push(deps[i]); + indices.push([i]); + } + else { + indices[index].push(i); + } + } + return { names: names, indices: indices }; +} + +var getOwnPropertyDescriptor = true; +try { + Object.getOwnPropertyDescriptor({ a: 0 }, 'a'); +} +catch(e) { + getOwnPropertyDescriptor = false; +} + +// 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') { + if (getOwnPropertyDescriptor) { + var d; + for (var p in exports) + if (d = Object.getOwnPropertyDescriptor(exports, p)) + defineProperty(esModule, p, d); + } + else { + var hasOwnProperty = exports && exports.hasOwnProperty; + for (var p in exports) { + if (!hasOwnProperty || exports.hasOwnProperty(p)) + esModule[p] = exports[p]; + } + } + } + esModule['default'] = exports; + defineProperty(esModule, '__useDefault', { + value: true + }); + return esModule; +} + +function extend(a, b, prepend) { + for (var p in b) { + if (!prepend || !(p in a)) + a[p] = b[p]; + } + return a; +} + +// package configuration options +var packageProperties = ['main', 'format', 'defaultExtension', 'meta', 'map', 'basePath', 'depCache']; + +// meta first-level extends where: +// array + array appends +// object + object extends +// other properties replace +function extendMeta(a, b, prepend) { + for (var p in b) { + var val = b[p]; + if (!(p in a)) + a[p] = val; + else if (val instanceof Array && a[p] instanceof Array) + a[p] = [].concat(prepend ? val : a[p]).concat(prepend ? a[p] : val); + else if (typeof val == 'object' && val !== null && typeof a[p] == 'object') + a[p] = extend(extend({}, a[p]), val, prepend); + else if (!prepend) + a[p] = val; + } +} + +function warn(msg) { + if (this.warnings && typeof console != 'undefined' && console.warn) + console.warn(msg); +}var absURLRegEx = /^[^\/]+:\/\//; + +function readMemberExpression(p, value) { + var pParts = p.split('.'); + while (pParts.length) + value = value[pParts.shift()]; + return value; +} + +var baseURLCache = {}; +function getBaseURLObj() { + if (baseURLCache[this.baseURL]) + return baseURLCache[this.baseURL]; + + // normalize baseURL if not already + if (this.baseURL[this.baseURL.length - 1] != '/') + this.baseURL += '/'; + + var baseURL = new URL(this.baseURL, baseURI); + + this.baseURL = baseURL.href; + + return (baseURLCache[this.baseURL] = baseURL); +} + +function getMapMatch(map, name) { + var bestMatch, bestMatchLength = 0; + + for (var p in map) { + if (name.substr(0, p.length) == p && (name.length == p.length || name[p.length] == '/')) { + var curMatchLength = p.split('/').length; + if (curMatchLength <= bestMatchLength) + continue; + bestMatch = p; + bestMatchLength = curMatchLength; + } + } + + return bestMatch; +} + +function setProduction(isProduction) { + this.set('@system-env', this.newModule({ + browser: isBrowser, + node: !!this._nodeRequire, + production: isProduction + })); +} + +var baseURIObj = new URL(baseURI); + +hookConstructor(function(constructor) { + return function() { + constructor.call(this); + + // support baseURL + this.baseURL = baseURI.substr(0, baseURI.lastIndexOf('/') + 1); + + // support map + this.map = {}; + + // global behaviour flags + this.warnings = false; + this.defaultJSExtensions = false; + this.globalEvaluationScope = true; + this.pluginFirst = false; + + // by default load ".json" files as json + // leading * meta doesn't need normalization + // NB add this in next breaking release + // this.meta['*.json'] = { format: 'json' }; + + // Default settings for globalEvaluationScope: + // Disabled for WebWorker, Chrome Extensions and jsdom + if (isWorker + || isBrowser && window.chrome && window.chrome.extension + || isBrowser && navigator.userAgent.match(/^Node\.js/)) + this.globalEvaluationScope = false; + + // support the empty module, as a concept + this.set('@empty', this.newModule({})); + + setProduction.call(this, false); + }; +}); + +// include the node require since we're overriding it +if (typeof require != 'undefined' && typeof process != 'undefined' && !process.browser) + SystemJSLoader.prototype._nodeRequire = require; + +var nodeCoreModules = ['assert', 'buffer', 'child_process', 'cluster', 'console', 'constants', + 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'module', 'net', 'os', 'path', + 'process', 'punycode', 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'sys', 'timers', + 'tls', 'tty', 'url', 'util', 'vm', 'zlib']; + +/* + Core SystemJS Normalization + + If a name is relative, we apply URL normalization to the page + If a name is an absolute URL, we leave it as-is + + Plain names (neither of the above) run through the map and paths + normalization phases. + + The paths normalization phase applies last (paths extension), which + defines the `decanonicalize` function and normalizes everything into + a URL. + */ +hook('normalize', function(normalize) { + return function(name, parentName) { + // first run map config + if (name[0] != '.' && name[0] != '/' && !name.match(absURLRegEx)) { + var mapMatch = getMapMatch(this.map, name); + if (mapMatch) + name = this.map[mapMatch] + name.substr(mapMatch.length); + } + + // dynamically load node-core modules when requiring `@node/fs` for example + if (name.substr(0, 6) == '@node/' && nodeCoreModules.indexOf(name.substr(6)) != -1) { + if (!this._nodeRequire) + throw new TypeError('Error loading ' + name + '. Can only load node core modules in Node.'); + this.set(name, this.newModule(getESModule(this._nodeRequire(name.substr(6))))); + } + + // relative URL-normalization + if (name[0] == '.' || name[0] == '/') { + if (parentName) + name = new URL(name, parentName.replace(/#/g, '%05')).href.replace(/%05/g, '#'); + else + name = new URL(name, baseURIObj).href; + } + + // if the module is in the registry already, use that + if (this.has(name)) + return name; + + if (name.match(absURLRegEx)) { + // defaultJSExtensions backwards compatibility + if (this.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js') + name += '.js'; + return name; + } + + // applyPaths implementation provided from ModuleLoader system.js source + name = applyPaths(this.paths, name) || name; + + // defaultJSExtensions backwards compatibility + if (this.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js') + name += '.js'; + + // ./x, /x -> page-relative + if (name[0] == '.' || name[0] == '/') + return new URL(name, baseURIObj).href; + // x -> baseURL-relative + else + return new URL(name, getBaseURLObj.call(this)).href; + }; +}); + +// percent encode just '#' in urls if using HTTP requests +var httpRequest = typeof XMLHttpRequest != 'undefined'; +hook('locate', function(locate) { + return function(load) { + return Promise.resolve(locate.call(this, load)) + .then(function(address) { + if (httpRequest) + return address.replace(/#/g, '%23'); + return address; + }); + }; +}); + +/* + * Fetch with authorization + */ +hook('fetch', function() { + return function(load) { + return new Promise(function(resolve, reject) { + fetchTextFromURL(load.address, load.metadata.authorization, resolve, reject); + }); + }; +}); + +/* + __useDefault + + When a module object looks like: + newModule( + __useDefault: true, + default: 'some-module' + }) + + Then importing that module provides the 'some-module' + result directly instead of the full module. + + Useful for eg module.exports = function() {} +*/ +hook('import', function(systemImport) { + return function(name, parentName, parentAddress) { + if (parentName && parentName.name) + warn.call(this, 'SystemJS.import(name, { name: parentName }) is deprecated for SystemJS.import(name, parentName), while importing ' + name + ' from ' + parentName.name); + return systemImport.call(this, name, parentName, parentAddress).then(function(module) { + return module.__useDefault ? module['default'] : module; + }); + }; +}); + +/* + * Allow format: 'detect' meta to enable format detection + */ +hook('translate', function(systemTranslate) { + return function(load) { + if (load.metadata.format == 'detect') + load.metadata.format = undefined; + return systemTranslate.call(this, load); + }; +}); + + +/* + * JSON format support + * + * Supports loading JSON files as a module format itself + * + * Usage: + * + * SystemJS.config({ + * meta: { + * '*.json': { format: 'json' } + * } + * }); + * + * Module is returned as if written: + * + * export default {JSON} + * + * No named exports are provided + * + * Files ending in ".json" are treated as json automatically by SystemJS + */ +hook('instantiate', function(instantiate) { + return function(load) { + if (load.metadata.format == 'json' && !this.builder) { + var entry = load.metadata.entry = createEntry(); + entry.deps = []; + entry.execute = function() { + try { + return JSON.parse(load.source); + } + catch(e) { + throw new Error("Invalid JSON file " + load.name); + } + }; + } + }; +}) + +/* + Extend config merging one deep only + + loader.config({ + some: 'random', + config: 'here', + deep: { + config: { too: 'too' } + } + }); + + <=> + + loader.some = 'random'; + loader.config = 'here' + loader.deep = loader.deep || {}; + loader.deep.config = { too: 'too' }; + + + Normalizes meta and package configs allowing for: + + SystemJS.config({ + meta: { + './index.js': {} + } + }); + + To become + + SystemJS.meta['https://thissite.com/index.js'] = {}; + + For easy normalization canonicalization with latest URL support. + +*/ +SystemJSLoader.prototype.env = 'development'; + +SystemJSLoader.prototype.config = function(cfg) { + var loader = this; + + if ('warnings' in cfg) + loader.warnings = cfg.warnings; + + // transpiler deprecation path + if (cfg.transpilerRuntime === false) + loader._loader.loadedTranspilerRuntime = true; + + // always configure baseURL first + if (cfg.baseURL) { + var hasConfig = false; + function checkHasConfig(obj) { + for (var p in obj) + return true; + } + if (checkHasConfig(loader.packages) || checkHasConfig(loader.meta) || checkHasConfig(loader.depCache) || checkHasConfig(loader.bundles) || checkHasConfig(loader.packageConfigPaths)) + throw new TypeError('Incorrect configuration order. The baseURL must be configured with the first SystemJS.config call.'); + + loader.baseURL = cfg.baseURL; + + // sanitize baseURL + getBaseURLObj.call(loader); + } + + if (cfg.defaultJSExtensions) { + loader.defaultJSExtensions = cfg.defaultJSExtensions; + warn.call(loader, 'The defaultJSExtensions configuration option is deprecated, use packages configuration instead.'); + } + + if (cfg.pluginFirst) + loader.pluginFirst = cfg.pluginFirst; + + if (cfg.production) + setProduction.call(loader, true); + + if (cfg.paths) { + for (var p in cfg.paths) + loader.paths[p] = cfg.paths[p]; + } + + if (cfg.map) { + var objMaps = ''; + for (var p in cfg.map) { + var v = cfg.map[p]; + + // object map backwards-compat into packages configuration + if (typeof v !== 'string') { + objMaps += (objMaps.length ? ', ' : '') + '"' + p + '"'; + + var prop = loader.decanonicalize(p + (p[p.length - 1] != '/' ? '/' : '')); + + // allow trailing '/' in package config + if (prop[prop.length - 1] == '/') + prop = prop.substr(0, prop.length - 1); + + // if a package main, revert it + var pkgMatch = ''; + for (var pkg in loader.packages) { + if (prop.substr(0, pkg.length) == pkg + && (!prop[pkg.length] || prop[pkg.length] == '/') + && pkgMatch.split('/').length < pkg.split('/').length) + pkgMatch = pkg; + } + if (pkgMatch && loader.packages[pkgMatch].main) + prop = prop.substr(0, prop.length - loader.packages[pkgMatch].main.length - 1); + + var pkg = loader.packages[prop] = loader.packages[prop] || {}; + pkg.map = v; + } + else { + loader.map[p] = v; + } + } + if (objMaps) + warn.call(loader, 'The map configuration for ' + objMaps + ' uses object submaps, which is deprecated in global map.\nUpdate this to use package contextual map with configs like SystemJS.config({ packages: { "' + p + '": { map: {...} } } }).'); + } + + if (cfg.packageConfigPaths) { + var packageConfigPaths = []; + for (var i = 0; i < cfg.packageConfigPaths.length; i++) { + var path = cfg.packageConfigPaths[i]; + var packageLength = Math.max(path.lastIndexOf('*') + 1, path.lastIndexOf('/')); + var normalized = loader.decanonicalize(path.substr(0, packageLength) + '/'); + normalized = normalized.substr(0, normalized.length - 1) + path.substr(packageLength); + packageConfigPaths[i] = normalized; + } + loader.packageConfigPaths = packageConfigPaths; + } + + if (cfg.bundles) { + for (var p in cfg.bundles) { + var bundle = []; + for (var i = 0; i < cfg.bundles[p].length; i++) + bundle.push(loader.decanonicalize(cfg.bundles[p][i])); + loader.bundles[p] = bundle; + } + } + + if (cfg.packages) { + for (var p in cfg.packages) { + if (p.match(/^([^\/]+:)?\/\/$/)) + throw new TypeError('"' + p + '" is not a valid package name.'); + + // trailing slash allows paths matches here + // NB deprecate this to just remove trailing / + // as decanonicalize doesn't respond to trailing / + // and paths wildcards should deprecate + var prop = loader.decanonicalize(p + (p[p.length - 1] != '/' ? '/' : '')); + + // allow trailing '/' in package config + if (prop[prop.length - 1] == '/') + prop = prop.substr(0, prop.length - 1); + + loader.packages[prop] = loader.packages[prop] || {}; + + // meta backwards compatibility + if (cfg.packages[p].modules) { + warn.call(loader, 'Package ' + p + ' is configured with "modules", which is deprecated as it has been renamed to "meta".'); + cfg.packages[p].meta = cfg.packages[p].modules; + delete cfg.packages[p].modules; + } + + for (var q in cfg.packages[p]) + if (indexOf.call(packageProperties, q) == -1) + warn.call(loader, '"' + q + '" is not a valid package configuration option in package ' + p); + + extendMeta(loader.packages[prop], cfg.packages[p]); + } + } + + for (var c in cfg) { + var v = cfg[c]; + var normalizeProp = false; + + if (c == 'baseURL' || c == 'map' || c == 'packages' || c == 'bundles' || c == 'paths' || c == 'warnings' || c == 'packageConfigPaths') + continue; + + if (typeof v != 'object' || v instanceof Array) { + loader[c] = v; + } + else { + loader[c] = loader[c] || {}; + + if (c == 'meta' || c == 'depCache') + normalizeProp = true; + + for (var p in v) { + // base-level wildcard meta does not normalize to retain catch-all quality + if (c == 'meta' && p[0] == '*') + loader[c][p] = v[p]; + else if (normalizeProp) + loader[c][loader.decanonicalize(p)] = v[p]; + else + loader[c][p] = v[p]; + } + } + } +};/* + * Package Configuration Extension + * + * Example: + * + * SystemJS.packages = { + * jquery: { + * basePath: 'lib', // optionally only use a subdirectory within the package + * main: 'index.js', // when not set, package name is requested directly + * format: 'amd', + * defaultExtension: 'ts', // defaults to 'js', can be set to false + * modules: { + * '*.ts': { + * loader: 'typescript' + * }, + * 'vendor/sizzle.js': { + * format: 'global' + * } + * }, + * map: { + * // map internal require('sizzle') to local require('./vendor/sizzle') + * sizzle: './vendor/sizzle.js', + * // map any internal or external require of 'jquery/vendor/another' to 'another/index.js' + * './vendor/another.js': './another/index.js', + * // test.js / test -> lib/test.js + * './test.js': './lib/test.js', + * + * // environment-specific map configurations + * './index.js': { + * '~browser': './index-node.js' + * } + * }, + * // allows for setting package-prefixed depCache + * // keys are normalized module names relative to the package itself + * depCache: { + * // import 'package/index.js' loads in parallel package/lib/test.js,package/vendor/sizzle.js + * './index.js': ['./test'], + * './test.js': ['external-dep'], + * 'external-dep/path.js': ['./another.js'] + * } + * } + * }; + * + * Then: + * import 'jquery' -> jquery/index.js + * import 'jquery/submodule' -> jquery/submodule.js + * import 'jquery/submodule.ts' -> jquery/submodule.ts loaded as typescript + * import 'jquery/vendor/another' -> another/index.js + * + * Detailed Behaviours + * - main can have a leading "./" can be added optionally + * - map and defaultExtension are applied to the main + * - defaultExtension adds the extension only if the exact extension is not present + * - defaultJSExtensions applies after map when defaultExtension is not set + * - if a meta value is available for a module, map and defaultExtension are skipped + * - like global map, package map also applies to subpaths (sizzle/x, ./vendor/another/sub) + * - condition module map is '@env' module in package or '@system-env' globally + * - map targets support conditional interpolation ('./x': './x.#{|env}.js') + * - internal package map targets cannot use boolean conditionals + * + * In addition, the following modules properties will be allowed to be package + * -relative as well in the package module config: + * + * - loader + * - alias + * + * + * Package Configuration Loading + * + * Not all packages may already have their configuration present in the System config + * For these cases, a list of packageConfigPaths can be provided, which when matched against + * a request, will first request a ".json" file by the package name to derive the package + * configuration from. This allows dynamic loading of non-predetermined code, a key use + * case in SystemJS. + * + * Example: + * + * SystemJS.packageConfigPaths = ['packages/test/package.json', 'packages/*.json']; + * + * // will first request 'packages/new-package/package.json' for the package config + * // before completing the package request to 'packages/new-package/path' + * SystemJS.import('packages/new-package/path'); + * + * // will first request 'packages/test/package.json' before the main + * SystemJS.import('packages/test'); + * + * When a package matches packageConfigPaths, it will always send a config request for + * the package configuration. + * The package name itself is taken to be the match up to and including the last wildcard + * or trailing slash. + * The most specific package config path will be used. + * Any existing package configurations for the package will deeply merge with the + * package config, with the existing package configurations taking preference. + * To opt-out of the package configuration request for a package that matches + * packageConfigPaths, use the { configured: true } package config option. + * + */ +(function() { + + hookConstructor(function(constructor) { + return function() { + constructor.call(this); + this.packages = {}; + this.packageConfigPaths = {}; + }; + }); + + function getPackage(loader, normalized) { + // use most specific package + var curPkg, curPkgLen = 0, pkgLen; + for (var p in loader.packages) { + if (normalized.substr(0, p.length) === p && (normalized.length === p.length || normalized[p.length] === '/')) { + pkgLen = p.split('/').length; + if (pkgLen > curPkgLen) { + curPkg = p; + curPkgLen = pkgLen; + } + } + } + return curPkg; + } + + function getBasePath(pkg) { + // sanitize basePath + var basePath = pkg.basePath && pkg.basePath != '.' ? pkg.basePath : ''; + if (basePath) { + if (basePath.substr(0, 2) == './') + basePath = basePath.substr(2); + if (basePath[basePath.length - 1] != '/') + basePath += '/'; + } + return basePath; + } + + function addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions) { + // don't apply extensions to folders or if defaultExtension = false + if (!subPath || subPath[subPath.length - 1] == '/' || skipExtensions || pkg.defaultExtension === false) + return subPath; + + // NB are you sure about this? + // skip if we have interpolation conditional syntax in subPath? + if (subPath.match(interpolationRegEx)) + return subPath; + + var metaMatch = false; + + // exact meta or meta with any content after the last wildcard skips extension + if (pkg.meta) + getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) + return metaMatch = true; + }); + + // exact global meta or meta with any content after the last wildcard skips extension + if (!metaMatch && loader.meta) + getMetaMatches(loader.meta, pkgName + '/' + basePath + subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) + return metaMatch = true; + }); + + if (metaMatch) + return subPath; + + // work out what the defaultExtension is and add if not there already + // NB reconsider if default should really be ".js"? + var defaultExtension = '.' + (pkg.defaultExtension || 'js'); + if (subPath.substr(subPath.length - defaultExtension.length) != defaultExtension) + return subPath + defaultExtension; + else + return subPath; + } + + function applyPackageConfigSync(loader, pkg, pkgName, subPath, skipExtensions) { + // main + if (!subPath) { + if (pkg.main) + subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main; + // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js') + else + // NB can add a default package main convention here when defaultJSExtensions is deprecated + // if it becomes internal to the package then it would no longer be an exit path + return pkgName + (loader.defaultJSExtensions ? '.js' : ''); + } + + var basePath = getBasePath(pkg); + + // map config checking without then with extensions + if (pkg.map) { + var mapPath = './' + subPath; + + var mapMatch = getMapMatch(pkg.map, mapPath); + + // we then check map with the default extension adding + if (!mapMatch) { + mapPath = './' + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions); + if (mapPath != './' + subPath) + mapMatch = getMapMatch(pkg.map, mapPath); + } + if (mapMatch) + return doMapSync(loader, pkg, pkgName, basePath, mapMatch, mapPath, skipExtensions); + } + + // normal package resolution + return pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions); + } + + function doMapSync(loader, pkg, pkgName, basePath, mapMatch, path, skipExtensions) { + var mapped = pkg.map[mapMatch]; + + // ignore conditionals in sync + if (typeof mapped != 'string') + mapped = mapMatch = path; + + // package map to main / base-level + if (mapped == '.') + mapped = pkgName; + + // internal package map + else if (mapped.substr(0, 2) == './') + return pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions); + + // external map reference + return loader.normalizeSync(mapped + path.substr(mapMatch.length), pkgName + '/'); + } + + function applyPackageConfig(loader, pkg, pkgName, subPath, skipExtensions) { + // main + if (!subPath) { + if (pkg.main) + subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main; + // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js') + else + // NB can add a default package main convention here when defaultJSExtensions is deprecated + // if it becomes internal to the package then it would no longer be an exit path + return Promise.resolve(pkgName + (loader.defaultJSExtensions ? '.js' : '')); + } + + var basePath = getBasePath(pkg); + + // map config checking without then with extensions + var mapPath, mapMatch; + + if (pkg.map) { + mapPath = './' + subPath; + mapMatch = getMapMatch(pkg.map, mapPath); + + // we then check map with the default extension adding + if (!mapMatch) { + mapPath = './' + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions); + if (mapPath != './' + subPath) + mapMatch = getMapMatch(pkg.map, mapPath); + } + } + + return (mapMatch ? doMap(loader, pkg, pkgName, basePath, mapMatch, mapPath, skipExtensions) : Promise.resolve()) + .then(function(mapped) { + if (mapped) + return Promise.resolve(mapped); + + // normal package resolution / fallback resolution for no conditional match + return Promise.resolve(pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions)); + }); + } + + function doStringMap(loader, pkg, pkgName, basePath, mapMatch, mapped, path, skipExtensions) { + // NB the interpolation cases should strictly skip subsequent interpolation + + // package map to main / base-level + if (mapped == '.') + mapped = pkgName; + + // internal package map + else if (mapped.substr(0, 2) == './') + return Promise.resolve(pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions)) + .then(function(name) { + return interpolateConditional.call(loader, name, pkgName + '/'); + }); + + // external map reference + // NB deprecate the use of the second argument here -> should be fully global reference + return loader.normalize(mapped + path.substr(mapMatch.length), pkgName + '/'); + } + + function doMap(loader, pkg, pkgName, basePath, mapMatch, path, skipExtensions) { + var mapped = pkg.map[mapMatch]; + + if (typeof mapped == 'string') + return doStringMap(loader, pkg, pkgName, basePath, mapMatch, mapped, path, skipExtensions); + + // we use a special conditional syntax to allow the builder to handle conditional branch points further + if (loader.builder) + return Promise.resolve(pkgName + '/#:' + path); + + // map object -> conditional map + return loader['import'](pkg.map['@env'] || '@system-env', pkgName) + .then(function(env) { + // first map condition to match is used + for (var e in mapped) { + var negate = e[0] == '~'; + + var value = readMemberExpression(negate ? e.substr(1) : e, env); + + if (!negate && value || negate && !value) + return mapped[e]; + } + }) + .then(function(mapped) { + if (mapped) + return doStringMap(loader, pkg, pkgName, basePath, mapMatch, mapped, path, skipExtensions); + + // no environment match -> fallback to original subPath by returning undefined + }); + } + + // normalizeSync = decanonicalize + package resolution + SystemJSLoader.prototype.normalizeSync = SystemJSLoader.prototype.decanonicalize = SystemJSLoader.prototype.normalize; + + // decanonicalize must JUST handle package defaultExtension: false case when defaultJSExtensions is set + // to be deprecated! + hook('decanonicalize', function(decanonicalize) { + return function(name, parentName) { + var decanonicalized = decanonicalize.call(this, name, parentName); + + if (!this.defaultJSExtensions) + return decanonicalized; + + var pkgName = getPackage(this, decanonicalized); + + var defaultExtension = name[name.length - 1] == '/' ? false : pkgName && this.packages[pkgName].defaultExtension; + + if ((defaultExtension === false || defaultExtension && defaultExtension != '.js') && name.substr(name.length - 3, 3) != '.js' && decanonicalized.substr(decanonicalized.length - 3, 3) == '.js') + decanonicalized = decanonicalized.substr(0, decanonicalized.length - 3); + + return decanonicalized; + }; + }); + + hook('normalizeSync', function(normalizeSync) { + return function(name, parentName, isPlugin) { + warn.call(this, 'SystemJS.normalizeSync has been deprecated for SystemJS.decanonicalize.'); + + var loader = this; + isPlugin = isPlugin === true; + + // apply contextual package map first + // (we assume the parent package config has already been loaded) + if (parentName) + var parentPackageName = getPackage(loader, parentName) || + loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' && + getPackage(loader, parentName.substr(0, parentName.length - 3)); + + var parentPackage = parentPackageName && loader.packages[parentPackageName]; + + // remove any parent basePath from parentName + if (parentPackage) { + var parentBasePath = getBasePath(parentPackage); + if (parentBasePath && parentName.substr(parentPackageName.length + 1, parentBasePath.length) == parentBasePath) + parentName = parentPackageName + parentName.substr(parentPackageName.length + parentBasePath.length); + } + + // ignore . since internal maps handled by standard package resolution + if (parentPackage && name[0] != '.') { + var parentMap = parentPackage.map; + var parentMapMatch = parentMap && getMapMatch(parentMap, name); + + if (parentMapMatch && typeof parentMap[parentMapMatch] == 'string') + return doMapSync(loader, parentPackage, parentPackageName, getBasePath(parentPackage), parentMapMatch, name, isPlugin); + } + + var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js'; + + // apply map, core, paths, contextual package map + var normalized = normalizeSync.call(loader, name, parentName); + + // undo defaultJSExtension + if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js') + defaultJSExtension = false; + if (defaultJSExtension) + normalized = normalized.substr(0, normalized.length - 3); + + var pkgConfigMatch = getPackageConfigMatch(loader, normalized); + var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized); + + if (!pkgName) + return normalized + (defaultJSExtension ? '.js' : ''); + + var subPath = normalized.substr(pkgName.length + 1); + + return applyPackageConfigSync(loader, loader.packages[pkgName] || {}, pkgName, subPath, isPlugin); + }; + }); + + hook('normalize', function(normalize) { + return function(name, parentName, isPlugin) { + var loader = this; + isPlugin = isPlugin === true; + + return Promise.resolve() + .then(function() { + // apply contextual package map first + // (we assume the parent package config has already been loaded) + if (parentName) + var parentPackageName = getPackage(loader, parentName) || + loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' && + getPackage(loader, parentName.substr(0, parentName.length - 3)); + + var parentPackage = parentPackageName && loader.packages[parentPackageName]; + + // remove any parent basePath from parentName + if (parentPackage) { + var parentBasePath = getBasePath(parentPackage); + if (parentBasePath && parentName.substr(parentPackageName.length + 1, parentBasePath.length) == parentBasePath) + parentName = parentPackageName + parentName.substr(parentPackageName.length + parentBasePath.length); + } + + // ignore . since internal maps handled by standard package resolution + if (parentPackage && name.substr(0, 2) != './') { + var parentMap = parentPackage.map; + var parentMapMatch = parentMap && getMapMatch(parentMap, name); + + if (parentMapMatch) + return doMap(loader, parentPackage, parentPackageName, parentBasePath, parentMapMatch, name, isPlugin); + } + + return Promise.resolve(); + }) + .then(function(mapped) { + if (mapped) + return mapped; + + var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js'; + + // apply map, core, paths, contextual package map + var normalized = normalize.call(loader, name, parentName); + + // undo defaultJSExtension + if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js') + defaultJSExtension = false; + if (defaultJSExtension) + normalized = normalized.substr(0, normalized.length - 3); + + var pkgConfigMatch = getPackageConfigMatch(loader, normalized); + var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized); + + if (!pkgName) + return Promise.resolve(normalized + (defaultJSExtension ? '.js' : '')); + + var pkg = loader.packages[pkgName]; + + // if package is already configured or not a dynamic config package, use existing package config + var isConfigured = pkg && (pkg.configured || !pkgConfigMatch); + return (isConfigured ? Promise.resolve(pkg) : loadPackageConfigPath(loader, pkgName, pkgConfigMatch.configPath)) + .then(function(pkg) { + var subPath = normalized.substr(pkgName.length + 1); + + return applyPackageConfig(loader, pkg, pkgName, subPath, isPlugin); + }); + }); + }; + }); + + // check if the given normalized name matches a packageConfigPath + // if so, loads the config + var packageConfigPaths = {}; + + // data object for quick checks against package paths + function createPkgConfigPathObj(path) { + var lastWildcard = path.lastIndexOf('*'); + var length = Math.max(lastWildcard + 1, path.lastIndexOf('/')); + return { + length: length, + // NB handle regex control character escapes or simply create a test function here + regEx: new RegExp('^(' + path.substr(0, length).replace(/\*/g, '[^\\/]+') + ')(\\/|$)'), + wildcard: lastWildcard != -1 + }; + } + + // most specific match wins + function getPackageConfigMatch(loader, normalized) { + var pkgName, exactMatch = false, configPath; + for (var i = 0; i < loader.packageConfigPaths.length; i++) { + var packageConfigPath = loader.packageConfigPaths[i]; + var p = packageConfigPaths[packageConfigPath] || (packageConfigPaths[packageConfigPath] = createPkgConfigPathObj(packageConfigPath)); + if (normalized.length < p.length) + continue; + var match = normalized.match(p.regEx); + if (match && (!pkgName || (!(exactMatch && p.wildcard) && pkgName.length < match[1].length))) { + pkgName = match[1]; + exactMatch = !p.wildcard; + configPath = pkgName + packageConfigPath.substr(p.length); + } + } + + if (!pkgName) + return; + + return { + packageName: pkgName, + configPath: configPath + }; + } + + function loadPackageConfigPath(loader, pkgName, pkgConfigPath) { + var configLoader = loader.pluginLoader || loader; + + // NB remove this when json is default + (configLoader.meta[pkgConfigPath] = configLoader.meta[pkgConfigPath] || {}).format = 'json'; + + return configLoader.load(pkgConfigPath) + .then(function() { + pkgConfig = configLoader.get(pkgConfigPath); + + var cfg = pkgConfig['default']; + + // support "systemjs" prefixing + if (cfg.systemjs) + cfg = cfg.systemjs; + + // modules backwards compatibility + if (cfg.modules) { + cfg.meta = cfg.modules; + warn.call(loader, 'Package config file ' + pkgConfigPath + ' is configured with "modules", which is deprecated as it has been renamed to "meta".'); + } + + // remove any non-system properties if generic config file (eg package.json) + for (var p in cfg) { + if (indexOf.call(packageProperties, p) == -1) + delete cfg[p]; + } + + // deeply-merge (to first level) config with any existing package config + var pkg = loader.packages[pkgName] = loader.packages[pkgName] || {}; + extendMeta(pkg, cfg, true); + + // support external depCache + var basePath = getBasePath(pkg); + if (cfg.depCache) { + for (var d in cfg.depCache) { + var dNormalized; + + if (d.substr(0, 2) == './') + dNormalized = pkgName + '/' + basePath + d.substr(2); + else + dNormalized = coreResolve.call(loader, d); + loader.depCache[dNormalized] = (loader.depCache[dNormalized] || []).concat(cfg.depCache[d]); + } + delete cfg.depCache; + } + + return pkg; + }); + } + + function getMetaMatches(pkgMeta, subPath, matchFn) { + // wildcard meta + var meta = {}; + var wildcardIndex; + for (var module in pkgMeta) { + // allow meta to start with ./ for flexibility + var dotRel = module.substr(0, 2) == './' ? './' : ''; + if (dotRel) + module = module.substr(2); + + wildcardIndex = module.indexOf('*'); + if (wildcardIndex === -1) + continue; + + if (module.substr(0, wildcardIndex) == subPath.substr(0, wildcardIndex) + && module.substr(wildcardIndex + 1) == subPath.substr(subPath.length - module.length + wildcardIndex + 1)) { + // alow match function to return true for an exit path + if (matchFn(module, pkgMeta[dotRel + module], module.split('/').length)) + return; + } + } + // exact meta + var exactMeta = pkgMeta[subPath] || pkgMeta['./' + subPath]; + if (exactMeta) + matchFn(exactMeta, exactMeta, 0); + } + + hook('locate', function(locate) { + return function(load) { + var loader = this; + return Promise.resolve(locate.call(this, load)) + .then(function(address) { + var pkgName = getPackage(loader, load.name); + if (pkgName) { + var pkg = loader.packages[pkgName]; + var basePath = getBasePath(pkg); + var subPath = load.name.substr(pkgName.length + basePath.length + 1); + + // format + if (pkg.format) + load.metadata.format = load.metadata.format || pkg.format; + + var meta = {}; + if (pkg.meta) { + var bestDepth = 0; + + // NB support a main shorthand in meta here? + getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) { + if (matchDepth > bestDepth) + bestDepth = matchDepth; + extendMeta(meta, matchMeta, matchDepth && bestDepth > matchDepth); + }); + + // allow alias and loader to be package-relative + if (meta.alias && meta.alias.substr(0, 2) == './') + meta.alias = pkgName + meta.alias.substr(1); + if (meta.loader && meta.loader.substr(0, 2) == './') + meta.loader = pkgName + meta.loader.substr(1); + extendMeta(load.metadata, meta); + } + } + + return address; + }); + }; + }); + +})(); +/* + * Script tag fetch + * + * When load.metadata.scriptLoad is true, we load via script tag injection. + */ +(function() { + + if (typeof document != 'undefined') + var head = document.getElementsByTagName('head')[0]; + + var curSystem; + + // if doing worker executing, this is set to the load record being executed + var workerLoad = null; + + // interactive mode handling method courtesy RequireJS + var ieEvents = head && (function() { + var s = document.createElement('script'); + var isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]'; + return s.attachEvent && !(s.attachEvent.toString && s.attachEvent.toString().indexOf('[native code') < 0) && !isOpera; + })(); + + // IE interactive-only part + // we store loading scripts array as { script: <script>, load: {...} } + var interactiveLoadingScripts = []; + var interactiveScript; + function getInteractiveScriptLoad() { + if (interactiveScript && interactiveScript.script.readyState === 'interactive') + return interactiveScript.load; + + for (var i = 0; i < interactiveLoadingScripts.length; i++) + if (interactiveLoadingScripts[i].script.readyState == 'interactive') { + interactiveScript = interactiveLoadingScripts[i]; + return interactiveScript.load; + } + } + + // System.register, System.registerDynamic, AMD define pipeline + // this is called by the above methods when they execute + // we then run the reduceRegister_ collection function either immediately + // if we are in IE and know the currently executing script (interactive) + // or later if we need to wait for the synchronous load callback to know the script + var loadingCnt = 0; + var registerQueue = []; + hook('pushRegister_', function(pushRegister) { + return function(register) { + // if using eval-execution then skip + if (pushRegister.call(this, register)) + return false; + + // if using worker execution, then we're done + if (workerLoad) + this.reduceRegister_(workerLoad, register); + + // detect if we know the currently executing load (IE) + // if so, immediately call reduceRegister + else if (ieEvents) + this.reduceRegister_(getInteractiveScriptLoad(), register); + + // otherwise, add to our execution queue + // to call reduceRegister on sync script load event + else if (loadingCnt) + registerQueue.push(register); + + // if we're not currently loading anything though + // then do the reduction against a null load + // (out of band named define or named register) + // note even in non-script environments, this catch is used + else + this.reduceRegister_(null, register); + + return true; + }; + }); + + function webWorkerImport(loader, load) { + return new Promise(function(resolve, reject) { + if (load.metadata.integrity) + reject(new Error('Subresource integrity checking is not supported in web workers.')); + + workerLoad = load; + try { + importScripts(load.address); + } + catch(e) { + workerLoad = null; + reject(e); + } + workerLoad = null; + + // if nothing registered, then something went wrong + if (!load.metadata.entry) + reject(new Error(load.address + ' did not call System.register or AMD define')); + + resolve(''); + }); + } + + // override fetch to use script injection + hook('fetch', function(fetch) { + return function(load) { + var loader = this; + + if (!load.metadata.scriptLoad || (!isBrowser && !isWorker)) + return fetch.call(this, load); + + if (isWorker) + return webWorkerImport(loader, load); + + return new Promise(function(resolve, reject) { + var s = document.createElement('script'); + + s.async = true; + + if (load.metadata.integrity) + s.setAttribute('integrity', load.metadata.integrity); + + if (ieEvents) { + s.attachEvent('onreadystatechange', complete); + interactiveLoadingScripts.push({ + script: s, + load: load + }); + } + else { + s.addEventListener('load', complete, false); + s.addEventListener('error', error, false); + } + + loadingCnt++; + + curSystem = __global.System; + + s.src = load.address; + head.appendChild(s); + + function complete(evt) { + if (s.readyState && s.readyState != 'loaded' && s.readyState != 'complete') + return; + + loadingCnt--; + + // complete call is sync on execution finish + // (in ie already done reductions) + if (!load.metadata.entry && !registerQueue.length) { + loader.reduceRegister_(load); + } + else if (!ieEvents) { + for (var i = 0; i < registerQueue.length; i++) + loader.reduceRegister_(load, registerQueue[i]); + registerQueue = []; + } + + cleanup(); + + // if nothing registered, then something went wrong + if (!load.metadata.entry && !load.metadata.bundle) + reject(new Error(load.name + ' did not call System.register or AMD define. If loading a global module configure the global name via the meta exports property for script injection support.')); + + resolve(''); + } + + function error(evt) { + cleanup(); + reject(new Error('Unable to load script ' + load.address)); + } + + function cleanup() { + __global.System = curSystem; + + if (s.detachEvent) { + s.detachEvent('onreadystatechange', complete); + for (var i = 0; i < interactiveLoadingScripts.length; i++) + if (interactiveLoadingScripts[i].script == s) { + if (interactiveScript && interactiveScript.script == s) + interactiveScript = null; + interactiveLoadingScripts.splice(i, 1); + } + } + else { + s.removeEventListener('load', complete, false); + s.removeEventListener('error', error, false); + } + + head.removeChild(s); + } + }); + }; + }); +})(); +/* + * Instantiate registry extension + * + * Supports Traceur System.register 'instantiate' output for loading ES6 as ES5. + * + * - Creates the loader.register function + * - Also supports metadata.format = 'register' in instantiate for anonymous register modules + * - Also supports metadata.deps, metadata.execute and metadata.executingRequire + * for handling dynamic modules alongside register-transformed ES6 modules + * + * + * The code here replicates the ES6 linking groups algorithm to ensure that + * circular ES6 compiled into System.register can work alongside circular AMD + * and CommonJS, identically to the actual ES6 loader. + * + */ + + +/* + * Registry side table entries in loader.defined + * Registry Entry Contains: + * - name + * - deps + * - declare for declarative modules + * - execute for dynamic modules, different to declarative execute on module + * - executingRequire indicates require drives execution for circularity of dynamic modules + * - declarative optional boolean indicating which of the above + * + * Can preload modules directly on SystemJS.defined['my/module'] = { deps, execute, executingRequire } + * + * Then the entry gets populated with derived information during processing: + * - normalizedDeps derived from deps, created in instantiate + * - groupIndex used by group linking algorithm + * - evaluated indicating whether evaluation has happend + * - module the module record object, containing: + * - exports actual module exports + * + * For dynamic we track the es module with: + * - esModule actual es module value + * - esmExports whether to extend the esModule with named exports + * + * Then for declarative only we track dynamic bindings with the 'module' records: + * - name + * - exports + * - setters declarative setter functions + * - dependencies, module records of dependencies + * - importers, module records of dependents + * + * After linked and evaluated, entries are removed, declarative module records remain in separate + * module binding table + * + */ + +var leadingCommentAndMetaRegEx = /^\s*(\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)*\s*/; +function detectRegisterFormat(source) { + var leadingCommentAndMeta = source.match(leadingCommentAndMetaRegEx); + return leadingCommentAndMeta && source.substr(leadingCommentAndMeta[0].length, 15) == 'System.register'; +} + +function createEntry() { + return { + name: null, + deps: null, + originalIndices: null, + declare: null, + execute: null, + executingRequire: false, + declarative: false, + normalizedDeps: null, + groupIndex: null, + evaluated: false, + module: null, + esModule: null, + esmExports: false + }; +} + +(function() { + + /* + * There are two variations of System.register: + * 1. System.register for ES6 conversion (2-3 params) - System.register([name, ]deps, declare) + * see https://github.com/ModuleLoader/es6-module-loader/wiki/System.register-Explained + * + * 2. System.registerDynamic for dynamic modules (3-4 params) - System.registerDynamic([name, ]deps, executingRequire, execute) + * the true or false statement + * + * this extension implements the linking algorithm for the two variations identical to the spec + * allowing compiled ES6 circular references to work alongside AMD and CJS circular references. + * + */ + SystemJSLoader.prototype.register = function(name, deps, declare) { + if (typeof name != 'string') { + declare = deps; + deps = name; + name = null; + } + + // dynamic backwards-compatibility + // can be deprecated eventually + if (typeof declare == 'boolean') + return this.registerDynamic.apply(this, arguments); + + var entry = createEntry(); + // ideally wouldn't apply map config to bundle names but + // dependencies go through map regardless so we can't restrict + // could reconsider in shift to new spec + entry.name = name && (this.decanonicalize || this.normalize).call(this, name); + entry.declarative = true; + entry.deps = deps; + entry.declare = declare; + + this.pushRegister_({ + amd: false, + entry: entry + }); + }; + SystemJSLoader.prototype.registerDynamic = function(name, deps, declare, execute) { + if (typeof name != 'string') { + execute = declare; + declare = deps; + deps = name; + name = null; + } + + // dynamic + var entry = createEntry(); + entry.name = name && (this.decanonicalize || this.normalize).call(this, name); + entry.deps = deps; + entry.execute = execute; + entry.executingRequire = declare; + + this.pushRegister_({ + amd: false, + entry: entry + }); + }; + hook('reduceRegister_', function() { + return function(load, register) { + if (!register) + return; + + var entry = register.entry; + var curMeta = load && load.metadata; + + // named register + if (entry.name) { + if (!(entry.name in this.defined)) + this.defined[entry.name] = entry; + + if (curMeta) + curMeta.bundle = true; + } + // anonymous register + if (!entry.name || load && entry.name == load.name) { + if (!curMeta) + throw new TypeError('Unexpected anonymous System.register call.'); + if (curMeta.entry) { + if (curMeta.format == 'register') + throw new Error('Multiple anonymous System.register calls in module ' + load.name + '. If loading a bundle, ensure all the System.register calls are named.'); + else + throw new Error('Module ' + load.name + ' interpreted as ' + curMeta.format + ' module format, but called System.register.'); + } + if (!curMeta.format) + curMeta.format = 'register'; + curMeta.entry = entry; + } + }; + }); + + hookConstructor(function(constructor) { + return function() { + constructor.call(this); + + this.defined = {}; + this._loader.moduleRecords = {}; + }; + }); + + function buildGroups(entry, loader, groups) { + groups[entry.groupIndex] = groups[entry.groupIndex] || []; + + if (indexOf.call(groups[entry.groupIndex], entry) != -1) + return; + + groups[entry.groupIndex].push(entry); + + for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) { + var depName = entry.normalizedDeps[i]; + var depEntry = loader.defined[depName]; + + // not in the registry means already linked / ES6 + if (!depEntry || depEntry.evaluated) + continue; + + // now we know the entry is in our unlinked linkage group + var depGroupIndex = entry.groupIndex + (depEntry.declarative != entry.declarative); + + // the group index of an entry is always the maximum + if (depEntry.groupIndex === null || depEntry.groupIndex < depGroupIndex) { + + // if already in a group, remove from the old group + if (depEntry.groupIndex !== null) { + groups[depEntry.groupIndex].splice(indexOf.call(groups[depEntry.groupIndex], depEntry), 1); + + // if the old group is empty, then we have a mixed depndency cycle + if (groups[depEntry.groupIndex].length == 0) + throw new Error("Mixed dependency cycle detected"); + } + + depEntry.groupIndex = depGroupIndex; + } + + buildGroups(depEntry, loader, groups); + } + } + + function link(name, loader) { + var startEntry = loader.defined[name]; + + // skip if already linked + if (startEntry.module) + return; + + startEntry.groupIndex = 0; + + var groups = []; + + buildGroups(startEntry, loader, groups); + + var curGroupDeclarative = !!startEntry.declarative == groups.length % 2; + for (var i = groups.length - 1; i >= 0; i--) { + var group = groups[i]; + for (var j = 0; j < group.length; j++) { + var entry = group[j]; + + // link each group + if (curGroupDeclarative) + linkDeclarativeModule(entry, loader); + else + linkDynamicModule(entry, loader); + } + curGroupDeclarative = !curGroupDeclarative; + } + } + + // module binding records + function Module() {} + defineProperty(Module, 'toString', { + value: function() { + return 'Module'; + } + }); + + function getOrCreateModuleRecord(name, moduleRecords) { + return moduleRecords[name] || (moduleRecords[name] = { + name: name, + dependencies: [], + exports: new Module(), // start from an empty module and extend + importers: [] + }); + } + + function linkDeclarativeModule(entry, loader) { + // only link if already not already started linking (stops at circular) + if (entry.module) + return; + + var moduleRecords = loader._loader.moduleRecords; + var module = entry.module = getOrCreateModuleRecord(entry.name, moduleRecords); + var exports = entry.module.exports; + + var declaration = entry.declare.call(__global, function(name, value) { + module.locked = true; + + if (typeof name == 'object') { + for (var p in name) + exports[p] = name[p]; + } + else { + exports[name] = value; + } + + for (var i = 0, l = module.importers.length; i < l; i++) { + var importerModule = module.importers[i]; + if (!importerModule.locked) { + var importerIndex = indexOf.call(importerModule.dependencies, module); + importerModule.setters[importerIndex](exports); + } + } + + module.locked = false; + return value; + }, entry.name); + + module.setters = declaration.setters; + module.execute = declaration.execute; + + if (!module.setters || !module.execute) { + throw new TypeError('Invalid System.register form for ' + entry.name); + } + + // now link all the module dependencies + for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) { + var depName = entry.normalizedDeps[i]; + var depEntry = loader.defined[depName]; + var depModule = moduleRecords[depName]; + + // work out how to set depExports based on scenarios... + var depExports; + + if (depModule) { + depExports = depModule.exports; + } + // dynamic, already linked in our registry + else if (depEntry && !depEntry.declarative) { + depExports = depEntry.esModule; + } + // in the loader registry + else if (!depEntry) { + depExports = loader.get(depName); + } + // we have an entry -> link + else { + linkDeclarativeModule(depEntry, loader); + depModule = depEntry.module; + depExports = depModule.exports; + } + + // only declarative modules have dynamic bindings + if (depModule && depModule.importers) { + depModule.importers.push(module); + module.dependencies.push(depModule); + } + else { + module.dependencies.push(null); + } + + // run setters for all entries with the matching dependency name + var originalIndices = entry.originalIndices[i]; + for (var j = 0, len = originalIndices.length; j < len; ++j) { + var index = originalIndices[j]; + if (module.setters[index]) { + module.setters[index](depExports); + } + } + } + } + + // An analog to loader.get covering execution of all three layers (real declarative, simulated declarative, simulated dynamic) + function getModule(name, loader) { + var exports; + var entry = loader.defined[name]; + + if (!entry) { + exports = loader.get(name); + if (!exports) + throw new Error('Unable to load dependency ' + name + '.'); + } + + else { + if (entry.declarative) + ensureEvaluated(name, [], loader); + + else if (!entry.evaluated) + linkDynamicModule(entry, loader); + + exports = entry.module.exports; + } + + if ((!entry || entry.declarative) && exports && exports.__useDefault) + return exports['default']; + + return exports; + } + + function linkDynamicModule(entry, loader) { + if (entry.module) + return; + + var exports = {}; + + var module = entry.module = { exports: exports, id: entry.name }; + + // AMD requires execute the tree first + if (!entry.executingRequire) { + for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) { + var depName = entry.normalizedDeps[i]; + // we know we only need to link dynamic due to linking algorithm + var depEntry = loader.defined[depName]; + if (depEntry) + linkDynamicModule(depEntry, loader); + } + } + + // now execute + entry.evaluated = true; + var output = entry.execute.call(__global, function(name) { + for (var i = 0, l = entry.deps.length; i < l; i++) { + if (entry.deps[i] != name) + continue; + return getModule(entry.normalizedDeps[i], loader); + } + throw new Error('Module ' + name + ' not declared as a dependency.'); + }, exports, module); + + if (output) + module.exports = output; + + // create the esModule object, which allows ES6 named imports of dynamics + exports = module.exports; + + // __esModule flag treats as already-named + if (exports && exports.__esModule) + entry.esModule = exports; + // set module as 'default' export, then fake named exports by iterating properties + else if (entry.esmExports && exports !== __global) + entry.esModule = getESModule(exports); + // just use the 'default' export + else + entry.esModule = { 'default': exports }; + } + + /* + * Given a module, and the list of modules for this current branch, + * ensure that each of the dependencies of this module is evaluated + * (unless one is a circular dependency already in the list of seen + * modules, in which case we execute it) + * + * Then we evaluate the module itself depth-first left to right + * execution to match ES6 modules + */ + function ensureEvaluated(moduleName, seen, loader) { + var entry = loader.defined[moduleName]; + + // if already seen, that means it's an already-evaluated non circular dependency + if (!entry || entry.evaluated || !entry.declarative) + return; + + // this only applies to declarative modules which late-execute + + seen.push(moduleName); + + for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) { + var depName = entry.normalizedDeps[i]; + if (indexOf.call(seen, depName) == -1) { + if (!loader.defined[depName]) + loader.get(depName); + else + ensureEvaluated(depName, seen, loader); + } + } + + if (entry.evaluated) + return; + + entry.evaluated = true; + entry.module.execute.call(__global); + } + + // override the delete method to also clear the register caches + hook('delete', function(del) { + return function(name) { + delete this._loader.moduleRecords[name]; + delete this.defined[name]; + return del.call(this, name); + }; + }); + + hook('fetch', function(fetch) { + return function(load) { + if (this.defined[load.name]) { + load.metadata.format = 'defined'; + return ''; + } + + if (load.metadata.format == 'register' && !load.metadata.authorization && load.metadata.scriptLoad !== false) + load.metadata.scriptLoad = true; + + load.metadata.deps = load.metadata.deps || []; + + return fetch.call(this, load); + }; + }); + + hook('translate', function(translate) { + // we run the meta detection here (register is after meta) + return function(load) { + load.metadata.deps = load.metadata.deps || []; + return Promise.resolve(translate.call(this, load)).then(function(source) { + // run detection for register format + if (load.metadata.format == 'register' || !load.metadata.format && detectRegisterFormat(load.source)) + load.metadata.format = 'register'; + return source; + }); + }; + }); + + hook('instantiate', function(instantiate) { + return function(load) { + if (load.metadata.format == 'detect') + load.metadata.format = undefined; + + // assumes previous instantiate is sync + // (core json support) + instantiate.call(this, load); + + var loader = this; + + var entry; + + // first we check if this module has already been defined in the registry + if (loader.defined[load.name]) { + entry = loader.defined[load.name]; + // don't support deps for ES modules + if (!entry.declarative) + entry.deps = entry.deps.concat(load.metadata.deps); + } + + // picked up already by an anonymous System.register script injection + // or via the dynamic formats + else if (load.metadata.entry) { + entry = load.metadata.entry; + entry.deps = entry.deps.concat(load.metadata.deps); + } + + // Contains System.register calls + // (dont run bundles in the builder) + else if (!(loader.builder && load.metadata.bundle) + && (load.metadata.format == 'register' || load.metadata.format == 'esm' || load.metadata.format == 'es6')) { + + if (typeof __exec != 'undefined') + __exec.call(loader, load); + + if (!load.metadata.entry && !load.metadata.bundle) + throw new Error(load.name + ' detected as ' + load.metadata.format + ' but didn\'t execute.'); + + entry = load.metadata.entry; + + // support metadata deps for System.register + if (entry && load.metadata.deps) + entry.deps = entry.deps.concat(load.metadata.deps); + } + + // named bundles are just an empty module + if (!entry) { + entry = createEntry(); + entry.deps = load.metadata.deps; + entry.execute = function() {}; + } + + // place this module onto defined for circular references + loader.defined[load.name] = entry; + + var grouped = group(entry.deps); + + entry.deps = grouped.names; + entry.originalIndices = grouped.indices; + entry.name = load.name; + entry.esmExports = load.metadata.esmExports !== false; + + // first, normalize all dependencies + var normalizePromises = []; + for (var i = 0, l = entry.deps.length; i < l; i++) + normalizePromises.push(Promise.resolve(loader.normalize(entry.deps[i], load.name))); + + return Promise.all(normalizePromises).then(function(normalizedDeps) { + + entry.normalizedDeps = normalizedDeps; + + return { + deps: entry.deps, + execute: function() { + // recursively ensure that the module and all its + // dependencies are linked (with dependency group handling) + link(load.name, loader); + + // now handle dependency execution in correct order + ensureEvaluated(load.name, [], loader); + + // remove from the registry + loader.defined[load.name] = undefined; + + // return the defined module object + return loader.newModule(entry.declarative ? entry.module.exports : entry.esModule); + } + }; + }); + }; + }); +})(); +hook('reduceRegister_', function(reduceRegister) { + return function(load, register) { + if (register || !load.metadata.exports) + return reduceRegister.call(this, load, register); + + load.metadata.format = 'global'; + var entry = load.metadata.entry = createEntry(); + entry.deps = load.metadata.deps; + var globalValue = readMemberExpression(load.metadata.exports, __global); + entry.execute = function() { + return globalValue; + }; + }; +}); + +hookConstructor(function(constructor) { + return function() { + var loader = this; + constructor.call(loader); + + var hasOwnProperty = Object.prototype.hasOwnProperty; + + // bare minimum ignores for IE8 + var ignoredGlobalProps = ['_g', 'sessionStorage', 'localStorage', 'clipboardData', 'frames', 'frameElement', 'external', + 'mozAnimationStartTime', 'webkitStorageInfo', 'webkitIndexedDB', 'mozInnerScreenY', 'mozInnerScreenX']; + + var globalSnapshot; + + function forEachGlobal(callback) { + if (Object.keys) + Object.keys(__global).forEach(callback); + else + for (var g in __global) { + if (!hasOwnProperty.call(__global, g)) + continue; + callback(g); + } + } + + function forEachGlobalValue(callback) { + forEachGlobal(function(globalName) { + if (indexOf.call(ignoredGlobalProps, globalName) != -1) + return; + try { + var value = __global[globalName]; + } + catch (e) { + ignoredGlobalProps.push(globalName); + } + callback(globalName, value); + }); + } + + loader.set('@@global-helpers', loader.newModule({ + prepareGlobal: function(moduleName, exportName, globals) { + // disable module detection + var curDefine = __global.define; + + __global.define = undefined; + __global.exports = undefined; + if (__global.module && __global.module.exports) + __global.module = undefined; + + // set globals + var oldGlobals; + if (globals) { + oldGlobals = {}; + for (var g in globals) { + oldGlobals[g] = __global[g]; + __global[g] = globals[g]; + } + } + + // store a complete copy of the global object in order to detect changes + if (!exportName) { + globalSnapshot = {}; + + forEachGlobalValue(function(name, value) { + globalSnapshot[name] = value; + }); + } + + // return function to retrieve global + return function() { + var globalValue; + + if (exportName) { + globalValue = readMemberExpression(exportName, __global); + } + else { + var singleGlobal; + var multipleExports; + var exports = {}; + + forEachGlobalValue(function(name, value) { + if (globalSnapshot[name] === value) + return; + if (typeof value == 'undefined') + return; + exports[name] = value; + + if (typeof singleGlobal != 'undefined') { + if (!multipleExports && singleGlobal !== value) + multipleExports = true; + } + else { + singleGlobal = value; + } + }); + globalValue = multipleExports ? exports : singleGlobal; + } + + // revert globals + if (oldGlobals) { + for (var g in oldGlobals) + __global[g] = oldGlobals[g]; + } + __global.define = curDefine; + + return globalValue; + }; + } + })); + }; +}); +hookConstructor(function(constructor) { + return function() { + var loader = this; + constructor.call(loader); + + if (typeof window != 'undefined' && typeof document != 'undefined' && window.location) + var windowOrigin = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : ''); + + loader.set('@@cjs-helpers', loader.newModule({ + getPathVars: function(moduleId) { + // remove any plugin syntax + var pluginIndex = moduleId.lastIndexOf('!'); + var filename; + if (pluginIndex != -1) + filename = moduleId.substr(0, pluginIndex); + else + filename = moduleId; + + var dirname = filename.split('/'); + dirname.pop(); + dirname = dirname.join('/'); + + if (filename.substr(0, 8) == 'file:///') { + filename = filename.substr(7); + dirname = dirname.substr(7); + + // on windows remove leading '/' + if (isWindows) { + filename = filename.substr(1); + dirname = dirname.substr(1); + } + } + else if (windowOrigin && filename.substr(0, windowOrigin.length) === windowOrigin) { + filename = filename.substr(windowOrigin.length); + dirname = dirname.substr(windowOrigin.length); + } + + return { + filename: filename, + dirname: dirname + }; + } + })) + }; +});/* + * AMD Helper function module + * Separated into its own file as this is the part needed for full AMD support in SFX builds + * NB since implementations have now diverged this can be merged back with amd.js + */ +hookConstructor(function(constructor) { + return function() { + var loader = this; + constructor.call(this); + + var commentRegEx = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg; + var cjsRequirePre = "(?:^|[^$_a-zA-Z\\xA0-\\uFFFF.])"; + var cjsRequirePost = "\\s*\\(\\s*(\"([^\"]+)\"|'([^']+)')\\s*\\)"; + var fnBracketRegEx = /\(([^\)]*)\)/; + var wsRegEx = /^\s+|\s+$/g; + + var requireRegExs = {}; + + function getCJSDeps(source, requireIndex) { + + // remove comments + source = source.replace(commentRegEx, ''); + + // determine the require alias + var params = source.match(fnBracketRegEx); + var requireAlias = (params[1].split(',')[requireIndex] || 'require').replace(wsRegEx, ''); + + // find or generate the regex for this requireAlias + var requireRegEx = requireRegExs[requireAlias] || (requireRegExs[requireAlias] = new RegExp(cjsRequirePre + requireAlias + cjsRequirePost, 'g')); + + requireRegEx.lastIndex = 0; + + var deps = []; + + var match; + while (match = requireRegEx.exec(source)) + deps.push(match[2] || match[3]); + + return deps; + } + + /* + AMD-compatible require + To copy RequireJS, set window.require = window.requirejs = loader.amdRequire + */ + function require(names, callback, errback, referer) { + // in amd, first arg can be a config object... we just ignore + if (typeof names == 'object' && !(names instanceof Array)) + return require.apply(null, Array.prototype.splice.call(arguments, 1, arguments.length - 1)); + + // amd require + if (typeof names == 'string' && typeof callback == 'function') + names = [names]; + if (names instanceof Array) { + var dynamicRequires = []; + for (var i = 0; i < names.length; i++) + dynamicRequires.push(loader['import'](names[i], referer)); + Promise.all(dynamicRequires).then(function(modules) { + if (callback) + callback.apply(null, modules); + }, errback); + } + + // commonjs require + else if (typeof names == 'string') { + var module = loader.get(loader.decanonicalize(names, referer)); + if (!module) + throw new Error('Module not already loaded loading "' + names + '" from "' + referer + '".'); + return module.__useDefault ? module['default'] : module; + } + + else + throw new TypeError('Invalid require'); + } + + function define(name, deps, factory) { + if (typeof name != 'string') { + factory = deps; + deps = name; + name = null; + } + if (!(deps instanceof Array)) { + factory = deps; + deps = ['require', 'exports', 'module'].splice(0, factory.length); + } + + if (typeof factory != 'function') + factory = (function(factory) { + return function() { return factory; } + })(factory); + + // in IE8, a trailing comma becomes a trailing undefined entry + if (deps[deps.length - 1] === undefined) + deps.pop(); + + // remove system dependencies + var requireIndex, exportsIndex, moduleIndex; + + if ((requireIndex = indexOf.call(deps, 'require')) != -1) { + + deps.splice(requireIndex, 1); + + // only trace cjs requires for non-named + // named defines assume the trace has already been done + if (!name) + deps = deps.concat(getCJSDeps(factory.toString(), requireIndex)); + } + + if ((exportsIndex = indexOf.call(deps, 'exports')) != -1) + deps.splice(exportsIndex, 1); + + if ((moduleIndex = indexOf.call(deps, 'module')) != -1) + deps.splice(moduleIndex, 1); + + function execute(req, exports, module) { + var depValues = []; + for (var i = 0; i < deps.length; i++) + depValues.push(req(deps[i])); + + module.uri = module.id; + + module.config = function() {}; + + // add back in system dependencies + if (moduleIndex != -1) + depValues.splice(moduleIndex, 0, module); + + if (exportsIndex != -1) + depValues.splice(exportsIndex, 0, exports); + + if (requireIndex != -1) { + function contextualRequire(names, callback, errback) { + if (typeof names == 'string' && typeof callback != 'function') + return req(names); + return require.call(loader, names, callback, errback, module.id); + } + contextualRequire.toUrl = function(name) { + // normalize without defaultJSExtensions + var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js'; + var url = loader.decanonicalize(name, module.id); + if (defaultJSExtension && url.substr(url.length - 3, 3) == '.js') + url = url.substr(0, url.length - 3); + return url; + }; + depValues.splice(requireIndex, 0, contextualRequire); + } + + // set global require to AMD require + var curRequire = __global.require; + __global.require = require; + + var output = factory.apply(exportsIndex == -1 ? __global : exports, depValues); + + __global.require = curRequire; + + if (typeof output == 'undefined' && module) + output = module.exports; + + if (typeof output != 'undefined') + return output; + } + + var entry = createEntry(); + entry.name = name && (loader.decanonicalize || loader.normalize).call(loader, name); + entry.deps = deps; + entry.execute = execute; + + loader.pushRegister_({ + amd: true, + entry: entry + }); + } + define.amd = {}; + + // reduction function to attach defines to a load record + hook('reduceRegister_', function(reduceRegister) { + return function(load, register) { + // only handle AMD registers here + if (!register || !register.amd) + return reduceRegister.call(this, load, register); + + var curMeta = load && load.metadata; + var entry = register.entry; + + if (curMeta) + curMeta.format = 'amd'; + + // anonymous define + if (!entry.name) { + if (!curMeta) + throw new TypeError('Unexpected anonymous AMD define.'); + + // already defined anonymously -> throw + if (curMeta.entry) + throw new TypeError('Multiple defines for anonymous module ' + load.name); + + curMeta.entry = entry; + } + // named define + else { + // if we don't have any other defines, + // then let this be an anonymous define + // this is just to support single modules of the form: + // define('jquery') + // still loading anonymously + // because it is done widely enough to be useful + // as soon as there is more than one define, this gets removed though + if (curMeta) { + if (!curMeta.entry && !curMeta.bundle) + curMeta.entry = entry; + else + curMeta.entry = undefined; + + // note this is now a bundle + curMeta.bundle = true; + } + + // define the module through the register registry + if (!(entry.name in this.defined)) + this.defined[entry.name] = entry; + } + }; + }); + + // adds define as a global (potentially just temporarily) + function createDefine() { + // ensure no NodeJS environment detection + var oldModule = __global.module; + var oldExports = __global.exports; + var oldDefine = __global.define; + + __global.module = undefined; + __global.exports = undefined; + __global.define = define; + + return function() { + __global.define = oldDefine; + __global.module = oldModule; + __global.exports = oldExports; + }; + } + + loader.set('@@amd-helpers', loader.newModule({ + createDefine: createDefine, + require: require, + define: define + })); + loader.amdDefine = define; + loader.amdRequire = require; + }; +});/* + SystemJS Loader Plugin Support + + Supports plugin loader syntax with "!", or via metadata.loader + + The plugin name is loaded as a module itself, and can override standard loader hooks + for the plugin resource. See the plugin section of the systemjs readme. +*/ + +(function() { + function getParentName(loader, parentName) { + // if parent is a plugin, normalize against the parent plugin argument only + if (parentName) { + var parentPluginIndex; + if (loader.pluginFirst) { + if ((parentPluginIndex = parentName.lastIndexOf('!')) != -1) + return parentName.substr(parentPluginIndex + 1); + } + else { + if ((parentPluginIndex = parentName.indexOf('!')) != -1) + return parentName.substr(0, parentPluginIndex); + } + + return parentName; + } + } + + function parsePlugin(loader, name) { + var argumentName; + var pluginName; + + var pluginIndex = name.lastIndexOf('!'); + + if (pluginIndex == -1) + return; + + if (loader.pluginFirst) { + argumentName = name.substr(pluginIndex + 1); + pluginName = name.substr(0, pluginIndex); + } + else { + argumentName = name.substr(0, pluginIndex); + pluginName = name.substr(pluginIndex + 1) || argumentName.substr(argumentName.lastIndexOf('.') + 1); + } + + return { + argument: argumentName, + plugin: pluginName + }; + } + + // put name back together after parts have been normalized + function combinePluginParts(loader, argumentName, pluginName, defaultExtension) { + if (defaultExtension && argumentName.substr(argumentName.length - 3, 3) == '.js') + argumentName = argumentName.substr(0, argumentName.length - 3); + + if (loader.pluginFirst) { + return pluginName + '!' + argumentName; + } + else { + return argumentName + '!' + pluginName; + } + } + + // note if normalize will add a default js extension + // if so, remove for backwards compat + // this is strange and sucks, but will be deprecated + function checkDefaultExtension(loader, arg) { + return loader.defaultJSExtensions && arg.substr(arg.length - 3, 3) != '.js'; + } + + function createNormalizeSync(normalizeSync) { + return function(name, parentName, isPlugin) { + var loader = this; + + parentName = getParentName(this, parentName); + var parsed = parsePlugin(loader, name); + + if (!parsed) + return normalizeSync.call(this, name, parentName, isPlugin); + + // if this is a plugin, normalize the plugin name and the argument + var argumentName = loader.normalizeSync(parsed.argument, parentName, true); + var pluginName = loader.normalizeSync(parsed.plugin, parentName, true); + return combinePluginParts(loader, argumentName, pluginName, checkDefaultExtension(loader, parsed.argument)); + }; + } + + hook('decanonicalize', createNormalizeSync); + hook('normalizeSync', createNormalizeSync); + + hook('normalize', function(normalize) { + return function(name, parentName, isPlugin) { + var loader = this; + + parentName = getParentName(this, parentName); + + var parsed = parsePlugin(loader, name); + + if (!parsed) + return normalize.call(loader, name, parentName, isPlugin); + + return Promise.all([ + loader.normalize(parsed.argument, parentName, true), + loader.normalize(parsed.plugin, parentName, true) + ]) + .then(function(normalized) { + return combinePluginParts(loader, normalized[0], normalized[1], checkDefaultExtension(loader, parsed.argument)); + }); + } + }); + + hook('locate', function(locate) { + return function(load) { + var loader = this; + + var name = load.name; + + // plugin syntax + var pluginSyntaxIndex; + if (loader.pluginFirst) { + if ((pluginSyntaxIndex = name.indexOf('!')) != -1) { + load.metadata.loader = name.substr(0, pluginSyntaxIndex); + load.name = name.substr(pluginSyntaxIndex + 1); + } + } + else { + if ((pluginSyntaxIndex = name.lastIndexOf('!')) != -1) { + load.metadata.loader = name.substr(pluginSyntaxIndex + 1); + load.name = name.substr(0, pluginSyntaxIndex); + } + } + + return locate.call(loader, load) + .then(function(address) { + var plugin = load.metadata.loader; + + if (!plugin) + return address; + + // only fetch the plugin itself if this name isn't defined + if (loader.defined && loader.defined[name]) + return address; + + var pluginLoader = loader.pluginLoader || loader; + + // load the plugin module and run standard locate + return pluginLoader['import'](plugin) + .then(function(loaderModule) { + // store the plugin module itself on the metadata + load.metadata.loaderModule = loaderModule; + + load.address = address; + if (loaderModule.locate) + return loaderModule.locate.call(loader, load); + + return address; + }); + }); + }; + }); + + hook('fetch', function(fetch) { + return function(load) { + var loader = this; + if (load.metadata.loaderModule && load.metadata.loaderModule.fetch && load.metadata.format != 'defined') { + load.metadata.scriptLoad = false; + return load.metadata.loaderModule.fetch.call(loader, load, function(load) { + return fetch.call(loader, load); + }); + } + else { + return fetch.call(loader, load); + } + }; + }); + + hook('translate', function(translate) { + return function(load) { + + /* + * Source map sanitization for load.metadata.sourceMap + * Used to set browser and build-level source maps for + * translated sources in a general way. + * + * This isn't plugin-specific, but can't go anywhere else for now + * As it is post-translate + */ + var sourceMap = load.metadata.sourceMap; + + // if an object not a JSON string do sanitizing + if (sourceMap && typeof sourceMap == 'object') { + var originalName = load.name.split('!')[0]; + + // force set the filename of the original file + sourceMap.file = originalName + '!transpiled'; + + // force set the sources list if only one source + if (!sourceMap.sources || sourceMap.sources.length == 1) + sourceMap.sources = [originalName]; + load.metadata.sourceMap = JSON.stringify(sourceMap); + } + + var loader = this; + if (load.metadata.loaderModule && load.metadata.loaderModule.translate && load.metadata.format != 'defined') { + return Promise.resolve(load.metadata.loaderModule.translate.call(loader, load)).then(function(result) { + // NB we should probably enforce a string output + if (typeof result == 'string') + load.source = result; + return translate.call(loader, load); + }); + } + else { + return translate.call(loader, load); + } + }; + }); + + hook('instantiate', function(instantiate) { + return function(load) { + var loader = this; + + if (load.metadata.loaderModule && load.metadata.loaderModule.instantiate && !loader.builder && load.metadata.format != 'defined') + return Promise.resolve(load.metadata.loaderModule.instantiate.call(loader, load)).then(function(result) { + load.metadata.entry = createEntry(); + load.metadata.entry.execute = function() { + return result; + } + load.metadata.entry.deps = load.metadata.deps; + load.metadata.format = 'defined'; + return instantiate.call(loader, load); + }); + else + return instantiate.call(loader, load); + }; + }); + +})();/* + * Conditions Extension + * + * Allows a condition module to alter the resolution of an import via syntax: + * + * import $ from 'jquery/#{browser}'; + * + * Will first load the module 'browser' via `SystemJS.import('browser')` and + * take the default export of that module. + * If the default export is not a string, an error is thrown. + * + * We then substitute the string into the require to get the conditional resolution + * enabling environment-specific variations like: + * + * import $ from 'jquery/ie' + * import $ from 'jquery/firefox' + * import $ from 'jquery/chrome' + * import $ from 'jquery/safari' + * + * It can be useful for a condition module to define multiple conditions. + * This can be done via the `|` modifier to specify an export member expression: + * + * import 'jquery/#{./browser.js|grade.version}' + * + * Where the `grade` export `version` member in the `browser.js` module is substituted. + * + * + * Boolean Conditionals + * + * For polyfill modules, that are used as imports but have no module value, + * a binary conditional allows a module not to be loaded at all if not needed: + * + * import 'es5-shim#?./conditions.js|needs-es5shim' + * + * These conditions can also be negated via: + * + * import 'es5-shim#?~./conditions.js|es6' + * + */ + + function parseCondition(condition) { + var conditionExport, conditionModule, negation; + + var negation = condition[0] == '~'; + var conditionExportIndex = condition.lastIndexOf('|'); + if (conditionExportIndex != -1) { + conditionExport = condition.substr(conditionExportIndex + 1); + conditionModule = condition.substr(negation, conditionExportIndex - negation) || '@system-env'; + } + else { + conditionExport = null; + conditionModule = condition.substr(negation); + } + + return { + module: conditionModule, + prop: conditionExport, + negate: negation + }; + } + + function serializeCondition(conditionObj) { + return (conditionObj.negate ? '~' : '') + conditionObj.module + (conditionObj.prop ? '|' + conditionObj.prop : ''); + } + + function resolveCondition(conditionObj, parentName, bool) { + return this['import'](conditionObj.module, parentName) + .then(function(m) { + if (conditionObj.prop) + m = readMemberExpression(conditionObj.prop, m); + else if (typeof m == 'object' && m + '' == 'Module') + m = m['default']; + + return conditionObj.negate ? !m : m; + }); + } + + var interpolationRegEx = /#\{[^\}]+\}/; + function interpolateConditional(name, parentName) { + // first we normalize the conditional + var conditionalMatch = name.match(interpolationRegEx); + + if (!conditionalMatch) + return Promise.resolve(name); + + var conditionObj = parseCondition(conditionalMatch[0].substr(2, conditionalMatch[0].length - 3)); + + // in builds, return normalized conditional + if (this.builder) + return this['normalize'](conditionObj.module, parentName) + .then(function(conditionModule) { + conditionObj.module = conditionModule; + return name.replace(interpolationRegEx, '#{' + serializeCondition(conditionObj) + '}'); + }); + + return resolveCondition.call(this, conditionObj, parentName, false) + .then(function(conditionValue) { + if (typeof conditionValue !== 'string') + throw new TypeError('The condition value for ' + name + ' doesn\'t resolve to a string.'); + + if (conditionValue.indexOf('/') != -1) + throw new TypeError('Unabled to interpolate conditional ' + name + (parentName ? ' in ' + parentName : '') + '\n\tThe condition value ' + conditionValue + ' cannot contain a "/" separator.'); + + return name.replace(interpolationRegEx, conditionValue); + }); + } + + function booleanConditional(name, parentName) { + // first we normalize the conditional + var booleanIndex = name.lastIndexOf('#?'); + + if (booleanIndex == -1) + return Promise.resolve(name); + + var conditionObj = parseCondition(name.substr(booleanIndex + 2)); + + // in builds, return normalized conditional + if (this.builder) + return this['normalize'](conditionObj.module, parentName) + .then(function(conditionModule) { + conditionObj.module = conditionModule; + return name.substr(0, booleanIndex) + '#?' + serializeCondition(conditionObj); + }); + + return resolveCondition.call(this, conditionObj, parentName, true) + .then(function(conditionValue) { + return conditionValue ? name.substr(0, booleanIndex) : '@empty'; + }); + } + + // normalizeSync does not parse conditionals at all although it could + hook('normalize', function(normalize) { + return function(name, parentName, parentAddress) { + var loader = this; + return booleanConditional.call(loader, name, parentName) + .then(function(name) { + return normalize.call(loader, name, parentName, parentAddress); + }) + .then(function(normalized) { + return interpolateConditional.call(loader, normalized, parentName); + }); + }; + }); +/* + * Alias Extension + * + * Allows a module to be a plain copy of another module by module name + * + * SystemJS.meta['mybootstrapalias'] = { alias: 'bootstrap' }; + * + */ +(function() { + // aliases + hook('fetch', function(fetch) { + return function(load) { + var alias = load.metadata.alias; + var aliasDeps = load.metadata.deps || []; + if (alias) { + load.metadata.format = 'defined'; + var entry = createEntry(); + this.defined[load.name] = entry; + entry.declarative = true; + entry.deps = aliasDeps.concat([alias]); + entry.declare = function(_export) { + return { + setters: [function(module) { + for (var p in module) + _export(p, module[p]); + if (module.__useDefault) + entry.module.exports.__useDefault = true; + }], + execute: function() {} + }; + }; + return ''; + } + + return fetch.call(this, load); + }; + }); +})();/* + * Meta Extension + * + * Sets default metadata on a load record (load.metadata) from + * loader.metadata via SystemJS.meta function. + * + * + * Also provides an inline meta syntax for module meta in source. + * + * Eg: + * + * loader.meta({ + * 'my/module': { deps: ['jquery'] } + * 'my/*': { format: 'amd' } + * }); + * + * Which in turn populates loader.metadata. + * + * load.metadata.deps and load.metadata.format will then be set + * for 'my/module' + * + * The same meta could be set with a my/module.js file containing: + * + * my/module.js + * "format amd"; + * "deps[] jquery"; + * "globals.some value" + * console.log('this is my/module'); + * + * Configuration meta always takes preference to inline meta. + * + * Multiple matches in wildcards are supported and ammend the meta. + * + * + * The benefits of the function form is that paths are URL-normalized + * supporting say + * + * loader.meta({ './app': { format: 'cjs' } }); + * + * Instead of needing to set against the absolute URL (https://site.com/app.js) + * + */ + +(function() { + + hookConstructor(function(constructor) { + return function() { + this.meta = {}; + constructor.call(this); + }; + }); + + hook('locate', function(locate) { + return function(load) { + var meta = this.meta; + var name = load.name; + + // NB for perf, maybe introduce a fast-path wildcard lookup cache here + // which is checked first + + // apply wildcard metas + var bestDepth = 0; + var wildcardIndex; + for (var module in meta) { + wildcardIndex = module.indexOf('*'); + if (wildcardIndex === -1) + continue; + if (module.substr(0, wildcardIndex) === name.substr(0, wildcardIndex) + && module.substr(wildcardIndex + 1) === name.substr(name.length - module.length + wildcardIndex + 1)) { + var depth = module.split('/').length; + if (depth > bestDepth) + bestDepth = depth; + extendMeta(load.metadata, meta[module], bestDepth != depth); + } + } + + // apply exact meta + if (meta[name]) + extendMeta(load.metadata, meta[name]); + + return locate.call(this, load); + }; + }); + + // detect any meta header syntax + // only set if not already set + var metaRegEx = /^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)+/; + var metaPartRegEx = /\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\/\/[^\n]*|"[^"]+"\s*;?|'[^']+'\s*;?/g; + + function setMetaProperty(target, p, value) { + var pParts = p.split('.'); + var curPart; + while (pParts.length > 1) { + curPart = pParts.shift(); + target = target[curPart] = target[curPart] || {}; + } + curPart = pParts.shift(); + if (!(curPart in target)) + target[curPart] = value; + } + + hook('translate', function(translate) { + return function(load) { + // NB meta will be post-translate pending transpiler conversion to plugins + var meta = load.source.match(metaRegEx); + if (meta) { + var metaParts = meta[0].match(metaPartRegEx); + + for (var i = 0; i < metaParts.length; i++) { + var curPart = metaParts[i]; + var len = curPart.length; + + var firstChar = curPart.substr(0, 1); + if (curPart.substr(len - 1, 1) == ';') + len--; + + if (firstChar != '"' && firstChar != "'") + continue; + + var metaString = curPart.substr(1, curPart.length - 3); + var metaName = metaString.substr(0, metaString.indexOf(' ')); + + if (metaName) { + var metaValue = metaString.substr(metaName.length + 1, metaString.length - metaName.length - 1); + + if (metaName.substr(metaName.length - 2, 2) == '[]') { + metaName = metaName.substr(0, metaName.length - 2); + load.metadata[metaName] = load.metadata[metaName] || []; + load.metadata[metaName].push(metaValue); + } + else if (load.metadata[metaName] instanceof Array) { + // temporary backwards compat for previous "deps" syntax + warn.call(this, 'Module ' + load.name + ' contains deprecated "deps ' + metaValue + '" meta syntax.\nThis should be updated to "deps[] ' + metaValue + '" for pushing to array meta.'); + load.metadata[metaName].push(metaValue); + } + else { + setMetaProperty(load.metadata, metaName, metaValue); + } + } + else { + load.metadata[metaString] = true; + } + } + } + + return translate.call(this, load); + }; + }); +})(); +/* + System bundles + + Allows a bundle module to be specified which will be dynamically + loaded before trying to load a given module. + + For example: + SystemJS.bundles['mybundle'] = ['jquery', 'bootstrap/js/bootstrap'] + + Will result in a load to "mybundle" whenever a load to "jquery" + or "bootstrap/js/bootstrap" is made. + + In this way, the bundle becomes the request that provides the module +*/ + +(function() { + // bundles support (just like RequireJS) + // bundle name is module name of bundle itself + // bundle is array of modules defined by the bundle + // when a module in the bundle is requested, the bundle is loaded instead + // of the form SystemJS.bundles['mybundle'] = ['jquery', 'bootstrap/js/bootstrap'] + hookConstructor(function(constructor) { + return function() { + constructor.call(this); + this.bundles = {}; + this._loader.loadedBundles = {}; + }; + }); + + // assign bundle metadata for bundle loads + hook('locate', function(locate) { + return function(load) { + var loader = this; + var matched = false; + + if (!(load.name in loader.defined)) + for (var b in loader.bundles) { + for (var i = 0; i < loader.bundles[b].length; i++) { + var curModule = loader.bundles[b][i]; + + if (curModule == load.name) { + matched = true; + break; + } + + // wildcard in bundles does not include / boundaries + if (curModule.indexOf('*') != -1) { + var parts = curModule.split('*'); + if (parts.length != 2) { + loader.bundles[b].splice(i--, 1); + continue; + } + + if (load.name.substring(0, parts[0].length) == parts[0] && + load.name.substr(load.name.length - parts[1].length, parts[1].length) == parts[1] && + load.name.substr(parts[0].length, load.name.length - parts[1].length - parts[0].length).indexOf('/') == -1) { + matched = true; + break; + } + } + } + + if (matched) + return loader['import'](b) + .then(function() { + return locate.call(loader, load); + }); + } + + return locate.call(loader, load); + }; + }); +})(); +/* + * Dependency Tree Cache + * + * Allows a build to pre-populate a dependency trace tree on the loader of + * the expected dependency tree, to be loaded upfront when requesting the + * module, avoinding the n round trips latency of module loading, where + * n is the dependency tree depth. + * + * eg: + * SystemJS.depCache = { + * 'app': ['normalized', 'deps'], + * 'normalized': ['another'], + * 'deps': ['tree'] + * }; + * + * SystemJS.import('app') + * // simultaneously starts loading all of: + * // 'normalized', 'deps', 'another', 'tree' + * // before "app" source is even loaded + * + */ + +(function() { + hookConstructor(function(constructor) { + return function() { + constructor.call(this); + this.depCache = {}; + } + }); + + hook('locate', function(locate) { + return function(load) { + var loader = this; + // load direct deps, in turn will pick up their trace trees + var deps = loader.depCache[load.name]; + if (deps) + for (var i = 0; i < deps.length; i++) + loader['import'](deps[i], load.name); + + return locate.call(loader, load); + }; + }); +})(); + +/* + * Script-only addition used for production loader + * + */ +hookConstructor(function(constructor) { + return function() { + constructor.apply(this, arguments); + + // prepare amd define + if (this.has('@@amd-helpers')) + this.get('@@amd-helpers').createDefine(); + }; +}); + +hook('fetch', function(fetch) { + return function(load) { + load.metadata.scriptLoad = true; + return fetch.call(this, load); + }; +});System = new SystemJSLoader(); + +__global.SystemJS = System; +System.version = '0.19.17 CSP'; + // -- exporting -- + + if (typeof exports === 'object') + module.exports = Loader; + + __global.Reflect = __global.Reflect || {}; + __global.Reflect.Loader = __global.Reflect.Loader || Loader; + __global.Reflect.global = __global.Reflect.global || __global; + __global.LoaderPolyfill = Loader; + + if (!System) { + System = new SystemLoader(); + System.constructor = SystemLoader; + } + + if (typeof exports === 'object') + module.exports = System; + + __global.System = System; + +})(typeof self != 'undefined' ? self : global);} + +// auto-load Promise and URL polyfills if needed in the browser +try { + var hasURL = typeof URLPolyfill != 'undefined' || new URL('test:///').protocol == 'test:'; +} +catch(e) {} + +if (typeof Promise === 'undefined' || !hasURL) { + // document.write + if (typeof document !== 'undefined') { + var scripts = document.getElementsByTagName('script'); + $__curScript = scripts[scripts.length - 1]; + var curPath = $__curScript.src; + var basePath = curPath.substr(0, curPath.lastIndexOf('/') + 1); + window.systemJSBootstrap = bootstrap; + document.write( + '<' + 'script type="text/javascript" src="' + basePath + 'system-polyfills.js">' + '<' + '/script>' + ); + } + // importScripts + else if (typeof importScripts !== 'undefined') { + var basePath = ''; + try { + throw new Error('_'); + } catch (e) { + e.stack.replace(/(?:at|@).*(http.+):[\d]+:[\d]+/, function(m, url) { + basePath = url.replace(/\/[^\/]*$/, '/'); + }); + } + importScripts(basePath + 'system-polyfills.js'); + bootstrap(); + } + else { + bootstrap(); + } +} +else { + bootstrap(); +} + + +})();
\ No newline at end of file |