<commit_before>// Generated on 2014-02-20 using generator-angular 0.7.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: {
      // configurable paths
      version: require('./bower.json').version,
      app: require('./bower.json').appPath,
      dist: 'dist'
    },

		bump: {
			options: {
				files: ['package.json', 'bower.json'],
				updateConfigs: ['yeoman'],
				commit: true,
				commitMessage: 'Release v%VERSION%. See CHANGELOG.md',
				commitFiles: ['-a'], // '-a' for all files
				createTag: true,
				tagName: 'v%VERSION%',
				tagMessage: 'Version %VERSION%',
				push: true,
				pushTo: 'origin master',
				gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d' // options to use with '$ git describe'
			}
		},

		changelog: {
			options: {
				// We'll use defaults for everything. https://github.com/btford/grunt-conventional-changelog
			}
		},

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'test'],
        options: {
          livereload: true
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      test: {
        options: {
          port: 9001,
          base: [
            'test',
            '<%= yeoman.app %>'
          ]
        }
      },
      livereload: {
        options: {
          open: true,
          base: [
            '<%= yeoman.app %>'
          ]
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= yeoman.app %>/scripts/{,*/}*.js'
      ],
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '<%= yeoman.dist %>/*',
            '!<%= yeoman.dist %>/.git*'
          ]
        }]
      }
    },

    // Allow the use of non-minsafe AngularJS files. Automatically makes it
    // minsafe compatible so Uglify does not destroy the ng references
		ngAnnotate: {
      dist: {
        src: ['<%= yeoman.dist %>/angular-apimock.js'],
        dest: '<%= yeoman.dist %>/angular-apimock.js'
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    uglify: {
      options: {
        preserveComments: 'some',
        report: 'gzip'
      },
      dist: {
        files: {
          '<%= yeoman.dist %>/angular-apimock.min.js': [
            '<%= yeoman.dist %>/angular-apimock.js'
          ]
        }
      }
    },

    concat: {
      options: {
        banner: '/*! Angular API Mock v<%= yeoman.version %>\n * Licensed with MIT\n * Made with ♥ from Seriema + Redhorn */\n',
      },
      dist: {
        src: '<%= yeoman.app %>/scripts/**/*.js',
        dest: '<%= yeoman.dist %>/angular-apimock.js'
      }
    },

		nugetpack: {
			dist: {
				src: 'package.nuspec',
				dest: 'nuget/',
				options: {
					version: '<%= yeoman.version %>'
				}
			}
		},

		nugetpush: {
			dist: {
				src: 'nuget/Angular-ApiMock.<%= yeoman.version %>.nupkg'
			}
		},

    // Test settings
    karma: {
      options: {
        configFile: 'karma.conf.js',
        singleRun: true
      },
      angular12: {
        files: [{
          src: [
            'test/ref/angular-v1.2.js',
            'test/ref/angular-mocks-v1.2.js',
            '<%= watch.js.files %>',
            '<%= watch.jsTest.files %>'
          ]}
        ]
      },
      angular13: {
        files: [{
          src: [
            'test/ref/angular-v1.3.js',
            'test/ref/angular-mocks-v1.3.js',
            '<%= watch.js.files %>',
            '<%= watch.jsTest.files %>'
          ]}
        ]
      },
      angular14: {
        files: [{
          src: [
            'test/ref/angular-v1.4.js',
            'test/ref/angular-mocks-v1.4.js',
            '<%= watch.js.files %>',
            '<%= watch.jsTest.files %>'
          ]}
        ]
      }
    }
  });

  grunt.registerTask('serve', [
    'connect',
    'watch:js'
  ]);

  grunt.registerTask('test', [
    'newer:jshint',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('fulltest', [
    'jshint',
    'connect:test',
    'karma'
  ]);

	grunt.registerTask('build', [
		'clean',
		'concat',
		'ngAnnotate',
		'uglify'
	]);

  grunt.registerTask('_publish', [
		'build',
		'nugetpack',
		'changelog',
		'bump-commit',
		'nugetpush'
  ]);

	grunt.registerTask('publish', ['publish:patch']);
	grunt.registerTask('publish:patch', ['fulltest', 'bump-only:patch', '_publish']);
	grunt.registerTask('publish:minor', ['fulltest', 'bump-only:minor', '_publish']);
	grunt.registerTask('publish:major', ['fulltest', 'bump-only:major', '_publish']);

	grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<commit_msg>chore(grunt): add headless browser for watch test task<commit_after>// Generated on 2014-02-20 using generator-angular 0.7.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: {
      // configurable paths
      version: require('./bower.json').version,
      app: require('./bower.json').appPath,
      dist: 'dist'
    },

		bump: {
			options: {
				files: ['package.json', 'bower.json'],
				updateConfigs: ['yeoman'],
				commit: true,
				commitMessage: 'Release v%VERSION%. See CHANGELOG.md',
				commitFiles: ['-a'], // '-a' for all files
				createTag: true,
				tagName: 'v%VERSION%',
				tagMessage: 'Version %VERSION%',
				push: true,
				pushTo: 'origin master',
				gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d' // options to use with '$ git describe'
			}
		},

		changelog: {
			options: {
				// We'll use defaults for everything. https://github.com/btford/grunt-conventional-changelog
			}
		},

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'karma:headless'],
        options: {
          livereload: true
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma:headless']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      test: {
        options: {
          port: 9001,
          base: [
            'test',
            '<%= yeoman.app %>'
          ]
        }
      },
      livereload: {
        options: {
          open: true,
          base: [
            '<%= yeoman.app %>'
          ]
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= yeoman.app %>/scripts/{,*/}*.js'
      ],
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '<%= yeoman.dist %>/*',
            '!<%= yeoman.dist %>/.git*'
          ]
        }]
      }
    },

    // Allow the use of non-minsafe AngularJS files. Automatically makes it
    // minsafe compatible so Uglify does not destroy the ng references
		ngAnnotate: {
      dist: {
        src: ['<%= yeoman.dist %>/angular-apimock.js'],
        dest: '<%= yeoman.dist %>/angular-apimock.js'
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    uglify: {
      options: {
        preserveComments: 'some',
        report: 'gzip'
      },
      dist: {
        files: {
          '<%= yeoman.dist %>/angular-apimock.min.js': [
            '<%= yeoman.dist %>/angular-apimock.js'
          ]
        }
      }
    },

    concat: {
      options: {
        banner: '/*! Angular API Mock v<%= yeoman.version %>\n * Licensed with MIT\n * Made with ♥ from Seriema + Redhorn */\n',
      },
      dist: {
        src: '<%= yeoman.app %>/scripts/**/*.js',
        dest: '<%= yeoman.dist %>/angular-apimock.js'
      }
    },

		nugetpack: {
			dist: {
				src: 'package.nuspec',
				dest: 'nuget/',
				options: {
					version: '<%= yeoman.version %>'
				}
			}
		},

		nugetpush: {
			dist: {
				src: 'nuget/Angular-ApiMock.<%= yeoman.version %>.nupkg'
			}
		},

    // Test settings
    karma: {
      options: {
        configFile: 'karma.conf.js',
        singleRun: true
      },
      headless: {
        browsers: ['PhantomJS']
      },
      angular12: {
        files: [{
          src: [
            'test/ref/angular-v1.2.js',
            'test/ref/angular-mocks-v1.2.js',
            '<%= watch.js.files %>',
            '<%= watch.jsTest.files %>'
          ]}
        ]
      },
      angular13: {
        files: [{
          src: [
            'test/ref/angular-v1.3.js',
            'test/ref/angular-mocks-v1.3.js',
            '<%= watch.js.files %>',
            '<%= watch.jsTest.files %>'
          ]}
        ]
      },
      angular14: {
        files: [{
          src: [
            'test/ref/angular-v1.4.js',
            'test/ref/angular-mocks-v1.4.js',
            '<%= watch.js.files %>',
            '<%= watch.jsTest.files %>'
          ]}
        ]
      }
    }
  });

  grunt.registerTask('serve', [
    'connect',
    'watch:js'
  ]);

  grunt.registerTask('test', [
    'newer:jshint',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('fulltest', [
    'jshint',
    'connect:test',
    'karma'
  ]);

	grunt.registerTask('build', [
		'clean',
		'concat',
		'ngAnnotate',
		'uglify'
	]);

  grunt.registerTask('_publish', [
		'build',
		'nugetpack',
		'changelog',
		'bump-commit',
		'nugetpush'
  ]);

	grunt.registerTask('publish', ['publish:patch']);
	grunt.registerTask('publish:patch', ['fulltest', 'bump-only:patch', '_publish']);
	grunt.registerTask('publish:minor', ['fulltest', 'bump-only:minor', '_publish']);
	grunt.registerTask('publish:major', ['fulltest', 'bump-only:major', '_publish']);

	grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

	grunt.initConfig({

		dir: {
			src: 'src',
			src_qrcode: 'node_modules/qrcodejs',
			dest: 'dist',
			demo: 'demo',
			bower_components: 'bower_components'
		},

		copy: {

		},

		clean: {
			dist: '<%= dir.dest %>/**'
		},

		eslint: {
            options: {
                configFile: './.eslintrc'
            },

            demo: ['<%= dir.demo %>']
        },

		connect: {
			options: {
				port: 8080,
				hostname: '*'
			},
			src: {},
			dist: {}
		},

		openui5_connect: {
			options: {
				resources: [
					'<%= dir.bower_components %>/openui5-sap.ui.core/resources',
					'<%= dir.bower_components %>/openui5-sap.m/resources',
					'<%= dir.bower_components %>/openui5-sap.ui.layout/resources',
					'<%= dir.bower_components %>/openui5-themelib_sap_belize/resources'
				]
			},
			src: {
				options: {
					appresources: '<%= dir.demo %>'
				}
			},
			dist: {
				options: {
					appresources: '<%= dir.demo %>'
				}
			}
		},

		openui5_preload: {
		    library: {
		        options: {
		            resources: [
		                { cwd: '<%= dir.src %>' },
		                { cwd: '<%= dir.src_qrcode %>', src: 'qrcode.js', prefix: 'it/designfuture/qrcode/3rdparty' }
		            ],
		            dest: '<%= dir.dest %>',
		            compatVersion: '1.44',
		            compress: false
		        },
		        libraries: 'it/designfuture/qrcode'
		    }
		}
	});

	// These publins provide necessary tasks
	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-openui5');
	grunt.loadNpmTasks('grunt-eslint');
    grunt.loadNpmTasks("grunt-contrib-watch");

	// Server task
	grunt.registerTask('serve', function(target) {
		grunt.task.run('openui5_connect:' + (target || 'src') + ':keepalive');
	});

	// Linting task
	grunt.registerTask('lint', ['eslint']);

	// Build task
	grunt.registerTask('build', ['openui5_preload']);

	// Default task
	grunt.registerTask('default', [
		'lint',
		'clean',
		'build',
		'serve:demo'
	]);

};<commit_msg>Updated tasks config (to add auto-rebuild on file change)<commit_after>module.exports = function(grunt) {

	grunt.initConfig({

		dir: {
			src: 'src',
			src_qrcode: 'node_modules/qrcodejs',
			dest: 'dist',
			demo: 'test/demo',
			bower_components: 'bower_components'
		},

		watch: {
			options: {
				livereload: true
			},
			css: {
				files: ['<%= dir.src %>/**/*.less', '<%= dir.src %>/**/*.css'],
				tasks: ['build']
			},
			js: {
				files: ['<%= dir.src %>/**/*.js'],
				tasks: ['build']
			}
		},

		copy: {
			main: {
				expand: true,
				cwd: '<%= dir.dest %>/',
				src: ['**'],
				dest: '<%= dir.demo %>/thirdparty/',
			},
		},

		clean: {
			dist: '<%= dir.dest %>/**'
		},

		eslint: {
            options: {
                configFile: './.eslintrc'
            },

            demo: ['<%= dir.demo %>']
        },

		connect: {
			options: {
				port: 8080,
				hostname: '*'
			},
			src: {},
			dist: {}
		},

		openui5_connect: {
			options: {
				resources: [
					'<%= dir.bower_components %>/openui5-sap.ui.core/resources',
					'<%= dir.bower_components %>/openui5-sap.m/resources',
					'<%= dir.bower_components %>/openui5-sap.ui.layout/resources',
					'<%= dir.bower_components %>/openui5-themelib_sap_belize/resources'
				]
			},
			src: {
				options: {
					appresources: '<%= dir.demo %>'
				}
			},
			dist: {
				options: {
					appresources: '<%= dir.demo %>'
				}
			}
		},

		openui5_preload: {
		    library: {
		        options: {
		            resources: [
		                { cwd: '<%= dir.src %>' },
		                { cwd: '<%= dir.src_qrcode %>', src: 'qrcode.js', prefix: 'it/designfuture/qrcode/3rdparty' }
		            ],
		            dest: '<%= dir.dest %>',
		            compatVersion: '1.44',
		            compress: false
		        },
		        libraries: 'it/designfuture/qrcode'
		    }
		}
	});

	// These publins provide necessary tasks
	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-openui5');
	grunt.loadNpmTasks('grunt-eslint');
    grunt.loadNpmTasks("grunt-contrib-watch");

	// Server task
	grunt.registerTask('serve', function(target) {
		grunt.task.run('openui5_connect:' + (target || 'src') );
		grunt.task.run('watch');
	});

	// Linting task
	grunt.registerTask('lint', ['eslint']);

	// Build task
	grunt.registerTask('build', ['clean', 'openui5_preload', 'copy']);

	// Default task
	grunt.registerTask('default', [
		'lint',
		'clean',
		'build',
		'serve'
	]);

};<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License.  You may obtain a copy
// of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
// License for the specific language governing permissions and limitations under
// the License.

(function($) {
  $.couch = $.couch || {};
  $.extend($.couch, {

    activeTasks: function(options) {
      options = options || {};
      $.ajax({
        type: "GET", url: "/_active_tasks", dataType: "json",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else  if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("Active task status could not be retrieved: " +
              resp.reason);
          }
        }
      });
    },

    allDbs: function(options) {
      options = options || {};
      $.ajax({
        type: "GET", url: "/_all_dbs",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("An error occurred retrieving the list of all databases: " +
              resp.reason);
          }
        }
      });
    },

    config: function(options, section, option, value) {
      options = options || {};
      var url = "/_config/";
      if (section) {
        url += encodeURIComponent(section) + "/";
        if (option) {
          url += encodeURIComponent(option);
        }
      }
      if (value === undefined) {
        var method = "GET";
      } else {
        var method = "PUT";
        var data = toJSON(value);
      }
      $.ajax({
        type: method, url: url, contentType: "application/json",
        dataType: "json", data: toJSON(value), processData: false,
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("An error occurred retrieving/updating the server " +
              "configuration: " + resp.reason);
          }
        }
      });
    },

    db: function(name) {
      return {
        name: name,
        uri: "/" + encodeURIComponent(name) + "/",

        compact: function(options) {
          options = options || {};
          $.ajax({
            type: "POST", url: this.uri + "_compact",
            contentType: "application/json",
            dataType: "json", data: "", processData: false,
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 202) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The database could not be compacted: " + resp.reason);
              }
            }
          });
        },
        create: function(options) {
          options = options || {};
          $.ajax({
            type: "PUT", url: this.uri, contentType: "application/json",
            dataType: "json", data: "", processData: false,
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 201) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The database could not be created: " + resp.reason);
              }
            }
          });
        },
        drop: function(options) {
          options = options || {};
          $.ajax({
            type: "DELETE", url: this.uri, dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The database could not be deleted: " + resp.reason);
              }
            }
          });
        },
        info: function(options) {
          options = options || {};
          $.ajax({
            type: "GET", url: this.uri, dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else  if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("Database information could not be retrieved: " +
                  resp.reason);
              }
            }
          });
        },
        allDocs: function(options) {
          options = options || {};
          $.ajax({
            type: "GET", url: this.uri + "_all_docs" + encodeOptions(options),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("An error occurred retrieving a list of all documents: " +
                  resp.reason);
              }
            }
          });
        },
        allDesignDocs: function(options) {
          options = options || {};
          this.allDocs($.extend({startkey:"_design", endkey:"_design0"}, options));
        },
        allApps: function(options) {
          options = options || {};
          var self = this;
          if (options.eachApp) {
            this.allDesignDocs({
              success: function(resp) {
                $.each(resp.rows, function() {
                  self.openDoc(this.id, {
                    success: function(ddoc) {
                      var index, appPath, appName = ddoc._id.split('/');
                      appName.shift();
                      appName = appName.join('/');
                      index = ddoc.couchapp && ddoc.couchapp.index;
                      if (index) {
                        appPath = ['', name, ddoc._id, index].join('/');
                      } else if (ddoc._attachments && ddoc._attachments["index.html"]) {
                        appPath = ['', name, ddoc._id, "index.html"].join('/');
                      }
                      if (appPath) options.eachApp(appName, appPath, ddoc);
                    }
                  });
                });
              }
            });
          } else {
            alert("please provide an eachApp function for allApps()");
          }
        },
        openDoc: function(docId, options, ajaxOptions) {
          options = options || {};
          ajaxOptions = ajaxOptions || {};
          $.ajax($.extend({
            type: "GET",
            url: this.uri + encodeURIComponent(docId) + encodeOptions(options),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The document could not be retrieved: " + resp.reason);
              }
            }
          }, ajaxOptions));
        },
        saveDoc: function(doc, options) {
          options = options || {};
          if (doc._id === undefined) {
            var method = "POST";
            var uri = this.uri;
          } else {
            var method = "PUT";
            var uri = this.uri  + encodeURIComponent(doc._id);
          }
          $.ajax({
            type: method, url: uri + encodeOptions(options),
            contentType: "application/json",
            dataType: "json", data: toJSON(doc),
            complete: function(req) {
              var resp = $.httpData(req, "json")
              doc._id = resp.id;
              doc._rev = resp.rev;
              if (req.status == 201) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The document could not be saved: " + resp.reason);
              }
            }
          });
        },
        removeDoc: function(doc, options) {
          options = options || {};
          $.ajax({
            type: "DELETE",
            url: this.uri + encodeURIComponent(doc._id) + encodeOptions({rev: doc._rev}),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The document could not be deleted: " + resp.reason);
              }
            }
          });
        },
        query: function(mapFun, reduceFun, language, options) {
          options = options || {};
          language = language || "javascript"
          if (typeof(mapFun) != "string") {
            mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")";
          }
          var body = {language: language, map: mapFun};
          if (reduceFun != null) {
            if (typeof(reduceFun) != "string")
              reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")";
            body.reduce = reduceFun;
          }
          $.ajax({
            type: "POST", url: this.uri + "_temp_view" + encodeOptions(options),
            contentType: "application/json",
            data: toJSON(body), dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("An error occurred querying the database: " + resp.reason);
              }
            }
          });
        },
        view: function(name, options) {
          options = options || {};
          name = name.split('/');
          $.ajax({
            type: "GET", url: this.uri + "_design/" + name[0] + "/_view/" + name[1] + encodeOptions(options),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("An error occurred accessing the view: " + resp.reason);
              }
            }
          });
        }
      };
    },

    info: function(options) {
      options = options || {};
      $.ajax({
        type: "GET", url: "/", dataType: "json",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("Server information could not be retrieved: " + resp.reason);
          }
        }
      });
    },

    replicate: function(source, target, options) {
      options = options || {};
      $.ajax({
        type: "POST", url: "/_replicate", dataType: "json",
        data: JSON.stringify({source: source, target: target}),
        contentType: "application/json",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("Replication failed: " + resp.reason);
          }
        }
      });
    }

  });

  // Convert a options object to an url query string.
  // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"'
  function encodeOptions(options) {
    var buf = []
    if (typeof(options) == "object" && options !== null) {
      for (var name in options) {
        if (name == "error" || name == "success") continue;
        var value = options[name];
        if (name == "key" || name == "startkey" || name == "endkey") {
          value = toJSON(value);
        }
        buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value));
      }
    }
    return buf.length ? "?" + buf.join("&") : "";
  }

  function toJSON(obj) {
    return obj !== null ? JSON.stringify(obj) : null;
  }

})(jQuery);
<commit_msg>add bulkSave method to jquery.couch.js<commit_after>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License.  You may obtain a copy
// of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
// License for the specific language governing permissions and limitations under
// the License.

