moved to commander for options and fixed up JS parsing errors

This commit is contained in:
Remy Sharp 2011-12-30 17:43:06 +00:00
parent 8a5f50fd0d
commit 229d4f146b
3 changed files with 99 additions and 100 deletions

View File

@ -1,90 +1,70 @@
#!/usr/bin/env node
var path = require('path'), fs = require('fs'), querystring = require('querystring'), util = require('util');
var path = require('path'),
fs = require('fs'),
querystring = require('querystring'),
util = require('util');
fs.realpath(__filename, function(error, script) {
var servedir, root, port;
if (error) throw error;
// Load `servedir`.
var Inliner = require(path.join(path.dirname(script), '../inliner')),
usage = [
'usage: inliner [options] http://yoursite.com',
'e.g.: inliner http://localhost:8080',
'',
'Options:',
' --verbose echo on STDERR the progress of inlining',
// ' --share save the output on jsbin.com and return a shareable url',
' --nocompress don\'t compress CSS or HTML - useful for debugging',
' --images don\'t encode images - keeps files size small, but more requests',
' --version current inliner version',
' --help this usage',
'',
'For more details see http://github.com/remy/inliner/\n'
].join('\n');
function controlArg(args, label, fn) {
var i;
var callback = function (arg, i) {
args.splice(i, 1);
fn(arg, i);
};
if ((i = args.indexOf(label)) !== -1) {
callback(args[i], i);
} else if ((i = args.indexOf('-' + label.substr(0, 1))) !== -1) {
callback(args[i], i);
} else if ((i = args.indexOf('--' + label)) !== -1) {
callback(args[i], i);
}
}
program = require('commander');
program
.version(Inliner.version)
.usage('[options] http://yoursite.com')
.option('-v, --verbose', 'echo on STDERR the progress of inlining')
.option('-n, --nocompress', "don't compress CSS or HTML - useful for debugging")
.option('-i, --images', "don't encode images - keeps files size small, but more requests")
//.option('-s, --share', "create jsbin.com url for HTML page")
//.option('-h, --help', "help - you're looking at it");
program.on('--help', function () {
console.log(' Examples:');
console.log('');
console.log(' $ inliner -v http://twitter.com > twitter.html');
console.log(' $ inliner -ni http://twitter.com > twitter.html');
console.log('');
console.log(' For more details see http://github.com/remy/inliner/');
console.log('');
});
program.parse(process.argv);
var options = Inliner.defaults(),
verbose = false,
share = false;
controlArg(process.argv, 'help', function () {
console.log(usage);
process.exit();
});
controlArg(process.argv, 'nocompress', function (arg, i) {
if (program.nocompress) {
options.compressCSS = false;
options.collapseWhitespace = false;
});
}
controlArg(process.argv, 'share', function (arg, i) {
if (program.share) {
share = true;
// because JS Bin is a damn sight easier to debug when it's not all on one line
options.compressCSS = false;
options.collapseWhitespace = false;
});
controlArg(process.argv, 'images', function (arg, i) {
options.images = false;
});
// order counts here - so verbose can also use -v
if (process.argv.length == 3) {
controlArg(process.argv, 'version', function () {
console.log(Inliner.prototype.version);
process.exit();
});
}
controlArg(process.argv, 'verbose', function (arg, i) {
verbose = true;
});
options.images = !program.images;
verbose = program.verbose;
if (process.argv[2] === undefined) {
console.log(usage);
process.exit();
if (program.args.length == 0) {
// ripped out of commander.js - should really be process.usage()
process.stdout.write(program.helpInformation());
program.emit('--help');
process.exit(0);
}
var url = process.argv[2];
if (url.indexOf('http') !== 0) {
var url = program.args[0];
if (path.existsSync(url)) {
// then it's a file
} else if (url.indexOf('http') !== 0) {
url = 'http://' + url;
}
@ -113,10 +93,10 @@ fs.realpath(__filename, function(error, script) {
});
});
request.write(data);
request.end();
request.end();
} else {
// using util.print because console.log evalutes sprintf commands - which we don't want to do
util.print(html);
util.print(html);
}
});

View File

