Added files for Juan

This commit is contained in:
2024-08-07 11:38:48 -07:00
parent f7878e3e60
commit 795d1d72ce
2871 changed files with 621552 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,146 @@
/**
* @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
'use strict';
var lang,
hasOwn = Object.prototype.hasOwnProperty;
function hasProp(obj, prop) {
return hasOwn.call(obj, prop);
}
lang = {
backSlashRegExp: /\\/g,
ostring: Object.prototype.toString,
isArray: Array.isArray || function(it) {
return lang.ostring.call(it) === "[object Array]";
},
isFunction: function(it) {
return lang.ostring.call(it) === "[object Function]";
},
isRegExp: function(it) {
return it && it instanceof RegExp;
},
hasProp: hasProp,
//returns true if the object does not have an own property prop,
//or if it does, it is a falsy value.
falseProp: function(obj, prop) {
return !hasProp(obj, prop) || !obj[prop];
},
//gets own property value for given prop on object
getOwn: function(obj, prop) {
return hasProp(obj, prop) && obj[prop];
},
_mixin: function(dest, source, override) {
var name;
for (name in source) {
if (source.hasOwnProperty(name)
&& (override || !dest.hasOwnProperty(name))) {
dest[name] = source[name];
}
}
return dest; // Object
},
/**
* mixin({}, obj1, obj2) is allowed. If the last argument is a boolean,
* then the source objects properties are force copied over to dest.
*/
mixin: function(dest) {
var parameters = Array.prototype.slice.call(arguments),
override, i, l;
if (!dest) {
dest = {};
}
if (parameters.length > 2 && typeof arguments[parameters.length - 1] === 'boolean') {
override = parameters.pop();
}
for (i = 1, l = parameters.length; i < l; i++) {
lang._mixin(dest, parameters[i], override);
}
return dest; // Object
},
delegate: (function() {
// boodman/crockford delegation w/ cornford optimization
function TMP() {
}
return function(obj, props) {
TMP.prototype = obj;
var tmp = new TMP();
TMP.prototype = null;
if (props) {
lang.mixin(tmp, props);
}
return tmp; // Object
};
}()),
/**
* Helper function for iterating over an array. If the func returns
* a true value, it will break out of the loop.
*/
each: function each(ary, func) {
if (ary) {
var i;
for (i = 0; i < ary.length; i += 1) {
if (func(ary[i], i, ary)) {
break;
}
}
}
},
/**
* Cycles over properties in an object and calls a function for each
* property value. If the function returns a truthy value, then the
* iteration is stopped.
*/
eachProp: function eachProp(obj, func) {
var prop;
for (prop in obj) {
if (hasProp(obj, prop)) {
if (func(obj[prop], prop)) {
break;
}
}
}
},
//Similar to Function.prototype.bind, but the "this" object is specified
//first, since it is easier to read/figure out what "this" will be.
bind: function bind(obj, fn) {
return function() {
return fn.apply(obj, arguments);
};
},
//Escapes a content string to be be a string that has characters escaped
//for inclusion as part of a JS string.
jsEscape: function(content) {
return content.replace(/(["'\\])/g, '\\$1')
.replace(/[\f]/g, "\\f")
.replace(/[\b]/g, "\\b")
.replace(/[\n]/g, "\\n")
.replace(/[\t]/g, "\\t")
.replace(/[\r]/g, "\\r");
}
};
module.exports = lang;

View File

@@ -0,0 +1,819 @@
/**
* @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
'use strict';
var esprima = require('./esprima'),
lang = require('./lang');
function arrayToString(ary) {
var output = '[';
if (ary) {
ary.forEach(function(item, i) {
output += (i > 0 ? ',' : '') + '"' + lang.jsEscape(item) + '"';
});
}
output += ']';
return output;
}
//This string is saved off because JSLint complains
//about obj.arguments use, as 'reserved word'
var argPropName = 'arguments';
//From an esprima example for traversing its ast.
function traverse(object, visitor) {
var key, child;
if (!object) {
return;
}
if (visitor.call(null, object) === false) {
return false;
}
for (key in object) {
if (object.hasOwnProperty(key)) {
child = object[key];
if (typeof child === 'object' && child !== null) {
if (traverse(child, visitor) === false) {
return false;
}
}
}
}
}
/**
* Pulls out dependencies from an array literal with just string members.
* If string literals, will just return those string values in an array,
* skipping other items in the array.
*
* @param {Node} node an AST node.
*
* @returns {Array} an array of strings.
* If null is returned, then it means the input node was not a valid
* dependency.
*/
function getValidDeps(node) {
if (!node || node.type !== 'ArrayExpression' || !node.elements) {
return;
}
var deps = [];
node.elements.some(function(elem) {
if (elem.type === 'Literal') {
deps.push(elem.value);
}
});
return deps.length ? deps : undefined;
}
/**
* Main parse function. Returns a string of any valid require or
* define/require.def calls as part of one JavaScript source string.
* @param {String} moduleName the module name that represents this file.
* It is used to create a default define if there is not one already for the
* file. This allows properly tracing dependencies for builds. Otherwise, if
* the file just has a require() call, the file dependencies will not be
* properly reflected: the file will come before its dependencies.
* @param {String} moduleName
* @param {String} fileName
* @param {String} fileContents
* @param {Object} options optional options. insertNeedsDefine: true will
* add calls to require.needsDefine() if appropriate.
* @returns {String} JS source string or null, if no require or
* define/require.def calls are found.
*/
function parse(moduleName, fileName, fileContents, options) {
options = options || {};
//Set up source input
var i, moduleCall, depString,
moduleDeps = [],
result = '',
moduleList = [],
needsDefine = true,
astRoot = esprima.parse(fileContents);
parse.recurse(astRoot, function(callName, config, name, deps) {
if (!deps) {
deps = [];
}
if (callName === 'define' && (!name || name === moduleName)) {
needsDefine = false;
}
if (!name) {
//If there is no module name, the dependencies are for
//this file/default module name.
moduleDeps = moduleDeps.concat(deps);
} else {
moduleList.push({
name: name,
deps: deps
});
}
//If define was found, no need to dive deeper, unless
//the config explicitly wants to dig deeper.
return !!options.findNestedDependencies;
}, options);
if (options.insertNeedsDefine && needsDefine) {
result += 'require.needsDefine("' + moduleName + '");';
}
if (moduleDeps.length || moduleList.length) {
for (i = 0; i < moduleList.length; i++) {
moduleCall = moduleList[i];
if (result) {
result += '\n';
}
//If this is the main module for this file, combine any
//"anonymous" dependencies (could come from a nested require
//call) with this module.
if (moduleCall.name === moduleName) {
moduleCall.deps = moduleCall.deps.concat(moduleDeps);
moduleDeps = [];
}
depString = arrayToString(moduleCall.deps);
result += 'define("' + moduleCall.name + '",' +
depString + ');';
}
if (moduleDeps.length) {
if (result) {
result += '\n';
}
depString = arrayToString(moduleDeps);
result += 'define("' + moduleName + '",' + depString + ');';
}
}
return result || null;
}
/**
* Handles parsing a file recursively for require calls.
* @param {Array} parentNode the AST node to start with.
* @param {Function} onMatch function to call on a parse match.
* @param {Object} [options] This is normally the build config options if
* it is passed.
*/
parse.recurse = function(object, onMatch, options) {
//Like traverse, but skips if branches that would not be processed
//after has application that results in tests of true or false boolean
//literal values.
var key, child,
hasHas = options && options.has;
if (!object) {
return;
}
//If has replacement has resulted in if(true){} or if(false){}, take
//the appropriate branch and skip the other one.
if (hasHas && object.type === 'IfStatement' && object.test.type &&
object.test.type === 'Literal') {
if (object.test.value) {
//Take the if branch
this.recurse(object.consequent, onMatch, options);
} else {
//Take the else branch
this.recurse(object.alternate, onMatch, options);
}
} else {
if (this.parseNode(object, onMatch) === false) {
return;
}
for (key in object) {
if (object.hasOwnProperty(key)) {
child = object[key];
if (typeof child === 'object' && child !== null) {
this.recurse(child, onMatch, options);
}
}
}
}
};
/**
* Determines if the file defines the require/define module API.
* Specifically, it looks for the `define.amd = ` expression.
* @param {String} fileName
* @param {String} fileContents
* @returns {Boolean}
*/
parse.definesRequire = function(fileName, fileContents) {
var found = false;
traverse(esprima.parse(fileContents), function(node) {
if (parse.hasDefineAmd(node)) {
found = true;
//Stop traversal
return false;
}
});
return found;
};
/**
* Finds require("") calls inside a CommonJS anonymous module wrapped in a
* define(function(require, exports, module){}) wrapper. These dependencies
* will be added to a modified define() call that lists the dependencies
* on the outside of the function.
* @param {String} fileName
* @param {String} fileContents
* @returns {Array} an array of module names that are dependencies. Always
* returns an array, but could be of length zero.
*/
parse.getAnonDeps = function(fileName, fileContents) {
var astRoot = esprima.parse(fileContents),
defFunc = this.findAnonDefineFactory(astRoot);
return parse.getAnonDepsFromNode(defFunc);
};
/**
* Finds require("") calls inside a CommonJS anonymous module wrapped
* in a define function, given an AST node for the definition function.
* @param {Node} node the AST node for the definition function.
* @returns {Array} and array of dependency names. Can be of zero length.
*/
parse.getAnonDepsFromNode = function(node) {
var deps = [],
funcArgLength;
if (node) {
this.findRequireDepNames(node, deps);
//If no deps, still add the standard CommonJS require, exports,
//module, in that order, to the deps, but only if specified as
//function args. In particular, if exports is used, it is favored
//over the return value of the function, so only add it if asked.
funcArgLength = node.params && node.params.length;
if (funcArgLength) {
deps = (funcArgLength > 1 ? ["require", "exports", "module"] :
["require"]).concat(deps);
}
}
return deps;
};
/**
* Finds the function in define(function (require, exports, module){});
* @param {Array} node
* @returns {Boolean}
*/
parse.findAnonDefineFactory = function(node) {
var match;
traverse(node, function(node) {
var arg0, arg1;
if (node && node.type === 'CallExpression' &&
node.callee && node.callee.type === 'Identifier' &&
node.callee.name === 'define' && node[argPropName]) {
//Just the factory function passed to define
arg0 = node[argPropName][0];
if (arg0 && arg0.type === 'FunctionExpression') {
match = arg0;
return false;
}
//A string literal module ID followed by the factory function.
arg1 = node[argPropName][1];
if (arg0.type === 'Literal' &&
arg1 && arg1.type === 'FunctionExpression') {
match = arg1;
return false;
}
}
});
return match;
};
/**
* Finds any config that is passed to requirejs. That includes calls to
* require/requirejs.config(), as well as require({}, ...) and
* requirejs({}, ...)
* @param {String} fileContents
*
* @returns {Object} a config details object with the following properties:
* - config: {Object} the config object found. Can be undefined if no
* config found.
* - range: {Array} the start index and end index in the contents where
* the config was found. Can be undefined if no config found.
* Can throw an error if the config in the file cannot be evaluated in
* a build context to valid JavaScript.
*/
parse.findConfig = function(fileContents) {
/*jslint evil: true */
var jsConfig, foundRange, foundConfig,
astRoot = esprima.parse(fileContents, {
range: true
});
traverse(astRoot, function(node) {
var arg,
requireType = parse.hasRequire(node);
if (requireType && (requireType === 'require' ||
requireType === 'requirejs' ||
requireType === 'requireConfig' ||
requireType === 'requirejsConfig')) {
arg = node[argPropName] && node[argPropName][0];
if (arg && arg.type === 'ObjectExpression') {
jsConfig = parse.nodeToString(fileContents, arg);
foundRange = arg.range;
return false;
}
} else {
arg = parse.getRequireObjectLiteral(node);
if (arg) {
jsConfig = parse.nodeToString(fileContents, arg);
foundRange = arg.range;
return false;
} else {
arg = parse.getObjectLiteral(node);
if (arg) {
jsConfig = parse.nodeToString(fileContents, arg);
foundRange = arg.range;
return false;
}
}
}
});
if (jsConfig) {
foundConfig = eval('(' + jsConfig + ')');
}
return {
config: foundConfig,
range: foundRange
};
};
/** Returns the node for the object literal assigned to require/requirejs,
* for holding a declarative config.
*/
parse.getRequireObjectLiteral = function(node) {
if (node.id && node.id.type === 'Identifier' &&
(node.id.name === 'require' || node.id.name === 'requirejs') &&
node.init && node.init.type === 'ObjectExpression') {
return node.init;
}
};
/**
* for holding requirejs build file
*/
parse.getObjectLiteral = function (node) {
if (node.type && node.type === 'ExpressionStatement' &&
(node.expression && !node.arguments) &&
(node.expression.type && node.expression.type === 'ObjectExpression') &&
(node.expression.properties && node.expression.properties.length > 0) &&
(node.expression.properties[0].type && node.expression.properties[0].type === 'Property'))
return node;
};
/**
* Renames require/requirejs/define calls to be ns + '.' + require/requirejs/define
* Does *not* do .config calls though. See pragma.namespace for the complete
* set of namespace transforms. This function is used because require calls
* inside a define() call should not be renamed, so a simple regexp is not
* good enough.
* @param {String} fileContents the contents to transform.
* @param {String} ns the namespace, *not* including trailing dot.
* @return {String} the fileContents with the namespace applied
*/
parse.renameNamespace = function(fileContents, ns) {
var ranges = [],
astRoot = esprima.parse(fileContents, {
range: true
});
parse.recurse(astRoot, function(callName, config, name, deps, node) {
ranges.push(node.range);
//Do not recurse into define functions, they should be using
//local defines.
return callName !== 'define';
}, {});
//Go backwards through the found ranges, adding in the namespace name
//in front.
ranges.reverse();
ranges.forEach(function(range) {
fileContents = fileContents.substring(0, range[0]) +
ns + '.' +
fileContents.substring(range[0]);
});
return fileContents;
};
/**
* Finds all dependencies specified in dependency arrays and inside
* simplified commonjs wrappers.
* @param {String} fileName
* @param {String} fileContents
*
* @returns {Array} an array of dependency strings. The dependencies
* have not been normalized, they may be relative IDs.
*/
parse.findDependencies = function(fileName, fileContents, options) {
var dependencies = [],
astRoot = esprima.parse(fileContents);
parse.recurse(astRoot, function(callName, config, name, deps) {
if (deps) {
dependencies = dependencies.concat(deps);
}
}, options);
return dependencies;
};
/**
* Finds only CJS dependencies, ones that are the form
* require('stringLiteral')
*/
parse.findCjsDependencies = function(fileName, fileContents) {
var dependencies = [];
traverse(esprima.parse(fileContents), function(node) {
var arg;
if (node && node.type === 'CallExpression' && node.callee &&
node.callee.type === 'Identifier' &&
node.callee.name === 'require' && node[argPropName] &&
node[argPropName].length === 1) {
arg = node[argPropName][0];
if (arg.type === 'Literal') {
dependencies.push(arg.value);
}
}
});
return dependencies;
};
//function define() {}
parse.hasDefDefine = function(node) {
return node.type === 'FunctionDeclaration' && node.id &&
node.id.type === 'Identifier' && node.id.name === 'define';
};
//define.amd = ...
parse.hasDefineAmd = function(node) {
return node && node.type === 'AssignmentExpression' &&
node.left && node.left.type === 'MemberExpression' &&
node.left.object && node.left.object.name === 'define' &&
node.left.property && node.left.property.name === 'amd';
};
//require(), requirejs(), require.config() and requirejs.config()
parse.hasRequire = function(node) {
var callName,
c = node && node.callee;
if (node && node.type === 'CallExpression' && c) {
if (c.type === 'Identifier' &&
(c.name === 'require' ||
c.name === 'requirejs')) {
//A require/requirejs({}, ...) call
callName = c.name;
} else if (c.type === 'MemberExpression' &&
c.object &&
c.object.type === 'Identifier' &&
(c.object.name === 'require' ||
c.object.name === 'requirejs') &&
c.property && c.property.name === 'config') {
// require/requirejs.config({}) call
callName = c.object.name + 'Config';
}
}
return callName;
};
//define()
parse.hasDefine = function(node) {
return node && node.type === 'CallExpression' && node.callee &&
node.callee.type === 'Identifier' &&
node.callee.name === 'define';
};
/**
* If there is a named define in the file, returns the name. Does not
* scan for mulitple names, just the first one.
*/
parse.getNamedDefine = function(fileContents) {
var name;
traverse(esprima.parse(fileContents), function(node) {
if (node && node.type === 'CallExpression' && node.callee &&
node.callee.type === 'Identifier' &&
node.callee.name === 'define' &&
node[argPropName] && node[argPropName][0] &&
node[argPropName][0].type === 'Literal') {
name = node[argPropName][0].value;
return false;
}
});
return name;
};
/**
* Determines if define(), require({}|[]) or requirejs was called in the
* file. Also finds out if define() is declared and if define.amd is called.
*/
parse.usesAmdOrRequireJs = function(fileName, fileContents) {
var uses;
traverse(esprima.parse(fileContents), function(node) {
var type, callName, arg;
if (parse.hasDefDefine(node)) {
//function define() {}
type = 'declaresDefine';
} else if (parse.hasDefineAmd(node)) {
type = 'defineAmd';
} else {
callName = parse.hasRequire(node);
if (callName) {
arg = node[argPropName] && node[argPropName][0];
if (arg && (arg.type === 'ObjectExpression' ||
arg.type === 'ArrayExpression')) {
type = callName;
}
} else if (parse.hasDefine(node)) {
type = 'define';
}
}
if (type) {
if (!uses) {
uses = {};
}
uses[type] = true;
}
});
return uses;
};
/**
* Determines if require(''), exports.x =, module.exports =,
* __dirname, __filename are used. So, not strictly traditional CommonJS,
* also checks for Node variants.
*/
parse.usesCommonJs = function(fileName, fileContents) {
var uses = null,
assignsExports = false;
traverse(esprima.parse(fileContents), function(node) {
var type,
exp = node.expression;
if (node.type === 'Identifier' &&
(node.name === '__dirname' || node.name === '__filename')) {
type = node.name.substring(2);
} else if (node.type === 'VariableDeclarator' && node.id &&
node.id.type === 'Identifier' &&
node.id.name === 'exports') {
//Hmm, a variable assignment for exports, so does not use cjs
//exports.
type = 'varExports';
} else if (exp && exp.type === 'AssignmentExpression' && exp.left &&
exp.left.type === 'MemberExpression' && exp.left.object) {
if (exp.left.object.name === 'module' && exp.left.property &&
exp.left.property.name === 'exports') {
type = 'moduleExports';
} else if (exp.left.object.name === 'exports' &&
exp.left.property) {
type = 'exports';
}
} else if (node && node.type === 'CallExpression' && node.callee &&
node.callee.type === 'Identifier' &&
node.callee.name === 'require' && node[argPropName] &&
node[argPropName].length === 1 &&
node[argPropName][0].type === 'Literal') {
type = 'require';
}
if (type) {
if (type === 'varExports') {
assignsExports = true;
} else if (type !== 'exports' || !assignsExports) {
if (!uses) {
uses = {};
}
uses[type] = true;
}
}
});
return uses;
};
parse.findRequireDepNames = function(node, deps) {
traverse(node, function(node) {
var arg;
if (node && node.type === 'CallExpression' && node.callee &&
node.callee.type === 'Identifier' &&
node.callee.name === 'require' &&
node[argPropName] && node[argPropName].length === 1) {
arg = node[argPropName][0];
if (arg.type === 'Literal') {
deps.push(arg.value);
}
}
});
};
/**
* Determines if a specific node is a valid require or define/require.def
* call.
* @param {Array} node
* @param {Function} onMatch a function to call when a match is found.
* It is passed the match name, and the config, name, deps possible args.
* The config, name and deps args are not normalized.
*
* @returns {String} a JS source string with the valid require/define call.
* Otherwise null.
*/
parse.parseNode = function(node, onMatch) {
var name, deps, cjsDeps, arg, factory,
args = node && node[argPropName],
callName = parse.hasRequire(node);
if (callName === 'require' || callName === 'requirejs') {
//A plain require/requirejs call
arg = node[argPropName] && node[argPropName][0];
if (arg.type !== 'ArrayExpression') {
if (arg.type === 'ObjectExpression') {
//A config call, try the second arg.
arg = node[argPropName][1];
}
}
deps = getValidDeps(arg);
if (!deps) {
return;
}
return onMatch("require", null, null, deps, node);
} else if (parse.hasDefine(node) && args && args.length) {
name = args[0];
deps = args[1];
factory = args[2];
if (name.type === 'ArrayExpression') {
//No name, adjust args
factory = deps;
deps = name;
name = null;
} else if (name.type === 'FunctionExpression') {
//Just the factory, no name or deps
factory = name;
name = deps = null;
} else if (name.type !== 'Literal') {
//An object literal, just null out
name = deps = factory = null;
}
if (name && name.type === 'Literal' && deps) {
if (deps.type === 'FunctionExpression') {
//deps is the factory
factory = deps;
deps = null;
} else if (deps.type === 'ObjectExpression') {
//deps is object literal, null out
deps = factory = null;
}
}
if (deps && deps.type === 'ArrayExpression') {
deps = getValidDeps(deps);
} else if (factory && factory.type === 'FunctionExpression') {
//If no deps and a factory function, could be a commonjs sugar
//wrapper, scan the function for dependencies.
cjsDeps = parse.getAnonDepsFromNode(factory);
if (cjsDeps.length) {
deps = cjsDeps;
}
} else if (deps || factory) {
//Does not match the shape of an AMD call.
return;
}
//Just save off the name as a string instead of an AST object.
if (name && name.type === 'Literal') {
name = name.value;
}
return onMatch("define", null, name, deps, node);
}
};
/**
* Converts an AST node into a JS source string by extracting
* the node's location from the given contents string. Assumes
* esprima.parse() with ranges was done.
* @param {String} contents
* @param {Object} node
* @returns {String} a JS source string.
*/
parse.nodeToString = function(contents, node) {
var range = node.range;
return contents.substring(range[0], range[1]);
};
/**
* Extracts license comments from JS text.
* @param {String} fileName
* @param {String} contents
* @returns {String} a string of license comments.
*/
parse.getLicenseComments = function(fileName, contents) {
var commentNode, refNode, subNode, value, i, j,
ast = esprima.parse(contents, {
comment: true
}),
result = '',
existsMap = {},
lineEnd = contents.indexOf('\r') === -1 ? '\n' : '\r\n';
if (ast.comments) {
for (i = 0; i < ast.comments.length; i++) {
commentNode = ast.comments[i];
if (commentNode.type === 'Line') {
value = '//' + commentNode.value + lineEnd;
refNode = commentNode;
if (i + 1 >= ast.comments.length) {
value += lineEnd;
} else {
//Look for immediately adjacent single line comments
//since it could from a multiple line comment made out
//of single line comments. Like this comment.
for (j = i + 1; j < ast.comments.length; j++) {
subNode = ast.comments[j];
if (subNode.type === 'Line' &&
subNode.range[0] === refNode.range[1]) {
//Adjacent single line comment. Collect it.
value += '//' + subNode.value + lineEnd;
refNode = subNode;
} else {
//No more single line comment blocks. Break out
//and continue outer looping.
break;
}
}
value += lineEnd;
i = j - 1;
}
} else {
value = '/*' + commentNode.value + '*/' + lineEnd + lineEnd;
}
if (!existsMap[value] && (value.indexOf('license') !== -1 ||
(commentNode.type === 'Block' &&
value.indexOf('/*!') === 0) ||
value.indexOf('opyright') !== -1 ||
value.indexOf('(c)') !== -1)) {
result += value;
existsMap[value] = true;
}
}
}
return result;
};
module.exports = parse;

View File

@@ -0,0 +1,201 @@
"use strict";
// LOGLEVEL-FORK: Summary
//
// The changes here are mostly about working with current versions of lodash.
// Grunt used to include lodash as `grunt.util._` for plugins to use, but has
// since deprecated it can be dangerous -- each plugin should really declare
// a dependency on a given version of lodash in its `package.json` and then
// require lodash directly so that updates to Grunt don't break plugins.
//
// However, this plugin is pretty old and uses lodash throughout, so we've
// just updated the broken callsites. Future Grunt upgrades could potentially
// require other changes to `grunt.util._.<whatever>` calls here.
//
// END LOGLEVEL-FORK
var template = __dirname + '/templates/jasmine-requirejs.html',
requirejs = {
'2.0.0' : __dirname + '/../vendor/require-2.0.0.js',
'2.0.1' : __dirname + '/../vendor/require-2.0.1.js',
'2.0.2' : __dirname + '/../vendor/require-2.0.2.js',
'2.0.3' : __dirname + '/../vendor/require-2.0.3.js',
'2.0.4' : __dirname + '/../vendor/require-2.0.4.js',
'2.0.5' : __dirname + '/../vendor/require-2.0.5.js',
'2.0.6' : __dirname + '/../vendor/require-2.0.6.js',
'2.1.0' : __dirname + '/../vendor/require-2.1.0.js',
'2.1.1' : __dirname + '/../vendor/require-2.1.1.js',
'2.1.2' : __dirname + '/../vendor/require-2.1.2.js',
'2.1.3' : __dirname + '/../vendor/require-2.1.3.js',
'2.1.4' : __dirname + '/../vendor/require-2.1.4.js',
'2.1.5' : __dirname + '/../vendor/require-2.1.5.js',
'2.1.6' : __dirname + '/../vendor/require-2.1.6.js',
'2.1.7' : __dirname + '/../vendor/require-2.1.7.js',
'2.1.8' : __dirname + '/../vendor/require-2.1.8.js',
'2.1.9' : __dirname + '/../vendor/require-2.1.9.js',
'2.1.10' : __dirname + '/../vendor/require-2.1.10.js'
},
path = require('path'),
parse = require('./lib/parse');
function filterGlobPatterns(scripts) {
Object.keys(scripts).forEach(function (group) {
if (Array.isArray(scripts[group])) {
scripts[group] = scripts[group].filter(function(script) {
return script.indexOf('*') === -1;
});
} else {
scripts[group] = [];
}
});
}
function resolvePath(filepath) {
filepath = filepath.trim();
if (filepath.substr(0,1) === '~') {
filepath = process.env.HOME + filepath.substr(1);
}
return path.resolve(filepath);
}
// LOGLEVEL-FORK: copying tempfiles now requires info from the `context` object.
function moveRequireJs(grunt, task, context, versionOrPath) {
var pathToRequireJS,
versionReg = /^(\d\.?)*$/;
if (versionReg.test(versionOrPath)) { // is version
if (versionOrPath in requirejs) {
pathToRequireJS = requirejs[versionOrPath];
} else {
throw new Error('specified requirejs version [' + versionOrPath + '] is not defined');
}
} else { // is path
pathToRequireJS = resolvePath(versionOrPath);
if (!grunt.file.exists(pathToRequireJS)) {
throw new Error('local file path of requirejs [' + versionOrPath + '] was not found');
}
}
task.copyTempFile(pathToRequireJS, path.join(context.temp, 'require.js'));
}
// END LOGLEVEL-FORK
exports.process = function(grunt, task, context) {
var version = context.options.version;
// find the latest version if none given
if (!version) {
version = Object.keys(requirejs).sort().pop();
}
// Remove glob patterns from scripts (see https://github.com/gruntjs/grunt-contrib-jasmine/issues/42)
filterGlobPatterns(context.scripts);
// Extract config from main require config file
if (context.options.requireConfigFile) {
// Remove mainConfigFile from src files
var requireConfigFiles = grunt.util._.flatten([context.options.requireConfigFile]);
var normalizedPaths = grunt.util._.map(requireConfigFiles, function(configFile){
return path.normalize(configFile);
});
context.scripts.src = grunt.util._.reject(context.scripts.src, function (script) {
// LOGLEVEL-FORK: Work with current versions of lodash.
return grunt.util._.includes(normalizedPaths, path.normalize(script));
// END LOGLEVEL-FORK
});
var configFromFiles = {};
grunt.util._.map(requireConfigFiles, function (configFile) {
grunt.util._.merge(configFromFiles, parse.findConfig(grunt.file.read(configFile)).config);
});
context.options.requireConfig = grunt.util._.merge(configFromFiles, context.options.requireConfig);
}
/**
* Find and resolve specified baseUrl.
*/
function getBaseUrl() {
var outDir = path.dirname(path.join(process.cwd(), context.outfile));
var requireBaseUrl = context.options.requireConfig && context.options.requireConfig.baseUrl;
if (requireBaseUrl && grunt.file.isDir(outDir, requireBaseUrl)) {
return requireBaseUrl;
} else {
return outDir;
}
}
var baseUrl = getBaseUrl();
/**
* Retrieves the module URL for a require call relative to the specified Base URL.
*/
function getRelativeModuleUrl(src) {
return path.relative(baseUrl, src).replace(/\.js$/, '');
}
// Remove baseUrl and .js from src files
context.scripts.src = grunt.util._.map(context.scripts.src, getRelativeModuleUrl);
// Prepend loaderPlugins to the appropriate files
if (context.options.loaderPlugin) {
Object.keys(context.options.loaderPlugin).forEach(function(type){
if (context.scripts[type]) {
context.scripts[type].forEach(function(file,i){
context.scripts[type][i] = context.options.loaderPlugin[type] + '!' + file;
});
}
});
}
// LOGLEVEL-FORK: this function now requires context info
moveRequireJs(grunt, task, context, version);
// END LOGLEVEL-FORK
context.serializeRequireConfig = function(requireConfig) {
var funcCounter = 0;
var funcs = {};
function isUnserializable(val) {
var unserializables = [Function, RegExp];
var typeTests = unserializables.map(function(unserializableType) {
return val instanceof unserializableType;
});
return !!~typeTests.indexOf(true);
}
function generateFunctionId() {
return '$template-jasmine-require_' + new Date().getTime() + '_' + (++funcCounter);
}
var jsonString = JSON.stringify(requireConfig, function(key, val) {
var funcId;
if (isUnserializable(val)) {
funcId = generateFunctionId();
funcs[funcId] = val;
return funcId;
}
return val;
}, 2);
Object.keys(funcs).forEach(function(id) {
jsonString = jsonString.replace('"' + id + '"', funcs[id].toString());
});
return jsonString;
};
// update relative path of .grunt folder to the location of spec runner
context.temp = path.relative(path.dirname(context.outfile),
context.temp);
var source = grunt.file.read(template);
// LOGLEVEL-FORK: Work with current versions of lodash.
return grunt.util._.template(source)(context);
// END LOGLEVEL-FORK
};

View File

@@ -0,0 +1,104 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner</title>
<% css.forEach(function(style){ %>
<link rel="stylesheet" type="text/css" href="<%= style %>">
<% }) %>
<% with (scripts) { %>
<% [].concat(vendor).forEach(function(script){ %>
<script src="<%= script %>"></script>
<% }) %>
<% }; %>
<script src="<%= temp ? temp + "/" : temp %>require.js"></script>
<% with (scripts) { %>
<% /* LOGLEVEL-FORK: Include new script types used by grunt-contrib-jasmine v4 */ %>
<% [].concat(polyfills, jasmine, boot, boot2, helpers).forEach(function(script){ %>
<script src="<%= script %>"></script>
<% }) %>
<% /* END LOGLEVEL-FORK */ %>
<% }; %>
<script>
require.onError = function(error) {
var message = error.requireType + ': ';
if (error.requireType === 'scripterror' || error.requireType === 'notloaded' && error.requireModules) {
message += 'Illegal path or script error: ' + '[\'' + error.requireModules.join("', '") + '\']';
} else {
message += error.message;
}
throw Error(message);
};
</script>
<script>
<% if (options.mainRequireConfig) { %>
require.config(<%= serializeRequireConfig(options.mainRequireConfig) %>);
<% } %>
<% var hasCallback = false;
if (options.requireConfig) {
if ('callback' in options.requireConfig) {
/* Inserting launchTest() as the last statement in callback function
to make sure spec is called after all initialization stuffs */
// capture the arguments and body fo callback function
options.requireConfig['callback'].toString().replace(/^function\s+\w*\(([^\)]*)\)\s*\{((?:.|[\n\r])*)}/m, function(match, args, body) {
var being_recreated_function = [];
if (args.length > 0) {
args = args.split(/,\s*/);
being_recreated_function = being_recreated_function.concat(args);
}
// append launchTest() to the end of function body
body += '\nlaunchTest();';
being_recreated_function = being_recreated_function.concat(body);
// recreate an anonymouse function with modified body
// re-assign callback property by just created new function
// (return value dosen't matter)
options.requireConfig['callback'] = Function.apply(this, being_recreated_function);
hasCallback = true;
});
}
%>
require.config(<%= serializeRequireConfig(options.requireConfig) %>);
<% } %>
</script>
<script>
// Delay onLoad function until we are ready
var startTests = window.onload;
window.onload = null;
function launchTest() {
require([
<% scripts.src.forEach(function(script, i){ %>
<% script = script.replace(/\\/g, '/') // replace all backward slashes to forward slash %>
'<%= script %>' <%= i < scripts.src.length-1 ? ',' : '' %>
<% }) %>
],
function(){
require(['<%= [].concat(scripts.specs,scripts.reporters).join("','") %>'], function(){
startTests();
});
}
)
}
</script>
<% if (!hasCallback) { %>
<script>
launchTest();
</script>
<% } %>
</head>
<body>
</body>
</html>