Add in the ability to do versioned releases. Still subject to final deployment plan though, and may change. Just a placeholder for now, based on the old process.
This commit is contained in:
Родитель
570b616b2f
Коммит
8f1904a4b1
20
README.md
20
README.md
|
@ -28,8 +28,26 @@ is used to create bug/ branches that correspond to Bugzilla bug numbers to do fi
|
|||
|
||||
## Build
|
||||
|
||||
TODO
|
||||
To build a new release:
|
||||
|
||||
* git flow release start 0.0.0
|
||||
* bump version number in version.txt
|
||||
* make web
|
||||
* git add web/0.0.0
|
||||
* git commit -a -m "versioned resources for release"
|
||||
* git tag -am "Release 0.0.0" 0.0.0
|
||||
* git flow release finish '0.0.0'
|
||||
* git checkout develop
|
||||
* git push origin develop
|
||||
* git checkout master
|
||||
* git pull origin master
|
||||
* git push origin master
|
||||
|
||||
Be sure to push the new tag when done:
|
||||
|
||||
* git push --tags
|
||||
|
||||
The code in master can now be bundled for deployment as an RPM.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file will optimize files that can be loaded via require.js into one file.
|
||||
* This file needs Rhino to require, and if the Closure compiler is used to minify
|
||||
* files, Java 6 is required.
|
||||
*
|
||||
* Call this file like so:
|
||||
* java -jar path/to/js.jar build.js directory/containing/build.js/ build.js
|
||||
*
|
||||
* General use:
|
||||
*
|
||||
* Create a build.js file that has the build options you want and pass that
|
||||
* build file to this file to do the build. See example.build.js for more information.
|
||||
*/
|
||||
|
||||
/*jslint regexp: false, nomen: false, plusplus: false */
|
||||
/*global load: false, print: false, quit: false, logger: false,
|
||||
fileUtil: false, lang: false, pragma: false, optimize: false, build: false,
|
||||
java: false, Packages: false */
|
||||
|
||||
"use strict";
|
||||
var require;
|
||||
|
||||
(function (args) {
|
||||
var requireBuildPath = args[0];
|
||||
if (requireBuildPath.charAt(requireBuildPath.length - 1) !== "/") {
|
||||
requireBuildPath += "/";
|
||||
}
|
||||
load(requireBuildPath + "jslib/build.js");
|
||||
build(args);
|
||||
|
||||
}(Array.prototype.slice.call(arguments)));
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
MYDIR=`cd \`dirname "$0"\`; pwd`
|
||||
java -classpath $MYDIR/lib/rhino/js.jar:$MYDIR/lib/closure/compiler.jar org.mozilla.javascript.tools.shell.Main $MYDIR/build.js $MYDIR "$@"
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
MYDIR=`cd \`dirname "$0"\`; pwd`
|
||||
java -classpath $MYDIR/lib/rhino/js.jar:$MYDIR/lib/closure/compiler.jar org.mozilla.javascript.tools.debugger.Main $MYDIR/build.js $MYDIR "$@"
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* This is an example build file that demonstrates how to use the build system for
|
||||
* require.js.
|
||||
*
|
||||
* THIS BUILD FILE WILL NOT WORK. It is referencing paths that probably
|
||||
* do not exist on your machine. Just use it as a guide.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
({
|
||||
//The top level directory that contains your app. If this option is used
|
||||
//then it assumed your scripts are in a subdirectory under this path.
|
||||
//This option is not required. If it is not specified, then baseUrl
|
||||
//below is the anchor point for finding things. If this option is specified,
|
||||
//then all the files from the app directory will be copied to the dir:
|
||||
//output area, and baseUrl will assume to be a relative path under
|
||||
//this directory.
|
||||
appDir: "some/path/",
|
||||
|
||||
//By default, all modules are located relative to this path. If baseUrl
|
||||
//is not explicitly set, then all modules are loaded relative to
|
||||
//the directory that holds the build file.
|
||||
baseUrl: "./",
|
||||
|
||||
//Set paths for modules. If relative paths, set relative to baseUrl above.
|
||||
paths: {
|
||||
"foo.bar": "../scripts/foo/bar",
|
||||
"baz": "../another/path/baz"
|
||||
},
|
||||
|
||||
//The directory path to save the output. If not specified, then
|
||||
//the path will default to be a directory called "build" as a sibling
|
||||
//to the build file. All relative paths are relative to the build file.
|
||||
dir: "../some/path",
|
||||
|
||||
//Used to inline i18n resources into the built file. If no locale
|
||||
//is specified, i18n resources will not be inlined. Only one locale
|
||||
//can be inlined for a build. Root bundles referenced by a build layer
|
||||
//will be included in a build layer regardless of locale being set.
|
||||
locale: "en-us",
|
||||
|
||||
//How to optimize all the JS files in the build output directory.
|
||||
//Right now only the following values
|
||||
//are supported (default is to not do any optimization):
|
||||
//- "closure": uses Google's Closure Compiler in simple optimization
|
||||
//mode to minify the code.
|
||||
//- "closure.keepLines": Same as closure option, but keeps line returns
|
||||
//in the minified files.
|
||||
//- "none": no minification will be done.
|
||||
optimize: "closure",
|
||||
|
||||
//Allow CSS optimizations. Allowed values:
|
||||
//- "standard": @import inlining, comment removal and line returns.
|
||||
//Removing line returns may have problems in IE, depending on the type
|
||||
//of CSS.
|
||||
//- "standard.keepLines": like "standard" but keeps line returns.
|
||||
//- "none": skip CSS optimizations.
|
||||
optimizeCss: "standard.keepLines",
|
||||
|
||||
//If optimizeCss is in use, a list of of files to ignore for the @import
|
||||
//inlining. The value of this option should be a comma separated list
|
||||
//of CSS file names to ignore. The file names should match whatever
|
||||
//strings are used in the @import calls.
|
||||
cssImportIgnore: null,
|
||||
|
||||
//Inlines the text for any text! dependencies, to avoid the separate
|
||||
//async XMLHttpRequest calls to load those dependencies.
|
||||
inlineText: true,
|
||||
|
||||
//Allow "use strict"; be included in the RequireJS files.
|
||||
//Default is false because there are not many browsers that can properly
|
||||
//process and give errors on code for ES5 strict mode,
|
||||
//and there is a lot of legacy code that will not work in strict mode.
|
||||
useStrict: false,
|
||||
|
||||
//Specify build pragmas. If the source files contain comments like so:
|
||||
//>>excludeStart("fooExclude", pragmas.fooExclude);
|
||||
//>>excludeEnd("fooExclude");
|
||||
//Then the comments that start with //>> are the build pragmas.
|
||||
//excludeStart/excludeEnd and includeStart/includeEnd work, and the
|
||||
//the pragmas value to the includeStart or excludeStart lines
|
||||
//is evaluated to see if the code between the Start and End pragma
|
||||
//lines should be included or excluded.
|
||||
pragmas: {
|
||||
//Indicates require will be included with jquery.
|
||||
jquery: true
|
||||
},
|
||||
|
||||
//Skip processing for pragmas.
|
||||
skipPragmas: false,
|
||||
|
||||
//If skipModuleInsertion is false, then files that do not use require.def
|
||||
//to define modules will get a require.def() placeholder inserted for them.
|
||||
//Also, require.pause/resume calls will be inserted.
|
||||
//Set it to true to avoid this. This is useful if you are building code that
|
||||
//does not use require() in the built project or in the JS files, but you
|
||||
//still want to use the optimization tool from RequireJS to concatenate modules
|
||||
//together.
|
||||
skipModuleInsertion: false,
|
||||
|
||||
//List the modules that will be optimized. All their immediate and deep
|
||||
//dependencies will be included in the module's file when the build is
|
||||
//done. If that module or any of its dependencies includes i18n bundles,
|
||||
//only the root bundles will be included unless the locale: section is set above.
|
||||
modules: [
|
||||
//Just specifying a module name means that module will be converted into
|
||||
//a built file that contains all of its dependencies. If that module or any
|
||||
//of its dependencies includes i18n bundles, they may not be included in the
|
||||
//built file unless the locale: section is set above.
|
||||
{
|
||||
name: "foo/bar/bop",
|
||||
|
||||
//Should the contents of require.js be included in the optimized module.
|
||||
//Defaults to false.
|
||||
includeRequire: true,
|
||||
|
||||
//For build profiles that contain more than one modules entry,
|
||||
//allow overrides for the properties that set for the whole build,
|
||||
//for example a different set of pragmas for this module.
|
||||
//The override's value is an object that can
|
||||
//contain any of the other build options in this file.
|
||||
override: {
|
||||
pragmas: {
|
||||
fooExclude: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//This module entry combines all the dependencies of foo/bar/bop and foo/bar/bee
|
||||
//and any of their dependencies into one file.
|
||||
{
|
||||
name: "foo/bar/bop",
|
||||
include: ["foo/bar/bee"]
|
||||
},
|
||||
|
||||
//This module entry combines all the dependencies of foo/bar/bip into one file,
|
||||
//but excludes foo/bar/bop and its dependencies from the built file. If you want
|
||||
//to exclude a module that is also another module being optimized, it is more
|
||||
//efficient if you define that module optimization entry before using it
|
||||
//in an exclude array.
|
||||
{
|
||||
name: "foo/bar/bip",
|
||||
exclude: [
|
||||
"foo/bar/bop"
|
||||
]
|
||||
},
|
||||
|
||||
//This module entry shows how to specify a specific module be excluded
|
||||
//from the built module file. excludeShallow means just exclude that
|
||||
//specific module, but if that module has nested dependencies that are
|
||||
//part of the built file, keep them in there. This is useful during
|
||||
//development when you want to have a fast bundled set of modules, but
|
||||
//just develop/debug one or two modules at a time.
|
||||
{
|
||||
name: "foo/bar/bin",
|
||||
excludeShallow: [
|
||||
"foo/bar/bot"
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
|
@ -0,0 +1,657 @@
|
|||
/**
|
||||
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*jslint regexp: false, plusplus: false, nomen: false */
|
||||
/*global java: false, lang: false, fileUtil: false, optimize: false,
|
||||
load: false, quit: false, print: false, logger: false, require: false,
|
||||
pragma: false, parse: false */
|
||||
|
||||
"use strict";
|
||||
|
||||
var build, buildBaseConfig;
|
||||
(function () {
|
||||
buildBaseConfig = {
|
||||
requireBuildPath: "../",
|
||||
appDir: "",
|
||||
pragmas: {},
|
||||
paths: {},
|
||||
optimize: "closure",
|
||||
optimizeCss: "standard.keepLines",
|
||||
inlineText: true,
|
||||
isBuild: true
|
||||
};
|
||||
|
||||
build = function (args) {
|
||||
var requireBuildPath, buildFile, baseUrlFile, buildPaths, deps, fileName, fileNames,
|
||||
prop, props, paths, path, i, fileContents, buildFileContents = "",
|
||||
doClosure, requireContents, pluginBuildFileContents,
|
||||
baseConfig, override, builtRequirePath, cmdConfig, config,
|
||||
modules, module, moduleName, builtModule, srcPath, buildContext;
|
||||
|
||||
if (!args || args.length < 2) {
|
||||
print("java -jar path/to/js.jar build.js directory/containing/build.js/ build.js\n" +
|
||||
"where build.js is the name of the build file (see example.build.js for hints on how to make a build file.");
|
||||
quit();
|
||||
}
|
||||
|
||||
//First argument to this script should be the directory on where to find this script.
|
||||
//This path should end in a slash.
|
||||
requireBuildPath = args[0];
|
||||
if (requireBuildPath.charAt(requireBuildPath.length - 1) !== "/") {
|
||||
requireBuildPath += "/";
|
||||
}
|
||||
|
||||
["lang", "logger", "fileUtil", "parse", "optimize", "pragma", "build"].forEach(function (path) {
|
||||
load(requireBuildPath + "jslib/" + path + ".js");
|
||||
});
|
||||
|
||||
//Next args can include a build file path as well as other build args.
|
||||
//build file path comes first. If it does not contain an = then it is
|
||||
//a build file path. Otherwise, just all build args.
|
||||
if (args[1].indexOf("=") === -1) {
|
||||
buildFile = args[1];
|
||||
args.splice(0, 2);
|
||||
} else {
|
||||
args.splice(0, 1);
|
||||
}
|
||||
|
||||
//Remaining args are options to the build
|
||||
cmdConfig = build.convertArrayToObject(args);
|
||||
cmdConfig.buildFile = buildFile;
|
||||
cmdConfig.requireBuildPath = requireBuildPath;
|
||||
|
||||
config = build.createConfig(cmdConfig);
|
||||
paths = config.paths;
|
||||
|
||||
//Load require.js with the build patches.
|
||||
load(config.requireUrl);
|
||||
load(requireBuildPath + "jslib/requirePatch.js");
|
||||
|
||||
if (!config.out && !config.cssIn) {
|
||||
//This is not just a one-off file build but a full build profile, with
|
||||
//lots of files to process.
|
||||
|
||||
//First copy all the baseUrl content
|
||||
fileUtil.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
|
||||
|
||||
//Adjust baseUrl if config.appDir is in play, and set up build output paths.
|
||||
buildPaths = {};
|
||||
if (config.appDir) {
|
||||
//All the paths should be inside the appDir
|
||||
buildPaths = paths;
|
||||
} else {
|
||||
//If no appDir, then make sure to copy the other paths to this directory.
|
||||
for (prop in paths) {
|
||||
if (paths.hasOwnProperty(prop)) {
|
||||
//Set up build path for each path prefix.
|
||||
buildPaths[prop] = prop.replace(/\./g, "/");
|
||||
|
||||
//Make sure source path is fully formed with baseUrl,
|
||||
//if it is a relative URL.
|
||||
srcPath = paths[prop];
|
||||
if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) {
|
||||
srcPath = config.baseUrl + srcPath;
|
||||
}
|
||||
|
||||
//Copy files to build area. Copy all files (the /\w/ regexp)
|
||||
fileUtil.copyDir(srcPath, config.dirBaseUrl + buildPaths[prop], /\w/, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Figure out source file location for each module layer. Do this by seeding require
|
||||
//with source area configuration. This is needed so that later the module layers
|
||||
//can be manually copied over to the source area, since the build may be
|
||||
//require multiple times and the above copyDir call only copies newer files.
|
||||
require({
|
||||
baseUrl: config.baseUrl,
|
||||
paths: paths
|
||||
});
|
||||
buildContext = require.s.contexts._;
|
||||
modules = config.modules;
|
||||
|
||||
if (modules) {
|
||||
modules.forEach(function (module) {
|
||||
if (module.name) {
|
||||
module._sourcePath = buildContext.nameToUrl(module.name);
|
||||
//If the module does not exist, and this is not a "new" module layer,
|
||||
//as indicated by a true "create" property on the module, then throw an error.
|
||||
if (!(new java.io.File(module._sourcePath)).exists() && !module.create) {
|
||||
throw new Error("ERROR: module path does not exist: " +
|
||||
module._sourcePath + " for module named: " + module.name +
|
||||
". Path is relative to: " + (new java.io.File('.')).getAbsolutePath());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (config.out) {
|
||||
//Just set up the _buildPath for the module layer.
|
||||
require(config);
|
||||
if (!config.cssIn) {
|
||||
config.modules[0]._buildPath = config.out;
|
||||
}
|
||||
} else if (!config.cssIn) {
|
||||
//Now set up the config for require to use the build area, and calculate the
|
||||
//build file locations. Pass along any config info too.
|
||||
baseConfig = {
|
||||
baseUrl: config.dirBaseUrl,
|
||||
paths: buildPaths
|
||||
};
|
||||
lang.mixin(baseConfig, config);
|
||||
require(baseConfig);
|
||||
|
||||
if (modules) {
|
||||
modules.forEach(function (module) {
|
||||
if (module.name) {
|
||||
module._buildPath = buildContext.nameToUrl(module.name, null);
|
||||
if (!module.create) {
|
||||
fileUtil.copyFile(module._sourcePath, module._buildPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (modules) {
|
||||
//For each module layer, call require to calculate dependencies.
|
||||
modules.forEach(function (module) {
|
||||
module.layer = build.traceDependencies(module, config);
|
||||
});
|
||||
|
||||
//Now build up shadow layers for anything that should be excluded.
|
||||
//Do this after tracing dependencies for each module, in case one
|
||||
//of those modules end up being one of the excluded values.
|
||||
modules.forEach(function (module) {
|
||||
if (module.exclude) {
|
||||
module.excludeLayers = [];
|
||||
module.exclude.forEach(function (exclude, i) {
|
||||
//See if it is already in the list of modules.
|
||||
//If not trace dependencies for it.
|
||||
module.excludeLayers[i] = build.findBuildModule(exclude, modules) ||
|
||||
{layer: build.traceDependencies({name: exclude}, config)};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
modules.forEach(function (module) {
|
||||
if (module.exclude) {
|
||||
//module.exclude is an array of module names. For each one,
|
||||
//get the nested dependencies for it via a matching entry
|
||||
//in the module.excludeLayers array.
|
||||
module.exclude.forEach(function (excludeModule, i) {
|
||||
var excludeLayer = module.excludeLayers[i].layer, map = excludeLayer.buildPathMap, prop;
|
||||
for (prop in map) {
|
||||
if (map.hasOwnProperty(prop)) {
|
||||
build.removeModulePath(prop, map[prop], module.layer);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (module.excludeShallow) {
|
||||
//module.excludeShallow is an array of module names.
|
||||
//shallow exclusions are just that module itself, and not
|
||||
//its nested dependencies.
|
||||
module.excludeShallow.forEach(function (excludeShallowModule) {
|
||||
var path = module.layer.buildPathMap[excludeShallowModule];
|
||||
if (path) {
|
||||
build.removeModulePath(excludeShallowModule, path, module.layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//Flatten them and collect the build output for each module.
|
||||
builtModule = build.flattenModule(module, module.layer, config);
|
||||
fileUtil.saveUtf8File(module._buildPath, builtModule.text);
|
||||
buildFileContents += builtModule.buildText;
|
||||
});
|
||||
}
|
||||
|
||||
//Do other optimizations.
|
||||
if (config.out && !config.cssIn) {
|
||||
//Just need to worry about one JS file.
|
||||
fileName = config.modules[0]._buildPath;
|
||||
optimize.jsFile(fileName, fileName, config);
|
||||
} else if (!config.cssIn) {
|
||||
//Normal optimizations across modules.
|
||||
|
||||
//JS optimizations.
|
||||
fileNames = fileUtil.getFilteredFileList(config.dir, /\.js$/, true);
|
||||
for (i = 0; (fileName = fileNames[i]); i++) {
|
||||
optimize.jsFile(fileName, fileName, config);
|
||||
}
|
||||
|
||||
//CSS optimizations
|
||||
if (config.optimizeCss && config.optimizeCss !== "none") {
|
||||
optimize.css(config.dir, config);
|
||||
}
|
||||
|
||||
//All module layers are done, write out the build.txt file.
|
||||
fileUtil.saveUtf8File(config.dir + "build.txt", buildFileContents);
|
||||
}
|
||||
|
||||
//If just have one CSS file to optimize, do that here.
|
||||
if (config.cssIn) {
|
||||
optimize.cssFile(config.cssIn, config.out, config);
|
||||
}
|
||||
|
||||
//Print out what was built into which layers.
|
||||
if (buildFileContents) {
|
||||
print(buildFileContents);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an array that has String members of "name=value"
|
||||
* into an object, where the properties on the object are the names in the array.
|
||||
* Also converts the strings "true" and "false" to booleans for the values.
|
||||
* member name/value pairs, and converts some comma-separated lists into
|
||||
* arrays.
|
||||
* @param {Array} ary
|
||||
*/
|
||||
build.convertArrayToObject = function (ary) {
|
||||
var result = {}, i, separatorIndex, prop, value,
|
||||
needArray = {
|
||||
"include": true,
|
||||
"exclude": true,
|
||||
"excludeShallow": true
|
||||
};
|
||||
|
||||
for (i = 0; i < ary.length; i++) {
|
||||
separatorIndex = ary[i].indexOf("=");
|
||||
if (separatorIndex === -1) {
|
||||
throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value";
|
||||
}
|
||||
|
||||
value = ary[i].substring(separatorIndex + 1, ary[i].length);
|
||||
if (value === "true") {
|
||||
value = true;
|
||||
} else if (value === "false") {
|
||||
value = false;
|
||||
}
|
||||
|
||||
prop = ary[i].substring(0, separatorIndex);
|
||||
|
||||
//Convert to array if necessary
|
||||
if (needArray[prop]) {
|
||||
value = value.split(",");
|
||||
}
|
||||
|
||||
result[prop] = value;
|
||||
}
|
||||
return result; //Object
|
||||
};
|
||||
|
||||
build.makeAbsPath = function (path, absFilePath) {
|
||||
//Add abspath if necessary. If path starts with a slash or has a colon,
|
||||
//then already is an abolute path.
|
||||
if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) {
|
||||
path = absFilePath +
|
||||
(absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') +
|
||||
path;
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a config object for an optimization build.
|
||||
* It will also read the build profile if it is available, to create
|
||||
* the configuration.
|
||||
*
|
||||
* @param {Object} cfg config options that take priority
|
||||
* over defaults and ones in the build file. These options could
|
||||
* be from a command line, for instance.
|
||||
*
|
||||
* @param {Object} the created config object.
|
||||
*/
|
||||
build.createConfig = function (cfg) {
|
||||
/*jslint evil: true */
|
||||
var config = {}, baseUrl, buildFileContents, buildFileConfig,
|
||||
paths, props, i, prop, buildFile, absFilePath, originalBaseUrl;
|
||||
|
||||
lang.mixin(config, buildBaseConfig);
|
||||
lang.mixin(config, cfg, true);
|
||||
|
||||
//Normalize build directory location, and set up path to require.js
|
||||
if (config.requireBuildPath.charAt(config.requireBuildPath.length - 1) !== "/") {
|
||||
config.requireBuildPath += "/";
|
||||
//Also adjust the override config params, since it
|
||||
//may be re-applied later after reading the build file.
|
||||
if (cfg.requireBuildPath) {
|
||||
cfg.requireBuildPath = config.requireBuildPath;
|
||||
}
|
||||
}
|
||||
config.requireUrl = fileUtil.absPath(java.io.File(cfg.requireBuildPath + "../require.js"));
|
||||
|
||||
if (config.buildFile) {
|
||||
//A build file exists, load it to get more config.
|
||||
buildFile = new java.io.File(config.buildFile).getAbsoluteFile();
|
||||
|
||||
//Find the build file, and make sure it exists, if this is a build
|
||||
//that has a build profile, and not just command line args with an in=path
|
||||
if (!buildFile.exists()) {
|
||||
throw new Error("ERROR: build file does not exist: " + buildFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
absFilePath = config.baseUrl = fileUtil.absPath(buildFile.getParentFile()).replace(lang.backSlashRegExp, '/');
|
||||
config.dir = config.baseUrl + "/build/";
|
||||
|
||||
//Load build file options.
|
||||
buildFileContents = fileUtil.readFile(buildFile);
|
||||
buildFileConfig = eval("(" + buildFileContents + ")");
|
||||
lang.mixin(config, buildFileConfig, true);
|
||||
|
||||
//Re-apply the override config values, things like command line
|
||||
//args should take precedence over build file values.
|
||||
lang.mixin(config, cfg, true);
|
||||
} else {
|
||||
if (!config.out && !config.cssIn) {
|
||||
throw new Error("ERROR: 'out' or 'cssIn' option missing.");
|
||||
}
|
||||
if (!config.out) {
|
||||
throw new Error("ERROR: 'out' option missing.");
|
||||
} else {
|
||||
config.out = config.out.replace(lang.backSlashRegExp, "/");
|
||||
}
|
||||
|
||||
if (!config.cssIn && !cfg.baseUrl) {
|
||||
throw new Error("ERROR: 'baseUrl' option missing.");
|
||||
}
|
||||
|
||||
//In this scenario, the absFile path is current directory
|
||||
absFilePath = (String((new java.io.File('.')).getAbsolutePath())).replace(lang.backSlashRegExp, '/');
|
||||
}
|
||||
|
||||
if (config.out && !config.cssIn) {
|
||||
//Just one file to optimize.
|
||||
|
||||
//Set up dummy module layer to build.
|
||||
config.modules = [
|
||||
{
|
||||
name: config.name,
|
||||
out: config.out,
|
||||
include: config.include,
|
||||
exclude: config.exclude,
|
||||
excludeShallow: config.excludeShallow
|
||||
}
|
||||
];
|
||||
|
||||
if (config.includeRequire) {
|
||||
config.modules[0].includeRequire = true;
|
||||
}
|
||||
|
||||
//Does not have a build file, so set up some defaults.
|
||||
//Optimizing CSS should not be allowed, unless explicitly
|
||||
//asked for on command line. In that case the only task is
|
||||
//to optimize a CSS file.
|
||||
if (!cfg.optimizeCss) {
|
||||
config.optimizeCss = "none";
|
||||
}
|
||||
}
|
||||
|
||||
//Adjust the path properties as appropriate.
|
||||
//First make sure build paths use front slashes and end in a slash,
|
||||
//and make sure they are aboslute paths.
|
||||
props = ["appDir", "dir", "baseUrl"];
|
||||
for (i = 0; (prop = props[i]); i++) {
|
||||
if (config[prop]) {
|
||||
config[prop] = config[prop].replace(lang.backSlashRegExp, "/");
|
||||
if (config[prop].charAt(config[prop].length - 1) !== "/") {
|
||||
config[prop] += "/";
|
||||
}
|
||||
|
||||
//Add abspath if necessary.
|
||||
if (prop === "baseUrl") {
|
||||
originalBaseUrl = config.baseUrl;
|
||||
if (config.appDir) {
|
||||
//If baseUrl with an appDir, the baseUrl is relative to
|
||||
//the appDir, *not* the absFilePath. appDir and dir are
|
||||
//made absolute before baseUrl, so this will work.
|
||||
config.baseUrl = build.makeAbsPath(originalBaseUrl, config.appDir);
|
||||
//Set up dir output baseUrl.
|
||||
config.dirBaseUrl = build.makeAbsPath(originalBaseUrl, config.dir);
|
||||
} else {
|
||||
//The dir output baseUrl is same as regular baseUrl, both
|
||||
//relative to the absFilePath.
|
||||
config.baseUrl = build.makeAbsPath(config[prop], absFilePath);
|
||||
config.dirBaseUrl = config.dir;
|
||||
}
|
||||
} else {
|
||||
config[prop] = build.makeAbsPath(config[prop], absFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Make sure some other paths are absolute.
|
||||
props = ["out", "cssIn"];
|
||||
for (i = 0; (prop = props[i]); i++) {
|
||||
if (config[prop]) {
|
||||
config[prop] = build.makeAbsPath(config[prop], absFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
//Make sure paths has a setting for require, so support plugins
|
||||
//can be loaded for the build.
|
||||
paths = config.paths;
|
||||
if (!paths.require) {
|
||||
paths.require = config.requireUrl.substring(0, config.requireUrl.lastIndexOf("/")) + "/require";
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
/**
|
||||
* finds the module being built/optimized with the given moduleName,
|
||||
* or returns null.
|
||||
* @param {String} moduleName
|
||||
* @param {Array} modules
|
||||
* @returns {Object} the module object from the build profile, or null.
|
||||
*/
|
||||
build.findBuildModule = function (moduleName, modules) {
|
||||
var i, module;
|
||||
for (i = 0; (module = modules[i]); i++) {
|
||||
if (module.name === moduleName) {
|
||||
return module;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a module name and path from a layer, if it is supposed to be
|
||||
* excluded from the layer.
|
||||
* @param {String} moduleName the name of the module
|
||||
* @param {String} path the file path for the module
|
||||
* @param {Object} layer the layer to remove the module/path from
|
||||
*/
|
||||
build.removeModulePath = function (module, path, layer) {
|
||||
var index = layer.buildFilePaths.indexOf(path);
|
||||
if (index !== -1) {
|
||||
layer.buildFilePaths.splice(index, 1);
|
||||
}
|
||||
|
||||
//Take it out of the specified modules. Specified modules are mostly
|
||||
//used to find require modifiers.
|
||||
delete layer.specified[module];
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the module build config object to trace the dependencies for the
|
||||
* given module.
|
||||
*
|
||||
* @param {Object} module the module object from the build config info.
|
||||
* @param {Object} the build config object.
|
||||
*
|
||||
* @returns {Object} layer information about what paths and modules should
|
||||
* be in the flattened module.
|
||||
*/
|
||||
build.traceDependencies = function (module, config) {
|
||||
var include, override, url, layer, prop,
|
||||
context = require.s.contexts._,
|
||||
baseConfig = context.config;
|
||||
|
||||
//Reset some state set up in requirePatch.js, and clean up require's
|
||||
//current context.
|
||||
require._buildReset();
|
||||
|
||||
//Put back basic config
|
||||
require(baseConfig);
|
||||
|
||||
logger.trace("\nTracing dependencies for: " + (module.name || module.out));
|
||||
include = module.name && !module.create ? [module.name] : [];
|
||||
if (module.include) {
|
||||
include = include.concat(module.include);
|
||||
}
|
||||
|
||||
//If there are overrides to basic config, set that up now.;
|
||||
if (module.override) {
|
||||
override = lang.delegate(baseConfig);
|
||||
lang.mixin(override, module.override, true);
|
||||
require(override);
|
||||
}
|
||||
|
||||
//Figure out module layer dependencies by calling require to do the work.
|
||||
require(include);
|
||||
|
||||
//Pull out the layer dependencies. Do not use the old context
|
||||
//but grab the latest value from inside require() since it was reset
|
||||
//since our last context reference.
|
||||
layer = require._layer;
|
||||
layer.specified = context.specified;
|
||||
|
||||
//Reset config
|
||||
if (module.override) {
|
||||
require(baseConfig);
|
||||
}
|
||||
|
||||
return layer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the module build config object to create an flattened version
|
||||
* of the module, with deep dependencies included.
|
||||
*
|
||||
* @param {Object} module the module object from the build config info.
|
||||
*
|
||||
* @param {Object} layer the layer object returned from build.traceDependencies.
|
||||
*
|
||||
* @param {Object} the build config object.
|
||||
*
|
||||
* @returns {Object} with two properties: "text", the text of the flattened
|
||||
* module, and "buildText", a string of text representing which files were
|
||||
* included in the flattened module text.
|
||||
*/
|
||||
build.flattenModule = function (module, layer, config) {
|
||||
var buildFileContents = "", requireContents = "",
|
||||
context = require.s.contexts._,
|
||||
//This regexp is not bullet-proof, and it has one optional part to
|
||||
//avoid issues with some Dojo transition modules that use a
|
||||
//define(\n//begin v1.x content
|
||||
//for a comment.
|
||||
anonDefRegExp = /(require\s*\.\s*def|define)\s*\(\s*(\/\/[^\n\r]*[\r\n])?(\[|f|\{)/,
|
||||
prop, path, reqIndex, fileContents, currContents,
|
||||
i, moduleName, specified, deps, includeRequire,
|
||||
parts, builder;
|
||||
|
||||
//Use override settings, particularly for pragmas
|
||||
if (module.override) {
|
||||
config = lang.delegate(config);
|
||||
lang.mixin(config, module.override, true);
|
||||
}
|
||||
|
||||
//Start build output for the module.
|
||||
buildFileContents += "\n" +
|
||||
(config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath) +
|
||||
"\n----------------\n";
|
||||
|
||||
//If the file wants require.js added to the module, add it now
|
||||
requireContents = "";
|
||||
includeRequire = false;
|
||||
if ("includeRequire" in module) {
|
||||
includeRequire = module.includeRequire;
|
||||
}
|
||||
if (includeRequire) {
|
||||
requireContents = pragma.process(config.requireUrl, fileUtil.readFile(config.requireUrl), config);
|
||||
buildFileContents += "require.js\n";
|
||||
}
|
||||
|
||||
//If there was an existing file with require in it, hoist to the top.
|
||||
if (!includeRequire && layer.existingRequireUrl) {
|
||||
reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
|
||||
if (reqIndex !== -1) {
|
||||
layer.buildFilePaths.splice(reqIndex, 1);
|
||||
layer.buildFilePaths.unshift(layer.existingRequireUrl);
|
||||
}
|
||||
}
|
||||
|
||||
//Write the built module to disk, and build up the build output.
|
||||
fileContents = "";
|
||||
for (i = 0; (path = layer.buildFilePaths[i]); i++) {
|
||||
moduleName = layer.buildFileToModule[path];
|
||||
|
||||
//Figure out if the module is a result of a build plugin, and if so,
|
||||
//then delegate to that plugin.
|
||||
parts = context.makeModuleMap(moduleName);
|
||||
builder = parts.prefix && require.pluginBuilders[parts.prefix];
|
||||
if (builder) {
|
||||
if (builder.write) {
|
||||
builder.write(parts.prefix, parts.name, function (input) {
|
||||
fileContents += input;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
//Add the contents but remove any pragmas.
|
||||
currContents = pragma.process(path, fileUtil.readFile(path), config);
|
||||
|
||||
//If anonymous module, insert the module name.
|
||||
currContents = currContents.replace(anonDefRegExp, function (match, callName, possibleComment, suffix) {
|
||||
layer.modulesWithNames[moduleName] = true;
|
||||
|
||||
//Look for CommonJS require calls inside the function if this is
|
||||
//an anonymous define/require.def call that just has a function registered.
|
||||
deps = null;
|
||||
if (suffix.indexOf('f') !== -1) {
|
||||
deps = parse.getAnonDeps(path, currContents);
|
||||
|
||||
if (deps.length) {
|
||||
deps = deps.map(function (dep) {
|
||||
return "'" + dep + "'";
|
||||
});
|
||||
} else {
|
||||
deps = null;
|
||||
}
|
||||
}
|
||||
|
||||
return "define('" + moduleName + "'," +
|
||||
(deps ? ('[' + deps.toString() + '],') : '') +
|
||||
suffix;
|
||||
});
|
||||
|
||||
fileContents += currContents;
|
||||
}
|
||||
|
||||
buildFileContents += path.replace(config.dir, "") + "\n";
|
||||
//Some files may not have declared a require module, and if so,
|
||||
//put in a placeholder call so the require does not try to load them
|
||||
//after the module is processed.
|
||||
//If we have a name, but no defined module, then add in the placeholder.
|
||||
if (moduleName && !layer.modulesWithNames[moduleName] && !config.skipModuleInsertion) {
|
||||
fileContents += 'define("' + moduleName + '", function(){});\n';
|
||||
}
|
||||
}
|
||||
|
||||
//Add the require file contents to the head of the file.
|
||||
fileContents = (requireContents ? requireContents + "\n" : "") +
|
||||
fileContents;
|
||||
|
||||
return {
|
||||
text: fileContents,
|
||||
buildText: buildFileContents
|
||||
};
|
||||
};
|
||||
}());
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*jslint */
|
||||
/*global Packages: false */
|
||||
"use strict";
|
||||
|
||||
var commandLine = {};
|
||||
(function () {
|
||||
var runtime = Packages.java.lang.Runtime.getRuntime();
|
||||
|
||||
/**
|
||||
* Executes a command on the command line. May not work right in
|
||||
* Windows environments, except maybe via something like cygwin.
|
||||
* @param {String} command the command to run on the command line.
|
||||
*/
|
||||
commandLine.exec = function (command) {
|
||||
var process = runtime.exec(["/bin/sh", "-c", command]);
|
||||
process.waitFor();
|
||||
};
|
||||
}());
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*jslint plusplus: false, regexp: false */
|
||||
/*global Packages: false, logger: false, fileUtil: false */
|
||||
"use strict";
|
||||
|
||||
var commonJs = {
|
||||
depRegExp: /require\s*\(\s*["']([\w-_\.\/]+)["']\s*\)/g,
|
||||
|
||||
//Set this to false in non-rhino environments. If rhino, then it uses
|
||||
//rhino's decompiler to remove comments before looking for require() calls,
|
||||
//otherwise, it will use a crude regexp approach to remove comments. The
|
||||
//rhino way is more robust, but he regexp is more portable across environments.
|
||||
useRhino: true,
|
||||
|
||||
//Set to false if you do not want this file to log. Useful in environments
|
||||
//like node where you want the work to happen without noise.
|
||||
useLog: true,
|
||||
|
||||
//Set to true to see full converted module contents logged to output.
|
||||
logConverted: false,
|
||||
|
||||
convertDir: function (commonJsPath, savePath, prefix) {
|
||||
//Normalize prefix
|
||||
prefix = prefix ? prefix + "/" : "";
|
||||
|
||||
var fileList, i,
|
||||
jsFileRegExp = /\.js$/,
|
||||
fileName, moduleName, convertedFileName, fileContents;
|
||||
|
||||
//Get list of files to convert.
|
||||
fileList = fileUtil.getFilteredFileList(commonJsPath, /\w/, true);
|
||||
|
||||
//Normalize on front slashes and make sure the paths do not end in a slash.
|
||||
commonJsPath = commonJsPath.replace(/\\/g, "/");
|
||||
savePath = savePath.replace(/\\/g, "/");
|
||||
if (commonJsPath.charAt(commonJsPath.length - 1) === "/") {
|
||||
commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1);
|
||||
}
|
||||
if (savePath.charAt(savePath.length - 1) === "/") {
|
||||
savePath = savePath.substring(0, savePath.length - 1);
|
||||
}
|
||||
|
||||
//Cycle through all the JS files and convert them.
|
||||
if (!fileList || !fileList.length) {
|
||||
if (commonJsPath === "convert") {
|
||||
//A request just to convert one file.
|
||||
logger.trace('\n\n' + commonJs.convert(savePath, fileUtil.readFile(savePath)));
|
||||
} else {
|
||||
logger.error("No files to convert in directory: " + commonJsPath);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; (fileName = fileList[i]); i++) {
|
||||
convertedFileName = fileName.replace(commonJsPath, savePath);
|
||||
|
||||
//Handle JS files.
|
||||
if (jsFileRegExp.test(fileName)) {
|
||||
moduleName = fileName.replace(commonJsPath + "/", "").replace(/\.js$/, "");
|
||||
|
||||
fileContents = fileUtil.readFile(fileName);
|
||||
fileContents = commonJs.convert(prefix + moduleName, fileName, fileContents);
|
||||
fileUtil.saveUtf8File(convertedFileName, fileContents);
|
||||
} else {
|
||||
//Just copy the file over.
|
||||
fileUtil.copyFile(fileName, convertedFileName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the comments from a string. Uses a more robust method if
|
||||
* Rhino is available, otherwise a cruder regexp is used. If the regexp
|
||||
* is used, then the contents may not be executable, but hopefully good
|
||||
* enough to use to find require() calls.
|
||||
*
|
||||
* @param {String} fileContents
|
||||
* @param {String} fileName mostly used for informative reasons if an error.
|
||||
*
|
||||
* @returns {String} a string of JS with comments removed.
|
||||
*/
|
||||
removeComments: function (fileContents, fileName) {
|
||||
var context, script;
|
||||
if (commonJs.useRhino) {
|
||||
context = Packages.org.mozilla.javascript.Context.enter();
|
||||
script = context.compileString(fileContents, fileName, 1, null);
|
||||
return String(context.decompileScript(script, 0));
|
||||
} else {
|
||||
return fileContents.replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg, "");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Regexp for testing if there is already a require.def call in the file,
|
||||
* in which case do not try to convert it.
|
||||
*/
|
||||
defRegExp: /(require\s*\.\s*def|define)\s*\(/,
|
||||
|
||||
/**
|
||||
* Regexp for testing if there is a require([]) or require(function(){})
|
||||
* call, indicating the file is already in requirejs syntax.
|
||||
*/
|
||||
rjsRegExp: /require\s*\(\s*(\[|function)/,
|
||||
|
||||
/**
|
||||
* Does the actual file conversion.
|
||||
*
|
||||
* @param {String} moduleName the name of the module to use for the
|
||||
* define() call.
|
||||
*
|
||||
* @param {String} fileName the name of the file.
|
||||
*
|
||||
* @param {String} fileContents the contents of a file :)
|
||||
*
|
||||
* @param {Boolean} skipDeps if true, require("") dependencies
|
||||
* will not be searched, but the contents will just be wrapped in the
|
||||
* standard require, exports, module dependencies. Only usable in sync
|
||||
* environments like Node where the require("") calls can be resolved on
|
||||
* the fly.
|
||||
*
|
||||
* @returns {String} the converted contents
|
||||
*/
|
||||
convert: function (moduleName, fileName, fileContents, skipDeps) {
|
||||
//Strip out comments.
|
||||
try {
|
||||
var deps = [], depName, match,
|
||||
//Remove comments
|
||||
tempContents = commonJs.removeComments(fileContents, fileName),
|
||||
baseName = moduleName.split("/");
|
||||
|
||||
//First see if the module is not already RequireJS-formatted.
|
||||
if (commonJs.defRegExp.test(tempContents) || commonJs.rjsRegExp.test(tempContents)) {
|
||||
return fileContents;
|
||||
}
|
||||
|
||||
//Set baseName to be one directory higher than moduleName.
|
||||
baseName.pop();
|
||||
|
||||
//Reset the regexp to start at beginning of file. Do this
|
||||
//since the regexp is reused across files.
|
||||
commonJs.depRegExp.lastIndex = 0;
|
||||
|
||||
if (!skipDeps) {
|
||||
//Find dependencies in the code that was not in comments.
|
||||
while ((match = commonJs.depRegExp.exec(tempContents))) {
|
||||
depName = match[1];
|
||||
if (commonJs.useLog) {
|
||||
logger.trace(" " + depName);
|
||||
}
|
||||
if (depName) {
|
||||
deps.push('"' + depName + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Construct the wrapper boilerplate.
|
||||
fileContents = 'define(["require", "exports", "module"' +
|
||||
(deps.length ? ', ' + deps.join(",") : '') + '], ' +
|
||||
'function(require, exports, module) {\n' +
|
||||
(commonJs.logConverted ? 'global._requirejs_logger.trace("Evaluating module: ' + moduleName + '");\n' : "") +
|
||||
fileContents +
|
||||
'\n});\n';
|
||||
} catch (e) {
|
||||
logger.error("COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e);
|
||||
return fileContents;
|
||||
}
|
||||
|
||||
if (commonJs.logConverted) {
|
||||
logger.trace("\nREQUIREJS CONVERTED MODULE: " + moduleName + "\n\n" + fileContents + "\n");
|
||||
}
|
||||
return fileContents;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,213 @@
|
|||
/**
|
||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
//Helper functions to deal with file I/O.
|
||||
|
||||
/*jslint plusplus: false */
|
||||
/*global java: false */
|
||||
"use strict";
|
||||
|
||||
var fileUtil = {
|
||||
backSlashRegExp: /\\/g,
|
||||
|
||||
getLineSeparator: function () {
|
||||
return java.lang.System.getProperty("line.separator"); //Java String
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the absolute file path as a string, normalized
|
||||
* to using front slashes for path separators.
|
||||
* @param {java.io.File} file
|
||||
*/
|
||||
fileUtil.absPath = function (file) {
|
||||
return (file.getAbsolutePath() + "").replace(fileUtil.backSlashRegExp, "/");
|
||||
};
|
||||
|
||||
fileUtil.getFilteredFileList = function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) {
|
||||
//summary: Recurses startDir and finds matches to the files that match regExpFilters.include
|
||||
//and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
|
||||
//and it will be treated as the "include" case.
|
||||
//Ignores files/directories that start with a period (.).
|
||||
var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
|
||||
i, file, filePath, ok, dirFiles;
|
||||
|
||||
topDir = startDir;
|
||||
if (!startDirIsJavaObject) {
|
||||
topDir = new java.io.File(startDir);
|
||||
}
|
||||
|
||||
regExpInclude = regExpFilters.include || regExpFilters;
|
||||
regExpExclude = regExpFilters.exclude || null;
|
||||
|
||||
if (topDir.exists()) {
|
||||
dirFileArray = topDir.listFiles();
|
||||
for (i = 0; i < dirFileArray.length; i++) {
|
||||
file = dirFileArray[i];
|
||||
if (file.isFile()) {
|
||||
filePath = file.getPath();
|
||||
if (makeUnixPaths) {
|
||||
//Make sure we have a JS string.
|
||||
filePath = String(filePath);
|
||||
if (filePath.indexOf("/") === -1) {
|
||||
filePath = filePath.replace(/\\/g, "/");
|
||||
}
|
||||
}
|
||||
|
||||
ok = true;
|
||||
if (regExpInclude) {
|
||||
ok = filePath.match(regExpInclude);
|
||||
}
|
||||
if (ok && regExpExclude) {
|
||||
ok = !filePath.match(regExpExclude);
|
||||
}
|
||||
|
||||
if (ok && !file.getName().match(/^\./)) {
|
||||
files.push(filePath);
|
||||
}
|
||||
} else if (file.isDirectory() && !file.getName().match(/^\./)) {
|
||||
dirFiles = this.getFilteredFileList(file, regExpFilters, makeUnixPaths, true);
|
||||
files.push.apply(files, dirFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files; //Array
|
||||
};
|
||||
|
||||
|
||||
fileUtil.copyDir = function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
|
||||
//summary: copies files from srcDir to destDir using the regExpFilter to determine if the
|
||||
//file should be copied. Returns a list file name strings of the destinations that were copied.
|
||||
regExpFilter = regExpFilter || /\w/;
|
||||
|
||||
var fileNames = fileUtil.getFilteredFileList(srcDir, regExpFilter, true),
|
||||
copiedFiles = [], i, srcFileName, destFileName;
|
||||
|
||||
for (i = 0; i < fileNames.length; i++) {
|
||||
srcFileName = fileNames[i];
|
||||
destFileName = srcFileName.replace(srcDir, destDir);
|
||||
|
||||
if (fileUtil.copyFile(srcFileName, destFileName, onlyCopyNew)) {
|
||||
copiedFiles.push(destFileName);
|
||||
}
|
||||
}
|
||||
|
||||
return copiedFiles.length ? copiedFiles : null; //Array or null
|
||||
};
|
||||
|
||||
fileUtil.copyFile = function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
|
||||
//summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
|
||||
//srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
|
||||
var destFile = new java.io.File(destFileName), srcFile, parentDir,
|
||||
srcChannel, destChannel;
|
||||
|
||||
//logger.trace("Src filename: " + srcFileName);
|
||||
//logger.trace("Dest filename: " + destFileName);
|
||||
|
||||
//If onlyCopyNew is true, then compare dates and only copy if the src is newer
|
||||
//than dest.
|
||||
if (onlyCopyNew) {
|
||||
srcFile = new java.io.File(srcFileName);
|
||||
if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
|
||||
return false; //Boolean
|
||||
}
|
||||
}
|
||||
|
||||
//Make sure destination dir exists.
|
||||
parentDir = destFile.getParentFile();
|
||||
if (!parentDir.exists()) {
|
||||
if (!parentDir.mkdirs()) {
|
||||
throw "Could not create directory: " + parentDir.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
//Java's version of copy file.
|
||||
srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
|
||||
destChannel = new java.io.FileOutputStream(destFileName).getChannel();
|
||||
destChannel.transferFrom(srcChannel, 0, srcChannel.size());
|
||||
srcChannel.close();
|
||||
destChannel.close();
|
||||
|
||||
return true; //Boolean
|
||||
};
|
||||
|
||||
fileUtil.readFile = function (/*String*/path, /*String?*/encoding) {
|
||||
//summary: reads a file and returns a string
|
||||
encoding = encoding || "utf-8";
|
||||
var file = new java.io.File(path),
|
||||
lineSeparator = fileUtil.getLineSeparator(),
|
||||
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
|
||||
stringBuffer, line;
|
||||
try {
|
||||
stringBuffer = new java.lang.StringBuffer();
|
||||
line = input.readLine();
|
||||
|
||||
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
||||
// http://www.unicode.org/faq/utf_bom.html
|
||||
|
||||
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
|
||||
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
|
||||
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
||||
// Eat the BOM, since we've already found the encoding on this file,
|
||||
// and we plan to concatenating this buffer with others; the BOM should
|
||||
// only appear at the top of a file.
|
||||
line = line.substring(1);
|
||||
}
|
||||
while (line !== null) {
|
||||
stringBuffer.append(line);
|
||||
stringBuffer.append(lineSeparator);
|
||||
line = input.readLine();
|
||||
}
|
||||
//Make sure we return a JavaScript string and not a Java string.
|
||||
return String(stringBuffer.toString()); //String
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
};
|
||||
|
||||
fileUtil.saveUtf8File = function (/*String*/fileName, /*String*/fileContents) {
|
||||
//summary: saves a file using UTF-8 encoding.
|
||||
fileUtil.saveFile(fileName, fileContents, "utf-8");
|
||||
};
|
||||
|
||||
fileUtil.saveFile = function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
|
||||
//summary: saves a file.
|
||||
var outFile = new java.io.File(fileName), outWriter, parentDir, os;
|
||||
|
||||
parentDir = outFile.getAbsoluteFile().getParentFile();
|
||||
if (!parentDir.exists()) {
|
||||
if (!parentDir.mkdirs()) {
|
||||
throw "Could not create directory: " + parentDir.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
if (encoding) {
|
||||
outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
|
||||
} else {
|
||||
outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
|
||||
}
|
||||
|
||||
os = new java.io.BufferedWriter(outWriter);
|
||||
try {
|
||||
os.write(fileContents);
|
||||
} finally {
|
||||
os.close();
|
||||
}
|
||||
};
|
||||
|
||||
fileUtil.deleteFile = function (/*String*/fileName) {
|
||||
//summary: deletes a file or directory if it exists.
|
||||
var file = new java.io.File(fileName), files, i;
|
||||
if (file.exists()) {
|
||||
if (file.isDirectory()) {
|
||||
files = file.listFiles();
|
||||
for (i = 0; i < files.length; i++) {
|
||||
this.deleteFile(files[i]);
|
||||
}
|
||||
}
|
||||
file["delete"]();
|
||||
}
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*jslint plusplus: false */
|
||||
/*global */
|
||||
|
||||
"use strict";
|
||||
|
||||
var lang = {
|
||||
backSlashRegExp: /\\/g,
|
||||
|
||||
/**
|
||||
* Simple function to mix in properties from source into target,
|
||||
* but only if target does not already have a property of the same name.
|
||||
*/
|
||||
mixin: function (target, source, override) {
|
||||
//Use an empty object to avoid other bad JS code that modifies
|
||||
//Object.prototype.
|
||||
var empty = {}, prop;
|
||||
for (prop in source) {
|
||||
if (override || !(prop in target)) {
|
||||
target[prop] = source[prop];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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
|
||||
};
|
||||
}())
|
||||
};
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
var logger = {
|
||||
TRACE: 0,
|
||||
INFO: 1,
|
||||
WARN: 2,
|
||||
ERROR: 3,
|
||||
level: 0,
|
||||
logPrefix: "",
|
||||
|
||||
trace: function(message){
|
||||
if(this.level <= this.TRACE){
|
||||
this._print(message);
|
||||
}
|
||||
},
|
||||
|
||||
info: function(message){
|
||||
if(this.level <= this.INFO){
|
||||
this._print(message);
|
||||
}
|
||||
},
|
||||
|
||||
warn: function(message){
|
||||
if(this.level <= this.WARN){
|
||||
this._print(message);
|
||||
}
|
||||
},
|
||||
|
||||
error: function(message){
|
||||
if(this.level <= this.ERROR){
|
||||
this._print(message);
|
||||
}
|
||||
},
|
||||
|
||||
_print: function(message){
|
||||
this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message);
|
||||
},
|
||||
|
||||
_sysPrint: function(message){
|
||||
print(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
/**
|
||||
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*jslint plusplus: false, nomen: false, regexp: false */
|
||||
/*global require: false, java: false, Packages: false, logger: false, fileUtil: false,
|
||||
readFile: false, lang: false */
|
||||
|
||||
"use strict";
|
||||
|
||||
var optimize;
|
||||
|
||||
(function () {
|
||||
var JSSourceFilefromCode,
|
||||
cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g,
|
||||
cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g;
|
||||
|
||||
|
||||
//Bind to Closure compiler, but if it is not available, do not sweat it.
|
||||
try {
|
||||
JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]);
|
||||
} catch (e) {}
|
||||
|
||||
//Helper for closure compiler, because of weird Java-JavaScript interactions.
|
||||
function closurefromCode(filename, content) {
|
||||
return JSSourceFilefromCode.invoke(null, [filename, content]);
|
||||
}
|
||||
|
||||
/**
|
||||
* If an URL from a CSS url value contains start/end quotes, remove them.
|
||||
* This is not done in the regexp, since my regexp fu is not that strong,
|
||||
* and the CSS spec allows for ' and " in the URL if they are backslash escaped.
|
||||
* @param {String} url
|
||||
*/
|
||||
function cleanCssUrlQuotes(url) {
|
||||
//Make sure we are not ending in whitespace.
|
||||
//Not very confident of the css regexps above that there will not be ending
|
||||
//whitespace.
|
||||
url = url.replace(/\s+$/, "");
|
||||
|
||||
if (url.charAt(0) === "'" || url.charAt(0) === "\"") {
|
||||
url = url.substring(1, url.length - 1);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inlines nested stylesheets that have @import calls in them.
|
||||
* @param {String} fileName
|
||||
* @param {String} fileContents
|
||||
* @param {String} [cssImportIgnore]
|
||||
*/
|
||||
function flattenCss(fileName, fileContents, cssImportIgnore) {
|
||||
//Find the last slash in the name.
|
||||
fileName = fileName.replace(lang.backSlashRegExp, "/");
|
||||
var endIndex = fileName.lastIndexOf("/"),
|
||||
//Make a file path based on the last slash.
|
||||
//If no slash, so must be just a file name. Use empty string then.
|
||||
filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "";
|
||||
|
||||
//Make sure we have a delimited ignore list to make matching faster
|
||||
if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") {
|
||||
cssImportIgnore += ",";
|
||||
}
|
||||
|
||||
return fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) {
|
||||
//Only process media type "all" or empty media type rules.
|
||||
if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
|
||||
return fullMatch;
|
||||
}
|
||||
|
||||
importFileName = cleanCssUrlQuotes(importFileName);
|
||||
|
||||
//Ignore the file import if it is part of an ignore list.
|
||||
if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
|
||||
return fullMatch;
|
||||
}
|
||||
|
||||
//Make sure we have a unix path for the rest of the operation.
|
||||
importFileName = importFileName.replace(lang.backSlashRegExp, "/");
|
||||
|
||||
try {
|
||||
//if a relative path, then tack on the filePath.
|
||||
//If it is not a relative path, then the readFile below will fail,
|
||||
//and we will just skip that import.
|
||||
var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName,
|
||||
importContents = fileUtil.readFile(fullImportFileName), i,
|
||||
importEndIndex, importPath, fixedUrlMatch, colonIndex, parts;
|
||||
|
||||
//Make sure to flatten any nested imports.
|
||||
importContents = flattenCss(fullImportFileName, importContents);
|
||||
|
||||
//Make the full import path
|
||||
importEndIndex = importFileName.lastIndexOf("/");
|
||||
|
||||
//Make a file path based on the last slash.
|
||||
//If no slash, so must be just a file name. Use empty string then.
|
||||
importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : "";
|
||||
|
||||
//Modify URL paths to match the path represented by this file.
|
||||
importContents = importContents.replace(cssUrlRegExp, function (fullMatch, urlMatch) {
|
||||
fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
|
||||
fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
|
||||
|
||||
//Only do the work for relative URLs. Skip things that start with / or have
|
||||
//a protocol.
|
||||
colonIndex = fixedUrlMatch.indexOf(":");
|
||||
if (fixedUrlMatch.charAt(0) !== "/" && (colonIndex === -1 || colonIndex > fixedUrlMatch.indexOf("/"))) {
|
||||
//It is a relative URL, tack on the path prefix
|
||||
urlMatch = importPath + fixedUrlMatch;
|
||||
} else {
|
||||
logger.trace(importFileName + "\n URL not a relative URL, skipping: " + urlMatch);
|
||||
}
|
||||
|
||||
//Collapse .. and .
|
||||
parts = urlMatch.split("/");
|
||||
for (i = parts.length - 1; i > 0; i--) {
|
||||
if (parts[i] === ".") {
|
||||
parts.splice(i, 1);
|
||||
} else if (parts[i] === "..") {
|
||||
if (i !== 0 && parts[i - 1] !== "..") {
|
||||
parts.splice(i - 1, 2);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "url(" + parts.join("/") + ")";
|
||||
});
|
||||
|
||||
return importContents;
|
||||
} catch (e) {
|
||||
logger.trace(fileName + "\n Cannot inline css import, skipping: " + importFileName);
|
||||
return fullMatch;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
optimize = {
|
||||
closure: function (fileName, fileContents, keepLines, config) {
|
||||
config = config || {};
|
||||
var jscomp = Packages.com.google.javascript.jscomp,
|
||||
flags = Packages.com.google.common.flags,
|
||||
//Fake extern
|
||||
externSourceFile = closurefromCode("fakeextern.js", " "),
|
||||
//Set up source input
|
||||
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||
options, option, FLAG_compilation_level, compiler,
|
||||
Compiler = Packages.com.google.javascript.jscomp.Compiler;
|
||||
|
||||
logger.trace("Minifying file: " + fileName);
|
||||
|
||||
//Set up options
|
||||
options = new jscomp.CompilerOptions();
|
||||
for (option in config.CompilerOptions) {
|
||||
// options are false by default and jslint wanted an if statement in this for loop
|
||||
if (config.CompilerOptions[option]) {
|
||||
options[option] = config.CompilerOptions[option];
|
||||
}
|
||||
|
||||
}
|
||||
options.prettyPrint = keepLines || options.prettyPrint;
|
||||
|
||||
FLAG_compilation_level = flags.Flag.value(jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS']);
|
||||
FLAG_compilation_level.get().setOptionsForCompilationLevel(options);
|
||||
|
||||
//Trigger the compiler
|
||||
Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']);
|
||||
compiler = new Compiler();
|
||||
compiler.compile(externSourceFile, jsSourceFile, options);
|
||||
return compiler.toSource();
|
||||
},
|
||||
|
||||
/**
|
||||
* Optimizes a file that contains JavaScript content. It will inline
|
||||
* text plugin files and run it through Google Closure Compiler
|
||||
* minification, if the config options specify it.
|
||||
*
|
||||
* @param {String} fileName the name of the file to optimize
|
||||
* @param {String} outFileName the name of the file to use for the
|
||||
* saved optimized content.
|
||||
* @param {Object} config the build config object.
|
||||
*/
|
||||
jsFile: function (fileName, outFileName, config) {
|
||||
var doClosure = (config.optimize + "").indexOf("closure") === 0,
|
||||
fileContents;
|
||||
|
||||
fileContents = fileUtil.readFile(fileName);
|
||||
|
||||
//Optimize the JS files if asked.
|
||||
if (doClosure) {
|
||||
fileContents = optimize.closure(fileName,
|
||||
fileContents,
|
||||
(config.optimize.indexOf(".keepLines") !== -1),
|
||||
config.closure);
|
||||
}
|
||||
|
||||
fileUtil.saveUtf8File(outFileName, fileContents);
|
||||
},
|
||||
|
||||
/**
|
||||
* Optimizes one CSS file, inlining @import calls, stripping comments, and
|
||||
* optionally removes line returns.
|
||||
* @param {String} fileName the path to the CSS file to optimize
|
||||
* @param {String} outFileName the path to save the optimized file.
|
||||
* @param {Object} config the config object with the optimizeCss and
|
||||
* cssImportIgnore options.
|
||||
*/
|
||||
cssFile: function (fileName, outFileName, config) {
|
||||
//Read in the file. Make sure we have a JS string.
|
||||
var originalFileContents = fileUtil.readFile(fileName),
|
||||
fileContents = flattenCss(fileName, originalFileContents, config.cssImportIgnore),
|
||||
startIndex, endIndex;
|
||||
|
||||
//Do comment removal.
|
||||
try {
|
||||
startIndex = -1;
|
||||
//Get rid of comments.
|
||||
while ((startIndex = fileContents.indexOf("/*")) !== -1) {
|
||||
endIndex = fileContents.indexOf("*/", startIndex + 2);
|
||||
if (endIndex === -1) {
|
||||
throw "Improper comment in CSS file: " + fileName;
|
||||
}
|
||||
fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
|
||||
}
|
||||
//Get rid of newlines.
|
||||
if (config.optimizeCss.indexOf(".keepLines") === -1) {
|
||||
fileContents = fileContents.replace(/[\r\n]/g, "");
|
||||
fileContents = fileContents.replace(/\s+/g, " ");
|
||||
fileContents = fileContents.replace(/\{\s/g, "{");
|
||||
fileContents = fileContents.replace(/\s\}/g, "}");
|
||||
} else {
|
||||
//Remove multiple empty lines.
|
||||
fileContents = fileContents.replace(/(\r\n)+/g, "\r\n");
|
||||
fileContents = fileContents.replace(/(\n)+/g, "\n");
|
||||
}
|
||||
} catch (e) {
|
||||
fileContents = originalFileContents;
|
||||
logger.error("Could not optimized CSS file: " + fileName + ", error: " + e);
|
||||
}
|
||||
|
||||
fileUtil.saveUtf8File(outFileName, fileContents);
|
||||
},
|
||||
|
||||
/**
|
||||
* Optimizes CSS files, inlining @import calls, stripping comments, and
|
||||
* optionally removes line returns.
|
||||
* @param {String} startDir the path to the top level directory
|
||||
* @param {Object} config the config object with the optimizeCss and
|
||||
* cssImportIgnore options.
|
||||
*/
|
||||
css: function (startDir, config) {
|
||||
if (config.optimizeCss.indexOf("standard") !== -1) {
|
||||
var i, fileName,
|
||||
fileList = fileUtil.getFilteredFileList(startDir, /\.css$/, true);
|
||||
if (fileList) {
|
||||
for (i = 0; i < fileList.length; i++) {
|
||||
fileName = fileList[i];
|
||||
logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName);
|
||||
optimize.cssFile(fileName, fileName, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}());
|
|
@ -0,0 +1,432 @@
|
|||
/**
|
||||
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*
|
||||
* Java 6 is required.
|
||||
*/
|
||||
|
||||
/*jslint plusplus: false */
|
||||
/*global java: false, Packages: false, load: false */
|
||||
|
||||
"use strict";
|
||||
|
||||
var parse;
|
||||
(function () {
|
||||
//fileContents = 'require.def("foo", ["one", \n//This is a comment\n"two",\n/*Another comment*/"three"], {});',
|
||||
//fileContents = 'require.def("foo", {one: "two"});',
|
||||
var jscomp = Packages.com.google.javascript.jscomp,
|
||||
compiler = new jscomp.Compiler(),
|
||||
|
||||
//Values taken from com.google.javascript.rhino.Token,
|
||||
//but duplicated here to avoid weird Java-to-JS transforms.
|
||||
GETPROP = 33,
|
||||
CALL = 37,
|
||||
NAME = 38,
|
||||
STRING = 40,
|
||||
ARRAYLIT = 63,
|
||||
OBJECTLIT = 64,
|
||||
ASSIGN = 86,
|
||||
FUNCTION = 105,
|
||||
EXPR_RESULT = 130,
|
||||
|
||||
//Oh Java, you rascal.
|
||||
JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]);
|
||||
|
||||
//Helper for closureOptimize, because of weird Java-JavaScript interactions.
|
||||
function closurefromCode(filename, content) {
|
||||
return JSSourceFilefromCode.invoke(null, [filename, content]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls node.getString() but makes sure a JS string is returned
|
||||
*/
|
||||
function nodeString(node) {
|
||||
return String(node.getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls compiler.parse, and if any errors, throws.
|
||||
*/
|
||||
function compilerParse(jsSourceFile, fileName) {
|
||||
var result = compiler.parse(jsSourceFile),
|
||||
errorManager = compiler.getErrorManager(),
|
||||
errorMsg = '', errors, i;
|
||||
|
||||
if (errorManager.getErrorCount() > 0) {
|
||||
errorMsg += 'ERROR(S) in file: ' + fileName + ':\n';
|
||||
errors = errorManager.getErrors();
|
||||
for (i = 0; i < errors.length; i++) {
|
||||
errorMsg += errors[i].toString() + '\n';
|
||||
}
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a node as being an object literal (like for i18n bundles)
|
||||
* or an array literal with just string members.
|
||||
* This function does not need to worry about comments, they are not
|
||||
* present in this AST.
|
||||
*/
|
||||
function validateDeps(node) {
|
||||
var type = node.getType(), i, dep;
|
||||
|
||||
if (type === OBJECTLIT || type === FUNCTION) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Dependencies can be an object literal or an array.
|
||||
if (type !== ARRAYLIT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; (dep = node.getChildAtIndex(i)); i++) {
|
||||
if (dep.getType() !== STRING) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main parse function. Returns a string of any valid require or define/require.def
|
||||
* calls as part of one JavaScript source string.
|
||||
* @param {String} fileName
|
||||
* @param {String} fileContents
|
||||
* @returns {String} JS source string or null, if no require or define/require.def
|
||||
* calls are found.
|
||||
*/
|
||||
parse = function (fileName, fileContents) {
|
||||
//Set up source input
|
||||
var matches = [], result = null,
|
||||
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||
astRoot = compilerParse(jsSourceFile, fileName);
|
||||
|
||||
parse.recurse(astRoot, matches);
|
||||
|
||||
if (matches.length) {
|
||||
result = matches.join("\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing a file recursively for require calls.
|
||||
* @param {Packages.com.google.javascript.rhino.Node} node
|
||||
* @param {Array} matches where to store the string matches
|
||||
*/
|
||||
parse.recurse = function (parentNode, matches) {
|
||||
var i, node, parsed;
|
||||
for (i = 0; (node = parentNode.getChildAtIndex(i)); i++) {
|
||||
parsed = parse.parseNode(node);
|
||||
if (parsed) {
|
||||
matches.push(parsed);
|
||||
}
|
||||
parse.recurse(node, matches);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the file defines require().
|
||||
* @param {String} fileName
|
||||
* @param {String} fileContents
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
parse.definesRequire = function (fileName, fileContents) {
|
||||
var jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||
astRoot = compilerParse(jsSourceFile, fileName);
|
||||
|
||||
return parse.nodeHasRequire(astRoot);
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds require("") calls inside a CommonJS anonymous module wrapped in a
|
||||
* define/require.def(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 jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||
astRoot = compilerParse(jsSourceFile, fileName),
|
||||
deps = [],
|
||||
defFunc = parse.findAnonRequireDefCallback(astRoot);
|
||||
|
||||
//Now look inside the def call's function for require calls.
|
||||
if (defFunc) {
|
||||
parse.findRequireDepNames(defFunc, deps);
|
||||
|
||||
//If no deps, still add the standard CommonJS require, exports, module,
|
||||
//in that order, to the deps.
|
||||
deps = ["require", "exports", "module"].concat(deps);
|
||||
}
|
||||
|
||||
return deps;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds the function in require.def(function (require, exports, module){});
|
||||
* @param {Packages.com.google.javascript.rhino.Node} node
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
parse.findAnonRequireDefCallback = function (node) {
|
||||
var methodName, func, callback, i, n;
|
||||
|
||||
if (node.getType() === GETPROP &&
|
||||
node.getFirstChild().getType() === NAME &&
|
||||
nodeString(node.getFirstChild()) === "require") {
|
||||
|
||||
methodName = nodeString(node.getChildAtIndex(1));
|
||||
if (methodName === "def") {
|
||||
func = node.getLastSibling();
|
||||
if (func.getType() === FUNCTION) {
|
||||
//Bingo.
|
||||
return func;
|
||||
}
|
||||
}
|
||||
} else if (node.getType() === EXPR_RESULT &&
|
||||
node.getFirstChild().getType() === CALL &&
|
||||
node.getFirstChild().getFirstChild().getType() === NAME &&
|
||||
nodeString(node.getFirstChild().getFirstChild()) === "define") {
|
||||
|
||||
func = node.getFirstChild().getFirstChild().getLastSibling();
|
||||
if (func.getType() === FUNCTION) {
|
||||
//Bingo.
|
||||
return func;
|
||||
}
|
||||
}
|
||||
|
||||
//Check child nodes
|
||||
for (i = 0; (n = node.getChildAtIndex(i)); i++) {
|
||||
if ((callback = parse.findAnonRequireDefCallback(n))) {
|
||||
return callback;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
parse.findRequireDepNames = function (node, deps) {
|
||||
var moduleName, i, n;
|
||||
|
||||
if (node.getType() === CALL) {
|
||||
if (node.getFirstChild().getType() === NAME &&
|
||||
nodeString(node.getFirstChild()) === "require") {
|
||||
|
||||
//It is a plain require() call.
|
||||
moduleName = node.getChildAtIndex(1);
|
||||
if (moduleName.getType() === STRING) {
|
||||
deps.push(nodeString(moduleName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check child nodes
|
||||
for (i = 0; (n = node.getChildAtIndex(i)); i++) {
|
||||
parse.findRequireDepNames(n, deps);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if a given node contains a require() definition.
|
||||
* @param {Packages.com.google.javascript.rhino.Node} node
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
parse.nodeHasRequire = function (node) {
|
||||
if (parse.isRequireNode(node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0, n; (n = node.getChildAtIndex(i)); i++) {
|
||||
if (parse.nodeHasRequire(n)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Is the given node the actual definition of require()
|
||||
* @param {Packages.com.google.javascript.rhino.Node} node
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
parse.isRequireNode = function (node) {
|
||||
//Actually look for the require.s = assignment, since
|
||||
//that is more indicative of RequireJS vs a plain require definition.
|
||||
var prop, name, s;
|
||||
if (node.getType() === ASSIGN) {
|
||||
prop = node.getFirstChild();
|
||||
if (prop.getType() === GETPROP) {
|
||||
name = prop.getFirstChild();
|
||||
if (name.getType() === NAME) {
|
||||
if (nodeString(name) === "require") {
|
||||
s = prop.getChildAtIndex(1);
|
||||
if (s && s.getType() === STRING &&
|
||||
nodeString(s) === "s") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
function optionalString(node) {
|
||||
var str = null;
|
||||
if (node) {
|
||||
str = parse.nodeToString(node);
|
||||
//Need to trim off trailing ; that is added by nodeToString too.
|
||||
if (str.charAt(str.length - 1) === ';') {
|
||||
str = str.slice(0, str.length - 1);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a require/require.def/define call to a string if it is a valid
|
||||
* call via static analysis of dependencies.
|
||||
* @param {String} callName the name of call (require or define)
|
||||
* @param {Packages.com.google.javascript.rhino.Node} the config node inside the call
|
||||
* @param {Packages.com.google.javascript.rhino.Node} the name node inside the call
|
||||
* @param {Packages.com.google.javascript.rhino.Node} the deps node inside the call
|
||||
*/
|
||||
parse.callToString = function (callName, config, name, deps) {
|
||||
//If name is an array, it means it is an anonymous module,
|
||||
//so adjust args appropriately. An anonymous module could
|
||||
//have a FUNCTION as the name type, but just ignore those
|
||||
//since we just want to find dependencies.
|
||||
//TODO: CHANGE THIS if/when support using a tostring
|
||||
//on function to find CommonJS dependencies.
|
||||
var configString, nameString, depString;
|
||||
if (name) {
|
||||
if (name.getType() === ARRAYLIT) {
|
||||
deps = name;
|
||||
}
|
||||
}
|
||||
|
||||
if (deps && !validateDeps(deps)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Only serialize the call name, config, module name and dependencies,
|
||||
//otherwise could get local variable names for module value.
|
||||
configString = config && config.getType() === OBJECTLIT && optionalString(config);
|
||||
nameString = optionalString(name);
|
||||
depString = optionalString(deps);
|
||||
|
||||
return callName + "(" +
|
||||
(configString ? configString : "") +
|
||||
(nameString ? (configString ? "," : "") + nameString : "") +
|
||||
(depString ? (configString || nameString ? "," : "") + depString : "") +
|
||||
");";
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if a specific node is a valid require or define/require.def call.
|
||||
* @param {Packages.com.google.javascript.rhino.Node} node
|
||||
*
|
||||
* @returns {String} a JS source string with the valid require/define call.
|
||||
* Otherwise null.
|
||||
*/
|
||||
parse.parseNode = function (node) {
|
||||
var call, methodName, targetName, name, config, deps, callChildCount;
|
||||
|
||||
if (node.getType() === EXPR_RESULT && node.getFirstChild().getType() === CALL) {
|
||||
call = node.getFirstChild();
|
||||
|
||||
if (call.getFirstChild().getType() === NAME &&
|
||||
nodeString(call.getFirstChild()) === "require") {
|
||||
|
||||
//It is a plain require() call.
|
||||
config = call.getChildAtIndex(1);
|
||||
deps = call.getChildAtIndex(2);
|
||||
if (config.getType() === ARRAYLIT) {
|
||||
deps = config;
|
||||
config = null;
|
||||
}
|
||||
|
||||
if (!deps || !validateDeps(deps)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parse.callToString("require", null, null, deps);
|
||||
|
||||
} else if (call.getType() === CALL &&
|
||||
call.getFirstChild().getType() === NAME &&
|
||||
nodeString(call.getFirstChild()) === "define") {
|
||||
|
||||
//A define call
|
||||
name = call.getChildAtIndex(1);
|
||||
deps = call.getChildAtIndex(2);
|
||||
return parse.callToString("define", null, name, deps);
|
||||
|
||||
} else if (call.getFirstChild().getType() === GETPROP &&
|
||||
call.getFirstChild().getFirstChild().getType() === NAME &&
|
||||
nodeString(call.getFirstChild().getFirstChild()) === "require") {
|
||||
|
||||
//Possibly a require.def/require.modify call
|
||||
|
||||
methodName = nodeString(call.getChildAtIndex(0).getChildAtIndex(1));
|
||||
if (methodName === "def") {
|
||||
|
||||
//A require.def() call
|
||||
name = call.getChildAtIndex(1);
|
||||
deps = call.getChildAtIndex(2);
|
||||
|
||||
return parse.callToString("define", null, name, deps);
|
||||
} else if (methodName === "modify") {
|
||||
|
||||
//A require.modify() call
|
||||
callChildCount = call.getChildCount();
|
||||
if (callChildCount > 0) {
|
||||
targetName = call.getChildAtIndex(1);
|
||||
}
|
||||
if (callChildCount > 1) {
|
||||
name = call.getChildAtIndex(2);
|
||||
}
|
||||
if (callChildCount > 2) {
|
||||
deps = call.getChildAtIndex(3);
|
||||
}
|
||||
|
||||
//Validate def name as a string
|
||||
if (!targetName || targetName.getType() !== STRING || !name || name.getType() !== STRING) {
|
||||
return null;
|
||||
}
|
||||
if (!validateDeps(deps)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parse.nodeToString(call);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an AST node into a JS source string. Does not maintain formatting
|
||||
* or even comments from original source, just returns valid JS source.
|
||||
* @param {Packages.com.google.javascript.rhino.Node} node
|
||||
* @returns {String} a JS source string.
|
||||
*/
|
||||
parse.nodeToString = function (node) {
|
||||
var codeBuilder = new jscomp.Compiler.CodeBuilder();
|
||||
compiler.toSource(codeBuilder, 1, node);
|
||||
return String(codeBuilder.toString());
|
||||
};
|
||||
}());
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*jslint regexp: false */
|
||||
/*global */
|
||||
|
||||
"use strict";
|
||||
|
||||
var pragma = {
|
||||
conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
|
||||
useStrictRegExp: /['"]use strict['"];/g,
|
||||
hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\)/g,
|
||||
|
||||
removeStrict: function (contents, config) {
|
||||
return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
|
||||
},
|
||||
|
||||
/**
|
||||
* processes the fileContents for some //>> conditional statements
|
||||
*/
|
||||
process: function (fileName, fileContents, config) {
|
||||
/*jslint evil: true */
|
||||
var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine,
|
||||
matches, type, marker, condition, isTrue, endRegExp, endMatches,
|
||||
endMarkerIndex, shouldInclude, startLength, pragmas = config.pragmas,
|
||||
//Legacy arg defined to help in dojo conversion script. Remove later
|
||||
//when dojo no longer needs conversion:
|
||||
kwArgs = pragmas;
|
||||
|
||||
//Replace has references if desired
|
||||
if (config.has) {
|
||||
fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) {
|
||||
if (test in config.has) {
|
||||
return !!config.has[test];
|
||||
}
|
||||
return match;
|
||||
});
|
||||
}
|
||||
|
||||
//If pragma work is not desired, skip it.
|
||||
if (config.skipPragmas) {
|
||||
return pragma.removeStrict(fileContents, config);
|
||||
}
|
||||
|
||||
while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) {
|
||||
//Found a conditional. Get the conditional line.
|
||||
lineEndIndex = fileContents.indexOf("\n", foundIndex);
|
||||
if (lineEndIndex === -1) {
|
||||
lineEndIndex = fileContents.length - 1;
|
||||
}
|
||||
|
||||
//Increment startIndex past the line so the next conditional search can be done.
|
||||
startIndex = lineEndIndex + 1;
|
||||
|
||||
//Break apart the conditional.
|
||||
conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
|
||||
matches = conditionLine.match(pragma.conditionalRegExp);
|
||||
if (matches) {
|
||||
type = matches[1];
|
||||
marker = matches[2];
|
||||
condition = matches[3];
|
||||
isTrue = false;
|
||||
//See if the condition is true.
|
||||
try {
|
||||
isTrue = !!eval("(" + condition + ")");
|
||||
} catch (e) {
|
||||
throw "Error in file: " +
|
||||
fileName +
|
||||
". Conditional comment: " +
|
||||
conditionLine +
|
||||
" failed with this error: " + e;
|
||||
}
|
||||
|
||||
//Find the endpoint marker.
|
||||
endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
|
||||
endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
|
||||
if (endMatches) {
|
||||
endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
|
||||
|
||||
//Find the next line return based on the match position.
|
||||
lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
|
||||
if (lineEndIndex === -1) {
|
||||
lineEndIndex = fileContents.length - 1;
|
||||
}
|
||||
|
||||
//Should we include the segment?
|
||||
shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
|
||||
|
||||
//Remove the conditional comments, and optionally remove the content inside
|
||||
//the conditional comments.
|
||||
startLength = startIndex - foundIndex;
|
||||
fileContents = fileContents.substring(0, foundIndex) +
|
||||
(shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
|
||||
fileContents.substring(lineEndIndex + 1, fileContents.length);
|
||||
|
||||
//Move startIndex to foundIndex, since that is the new position in the file
|
||||
//where we need to look for more conditionals in the next while loop pass.
|
||||
startIndex = foundIndex;
|
||||
} else {
|
||||
throw "Error in file: " +
|
||||
fileName +
|
||||
". Cannot find end marker for conditional comment: " +
|
||||
conditionLine;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pragma.removeStrict(fileContents, config);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*
|
||||
* This file patches require.js to communicate with the build system.
|
||||
*/
|
||||
|
||||
/*jslint nomen: false, plusplus: false, regexp: false */
|
||||
/*global load: false, require: false, logger: false, setTimeout: true,
|
||||
pragma: false, Packages: false, parse: false, java: true, define: true */
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
var layer,
|
||||
lineSeparator = java.lang.System.getProperty("line.separator"),
|
||||
pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/,
|
||||
oldDef;
|
||||
|
||||
//A file read function that can deal with BOMs
|
||||
function _readFile(path, encoding) {
|
||||
encoding = encoding || "utf-8";
|
||||
var file = new java.io.File(path),
|
||||
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
|
||||
stringBuffer, line;
|
||||
try {
|
||||
stringBuffer = new java.lang.StringBuffer();
|
||||
line = input.readLine();
|
||||
|
||||
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
||||
// http://www.unicode.org/faq/utf_bom.html
|
||||
|
||||
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
|
||||
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
|
||||
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
||||
// Eat the BOM, since we've already found the encoding on this file,
|
||||
// and we plan to concatenating this buffer with others; the BOM should
|
||||
// only appear at the top of a file.
|
||||
line = line.substring(1);
|
||||
}
|
||||
while (line !== null) {
|
||||
stringBuffer.append(line);
|
||||
stringBuffer.append(lineSeparator);
|
||||
line = input.readLine();
|
||||
}
|
||||
//Make sure we return a JavaScript string and not a Java string.
|
||||
return String(stringBuffer.toString()); //String
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset state for each build layer pass. */
|
||||
require._buildReset = function () {
|
||||
//Clear up the existing context.
|
||||
delete require.s.contexts._;
|
||||
|
||||
//These variables are not contextName-aware since the build should
|
||||
//only have one context.
|
||||
layer = require._layer = {
|
||||
buildPathMap: {},
|
||||
buildFileToModule: {},
|
||||
buildFilePaths: [],
|
||||
loadedFiles: {},
|
||||
modulesWithNames: {},
|
||||
existingRequireUrl: ""
|
||||
};
|
||||
};
|
||||
|
||||
require._buildReset();
|
||||
|
||||
/**
|
||||
* Makes sure the URL is something that can be supported by the
|
||||
* optimization tool.
|
||||
* @param {String} url
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
require._isSupportedBuildUrl = function (url) {
|
||||
//Ignore URLs with protocols or question marks, means either network
|
||||
//access is needed to fetch it or it is too dynamic. Note that
|
||||
//on Windows, full paths are used for some urls, which include
|
||||
//the drive, like c:/something, so need to test for something other
|
||||
//than just a colon.
|
||||
return url.indexOf("://") === -1 && url.indexOf("?") === -1;
|
||||
};
|
||||
|
||||
//Override require.def to catch modules that just define an object, so that
|
||||
//a dummy require.def call is not put in the build file for them. They do
|
||||
//not end up getting defined via require.execCb, so we need to catch them
|
||||
//at the require.def call.
|
||||
oldDef = require.def;
|
||||
|
||||
//This function signature does not have to be exact, just match what we
|
||||
//are looking for.
|
||||
define = require.def = function (name, obj) {
|
||||
if (typeof name === "string") {
|
||||
layer.modulesWithNames[name] = true;
|
||||
}
|
||||
return oldDef.apply(require, arguments);
|
||||
};
|
||||
|
||||
//Add some utilities for plugins/pluginBuilders
|
||||
require._readFile = _readFile;
|
||||
require._fileExists = function (path) {
|
||||
return (new java.io.File(path)).exists();
|
||||
};
|
||||
|
||||
require.pluginBuilders = {};
|
||||
|
||||
//Override load so that the file paths can be collected.
|
||||
require.load = function (context, moduleName, url) {
|
||||
/*jslint evil: true */
|
||||
var isPlugin = false,
|
||||
contents, pluginBuilderMatch, builderName;
|
||||
|
||||
//Adjust the URL if it was not transformed to use baseUrl.
|
||||
if (require.jsExtRegExp.test(moduleName)) {
|
||||
url = context.config.dirBaseUrl + url;
|
||||
}
|
||||
|
||||
context.loaded[moduleName] = false;
|
||||
context.scriptCount += 1;
|
||||
|
||||
//Only handle urls that can be inlined, so that means avoiding some
|
||||
//URLs like ones that require network access or may be too dynamic,
|
||||
//like JSONP
|
||||
if (require._isSupportedBuildUrl(url)) {
|
||||
//Save the module name to path and path to module name mappings.
|
||||
layer.buildPathMap[moduleName] = url;
|
||||
layer.buildFileToModule[url] = moduleName;
|
||||
|
||||
//Load the file contents, process for conditionals, then
|
||||
//evaluate it.
|
||||
contents = _readFile(url);
|
||||
contents = pragma.process(url, contents, context.config);
|
||||
|
||||
//Find out if the file contains a require() definition. Need to know
|
||||
//this so we can inject plugins right after it, but before they are needed,
|
||||
//and to make sure this file is first, so that require.def calls work.
|
||||
//This situation mainly occurs when the build is done on top of the output
|
||||
//of another build, where the first build may include require somewhere in it.
|
||||
if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) {
|
||||
layer.existingRequireUrl = url;
|
||||
}
|
||||
|
||||
if (moduleName in context.plugins) {
|
||||
//This is a loader plugin, check to see if it has a build extension,
|
||||
//otherwise the plugin will act as the plugin builder too.
|
||||
pluginBuilderMatch = pluginBuilderRegExp.exec(contents);
|
||||
if (pluginBuilderMatch) {
|
||||
//Load the plugin builder for the plugin contents.
|
||||
builderName = context.normalize(pluginBuilderMatch[3], moduleName);
|
||||
contents = _readFile(context.nameToUrl(builderName));
|
||||
}
|
||||
|
||||
//plugins need to have their source evaled as-is.
|
||||
isPlugin = true;
|
||||
}
|
||||
|
||||
//Parse out the require and define calls.
|
||||
//Do this even for plugins in case they have their own
|
||||
//dependencies that may be separate to how the pluginBuilder works.
|
||||
if (!isPlugin) {
|
||||
contents = parse(url, contents);
|
||||
}
|
||||
|
||||
if (contents) {
|
||||
eval(contents);
|
||||
|
||||
//Support anonymous modules.
|
||||
context.completeLoad(moduleName);
|
||||
}
|
||||
|
||||
// remember the list of dependencies for this layer.O
|
||||
layer.buildFilePaths.push(url);
|
||||
}
|
||||
|
||||
//Mark the module loaded.
|
||||
context.loaded[moduleName] = true;
|
||||
|
||||
//Get a handle on the pluginBuilder
|
||||
if (isPlugin) {
|
||||
require.pluginBuilders[moduleName] = context.defined[moduleName];
|
||||
}
|
||||
};
|
||||
|
||||
//This method is called when a plugin specifies a loaded value. Use
|
||||
//this to track dependencies that do not go through require.load.
|
||||
require.onPluginLoad = function (context, pluginName, name, value) {
|
||||
var registeredName = pluginName + '!' + name;
|
||||
layer.buildFilePaths.push(registeredName);
|
||||
layer.buildFileToModule[registeredName] = registeredName;
|
||||
layer.modulesWithNames[registeredName] = true;
|
||||
};
|
||||
|
||||
//Override a method provided by require/text.js for loading text files as
|
||||
//dependencies.
|
||||
require.fetchText = function (url, callback) {
|
||||
callback(_readFile(url));
|
||||
};
|
||||
|
||||
//Marks the module as part of the loaded set, and puts
|
||||
//it in the right position for output in the build layer,
|
||||
//since require() already did the dependency checks and should have
|
||||
//called this method already for those dependencies.
|
||||
require.execCb = function (name, cb, args) {
|
||||
var url = name && layer.buildPathMap[name];
|
||||
if (url && !layer.loadedFiles[url]) {
|
||||
layer.loadedFiles[url] = true;
|
||||
layer.modulesWithNames[name] = true;
|
||||
}
|
||||
if (cb.__requireJsBuild) {
|
||||
return cb.apply(null, args);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}());
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Contents
|
||||
//
|
||||
|
||||
The Closure Compiler performs checking, instrumentation, and
|
||||
optimizations on JavaScript code. The purpose of this README is to
|
||||
explain how to build and run the Closure Compiler.
|
||||
|
||||
The Closure Compiler requires Java 6 or higher.
|
||||
http://www.java.com/
|
||||
|
||||
|
||||
//
|
||||
// Building The Closure Compiler
|
||||
//
|
||||
|
||||
There are three ways to get a Closure Compiler executable.
|
||||
|
||||
1) Use one we built for you.
|
||||
|
||||
Pre-built Closure binaries can be found at
|
||||
http://code.google.com/p/closure-compiler/downloads/list
|
||||
|
||||
|
||||
2) Check out the source and build it with Apache Ant.
|
||||
|
||||
First, check out the full source tree of the Closure Compiler. There
|
||||
are instructions on how to do this at the project site.
|
||||
http://code.google.com/p/closure-compiler/source/checkout
|
||||
|
||||
Apache Ant is a cross-platform build tool.
|
||||
http://ant.apache.org/
|
||||
|
||||
At the root of the source tree, there is an Ant file named
|
||||
build.xml. To use it, navigate to the same directory and type the
|
||||
command
|
||||
|
||||
ant jar
|
||||
|
||||
This will produce a jar file called "build/compiler.jar".
|
||||
|
||||
|
||||
3) Check out the source and build it with Eclipse.
|
||||
|
||||
Eclipse is a cross-platform IDE.
|
||||
http://www.eclipse.org/
|
||||
|
||||
Under Eclipse's File menu, click "New > Project ..." and create a
|
||||
"Java Project." You will see an options screen. Give the project a
|
||||
name, select "Create project from existing source," and choose the
|
||||
root of the checked-out source tree as the existing directory. Verify
|
||||
that you are using JRE version 6 or higher.
|
||||
|
||||
Eclipse can use the build.xml file to discover rules. When you
|
||||
navigate to the build.xml file, you will see all the build rules in
|
||||
the "Outline" pane. Run the "jar" rule to build the compiler in
|
||||
build/compiler.jar.
|
||||
|
||||
|
||||
//
|
||||
// Running The Closure Compiler
|
||||
//
|
||||
|
||||
Once you have the jar binary, running the Closure Compiler is straightforward.
|
||||
|
||||
On the command line, type
|
||||
|
||||
java -jar compiler.jar
|
||||
|
||||
This starts the compiler in interactive mode. Type
|
||||
|
||||
var x = 17 + 25;
|
||||
|
||||
then hit "Enter", then hit "Ctrl-Z" (on Windows) or "Ctrl-D" (on Mac or Linux)
|
||||
and "Enter" again. The Compiler will respond:
|
||||
|
||||
var x=42;
|
||||
|
||||
The Closure Compiler has many options for reading input from a file,
|
||||
writing output to a file, checking your code, and running
|
||||
optimizations. To learn more, type
|
||||
|
||||
java -jar compiler.jar --help
|
||||
|
||||
You can read more detailed documentation about the many flags at
|
||||
http://code.google.com/closure/compiler/docs/gettingstarted_app.html
|
||||
|
||||
|
||||
//
|
||||
// Compiling Multiple Scripts
|
||||
//
|
||||
|
||||
If you have multiple scripts, you should compile them all together with
|
||||
one compile command.
|
||||
|
||||
java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js
|
||||
|
||||
The Closure Compiler will concatenate the files in the order they're
|
||||
passed at the command line.
|
||||
|
||||
If you need to compile many, many scripts together, you may start to
|
||||
run into problems with managing dependencies between scripts. You
|
||||
should check out the Closure Library. It contains functions for
|
||||
enforcing dependencies between scripts, and a tool called calcdeps.py
|
||||
that knows how to give scripts to the Closure Compiler in the right
|
||||
order.
|
||||
|
||||
http://code.google.com/p/closure-library/
|
||||
|
||||
//
|
||||
// Licensing
|
||||
//
|
||||
|
||||
Unless otherwise stated, all source files are licensed under
|
||||
the Apache License, Version 2.0.
|
||||
|
||||
|
||||
-----
|
||||
Code under:
|
||||
src/com/google/javascript/rhino
|
||||
test/com/google/javascript/rhino
|
||||
|
||||
URL: http://www.mozilla.org/rhino
|
||||
Version: 1.5R3, with heavy modifications
|
||||
License: Netscape Public License and MPL / GPL dual license
|
||||
|
||||
Description: A partial copy of Mozilla Rhino. Mozilla Rhino is an
|
||||
implementation of JavaScript for the JVM. The JavaScript parser and
|
||||
the parse tree data structures were extracted and modified
|
||||
significantly for use by Google's JavaScript compiler.
|
||||
|
||||
Local Modifications: The packages have been renamespaced. All code not
|
||||
relavant to parsing has been removed. A JSDoc parser and static typing
|
||||
system have been added.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/libtrunk_rhino_parser_jarjared.jar
|
||||
|
||||
Rhino
|
||||
URL: http://www.mozilla.org/rhino
|
||||
Version: Trunk
|
||||
License: Netscape Public License and MPL / GPL dual license
|
||||
|
||||
Description: Mozilla Rhino is an implementation of JavaScript for the JVM.
|
||||
|
||||
Local Modifications: None. We've used JarJar to renamespace the code
|
||||
post-compilation. See:
|
||||
http://code.google.com/p/jarjar/
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/args4j_deploy.jar
|
||||
|
||||
Args4j
|
||||
URL: https://args4j.dev.java.net/
|
||||
Version: 2.0.9
|
||||
License: MIT
|
||||
|
||||
Description:
|
||||
args4j is a small Java class library that makes it easy to parse command line
|
||||
options/arguments in your CUI application.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/google_common_deploy.jar
|
||||
|
||||
Guava Libraries
|
||||
URL: http://code.google.com/p/guava-libraries/
|
||||
Version: Trunk
|
||||
License: Apache License 2.0
|
||||
|
||||
Description: Google's core Java libraries.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/hamcrest-core-1.1.jar
|
||||
|
||||
Hamcrest
|
||||
URL: http://code.google.com/p/hamcrest
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
|
||||
Description:
|
||||
Provides a library of matcher objects (also known as constraints or
|
||||
predicates) allowing 'match' rules to be defined declaratively, to be used in
|
||||
other frameworks. Typical scenarios include testing frameworks, mocking
|
||||
libraries and UI validation rules.
|
||||
|
||||
Local modifications:
|
||||
The original jars contained both source code and compiled classes.
|
||||
|
||||
hamcrest-core-1.1.jar just contains the compiled classes.
|
||||
|
||||
|
||||
----
|
||||
Code in:
|
||||
lib/junit.jar
|
||||
|
||||
JUnit
|
||||
URL: http://sourceforge.net/projects/junit/
|
||||
Version: 4.5
|
||||
License: Common Public License 1.0
|
||||
|
||||
Description: A framework for writing and running automated tests in Java.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
---
|
||||
Code in:
|
||||
lib/protobuf_deploy.jar
|
||||
|
||||
Protocol Buffers
|
||||
URL: http://code.google.com/p/protobuf/
|
||||
Version: 2.2.0a
|
||||
License: New BSD License
|
||||
|
||||
Description: Supporting libraries for protocol buffers,
|
||||
an encoding of structured data.
|
||||
|
||||
Local Modifications: None
|
||||
|
||||
|
||||
---
|
||||
Code in:
|
||||
lib/ant_deploy.jar
|
||||
|
||||
URL: http://ant.apache.org/bindownload.cgi
|
||||
Version: 1.6.5
|
||||
License: Apache License 2.0
|
||||
Description:
|
||||
Ant is a Java based build tool. In theory it is kind of like "make"
|
||||
without make's wrinkles and with the full portability of pure java code.
|
||||
|
||||
Local Modifications:
|
||||
Modified apache-ant-1.6.5/bin/ant to look in the ant.runfiles directory
|
Двоичный файл не отображается.
|
@ -0,0 +1,4 @@
|
|||
Mozilla Rhino (js.jar from http://www.mozilla.org/rhino/) was
|
||||
initially developed by Netscape Communications Corporation and is
|
||||
provided by the Dojo Foundation "as is" under the MPL 1.1 license,
|
||||
available at http://www.mozilla.org/MPL
|
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* @license RequireJS i18n Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*jslint regexp: false, nomen: false, plusplus: false */
|
||||
/*global require: false, navigator: false, define: false */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This plugin handles i18n! prefixed modules. It does the following:
|
||||
*
|
||||
* 1) A regular module can have a dependency on an i18n bundle, but the regular
|
||||
* module does not want to specify what locale to load. So it just specifies
|
||||
* the top-level bundle, like "i18n!nls/colors".
|
||||
*
|
||||
* This plugin will load the i18n bundle at nls/colors, see that it is a root/master
|
||||
* bundle since it does not have a locale in its name. It will then try to find
|
||||
* the best match locale available in that master bundle, then request all the
|
||||
* locale pieces for that best match locale. For instance, if the locale is "en-us",
|
||||
* then the plugin will ask for the "en-us", "en" and "root" bundles to be loaded
|
||||
* (but only if they are specified on the master bundle).
|
||||
*
|
||||
* Once all the bundles for the locale pieces load, then it mixes in all those
|
||||
* locale pieces into each other, then finally sets the context.defined value
|
||||
* for the nls/colors bundle to be that mixed in locale.
|
||||
*
|
||||
* 2) A regular module specifies a specific locale to load. For instance,
|
||||
* i18n!nls/fr-fr/colors. In this case, the plugin needs to load the master bundle
|
||||
* first, at nls/colors, then figure out what the best match locale is for fr-fr,
|
||||
* since maybe only fr or just root is defined for that locale. Once that best
|
||||
* fit is found, all of its locale pieces need to have their bundles loaded.
|
||||
*
|
||||
* Once all the bundles for the locale pieces load, then it mixes in all those
|
||||
* locale pieces into each other, then finally sets the context.defined value
|
||||
* for the nls/fr-fr/colors bundle to be that mixed in locale.
|
||||
*/
|
||||
(function () {
|
||||
//regexp for reconstructing the master bundle name from parts of the regexp match
|
||||
//nlsRegExp.exec("foo/bar/baz/nls/en-ca/foo") gives:
|
||||
//["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
|
||||
//nlsRegExp.exec("foo/bar/baz/nls/foo") gives:
|
||||
//["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
|
||||
//so, if match[5] is blank, it means this is the top bundle definition.
|
||||
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;
|
||||
|
||||
//Helper function to avoid repeating code. Lots of arguments in the
|
||||
//desire to stay functional and support RequireJS contexts without having
|
||||
//to know about the RequireJS contexts.
|
||||
function addPart(locale, master, needed, toLoad, prefix, suffix) {
|
||||
if (master[locale]) {
|
||||
needed.push(locale);
|
||||
if (master[locale] === true || master[locale] === 1) {
|
||||
toLoad.push(prefix + locale + '/' + suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addIfExists(req, locale, toLoad, prefix, suffix) {
|
||||
var fullName = prefix + locale + '/' + suffix;
|
||||
if (require._fileExists(req.nameToUrl(fullName, null))) {
|
||||
toLoad.push(fullName);
|
||||
}
|
||||
}
|
||||
|
||||
define({
|
||||
/**
|
||||
* Called when a dependency needs to be loaded.
|
||||
*/
|
||||
load: function (name, req, onLoad, config) {
|
||||
config = config || {};
|
||||
|
||||
var masterName,
|
||||
match = nlsRegExp.exec(name),
|
||||
prefix = match[1],
|
||||
locale = match[4],
|
||||
suffix = match[5],
|
||||
parts = locale.split("-"),
|
||||
toLoad = [],
|
||||
value = {},
|
||||
i, part, current = "";
|
||||
|
||||
//If match[5] is blank, it means this is the top bundle definition,
|
||||
//so it does not have to be handled. Locale-specific requests
|
||||
//will have a match[4] value but no match[5]
|
||||
if (match[5]) {
|
||||
//locale-specific bundle
|
||||
prefix = match[1];
|
||||
masterName = prefix + suffix;
|
||||
} else {
|
||||
//Top-level bundle.
|
||||
masterName = name;
|
||||
suffix = match[4];
|
||||
locale = config.locale || (config.locale =
|
||||
typeof navigator === "undefined" ? "root" :
|
||||
(navigator.language ||
|
||||
navigator.userLanguage || "root").toLowerCase());
|
||||
parts = locale.split("-");
|
||||
}
|
||||
|
||||
if (config.isBuild) {
|
||||
//Check for existence of all locale possible files and
|
||||
//require them if exist.
|
||||
toLoad.push(masterName);
|
||||
addIfExists(req, "root", toLoad, prefix, suffix);
|
||||
for (i = 0; (part = parts[i]); i++) {
|
||||
current += (current ? "-" : "") + part;
|
||||
addIfExists(req, current, toLoad, prefix, suffix);
|
||||
}
|
||||
req(toLoad);
|
||||
onLoad();
|
||||
} else {
|
||||
//First, fetch the master bundle, it knows what locales are available.
|
||||
req([masterName], function (master) {
|
||||
//Figure out the best fit
|
||||
var needed = [];
|
||||
|
||||
//Always allow for root, then do the rest of the locale parts.
|
||||
addPart("root", master, needed, toLoad, prefix, suffix);
|
||||
for (i = 0; (part = parts[i]); i++) {
|
||||
current += (current ? "-" : "") + part;
|
||||
addPart(current, master, needed, toLoad, prefix, suffix);
|
||||
}
|
||||
|
||||
//Load all the parts missing.
|
||||
req(toLoad, function () {
|
||||
var i, partBundle;
|
||||
for (i = needed.length - 1; i > -1 && (part = needed[i]); i--) {
|
||||
partBundle = master[part];
|
||||
if (partBundle === true || partBundle === 1) {
|
||||
partBundle = req(prefix + part + '/' + suffix);
|
||||
}
|
||||
require.mixin(value, partBundle);
|
||||
}
|
||||
|
||||
//All done, notify the loader.
|
||||
onLoad(value);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* @license RequireJS order Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*jslint nomen: false, plusplus: false */
|
||||
/*global require: false, define: false, window: false, document: false,
|
||||
setTimeout: false */
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
//Sadly necessary browser inference due to differences in the way
|
||||
//that browsers load and execute dynamically inserted javascript
|
||||
//and whether the script/cache method works.
|
||||
//Currently, Gecko and Opera do not load/fire onload for scripts with
|
||||
//type="script/cache" but they execute injected scripts in order
|
||||
//unless the 'async' flag is present.
|
||||
//However, this is all changing in latest browsers implementing HTML5
|
||||
//spec. Firefox nightly supports using the .async true by default, and
|
||||
//if false, then it will execute in order. Favor that test first for forward
|
||||
//compatibility. However, it is unclear if webkit/IE will follow suit.
|
||||
//Latest webkit breaks the script/cache trick.
|
||||
//Test for document and window so that this file can be loaded in
|
||||
//a web worker/non-browser env. It will not make sense to use this
|
||||
//plugin in a non-browser env, but the file should not error out if included
|
||||
//in the allplugins-require.js file, then loaded in a non-browser env.
|
||||
var supportsInOrderExecution = typeof document !== "undefined" &&
|
||||
typeof window !== "undefined" &&
|
||||
(document.createElement("script").async ||
|
||||
(window.opera && Object.prototype.toString.call(window.opera) === "[object Opera]") ||
|
||||
//If Firefox 2 does not have to be supported, then
|
||||
//a better check may be:
|
||||
//('mozIsLocallyAvailable' in window.navigator)
|
||||
("MozAppearance" in document.documentElement.style)),
|
||||
readyRegExp = /^(complete|loaded)$/,
|
||||
waiting = [],
|
||||
cached = {};
|
||||
|
||||
function loadResource(name, req, onLoad) {
|
||||
req([name], function (value) {
|
||||
//The value may be a real defined module. Wrap
|
||||
//it in a function call, because this function is used
|
||||
//as the factory function for this ordered dependency.
|
||||
onLoad(function () {
|
||||
return value;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//Callback used by the type="script/cache" callback that indicates a script
|
||||
//has finished downloading.
|
||||
function scriptCacheCallback(evt) {
|
||||
var node = evt.currentTarget || evt.srcElement, i,
|
||||
moduleName, resource;
|
||||
|
||||
if (evt.type === "load" || readyRegExp.test(node.readyState)) {
|
||||
//Pull out the name of the module and the context.
|
||||
moduleName = node.getAttribute("data-requiremodule");
|
||||
|
||||
//Mark this cache request as loaded
|
||||
cached[moduleName] = true;
|
||||
|
||||
//Find out how many ordered modules have loaded
|
||||
for (i = 0; (resource = waiting[i]); i++) {
|
||||
if (cached[resource.name]) {
|
||||
loadResource(resource.name, resource.req, resource.onLoad);
|
||||
} else {
|
||||
//Something in the ordered list is not loaded,
|
||||
//so wait.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//If just loaded some items, remove them from waiting.
|
||||
if (i > 0) {
|
||||
waiting.splice(0, i);
|
||||
}
|
||||
|
||||
//Remove this script tag from the DOM
|
||||
//Use a setTimeout for cleanup because some older IE versions vomit
|
||||
//if removing a script node while it is being evaluated.
|
||||
setTimeout(function () {
|
||||
node.parentNode.removeChild(node);
|
||||
}, 15);
|
||||
}
|
||||
}
|
||||
|
||||
define({
|
||||
load: function (name, req, onLoad, config) {
|
||||
var url = req.nameToUrl(name, null);
|
||||
|
||||
//If a build, just load the module as usual.
|
||||
if (config.isBuild) {
|
||||
loadResource(name, req, onLoad);
|
||||
return;
|
||||
}
|
||||
|
||||
//Make sure the async attribute is not set for any pathway involving
|
||||
//this script.
|
||||
require.s.skipAsync[url] = true;
|
||||
if (supportsInOrderExecution) {
|
||||
//Just a normal script tag append, but without async attribute
|
||||
//on the script.
|
||||
req([name], function (value) {
|
||||
//The value may be a real defined module. Wrap
|
||||
//it in a function call, because this function is used
|
||||
//as the factory function for this ordered dependency.
|
||||
onLoad(function () {
|
||||
return value;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
//Credit to LABjs author Kyle Simpson for finding that scripts
|
||||
//with type="script/cache" allow scripts to be downloaded into
|
||||
//browser cache but not executed. Use that
|
||||
//so that subsequent addition of a real type="text/javascript"
|
||||
//tag will cause the scripts to be executed immediately in the
|
||||
//correct order.
|
||||
if (req.isDefined(name)) {
|
||||
req([name], function (value) {
|
||||
//The value may be a real defined module. Wrap
|
||||
//it in a function call, because this function is used
|
||||
//as the factory function for this ordered dependency.
|
||||
onLoad(function () {
|
||||
return value;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
waiting.push({
|
||||
name: name,
|
||||
req: req,
|
||||
onLoad: onLoad
|
||||
});
|
||||
require.attach(url, "", name, scriptCacheCallback, "script/cache");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @license RequireJS rhino Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*global require: false, readFile: false */
|
||||
|
||||
/*
|
||||
TODO: Work out relative paths, that use ./ and such, and allow loading normal
|
||||
CommonJS modules, by overriding require.get().
|
||||
*/
|
||||
|
||||
/*globals load: false, java: false */
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
|
||||
var fileUtil = {
|
||||
backSlashRegExp: /\\/g,
|
||||
|
||||
getLineSeparator: function () {
|
||||
return java.lang.System.getProperty("line.separator"); //Java String
|
||||
}
|
||||
};
|
||||
|
||||
require.load = function (context, moduleName, url) {
|
||||
//isDone is used by require.ready()
|
||||
require.s.isDone = false;
|
||||
|
||||
//Indicate a the module is in process of loading.
|
||||
context.loaded[moduleName] = false;
|
||||
context.scriptCount += 1;
|
||||
|
||||
load(url);
|
||||
|
||||
//Support anonymous modules.
|
||||
context.completeLoad(moduleName);
|
||||
};
|
||||
|
||||
//Adapter to get text plugin to work.
|
||||
require.fetchText = function (url, callback) {
|
||||
var encoding = "utf-8",
|
||||
file = new java.io.File(url),
|
||||
lineSeparator = fileUtil.getLineSeparator(),
|
||||
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
|
||||
stringBuffer, line,
|
||||
content = '';
|
||||
try {
|
||||
stringBuffer = new java.lang.StringBuffer();
|
||||
line = input.readLine();
|
||||
|
||||
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
||||
// http://www.unicode.org/faq/utf_bom.html
|
||||
|
||||
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
|
||||
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
|
||||
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
||||
// Eat the BOM, since we've already found the encoding on this file,
|
||||
// and we plan to concatenating this buffer with others; the BOM should
|
||||
// only appear at the top of a file.
|
||||
line = line.substring(1);
|
||||
}
|
||||
|
||||
stringBuffer.append(line);
|
||||
|
||||
while ((line = input.readLine()) !== null) {
|
||||
stringBuffer.append(lineSeparator);
|
||||
stringBuffer.append(line);
|
||||
}
|
||||
//Make sure we return a JavaScript string and not a Java string.
|
||||
content = String(stringBuffer.toString()); //String
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
callback(content);
|
||||
};
|
||||
|
||||
}());
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* @license RequireJS text Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*jslint regexp: false, nomen: false, plusplus: false */
|
||||
/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
|
||||
define: false */
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
|
||||
xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
|
||||
bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
|
||||
buildMap = [];
|
||||
|
||||
if (!require.textStrip) {
|
||||
require.textStrip = function (text) {
|
||||
//Strips <?xml ...?> declarations so that external SVG and XML
|
||||
//documents can be added to a document without worry. Also, if the string
|
||||
//is an HTML document, only the part inside the body tag is returned.
|
||||
if (text) {
|
||||
text = text.replace(xmlRegExp, "");
|
||||
var matches = text.match(bodyRegExp);
|
||||
if (matches) {
|
||||
text = matches[1];
|
||||
}
|
||||
} else {
|
||||
text = "";
|
||||
}
|
||||
return text;
|
||||
};
|
||||
}
|
||||
|
||||
if (!require.jsEscape) {
|
||||
require.jsEscape = function (text) {
|
||||
return text.replace(/(['\\])/g, '\\$1')
|
||||
.replace(/[\f]/g, "\\f")
|
||||
.replace(/[\b]/g, "\\b")
|
||||
.replace(/[\n]/g, "\\n")
|
||||
.replace(/[\t]/g, "\\t")
|
||||
.replace(/[\r]/g, "\\r");
|
||||
};
|
||||
}
|
||||
|
||||
//Upgrade require to add some methods for XHR handling. But it could be that
|
||||
//this require is used in a non-browser env, so detect for existing method
|
||||
//before attaching one.
|
||||
if (!require.getXhr) {
|
||||
require.getXhr = function () {
|
||||
//Would love to dump the ActiveX crap in here. Need IE 6 to die first.
|
||||
var xhr, i, progId;
|
||||
if (typeof XMLHttpRequest !== "undefined") {
|
||||
return new XMLHttpRequest();
|
||||
} else {
|
||||
for (i = 0; i < 3; i++) {
|
||||
progId = progIds[i];
|
||||
try {
|
||||
xhr = new ActiveXObject(progId);
|
||||
} catch (e) {}
|
||||
|
||||
if (xhr) {
|
||||
progIds = [progId]; // so faster next time
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!xhr) {
|
||||
throw new Error("require.getXhr(): XMLHttpRequest not available");
|
||||
}
|
||||
|
||||
return xhr;
|
||||
};
|
||||
}
|
||||
|
||||
if (!require.fetchText) {
|
||||
require.fetchText = function (url, callback) {
|
||||
var xhr = require.getXhr();
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onreadystatechange = function (evt) {
|
||||
//Do not explicitly handle errors, those should be
|
||||
//visible via console output in the browser.
|
||||
if (xhr.readyState === 4) {
|
||||
callback(xhr.responseText);
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
};
|
||||
}
|
||||
|
||||
define({
|
||||
load: function (name, req, onLoad, config) {
|
||||
//Name has format: some.module.filext!strip
|
||||
//The strip part is optional.
|
||||
//if strip is present, then that means only get the string contents
|
||||
//inside a body tag in an HTML string. For XML/SVG content it means
|
||||
//removing the <?xml ...?> declarations so the content can be inserted
|
||||
//into the current doc without problems.
|
||||
|
||||
var strip = false, url, index = name.indexOf("."),
|
||||
modName = name.substring(0, index),
|
||||
ext = name.substring(index + 1, name.length);
|
||||
|
||||
index = ext.indexOf("!");
|
||||
if (index !== -1) {
|
||||
//Pull off the strip arg.
|
||||
strip = ext.substring(index + 1, ext.length);
|
||||
strip = strip === "strip";
|
||||
ext = ext.substring(0, index);
|
||||
}
|
||||
|
||||
//Load the text.
|
||||
url = req.nameToUrl(modName, "." + ext);
|
||||
require.fetchText(url, function (text) {
|
||||
text = strip ? require.textStrip(text) : text;
|
||||
if (config.isBuild && config.inlineText) {
|
||||
buildMap[name] = text;
|
||||
}
|
||||
onLoad(text);
|
||||
});
|
||||
},
|
||||
|
||||
write: function (pluginName, moduleName, write) {
|
||||
if (moduleName in buildMap) {
|
||||
var text = require.jsEscape(buildMap[moduleName]);
|
||||
write("define('" + pluginName + "!" + moduleName +
|
||||
"', function () { return '" + text + "';});\n");
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
|
@ -0,0 +1 @@
|
|||
0.4.0
|
Загрузка…
Ссылка в новой задаче