(function($) {
  $.couch = $.couch || {};
  $.extend($.couch, {

    activeTasks: function(options) {
      options = options || {};
      $.ajax({
        type: "GET", url: "/_active_tasks", dataType: "json",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else  if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("Active task status could not be retrieved: " +
              resp.reason);
          }
        }
      });
    },

    allDbs: function(options) {
      options = options || {};
      $.ajax({
        type: "GET", url: "/_all_dbs",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("An error occurred retrieving the list of all databases: " +
              resp.reason);
          }
        }
      });
    },

    config: function(options, section, option, value) {
      options = options || {};
      var url = "/_config/";
      if (section) {
        url += encodeURIComponent(section) + "/";
        if (option) {
          url += encodeURIComponent(option);
        }
      }
      if (value === undefined) {
        var method = "GET";
      } else {
        var method = "PUT";
        var data = toJSON(value);
      }
      $.ajax({
        type: method, url: url, contentType: "application/json",
        dataType: "json", data: toJSON(value), processData: false,
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("An error occurred retrieving/updating the server " +
              "configuration: " + resp.reason);
          }
        }
      });
    },

    db: function(name) {
      return {
        name: name,
        uri: "/" + encodeURIComponent(name) + "/",

        compact: function(options) {
          options = options || {};
          $.ajax({
            type: "POST", url: this.uri + "_compact",
            contentType: "application/json",
            dataType: "json", data: "", processData: false,
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 202) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The database could not be compacted: " + resp.reason);
              }
            }
          });
        },
        create: function(options) {
          options = options || {};
          $.ajax({
            type: "PUT", url: this.uri, contentType: "application/json",
            dataType: "json", data: "", processData: false,
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 201) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The database could not be created: " + resp.reason);
              }
            }
          });
        },
        drop: function(options) {
          options = options || {};
          $.ajax({
            type: "DELETE", url: this.uri, dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The database could not be deleted: " + resp.reason);
              }
            }
          });
        },
        info: function(options) {
          options = options || {};
          $.ajax({
            type: "GET", url: this.uri, dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else  if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("Database information could not be retrieved: " +
                  resp.reason);
              }
            }
          });
        },
        allDocs: function(options) {
          options = options || {};
          $.ajax({
            type: "GET", url: this.uri + "_all_docs" + encodeOptions(options),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("An error occurred retrieving a list of all documents: " +
                  resp.reason);
              }
            }
          });
        },
        allDesignDocs: function(options) {
          options = options || {};
          this.allDocs($.extend({startkey:"_design", endkey:"_design0"}, options));
        },
        allApps: function(options) {
          options = options || {};
          var self = this;
          if (options.eachApp) {
            this.allDesignDocs({
              success: function(resp) {
                $.each(resp.rows, function() {
                  self.openDoc(this.id, {
                    success: function(ddoc) {
                      var index, appPath, appName = ddoc._id.split('/');
                      appName.shift();
                      appName = appName.join('/');
                      index = ddoc.couchapp && ddoc.couchapp.index;
                      if (index) {
                        appPath = ['', name, ddoc._id, index].join('/');
                      } else if (ddoc._attachments && ddoc._attachments["index.html"]) {
                        appPath = ['', name, ddoc._id, "index.html"].join('/');
                      }
                      if (appPath) options.eachApp(appName, appPath, ddoc);
                    }
                  });
                });
              }
            });
          } else {
            alert("please provide an eachApp function for allApps()");
          }
        },
        openDoc: function(docId, options, ajaxOptions) {
          options = options || {};
          ajaxOptions = ajaxOptions || {};
          $.ajax($.extend({
            type: "GET",
            url: this.uri + encodeURIComponent(docId) + encodeOptions(options),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The document could not be retrieved: " + resp.reason);
              }
            }
          }, ajaxOptions));
        },
        saveDoc: function(doc, options) {
          options = options || {};
          if (doc._id === undefined) {
            var method = "POST";
            var uri = this.uri;
          } else {
            var method = "PUT";
            var uri = this.uri  + encodeURIComponent(doc._id);
          }
          $.ajax({
            type: method, url: uri + encodeOptions(options),
            contentType: "application/json",
            dataType: "json", data: toJSON(doc),
            complete: function(req) {
              var resp = $.httpData(req, "json");
              doc._id = resp.id;
              doc._rev = resp.rev;
              if (req.status == 201) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The document could not be saved: " + resp.reason);
              }
            }
          });
        },
        bulkSave: function(docs, options) {
          options = options || {};
          $.ajax({
            type: 'POST', url: this.uri + "_bulk_docs" + encodeOptions(options),
            contentType: "application/json",
            dataType: "json", data: toJSON({docs: docs}),
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 201) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The documents could not be saved: " + resp.reason);
              }
            }
          });
        },
        removeDoc: function(doc, options) {
          options = options || {};
          $.ajax({
            type: "DELETE",
            url: this.uri + encodeURIComponent(doc._id) + encodeOptions({rev: doc._rev}),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("The document could not be deleted: " + resp.reason);
              }
            }
          });
        },
        query: function(mapFun, reduceFun, language, options) {
          options = options || {};
          language = language || "javascript"
          if (typeof(mapFun) != "string") {
            mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")";
          }
          var body = {language: language, map: mapFun};
          if (reduceFun != null) {
            if (typeof(reduceFun) != "string")
              reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")";
            body.reduce = reduceFun;
          }
          $.ajax({
            type: "POST", url: this.uri + "_temp_view" + encodeOptions(options),
            contentType: "application/json",
            data: toJSON(body), dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("An error occurred querying the database: " + resp.reason);
              }
            }
          });
        },
        view: function(name, options) {
          options = options || {};
          name = name.split('/');
          $.ajax({
            type: "GET", url: this.uri + "_design/" + name[0] + "/_view/" + name[1] + encodeOptions(options),
            dataType: "json",
            complete: function(req) {
              var resp = $.httpData(req, "json");
              if (req.status == 200) {
                if (options.success) options.success(resp);
              } else if (options.error) {
                options.error(req.status, resp.error, resp.reason);
              } else {
                alert("An error occurred accessing the view: " + resp.reason);
              }
            }
          });
        }
      };
    },

    info: function(options) {
      options = options || {};
      $.ajax({
        type: "GET", url: "/", dataType: "json",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("Server information could not be retrieved: " + resp.reason);
          }
        }
      });
    },

    replicate: function(source, target, options) {
      options = options || {};
      $.ajax({
        type: "POST", url: "/_replicate", dataType: "json",
        data: JSON.stringify({source: source, target: target}),
        contentType: "application/json",
        complete: function(req) {
          var resp = $.httpData(req, "json");
          if (req.status == 200) {
            if (options.success) options.success(resp);
          } else if (options.error) {
            options.error(req.status, resp.error, resp.reason);
          } else {
            alert("Replication failed: " + resp.reason);
          }
        }
      });
    }

  });

  // Convert a options object to an url query string.
  // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"'
  function encodeOptions(options) {
    var buf = []
    if (typeof(options) == "object" && options !== null) {
      for (var name in options) {
        if (name == "error" || name == "success") continue;
        var value = options[name];
        if (name == "key" || name == "startkey" || name == "endkey") {
          value = toJSON(value);
        }
        buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value));
      }
    }
    return buf.length ? "?" + buf.join("&") : "";
  }

  function toJSON(obj) {
    return obj !== null ? JSON.stringify(obj) : null;
  }

})(jQuery);
<|endoftext|>


