From 655c83e40ac4f8c9b0261cdecd647f06bf81847c Mon Sep 17 00:00:00 2001 From: Rafael Rinaldi Date: Tue, 12 Feb 2013 01:26:22 -0200 Subject: [PATCH 1/8] Added compiled file option. --- bin/yuglify | 38 ++++++++++++----- lib/sprintf.js | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 66 +++++++++++++++-------------- 3 files changed, 175 insertions(+), 42 deletions(-) create mode 100644 lib/sprintf.js diff --git a/bin/yuglify b/bin/yuglify index 65e5bf0..09e7a2c 100755 --- a/bin/yuglify +++ b/bin/yuglify @@ -17,24 +17,26 @@ var nopt = require('nopt'), output: path, terminal: Boolean, help: Boolean, - version: Boolean + version: Boolean, + name: String, + compile: String }, shorts = { 'o': ['--output'], 't': ['--type'], 'h': ['--help'], - 'v': ['--version'] + 'v': ['--version'], + 'n': ['--name'], + 'c': ['--compile'] }, parsed = nopt(known, shorts); - -parsed.type = parsed.type || 'js'; //Default to JS files + parsed.type = parsed.type || 'js'; //Default to JS files if (parsed.version) { console.log(pack.version); process.exit(0); } - if (parsed.help || (!parsed.argv.remain.length && !parsed.terminal)) { var help = [ 'yuglify@' + pack.version, @@ -77,10 +79,12 @@ if (parsed.terminal) { }); }); } else { - console.log('compressing..'); + + console.log('Compressing...'); console.log(parsed.argv.remain.join(', ')); - var out = parsed.out, + var out = parsed.output, + compiled = '', files = parsed.argv.remain; //Uglify is blocking, so we will do this in sync.. @@ -89,7 +93,9 @@ if (parsed.terminal) { if (exists(file)) { var data = fs.readFileSync(file, 'utf8'), ext = path.extname(file), - out = path.join(path.dirname(file), path.basename(file).replace(ext, '') + '-min' + ext), + basename = + out = path.join(path.dirname(file), path.basename(file).replace(ext, '') + '.min' + ext), + compfn = (ext === '.css' ? cssmin : jsmin); compfn(data, function(err, smashed) { @@ -97,12 +103,24 @@ if (parsed.terminal) { throw(err); process.exit(1); } - fs.writeFileSync(out, smashed, 'utf8'); - console.log('compressed file', out); + + if(parsed.compile) { + compiled += smashed; + } else { + fs.writeFileSync(out, smashed, 'utf8'); + console.log('Compressed file:', out); + } + }); } else { console.log('Failed to find', file); process.exit(1); } }); + + if(parsed.compile) { + fs.writeFileSync(parsed.compile, compiled.replace(/(\n|\r)/gi, ''), 'utf8'); + console.log('Single compiled and compressed file:', parsed.compile); + compiled = ''; + } } diff --git a/lib/sprintf.js b/lib/sprintf.js new file mode 100644 index 0000000..052b003 --- /dev/null +++ b/lib/sprintf.js @@ -0,0 +1,113 @@ +/** +* +* Basic sprintf implementation for JavaScript. Created for personal learning purposes. +* This implementation has string (%s w/ padding), decimal (%d w/ padding) and object (%(foo)s) support. +* +* @example +* console.log(sprintf("http://%s.%s", "rinaldi", "nu")); // http://rinaldi.nu +* console.log(sprintf("%(lorem)s %(ipsum)s", {lorem: "Lorem", ipsum: "Ipsum"})); // Lorem Ipsum +* console.log(sprintf("%30s", "foo")); // foo +* +* @author Rafael Rinaldi (rafaelrinaldi.com) +* @since Mar 17, 2010 +* +*/ +exports.sprintf = function ( p_raw ) { + + var raw = p_raw, + buffer, + args = arguments, + BASIC_REGEX = /%[d|s]|%\d+[d|s]/gi, + COMPLEX_REGEX = /%(\(([\w_\d]+)\))s/gi; + + buffer = p_raw; + + if(!raw) return null; + + if(hasBasicFormatter()) + processBasic(); + else if(hasComplexFormatter()) + processComplex(); + + /** + * + * Fill the buffer with a new entry. + * + * @param p_match Match. + * @param p_substitution Substitution value. + * @param p_padding Padding. + * + **/ + function pad( p_match, p_substitution, p_padding ) { + + /** Tip by Miller Medeiros (millermedeiros.com). **/ + var padding = new Array(p_padding + 1).join(" "); + + /** Computes the result to string buffer. **/ + buffer = buffer.replace(p_match, padding + p_substitution); + + } + + /** + * @return True if the second parameter is a number or a string, false otherwise. + */ + function hasBasicFormatter() { + return (typeof args[1] === "string" || typeof args[1] === "number"); + } + + /** + * @return True if the second parameter is a pure object, false otherwise. + */ + function hasComplexFormatter() { + return (typeof args[1] === "object"); + } + + /** Process values in the format: %s, %d, %ns and %nd. **/ + function processBasic() { + + var index = 0, + matches = raw.match(BASIC_REGEX), + match, + substitution, + padding; + + do { + match = matches[index]; + substitution = args[index + 1]; + padding = parseInt(match.substring(1, match.length - 1)) || 0; + + pad(match, substitution, padding); + + index++; + } + + while(index < matches.length); + + } + + /** Process values in the format: %(complex)s. **/ + function processComplex() { + + var index = 0, + matches = raw.match(COMPLEX_REGEX), + match, + id, + substitution; + + do { + match = matches[index]; + id = match.substring(2, match.length - 2); + substitution = args[1][id]; + + pad(match, substitution, 0); + + index++; + } + + while(index < matches.length); + + } + + return buffer; + +} \ No newline at end of file diff --git a/package.json b/package.json index 3efc3da..cec7a90 100644 --- a/package.json +++ b/package.json @@ -1,35 +1,37 @@ { - "name": "yuglify", - "description": "cli wrapper for uglify and cssmin used by YUI", - "version": "0.1.2", - "dependencies": { - "uglify-js": "~1.3.3", - "ycssmin": "~1.0.0", - "nopt": "*" - }, - "devDependencies": { - "yui-lint": "~0.1.1", - "jshint": "~0.9.0", - "vows": "*" - }, - "main": "./lib/index.js", - "bin": { - "yuglify": "./bin/yuglify" - }, - "scripts": { - "pretest": "jshint --config ./node_modules/yui-lint/jshint.json ./lib/*.js ./bin/yuglify", - "test": "vows --spec ./tests/*.js" - }, - "preferGlobal": "true", - "bugs": { "url" : "http://github.com/yui/yuglify/issues" }, - "licenses":[ - { - "type" : "BSD", - "url" : "https://github.com/yui/yuglify/blob/master/LICENSE" - } - ], - "repository": { - "type":"git", - "url":"http://github.com/yui/yuglify.git" + "name": "yuglify", + "description": "cli wrapper for uglify and cssmin used by YUI", + "version": "0.1.2", + "dependencies": { + "uglify-js": "~1.3.4", + "ycssmin": "~1.0.1", + "nopt": "~2.1.1" + }, + "devDependencies": { + "yui-lint": "~0.1.1", + "jshint": "~0.9.0", + "vows": "*" + }, + "main": "./lib/index.js", + "bin": { + "yuglify": "./bin/yuglify" + }, + "scripts": { + "pretest": "jshint --config ./node_modules/yui-lint/jshint.json ./lib/*.js ./bin/yuglify", + "test": "vows --spec ./tests/*.js" + }, + "preferGlobal": "true", + "bugs": { + "url": "http://github.com/yui/yuglify/issues" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/yui/yuglify/blob/master/LICENSE" } + ], + "repository": { + "type": "git", + "url": "http://github.com/yui/yuglify.git" + } } From eaae0a7b7d18f60928bea0843f8e51f485368a7b Mon Sep 17 00:00:00 2001 From: Rafael Rinaldi Date: Tue, 12 Feb 2013 02:56:10 -0200 Subject: [PATCH 2/8] Added custom name feature. --- bin/yuglify | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/bin/yuglify b/bin/yuglify index 09e7a2c..b1fd20f 100755 --- a/bin/yuglify +++ b/bin/yuglify @@ -12,6 +12,10 @@ var nopt = require('nopt'), pack = require('../package.json'), jsmin = require('../').jsmin, cssmin = require('../').cssmin, + sprintf = require('../lib/sprintf.js').sprintf, + defaults = { + name: "%(name)s.min%(ext)s" + }, known = { type: ['css', 'js'], output: path, @@ -29,6 +33,7 @@ var nopt = require('nopt'), 'n': ['--name'], 'c': ['--compile'] }, + filename = defaults.name, parsed = nopt(known, shorts); parsed.type = parsed.type || 'js'; //Default to JS files @@ -37,6 +42,10 @@ if (parsed.version) { process.exit(0); } +if(parsed.name) { + filename = parsed.name; +} + if (parsed.help || (!parsed.argv.remain.length && !parsed.terminal)) { var help = [ 'yuglify@' + pack.version, @@ -80,24 +89,26 @@ if (parsed.terminal) { }); } else { - console.log('Compressing...'); - console.log(parsed.argv.remain.join(', ')); - - var out = parsed.output, - compiled = '', + console.log('Compressing:', parsed.argv.remain.join(', ')); + + var buffer = '', files = parsed.argv.remain; //Uglify is blocking, so we will do this in sync.. files.forEach(function(file) { + file = path.resolve(file); + if (exists(file)) { - var data = fs.readFileSync(file, 'utf8'), - ext = path.extname(file), - basename = - out = path.join(path.dirname(file), path.basename(file).replace(ext, '') + '.min' + ext), - compfn = (ext === '.css' ? cssmin : jsmin); + var data = fs.readFileSync(file, 'utf8'), + destination = path.dirname(file) + '/', + extension = path.extname(file), + basename = path.basename(file).replace(extension, ''), + compressed = destination.concat(sprintf(filename, {name: basename, ext: extension})), + compfn = (extension === '.css' ? cssmin : jsmin); + compfn(data, function(err, smashed) { if (err) { throw(err); @@ -105,10 +116,10 @@ if (parsed.terminal) { } if(parsed.compile) { - compiled += smashed; + buffer += smashed; } else { - fs.writeFileSync(out, smashed, 'utf8'); - console.log('Compressed file:', out); + fs.writeFileSync(compressed, smashed, 'utf8'); + console.log('Compressed file:', compressed); } }); @@ -119,8 +130,13 @@ if (parsed.terminal) { }); if(parsed.compile) { - fs.writeFileSync(parsed.compile, compiled.replace(/(\n|\r)/gi, ''), 'utf8'); - console.log('Single compiled and compressed file:', parsed.compile); - compiled = ''; + + var compiled = parsed.compile === "true" ? sprintf(filename, {name: "main", ext: ".js"}) : parsed.compile; + + fs.writeFileSync(compiled, buffer.replace(/(\n|\r)/gi, ''), 'utf8'); + console.log('Single compiled and compressed file:', compiled); + buffer = ''; + } -} + +} \ No newline at end of file From b7bb38474093236a9a4c0fad2163ae2258ad74a8 Mon Sep 17 00:00:00 2001 From: Rafael Rinaldi Date: Tue, 12 Feb 2013 02:58:34 -0200 Subject: [PATCH 3/8] Updating help. --- bin/yuglify | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/yuglify b/bin/yuglify index b1fd20f..506794b 100755 --- a/bin/yuglify +++ b/bin/yuglify @@ -59,6 +59,8 @@ if (parsed.help || (!parsed.argv.remain.length && !parsed.terminal)) { ' --type js|css what type of file to compress (used with stdin)', ' --terminal use stdin and stdout instead of files', ' --output use this file when using --terminal', + ' --name/-n