First pass at JS optimization, and hide share ui until jquery ui tabs transform the dom, to avoid seeing a blink of all tabs in the UI. Needs a bit more work to make sure makefile changes work for Gozer's process.
This commit is contained in:
Родитель
419d8ca926
Коммит
dfc49680d0
|
@ -13,3 +13,5 @@ development.db
|
|||
^grinder/.*\.log.*
|
||||
^grinder/.*-file-store
|
||||
^grinder/.*\$py.class
|
||||
web-static
|
||||
|
||||
|
|
12
Makefile
12
Makefile
|
@ -6,6 +6,10 @@ srcdir=$(TOPSRCDIR)/extensions/firefox-share/src/
|
|||
objdir=$(TOPSRCDIR)/extensions/firefox-share/dist/
|
||||
stage_dir=$(objdir)/stage
|
||||
xpi_dir=$(TOPSRCDIR)/web
|
||||
web_dir=$(TOPSRCDIR)/web
|
||||
static_dir=$(TOPSRCDIR)/web-static
|
||||
webbuild_dir=$(TOPSRCDIR)/tools/webbuild
|
||||
requirejs_dir=$(webbuild_dir)/requirejs
|
||||
|
||||
version := 0.1
|
||||
|
||||
|
@ -57,7 +61,15 @@ $(xpi_dir)/$(xpi_name): $(xpi_dir) $(stage_dir) $(dep_files)
|
|||
cd $(stage_dir) && zip -9r $(xpi_name) $(xpi_files)
|
||||
mv $(stage_dir)/$(xpi_name) $(xpi_dir)/$(xpi_name)
|
||||
|
||||
web: $(static_dir)
|
||||
|
||||
$(static_dir):
|
||||
cp -r $(web_dir) $(static_dir)
|
||||
cd $(webbuild_dir) && $(requirejs_dir)/build/build.sh share.build.js
|
||||
cd $(webbuild_dir) && $(requirejs_dir)/build/build.sh frontpage.build.js
|
||||
|
||||
clean:
|
||||
rm -rf $(objdir)
|
||||
rm -rf $(static_dir)
|
||||
|
||||
.PHONY: xpi clean
|
||||
|
|
|
@ -24,7 +24,6 @@ Tasks:
|
|||
|
||||
* Do a build, preseed the UI so it is fast on first click. And just snap down the - James
|
||||
UI right away instead of waiting for load? Then in that case skip the animation.
|
||||
Also hide the UI until the jquery UI has been rendered, so don't see all tabs shown.
|
||||
|
||||
* Instructions: want honest feedback on if they would recommend. - Andy
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
baseUrl: "../../web-static/scripts/",
|
||||
paths: {
|
||||
"index": "../frontpage/index",
|
||||
"jquery": "requireplugins-jquery-1.4.2"
|
||||
},
|
||||
name: "index",
|
||||
exclude: ['jquery'],
|
||||
out: '../../web-static/frontpage/index.js'
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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,178 @@
|
|||
/*
|
||||
* 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("requireExcludeModify", pragmas.requireExcludeModify);
|
||||
//>>excludeEnd("requireExcludeModify");
|
||||
//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,
|
||||
//Remove require.modify() code
|
||||
requireExcludeModify: true,
|
||||
//Remove plugin support from require. The i18n! jsonp! order! and
|
||||
//text! extensions will not work.
|
||||
requireExcludePlugin: true,
|
||||
//Remove the page loaded detection.
|
||||
requireExcludePageLoad: true
|
||||
},
|
||||
|
||||
//Skip processing for pragmas.
|
||||
skipPragmas: false,
|
||||
|
||||
//If execModules is true, each script is execute in
|
||||
//full to find the require calls/dependencies, but the code is executed
|
||||
//in the Rhino JavaScript environment. Set this value to true only
|
||||
//if the code follows the strict require pattern of wrapping all
|
||||
//code in a require callback. If you are using jQuery, Prototype or MooTools
|
||||
//you should not set this value to true. Default is false.
|
||||
execModules: 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: {
|
||||
requireExcludeModify: 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,652 @@
|
|||
/**
|
||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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 */
|
||||
|
||||
"use strict";
|
||||
|
||||
var build, buildBaseConfig;
|
||||
(function () {
|
||||
buildBaseConfig = {
|
||||
requireBuildPath: "../",
|
||||
appDir: "",
|
||||
pragmas: {},
|
||||
paths: {},
|
||||
optimize: "closure",
|
||||
optimizeCss: "standard.keepLines",
|
||||
inlineText: true,
|
||||
execModules: false
|
||||
};
|
||||
|
||||
build = function (args) {
|
||||
var requireBuildPath, buildFile, baseUrlFile, buildPaths, deps, fileName, fileNames,
|
||||
prop, props, paths, path, i, fileContents, buildFileContents = "",
|
||||
doClosure, requireContents, pluginContents, pluginBuildFileContents,
|
||||
baseConfig, override, builtRequirePath, cmdConfig, config,
|
||||
modules, module, moduleName, builtModule;
|
||||
|
||||
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) {
|
||||
config.dirBaseUrl = config.dir + config.baseUrl;
|
||||
config.baseUrl = config.appDir + config.baseUrl;
|
||||
//All the paths should be inside the appDir
|
||||
buildPaths = paths;
|
||||
} else {
|
||||
config.dirBaseUrl = config.dir;
|
||||
//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, "/");
|
||||
//Copy files to build area. Copy all files (the /\w/ regexp)
|
||||
fileUtil.copyDir(paths[prop], 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
|
||||
});
|
||||
modules = config.modules;
|
||||
|
||||
if (modules) {
|
||||
modules.forEach(function (module) {
|
||||
if (module.name) {
|
||||
module._sourcePath = require.nameToUrl(module.name, null, require.s.ctxName);
|
||||
//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 = require.nameToUrl(module.name, null, require.s.ctxName);
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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.
|
||||
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 (!config.buildFile.exists()) {
|
||||
throw new Error("ERROR: build file does not exist: " + config.buildFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
config.baseUrl = fileUtil.absPath(config.buildFile.getParentFile());
|
||||
config.buildFile = fileUtil.absPath(config.buildFile);
|
||||
config.dir = config.baseUrl + "/build/";
|
||||
|
||||
//Load build file options.
|
||||
buildFileContents = fileUtil.readFile(config.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 {
|
||||
//Base URL is relative to the in file.
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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] += "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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[require.s.ctxName],
|
||||
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 = require.s.contexts[require.s.ctxName].specified;
|
||||
|
||||
//Add any other files that did not have an explicit name on them.
|
||||
//These are files that do not call back into require when loaded.
|
||||
for (prop in layer.buildPathMap) {
|
||||
if (layer.buildPathMap.hasOwnProperty(prop)) {
|
||||
url = layer.buildPathMap[prop];
|
||||
//Always store the url to module name mapping for use later,
|
||||
//particularly for anonymous modules and tracking down files that
|
||||
//did not call require.def to define a module
|
||||
layer.buildFileToModule[url] = prop;
|
||||
|
||||
if (!layer.loadedFiles[url]) {
|
||||
//Do not add plugins to build file paths since they will
|
||||
//be added later, near the top of the module layer.
|
||||
if (prop.indexOf("require/") !== 0) {
|
||||
layer.buildFilePaths.push(url);
|
||||
}
|
||||
layer.loadedFiles[url] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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 = "",
|
||||
pluginContents = "", pluginBuildFileContents = "", includeRequire,
|
||||
anonDefRegExp = /require\s*\.\s*def\s*\(\s*(\[|f|\{)/,
|
||||
prop, path, reqIndex, fileContents, currContents,
|
||||
i, moduleName, specified, deps;
|
||||
|
||||
//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 = "";
|
||||
pluginContents = "";
|
||||
pluginBuildFileContents = "";
|
||||
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";
|
||||
}
|
||||
|
||||
//Check for any plugins loaded, and hoist to the top, but below
|
||||
//the require() definition.
|
||||
specified = layer.specified;
|
||||
for (prop in specified) {
|
||||
if (specified.hasOwnProperty(prop)) {
|
||||
if (prop.indexOf("require/") === 0) {
|
||||
path = layer.buildPathMap[prop];
|
||||
if (path) {
|
||||
pluginBuildFileContents += path.replace(config.dir, "") + "\n";
|
||||
pluginContents += pragma.process(path, fileUtil.readFile(path), config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (includeRequire) {
|
||||
//require.js will be included so the plugins will appear right after it.
|
||||
buildFileContents += pluginBuildFileContents;
|
||||
}
|
||||
|
||||
//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];
|
||||
|
||||
//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, suffix) {
|
||||
layer.modulesWithNames[moduleName] = true;
|
||||
|
||||
//Look for CommonJS require calls inside the function if this is
|
||||
//an anonymous 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;
|
||||
}
|
||||
}
|
||||
|
||||
//Adust module name if it is for a plugin
|
||||
if (require.s.contexts._.defPlugin[moduleName]) {
|
||||
moduleName = require.s.contexts._.defPlugin[moduleName] + '!' + moduleName;
|
||||
//Mark that it is a module with a name so do not need
|
||||
//a stub name insertion for it later.
|
||||
layer.modulesWithNames[moduleName] = true;
|
||||
}
|
||||
|
||||
return "require.def('" + 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 += 'require.def("' + moduleName + '", function(){});\n';
|
||||
}
|
||||
|
||||
//If we have plugins but are not injecting require.js,
|
||||
//then need to place the plugins after the require definition,
|
||||
//if it was found.
|
||||
if (layer.existingRequireUrl === path && !includeRequire) {
|
||||
fileContents += pluginContents;
|
||||
buildFileContents += pluginBuildFileContents;
|
||||
pluginContents = "";
|
||||
}
|
||||
}
|
||||
|
||||
//Add the require file contents to the head of the file.
|
||||
fileContents = (requireContents ? requireContents + "\n" : "") +
|
||||
(pluginContents ? pluginContents + "\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, GPL 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,173 @@
|
|||
/**
|
||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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\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
|
||||
* require.def call.
|
||||
*
|
||||
* @param {String} fileName the name of the file.
|
||||
*
|
||||
* @param {String} fileContents the contents of a file :)
|
||||
*
|
||||
* @returns {String} the converted contents
|
||||
*/
|
||||
convert: function (moduleName, fileName, fileContents) {
|
||||
//Strip out comments.
|
||||
if (commonJs.useLog) {
|
||||
logger.trace("fileName: " + fileName);
|
||||
}
|
||||
try {
|
||||
var i, deps = [], depName, origDepName, part, pathConverted = {},
|
||||
prop, reqRegExp, 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;
|
||||
|
||||
//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 = 'require.def(["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) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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 |= /\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) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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,356 @@
|
|||
/**
|
||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
|
||||
/*jslint plusplus: false */
|
||||
/*global require: false, java: false, Packages: false, logger: false, fileUtil: false,
|
||||
readFile: false, lang: false */
|
||||
|
||||
"use strict";
|
||||
|
||||
var optimize;
|
||||
|
||||
(function () {
|
||||
var JSSourceFilefromCode,
|
||||
textDepRegExp = /["'](text)\!([^"']+)["']/g,
|
||||
relativeDefRegExp = /require\s*\.\s*def\s*\(\s*['"]([^'"]+)['"]/g,
|
||||
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]);
|
||||
}
|
||||
|
||||
//Adds escape sequences for non-visual characters, double quote and backslash
|
||||
//and surrounds with double quotes to form a valid string literal.
|
||||
//Assumes the string will be in a single quote string value.
|
||||
function jsEscape(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");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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, FLAG_compilation_level, compiler,
|
||||
Compiler = Packages.com.google.javascript.jscomp.Compiler;
|
||||
|
||||
logger.trace("Minifying file: " + fileName);
|
||||
|
||||
//Set up options
|
||||
options = new jscomp.CompilerOptions();
|
||||
options.prettyPrint = keepLines;
|
||||
|
||||
FLAG_compilation_level = flags.Flag.value(jscomp.CompilationLevel.SIMPLE_OPTIMIZATIONS);
|
||||
FLAG_compilation_level.get().setOptionsForCompilationLevel(options);
|
||||
|
||||
//Trigger the compiler
|
||||
Compiler.setLoggingLevel(Packages.java.util.logging.Level.WARNING);
|
||||
compiler = new Compiler();
|
||||
compiler.compile(externSourceFile, jsSourceFile, options);
|
||||
return compiler.toSource();
|
||||
},
|
||||
|
||||
//Inlines text! dependencies.
|
||||
inlineText: function (fileName, fileContents) {
|
||||
return fileContents.replace(textDepRegExp, function (match, prefix, dep, offset) {
|
||||
var parts, modName, ext, strip, content, normalizedName, index,
|
||||
defSegment, defStart, defMatch, tempMatch, defName;
|
||||
|
||||
parts = dep.split("!");
|
||||
modName = parts[0];
|
||||
ext = "";
|
||||
strip = parts[1];
|
||||
content = parts[2];
|
||||
|
||||
//Extension is part of modName
|
||||
index = modName.lastIndexOf(".");
|
||||
if (index !== -1) {
|
||||
ext = modName.substring(index + 1, modName.length);
|
||||
modName = modName.substring(0, index);
|
||||
}
|
||||
|
||||
//Adjust the text path to be a full name, not a relative
|
||||
//one, if needed.
|
||||
normalizedName = modName;
|
||||
if (modName.charAt(0) === ".") {
|
||||
//Need to backtrack an arbitrary amount in the file
|
||||
//to find the require.def call
|
||||
//that includes this relative name, to find what path to use
|
||||
//for the relative part.
|
||||
defStart = offset - 1000;
|
||||
if (defStart < 0) {
|
||||
defStart = 0;
|
||||
}
|
||||
defSegment = fileContents.substring(defStart, offset);
|
||||
|
||||
//Take the last match, the one closest to current text! string.
|
||||
relativeDefRegExp.lastIndex = 0;
|
||||
while ((tempMatch = relativeDefRegExp.exec(defSegment)) !== null) {
|
||||
defMatch = tempMatch;
|
||||
}
|
||||
|
||||
if (!defMatch) {
|
||||
throw new Error("Cannot resolve relative dependency: " + dep + " in file: " + fileName);
|
||||
}
|
||||
|
||||
//Take the last match, the one closest to current text! string.
|
||||
defName = defMatch[1];
|
||||
|
||||
normalizedName = require.normalizeName(modName, defName);
|
||||
}
|
||||
|
||||
if (strip !== "strip") {
|
||||
content = strip;
|
||||
strip = null;
|
||||
}
|
||||
|
||||
if (content) {
|
||||
//Already an inlined resource, return.
|
||||
return match;
|
||||
} else {
|
||||
content = readFile(require.nameToUrl(normalizedName, "." + ext, require.s.ctxName));
|
||||
if (strip) {
|
||||
content = require.textStrip(content);
|
||||
}
|
||||
return "'" + prefix +
|
||||
"!" + modName +
|
||||
(ext ? "." + ext : "") +
|
||||
(strip ? "!strip" : "") +
|
||||
"!" + jsEscape(content) + "'";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
if (config.inlineText && !optimize.textLoaded) {
|
||||
//Make sure text extension is loaded.
|
||||
require(["require/text"]);
|
||||
optimize.textLoaded = true;
|
||||
}
|
||||
|
||||
fileContents = fileUtil.readFile(fileName);
|
||||
|
||||
//Inline text files.
|
||||
if (config.inlineText) {
|
||||
fileContents = optimize.inlineText(fileName, fileContents);
|
||||
}
|
||||
|
||||
//Optimize the JS files if asked.
|
||||
if (doClosure) {
|
||||
fileContents = optimize.closure(fileName,
|
||||
fileContents,
|
||||
(config.optimize.indexOf(".keepLines") !== -1));
|
||||
}
|
||||
|
||||
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, startIndex, endIndex, originalFileContents, fileContents,
|
||||
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,349 @@
|
|||
/**
|
||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 require.def
|
||||
* calls are found.
|
||||
*/
|
||||
parse = function (fileName, fileContents) {
|
||||
//Set up source input
|
||||
var matches = [], result = null,
|
||||
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||
astRoot = compiler.parse(jsSourceFile);
|
||||
|
||||
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 = compiler.parse(jsSourceFile);
|
||||
|
||||
return parse.nodeHasRequire(astRoot);
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds require("") calls inside a CommonJS anonymous module wrapped in a
|
||||
* require.def(function(require, exports, module){}) wrapper. These dependencies
|
||||
* will be added to a modified require.def 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 = compiler.parse(jsSourceFile),
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if a specific node is a valid require or require.def call.
|
||||
* @param {Packages.com.google.javascript.rhino.Node} node
|
||||
*
|
||||
* @returns {String} a JS source string with the valid require call.
|
||||
* Otherwise null.
|
||||
*/
|
||||
parse.parseNode = function (node) {
|
||||
var call, methodName, targetName, name, 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.
|
||||
deps = call.getChildAtIndex(1);
|
||||
if (!validateDeps(deps)) {
|
||||
return null;
|
||||
}
|
||||
return parse.nodeToString(call);
|
||||
|
||||
} 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);
|
||||
|
||||
//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.
|
||||
if (name.getType() === ARRAYLIT) {
|
||||
deps = name;
|
||||
}
|
||||
|
||||
if (deps && !validateDeps(deps)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parse.nodeToString(call);
|
||||
} 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,107 @@
|
|||
/**
|
||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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,
|
||||
|
||||
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 = {
|
||||
profileProperties: {
|
||||
hostenvType: "browser"
|
||||
}
|
||||
};
|
||||
|
||||
//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,170 @@
|
|||
/**
|
||||
* @license RequireJS Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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 */
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
var layer,
|
||||
lineSeparator = java.lang.System.getProperty("line.separator"),
|
||||
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[require.s.ctxName];
|
||||
|
||||
//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.
|
||||
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.
|
||||
require.def = function (name, obj) {
|
||||
if (typeof name === "string" && !require.isArray(obj) && !require.isFunction(obj)) {
|
||||
layer.modulesWithNames[name] = true;
|
||||
}
|
||||
return oldDef.apply(require, arguments);
|
||||
};
|
||||
|
||||
//Override load so that the file paths can be collected.
|
||||
require.load = function (moduleName, contextName) {
|
||||
/*jslint evil: true */
|
||||
var url = require.nameToUrl(moduleName, null, contextName), map,
|
||||
contents,
|
||||
context = require.s.contexts[contextName];
|
||||
context.loaded[moduleName] = false;
|
||||
|
||||
//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 mapping.
|
||||
map = layer.buildPathMap[moduleName] = url;
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//Only eval complete contents if asked, or if it is a require extension.
|
||||
//Otherwise, treat the module as not safe for execution and parse out
|
||||
//the require calls.
|
||||
if (!context.config.execModules && moduleName !== "require/text" && moduleName !== "require/i18n") {
|
||||
//Only find the require parts with [] dependencies and
|
||||
//evaluate those. This path is useful when the code
|
||||
//does not follow the strict require pattern of wrapping all
|
||||
//code in a require callback.
|
||||
contents = parse(url, contents);
|
||||
}
|
||||
|
||||
if (contents) {
|
||||
eval(contents);
|
||||
|
||||
//Support anonymous modules.
|
||||
require.completeLoad(moduleName, context);
|
||||
}
|
||||
}
|
||||
|
||||
//Mark the module loaded.
|
||||
context.loaded[moduleName] = true;
|
||||
require.checkLoaded(contextName);
|
||||
};
|
||||
|
||||
//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.buildFilePaths.push(url);
|
||||
layer.loadedFiles[url] = true;
|
||||
layer.modulesWithNames[name] = true;
|
||||
}
|
||||
};
|
||||
}());
|
|
@ -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,326 @@
|
|||
/**
|
||||
* @license RequireJS i18n Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*jslint regexp: false, nomen: false, plusplus: false */
|
||||
/*global require: false, navigator: 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(\/|$))([^\/]*)\/?([^\/]*)/,
|
||||
empty = {};
|
||||
|
||||
function getWaiting(name, context) {
|
||||
var nlswAry = context.nlsWaiting;
|
||||
return nlswAry[name] ||
|
||||
//Push a new waiting object on the nlsWaiting array, but also put
|
||||
//a shortcut lookup by name to the object on the array.
|
||||
(nlswAry[name] = nlswAry[(nlswAry.push({ _name: name}) - 1)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure all the locale pieces are loaded, and finds the best match
|
||||
* for the requested locale.
|
||||
*/
|
||||
function resolveLocale(masterName, bundle, locale, context) {
|
||||
//Break apart the locale to get the parts.
|
||||
var i, parts, toLoad, nlsw, loc, val, bestLoc = "root";
|
||||
|
||||
parts = locale.split("-");
|
||||
|
||||
//Now see what bundles exist for each country/locale.
|
||||
//Want to walk up the chain, so if locale is en-us-foo,
|
||||
//look for en-us-foo, en-us, en, then root.
|
||||
toLoad = [];
|
||||
|
||||
nlsw = getWaiting(masterName, context);
|
||||
|
||||
for (i = parts.length; i > -1; i--) {
|
||||
loc = i ? parts.slice(0, i).join("-") : "root";
|
||||
val = bundle[loc];
|
||||
if (val) {
|
||||
//Store which bundle to use for the default bundle definition.
|
||||
if (locale === context.config.locale && !nlsw._match) {
|
||||
nlsw._match = loc;
|
||||
}
|
||||
|
||||
//Store the best match for the target locale
|
||||
if (bestLoc === "root") {
|
||||
bestLoc = loc;
|
||||
}
|
||||
|
||||
//Track that the locale needs to be resolved with its parts.
|
||||
//Mark what locale should be used when resolving.
|
||||
nlsw[loc] = loc;
|
||||
|
||||
//If locale value is true, it means it is a resource that
|
||||
//needs to be loaded. Track it to load if it has not already
|
||||
//been asked for.
|
||||
if (val === true) {
|
||||
//split off the bundl name from master name and insert the
|
||||
//locale before the bundle name. So, if masterName is
|
||||
//some/path/nls/colors, then the locale fr-fr's bundle name should
|
||||
//be some/path/nls/fr-fr/colors
|
||||
val = masterName.split("/");
|
||||
val.splice(-1, 0, loc);
|
||||
val = val.join("/");
|
||||
|
||||
if (!context.specified[val] && !(val in context.loaded) && !context.defined[val]) {
|
||||
context.defPlugin[val] = 'i18n';
|
||||
toLoad.push(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If locale was not an exact match, store the closest match for it.
|
||||
if (bestLoc !== locale) {
|
||||
if (context.defined[bestLoc]) {
|
||||
//Already got it. Easy peasy lemon squeezy.
|
||||
context.defined[locale] = context.defined[bestLoc];
|
||||
} else {
|
||||
//Need to wait for things to load then define it.
|
||||
nlsw[locale] = bestLoc;
|
||||
}
|
||||
}
|
||||
|
||||
//Load any bundles that are still needed.
|
||||
if (toLoad.length) {
|
||||
require(toLoad, context.contextName);
|
||||
}
|
||||
}
|
||||
|
||||
require.plugin({
|
||||
prefix: "i18n",
|
||||
|
||||
/**
|
||||
* This callback is prefix-specific, only gets called for this prefix
|
||||
*/
|
||||
require: function (name, deps, callback, context) {
|
||||
var i, match, nlsw, bundle, master, toLoad, obj = context.defined[name];
|
||||
|
||||
//All i18n modules must match the nls module name structure.
|
||||
match = nlsRegExp.exec(name);
|
||||
//If match[5] is blank, it means this is the top bundle definition,
|
||||
//so it does not have to be handled. Only deal with ones that have a locale
|
||||
//(a match[4] value but no match[5])
|
||||
if (match[5]) {
|
||||
master = match[1] + match[5];
|
||||
|
||||
//Track what locale bundle need to be generated once all the modules load.
|
||||
nlsw = getWaiting(master, context);
|
||||
nlsw[match[4]] = match[4];
|
||||
|
||||
bundle = context.nls[master];
|
||||
if (!bundle) {
|
||||
//No master bundle yet, ask for it.
|
||||
context.defPlugin[master] = 'i18n';
|
||||
require([master], context.contextName);
|
||||
bundle = context.nls[master] = {};
|
||||
}
|
||||
//For nls modules, the callback is just a regular object,
|
||||
//so save it off in the bundle now.
|
||||
bundle[match[4]] = callback;
|
||||
} else {
|
||||
//Integrate bundle into the nls area.
|
||||
bundle = context.nls[name];
|
||||
if (bundle) {
|
||||
//A specific locale already started the bundle object.
|
||||
//Do a mixin (which will not overwrite the locale property
|
||||
//on the bundle that has the previously loaded locale's info)
|
||||
require.mixin(bundle, obj);
|
||||
} else {
|
||||
bundle = context.nls[name] = obj;
|
||||
}
|
||||
context.nlsRootLoaded[name] = true;
|
||||
|
||||
//Make sure there are no locales waiting to be resolved.
|
||||
toLoad = context.nlsToLoad[name];
|
||||
if (toLoad) {
|
||||
delete context.nlsToLoad[name];
|
||||
for (i = 0; i < toLoad.length; i++) {
|
||||
resolveLocale(name, bundle, toLoad[i], context);
|
||||
}
|
||||
}
|
||||
|
||||
resolveLocale(name, bundle, context.config.locale, context);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new context is defined. Use this to store
|
||||
* context-specific info on it.
|
||||
*/
|
||||
newContext: function (context) {
|
||||
require.mixin(context, {
|
||||
nlsWaiting: [],
|
||||
nls: {},
|
||||
nlsRootLoaded: {},
|
||||
nlsToLoad: {}
|
||||
});
|
||||
if (!context.config.locale) {
|
||||
context.config.locale = typeof navigator === "undefined" ? "root" :
|
||||
(navigator.language || navigator.userLanguage || "root").toLowerCase();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a dependency needs to be loaded.
|
||||
*/
|
||||
load: function (name, contextName) {
|
||||
//Make sure the root bundle is loaded, to check if we can support
|
||||
//loading the requested locale, or if a different one needs
|
||||
//to be chosen.
|
||||
var masterName, context = require.s.contexts[contextName], bundle,
|
||||
match = nlsRegExp.exec(name), locale = match[4];
|
||||
|
||||
//If match[5] is blank, it means this is the top bundle definition,
|
||||
//so it does not have to be handled. Only deal with ones that have a locale
|
||||
//(a match[4] value but no match[5])
|
||||
if (match[5]) {
|
||||
//locale-specific bundle
|
||||
masterName = match[1] + match[5];
|
||||
bundle = context.nls[masterName];
|
||||
if (context.nlsRootLoaded[masterName] && bundle) {
|
||||
resolveLocale(masterName, bundle, locale, context);
|
||||
} else {
|
||||
//Store this locale to figure out after masterName is loaded and load masterName.
|
||||
(context.nlsToLoad[masterName] || (context.nlsToLoad[masterName] = [])).push(locale);
|
||||
context.defPlugin[masterName] = 'i18n';
|
||||
require([masterName], contextName);
|
||||
}
|
||||
} else {
|
||||
//Top-level bundle. Just call regular load, if not already loaded
|
||||
if (!context.nlsRootLoaded[name]) {
|
||||
context.defPlugin[name] = 'i18n';
|
||||
require.load(name, contextName);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the dependencies of a module are checked.
|
||||
*/
|
||||
checkDeps: function (name, deps, context) {
|
||||
//i18n bundles are always defined as objects for their "dependencies",
|
||||
//and that object is already processed in the require method, no need to
|
||||
//do work in here.
|
||||
},
|
||||
|
||||
/**
|
||||
* Called to determine if a module is waiting to load.
|
||||
*/
|
||||
isWaiting: function (context) {
|
||||
return !!context.nlsWaiting.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when all modules have been loaded.
|
||||
*/
|
||||
orderDeps: function (context) {
|
||||
//Clear up state since further processing could
|
||||
//add more things to fetch.
|
||||
var i, j, master, msWaiting, bundle, parts, moduleSuffix, mixed,
|
||||
modulePrefix, loc, defLoc, locPart, nlsWaiting = context.nlsWaiting,
|
||||
bestFit;
|
||||
context.nlsWaiting = [];
|
||||
context.nlsToLoad = {};
|
||||
|
||||
//First, properly mix in any nls bundles waiting to happen.
|
||||
for (i = 0; (msWaiting = nlsWaiting[i]); i++) {
|
||||
//Each property is a master bundle name.
|
||||
master = msWaiting._name;
|
||||
bundle = context.nls[master];
|
||||
defLoc = null;
|
||||
|
||||
//Create the module name parts from the master name. So, if master
|
||||
//is foo/nls/bar, then the parts should be prefix: "foo/nls",
|
||||
// suffix: "bar", and the final locale's module name will be foo/nls/locale/bar
|
||||
parts = master.split("/");
|
||||
modulePrefix = parts.slice(0, parts.length - 1).join("/");
|
||||
moduleSuffix = parts[parts.length - 1];
|
||||
//Cycle through the locale props on the waiting object and combine
|
||||
//the locales together.
|
||||
for (loc in msWaiting) {
|
||||
if (loc !== "_name" && !(loc in empty)) {
|
||||
if (loc === "_match") {
|
||||
//Found default locale to use for the top-level bundle name.
|
||||
defLoc = msWaiting[loc];
|
||||
|
||||
} else if (msWaiting[loc] !== loc) {
|
||||
//A "best fit" locale, store it off to the end and handle
|
||||
//it at the end by just assigning the best fit value, since
|
||||
//after this for loop, the best fit locale will be defined.
|
||||
(bestFit || (bestFit = {}))[loc] = msWaiting[loc];
|
||||
} else {
|
||||
//Mix in the properties of this locale together.
|
||||
//Split the locale into pieces.
|
||||
mixed = {};
|
||||
parts = loc.split("-");
|
||||
for (j = parts.length; j > 0; j--) {
|
||||
locPart = parts.slice(0, j).join("-");
|
||||
if (locPart !== "root" && bundle[locPart]) {
|
||||
require.mixin(mixed, bundle[locPart]);
|
||||
}
|
||||
}
|
||||
if (bundle.root) {
|
||||
require.mixin(mixed, bundle.root);
|
||||
}
|
||||
|
||||
context.defined[modulePrefix + "/" + loc + "/" + moduleSuffix] = mixed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Finally define the default locale. Wait to the end of the property
|
||||
//loop above so that the default locale bundle has been properly mixed
|
||||
//together.
|
||||
context.defined[master] = context.defined[modulePrefix + "/" + defLoc + "/" + moduleSuffix];
|
||||
|
||||
//Handle any best fit locale definitions.
|
||||
if (bestFit) {
|
||||
for (loc in bestFit) {
|
||||
if (!(loc in empty)) {
|
||||
context.defined[modulePrefix + "/" + loc + "/" + moduleSuffix] = context.defined[modulePrefix + "/" + bestFit[loc] + "/" + moduleSuffix];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* @license RequireJS jsonp Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*jslint nomen: false, plusplus: false */
|
||||
/*global require: false, setTimeout: false */
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
var countId = 0;
|
||||
|
||||
//A place to hold callback functions
|
||||
require._jsonp = {};
|
||||
|
||||
require.plugin({
|
||||
prefix: "jsonp",
|
||||
|
||||
/**
|
||||
* This callback is prefix-specific, only gets called for this prefix
|
||||
*/
|
||||
require: function (name, deps, callback, context) {
|
||||
//No-op, require never gets these jsonp items, they are always
|
||||
//a dependency, see load for the action.
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new context is defined. Use this to store
|
||||
* context-specific info on it.
|
||||
*/
|
||||
newContext: function (context) {
|
||||
require.mixin(context, {
|
||||
jsonpWaiting: []
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a dependency needs to be loaded.
|
||||
*/
|
||||
load: function (name, contextName) {
|
||||
//Name has format: some/url?param1=value1&callback=?
|
||||
//where the last question mark indicates where the jsonp callback
|
||||
//function name needs to go.
|
||||
var index = name.indexOf("?"),
|
||||
url = name.substring(0, index),
|
||||
params = name.substring(index + 1, name.length),
|
||||
context = require.s.contexts[contextName],
|
||||
data = {
|
||||
name: name
|
||||
},
|
||||
funcName = "f" + (countId++),
|
||||
head = require.s.head,
|
||||
node = head.ownerDocument.createElement("script");
|
||||
|
||||
//Create JSONP callback function
|
||||
require._jsonp[funcName] = function (value) {
|
||||
data.value = value;
|
||||
context.loaded[name] = true;
|
||||
require.checkLoaded(contextName);
|
||||
//Use a setTimeout for cleanup because some older IE versions vomit
|
||||
//if removing a script node while it is being evaluated.
|
||||
setTimeout(function () {
|
||||
head.removeChild(node);
|
||||
delete require._jsonp[funcName];
|
||||
}, 15);
|
||||
};
|
||||
|
||||
//Hold on to the data for later dependency resolution in orderDeps.
|
||||
context.jsonpWaiting.push(data);
|
||||
|
||||
//Build up the full JSONP URL
|
||||
url = require.nameToUrl(url, "?", contextName);
|
||||
//nameToUrl call may or may not have placed an ending ? on the URL,
|
||||
//be sure there is one and add the rest of the params.
|
||||
url += (url.indexOf("?") === -1 ? "?" : "") + params.replace("?", "require._jsonp." + funcName);
|
||||
|
||||
context.loaded[name] = false;
|
||||
node.type = "text/javascript";
|
||||
node.charset = "utf-8";
|
||||
node.src = url;
|
||||
|
||||
//Use async so Gecko does not block on executing the script if something
|
||||
//like a long-polling comet tag is being run first. Gecko likes
|
||||
//to evaluate scripts in DOM order, even for dynamic scripts.
|
||||
//It will fetch them async, but only evaluate the contents in DOM
|
||||
//order, so a long-polling script tag can delay execution of scripts
|
||||
//after it. But telling Gecko we expect async gets us the behavior
|
||||
//we want -- execute it whenever it is finished downloading. Only
|
||||
//Helps Firefox 3.6+
|
||||
node.async = true;
|
||||
|
||||
head.appendChild(node);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the dependencies of a module are checked.
|
||||
*/
|
||||
checkDeps: function (name, deps, context) {
|
||||
//No-op, checkDeps never gets these jsonp items, they are always
|
||||
//a dependency, see load for the action.
|
||||
},
|
||||
|
||||
/**
|
||||
* Called to determine if a module is waiting to load.
|
||||
*/
|
||||
isWaiting: function (context) {
|
||||
return !!context.jsonpWaiting.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when all modules have been loaded.
|
||||
*/
|
||||
orderDeps: function (context) {
|
||||
//Clear up state since further processing could
|
||||
//add more things to fetch.
|
||||
var i, dep, waitAry = context.jsonpWaiting;
|
||||
context.jsonpWaiting = [];
|
||||
for (i = 0; (dep = waitAry[i]); i++) {
|
||||
context.defined[dep.name] = dep.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* @license RequireJS order Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*jslint nomen: false, plusplus: false */
|
||||
/*global require: 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.
|
||||
var supportsInOrderExecution = ((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)$/;
|
||||
|
||||
//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,
|
||||
context, contextName, moduleName, waiting, cached;
|
||||
|
||||
if (evt.type === "load" || readyRegExp.test(node.readyState)) {
|
||||
//Pull out the name of the module and the context.
|
||||
contextName = node.getAttribute("data-requirecontext");
|
||||
moduleName = node.getAttribute("data-requiremodule");
|
||||
context = require.s.contexts[contextName];
|
||||
waiting = context.orderWaiting;
|
||||
cached = context.orderCached;
|
||||
|
||||
//Mark this cache request as loaded
|
||||
cached[moduleName] = true;
|
||||
|
||||
//Find out how many ordered modules have loaded
|
||||
for (i = 0; cached[waiting[i]]; i++) {}
|
||||
if (i > 0) {
|
||||
require(waiting.splice(0, i), contextName);
|
||||
}
|
||||
|
||||
//If no other order cache items are in the queue, do some cleanup.
|
||||
if (!waiting.length) {
|
||||
context.orderCached = {};
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
require.plugin({
|
||||
prefix: "order",
|
||||
|
||||
/**
|
||||
* This callback is prefix-specific, only gets called for this prefix
|
||||
*/
|
||||
require: function (name, deps, callback, context) {
|
||||
//No-op, require never gets these order items, they are always
|
||||
//a dependency, see load for the action.
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new context is defined. Use this to store
|
||||
* context-specific info on it.
|
||||
*/
|
||||
newContext: function (context) {
|
||||
require.mixin(context, {
|
||||
orderWaiting: [],
|
||||
orderCached: {}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a dependency needs to be loaded.
|
||||
*/
|
||||
load: function (name, contextName) {
|
||||
var context = require.s.contexts[contextName],
|
||||
url = require.nameToUrl(name, null, contextName);
|
||||
|
||||
//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.
|
||||
require([name], contextName);
|
||||
} 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.
|
||||
context.orderWaiting.push(name);
|
||||
context.loaded[name] = false;
|
||||
require.attach(url, contextName, name, scriptCacheCallback, "script/cache");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the dependencies of a module are checked.
|
||||
*/
|
||||
checkDeps: function (name, deps, context) {
|
||||
//No-op, checkDeps never gets these order items, they are always
|
||||
//a dependency, see load for the action.
|
||||
},
|
||||
|
||||
/**
|
||||
* Called to determine if a module is waiting to load.
|
||||
*/
|
||||
isWaiting: function (context) {
|
||||
return !!context.orderWaiting.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when all modules have been loaded. Not needed for this plugin.
|
||||
* State is reset as part of scriptCacheCallback.
|
||||
*/
|
||||
orderDeps: function (context) {
|
||||
}
|
||||
});
|
||||
}());
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @license RequireJS rhino Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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 */
|
||||
"use strict";
|
||||
|
||||
require.load = function (moduleName, contextName) {
|
||||
var url = require.nameToUrl(moduleName, null, contextName),
|
||||
context = require.s.contexts[contextName];
|
||||
|
||||
//isDone is used by require.ready()
|
||||
require.s.isDone = false;
|
||||
|
||||
//Indicate a the module is in process of loading.
|
||||
context.loaded[moduleName] = false;
|
||||
|
||||
load(url);
|
||||
|
||||
//Support anonymous modules.
|
||||
require.completeLoad(moduleName, context);
|
||||
};
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* @license RequireJS text Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL 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 */
|
||||
"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;
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
//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);
|
||||
};
|
||||
}
|
||||
|
||||
require.plugin({
|
||||
prefix: "text",
|
||||
|
||||
/**
|
||||
* This callback is prefix-specific, only gets called for this prefix
|
||||
*/
|
||||
require: function (name, deps, callback, context) {
|
||||
//No-op, require never gets these text items, they are always
|
||||
//a dependency, see load for the action.
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new context is defined. Use this to store
|
||||
* context-specific info on it.
|
||||
*/
|
||||
newContext: function (context) {
|
||||
require.mixin(context, {
|
||||
text: {},
|
||||
textWaiting: []
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a dependency needs to be loaded.
|
||||
*/
|
||||
load: function (name, contextName) {
|
||||
//Name has format: some.module!filext!strip!text
|
||||
//The strip and text parts are 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.
|
||||
//If text is present, it is the actual text of the file.
|
||||
var strip = false, text = null, key, url, index = name.indexOf("."),
|
||||
modName = name.substring(0, index), fullKey,
|
||||
ext = name.substring(index + 1, name.length),
|
||||
context = require.s.contexts[contextName],
|
||||
tWaitAry = context.textWaiting;
|
||||
|
||||
index = ext.indexOf("!");
|
||||
if (index !== -1) {
|
||||
//Pull off the strip arg.
|
||||
strip = ext.substring(index + 1, ext.length);
|
||||
ext = ext.substring(0, index);
|
||||
index = strip.indexOf("!");
|
||||
if (index !== -1 && strip.substring(0, index) === "strip") {
|
||||
//Pull off the text.
|
||||
text = strip.substring(index + 1, strip.length);
|
||||
strip = "strip";
|
||||
} else if (strip !== "strip") {
|
||||
//strip is actually the inlined text.
|
||||
text = strip;
|
||||
strip = null;
|
||||
}
|
||||
}
|
||||
key = modName + "!" + ext;
|
||||
fullKey = strip ? key + "!" + strip : key;
|
||||
|
||||
//Store off text if it is available for the given key and be done.
|
||||
if (text !== null && !context.text[key]) {
|
||||
context.defined[name] = context.text[key] = text;
|
||||
return;
|
||||
}
|
||||
|
||||
//If text is not available, load it.
|
||||
if (!context.text[key] && !context.textWaiting[key] && !context.textWaiting[fullKey]) {
|
||||
//Keep track that the fullKey needs to be resolved, during the
|
||||
//orderDeps stage.
|
||||
if (!tWaitAry[fullKey]) {
|
||||
tWaitAry[fullKey] = tWaitAry[(tWaitAry.push({
|
||||
name: name,
|
||||
key: key,
|
||||
fullKey: fullKey,
|
||||
strip: !!strip
|
||||
}) - 1)];
|
||||
}
|
||||
|
||||
//Load the text.
|
||||
url = require.nameToUrl(modName, "." + ext, contextName);
|
||||
context.loaded[name] = false;
|
||||
require.fetchText(url, function (text) {
|
||||
context.text[key] = text;
|
||||
context.loaded[name] = true;
|
||||
require.checkLoaded(contextName);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the dependencies of a module are checked.
|
||||
*/
|
||||
checkDeps: function (name, deps, context) {
|
||||
//No-op, checkDeps never gets these text items, they are always
|
||||
//a dependency, see load for the action.
|
||||
},
|
||||
|
||||
/**
|
||||
* Called to determine if a module is waiting to load.
|
||||
*/
|
||||
isWaiting: function (context) {
|
||||
return !!context.textWaiting.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when all modules have been loaded.
|
||||
*/
|
||||
orderDeps: function (context) {
|
||||
//Clear up state since further processing could
|
||||
//add more things to fetch.
|
||||
var i, dep, text, tWaitAry = context.textWaiting;
|
||||
context.textWaiting = [];
|
||||
for (i = 0; (dep = tWaitAry[i]); i++) {
|
||||
text = context.text[dep.key];
|
||||
context.defined[dep.name] = dep.strip ? require.textStrip(text) : text;
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @license RequireJS transportD Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT, GPL or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
/*jslint */
|
||||
/*global require: false */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* An adapter for the CommonJS Transport/D proposal:
|
||||
* http://wiki.commonjs.org/wiki/Modules/Transport/D
|
||||
* NOTE: this integration does NOT support contexts, so only one version in the page.
|
||||
* @param {Object} modules a dictionary of module names with module descriptors
|
||||
* @param [Array] dependencies a list of module names that are dependencies for
|
||||
* all the modules listed in the modules argument.
|
||||
*/
|
||||
require.define = function (modules, dependencies) {
|
||||
var moduleName, descriptor;
|
||||
for (moduleName in modules) {
|
||||
if (modules.hasOwnProperty(moduleName)) {
|
||||
descriptor = modules[moduleName];
|
||||
require.def(
|
||||
moduleName,
|
||||
(descriptor.injects || ["require", "exports", "module"]).concat(dependencies || []),
|
||||
typeof descriptor === "function" ? descriptor : descriptor.factory
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
baseUrl: "../../web-static/scripts/",
|
||||
paths: {
|
||||
"index": "../share/index",
|
||||
"jquery": "requireplugins-jquery-1.4.2"
|
||||
},
|
||||
name: "index",
|
||||
exclude: ['jquery'],
|
||||
out: '../../web-static/share/index.js'
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<title>Linkdrop</title>
|
||||
<script type="text/javascript" data-main="index.js" src="../scripts/requireplugins-jquery-1.4.2.js"></script>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
|
||||
const EXPORTED_SYMBOLS = ["hex_md5"];
|
||||
var EXPORTED_SYMBOLS = ["hex_md5"];
|
||||
|
||||
/*
|
||||
* Configurable variables. You may need to tweak these to be compatible with
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,7 +7,7 @@
|
|||
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
|
||||
<script>require(["index.js"]);</script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="invisible">
|
||||
|
||||
<div id="tabs">
|
||||
|
||||
|
|
|
@ -552,6 +552,9 @@ function (require, $, fn, rdapi, oauth, jig, url,
|
|||
});
|
||||
});
|
||||
|
||||
//Make the body visible now to the user, now that tabs have been set up.
|
||||
bodyDom.removeClass('invisible');
|
||||
|
||||
//In settings, hook up remove buttons to remove an account
|
||||
bodyDom.delegate('.accountRemove', 'click', function (evt) {
|
||||
var buttonNode = evt.target,
|
||||
|
|
|
@ -49,6 +49,10 @@ ul.nav li.hidden {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#tabs {
|
||||
padding: 0 10px;
|
||||
overflow: hidden;
|
||||
|
|
Загрузка…
Ссылка в новой задаче