<commit_before>var path = require('path');
var execFile = require('child_process').execFile;
var packagejson = require('./package.json');
var electron = require('electron-prebuilt');

var WINDOWS_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_windows-amd64.exe';
var DARWIN_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_darwin-amd64';

module.exports = function (grunt) {
  require('load-grunt-tasks')(grunt);
  var target = grunt.option('target') || 'development';
  var beta = grunt.option('beta') || false;
  var alpha = grunt.option('alpha') || false;
  var env = process.env;
  env.NODE_PATH = '..:' + env.NODE_PATH;
  env.NODE_ENV = target;

  var certificateFile = grunt.option('certificateFile');

  var version = function (str) {
    var match = str.match(/(\d+\.\d+\.\d+)/);
    return match ? match[1] : null;
  };

  grunt.registerMultiTask('download-binary', 'Downloads binary unless version up to date', function () {
    var target = grunt.task.current.target;
    var done = this.async();
    var config = grunt.config('download-binary')[target];
    execFile(config.binary, ['--version'], function (err, stdout) {
      var currentVersion = version(stdout);
      if (!currentVersion || currentVersion !== version(config.version)) {
        grunt.task.run('curl:' + target);
        grunt.task.run('chmod');
      }
      done();

    });
  });

  var BASENAME = 'Kitematic';
  var APPNAME = BASENAME;

  if (alpha) {
    APPNAME += ' (Alpha)';
  } else if (beta) {
    APPNAME += ' (Beta)';
  }

  var OSX_OUT = './dist/osx';
  var OSX_FILENAME = OSX_OUT + '/' + APPNAME + '.app';

  grunt.initConfig({
    IDENTITY: 'Developer ID Application: Docker Inc',
    APPNAME: APPNAME,
    OSX_OUT: OSX_OUT,
    OSX_FILENAME: OSX_FILENAME,
    OSX_FILENAME_ESCAPED: OSX_FILENAME.replace(' ', '\\ ').replace('(','\\(').replace(')','\\)'),

    // electron
    electron: {
      windows: {
        options: {
          name: BASENAME,
          dir: 'build/',
          out: 'dist/',
          version: packagejson['electron-version'],
          platform: 'win32',
          arch: 'x64',
          asar: true,
          icon: 'util/kitematic.ico'
        }
      },
      osx: {
        options: {
          name: APPNAME,
          dir: 'build/',
          out: '<%= OSX_OUT %>',
          version: packagejson['electron-version'],
          platform: 'darwin',
          arch: 'x64',
          asar: true,
          'app-bundle-id': 'com.kitematic.kitematic',
          'app-version': packagejson.version
        }
      }
    },

    prompt: {
      'create-windows-installer': {
        options: {
          questions: [
            {
              config: 'certificatePassword',
              type: 'password',
              message: 'Certificate Password: '
            }
          ]
        }
      }
    },

    rcedit: {
      exes: {
        files: [{
          expand: true,
          cwd: 'dist/' + BASENAME + '-win32',
          src: [BASENAME + '.exe']
        }],
        options: {
          icon: 'util/kitematic.ico',
          'file-version': packagejson.version,
          'product-version': packagejson.version,
          'version-string': {
            'CompanyName': 'Docker',
            'ProductVersion': packagejson.version,
            'ProductName': APPNAME,
            'FileDescription': APPNAME,
            'InternalName': BASENAME + '.exe',
            'OriginalFilename': BASENAME + '.exe',
            'LegalCopyright': 'Copyright 2015 Docker Inc. All rights reserved.'
          }
        }
      }
    },

    'create-windows-installer': {
      appDirectory: 'dist/' + BASENAME + '-win32/',
      authors: 'Docker Inc.',
      loadingGif: 'util/loading.gif',
      setupIcon: 'util/setup.ico',
      iconUrl: 'https://raw.githubusercontent.com/kitematic/kitematic/master/util/kitematic.ico',
      description: APPNAME,
      title: APPNAME,
      exe: BASENAME + '.exe',
      version: packagejson.version,
      signWithParams: '/f ' + certificateFile + ' /p <%= certificatePassword %> /tr http://timestamp.comodoca.com/rfc3161'
    },

    // docker binaries
    'download-binary': {
      'docker-machine': {
        version: packagejson['docker-machine-version'],
        binary: path.join('resources', 'docker-machine'),
        download: 'curl:docker-machine'
      }
    },

    // images
    copy: {
      dev: {
        files: [{
          expand: true,
          cwd: '.',
          src: ['package.json', 'settings.json', 'index.html'],
          dest: 'build/'
        }, {
          expand: true,
          cwd: 'images/',
          src: ['**/*'],
          dest: 'build/'
        }, {
          expand: true,
          cwd: 'fonts/',
          src: ['**/*'],
          dest: 'build/'
        }, {
          cwd: 'node_modules/',
          src: Object.keys(packagejson.dependencies).map(function (dep) { return dep + '/**/*';}),
          dest: 'build/node_modules/',
          expand: true
        }]
      },
      windows: {
        files: [{
          expand: true,
          cwd: 'resources',
          src: ['docker*', 'ssh.exe', 'OPENSSH_LICENSE', 'msys-*'],
          dest: 'dist/' + BASENAME + '-win32/resources/resources/'
        }],
        options: {
          mode: true
        }
      },
      osx: {
        files: [{
          expand: true,
          cwd: 'resources',
          src: ['docker*', 'macsudo', 'terminal'],
          dest: '<%= OSX_FILENAME %>/Contents/Resources/resources/'
        }, {
          src: 'util/kitematic.icns',
          dest: '<%= OSX_FILENAME %>/Contents/Resources/atom.icns'
        }],
        options: {
          mode: true
        }
      }
    },

    rename: {
      installer: {
        src: 'installer/Setup.exe',
        dest: 'installer/' + BASENAME + 'Setup-' + packagejson.version + '-Windows-Alpha.exe'
      }
    },

    // download binaries
    curl: {
      'docker-machine': {
        src: process.platform === 'win32' ? WINDOWS_DOCKER_MACHINE_URL : DARWIN_DOCKER_MACHINE_URL,
        dest: process.platform === 'win32' ? path.join('resources', 'docker-machine.exe') : path.join('resources', 'docker-machine')
      }
    },

    chmod: {
      binaries: {
        options: {
          mode: '755'
        },
        src: ['resources/docker*']
      }
    },

    // styles
    less: {
      options: {
        sourceMapFileInline: true
      },
      dist: {
        files: {
          'build/main.css': 'styles/main.less'
        }
      }
    },

    plistbuddy: {
      addBundleURLTypes: {
        method: 'Add',
        entry: 'CFBundleURLTypes',
        type: 'array',
        src: '<%= OSX_FILENAME %>/Contents/Info.plist'
      },
      addBundleURLTypesDict: {
        method: 'Add',
        entry: 'CFBundleURLTypes:0',
        type: 'dict',
        src: '<%= OSX_FILENAME %>/Contents/Info.plist'
      },
      addBundleURLTypesDictName: {
        method: 'Add',
        entry: 'CFBundleURLTypes:0:CFBundleURLName',
        type: 'string',
        value: 'Docker App Protocol',
        src: '<%= OSX_FILENAME %>/Contents/Info.plist'
      },
      addBundleURLTypesDictSchemes: {
        method: 'Add',
        entry: 'CFBundleURLTypes:0:CFBundleURLSchemes',
        type: 'array',
        src: '<%= OSX_FILENAME %>/Contents/Info.plist'
      },
      addBundleURLTypesDictSchemesDocker: {
        method: 'Add',
        entry: 'CFBundleURLTypes:0:CFBundleURLSchemes:0',
        type: 'string',
        value: 'docker',
        src: '<%= OSX_FILENAME %>/Contents/Info.plist'
      }
    },

    // javascript
    babel: {
      options: {
        sourceMap: 'inline',
        blacklist: 'regenerator'
      },
      dist: {
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['**/*.js'],
          dest: 'build/',
        }]
      }
    },

    shell: {
      electron: {
        command: electron + ' ' + 'build',
        options: {
          async: true,
          execOptions: {
            env: env
          }
        }
      },
      sign: {
        options: {
          failOnError: false,
        },
        command: [
          'codesign --deep -v -f -s "<%= IDENTITY %>" <%= OSX_FILENAME_ESCAPED %>/Contents/Frameworks/*',
          'codesign -v -f -s "<%= IDENTITY %>" <%= OSX_FILENAME_ESCAPED %>',
          'codesign -vvv --display <%= OSX_FILENAME_ESCAPED %>',
          'codesign -v --verify <%= OSX_FILENAME_ESCAPED %>'
        ].join(' && '),
      },
      zip: {
        command: 'ditto -c -k --sequesterRsrc --keepParent <%= OSX_FILENAME_ESCAPED %> <%= OSX_OUT %>/' + BASENAME + '-' + packagejson.version + '-Mac.zip',
      }
    },

    clean: {
      release: ['build/', 'dist/', 'installer/'],
    },

    // livereload
    watchChokidar: {
      options: {
        spawn: true
      },
      livereload: {
        options: {livereload: true},
        files: ['build/**/*']
      },
      js: {
        files: ['src/**/*.js'],
        tasks: ['newer:babel']
      },
      less: {
        files: ['styles/**/*.less'],
        tasks: ['less']
      },
      copy: {
        files: ['images/*', 'index.html', 'fonts/*'],
        tasks: ['newer:copy:dev']
      }
    }
  });

  grunt.registerTask('default', ['download-binary', 'newer:babel', 'less', 'newer:copy:dev', 'shell:electron', 'watchChokidar']);

  if (process.platform === 'win32') {
    grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:windows', 'copy:windows', 'rcedit:exes', 'prompt:create-windows-installer', 'create-windows-installer', 'rename:installer']);
  } else {
    grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:osx', 'copy:osx', 'plistbuddy', 'shell:sign', 'shell:zip']);
  }

  process.on('SIGINT', function () {
    grunt.task.run(['shell:electron:kill']);
    process.exit(1);
  });
};
<commit_msg>Remove plistbuddy entry<commit_after>var path = require('path');
var execFile = require('child_process').execFile;
var packagejson = require('./package.json');
var electron = require('electron-prebuilt');

