Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 108 additions & 74 deletions bin/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Copyright(c) 2011 LearnBoost <[email protected]>
* MIT Licensed
*/

/**
* Module dependencies.
*/
Expand All @@ -14,20 +14,22 @@ var fs = require('fs')

/**
* License headers.
*
* @api private
*/

var template = '/*! Socket.IO.%ext% build:' + socket.version + ', %type%. Copyright(c) 2011 LearnBoost <[email protected]> MIT Licensed */\n'
, development = template.replace('%type%', 'development').replace('%ext%', 'js')
, production = template.replace('%type%', 'production').replace('%ext%', 'min.js');

/**
* If statements, these allows you to create serveride & client side compatible code
* using specially designed `if` statements that remove serverside designed code from
* the source files
* If statements, these allows you to create serveride & client side compatible
* code using specially designed `if` statements that remove serverside
* designed code from the source files
*
* @api private
*/

var starttagIF = '// if node'
, endtagIF = '// end node';

Expand All @@ -38,7 +40,7 @@ var starttagIF = '// if node'
* @type {Array}
* @api private
*/

var base = [
'io.js'
, 'util.js'
Expand All @@ -60,47 +62,56 @@ var base = [
* @type {Object}
* @api public
*/
var baseTransports = {

var baseTransports = {
'websocket': ['transports/websocket.js']
, 'flashsocket': [
'transports/websocket.js'
, 'transports/flashsocket.js'
, 'vendor/web-socket-js/swfobject.js'
, 'vendor/web-socket-js/web_socket.js'
'transports/websocket.js'
, 'transports/flashsocket.js'
, 'vendor/web-socket-js/swfobject.js'
, 'vendor/web-socket-js/web_socket.js'
]
, 'htmlfile': ['transports/xhr.js', 'transports/htmlfile.js']
/* FIXME: re-enable me once we have multi-part support
, 'xhr-multipart': ['transports/xhr.js', 'transports/xhr-multipart.js'] */
, 'xhr-polling': ['transports/xhr.js', 'transports/xhr-polling.js']
, 'jsonp-polling': ['transports/xhr.js', 'transports/jsonp-polling.js']
};
, 'jsonp-polling': [
'transports/xhr.js'
, 'transports/xhr-polling.js'
, 'transports/jsonp-polling.js'
]
};

/**
* Builds a custom Socket.IO distribution based on the transports that you need. You
* can configure the build to create development build or production build (minified).
* Builds a custom Socket.IO distribution based on the transports that you
* need. You can configure the build to create development build or production
* build (minified).
*
* @param {Array} transports The transports that needs to be bundled.
* @param {Object} [options] Options to configure the building process.
* @param {Function} callback The argument is always the callback, because the options are.. optional:D.
* @callback {String|Boolean} err An optional argument, if it exists than an error occurred during the build process.
* @param {Function} callback Last argument should always be the callback
* @callback {String|Boolean} err An optional argument, if it exists than an error
* occurred during the build process.
* @callback {String} result The result of the build process.
* @api public
*/
var builder = module.exports = function(){

var builder = module.exports = function () {
var transports, options, callback, error = null
, args = Array.prototype.slice.call(arguments,0)
, args = Array.prototype.slice.call(arguments, 0)
, settings = {
minify: true
, node: false
, custom: []
};

// Fancy pancy argument support
// this makes any pattern possible mainly because we require only one of each type
args.forEach(function(arg){
switch(Object.prototype.toString.call(arg).replace(/\[object\s(\w+)\]/gi , '$1' ).toLowerCase()){

// Fancy pancy argument support this makes any pattern possible mainly
// because we require only one of each type
args.forEach(function (arg) {
var type = Object.prototype.toString.call(arg)
.replace(/\[object\s(\w+)\]/gi , '$1' ).toLowerCase();

switch (type) {
case 'array':
return transports = arg;
case 'object':
Expand All @@ -109,90 +120,102 @@ var builder = module.exports = function(){
return callback = arg;
}
});

// Add defaults
options = options || {};
transports = transports || Object.keys(baseTransports);

// Merge the data
for(var option in options) settings[option] = options[option];

// Start creating a dependencies chain with all the required files for the custom Socket.IO bundle.
for(var option in options) {
settings[option] = options[option];
}

// Start creating a dependencies chain with all the required files for the
// custom Socket.IO bundle.
var files = [];
base.forEach(function(file){
base.forEach(function (file) {
files.push(__dirname + '/../lib/' + file);
});
transports.forEach(function(transport){

transports.forEach(function (transport) {
var dependencies = baseTransports[transport];
if (!dependencies) return error = 'Unsupported transport `' + transport + '` supplied as argument.';

if (!dependencies) {
error = 'Unsupported transport `' + transport + '` supplied as argument.';
return;
}

// Add the files to the files list, but only if they are not added before
dependencies.forEach(function(file){
dependencies.forEach(function (file) {
var path = __dirname + '/../lib/' + file;
if (!~files.indexOf(path)) files.push(path);
})
});

// check to see if the files tree compilation generated any errors.
if (error) return callback(error);

var results = {};
files.forEach(function(file){
fs.readFile(file, function(err, content){
files.forEach(function (file) {
fs.readFile(file, function (err, content) {
if (err) error = err;
results[file] = content;

// check if we are done yet, or not.. Just by checking the size of the result
// object.
if (Object.keys(results).length !== files.length) return;

// we are done, did we error?
if (error) return callback(error);

// concatinate the file contents in order
var code = development
, ignore = 0;
files.forEach(function(file){

files.forEach(function (file) {
code += results[file];
});

// check if we need to add custom code
if (settings.custom.length){
settings.custom.forEach(function(content){
if (settings.custom.length) {
settings.custom.forEach(function (content) {
code += content;
})
});
}

// Search for conditional code blocks that need to be removed as they where designed for
// a server side env. but only if we don't want to make this build node compatible
if (!settings.node){
code = code.split('\n').filter(function(line){

// Search for conditional code blocks that need to be removed as they
// where designed for a server side env. but only if we don't want to
// make this build node compatible.
if (!settings.node) {
code = code.split('\n').filter(function (line) {
// check if there are tags in here
var start = line.indexOf(starttagIF) >= 0
, end = line.indexOf(endtagIF) >= 0
, ret = ignore;

// ignore the current line
if (start) ignore++,ret = ignore;

if (start) {
ignore++;
ret = ignore;
}

// stop ignoring the next line
if (end) ignore--;

if (end) {
ignore--;
}

return ret == 0;
}).join('\n')
}).join('\n');
}

// check if we need to process it any further
if (settings.minify){
if (settings.minify) {
var ast = uglify.parser.parse(code);
ast = uglify.uglify.ast_mangle(ast);
ast = uglify.uglify.ast_squeeze(ast);

code = production + uglify.uglify.gen_code(ast);
}

callback(error, code);
})
})
Expand Down Expand Up @@ -224,21 +247,32 @@ builder.transports = baseTransports;
*/

if (!module.parent){
var args = process.argv.slice(2); // the first 2 are `node` and the path to this file, we don't need them

// the first 2 are `node` and the path to this file, we don't need them
var args = process.argv.slice(2);

// build a development build
builder(args.length ? args : false, {minify:false},function(err, content){
builder(args.length ? args : false, { minify:false }, function (err, content) {
if (err) return console.error(err);

fs.write(fs.openSync(__dirname + '/../dist/socket.io.js', 'w'), content, 0, 'utf8');

fs.write(
fs.openSync(__dirname + '/../dist/socket.io.js', 'w')
, content
, 0
, 'utf8'
);
console.log('Successfully generated the development build: socket.io.js');
});

// and build a production build
builder(args.length ? args : false, function(err, content){
builder(args.length ? args : false, function (err, content) {
if (err) return console.error(err);

fs.write(fs.openSync(__dirname + '/../dist/socket.io.min.js', 'w'), content, 0, 'utf8');

fs.write(
fs.openSync(__dirname + '/../dist/socket.io.min.js', 'w')
, content
, 0
, 'utf8'
);
console.log('Successfully generated the production build: socket.io.min.js');
});
}