Skip to content
Browse files

Initial Commit

  • Loading branch information...
0 parents commit cdb059b26d4f920fa409b7de51f23178b0af37ca @davglass davglass committed Oct 9, 2012
Showing with 348 additions and 0 deletions.
  1. +11 −0 .gitignore
  2. +25 −0 LICENSE
  3. +78 −0 README.md
  4. +78 −0 bin/yuglify
  5. +19 −0 lib/cssmin.js
  6. +2 −0 lib/index.js
  7. +81 −0 lib/jsminify.js
  8. +35 −0 package.json
  9. +19 −0 tests/default.js
11 .gitignore
@@ -0,0 +1,11 @@
+**/node_modules/
+**/npm-debug.log
+node_modules/
+tmp/
+CVS/
+.DS_Store
+.*.swp
+.svn
+*~
+.com.apple.timemachine.supported
+tests/assets/yql/build/*/*.js
25 LICENSE
@@ -0,0 +1,25 @@
+Copyright 2012 Yahoo! Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Yahoo! Inc. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
78 README.md
@@ -0,0 +1,78 @@
+yUglify
+=======
+
+`yuglify` is a wrapper around [UglifyJS](https://github.com/mishoo/UglifyJS) and [https://github.com/jbleuzen/node-cssmin](cssmin)
+with the default YUI configurations on each of them.
+
+CLI Usage
+----------
+
+ npm -g install yuglify
+
+`yuglify` has a very simple CLI interface to allow you to compress files from the command line.
+
+ yuglify ./lib/*.js #uses shell globbing, won't work on Windows
+
+This will read all passed files and compress them (js or css) and write them back beside the original
+with the name altered to `-min.js|css`.
+
+Required
+--------
+
+ npm install yuglify
+
+
+```javascript
+
+var yuglify = require('yuglify');
+
+yuglify.jsmin('<string of source', function(err, smashed) {
+});
+
+yuglify.cssmin('<string of source', function(err, smashed) {
+});
+
+```
+
+Purpose
+-------
+
+This module is primarily designed to be used inside the
+YUI Build tool, [shifter](http://yui.github.com/shifter/).
+
+Why not use the default Uglify?
+-------------------------------
+
+We need to support the `/*!` license comment blocks when minifying, so we added
+a preprocessor to the code to pull them from the source, then place them back when
+the minification is complete.
+
@mishoo
mishoo added a note Oct 16, 2012

UglifyJS2 supports keeping certain comments in the AST and should yield better/faster compression overall.

@davglass
YUI Library member
davglass added a note Oct 16, 2012

Is UglifyJS2 stable? I wasn't aware that it was stable enough to use in production.

@mishoo
mishoo added a note Oct 16, 2012

Depends what you mean by "stable". If you mean "as popular as v1", then nope, I'm not there yet. That's not up-to-me though — what was up-to-me I did: IMO it's stable, fast and better documented than v1, also it has features that v1 couldn't dream of (like generating source maps and keeping some comments in the output).

@davglass
YUI Library member
davglass added a note Oct 16, 2012

I'll take a look and see how hard it will be to port our wrapper over to 2 :)

@mishoo
mishoo added a note Oct 16, 2012

Cool. :) If you find a bug or need any help please drop me an email or file an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+We also needed to make sure that the file ends in a clean line ending for our
+combo servers. This way we ensure that other modules don't have to end with a
+semi-colon and the combohandler doesn't concat them together in a bad way.
+
+We've also added support to add a semi-colon if the last character of the
+minified source is either a `)` or a `}`.
+
+The last thing this module does is provide the default config that we think
+is the most compatible with the way that YUI Compressor used to minify our
+files.
+
+```
+{
+ mangle: true,
+ squeeze: true,
+ semicolon: false,
+ lift_vars: true,
+ mangle_toplevel: true,
+ no_mangle_functions: true,
+ max_line_length: 6000
+}
+```
+
+Testing
+-------
+
+Currently, the tests for this module are just to make sure that they are exported properly.
+Shifter's test suite validates that these compressors are working as expected. Soon, we'll
+move them over to this repo too.
78 bin/yuglify
@@ -0,0 +1,78 @@
+#!/usr/bin/env node
+
+var nopt = require('nopt'),
+ path = require('path'),
+ fs = require('fs'),
+ exists = fs.existsSync || path.existsSync,
+ pack = require('../package.json'),
+ jsmin = require('../').jsmin,
+ cssmin = require('../').cssmin,
+ known = {
+ help: Boolean,
+ version: Boolean
+ },
+ shorts = {
+ "h": ['--help'],
+ "v": ['--version']
+ },
+ parsed = nopt(known, shorts);
+
+parsed.type = parsed.type || 'js'; //Default to JS files
+
+if (parsed.version) {
+ console.log(pack.version);
+ process.exit(0);
+}
+
+if (parsed.help) {
+ var help = [
+ 'yuglify@' + pack.version,
+ '',
+ ' yuglify ./foo.js #Auto saves to ./foo-min.js',
+ ' yuglify ./foo/foo.js ./bar/bar.js #Auto saves to ./foo/foo-min.js and ./bar/bar-min.js',
+ ' yuglify ./foo/foo.css ./bar/bar.js #Auto saves to ./foo/foo-min.css and ./bar/bar-min.js',
+ '',
+ ' --help/-h show this',
+ ' --version/-v show version',
+ ' <files to compress>',
+ ];
+ console.log(help.join('\n'));
+ process.exit(0);
+}
+
+if (!parsed.argv.remain.length) {
+ console.log('no files');
+ process.exit(1);
+}
+
+console.log('compressing..');
+console.log(parsed.argv.remain.join(', '));
+
+console.log(parsed);
+
+var out = parsed.out,
+ 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),
+ out = path.join(path.dirname(file), path.basename(file).replace(ext, '') + '-min' + ext),
+ compfn = (ext === '.css' ? cssmin : jsmin);
+
+ compfn(data, function(err, smashed) {
+ if (err) {
+ throw(err);
+ process.exit(1);
+ }
+ fs.writeFileSync(out, smashed, 'utf8');
+ console.log('compressed file', out);
+ });
+ } else {
+ console.log('Failed to find', file);
+ process.exit(1);
+ }
+});
+
19 lib/cssmin.js
@@ -0,0 +1,19 @@
+/*
+Copyright (c) 2012, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://yuilibrary.com/license/
+*/
+
+var cssmin = require('cssmin').cssmin,
+ lines = 6000;
+
+exports.cssmin = function (source, num, callback) {
+ if (typeof num === 'function') {
+ callback = num;
+ num = lines;
+ }
+ num = num || lines;
+ var result = cssmin(source, num);
+ done(null, result + '\n');
+};
+
2 lib/index.js
@@ -0,0 +1,2 @@
+exports.jsmin = require('./jsminify').jsminify;
+exports.cssmin = require('./cssmin').cssmin;
81 lib/jsminify.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011-2012, Yahoo! Inc. All rights reserved.
+ * Copyrights licensed under the New BSD License.
+ * See the accompanying LICENSE file for terms.
+ */
+/*
+ * The comment/license workaround is based on the Ender workaround here:
+ * https://github.com/ender-js/Ender/blob/76961673be2a29e893d8d3dc9b97e3faf8b169a6/lib/ender.file.js#L25-58
+ * Ender is licensed under MIT - copyright 2012 Dustin Diaz & Jacob Thornton
+ * http://ender.no.de/
+*/
+var parser = require('uglify-js').parser,
+ uglify = require('uglify-js').uglify;
+
+exports.config = {
+ mangle: true,
+ squeeze: true,
+ semicolon: false,
+ lift_vars: true,
+ mangle_toplevel: true,
+ no_mangle_functions: true,
+ max_line_length: 6000
+};
+
+exports.jsminify = function (code, config, callback) {
+ if (typeof config === 'function') {
+ callback = config;
+ config = exports.config;
+ }
+ config = config || exports.config;
+ var comments = [],
+ token = '"yUglify: preserved comment block"',
+ reMultiComments = /\/\*![\s\S]*?\*\//g,
+ /*
+ In some cases Uglify adds a comma, in others it doesn't
+ So we have to process the tokens twice, first with the comma
+ then without it to catch both cases and to be clear about it.
+ */
+ reTokens1 = new RegExp(token + ',', 'g'),
+ reTokens = new RegExp(token, 'g'),
+ ast;
+
+ try {
+ code = code.replace(reMultiComments, function (comment) {
+ comments.push(comment);
+ return ';' + token + ';';
+ });
+
+ config.ascii_only = true; //Force ascii
+ ast = parser.parse(code, config.semicolon || false);
+
+ if (config.mangle) {
+ ast = uglify.ast_mangle(ast, config);
+ }
+ if (config.squeeze) {
+ ast = uglify.ast_squeeze(ast, config);
+ }
+
+ code = uglify.gen_code(ast, config);
+
+ //First pass with comma (comment inside code somewhere
+ code = code.replace(reTokens1, function () {
+ return '\n' + comments.shift() + '\n';
+ });
+
+ //Second pass without the comma to catch normal comments
+ code = code.replace(reTokens, function () {
+ return '\n' + comments.shift() + '\n';
+ });
+
+ if ((code.substr(code.length - 1) === ')') ||
+ (code.substr(code.length - 1) === '}')) {
+ code += ';';
+ }
+ code += '\n';
+
+ callback(null, code);
+ } catch (e) {
+ callback(e);
+ }
+};
35 package.json
@@ -0,0 +1,35 @@
+{
+ "name": "yuglify",
+ "description": "cli wrapper for uglify and cssmin used by YUI",
+ "version": "0.0.1",
+ "dependencies": {
+ "uglify-js": "~1.3.3",
+ "cssmin": "~0.3.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"
+ }
+}
19 tests/default.js
@@ -0,0 +1,19 @@
+var vows = require('vows'),
+ path = require('path'),
+ assert = require('assert');
+
+var tests = {
+ "require": {
+ topic: function() {
+ return require('../lib');
+ },
+ "should have jsmin": function(topic) {
+ assert.ok(topic.jsmin);
+ },
+ "should have cssmin": function(topic) {
+ assert.ok(topic.cssmin);
+ }
+ }
+};
+
+vows.describe('yUglify').addBatch(tests).export(module);

0 comments on commit cdb059b

Please sign in to comment.
Something went wrong with that request. Please try again.