var WINDOWS_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_windows-amd64.exe';
var DARWIN_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_darwin-amd64';

module.exports = function (grunt) {
  require('load-grunt-tasks')(grunt);
  var target = grunt.option('target') || 'development';
  var beta = grunt.option('beta') || false;
  var alpha = grunt.option('alpha') || false;
  var env = process.env;
  env.NODE_PATH = '..:' + env.NODE_PATH;
  env.NODE_ENV = target;

  var certificateFile = grunt.option('certificateFile');

  var version = function (str) {
    var match = str.match(/(\d+\.\d+\.\d+)/);
    return match ? match[1] : null;
  };

  grunt.registerMultiTask('download-binary', 'Downloads binary unless version up to date', function () {
    var target = grunt.task.current.target;
    var done = this.async();
    var config = grunt.config('download-binary')[target];
    execFile(config.binary, ['--version'], function (err, stdout) {
      var currentVersion = version(stdout);
      if (!currentVersion || currentVersion !== version(config.version)) {
        grunt.task.run('curl:' + target);
        grunt.task.run('chmod');
      }
      done();

    });
  });

  var BASENAME = 'Kitematic';
  var APPNAME = BASENAME;

  if (alpha) {
    APPNAME += ' (Alpha)';
  } else if (beta) {
    APPNAME += ' (Beta)';
  }

  var OSX_OUT = './dist/osx';
  var OSX_FILENAME = OSX_OUT + '/' + APPNAME + '.app';

  grunt.initConfig({
    IDENTITY: 'Developer ID Application: Docker Inc',
    APPNAME: APPNAME,
    OSX_OUT: OSX_OUT,
    OSX_FILENAME: OSX_FILENAME,
    OSX_FILENAME_ESCAPED: OSX_FILENAME.replace(' ', '\\ ').replace('(','\\(').replace(')','\\)'),

    // electron
    electron: {
      windows: {
        options: {
          name: BASENAME,
          dir: 'build/',
          out: 'dist/',
          version: packagejson['electron-version'],
          platform: 'win32',
          arch: 'x64',
          asar: true,
          icon: 'util/kitematic.ico'
        }
      },
      osx: {
        options: {
          name: APPNAME,
          dir: 'build/',
          out: '<%= OSX_OUT %>',
          version: packagejson['electron-version'],
          platform: 'darwin',
          arch: 'x64',
          asar: true,
          'app-bundle-id': 'com.kitematic.kitematic',
          'app-version': packagejson.version
        }
      }
    },

    prompt: {
      'create-windows-installer': {
        options: {
          questions: [
            {
              config: 'certificatePassword',
              type: 'password',
              message: 'Certificate Password: '
            }
          ]
        }
      }
    },

    rcedit: {
      exes: {
        files: [{
          expand: true,
          cwd: 'dist/' + BASENAME + '-win32',
          src: [BASENAME + '.exe']
        }],
        options: {
          icon: 'util/kitematic.ico',
          'file-version': packagejson.version,
          'product-version': packagejson.version,
          'version-string': {
            'CompanyName': 'Docker',
            'ProductVersion': packagejson.version,
            'ProductName': APPNAME,
            'FileDescription': APPNAME,
            'InternalName': BASENAME + '.exe',
            'OriginalFilename': BASENAME + '.exe',
            'LegalCopyright': 'Copyright 2015 Docker Inc. All rights reserved.'
          }
        }
      }
    },

    'create-windows-installer': {
      appDirectory: 'dist/' + BASENAME + '-win32/',
      authors: 'Docker Inc.',
      loadingGif: 'util/loading.gif',
      setupIcon: 'util/setup.ico',
      iconUrl: 'https://raw.githubusercontent.com/kitematic/kitematic/master/util/kitematic.ico',
      description: APPNAME,
      title: APPNAME,
      exe: BASENAME + '.exe',
      version: packagejson.version,
      signWithParams: '/f ' + certificateFile + ' /p <%= certificatePassword %> /tr http://timestamp.comodoca.com/rfc3161'
    },

    // docker binaries
    'download-binary': {
      'docker-machine': {
        version: packagejson['docker-machine-version'],
        binary: path.join('resources', 'docker-machine'),
        download: 'curl:docker-machine'
      }
    },

    // images
    copy: {
      dev: {
        files: [{
          expand: true,
          cwd: '.',
          src: ['package.json', 'settings.json', 'index.html'],
          dest: 'build/'
        }, {
          expand: true,
          cwd: 'images/',
          src: ['**/*'],
          dest: 'build/'
        }, {
          expand: true,
          cwd: 'fonts/',
          src: ['**/*'],
          dest: 'build/'
        }, {
          cwd: 'node_modules/',
          src: Object.keys(packagejson.dependencies).map(function (dep) { return dep + '/**/*';}),
          dest: 'build/node_modules/',
          expand: true
        }]
      },
      windows: {
        files: [{
          expand: true,
          cwd: 'resources',
          src: ['docker*', 'ssh.exe', 'OPENSSH_LICENSE', 'msys-*'],
          dest: 'dist/' + BASENAME + '-win32/resources/resources/'
        }],
        options: {
          mode: true
        }
      },
      osx: {
        files: [{
          expand: true,
          cwd: 'resources',
          src: ['docker*', 'macsudo', 'terminal'],
          dest: '<%= OSX_FILENAME %>/Contents/Resources/resources/'
        }, {
          src: 'util/kitematic.icns',
          dest: '<%= OSX_FILENAME %>/Contents/Resources/atom.icns'
        }],
        options: {
          mode: true
        }
      }
    },

    rename: {
      installer: {
        src: 'installer/Setup.exe',
        dest: 'installer/' + BASENAME + 'Setup-' + packagejson.version + '-Windows-Alpha.exe'
      }
    },

    // download binaries
    curl: {
      'docker-machine': {
        src: process.platform === 'win32' ? WINDOWS_DOCKER_MACHINE_URL : DARWIN_DOCKER_MACHINE_URL,
        dest: process.platform === 'win32' ? path.join('resources', 'docker-machine.exe') : path.join('resources', 'docker-machine')
      }
    },

    chmod: {
      binaries: {
        options: {
          mode: '755'
        },
        src: ['resources/docker*']
      }
    },

    // styles
    less: {
      options: {
        sourceMapFileInline: true
      },
      dist: {
        files: {
          'build/main.css': 'styles/main.less'
        }
      }
    },

    // javascript
    babel: {
      options: {
        sourceMap: 'inline',
        blacklist: 'regenerator'
      },
      dist: {
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['**/*.js'],
          dest: 'build/',
        }]
      }
    },

    shell: {
      electron: {
        command: electron + ' ' + 'build',
        options: {
          async: true,
          execOptions: {
            env: env
          }
        }
      },
      sign: {
        options: {
          failOnError: false,
        },
        command: [
          'codesign --deep -v -f -s "<%= IDENTITY %>" <%= OSX_FILENAME_ESCAPED %>/Contents/Frameworks/*',
          'codesign -v -f -s "<%= IDENTITY %>" <%= OSX_FILENAME_ESCAPED %>',
          'codesign -vvv --display <%= OSX_FILENAME_ESCAPED %>',
          'codesign -v --verify <%= OSX_FILENAME_ESCAPED %>'
        ].join(' && '),
      },
      zip: {
        command: 'ditto -c -k --sequesterRsrc --keepParent <%= OSX_FILENAME_ESCAPED %> <%= OSX_OUT %>/' + BASENAME + '-' + packagejson.version + '-Mac.zip',
      }
    },

    clean: {
      release: ['build/', 'dist/', 'installer/'],
    },

    // livereload
    watchChokidar: {
      options: {
        spawn: true
      },
      livereload: {
        options: {livereload: true},
        files: ['build/**/*']
      },
      js: {
        files: ['src/**/*.js'],
        tasks: ['newer:babel']
      },
      less: {
        files: ['styles/**/*.less'],
        tasks: ['less']
      },
      copy: {
        files: ['images/*', 'index.html', 'fonts/*'],
        tasks: ['newer:copy:dev']
      }
    }
  });

  grunt.registerTask('default', ['download-binary', 'newer:babel', 'less', 'newer:copy:dev', 'shell:electron', 'watchChokidar']);

  if (process.platform === 'win32') {
    grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:windows', 'copy:windows', 'rcedit:exes', 'prompt:create-windows-installer', 'create-windows-installer', 'rename:installer']);
  } else {
    grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:osx', 'copy:osx', 'shell:sign', 'shell:zip']);
  }

  process.on('SIGINT', function () {
    grunt.task.run(['shell:electron:kill']);
    process.exit(1);
  });
};
<|endoftext|>


