summaryrefslogtreecommitdiff
path: root/build-tools
diff options
context:
space:
mode:
Diffstat (limited to 'build-tools')
-rw-r--r--build-tools/README.txt20
-rwxr-xr-xbuild-tools/bin/cleancss44
-rwxr-xr-xbuild-tools/bin/lessc6
-rwxr-xr-xbuild-tools/bin/uglifyjs6
-rw-r--r--build-tools/lib/cleancss/LICENSE7
-rw-r--r--build-tools/lib/cleancss/clean.js201
-rw-r--r--build-tools/lib/cleancss/index.js1
-rw-r--r--build-tools/lib/less/index.js6
-rw-r--r--build-tools/lib/optimist/LICENSE21
-rw-r--r--build-tools/lib/optimist/index.js475
-rw-r--r--build-tools/lib/wordwrap/LICENSE4
-rw-r--r--build-tools/lib/wordwrap/index.js76
l---------build-tools/node_modules1
13 files changed, 865 insertions, 3 deletions
diff --git a/build-tools/README.txt b/build-tools/README.txt
index 31dc7c0a..0efd403a 100644
--- a/build-tools/README.txt
+++ b/build-tools/README.txt
@@ -22,3 +22,23 @@ Tizen Web UI Framework includes following tools used on build;
* node-jslint: BSD License (build-tools/lib/jslint/LICENSE)
* jslint: Customized MIT License (build-tools/lib/jslint/jslint.js)
* nopt, abbrev: MIT License (build-tools/lib/jslint/nopt/LICENSE)
+
+* clean-css (http://github.com/GoalSmashers/clean-css)
+ * Version: 0.4.0
+ * Description: A CSS code minifier
+ * Mods
+ * Fix local library path and name
+ * License
+ * MIT license (build-tools/lib/cleancss/LICENSE)
+
+* optimist (http://github.com/substack/node-optimist)
+ * Version: 0.3.4
+ * Description: A node.js command-line option parser libraryr, used by clean-css.
+ * License
+ * MIT/X11 license (build-tools/lib/optimist/LICENSE)
+
+* wordwrap (http://github.com/substack/node-wordwrap)
+ * Version: b026541 (Released at Apr. 30 2012)
+ * Description: Word-wrapping library, used by optimist.
+ * License
+ * MIT license (build-tools/lib/wordwrap/LICENSE)
diff --git a/build-tools/bin/cleancss b/build-tools/bin/cleancss
new file mode 100755
index 00000000..0ec2ef32
--- /dev/null
+++ b/build-tools/bin/cleancss
@@ -0,0 +1,44 @@
+#!/usr/bin/env node
+
+global.util = require("util");
+var argv = require('optimist').argv,
+ cleanCss = require('cleancss'),
+ fs = require('fs');
+
+var options = {
+ source: null,
+ target: null
+};
+var cleanOptions = {};
+
+if (argv.o) options.target = argv.o;
+if (argv._) options.source = argv._[0];
+if (argv.e) cleanOptions.removeEmpty = true;
+
+if (argv.h || argv.help) {
+ global.util.print('Usage: cleancss [-e] -o <output-file> <input-file>\n');
+ process.exit(0);
+}
+
+if (options.source) {
+ fs.readFile(options.source, 'utf8', function(error, text) {
+ if (error) throw error;
+ output(cleanCss.process(text));
+ });
+} else {
+ var stdin = process.openStdin();
+ stdin.setEncoding('utf-8');
+ var text = '';
+ stdin.on('data', function(chunk) { text += chunk; });
+ stdin.on('end', function() { output(cleanCss.process(text, cleanOptions)); });
+}
+
+function output(cleaned) {
+ if (options.target) {
+ var out = fs.createWriteStream(options.target, { flags: 'w', encoding: 'utf-8', mode: 0644 });
+ out.write(cleaned);
+ out.end();
+ } else {
+ process.stdout.write(cleaned);
+ }
+};
diff --git a/build-tools/bin/lessc b/build-tools/bin/lessc
index 1e3c961f..32f993ff 100755
--- a/build-tools/bin/lessc
+++ b/build-tools/bin/lessc
@@ -4,7 +4,11 @@ var path = require('path'),
fs = require('fs'),
sys = require('sys');
-require.paths.unshift(path.join(__dirname, '..', 'lib'));
+try {
+ // For old node.js versions
+ require.paths.unshift( path.join( __dirname, '..', 'lib' ) );
+} catch ( ex ) {
+}
var less = require('less');
var args = process.argv.slice(1);
diff --git a/build-tools/bin/uglifyjs b/build-tools/bin/uglifyjs
index 061cd4da..485d9c11 100755
--- a/build-tools/bin/uglifyjs
+++ b/build-tools/bin/uglifyjs
@@ -7,7 +7,11 @@ var fs = require("fs");
// Add ../lib to require path
// by Youmin Ha <youmin.ha@samsung.com>
var path = require("path");
-require.paths.unshift(path.join(__dirname, '..', 'lib'));
+
+try {
+ require.paths.unshift(path.join(__dirname, '..', 'lib'));
+} catch (ex) {
+}
var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js
jsp = uglify.parser,
diff --git a/build-tools/lib/cleancss/LICENSE b/build-tools/lib/cleancss/LICENSE
new file mode 100644
index 00000000..9e592d3d
--- /dev/null
+++ b/build-tools/lib/cleancss/LICENSE
@@ -0,0 +1,7 @@
+Copyright (c) 2011 GoalSmashers.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/build-tools/lib/cleancss/clean.js b/build-tools/lib/cleancss/clean.js
new file mode 100644
index 00000000..3fa03f04
--- /dev/null
+++ b/build-tools/lib/cleancss/clean.js
@@ -0,0 +1,201 @@
+var util = require('util');
+
+var CleanCSS = {
+ colors: {
+ white: '#fff',
+ black: '#000',
+ fuchsia: '#f0f',
+ yellow: '#ff0'
+ },
+
+ specialComments: [],
+ contentBlocks: [],
+
+ process: function(data, options) {
+ var self = this,
+ replace = function(pattern, replacement) {
+ if (typeof arguments[0] == 'function')
+ arguments[0]();
+ else
+ data = data.replace.apply(data, arguments);
+ };
+
+ options = options || {};
+
+ // replace function
+ if (options.debug) {
+ var originalReplace = replace;
+ replace = function(pattern, replacement) {
+ var name = typeof pattern == 'function' ?
+ /function (\w+)\(/.exec(pattern.toString())[1] :
+ pattern;
+ console.time(name);
+ originalReplace(pattern, replacement);
+ console.timeEnd(name);
+ };
+ }
+
+ // strip comments one by one
+ replace(function stripComments() {
+ data = self.stripComments(data);
+ });
+
+ // replace content: with a placeholder
+ replace(function stripContent() {
+ data = self.stripContent(data);
+ });
+
+ replace(/;\s*;+/g, ';') // whitespace between semicolons & multiple semicolons
+ replace(/\n/g, '') // line breaks
+ replace(/\s+/g, ' ') // multiple whitespace
+ replace(/ !important/g, '!important') // whitespace before !important
+ replace(/[ ]?,[ ]?/g, ',') // space with a comma
+ replace(/progid:[^(]+\(([^\)]+)/g, function(match, contents) { // restore spaces inside IE filters (IE 7 issue)
+ return match.replace(/,/g, ', ');
+ })
+ replace(/ ([+~>]) /g, '$1') // replace spaces around selectors
+ replace(/\{([^}]+)\}/g, function(match, contents) { // whitespace inside content
+ return '{' + contents.trim().replace(/(\s*)([;:=\s])(\s*)/g, '$2') + '}';
+ })
+ replace(/;}/g, '}') // trailing semicolons
+ replace(/rgb\s*\(([^\)]+)\)/g, function(match, color) { // rgb to hex colors
+ var parts = color.split(',');
+ var encoded = '#';
+ for (var i = 0; i < 3; i++) {
+ var asHex = parseInt(parts[i], 10).toString(16);
+ encoded += asHex.length == 1 ? '0' + asHex : asHex;
+ }
+ return encoded;
+ })
+ replace(/([^"'=\s])\s*#([0-9a-f]{6})/gi, function(match, prefix, color) { // long hex to short hex
+ if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5])
+ return (prefix + (/:$/.test(prefix) ? '' : ' ')) + '#' + color[0] + color[2] + color[4];
+ else
+ return (prefix + (/:$/.test(prefix) ? '' : ' ')) + '#' + color;
+ })
+ replace(/(color|background):(\w+)/g, function(match, property, colorName) { // replace standard colors with hex values (only if color name is longer then hex value)
+ if (CleanCSS.colors[colorName]) return property + ':' + CleanCSS.colors[colorName];
+ else return match;
+ })
+ replace(/([: ,\(])#f00/g, '$1red') // replace #f00 with red as it's shorter
+ replace(/font\-weight:(\w+)/g, function(match, weight) { // replace font weight with numerical value
+ if (weight == 'normal') return 'font-weight:400';
+ else if (weight == 'bold') return 'font-weight:700';
+ else return match;
+ })
+ replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\([^\)]+\))([;}'"])/g, function(match, filter, args, suffix) { // IE shorter filters but only if single (IE 7 issue)
+ return filter.toLowerCase() + args + suffix;
+ })
+ replace(/(\s|:)0(px|em|ex|cm|mm|in|pt|pc|%)/g, '$1' + '0') // zero + unit to zero
+ replace(/(border|border-top|border-right|border-bottom|border-left|outline):none/g, '$1:0') // none to 0
+ replace(/(background):none([;}])/g, '$1:0$2') // background:none to 0
+ replace(/0 0 0 0([^\.])/g, '0$1') // multiple zeros into one
+ replace(/([: ,=\-])0\.(\d)/g, '$1.$2')
+ if (options.removeEmpty) replace(/[^}]+?{\s*?}/g, '') // empty elements
+ if (data.indexOf('charset') > 0) replace(/(.+)(@charset [^;]+;)/, '$2$1') // move first charset to the beginning
+ replace(/(.)(@charset [^;]+;)/g, '$1') // remove all extra charsets that are not at the beginning
+ replace(/\*([\.#:\[])/g, '$1') // remove universal selector when not needed (*#id, *.class etc)
+ replace(/ {/g, '{') // whitespace before definition
+ replace(/\} /g, '}') // whitespace after definition
+
+ // Get the special comments, content content, and spaces inside calc back
+ replace(/calc\([^\}]+\}/g, function(match) {
+ return match.replace(/\+/g, ' + ');
+ });
+ replace(/__CSSCOMMENT__/g, function() { return self.specialComments.shift(); });
+ replace(/__CSSCONTENT__/g, function() { return self.contentBlocks.shift(); });
+
+ return data.trim() // trim spaces at beginning and end
+ },
+
+ // Strips special comments (/*! ... */) by replacing them by __CSSCOMMENT__ marker
+ // for further restoring. Plain comments are removed. It's done by scanning datq using
+ // String#indexOf scanning instead of regexps to speed up the process.
+ stripComments: function(data) {
+ var tempData = [],
+ nextStart = 0,
+ nextEnd = 0,
+ cursor = 0;
+
+ for (; nextEnd < data.length; ) {
+ nextStart = data.indexOf('/*', nextEnd);
+ nextEnd = data.indexOf('*/', nextStart);
+ if (nextStart == -1 || nextEnd == -1) break;
+
+ tempData.push(data.substring(cursor, nextStart))
+ if (data[nextStart + 2] == '!') {
+ // in case of special comments, replace them with a placeholder
+ this.specialComments.push(data.substring(nextStart, nextEnd + 2));
+ tempData.push('__CSSCOMMENT__');
+ }
+ cursor = nextEnd + 2;
+ }
+
+ return tempData.length > 0 ?
+ tempData.join('') + data.substring(cursor, data.length) :
+ data;
+ },
+
+ // Strips content tags by replacing them by __CSSCONTENT__ marker
+ // for further restoring. It's done via string scanning instead of
+ // regexps to speed up the process.
+ stripContent: function(data) {
+ var tempData = [],
+ nextStart = 0,
+ nextEnd = 0,
+ tempStart = 0,
+ cursor = 0,
+ matchedParenthesis = null;
+
+ // Finds either first (matchedParenthesis == null) or second matching parenthesis
+ // so we can determine boundaries of content block.
+ var nextParenthesis = function(pos) {
+ var min,
+ max = data.length;
+
+ if (matchedParenthesis) {
+ min = data.indexOf(matchedParenthesis, pos);
+ if (min == -1) min = max;
+ } else {
+ var next1 = data.indexOf("'", pos);
+ var next2 = data.indexOf('"', pos);
+ if (next1 == -1) next1 = max;
+ if (next2 == -1) next2 = max;
+
+ min = next1 > next2 ? next2 : next1;
+ }
+
+ if (min == max) return -1;
+
+ if (matchedParenthesis) {
+ matchedParenthesis = null;
+ return min;
+ } else {
+ // check if there's anything else between pos and min that doesn't match ':' or whitespace
+ if (/[^:\s]/.test(data.substring(pos, min))) return -1;
+ matchedParenthesis = data.charAt(min);
+ return min + 1;
+ }
+ };
+
+ for (; nextEnd < data.length; ) {
+ nextStart = data.indexOf('content', nextEnd);
+ if (nextStart == -1) break;
+
+ nextStart = nextParenthesis(nextStart + 7);
+ nextEnd = nextParenthesis(nextStart);
+ if (nextStart == -1 || nextEnd == -1) break;
+
+ tempData.push(data.substring(cursor, nextStart - 1));
+ tempData.push('__CSSCONTENT__');
+ this.contentBlocks.push(data.substring(nextStart - 1, nextEnd + 1));
+ cursor = nextEnd + 1;
+ }
+
+ return tempData.length > 0 ?
+ tempData.join('') + data.substring(cursor, data.length) :
+ data;
+ }
+};
+
+module.exports = CleanCSS;
diff --git a/build-tools/lib/cleancss/index.js b/build-tools/lib/cleancss/index.js
new file mode 100644
index 00000000..b93b57c3
--- /dev/null
+++ b/build-tools/lib/cleancss/index.js
@@ -0,0 +1 @@
+module.exports = require("./clean");
diff --git a/build-tools/lib/less/index.js b/build-tools/lib/less/index.js
index 39c40ca2..3b4e928d 100644
--- a/build-tools/lib/less/index.js
+++ b/build-tools/lib/less/index.js
@@ -2,7 +2,11 @@ var path = require('path'),
sys = require('sys'),
fs = require('fs');
-require.paths.unshift(path.join(__dirname, '..'));
+try {
+ // For old node.js versions
+ require.paths.unshift( path.join( __dirname, '..' ) );
+} catch ( ex ) {
+}
var less = {
version: [1, 1, 3],
diff --git a/build-tools/lib/optimist/LICENSE b/build-tools/lib/optimist/LICENSE
new file mode 100644
index 00000000..432d1aeb
--- /dev/null
+++ b/build-tools/lib/optimist/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/build-tools/lib/optimist/index.js b/build-tools/lib/optimist/index.js
new file mode 100644
index 00000000..4dc39f4e
--- /dev/null
+++ b/build-tools/lib/optimist/index.js
@@ -0,0 +1,475 @@
+var path = require('path');
+var wordwrap = require('wordwrap');
+
+/* Hack an instance of Argv with process.argv into Argv
+ so people can do
+ require('optimist')(['--beeble=1','-z','zizzle']).argv
+ to parse a list of args and
+ require('optimist').argv
+ to get a parsed version of process.argv.
+*/
+
+var inst = Argv(process.argv.slice(2));
+Object.keys(inst).forEach(function (key) {
+ Argv[key] = typeof inst[key] == 'function'
+ ? inst[key].bind(inst)
+ : inst[key];
+});
+
+var exports = module.exports = Argv;
+function Argv (args, cwd) {
+ var self = {};
+ if (!cwd) cwd = process.cwd();
+
+ self.$0 = process.argv
+ .slice(0,2)
+ .map(function (x) {
+ var b = rebase(cwd, x);
+ return x.match(/^\//) && b.length < x.length
+ ? b : x
+ })
+ .join(' ')
+ ;
+
+ if (process.argv[1] == process.env._) {
+ self.$0 = process.env._.replace(
+ path.dirname(process.execPath) + '/', ''
+ );
+ }
+
+ var flags = { bools : {}, strings : {} };
+
+ self.boolean = function (bools) {
+ if (!Array.isArray(bools)) {
+ bools = [].slice.call(arguments);
+ }
+
+ bools.forEach(function (name) {
+ flags.bools[name] = true;
+ });
+
+ return self;
+ };
+
+ self.string = function (strings) {
+ if (!Array.isArray(strings)) {
+ strings = [].slice.call(arguments);
+ }
+
+ strings.forEach(function (name) {
+ flags.strings[name] = true;
+ });
+
+ return self;
+ };
+
+ var aliases = {};
+ self.alias = function (x, y) {
+ if (typeof x === 'object') {
+ Object.keys(x).forEach(function (key) {
+ self.alias(key, x[key]);
+ });
+ }
+ else if (Array.isArray(y)) {
+ y.forEach(function (yy) {
+ self.alias(x, yy);
+ });
+ }
+ else {
+ var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y);
+ aliases[x] = zs.filter(function (z) { return z != x });
+ aliases[y] = zs.filter(function (z) { return z != y });
+ }
+
+ return self;
+ };
+
+ var demanded = {};
+ self.demand = function (keys) {
+ if (typeof keys == 'number') {
+ if (!demanded._) demanded._ = 0;
+ demanded._ += keys;
+ }
+ else if (Array.isArray(keys)) {
+ keys.forEach(function (key) {
+ self.demand(key);
+ });
+ }
+ else {
+ demanded[keys] = true;
+ }
+
+ return self;
+ };
+
+ var usage;
+ self.usage = function (msg, opts) {
+ if (!opts && typeof msg === 'object') {
+ opts = msg;
+ msg = null;
+ }
+
+ usage = msg;
+
+ if (opts) self.options(opts);
+
+ return self;
+ };
+
+ function fail (msg) {
+ self.showHelp();
+ if (msg) console.error(msg);
+ process.exit(1);
+ }
+
+ var checks = [];
+ self.check = function (f) {
+ checks.push(f);
+ return self;
+ };
+
+ var defaults = {};
+ self.default = function (key, value) {
+ if (typeof key === 'object') {
+ Object.keys(key).forEach(function (k) {
+ self.default(k, key[k]);
+ });
+ }
+ else {
+ defaults[key] = value;
+ }
+
+ return self;
+ };
+
+ var descriptions = {};
+ self.describe = function (key, desc) {
+ if (typeof key === 'object') {
+ Object.keys(key).forEach(function (k) {
+ self.describe(k, key[k]);
+ });
+ }
+ else {
+ descriptions[key] = desc;
+ }
+ return self;
+ };
+
+ self.parse = function (args) {
+ return Argv(args).argv;
+ };
+
+ self.option = self.options = function (key, opt) {
+ if (typeof key === 'object') {
+ Object.keys(key).forEach(function (k) {
+ self.options(k, key[k]);
+ });
+ }
+ else {
+ if (opt.alias) self.alias(key, opt.alias);
+ if (opt.demand) self.demand(key);
+ if (typeof opt.default !== 'undefined') {
+ self.default(key, opt.default);
+ }
+
+ if (opt.boolean || opt.type === 'boolean') {
+ self.boolean(key);
+ }
+ if (opt.string || opt.type === 'string') {
+ self.string(key);
+ }
+
+ var desc = opt.describe || opt.description || opt.desc;
+ if (desc) {
+ self.describe(key, desc);
+ }
+ }
+
+ return self;
+ };
+
+ var wrap = null;
+ self.wrap = function (cols) {
+ wrap = cols;
+ return self;
+ };
+
+ self.showHelp = function (fn) {
+ if (!fn) fn = console.error;
+ fn(self.help());
+ };
+
+ self.help = function () {
+ var keys = Object.keys(
+ Object.keys(descriptions)
+ .concat(Object.keys(demanded))
+ .concat(Object.keys(defaults))
+ .reduce(function (acc, key) {
+ if (key !== '_') acc[key] = true;
+ return acc;
+ }, {})
+ );
+
+ var help = keys.length ? [ 'Options:' ] : [];
+
+ if (usage) {
+ help.unshift(usage.replace(/\$0/g, self.$0), '');
+ }
+
+ var switches = keys.reduce(function (acc, key) {
+ acc[key] = [ key ].concat(aliases[key] || [])
+ .map(function (sw) {
+ return (sw.length > 1 ? '--' : '-') + sw
+ })
+ .join(', ')
+ ;
+ return acc;
+ }, {});
+
+ var switchlen = longest(Object.keys(switches).map(function (s) {
+ return switches[s] || '';
+ }));
+
+ var desclen = longest(Object.keys(descriptions).map(function (d) {
+ return descriptions[d] || '';
+ }));
+
+ keys.forEach(function (key) {
+ var kswitch = switches[key];
+ var desc = descriptions[key] || '';
+
+ if (wrap) {
+ desc = wordwrap(switchlen + 4, wrap)(desc)
+ .slice(switchlen + 4)
+ ;
+ }
+
+ var spadding = new Array(
+ Math.max(switchlen - kswitch.length + 3, 0)
+ ).join(' ');
+
+ var dpadding = new Array(
+ Math.max(desclen - desc.length + 1, 0)
+ ).join(' ');
+
+ var type = null;
+
+ if (flags.bools[key]) type = '[boolean]';
+ if (flags.strings[key]) type = '[string]';
+
+ if (!wrap && dpadding.length > 0) {
+ desc += dpadding;
+ }
+
+ var prelude = ' ' + kswitch + spadding;
+ var extra = [
+ type,
+ demanded[key]
+ ? '[required]'
+ : null
+ ,
+ defaults[key] !== undefined
+ ? '[default: ' + JSON.stringify(defaults[key]) + ']'
+ : null
+ ,
+ ].filter(Boolean).join(' ');
+
+ var body = [ desc, extra ].filter(Boolean).join(' ');
+
+ if (wrap) {
+ var dlines = desc.split('\n');
+ var dlen = dlines.slice(-1)[0].length
+ + (dlines.length === 1 ? prelude.length : 0)
+
+ body = desc + (dlen + extra.length > wrap - 2
+ ? '\n'
+ + new Array(wrap - extra.length + 1).join(' ')
+ + extra
+ : new Array(wrap - extra.length - dlen + 1).join(' ')
+ + extra
+ );
+ }
+
+ help.push(prelude + body);
+ });
+
+ help.push('');
+ return help.join('\n');
+ };
+
+ Object.defineProperty(self, 'argv', {
+ get : parseArgs,
+ enumerable : true,
+ });
+
+ function parseArgs () {
+ var argv = { _ : [], $0 : self.$0 };
+ Object.keys(flags.bools).forEach(function (key) {
+ setArg(key, defaults[key] || false);
+ });
+
+ function setArg (key, val) {
+ var num = Number(val);
+ var value = typeof val !== 'string' || isNaN(num) ? val : num;
+ if (flags.strings[key]) value = val;
+
+ setKey(argv, key.split('.'), value);
+
+ (aliases[key] || []).forEach(function (x) {
+ argv[x] = argv[key];
+ });
+ }
+
+ for (var i = 0; i < args.length; i++) {
+ var arg = args[i];
+
+ if (arg === '--') {
+ argv._.push.apply(argv._, args.slice(i + 1));
+ break;
+ }
+ else if (arg.match(/^--.+=/)) {
+ var m = arg.match(/^--([^=]+)=(.*)/);
+ setArg(m[1], m[2]);
+ }
+ else if (arg.match(/^--no-.+/)) {
+ var key = arg.match(/^--no-(.+)/)[1];
+ setArg(key, false);
+ }
+ else if (arg.match(/^--.+/)) {
+ var key = arg.match(/^--(.+)/)[1];
+ var next = args[i + 1];
+ if (next !== undefined && !next.match(/^-/)
+ && !flags.bools[key]
+ && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
+ setArg(key, next);
+ i++;
+ }
+ else if (/true|false/.test(next)) {
+ setArg(key, next === 'true');
+ i++;
+ }
+ else {
+ setArg(key, true);
+ }
+ }
+ else if (arg.match(/^-[^-]+/)) {
+ var letters = arg.slice(1,-1).split('');
+
+ var broken = false;
+ for (var j = 0; j < letters.length; j++) {
+ if (letters[j+1] && letters[j+1].match(/\W/)) {
+ setArg(letters[j], arg.slice(j+2));
+ broken = true;
+ break;
+ }
+ else {
+ setArg(letters[j], true);
+ }
+ }
+
+ if (!broken) {
+ var key = arg.slice(-1)[0];
+
+ if (args[i+1] && !args[i+1].match(/^-/)
+ && !flags.bools[key]
+ && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
+ setArg(key, args[i+1]);
+ i++;
+ }
+ else if (args[i+1] && /true|false/.test(args[i+1])) {
+ setArg(key, args[i+1] === 'true');
+ i++;
+ }
+ else {
+ setArg(key, true);
+ }
+ }
+ }
+ else {
+ var n = Number(arg);
+ argv._.push(flags.strings['_'] || isNaN(n) ? arg : n);
+ }
+ }
+
+ Object.keys(defaults).forEach(function (key) {
+ if (!(key in argv)) {
+ argv[key] = defaults[key];
+ if (key in aliases) {
+ argv[aliases[key]] = defaults[key];
+ }
+ }
+ });
+
+ if (demanded._ && argv._.length < demanded._) {
+ fail('Not enough non-option arguments: got '
+ + argv._.length + ', need at least ' + demanded._
+ );
+ }
+
+ var missing = [];
+ Object.keys(demanded).forEach(function (key) {
+ if (!argv[key]) missing.push(key);
+ });
+
+ if (missing.length) {
+ fail('Missing required arguments: ' + missing.join(', '));
+ }
+
+ checks.forEach(function (f) {
+ try {
+ if (f(argv) === false) {
+ fail('Argument check failed: ' + f.toString());
+ }
+ }
+ catch (err) {
+ fail(err)
+ }
+ });
+
+ return argv;
+ }
+
+ function longest (xs) {
+ return Math.max.apply(
+ null,
+ xs.map(function (x) { return x.length })
+ );
+ }
+
+ return self;
+};
+
+// rebase an absolute path to a relative one with respect to a base directory
+// exported for tests
+exports.rebase = rebase;
+function rebase (base, dir) {
+ var ds = path.normalize(dir).split('/').slice(1);
+ var bs = path.normalize(base).split('/').slice(1);
+
+ for (var i = 0; ds[i] && ds[i] == bs[i]; i++);
+ ds.splice(0, i); bs.splice(0, i);
+
+ var p = path.normalize(
+ bs.map(function () { return '..' }).concat(ds).join('/')
+ ).replace(/\/$/,'').replace(/^$/, '.');
+ return p.match(/^[.\/]/) ? p : './' + p;
+};
+
+function setKey (obj, keys, value) {
+ var o = obj;
+ keys.slice(0,-1).forEach(function (key) {
+ if (o[key] === undefined) o[key] = {};
+ o = o[key];
+ });
+
+ var key = keys[keys.length - 1];
+ if (o[key] === undefined || typeof o[key] === 'boolean') {
+ o[key] = value;
+ }
+ else if (Array.isArray(o[key])) {
+ o[key].push(value);
+ }
+ else {
+ o[key] = [ o[key], value ];
+ }
+}
diff --git a/build-tools/lib/wordwrap/LICENSE b/build-tools/lib/wordwrap/LICENSE
new file mode 100644
index 00000000..e65c0b24
--- /dev/null
+++ b/build-tools/lib/wordwrap/LICENSE
@@ -0,0 +1,4 @@
+Copyright 2011 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT license:
+http://www.opensource.org/licenses/mit-license.php
diff --git a/build-tools/lib/wordwrap/index.js b/build-tools/lib/wordwrap/index.js
new file mode 100644
index 00000000..c9bc9452
--- /dev/null
+++ b/build-tools/lib/wordwrap/index.js
@@ -0,0 +1,76 @@
+var wordwrap = module.exports = function (start, stop, params) {
+ if (typeof start === 'object') {
+ params = start;
+ start = params.start;
+ stop = params.stop;
+ }
+
+ if (typeof stop === 'object') {
+ params = stop;
+ start = start || params.start;
+ stop = undefined;
+ }
+
+ if (!stop) {
+ stop = start;
+ start = 0;
+ }
+
+ if (!params) params = {};
+ var mode = params.mode || 'soft';
+ var re = mode === 'hard' ? /\b/ : /(\S+\s+)/;
+
+ return function (text) {
+ var chunks = text.toString()
+ .split(re)
+ .reduce(function (acc, x) {
+ if (mode === 'hard') {
+ for (var i = 0; i < x.length; i += stop - start) {
+ acc.push(x.slice(i, i + stop - start));
+ }
+ }
+ else acc.push(x)
+ return acc;
+ }, [])
+ ;
+
+ return chunks.reduce(function (lines, rawChunk) {
+ if (rawChunk === '') return lines;
+
+ var chunk = rawChunk.replace(/\t/g, ' ');
+
+ var i = lines.length - 1;
+ if (lines[i].length + chunk.length > stop) {
+ lines[i] = lines[i].replace(/\s+$/, '');
+
+ chunk.split(/\n/).forEach(function (c) {
+ lines.push(
+ new Array(start + 1).join(' ')
+ + c.replace(/^\s+/, '')
+ );
+ });
+ }
+ else if (chunk.match(/\n/)) {
+ var xs = chunk.split(/\n/);
+ lines[i] += xs.shift();
+ xs.forEach(function (c) {
+ lines.push(
+ new Array(start + 1).join(' ')
+ + c.replace(/^\s+/, '')
+ );
+ });
+ }
+ else {
+ lines[i] += chunk;
+ }
+
+ return lines;
+ }, [ new Array(start + 1).join(' ') ]).join('\n');
+ };
+};
+
+wordwrap.soft = wordwrap;
+
+wordwrap.hard = function (start, stop) {
+ return wordwrap(start, stop, { mode : 'hard' });
+};
diff --git a/build-tools/node_modules b/build-tools/node_modules
new file mode 120000
index 00000000..7951405f
--- /dev/null
+++ b/build-tools/node_modules
@@ -0,0 +1 @@
+lib \ No newline at end of file