raptor
Version:
RaptorJS provides an AMD module loader that works in Node, Rhino and the web browser. It also includes various sub-modules to support building optimized web applications.
489 lines (387 loc) • 17.8 kB
JavaScript
define.Class(
"raptor/optimizer/Config",
['raptor'],
function(raptor, require) {
"use strict";
var strings = require('raptor/strings'),
BundleMappings = require('raptor/optimizer/BundleMappings'),
promises = require('raptor/promises'),
listeners = require('raptor/listeners'),
// allow whitespace and comma to separate values (used for locales)
localesSeparator = /(?:\s*,\s*|\s+)/;
var Config = function(params) {
this.configResource = null;
this.outputDir = null;
this.bundlingEnabled = true;
this.checksumsEnabled = true;
this.enabledProfiles = {};
this.urlPrefix = null;
this.enabledExtensions = require('raptor/packaging').createExtensionCollection();
this.params = {};
this.bundleSetConfigsByName = {};
this.inPlaceDeploymentEnabled = false;
this.serverSourceMappings = [];
this.pageConfigs = [];
this.pageConfigsByName = {};
this.checksumLength = 8;
this.filters = [];
this.bundlingEnabled = true;
this.minifyJs = false;
this.minifyCss = false;
this.basePath = null;
this.writer = null;
this.includeSlotNameForBundles = false;
this.plugins = [];
this.pluginsObservable = listeners.createObservable();
this.enabledLocales = undefined;
/*
* The PageOptimizer Config does not have any wrappers enabled by default.
* If wrappers are explicitly set then this value will be an object whose
* keys are wrapper IDs and whose values are boolean values that indicate
* whether or not that specific wrapper is enabled.
*/
this.bundleWrappers = undefined;
if (params) {
raptor.extend(this.params, params);
}
};
Config.prototype = {
getPageConfig: function(name) {
return this.pageConfigsByName[name];
},
setUrlPrefix: function(urlPrefix) {
this.urlPrefix = urlPrefix;
},
addPlugin: function(pluginConfig) {
var plugin;
var module = pluginConfig.module;
var inputConfig = pluginConfig.config;
if (module) {
if (typeof module === 'string') {
module = require(module);
}
if (module.create) {
plugin = module.create(this);
}
else {
plugin = module;
}
}
var config = plugin.config || (plugin.config = {});
if (inputConfig) {
for (var name in inputConfig) {
if (inputConfig.hasOwnProperty(name)) {
config[name] = inputConfig[name];
}
}
}
for (var key in plugin) {
if (key.startsWith('on')) {
var message = key.substring(2);
message = message.charAt(0).toLowerCase() + message.substring(1);
this.pluginSubscribe(message, plugin[key], plugin);
}
}
this.plugins.push(plugin);
},
pluginSubscribe: function(message, callback, thisObj) {
return this.pluginsObservable.subscribe(message, callback, thisObj);
},
notifyPlugins: function(message, eventArgs) {
this.pluginsObservable.publish(message, eventArgs);
},
enableJSMinification: function() {
this.addFilter("raptor/optimizer/MinifyJSFilter");
},
enableCSSMinification: function() {
this.addFilter("raptor/optimizer/MinifyCSSFilter");
},
enableResolveCSSUrlFilter: function() {
this.addFilter("raptor/optimizer/ResolveCSSUrlsFilter");
},
addFilter: function(filter) {
var filterFunc,
filterThisObj,
filterName,
filterContentType;
if (typeof filter === 'string') {
filter = {
className: filter
};
}
if (typeof filter === 'function') {
}
else if (typeof filter === 'object') {
if (filter.className) {
filterName = filter.className;
filter = require(filter.className);
}
}
else {
throw new Error("Invalid filter: " + filter);
}
if (typeof filter === 'function') {
var FilterClass = filter;
filter = new FilterClass();
}
filterFunc = filter.filter;
filterContentType = filter.contentType;
filterThisObj = filter;
if (filterThisObj) {
filterFunc = filterFunc.bind(filterThisObj);
}
filterFunc._name = filterName || filter.name;
filterFunc.contentType = filterContentType;
// Check if the filter has already been added
for (var i=0; i<this.filters.length; i++) {
if (this.filters[i] === filterFunc) {
return;
}
}
this.filters.push(filterFunc);
},
getFilters: function() {
return this.filters;
},
setOutputDir: function(outputDir) {
this.outputDir = outputDir;
},
isChecksumsEnabled: function() {
return this.checksumsEnabled === true;
},
isInPlaceDeploymentEnabled: function() {
return this.inPlaceDeploymentEnabled === true;
},
isBundlingEnabled: function() {
return this.bundlingEnabled;
},
addServerSourceMapping: function(baseDir, urlPrefix) {
this.serverSourceMappings.push({baseDir: baseDir, urlPrefix: urlPrefix});
},
hasServerSourceMappings: function() {
return this.serverSourceMappings.length !== 0;
},
getServerSourceMappings: function() {
return this.serverSourceMappings;
},
getUrlForSourceFile: function(sourceFilePath) {
var path = require('path');
for (var i=0, len=this.serverSourceMappings.length; i<len; i++) {
var mapping = this.serverSourceMappings[i];
if (strings.startsWith(sourceFilePath, mapping.baseDir)) {
var relativePath = path.relative(mapping.baseDir, sourceFilePath);
if (!mapping.urlPrefix.endsWith('/') && !relativePath.startsWith('/')) {
relativePath = '/' + relativePath;
}
return mapping.urlPrefix + relativePath;
}
}
return null;
},
getParam: function(name) {
return this.params[name];
},
getParams: function() {
return this.params;
},
addParam: function(name, value) {
if (this.params.hasOwnProperty(name)) {
return; //Params are only write-once
}
this.params[name] = value;
},
getUrlPrefix: function() {
return this.urlPrefix;
},
getOutputDir: function() {
return this.outputDir;
},
addBundleSetConfig: function(bundleSetConfig) {
var BundleSetConfig = require('raptor/optimizer/BundleSetConfig');
if (!(bundleSetConfig instanceof BundleSetConfig)) {
bundleSetConfig = new BundleSetConfig(bundleSetConfig);
}
if (!bundleSetConfig.name) {
bundleSetConfig.name = "default";
}
if (this.bundleSetConfigsByName[bundleSetConfig.name]) {
throw raptor.createError(new Error('Bundles with name "' + bundleSetConfig.name + '" defined multiple times'));
}
this.bundleSetConfigsByName[bundleSetConfig.name] = bundleSetConfig;
return bundleSetConfig;
},
getBundleSetConfig: function(name) {
return this.bundleSetConfigsByName[name];
},
enableExtension: function(name) {
this.enabledExtensions.add(name);
},
getEnabledExtensions: function() {
return this.enabledExtensions;
},
setEnabledExtensions: function(enabledExtensions) {
this.enabledExtensions = require('raptor/packaging').createExtensionCollection(enabledExtensions);
},
enableMinification: function() {
this.enableJSMinification();
this.enableCSSMinification();
},
enableProfile: function(profileName) {
this.enabledProfiles[profileName] = true;
},
enableProfiles: function(profileNames) {
if (typeof profileNames === 'string') {
profileNames = profileNames.split(/\s*[,;]\s*/);
}
raptor.forEach(profileNames, function(profileName) {
this.enableProfile(profileName);
}, this);
},
setProfile: function(profileName) {
this.enabledProfiles = {};
this.enableProfile(profileName);
},
isProfileEnabled: function(profileName) {
return this.enabledProfiles[profileName] === true;
},
registerPageConfig: function(pageConfig) {
if (!pageConfig.name) {
throw raptor.createError(new Error('name is required for page'));
}
this.pageConfigs.push(pageConfig);
this.pageConfigsByName[pageConfig.name] = pageConfig;
},
setConfigResource: function(configResource) {
this.configResource = configResource;
},
getConfigResource: function() {
return this.configResource;
},
getChecksumLength: function() {
return this.checksumLength;
},
createBundleMappings: function(bundleSetConfig, context) {
var BundleSetConfig = require('raptor/optimizer/BundleSetConfig'),
BundleConfig = require('raptor/optimizer/BundleConfig'),
bundleMappings = new BundleMappings(context);
var config = this,
addBundles = function(o) {
var promise;
try
{
if (o.enabled === false) {
// No-op
}
else if (o.ref) {
var referencedBundleSetConfig = config.getBundleSetConfig(o.ref);
if (!referencedBundleSetConfig) {
throw raptor.createError(new Error('Bundles not found with name "' + o.ref + '"'));
}
promise = addBundles(referencedBundleSetConfig);
}
else if (o instanceof BundleConfig) {
var bundleName = o.name;
if (!bundleName) {
throw raptor.createError(new Error("Illegal state. Bundle name is required"));
}
promise = bundleMappings.addDependenciesToBundle(
o.dependencies,
bundleName,
o.checksumsEnabled,
o.wrappers);
}
else if (o instanceof BundleSetConfig) {
var promiseChain = null;
o.forEachChild(function(child) {
function addBundlesForChild() {
return addBundles(child);
}
if (promiseChain) {
promiseChain = promiseChain.then(addBundlesForChild);
}
else {
promiseChain = addBundlesForChild();
}
});
promise = promiseChain;
}
if (!promise) {
var deferred = promises.defer();
deferred.resolve();
promise = deferred.promise;
}
return promise;
}
catch(e) {
throw raptor.createError(new Error('Unable to build bundle mappings for "' + bundleSetConfig.name + '" in optimizer configuration. Exception: ' + e), e);
}
};
var promise = addBundles(bundleSetConfig);
var deferred = promises.defer();
promise
.then(function() {
deferred.resolve(bundleMappings);
})
.fail(function(e) {
deferred.reject(e);
});
return deferred.promise;
},
parseXml: function(xml, configFilePath) {
var ConfigXmlParser = require('raptor/optimizer/ConfigXmlParser');
var parser = new ConfigXmlParser();
parser.parse(xml, configFilePath, this);
},
forEachPageConfig: function(callback, thisObj) {
this.pageConfigs.forEach(callback, thisObj);
},
setChecksumsEnabled: function(checksumsEnabled) {
this.checksumsEnabled = checksumsEnabled;
},
setInPlaceDeploymentEnabled: function(inPlaceDeploymentEnabled) {
this.inPlaceDeploymentEnabled = inPlaceDeploymentEnabled;
},
getBasePath: function() {
return this.basePath;
},
setBasePath: function(basePath) {
this.basePath = basePath;
},
getWriter: function() {
return this.writer;
},
setWriter: function(writer) {
this.writer = writer;
},
addLocales: function(locales) {
if (this.enabledLocales === undefined) {
this.enabledLocales = {};
}
if (!locales) {
return;
}
if (!Array.isArray(locales)) {
locales = locales.split(localesSeparator);
}
for (var i = 0; i < locales.length; i++) {
this.enabledLocales[locales[i]] = true;
}
},
getLocales: function() {
return this.enabledLocales ? Object.keys(this.enabledLocales) : undefined;
},
enableBundleWrapper: function(wrapperId) {
if (!this.bundleWrappers) {
this.bundleWrappers = {};
}
this.bundleWrappers[wrapperId] = true;
},
disableBundleWrapper: function(wrapperId) {
if (!this.bundleWrappers) {
this.bundleWrappers = {};
}
this.bundleWrappers[wrapperId] = false;
}
};
return Config;
});