<commit_before>$(function() {
  $('#trainer').each(function() {
    var $trainer = $(this);
    var $board = $trainer.find('.lichess_board');
    var $side = $trainer.find('> .side');
    var $right = $trainer.find('> .right');
    var $bar = $trainer.find('.progress_bar');
    var $coord = $trainer.find('#next_coord').disableSelection();
    var $start = $right.find('.start');
    var $explanation = $right.find('.explanation');
    var $score = $trainer.find('.score_container strong');
    var scoreUrl = $trainer.data('score-url');
    var colorUrl = $trainer.data('color-url');
    var duration = 30 * 1000;
    var tickDelay = 50;
    var colorPref = $trainer.data('color-pref');
    var color;
    var coordToGuess, startAt, score;

    $trainer.find('.buttons').buttonset().disableSelection();

    var showColor = function() {
      color = colorPref == 'random' ? ['white', 'black'][_.random(0, 1)] : colorPref;
      $trainer.removeClass('white black').addClass(color);
    };
    showColor();

    $trainer.find('form.color').on('click', 'input', function() {
      var c = {
        1: 'white',
        2: 'random',
        3: 'black'
      }[$(this).val()];
      if (colorUrl && c != colorPref) $.ajax({
        url: colorUrl,
        method: 'post',
        data: {
          color: $(this).val()
        }
      });
      colorPref = c;
      showColor();
      return false;
    });

    var showCharts = function() {
      var dark = $('body').hasClass('dark');
      var theme = {
        type: 'line',
        width: '213px',
        height: '80px',
        lineColor: dark ? '#4444ff' : '#0000ff',
        fillColor: dark ? '#222255' : '#ccccff'
      };
      $side.find('.user_chart').each(function() {
        $(this).sparkline($(this).data('points'), theme);
      });
    };
    showCharts();

    var centerRight = function() {
      $right.css('top', (256 - $right.height() / 2) + 'px');
    };
    centerRight();

    var newCoord = function() {
      var c;
      do {
        c = 'abcdefgh' [_.random(0, 7)] + _.random(1, 8);
      } while (c == coordToGuess);
      coordToGuess = c;
      $coord.text(coordToGuess);
    };

    var stop = function() {
      $trainer.removeClass('play');
      centerRight();
      $trainer.removeClass('wrong');
      $board.off('click', '.lcs');
      if (scoreUrl) $.ajax({
        url: scoreUrl,
        method: 'post',
        data: {
          color: color,
          score: score
        },
        success: function(charts) {
          $side.find('.scores').html(charts);
          showCharts();
        }
      });
    };

    var tick = function() {
      var spent = Math.min(duration, (new Date() - startAt));
      $bar.css('width', (100 * spent / duration) + '%');
      if (spent < duration) setTimeout(tick, tickDelay);
      else stop();
    };

    $score.click(function() {
      $start.filter(':visible').click();
    });

    $start.click(function() {
      $explanation.remove();
      $trainer.addClass('play').removeClass('init');
      showColor();
      $coord.text('');
      centerRight();
      score = 0;
      $score.text(score);
      $bar.css('width', 0);
      setTimeout(function() {
        startAt = new Date();
        $board.on('click', '.lcs', function() {
          var hit = this.id == coordToGuess;
          if (hit) {
            score++;
            $score.text(score);
            newCoord();
          } else {
            $coord.addClass('nope');
            setTimeout(function() {
              $coord.removeClass('nope');
            }, 100);
          }
          $trainer.toggleClass('wrong', !hit);
        });
        newCoord();
        tick();
      }, 1000);
    });
  });
});
<commit_msg>added look-ahead for coordinates training<commit_after>$(function() {
  $('#trainer').each(function() {
    var $trainer = $(this);
    var $board = $trainer.find('.lichess_board');
    var $side = $trainer.find('> .side');
    var $right = $trainer.find('> .right');
    var $bar = $trainer.find('.progress_bar');
    var $coords = [
      $trainer.find('#next_coord0').disableSelection(),
      $trainer.find('#next_coord1').disableSelection(),
      $trainer.find('#next_coord2').disableSelection()
    ];
    var $start = $right.find('.start');
    var $explanation = $right.find('.explanation');
    var $score = $trainer.find('.score_container strong');
    var scoreUrl = $trainer.data('score-url');
    var colorUrl = $trainer.data('color-url');
    var duration = 30 * 1000;
    var tickDelay = 50;
    var colorPref = $trainer.data('color-pref');
    var color;
    var startAt, score;

    $trainer.find('.buttons').buttonset().disableSelection();

    var showColor = function() {
      color = colorPref == 'random' ? ['white', 'black'][_.random(0, 1)] : colorPref;
      $trainer.removeClass('white black').addClass(color);
    };
    showColor();

    $trainer.find('form.color').on('click', 'input', function() {
      var c = {
        1: 'white',
        2: 'random',
        3: 'black'
      }[$(this).val()];
      if (colorUrl && c != colorPref) $.ajax({
        url: colorUrl,
        method: 'post',
        data: {
          color: $(this).val()
        }
      });
      colorPref = c;
      showColor();
      return false;
    });

    var showCharts = function() {
      var dark = $('body').hasClass('dark');
      var theme = {
        type: 'line',
        width: '213px',
        height: '80px',
        lineColor: dark ? '#4444ff' : '#0000ff',
        fillColor: dark ? '#222255' : '#ccccff'
      };
      $side.find('.user_chart').each(function() {
        $(this).sparkline($(this).data('points'), theme);
      });
    };
    showCharts();

    var centerRight = function() {
      $right.css('top', (256 - $right.height() / 2) + 'px');
    };
    centerRight();

    var clearCoords = function() {
      $.each($coords, function(i, e) {
        e.text('');
      });
    }

    var newCoord = function(prevCoord) {
      // disallow the previous coordinate's row or file from being selected
      var files = 'abcdefgh';
      var fileIndex = files.indexOf(prevCoord[0]);
      files = files.slice(0, fileIndex) + files.slice(fileIndex + 1, 8);

      var rows = '12345678';
      var rowIndex = rows.indexOf(prevCoord[1]);
      rows = rows.slice(0, rowIndex) + rows.slice(rowIndex + 1, 8);

      return files[_.random(0, files.length - 1)] + rows[_.random(0, rows.length - 1)];
    };

    var advanceCoords = function() {
      $coords[0].removeClass('nope');
      var lastElement = $coords.shift();
      $.each($coords, function(i, e) {
        e.attr('id', 'next_coord' + i);
      });
      lastElement.attr('id', 'next_coord' + ($coords.length));
      lastElement.text(newCoord($coords[$coords.length - 1].text()));
      $coords.push(lastElement);
    }

    var stop = function() {
      clearCoords();
      $trainer.removeClass('play');
      centerRight();
      $trainer.removeClass('wrong');
      $board.off('click', '.lcs');
      if (scoreUrl) $.ajax({
        url: scoreUrl,
        method: 'post',
        data: {
          color: color,
          score: score
        },
        success: function(charts) {
          $side.find('.scores').html(charts);
          showCharts();
        }
      });
    };

    var tick = function() {
      var spent = Math.min(duration, (new Date() - startAt));
      $bar.css('width', (100 * spent / duration) + '%');
      if (spent < duration) setTimeout(tick, tickDelay);
      else stop();
    };

    $score.click(function() {
      $start.filter(':visible').click();
    });

    $start.click(function() {
      $explanation.remove();
      $trainer.addClass('play').removeClass('init');
      showColor();
      clearCoords();
      centerRight();
      score = 0;
      $score.text(score);
      $bar.css('width', 0);
      setTimeout(function() {
        startAt = new Date();
        $board.on('click', '.lcs', function() {
          var hit = this.id == $coords[0].text();
          if (hit) {
            score++;
            $score.text(score);
            advanceCoords();
          } else {
          $coords[0].addClass('nope');
          setTimeout(function() {
            $coords[0].removeClass('nope');
          }, 500);
          }
          $trainer.toggleClass('wrong', !hit);
        });
        $coords[0].text(newCoord('a1'));
        for(i = 1; i < $coords.length; i++)
          $coords[i].text(newCoord($coords[i - 1].text()));
        tick();
      }, 1000);
    });
  });
});
<|endoftext|>