@ -1,10 +1,14 @@
var URL = require('url'),
util = require('util'),
jsmin = require('./jsmin'),
events = require('events'),
Buffer = require('buffer').Buffer,
fs = require('fs'),
path = require('path'),
jsdom = require('jsdom'),
jsp = require('uglify-js/lib/parse-js'),
pro = require('uglify-js/lib/process'),
uglifyjs = require('uglify-js'),
jsp = uglifyjs.parser,
pro = uglifyjs.uglify,
compress = null, // import only when required - might make the command line tool easier to use
http = {
http: require('http'),
@ -111,11 +115,14 @@ function Inliner(url, options, callback) {
if (items === 0) {
// manually remove the comments
var els = removeComments(window.document.documentElement);
// collapse the white space
if (inliner.options.collapseWhitespace) {
// TODO put white space helper back in
window.$('pre').html(function (i, html) {
return html.replace(/\n/g, '~~nl~~').replace(/\s/g, '~~s~~');
return html.replace(/\n/g, '~~nl~~'); //.replace(/\s/g, '~~s~~');
});
window.$('textarea').val(function (i, v) {
return v.replace(/\n/g, '~~nl~~').replace(/\s/g, '~~s~~');
});
html = window.document.innerHTML;
html = html.replace(/\s+/g, ' ').replace(/~~nl~~/g, '\n').replace(/~~s~~/g, ' ');
@ -179,7 +186,7 @@ function Inliner(url, options, callback) {
}
window.$(link).replaceWith(style);
finished();
finished();
});
});
});
@ -192,7 +199,10 @@ function Inliner(url, options, callback) {
assets.scripts.each(function () {
var $script = window.$(this),
src = $script.attr('src'),
orig_code = this.innerHTML,
// note: not using .innerHTML as this coerses & => &
orig_code = this.firstChild.nodeValue
.replace(/<\/script>/gi, '<\\/script>'),
// .replace(/\/\/.*\n/gi, ''),
final_code = '';
// only remove the src if we have a script body
@ -213,26 +223,25 @@ function Inliner(url, options, callback) {
final_code = pro.gen_code(ast);
// some protection against putting script tags in the body
final_code = final_code.replace(/<\/script>/gi, '<\\/script>');
this.innerText = final_code;
// window.$(this).text(final_code);
window.$(this).text(final_code).append('\n');
if (src) {
inliner.emit('progress', 'compress ' + URL.resolve(root, src));
} else {
inliner.emit('progress', 'compress inline script');
}
}
} catch (e) {
// console.error(orig_code.indexOf('script>script'));
// this.innerHTML = orig_code.replace(/<\/script>/gi, '<\\/script>');
// console.error('exception', e);
// window.$(this).html(jsmin('', orig_code, 2));
console.error('exception on ', src);
console.error('exception in ' + src + ': ' + e.message);
console.error('>>>>>> ' + orig_code.split('\n')[e.line - 1]);
}
inliner.todo--;
inliner.emit('jobs', (inliner.total - inliner.todo) + '/' + inliner.total);
} else if (orig_code) {
// window.$(this).text(orig_code.replace(/<\/script>/gi, '<\\/script>'));
this.innerText = orig_code.replace(/<\/script>/gi, '<\\/script>');
window.$(this).text(orig_code);
// this.innerText = orig_code;
}
});
finished();
@ -252,7 +261,7 @@ function Inliner(url, options, callback) {
} else if (this.src) {
inliner.get(scriptURL, { not: 'text/html' }, function (data) {
// catches an exception that was being thrown, but script escaping wasn't being caught
if (data) $script.text(data.replace(/<\/script>/gi, '<\\/script>'));
if (data) $script.text(data.replace(/<\/script>/gi, '<\\/script>')); //.replace(/\/\/.*$\n/g, ''));
// $script.before('<!-- ' + scriptURL + ' -->');
breakdown.scripts--;
inliner.todo--;
@ -289,7 +298,7 @@ function Inliner(url, options, callback) {
util.inherits(Inliner, events.EventEmitter);
Inliner.prototype.version = JSON.parse(require('fs').readFileSync(__dirname + '/package.json').toString()).version;
Inliner.version = Inliner.prototype.version = JSON.parse(require('fs').readFileSync(__dirname + '/package.json').toString()).version;
Inliner.prototype.get = function (url, options, callback) {
// support no options being passed in
@ -308,11 +317,30 @@ Inliner.prototype.get = function (url, options, callback) {
} else {
this.requestCachePending[url] = [callback];
}
var inliner = this;
// TODO remove the sync
if (path.existsSync(url)) {
// then we're dealing with a file
fs.readFile(url, 'utf8', function (err, body) {
inliner.requestCache[url] = body;
inliner.requestCachePending[url].forEach(function (callback, i) {
if (i == 0 && body) {
inliner.emit('progress', (options.encode ? 'encode' : 'get') + ' ' + url);
} else if (body) {
inliner.emit('progress', 'cached ' + url);
}
callback && callback(body);
});
});
return;
}
// otherwis continue and create a new web request
var request = makeRequest(url),
body = '',
inliner = this;
body = '';
// this tends to occur when we can't connect to the url - i.e. target is down
// note that the main inliner app handles sending the error back to the client
@ -330,6 +358,7 @@ Inliner.prototype.get = function (url, options, callback) {
// once loaded, we set up event listeners to handle data coming in and do a little
// dance with the response object - which I'll explain... ==>
if (res.headers['content-encoding'] == 'gzip') {
console.error('loading gzip library');
if (compress === null) {
try {
compress = require('./node-compress/lib/compress/');
@ -374,6 +403,7 @@ Inliner.prototype.get = function (url, options, callback) {
gunzip.end();
return;
}
if (res.statusCode !== 200) {
inliner.emit('progress', 'get ' + res.statusCode + ' on ' + url);
body = ''; // ?
@ -508,19 +538,7 @@ var makeRequest = Inliner.makeRequest = function (url, extraOptions) {
module.exports = Inliner;
if (!module.parent) {
if (process.argv[2] === undefined) {
console.log('Usage: inliner http://yoursite.com\ninliner [nocompress]\nThis will output the inlined HTML, CSS, images and JavaScript');
process.exit();
}
(function () {
var options;
if (process.argv[3] === 'nocompress') {
options = { compressCSS: false, collapseWhitespace: false };
}
var inliner = new Inliner(process.argv[2], options, function (html) {
require('util').print(html);
});
})();
// if this module isn't being included in a larger app, defer to the
// bin/inliner for the help options
require('./bin/inliner');
}

View File

@ -10,8 +10,9 @@
"web": "http://github.com/remy"
},
"dependencies": {
"jsdom": ">=0.2.0",
"uglify-js": ">=1.0.2"
"jsdom": "latest",
"uglify-js": "1.2.2",
"commander": "0.5.1"
},
"repository": {
"type": "git",