diff --git a/README.md b/README.md
index ca58803a5..20f7a0a5e 100644
--- a/README.md
+++ b/README.md
@@ -65,6 +65,7 @@ List of Definitions
* [i18next](http://i18next.com/) (by [Maarten Docter](https://github.com/mdocter))
* [Impress.js](https://github.com/bartaz/impress.js) (by [Boris Yankov](https://github.com/borisyankov))
* [iScroll](http://cubiq.org/iscroll-4) (by [Boris Yankov](https://github.com/borisyankov))
+* [jake](https://github.com/mde/jake) (by [Kon](http://phyzkit.net/))
* [Jasmine](http://pivotal.github.com/jasmine/) (by [Boris Yankov](https://github.com/borisyankov))
* [jQRangeSlider](http://ghusse.github.com/jQRangeSlider) (by [D�niel Tar](https://github.com/qcz))
* [jQuery](http://jquery.com/) (from TypeScript samples)
diff --git a/jake/jake-tests.ts b/jake/jake-tests.ts
new file mode 100644
index 000000000..410764d28
--- /dev/null
+++ b/jake/jake-tests.ts
@@ -0,0 +1,267 @@
+// https://github.com/mde/jake
+///
+
+import path = module("path");
+
+desc('This is the default task.');
+task('default', function (params) {
+ console.log('This is the default task.');
+});
+
+desc('This task has prerequisites.');
+task('hasPrereqs', ['foo', 'bar', 'baz'], function (params) {
+ console.log('Ran some prereqs first.');
+});
+
+desc('This is an asynchronous task.');
+task('asyncTask', {async: true}, function () {
+ setTimeout(complete, 1000);
+});
+
+desc('This builds a minified JS file for production.');
+file('foo-minified.js', ['bar', 'foo-bar.js', 'foo-baz.js'], function () {
+ // Code to concat and minify goes here
+});
+
+desc('This creates the bar directory for use with the foo-minified.js file-task.');
+directory('bar');
+
+desc('This is the default task.');
+task('default', function () {
+ console.log('This is the default task.');
+});
+
+namespace('foo', function () {
+ desc('This the foo:bar task');
+ task('bar', function () {
+ console.log('doing foo:bar task');
+ });
+
+ desc('This the foo:baz task');
+ task('baz', ['default', 'foo:bar'], function () {
+ console.log('doing foo:baz task');
+ });
+
+});
+
+desc('This is an awesome task.');
+task('awesome', function (a, b, c) {
+ console.log(a, b, c);
+});
+
+
+desc('This is an awesome task.');
+task('awesome', function (a, b, c) {
+ console.log(a, b, c);
+ console.log(process.env.qux, process.env.frang);
+});
+
+
+jake.addListener('complete', function () {
+ process.exit();
+});
+
+desc('Calls the foo:bar task and its prerequisites.');
+task('invokeFooBar', function () {
+ // Calls foo:bar and its prereqs
+ jake.Task['foo:bar'].invoke();
+});
+
+desc('Calls the foo:bar task and its prerequisites.');
+task('invokeFooBar', function () {
+ // Calls foo:bar and its prereqs
+ jake.Task['foo:bar'].invoke();
+ // Does nothing
+ jake.Task['foo:bar'].invoke();
+});
+
+desc('Calls the foo:bar task without its prerequisites.');
+task('executeFooBar', function () {
+ // Calls foo:bar without its prereqs
+ jake.Task['foo:baz'].execute();
+});
+
+desc('Calls the foo:bar task without its prerequisites.');
+task('executeFooBar', function () {
+ // Calls foo:bar without its prereqs
+ jake.Task['foo:baz'].execute();
+ // Can keep running this over and over
+ jake.Task['foo:baz'].execute();
+ jake.Task['foo:baz'].execute();
+});
+
+desc('Calls the foo:bar task and its prerequisites.');
+task('invokeFooBar', function () {
+ // Calls foo:bar and its prereqs
+ jake.Task['foo:bar'].invoke();
+ // Does nothing
+ jake.Task['foo:bar'].invoke();
+ // Only re-runs foo:bar, but not its prerequisites
+ jake.Task['foo:bar'].reenable();
+ jake.Task['foo:bar'].invoke();
+});
+
+desc('Calls the foo:bar task and its prerequisites.');
+task('invokeFooBar', function () {
+ // Calls foo:bar and its prereqs
+ jake.Task['foo:bar'].invoke();
+ // Does nothing
+ jake.Task['foo:bar'].invoke();
+ // Re-runs foo:bar and all of its prerequisites
+ jake.Task['foo:bar'].reenable(true);
+ jake.Task['foo:bar'].invoke();
+});
+
+desc('Passes params on to other tasks.');
+task('passParams', function () {
+ var t = jake.Task['foo:bar'];
+ // Calls foo:bar, passing along current args
+ t.invoke.apply(t, arguments);
+});
+
+desc('Calls the async foo:baz task and its prerequisites.');
+task('invokeFooBaz', {async: true}, function () {
+ var t = jake.Task['foo:baz'];
+ t.addListener('complete', function () {
+ console.log('Finished executing foo:baz');
+ // Maybe run some other code
+ // ...
+ // Complete the containing task
+ complete();
+ });
+ // Kick off foo:baz
+ t.invoke();
+});
+
+
+namespace('vronk', function () {
+ task('groo', function () {
+ var t = jake.Task['vronk:zong'];
+ t.addListener('error', function (e) {
+ console.log(e.message);
+ });
+ t.invoke();
+ });
+
+ task('zong', function () {
+ throw new Error('OMFGZONG');
+ });
+});
+
+desc('This task fails.');
+task('failTask', function () {
+ fail('Yikes. Something back happened.');
+});
+
+
+desc('This task fails with an exit-status of 42.');
+task('failTaskQuestionCustomStatus', function () {
+ fail('What is the answer?', 42);
+});
+
+
+declare var sourceDir:string;
+declare var currentDir:string;
+jake.mkdirP('app/views/layouts');
+jake.cpR(path.join(sourceDir, '/templates'), currentDir);
+jake.readdirR('pkg');
+jake.rmRf('pkg');
+
+desc('Runs the Jake tests.');
+task('test', {async: true}, function () {
+ var cmds = [
+ 'node ./tests/parseargs.js'
+ , 'node ./tests/task_base.js'
+ , 'node ./tests/file_task.js'
+ ];
+ jake.exec(cmds, function () {
+ console.log('All tests passed.');
+ complete();
+ }, {printStdout: true});
+});
+
+var ex = jake.createExec(['do_thing.sh'], {printStdout: true});
+ex.addListener('error', function (msg, code) {
+ if (code == 127) {
+ console.log("Couldn't find do_thing script, trying do_other_thing");
+ ex.append('do_other_thing.sh');
+ }
+ else {
+ fail('Fatal error: ' + msg, code);
+ }
+});
+ex.run();
+
+task('echo', {async: true}, function () {
+ jake.exec(['echo "hello"'], function () {
+ jake.logger.log('Done.');
+ complete();
+ }, {printStdout: !jake.program.opts.quiet});
+});
+
+function hoge(){
+ var t = new jake.PackageTask('fonebone', 'v0.1.2112', function () {
+ var fileList = [
+ 'Jakefile'
+ , 'README.md'
+ , 'package.json'
+ , 'lib/*'
+ , 'bin/*'
+ , 'tests/*'
+ ];
+ this.packageFiles.include(fileList);
+ this.needTarGz = true;
+ this.needTarBz2 = true;
+ });
+}
+
+var list = new jake.FileList();
+list.include('foo/*.txt');
+list.include(['bar/*.txt', 'README.md']);
+list.include('Makefile', 'package.json');
+list.exclude('foo/zoobie.txt');
+list.exclude(/foo\/src.*.txt/);
+console.log(list.toArray());
+
+
+var t = new jake.TestTask('fonebone', function () {
+ var fileList = [
+ 'tests/*'
+ , 'lib/adapters/**/test.js'
+ ];
+ this.testFiles.include(fileList);
+ this.testFiles.exclude('tests/helper.js');
+ this.testName = 'testMainAndAdapters';
+});
+
+var assert = require('assert')
+ , tests;
+
+tests = {
+ 'sync test': function () {
+ // Assert something
+ assert.ok(true);
+ }
+, 'async test': function (next) {
+ // Assert something else
+ assert.ok(true);
+ // Won't go next until this is called
+ next();
+ }
+, 'another sync test': function () {
+ // Assert something else
+ assert.ok(true);
+ }
+};
+
+//module.exports = tests;
+
+var p = new jake.NpmPublishTask('jake', [
+ 'Makefile'
+, 'Jakefile'
+, 'README.md'
+, 'package.json'
+, 'lib/*'
+, 'bin/*'
+, 'tests/*'
+]);
\ No newline at end of file
diff --git a/jake/jake.d.ts b/jake/jake.d.ts
new file mode 100644
index 000000000..ec6f20d2b
--- /dev/null
+++ b/jake/jake.d.ts
@@ -0,0 +1,388 @@
+// Type definitions for jake
+// Project: https://github.com/mde/jake
+// Definitions by: Kon
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+///
+
+/**
+ * Complets an asynchronous task, allowing Jake's execution to proceed to the next task
+ */
+function complete(): void;
+
+/**
+ * Creates a description for a Jake Task (or FileTask, DirectoryTask). When invoked, the description that iscreated will be associated with whatever Task is created next.
+ * @param description The description for the Task
+ */
+function desc(description:string): void;
+
+/**
+ * Creates a Jake DirectoryTask. Can be used as a prerequisite for FileTasks, or for simply ensuring a directory exists for use with a Task's action.
+ * @param name The name of the DiretoryTask
+ */
+function directory(name:string): jake.DirectoryTask;
+
+
+/**
+ * Causes Jake execution to abort with an error. Allows passing an optional error code, which will be used to set the exit-code of exiting process.
+ * @param err The error to thow when aborting execution. If this argument is an Error object, it will simply be thrown. If a String, it will be used as the error-message. (If it is a multi-line String, the first line will be used as the Error message, and the remaining lines will be used as the error-stack.)
+ */
+function fail(...err:string[]): void;
+function fail(...err:Error[]): void;
+function fail(...err:any[]): void;
+
+/**
+ * Creates a Jake FileTask.
+ * @name name The name of the Task
+ * @param prereqs Prerequisites to be run before this task
+ * @param action The action to perform for this task
+ * @param opts Perform this task asynchronously. If you flag a task with this option, you must call the global `complete` method inside the task's action, for execution to proceed to the next task.
+ */
+function file(name:string, prereqs?:string[], action?:()=>void, opts?:jake.FileTaskOptions): jake.FileTask;
+
+/**
+ * Creates a namespace which allows logical grouping of tasks, and prevents name-collisions with task-names. Namespaces can be nested inside of other namespaces.
+ * @param name The name of the namespace
+ * @param scope The enclosing scope for the namespaced tasks
+ */
+function namespace(name:string, scope:()=>void): void;
+
+/**
+ * @param name The name of the Task
+ * @param prereqs Prerequisites to be run before this task
+ * @param action The action to perform for this task
+ * @param opts
+ */
+function task(name:string, prereqs?:string[], action?:(...params:any[])=>any, opts?:jake.TaskOptions): jake.Task;
+function task(name:string, action?:(...params:any[])=>any, opts?:jake.TaskOptions): jake.Task;
+function task(name:string, opts?:jake.TaskOptions, action?:(...params:any[])=>any): jake.Task;
+
+module jake{
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // File-utils //////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////////
+
+ interface UtilOptions{
+ silent?: bool;
+ }
+
+ /**
+ * The jake.mkdirP utility recursively creates a set of nested directories. It will not throw an error if any of the directories already exists.
+ * https://github.com/substack/node-mkdirp
+ */
+ export function mkdirP(name:string, mode?:string, f?:(er:Error, made:any)=>void): void;
+ export function mkdirP(name:string, f?:(er:Error, made:any)=>void): void;
+
+ /**
+ * The jake.cpR utility does a recursive copy of a file or directory.
+ * Note that this command can only copy files and directories; it does not perform globbing (so arguments like '*.txt' are not possible).
+ * @param path the file/directory to copy,
+ * @param destination the destination.
+ */
+ export function cpR(path:string, destination:string, opts?:UtilOptions, callback?:()=>void): void;
+ export function cpR(path:string, destination:string, callback?:(err:Error)=>void): void;
+
+ /**
+ * The jake.readdirR utility gives you a recursive directory listing, giving you output somewhat similar to the Unix find command. It only works with a directory name, and does not perform filtering or globbing.
+ * @return an array of filepaths for all files in the 'pkg' directory, and all its subdirectories.
+ */
+ export function readdirR(name:string, opts?:UtilOptions): string[];
+
+ /**
+ * The jake.rmRf utility recursively removes a directory and all its contents.
+ */
+ export function rmRf(name:string, opts?:UtilOptions): void;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // Running shell-commands ////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////////
+
+ interface ExecOptions{
+ /**
+ * print to stdout, default false
+ */
+
+ printStdout?:bool;
+ /**
+ * print to stderr, default false
+ */
+ printStderr?:bool;
+
+ /**
+ * stop execution on error, default true
+ */
+ breakOnError?:bool;
+ }
+ export function exec(cmds:string[], callback?:()=>void, opts?:ExecOptions);
+
+
+ /**
+ * @event cmdStart When a new command begins to run. Passes one arg, the command being run.
+ * @event cmdEnd When a command finishes. Passes one arg, the command being run.
+ * @event stdout When the stdout for the child-process recieves data. This streams the stdout data. Passes one arg, the chunk of data.
+ * @event stderr When the stderr for the child-process recieves data. This streams the stderr data. Passes one arg, the chunk of data.
+ * @event error When a shell-command
+ */
+ export interface Exec extends EventEmitter{
+ constructor(cmds:string[], callback?:()=>void, opts?:ExecOptions);
+ constructor(cmds:string[], opts?:ExecOptions, callback?:()=>void);
+ constructor(cmds:string, callback?:()=>void, opts?:ExecOptions);
+ constructor(cmds:string, opts?:ExecOptions, callback?:()=>void);
+ append(cmd:string): void;
+ run(): void;
+ }
+
+ export function createExec(cmds:string[], callback?:()=>void, opts?:ExecOptions ):Exec;
+ export function createExec(cmds:string[], opts?:ExecOptions, callback?:()=>void):Exec;
+ export function createExec(cmds:string, callback?:()=>void, opts?:ExecOptions ):Exec;
+ export function createExec(cmds:string, opts?:ExecOptions, callback?:()=>void):Exec;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Logging and output ////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ interface Logger{
+ log(value:any): void;
+ error(value:any): void;
+ }
+
+ export var logger: Logger;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // program ////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ export var program: {
+ opts: {
+ [name:string]: any;
+ quiet: bool;
+ };
+ taskNames: string[];
+ taskArgs: string[];
+ envVars: { [key:string]: string; };
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Tasks /////////////////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ export interface TaskOptions{
+ /**
+ * Perform this task asynchronously. If you flag a task with this option, you must call the global `complete` method inside the task's action, for execution to proceed to the next task.
+ * @default false
+ */
+ asyc?: bool;
+ }
+
+ /**
+ * A Jake Task
+ *
+ * @event complete
+ */
+ export class Task implements EventEmitter{
+ /**
+ * @name name The name of the Task
+ * @param prereqs Prerequisites to be run before this task
+ * @param action The action to perform for this task
+ * @param opts Perform this task asynchronously. If you flag a task with this option, you must call the global `complete` method inside the task's action, for execution to proceed to the next task.
+ */
+ constructor(name:string, prereqs?:string[], action?:()=>void, opts?:TaskOptions);
+
+ /**
+ * Runs prerequisites, then this task. If the task has already been run, will not run the task again.
+ */
+ invoke(): void;
+
+ /**
+ * Runs this task, without running any prerequisites. If the task has already been run, it will still run it again.
+ */
+ reenable(): void;
+
+ addListener(event: string, listener: Function);
+ on(event: string, listener: Function);
+ once(event: string, listener: Function): void;
+ removeListener(event: string, listener: Function): void;
+ removeAllListener(event: string): void;
+ setMaxListeners(n: number): void;
+ listeners(event: string): { Function; }[];
+ emit(event: string, arg1?: any, arg2?: any): void;
+ }
+
+
+
+ export class DirectoryTask{
+ /**
+ * @param name The name of the directory to create.
+ */
+ constructor(name:string);
+ }
+
+ export interface FileTaskOptions{
+ /**
+ * Perform this task asynchronously. If you flag a task with this option, you must call the global `complete` method inside the task's action, for execution to proceed to the next task.
+ * @default false
+ */
+ asyc?: bool;
+ }
+
+ export class FileTask{
+ /**
+ * @param name The name of the Task
+ * @param prereqs Prerequisites to be run before this task
+ * @param action The action to perform to create this file
+ * @param opts Perform this task asynchronously. If you flag a task with this option, you must call the global `complete` method inside the task's action, for execution to proceed to the next task.
+ */
+ constructor(name:string, prereqs?:string[], action?:()=>void, opts?:FileTaskOptions);
+ }
+
+ interface FileFilter{
+ (filename:string): bool;
+ }
+
+ export class FileList{
+ constructor();
+
+ /**
+ * Includes file-patterns in the FileList. Should be called with one or more
+ * pattern for finding file to include in the list. Arguments should be strings
+ * for either a glob-pattern or a specific file-name, or an array of them
+ */
+ include(files:string[]): void;
+ include(...files:string[]): void;
+
+ /**
+ * Indicates whether a particular file would be filtered out by the current
+ * exclusion rules for this FileList.
+ * @param name The filename to check
+ * @return Whether or not the file should be excluded
+ */
+ shouldExclude(name:string): bool;
+
+ /**
+ * Excludes file-patterns from the FileList. Should be called with one or more
+ * pattern for finding file to include in the list. Arguments can be:
+ * 1. Strings for either a glob-pattern or a specific file-name
+ * 2. Regular expression literals
+ * 3. Functions to be run on the filename that return a true/false
+ */
+ exclude(file:string[]): void;
+ exclude(...file:string[]): void;
+ exclude(file:RegExp[]): void;
+ exclude(...file:RegExp[]): void;
+ exclude(file:FileFilter[]): void;
+ exclude(...file:FileFilter[]): void;
+
+
+ /**
+ * Populates the FileList from the include/exclude rules with a list of
+ * actual files
+ */
+ resolve(): void;
+
+ /**
+ * Convert to a plain-jane array
+ */
+ toArray(): string[];
+
+ /**
+ * Get rid of any current exclusion rules
+ */
+ clearExclude(): void;
+ }
+
+ export class PackageTask{
+ /**
+ * Instantiating a PackageTask creates a number of Jake Tasks that make packaging and distributing your software easy.
+ * @param name The name of the project
+ * @param version The current project version (will be appended to the project-name in the package-archive
+ * @param definition Defines the contents of the package, and format of the package-archive. Will be executed on the instantiated PackageTask (i.e., 'this', will be the PackageTask instance), to set the various instance-propertiess.
+ */
+ constructor(name:string, version:string, definition:()=>void);
+
+ /**
+ * Equivalent to the '-C' command for the `tar` and `jar` commands. ("Change to this directory before adding files.")
+ */
+ archiveChangeDir: string;
+
+ /**
+ * Specifies the files and directories to include in the package-archive. If unset, this will default to the main package directory -- i.e., name + version.
+ */
+ archiveContentDir: string;
+
+ /**
+ * The shell-command to use for creating jar archives.
+ */
+ jarCommand: string;
+
+ /**
+ * Can be set to point the `jar` utility at a manifest file to use in a .jar archive. If unset, one will be automatically created by the `jar` utility. This path should be relative to the root of the package directory (this.packageDir above, likely 'pkg')
+ */
+ manifestFile: string;
+
+ /**
+ * The name of the project
+ */
+ name: string;
+
+ /**
+ * If set to true, uses the `jar` utility to create a .jar archive of the pagckage
+ */
+ needJar: bool;
+
+ /**
+ * If set to true, uses the `tar` utility to create a gzip .tgz archive of the pagckage
+ */
+ needTar: bool;
+
+ /**
+ * If set to true, uses the `tar` utility to create a bzip2 .bz2 archive of the pagckage
+ */
+ needTarBz2: bool;
+
+ /**
+ * If set to true, uses the `zip` utility to create a .zip archive of the pagckage
+ */
+ needZip: bool;
+
+ /**
+ * The list of files and directories to include in the package-archive
+ */
+ packageFiles: FileList;
+
+ /**
+ * The shell-command to use for creating tar archives.
+ */
+ tarCommand: string;
+
+ /**
+ * The project version-string
+ */
+ version: string;
+
+ /**
+ * The shell-command to use for creating zip archives.
+ */
+ zipCommand: string;
+
+ }
+
+ export class TestTask{
+ constructor(name:string, definition?:()=>void);
+ }
+
+ export class NpmPublishTask{
+ constructor(name:string, packageFiles:string[]);
+ }
+
+ export function addListener(event: string, listener: Function);
+ export function on(event: string, listener: Function);
+ export function once(event: string, listener: Function): void;
+ export function removeListener(event: string, listener: Function): void;
+ export function removeAllListener(event: string): void;
+ export function setMaxListeners(n: number): void;
+ export function listeners(event: string): { Function; }[];
+ export function emit(event: string, arg1?: any, arg2?: any): void;
+}
\ No newline at end of file