<commit_before>// @flow

const READY_STATE_CHANGE = 'readystatechange'
const doc = document

export const ready = new Promise(resolve => {
  const checkReady = () => {
    if (doc.readyState === 'complete') {
      resolve()
      doc.removeEventListener(READY_STATE_CHANGE, checkReady)
    }
  }

  doc.addEventListener(READY_STATE_CHANGE, checkReady)

  checkReady()
})

export const documentElement = doc.documentElement
export default doc
<commit_msg>refactor: fix flow error<commit_after>// @flow

const READY_STATE_CHANGE = 'readystatechange'
const doc = document

export const ready: Promise<void> = new Promise(resolve => {
  const checkReady = () => {
    if (doc.readyState === 'complete') {
      resolve()
      doc.removeEventListener(READY_STATE_CHANGE, checkReady)
    }
  }

  doc.addEventListener(READY_STATE_CHANGE, checkReady)

  checkReady()
})

export const documentElement = doc.documentElement
export default doc
<|endoftext|>


<commit_before>const k = require("../helpers/kindlemail");
const chai = require("chai");
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
const assert = chai.assert,
    expect = chai.expect;
chai.should();
const fs = require("fs");
const filepath = __dirname + "/test.mobi";
const mockMails = ["asd@asd", "asd", "@", ".asd@asd.asd",
    "asd@asd@asd.asd", "asd@.asd"
];

describe("Input validator", () => {
    before(function () {
        fs.openSync(filepath, "w");
    });

    after(function () {
        fs.unlinkSync(filepath, "w");
    });
    mockMails.map(elem => {
        it("checks if user email is valid", () => {
            return k.send({
                to: "valid@email.com",
                sender: {
                    user: elem,
                    pass: "pass"
                },
                filePath: filepath
            }).should.eventually.be.rejectedWith("Email is not valid");
        });
        it("checks if recipient email is valid", () => {
            return k.send({
                to: elem,
                sender: {
                    user: "valid@email.com",
                    pass: "pass"
                },
                filePath: filepath
            }).should.eventually.be.rejectedWith("Email is not valid");
        });
    });
    it("checks if file exists", () => {
        return k.send({
            to: "valid@email.com",
            sender: {
                user: "valid@email.com",
                pass: "pass"
            },
            filePath: "invalid.mobi"
        }).should.eventually.be.rejectedWith("File not found!");
    });
    it("should fail with invalid user pass combinations", () => {
        return k.send({
            to: "valid@email.com",
            sender: {
                user: "valid@email.com",
                pass: "pass"
            },
            filePath: filepath
        }).then(() => fs.unlinkSync(filepath)).should.eventually.be.rejectedWith("ECONNREFUSED");
    });
});<commit_msg>Remove unnecessary promise<commit_after>const k = require("../helpers/kindlemail");
const chai = require("chai");
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
const assert = chai.assert,
    expect = chai.expect;
chai.should();
const fs = require("fs");
const filepath = __dirname + "/test.mobi";
const mockMails = ["asd@asd", "asd", "@", ".asd@asd.asd",
    "asd@asd@asd.asd", "asd@.asd"
];

describe("Input validator", () => {
    before(function () {
        fs.openSync(filepath, "w");
    });

    after(function () {
        fs.unlinkSync(filepath, "w");
    });
    mockMails.map(elem => {
        it("checks if user email is valid", () => {
            return k.send({
                to: "valid@email.com",
                sender: {
                    user: elem,
                    pass: "pass"
                },
                filePath: filepath
            }).should.eventually.be.rejectedWith("Email is not valid");
        });
        it("checks if recipient email is valid", () => {
            return k.send({
                to: elem,
                sender: {
                    user: "valid@email.com",
                    pass: "pass"
                },
                filePath: filepath
            }).should.eventually.be.rejectedWith("Email is not valid");
        });
    });
    it("checks if file exists", () => {
        return k.send({
            to: "valid@email.com",
            sender: {
                user: "valid@email.com",
                pass: "pass"
            },
            filePath: "invalid.mobi"
        }).should.eventually.be.rejectedWith("File not found!");
    });
    it("should fail with invalid user pass combinations", () => {
        return k.send({
            to: "valid@email.com",
            sender: {
                user: "valid@email.com",
                pass: "pass"
            },
            filePath: filepath
        }).should.eventually.be.rejectedWith("ECONNREFUSED");
    });
});
<|endoftext|>