<commit_before>'use strict';

/**
 * Module dependencies.
 */
var _ = require('lodash'),
  defaultAssets = require('./config/assets/default'),
  testAssets = require('./config/assets/test'),
  fs = require('fs'),
  path = require('path');

module.exports = function (grunt) {
  // Project Configuration
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    env: {
      test: {
        NODE_ENV: 'test'
      },
      dev: {
        NODE_ENV: 'development'
      },
      prod: {
        NODE_ENV: 'production'
      }
    },
    watch: {
      serverViews: {
        files: defaultAssets.server.views,
        options: {
          livereload: true
        }
      },
      serverJS: {
        files: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS),
        tasks: ['jshint'],
        options: {
          livereload: true
        }
      },
      clientViews: {
        files: defaultAssets.client.views,
        options: {
          livereload: true
        }
      },
      clientJS: {
        files: defaultAssets.client.js,
        tasks: ['jshint'],
        options: {
          livereload: true
        }
      },
      clientCSS: {
        files: defaultAssets.client.css,
        tasks: ['csslint'],
        options: {
          livereload: true
        }
      },
      clientSCSS: {
        files: defaultAssets.client.sass,
        tasks: ['sass', 'csslint'],
        options: {
          livereload: true
        }
      },
      clientLESS: {
        files: defaultAssets.client.less,
        tasks: ['less', 'csslint'],
        options: {
          livereload: true
        }
      }
    },
    nodemon: {
      dev: {
        script: 'server.js',
        options: {
          nodeArgs: ['--debug'],
          ext: 'js,html',
          watch: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.views, defaultAssets.server.allJS, defaultAssets.server.config)
        }
      }
    },
    concurrent: {
      default: ['nodemon', 'watch'],
      debug: ['nodemon', 'watch', 'node-inspector'],
      options: {
        logConcurrentOutput: true
      }
    },
    jshint: {
      all: {
        src: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS, defaultAssets.client.js, testAssets.tests.server, testAssets.tests.client, testAssets.tests.e2e),
        options: {
          jshintrc: true,
          node: true,
          mocha: true,
          jasmine: true
        }
      }
    },
    csslint: {
      options: {
        csslintrc: '.csslintrc'
      },
      all: {
        src: defaultAssets.client.css
      }
    },
    ngAnnotate: {
      production: {
        files: {
          'public/dist/application.js': defaultAssets.client.js
        }
      }
    },
    uglify: {
      production: {
        options: {
          mangle: false
        },
        files: {
          'public/dist/application.min.js': 'public/dist/application.js'
        }
      }
    },
    cssmin: {
      combine: {
        files: {
          'public/dist/application.min.css': defaultAssets.client.css
        }
      }
    },
    sass: {
      dist: {
        files: [{
          expand: true,
          src: defaultAssets.client.sass,
          ext: '.css',
          rename: function (base, src) {
            return src.replace('/scss/', '/css/');
          }
				}]
      }
    },
    less: {
      dist: {
        files: [{
          expand: true,
          src: defaultAssets.client.less,
          ext: '.css',
          rename: function (base, src) {
            return src.replace('/less/', '/css/');
          }
				}]
      }
    },
    'node-inspector': {
      custom: {
        options: {
          'web-port': 1337,
          'web-host': 'localhost',
          'debug-port': 5858,
          'save-live-edit': true,
          'no-preload': true,
          'stack-trace-limit': 50,
          'hidden': []
        }
      }
    },
    mochaTest: {
      src: testAssets.tests.server,
      options: {
        reporter: 'spec',
        timeout: 10000
      }
    },
    mocha_istanbul: {
      coverage: {
        src: testAssets.tests.server,
        options: {
          print: 'detail',
          coverage: true,
          require: 'test.js',
          coverageFolder: 'coverage',
          reportFormats: ['cobertura','lcovonly'],
          check: {
            lines: 40,
            statements: 40
          }
        }
      }
    },
    karma: {
      unit: {
        configFile: 'karma.conf.js'
      }
    },
    protractor: {
      options: {
        configFile: 'protractor.conf.js',
        keepAlive: true,
        noColor: false,
        webdriverManagerUpdate: true
      },
      e2e: {
        options: {
          args: {} // Target-specific arguments
        }
      }
    },
    copy: {
      localConfig: {
        src: 'config/env/local.example.js',
        dest: 'config/env/local.js',
        filter: function () {
          return !fs.existsSync('config/env/local.js');
        }
      }
    }
  });

  grunt.event.on('coverage', function(lcovFileContents, done) {
    require('coveralls').handleInput(lcovFileContents, function(err) {
      if (err) {
        return done(err);
      }
      done();
    });
  });

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

  // Make sure upload directory exists
  grunt.task.registerTask('mkdir:upload', 'Task that makes sure upload directory exists.', function () {
    // Get the callback
    var done = this.async();

    grunt.file.mkdir(path.normalize(__dirname + '/modules/users/client/img/profile/uploads'));

    done();
  });

  // Connect to the MongoDB instance and load the models
  grunt.task.registerTask('mongoose', 'Task that connects to the MongoDB instance and loads the application models.', function () {
    // Get the callback
    var done = this.async();

    // Use mongoose configuration
    var mongoose = require('./config/lib/mongoose.js');

    // Connect to database
    mongoose.connect(function (db) {
      done();
    });
  });

  grunt.task.registerTask('server', 'Starting the server', function () {
    // Get the callback
    var done = this.async();

    var path = require('path');
    var app = require(path.resolve('./config/lib/app'));
    var server = app.start(function () {
      done();
    });
  });

  // Lint CSS and JavaScript files.
  grunt.registerTask('lint', ['sass', 'less', 'jshint', 'csslint']);

  // Lint project files and minify them into two production files.
  grunt.registerTask('build', ['env:dev', 'lint', 'ngAnnotate', 'uglify', 'cssmin']);

  // Run the project tests
  grunt.registerTask('test', ['env:test', 'lint', 'mkdir:upload', 'copy:localConfig', 'server', 'mochaTest', 'karma:unit', 'protractor']);
  grunt.registerTask('test:server', ['env:test', 'lint', 'server', 'mochaTest']);
  grunt.registerTask('test:client', ['env:test', 'lint', 'server', 'karma:unit']);
  grunt.registerTask('test:e2e', ['env:test', 'lint', 'server', 'protractor']);

  // Run project coverage
  grunt.registerTask('coverage', ['env:test', 'lint', 'mocha_istanbul:coverage']);

  // Run the project in development mode
  grunt.registerTask('default', ['env:dev', 'lint', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);

  // Run the project in debug mode
  grunt.registerTask('debug', ['env:dev', 'lint', 'mkdir:upload', 'copy:localConfig', 'concurrent:debug']);

  // Run the project in production mode
  grunt.registerTask('prod', ['build', 'env:prod', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);

  grunt.registerTask('heroku:development', ['env:dev', 'lint', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);
  grunt.registerTask('heroku:production', ['build', 'env:prod', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);
};
<commit_msg>refactoring<commit_after>'use strict';

/**
 * Module dependencies.
 */
var _ = require('lodash'),
  defaultAssets = require('./config/assets/default'),
  testAssets = require('./config/assets/test'),
  fs = require('fs'),
  path = require('path');

module.exports = function (grunt) {
  // Project Configuration
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    env: {
      test: {
        NODE_ENV: 'test'
      },
      dev: {
        NODE_ENV: 'development'
      },
      prod: {
        NODE_ENV: 'production'
      }
    },
    watch: {
      serverViews: {
        files: defaultAssets.server.views,
        options: {
          livereload: true
        }
      },
      serverJS: {
        files: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS),
        tasks: ['jshint'],
        options: {
          livereload: true
        }
      },
      clientViews: {
        files: defaultAssets.client.views,
        options: {
          livereload: true
        }
      },
      clientJS: {
        files: defaultAssets.client.js,
        tasks: ['jshint'],
        options: {
          livereload: true
        }
      },
      clientCSS: {
        files: defaultAssets.client.css,
        tasks: ['csslint'],
        options: {
          livereload: true
        }
      },
      clientSCSS: {
        files: defaultAssets.client.sass,
        tasks: ['sass', 'csslint'],
        options: {
          livereload: true
        }
      },
      clientLESS: {
        files: defaultAssets.client.less,
        tasks: ['less', 'csslint'],
        options: {
          livereload: true
        }
      }
    },
    nodemon: {
      dev: {
        script: 'server.js',
        options: {
          nodeArgs: ['--debug'],
          ext: 'js,html',
          watch: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.views, defaultAssets.server.allJS, defaultAssets.server.config)
        }
      }
    },
    concurrent: {
      default: ['nodemon', 'watch'],
      debug: ['nodemon', 'watch', 'node-inspector'],
      options: {
        logConcurrentOutput: true
      }
    },
    jshint: {
      all: {
        src: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS, defaultAssets.client.js, testAssets.tests.server, testAssets.tests.client, testAssets.tests.e2e),
        options: {
          jshintrc: true,
          node: true,
          mocha: true,
          jasmine: true
        }
      }
    },
    csslint: {
      options: {
        csslintrc: '.csslintrc'
      },
      all: {
        src: defaultAssets.client.css
      }
    },
    ngAnnotate: {
      production: {
        files: {
          'public/dist/application.js': defaultAssets.client.js
        }
      }
    },
    uglify: {
      production: {
        options: {
          mangle: false
        },
        files: {
          'public/dist/application.min.js': 'public/dist/application.js'
        }
      }
    },
    cssmin: {
      combine: {
        files: {
          'public/dist/application.min.css': defaultAssets.client.css
        }
      }
    },
    sass: {
      dist: {
        options: {
          bundleExec: true
        },
        files: [{
          expand: true,
          src: defaultAssets.client.sass,
          ext: '.css',
          rename: function (base, src) {
            return src.replace('/scss/', '/css/');
          }
				}]
      }
    },
    less: {
      dist: {
        files: [{
          expand: true,
          src: defaultAssets.client.less,
          ext: '.css',
          rename: function (base, src) {
            return src.replace('/less/', '/css/');
          }
				}]
      }
    },
    'node-inspector': {
      custom: {
        options: {
          'web-port': 1337,
          'web-host': 'localhost',
          'debug-port': 5858,
          'save-live-edit': true,
          'no-preload': true,
          'stack-trace-limit': 50,
          'hidden': []
        }
      }
    },
    mochaTest: {
      src: testAssets.tests.server,
      options: {
        reporter: 'spec',
        timeout: 10000
      }
    },
    mocha_istanbul: {
      coverage: {
        src: testAssets.tests.server,
        options: {
          print: 'detail',
          coverage: true,
          require: 'test.js',
          coverageFolder: 'coverage',
          reportFormats: ['cobertura','lcovonly'],
          check: {
            lines: 40,
            statements: 40
          }
        }
      }
    },
    karma: {
      unit: {
        configFile: 'karma.conf.js'
      }
    },
    protractor: {
      options: {
        configFile: 'protractor.conf.js',
        keepAlive: true,
        noColor: false,
        webdriverManagerUpdate: true
      },
      e2e: {
        options: {
          args: {} // Target-specific arguments
        }
      }
    },
    copy: {
      localConfig: {
        src: 'config/env/local.example.js',
        dest: 'config/env/local.js',
        filter: function () {
          return !fs.existsSync('config/env/local.js');
        }
      }
    }
  });

  grunt.event.on('coverage', function(lcovFileContents, done) {
    require('coveralls').handleInput(lcovFileContents, function(err) {
      if (err) {
        return done(err);
      }
      done();
    });
  });

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

  // Make sure upload directory exists
  grunt.task.registerTask('mkdir:upload', 'Task that makes sure upload directory exists.', function () {
    // Get the callback
    var done = this.async();

    grunt.file.mkdir(path.normalize(__dirname + '/modules/users/client/img/profile/uploads'));

    done();
  });

  // Connect to the MongoDB instance and load the models
  grunt.task.registerTask('mongoose', 'Task that connects to the MongoDB instance and loads the application models.', function () {
    // Get the callback
    var done = this.async();

    // Use mongoose configuration
    var mongoose = require('./config/lib/mongoose.js');

    // Connect to database
    mongoose.connect(function (db) {
      done();
    });
  });

  grunt.task.registerTask('server', 'Starting the server', function () {
    // Get the callback
    var done = this.async();

    var path = require('path');
    var app = require(path.resolve('./config/lib/app'));
    var server = app.start(function () {
      done();
    });
  });

  // Lint CSS and JavaScript files.
  grunt.registerTask('lint', ['sass', 'less', 'jshint', 'csslint']);

  // Lint project files and minify them into two production files.
  grunt.registerTask('build', ['env:dev', 'lint', 'ngAnnotate', 'uglify', 'cssmin']);

  // Run the project tests
  grunt.registerTask('test', ['env:test', 'lint', 'mkdir:upload', 'copy:localConfig', 'server', 'mochaTest', 'karma:unit', 'protractor']);
  grunt.registerTask('test:server', ['env:test', 'lint', 'server', 'mochaTest']);
  grunt.registerTask('test:client', ['env:test', 'lint', 'server', 'karma:unit']);
  grunt.registerTask('test:e2e', ['env:test', 'lint', 'server', 'protractor']);

  // Run project coverage
  grunt.registerTask('coverage', ['env:test', 'lint', 'mocha_istanbul:coverage']);

  // Run the project in development mode
  grunt.registerTask('default', ['env:dev', 'lint', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);

  // Run the project in debug mode
  grunt.registerTask('debug', ['env:dev', 'lint', 'mkdir:upload', 'copy:localConfig', 'concurrent:debug']);

  // Run the project in production mode
  grunt.registerTask('prod', ['build', 'env:prod', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);

  grunt.registerTask('heroku:development', ['env:dev', 'lint', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);
  grunt.registerTask('heroku:production', ['build', 'env:prod', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    var fs=require("fs");
    var pathModule=require("path");

    var filterTypeScriptFiles = function(content, srcPath) {
        var matchRule = /^.*@private/ig;
        if (matchRule.test(content))
        {
            return false;
        }
        var processed = content;
        processed = processed.replace(/\/\/[\/\s]*@private((.|\s)*?)\/\/[\/\s]*@endprivate/gm, "");
        return processed;
    };

    var updatePackageDef = function(content, update)
    {
        var contentAsObject = JSON.parse(content);
        update(contentAsObject);
        return JSON.stringify(contentAsObject, null, "\t");
    }

    var updateModulesPackageDef = function(content, srcPath) {
        return updatePackageDef(content, function(contentAsObject) {
            contentAsObject.version = localCfg.packageVersion;
            if (localCfg.commitSHA) {
                contentAsObject.repository.url += "/commit/" + localCfg.commitSHA;
            }
        });
    };

    var updateAppPackageDef = function(content, srcPath) {
        var currentAppName = grunt.task.current.data.appName;
        return updatePackageDef(content, function(contentAsObject) {
            contentAsObject.version = localCfg.packageVersion;
            contentAsObject.author = "Telerik <support@telerik.com>";
            var specificKeywords = ["telerik", "mobile", "nativescript", "{N}", "tns", "appbuilder"];
            if (currentAppName.indexOf("template-") == 0) {
                var templateName = currentAppName.substring("template-".length);
                contentAsObject.name = "tns-" + currentAppName;
                contentAsObject.description = "Nativescript " + templateName + " project template";
                specificKeywords.push("template");
            }
            else {
                contentAsObject.name = "tns-samples-" + currentAppName;
                contentAsObject.description = "Nativescript " + currentAppName + " sample application";
                specificKeywords.push("sample");
            }
            contentAsObject.license = "BSD";
            addKeywords(contentAsObject, specificKeywords);

            if (!contentAsObject.repository) {
                contentAsObject.repository = {};
            }
            if (!contentAsObject.repository.url) {
                contentAsObject.repository.url = localCfg.mainPackageContent.repository.url;
            }
            if (localCfg.commitSHA) {
                contentAsObject.repository.url += "/commit/" + localCfg.commitSHA;
            }
        });
    };

    var addKeywords = function(packageObject, newKeywords) {
        if (!packageObject.keywords) {
            packageObject.keywords = newKeywords;
            return;
        }

        if (typeof(packageObject.keywords) == "string") {
            packageObject.keywords = packageObject.keywords.split(" ");
        }
        packageObject.keywords = packageObject.keywords.concat(newKeywords);
    };

    var updateDefinitionsPackageDef = function(content, srcPath) {
        return updatePackageDef(content, function(contentAsObject) {
            contentAsObject.version = localCfg.packageVersion;
            contentAsObject.name = "tns-definitions";
            contentAsObject.description = "NativeScript Module definitions";
            contentAsObject.license = "Apache-2.0";
            if (localCfg.commitSHA) {
                contentAsObject.repository.url += "/commit/" + localCfg.commitSHA;
            }
        });
    };

    var getCommitSha = function() {
        if (process.env.GIT_COMMIT) {
            return process.env.GIT_COMMIT;
        }
        return "";
    };

    var assignGitSHA = function(err, stdout, stderr, cb) {
        if (!localCfg.commitSHA) {
            localCfg.commitSHA = stdout.replace("\n", "");
        }
        cb();
    };

    var getPackageVersion = function() {
        var buildVersion = process.env.PACKAGE_VERSION;
        if (!buildVersion) {
            return localCfg.mainPackageContent.version;
        }
        return localCfg.mainPackageContent.version + "-" + buildVersion;
    };

    var processAppFile = function(content, srcPath) {
        return content;
    };

    var getSubDirs = function(dir) {
        var allObjects = fs.readdirSync(dir);
        var allDirs = [];
        for (var i=0; i<allObjects.length; i++)
        {
            var currentObjName = allObjects[i];
            var currentObjPath = pathModule.join(dir, currentObjName);
            var stats = fs.statSync(currentObjPath);
            if (stats.isDirectory())
            {
                allDirs.push({name: currentObjName, path: currentObjPath});
            }
        }
        return allDirs;
    }

    var localCfg = {
        srcDir: ".",
        srcAppsDir: "./apps",
        packageJsonFilePath: "./package.json",
        outDir: "./bin/dist",
        outModulesDir: "./bin/dist/modules",
        outAppsDir: "./bin/dist/apps",
        outTsAppsDir: "./bin/dist/ts-apps",
        outDefinitionsDir: "./bin/dist/definitions",

        excludedModules: [
            "!./ui/slide-out/**/*.*"
        ]
    };

    var nodeTestEnv = JSON.parse(JSON.stringify(process.env));
    nodeTestEnv['NODE_PATH'] = localCfg.outModulesDir;

    localCfg.nodeTestsDir = pathModule.join(localCfg.outModulesDir, 'node-tests');

    localCfg.mainPackageContent = grunt.file.readJSON(localCfg.packageJsonFilePath);
    localCfg.packageVersion = getPackageVersion(localCfg.packageJsonFilePath);
    localCfg.commitSHA = getCommitSha();
    localCfg.defaultExcludes = [
            "!" + localCfg.outDir + "/**/*.*",
            "!./node_modules/**/*.*",
            "!./bin/**/*.*",
            "!./build/**/*.*",
            "!./Deploy/**/*.*",
            "!./obj/**/*.*",
            "!./out/**/*.*",
            "!./.*/**/*.*"
        ];
    localCfg.typeScriptSrc = [
            "./**/*.ts"
        ].concat(localCfg.defaultExcludes).concat(localCfg.excludedModules);
    localCfg.typeScriptSrcForTsLint = localCfg.typeScriptSrc.concat([
        "!./ios.d.ts",
        "!./android17.d.ts",
        "!./libjs.d.ts"
    ]);

    grunt.initConfig({
        localCfg : localCfg,
        pkg: grunt.file.readJSON('package.json'),
        clean: {
            build: {
                src: [localCfg.outDir]
            },
            typeScriptLeftovers: {
                expand: true,
                src: [
                    "./.baseDir.*",
                    "./_references.js",
                    "./**/*.map"
                ],
                cwd: localCfg.outModulesDir
            },
            nodeTests: {
                src: localCfg.nodeTestsDir,
            },
            readyAppFiles: {
                src: [localCfg.outModulesDir + "/apps/**"]
            }
        },
        copy: {
            jsLibs: {
                expand: true,
                src: [
                    "./js-libs/**/*.js",
                    "./fetch/**/*.js",
                ],
                dest: "<%= localCfg.outModulesDir %>/",
                cwd: localCfg.srcDir
            },
            license: {
                expand: true,
                src: [
                    "./LICENSE",
                ],
                dest: "<%= localCfg.outModulesDir %>/",
                cwd: localCfg.srcDir
            },
            appLicense: {
                expand: true,
                src: ["./LICENSE"],
                cwd: localCfg.srcAppsDir,
                dest: "__dummy__"
            },
            definitionFiles: {
                src: [
                    localCfg.srcDir + "/**/*.d.ts",
                    pathModule.join(localCfg.srcDir, "LICENSE"),
                    //Exclude the d.ts files in the apps folder - these are part of the apps and are already packed there!
                    "!" + localCfg.srcDir + "/apps/**"
                ].concat(localCfg.defaultExcludes).concat(localCfg.excludedModules),
                dest: localCfg.outDefinitionsDir + "/",
                expand: true,
                options: {
                    process: filterTypeScriptFiles
                }
            },
            modulesPackageDef: {
                src: localCfg.packageJsonFilePath,
                dest: localCfg.outModulesDir + "/",
                options: {
                    process: updateModulesPackageDef
                }
            },
            definitionsPackageDef: {
                src: localCfg.packageJsonFilePath,
                dest: localCfg.outDefinitionsDir + "/",
                options: {
                    process: updateDefinitionsPackageDef
                }
            },
            appPackageDef: {
                expand: true,
                flatten: true,
                src: "__app_package_json",
                dest:  "__dummy__",
                options: {
                    process: updateAppPackageDef
                }
            },
            childPackageFiles: {
                src: [
                    localCfg.srcDir + "/**/package.json",
                    "!./package.json",
                    "!./Deploy/**/*.*",
                    "!./bin/**/*.*",
                    "!./Tests/**/*.*",
                    "!" + localCfg.outDir + "/**/*.*"
                ].concat(localCfg.excludedModules),
                dest: localCfg.outModulesDir + "/"
            },
            rawAppsFiles: {
                expand: true,
                src: [
                    "**/*.*",
                    "**/*",
                    "!**/*.map",
                    "!**/*.ts"
                ],
                dest: localCfg.outAppsDir,
                cwd: localCfg.srcAppsDir,
                dot: true
            },
            readyAppFiles: {
                expand: true,
                src: ["./**/*.*"],
                dest: localCfg.outAppsDir + "/",
                cwd: localCfg.outModulesDir + "/apps/",
                options: {
                    process: processAppFile
                }
            },
            readyTsAppFiles: {
                expand: true,
                src: ["./**/*.*", "!./**/*.map"],
                dest: localCfg.outTsAppsDir + "/",
                cwd: localCfg.srcAppsDir
            },
            readyPackages: {
                expand: true,
                src: ["./**/*.tgz"],
                dest: localCfg.outDir + "/",
                cwd: localCfg.outDir,
                flatten: true
            }
        },
        ts: {
            build: {
                src: localCfg.typeScriptSrc,
                outDir: localCfg.outModulesDir,
                options: {
                    fast: 'never',
                    module: "commonjs",
                    target: "es5",
                    sourceMap: false,
                    declaration: false,
                    removeComments: "<%= !grunt.option('leavecomments') || '' %>",
                    compiler: "node_modules/typescript/bin/tsc",
                    noEmitOnError: true,
                    experimentalDecorators: true
                }
            },
            buildNodeTests: {
                src: [
                    'js-libs/easysax/**/*.ts',
                    'xml/**/*.ts',
                    'node-tests/**/*.ts',
                ],
                outDir: localCfg.outModulesDir,
                options: {
                    fast: 'never',
                    module: "commonjs",
                    target: "es5",
                    sourceMap: false,
                    declaration: false,
                    removeComments: "<%= !grunt.option('leavecomments') || '' %>",
                    compiler: "node_modules/typescript/bin/tsc",
                    noEmitOnError: true
                }
            }
        },
        tslint: {
            build: {
                files: {
                    src: localCfg.typeScriptSrcForTsLint
                },
                options: {
                    configuration: grunt.file.readJSON("./build/tslint.json")
                }
            }
        },
        exec: {
            packModules: {
                cmd: "npm pack",
                cwd: localCfg.outModulesDir + "/"
            },
            packDefinitions: {
                cmd: "npm pack",
                cwd: localCfg.outDefinitionsDir + "/"
            },
            packApp: {
                cmd: "npm pack",
                cwd: "__dummy__"
            },
            mochaNode: {
                cmd: "grunt simplemocha:node"
            }
        },
        multidest: {
            copyLicenseFiles: {
                tasks: ["copy:appLicense"],
                dest: function() {
                    var apps = getSubDirs(localCfg.srcAppsDir);
                    var targetDirs = [];
                    apps.forEach(function(item){
                        targetDirs.push(pathModule.join(localCfg.outAppsDir, item.name));
                        targetDirs.push(pathModule.join(localCfg.outTsAppsDir, item.name));
                    });
                    return targetDirs;
                }()
            }
        },
        shell: {
            getGitSHA: {
                command: "git rev-parse HEAD",
                options: {
                    callback: assignGitSHA
                }
            },
        },
        simplemocha: {
            node: {
                src: localCfg.nodeTestsDir + '/**/*.js'
            }
        },
        env: {
            nodeTests: {
                NODE_PATH: localCfg.outModulesDir,
            }
        }
    });

    grunt.loadNpmTasks("grunt-ts");
    grunt.loadNpmTasks("grunt-contrib-clean");
    grunt.loadNpmTasks("grunt-contrib-copy");
    grunt.loadNpmTasks("grunt-exec");
    grunt.loadNpmTasks("grunt-tslint");
    grunt.loadNpmTasks("grunt-multi-dest");
    grunt.loadNpmTasks("grunt-shell");
    grunt.loadNpmTasks("grunt-env");
    grunt.loadNpmTasks("grunt-simple-mocha");

    var cloneTasks = function(originalTasks, taskNameSuffix)
    {
        var clonedTasks = [];
        for(var i=0; i<originalTasks.length; i++)
        {
            var originalTask = originalTasks[i];

            var taskCfg = grunt.util._.clone(grunt.config(originalTask.name));
            var taskName = grunt.util._.clone(originalTask.name);
            taskName[1] = taskName[1] + "_" + taskNameSuffix;

            originalTask.specializeCfg(taskCfg, taskNameSuffix);

            clonedTasks.push({name: taskName, cfg: taskCfg});
        }
        return clonedTasks;
    }

    var enqueueTasks = function(tasks) {
        for (var i=0; i<tasks.length; i++) {
            var task = tasks[i];
            grunt.config(task.name, task.cfg);
            grunt.task.run(task.name.join(":"));
        }
    }

    grunt.registerTask("processEachApp", function(outAppsDir, pkgAppNameSuffix){
        var allapps = getSubDirs(localCfg.srcAppsDir);
        var tasks = [
            {
                name: ["copy", "appPackageDef"],
                specializeCfg: function (cfg, currentAppName) {
                    outAppDir = pathModule.join(outAppsDir, currentAppName);
                    var pkgFilePath = pathModule.join(outAppDir, "package.json");
                    cfg.src = pkgFilePath;
                    cfg.dest = outAppDir;
                    cfg.appName = currentApp.name + (pkgAppNameSuffix || "");
                }
            },
            {
                name: ["exec", "packApp"],
                specializeCfg: function(cfg, currentAppName) {
                    cfg.cwd = pathModule.join(outAppsDir, currentAppName);
                }
            }
        ];

        for (var j=0; j<allapps.length; j++)
        {
            var currentApp = allapps[j];
            var clonedTasks = cloneTasks(tasks, currentApp.name);

            enqueueTasks(clonedTasks);
        }
    });

    grunt.registerTask("tests", [
        "default"
    ]);

    grunt.registerTask("collect-apps-raw-files", [
        "copy:rawAppsFiles",
        "multidest:copyLicenseFiles"
    ]);

    // Does nothing to avoid copying the same files twice. Instead,
    //  the distribute-definition-files tasks copies the d.ts files
    //  from the source root directly to the output folder.
    grunt.registerTask("collect-definitions-raw-files", []);

    grunt.registerTask("collect-modules-raw-files", [
        "copy:jsLibs",
        "copy:license"
    ]);

    grunt.registerTask("compile-ts", [
        "ts:build",
        "clean:typeScriptLeftovers",
        "copy:childPackageFiles"
    ]);
    grunt.registerTask("distribute-apps-files", [
        "copy:readyAppFiles",
        "clean:readyAppFiles"
    ]);
    grunt.registerTask("distribute-ts-apps-files", [
        "copy:readyTsAppFiles"
    ]);
    grunt.registerTask("distribute-definition-files", [
        "copy:definitionFiles"
    ]);
    grunt.registerTask("pack-modules", [
        "copy:modulesPackageDef",
        "exec:packModules"
    ]);
    grunt.registerTask("pack-apps", [
        "processEachApp:" + localCfg.outAppsDir
    ]);
    grunt.registerTask("pack-ts-apps", [
        "processEachApp:" + localCfg.outTsAppsDir + ":-ts"
    ]);
    grunt.registerTask("pack-definitions", [
        "copy:definitionsPackageDef",
        "exec:packDefinitions"
    ]);
    grunt.registerTask("get-ready-packages", [
        "copy:readyPackages"
    ]);

    grunt.registerTask("default", ((typeof(grunt.option('runtslint')) != "undefined" && !grunt.option('runtslint')) ? [] : ["tslint:build"]).concat([
        "clean:build",
        "shell:getGitSHA",

        "collect-apps-raw-files",
        "collect-definitions-raw-files",
        "collect-modules-raw-files",

        "compile-ts",
        "distribute-apps-files",
        "distribute-ts-apps-files",
        "distribute-definition-files",

        "pack-modules",
        "pack-apps",
        "pack-ts-apps",
        "pack-definitions",
        "get-ready-packages"
    ]));

    grunt.registerTask("testEnv", function() {
        console.log('fafla', process.env.NODE_PATH);
        //var x = require('xml')
        //console.log(x);
    });

    grunt.registerTask("node-tests", [
        "clean:nodeTests",
        "ts:buildNodeTests",
        "copy:childPackageFiles",
        "copy:jsLibs",
        "env:nodeTests",
        "exec:mochaNode", //spawn a new process to use the new NODE_PATH
    ]);
};
<commit_msg>Fix package.json output and remove __extends output<commit_after>module.exports = function(grunt) {
    var fs=require("fs");
    var pathModule=require("path");

    var filterTypeScriptFiles = function(content, srcPath) {
        var matchRule = /^.*@private/ig;
        if (matchRule.test(content))
        {
            return false;
        }
        var processed = content;
        processed = processed.replace(/\/\/[\/\s]*@private((.|\s)*?)\/\/[\/\s]*@endprivate/gm, "");
        return processed;
    };

    var updatePackageDef = function(content, update)
    {
        var contentAsObject = JSON.parse(content);
        update(contentAsObject);
        return JSON.stringify(contentAsObject, null, "\t");
    }

    var updateModulesPackageDef = function(content, srcPath) {
        return updatePackageDef(content, function(contentAsObject) {
            contentAsObject.version = localCfg.packageVersion;
            if (localCfg.commitSHA) {
                contentAsObject.repository.url += "/commit/" + localCfg.commitSHA;
            }
        });
    };

    var updateAppPackageDef = function(content, srcPath) {
        var currentAppName = grunt.task.current.data.appName;
        return updatePackageDef(content, function(contentAsObject) {
            contentAsObject.version = localCfg.packageVersion;
            contentAsObject.author = "Telerik <support@telerik.com>";
            var specificKeywords = ["telerik", "mobile", "nativescript", "{N}", "tns", "appbuilder"];
            if (currentAppName.indexOf("template-") == 0) {
                var templateName = currentAppName.substring("template-".length);
                contentAsObject.name = "tns-" + currentAppName;
                contentAsObject.description = "Nativescript " + templateName + " project template";
                specificKeywords.push("template");
            }
            else {
                contentAsObject.name = "tns-samples-" + currentAppName;
                contentAsObject.description = "Nativescript " + currentAppName + " sample application";
                specificKeywords.push("sample");
            }
            contentAsObject.license = "BSD";
            addKeywords(contentAsObject, specificKeywords);

            if (!contentAsObject.repository) {
                contentAsObject.repository = {};
            }
            if (!contentAsObject.repository.url) {
                contentAsObject.repository.url = localCfg.mainPackageContent.repository.url;
            }
            if (localCfg.commitSHA) {
                contentAsObject.repository.url += "/commit/" + localCfg.commitSHA;
            }
        });
    };

    var addKeywords = function(packageObject, newKeywords) {
        if (!packageObject.keywords) {
            packageObject.keywords = newKeywords;
            return;
        }

        if (typeof(packageObject.keywords) == "string") {
            packageObject.keywords = packageObject.keywords.split(" ");
        }
        packageObject.keywords = packageObject.keywords.concat(newKeywords);
    };

    var updateDefinitionsPackageDef = function(content, srcPath) {
        return updatePackageDef(content, function(contentAsObject) {
            contentAsObject.version = localCfg.packageVersion;
            contentAsObject.name = "tns-definitions";
            contentAsObject.description = "NativeScript Module definitions";
            contentAsObject.license = "Apache-2.0";
            if (localCfg.commitSHA) {
                contentAsObject.repository.url += "/commit/" + localCfg.commitSHA;
            }
        });
    };

    var getCommitSha = function() {
        if (process.env.GIT_COMMIT) {
            return process.env.GIT_COMMIT;
        }
        return "";
    };

    var assignGitSHA = function(err, stdout, stderr, cb) {
        if (!localCfg.commitSHA) {
            localCfg.commitSHA = stdout.replace("\n", "");
        }
        cb();
    };

    var getPackageVersion = function() {
        var buildVersion = process.env.PACKAGE_VERSION;
        if (!buildVersion) {
            return localCfg.mainPackageContent.version;
        }
        return localCfg.mainPackageContent.version + "-" + buildVersion;
    };

    var processAppFile = function(content, srcPath) {
        return content;
    };

    var getSubDirs = function(dir) {
        var allObjects = fs.readdirSync(dir);
        var allDirs = [];
        for (var i=0; i<allObjects.length; i++)
        {
            var currentObjName = allObjects[i];
            var currentObjPath = pathModule.join(dir, currentObjName);
            var stats = fs.statSync(currentObjPath);
            if (stats.isDirectory())
            {
                allDirs.push({name: currentObjName, path: currentObjPath});
            }
        }
        return allDirs;
    }

    var localCfg = {
        srcDir: ".",
        srcAppsDir: "./apps",
        packageJsonFilePath: "./package.json",
        outDir: "./bin/dist",
        outModulesDir: "./bin/dist/modules",
        outAppsDir: "./bin/dist/apps",
        outTsAppsDir: "./bin/dist/ts-apps",
        outDefinitionsDir: "./bin/dist/definitions",

        excludedModules: [
            "!./ui/slide-out/**/*.*"
        ]
    };

    var nodeTestEnv = JSON.parse(JSON.stringify(process.env));
    nodeTestEnv['NODE_PATH'] = localCfg.outModulesDir;

    localCfg.nodeTestsDir = pathModule.join(localCfg.outModulesDir, 'node-tests');

    localCfg.mainPackageContent = grunt.file.readJSON(localCfg.packageJsonFilePath);
    localCfg.packageVersion = getPackageVersion(localCfg.packageJsonFilePath);
    localCfg.commitSHA = getCommitSha();
    localCfg.defaultExcludes = [
            "!" + localCfg.outDir + "/**/*.*",
            "!./node_modules/**/*.*",
            "!./bin/**/*.*",
            "!./build/**/*.*",
            "!./Deploy/**/*.*",
            "!./obj/**/*.*",
            "!./out/**/*.*",
            "!./.*/**/*.*"
        ];
    localCfg.typeScriptSrc = [
            "./**/*.ts"
        ].concat(localCfg.defaultExcludes).concat(localCfg.excludedModules);
    localCfg.typeScriptSrcForTsLint = localCfg.typeScriptSrc.concat([
        "!./ios.d.ts",
        "!./android17.d.ts",
        "!./libjs.d.ts"
    ]);

    grunt.initConfig({
        localCfg : localCfg,
        pkg: grunt.file.readJSON('package.json'),
        clean: {
            build: {
                src: [localCfg.outDir]
            },
            typeScriptLeftovers: {
                expand: true,
                src: [
                    "./.baseDir.*",
                    "./_references.js",
                    "./**/*.map"
                ],
                cwd: localCfg.outModulesDir
            },
            nodeTests: {
                src: localCfg.nodeTestsDir,
            },
            readyAppFiles: {
                src: [localCfg.outModulesDir + "/apps/**"]
            }
        },
        copy: {
            jsLibs: {
                expand: true,
                src: [
                    "./js-libs/**/*.js",
                    "./fetch/**/*.js",
                ],
                dest: "<%= localCfg.outModulesDir %>/",
                cwd: localCfg.srcDir
            },
            license: {
                expand: true,
                src: [
                    "./LICENSE",
                ],
                dest: "<%= localCfg.outModulesDir %>/",
                cwd: localCfg.srcDir
            },
            appLicense: {
                expand: true,
                src: ["./LICENSE"],
                cwd: localCfg.srcAppsDir,
                dest: "__dummy__"
            },
            definitionFiles: {
                src: [
                    localCfg.srcDir + "/**/*.d.ts",
                    pathModule.join(localCfg.srcDir, "LICENSE"),
                    //Exclude the d.ts files in the apps folder - these are part of the apps and are already packed there!
                    "!" + localCfg.srcDir + "/apps/**"
                ].concat(localCfg.defaultExcludes).concat(localCfg.excludedModules),
                dest: localCfg.outDefinitionsDir + "/",
                expand: true,
                options: {
                    process: filterTypeScriptFiles
                }
            },
            modulesPackageDef: {
                expand: true,
                src: localCfg.packageJsonFilePath,
                dest: localCfg.outModulesDir + "/",
                options: {
                    process: updateModulesPackageDef
                }
            },
            definitionsPackageDef: {
                src: localCfg.packageJsonFilePath,
                dest: localCfg.outDefinitionsDir + "/",
                options: {
                    process: updateDefinitionsPackageDef
                }
            },
            appPackageDef: {
                expand: true,
                flatten: true,
                src: "__app_package_json",
                dest:  "__dummy__",
                options: {
                    process: updateAppPackageDef
                }
            },
            childPackageFiles: {
                expand: true,
                src: [
                    localCfg.srcDir + "/**/package.json",
                    "!./package.json",
                    "!./Deploy/**/*.*",
                    "!./bin/**/*.*",
                    "!./Tests/**/*.*",
                    "!" + localCfg.outDir + "/**/*.*"
                ].concat(localCfg.excludedModules),
                dest: localCfg.outModulesDir + "/"
            },
            rawAppsFiles: {
                expand: true,
                src: [
                    "**/*.*",
                    "**/*",
                    "!**/*.map",
                    "!**/*.ts"
                ],
                dest: localCfg.outAppsDir,
                cwd: localCfg.srcAppsDir,
                dot: true
            },
            readyAppFiles: {
                expand: true,
                src: ["./**/*.*"],
                dest: localCfg.outAppsDir + "/",
                cwd: localCfg.outModulesDir + "/apps/",
                options: {
                    process: processAppFile
                }
            },
            readyTsAppFiles: {
                expand: true,
                src: ["./**/*.*", "!./**/*.map"],
                dest: localCfg.outTsAppsDir + "/",
                cwd: localCfg.srcAppsDir
            },
            readyPackages: {
                expand: true,
                src: ["./**/*.tgz"],
                dest: localCfg.outDir + "/",
                cwd: localCfg.outDir,
                flatten: true
            }
        },
        ts: {
            build: {
                src: localCfg.typeScriptSrc,
                outDir: localCfg.outModulesDir,
                options: {
                    fast: 'never',
                    module: "commonjs",
                    target: "es5",
                    sourceMap: false,
                    declaration: false,
                    removeComments: "<%= !grunt.option('leavecomments') || '' %>",
                    compiler: "node_modules/typescript/bin/tsc",
                    noEmitOnError: true,
                    experimentalDecorators: true,
                    noEmitHelpers: true
                }
            },
            buildNodeTests: {
                src: [
                    'js-libs/easysax/**/*.ts',
                    'xml/**/*.ts',
                    'node-tests/**/*.ts',
                ],
                outDir: localCfg.outModulesDir,
                options: {
                    fast: 'never',
                    module: "commonjs",
                    target: "es5",
                    sourceMap: false,
                    declaration: false,
                    removeComments: "<%= !grunt.option('leavecomments') || '' %>",
                    compiler: "node_modules/typescript/bin/tsc",
                    noEmitOnError: true
                }
            }
        },
        tslint: {
            build: {
                files: {
                    src: localCfg.typeScriptSrcForTsLint
                },
                options: {
                    configuration: grunt.file.readJSON("./build/tslint.json")
                }
            }
        },
        exec: {
            packModules: {
                cmd: "npm pack",
                cwd: localCfg.outModulesDir + "/"
            },
            packDefinitions: {
                cmd: "npm pack",
                cwd: localCfg.outDefinitionsDir + "/"
            },
            packApp: {
                cmd: "npm pack",
                cwd: "__dummy__"
            },
            mochaNode: {
                cmd: "grunt simplemocha:node"
            }
        },
        multidest: {
            copyLicenseFiles: {
                tasks: ["copy:appLicense"],
                dest: function() {
                    var apps = getSubDirs(localCfg.srcAppsDir);
                    var targetDirs = [];
                    apps.forEach(function(item){
                        targetDirs.push(pathModule.join(localCfg.outAppsDir, item.name));
                        targetDirs.push(pathModule.join(localCfg.outTsAppsDir, item.name));
                    });
                    return targetDirs;
                }()
            }
        },
        shell: {
            getGitSHA: {
                command: "git rev-parse HEAD",
                options: {
                    callback: assignGitSHA
                }
            },
        },
        simplemocha: {
            node: {
                src: localCfg.nodeTestsDir + '/**/*.js'
            }
        },
        env: {
            nodeTests: {
                NODE_PATH: localCfg.outModulesDir,
            }
        }
    });

    grunt.loadNpmTasks("grunt-ts");
    grunt.loadNpmTasks("grunt-contrib-clean");
    grunt.loadNpmTasks("grunt-contrib-copy");
    grunt.loadNpmTasks("grunt-exec");
    grunt.loadNpmTasks("grunt-tslint");
    grunt.loadNpmTasks("grunt-multi-dest");
    grunt.loadNpmTasks("grunt-shell");
    grunt.loadNpmTasks("grunt-env");
    grunt.loadNpmTasks("grunt-simple-mocha");

    var cloneTasks = function(originalTasks, taskNameSuffix)
    {
        var clonedTasks = [];
        for(var i=0; i<originalTasks.length; i++)
        {
            var originalTask = originalTasks[i];

            var taskCfg = grunt.util._.clone(grunt.config(originalTask.name));
            var taskName = grunt.util._.clone(originalTask.name);
            taskName[1] = taskName[1] + "_" + taskNameSuffix;

            originalTask.specializeCfg(taskCfg, taskNameSuffix);

            clonedTasks.push({name: taskName, cfg: taskCfg});
        }
        return clonedTasks;
    }

    var enqueueTasks = function(tasks) {
        for (var i=0; i<tasks.length; i++) {
            var task = tasks[i];
            grunt.config(task.name, task.cfg);
            grunt.task.run(task.name.join(":"));
        }
    }

    grunt.registerTask("processEachApp", function(outAppsDir, pkgAppNameSuffix){
        var allapps = getSubDirs(localCfg.srcAppsDir);
        var tasks = [
            {
                name: ["copy", "appPackageDef"],
                specializeCfg: function (cfg, currentAppName) {
                    outAppDir = pathModule.join(outAppsDir, currentAppName);
                    var pkgFilePath = pathModule.join(outAppDir, "package.json");
                    cfg.src = pkgFilePath;
                    cfg.dest = outAppDir;
                    cfg.appName = currentApp.name + (pkgAppNameSuffix || "");
                }
            },
            {
                name: ["exec", "packApp"],
                specializeCfg: function(cfg, currentAppName) {
                    cfg.cwd = pathModule.join(outAppsDir, currentAppName);
                }
            }
        ];

        for (var j=0; j<allapps.length; j++)
        {
            var currentApp = allapps[j];
            var clonedTasks = cloneTasks(tasks, currentApp.name);

            enqueueTasks(clonedTasks);
        }
    });

    grunt.registerTask("tests", [
        "default"
    ]);

    grunt.registerTask("collect-apps-raw-files", [
        "copy:rawAppsFiles",
        "multidest:copyLicenseFiles"
    ]);

    // Does nothing to avoid copying the same files twice. Instead,
    //  the distribute-definition-files tasks copies the d.ts files
    //  from the source root directly to the output folder.
    grunt.registerTask("collect-definitions-raw-files", []);

    grunt.registerTask("collect-modules-raw-files", [
        "copy:jsLibs",
        "copy:license"
    ]);

    grunt.registerTask("compile-ts", [
        "ts:build",
        "clean:typeScriptLeftovers",
        "copy:childPackageFiles"
    ]);
    grunt.registerTask("distribute-apps-files", [
        "copy:readyAppFiles",
        "clean:readyAppFiles"
    ]);
    grunt.registerTask("distribute-ts-apps-files", [
        "copy:readyTsAppFiles"
    ]);
    grunt.registerTask("distribute-definition-files", [
        "copy:definitionFiles"
    ]);
    grunt.registerTask("pack-modules", [
        "copy:modulesPackageDef",
        "exec:packModules"
    ]);
    grunt.registerTask("pack-apps", [
        "processEachApp:" + localCfg.outAppsDir
    ]);
    grunt.registerTask("pack-ts-apps", [
        "processEachApp:" + localCfg.outTsAppsDir + ":-ts"
    ]);
    grunt.registerTask("pack-definitions", [
        "copy:definitionsPackageDef",
        "exec:packDefinitions"
    ]);
    grunt.registerTask("get-ready-packages", [
        "copy:readyPackages"
    ]);

    grunt.registerTask("default", ((typeof(grunt.option('runtslint')) != "undefined" && !grunt.option('runtslint')) ? [] : ["tslint:build"]).concat([
        "clean:build",
        "shell:getGitSHA",

        "collect-apps-raw-files",
        "collect-definitions-raw-files",
        "collect-modules-raw-files",

        "compile-ts",
        "distribute-apps-files",
        "distribute-ts-apps-files",
        "distribute-definition-files",

        "pack-modules",
        "pack-apps",
        "pack-ts-apps",
        "pack-definitions",
        "get-ready-packages"
    ]));

    grunt.registerTask("testEnv", function() {
        console.log('fafla', process.env.NODE_PATH);
        //var x = require('xml')
        //console.log(x);
    });

    grunt.registerTask("node-tests", [
        "clean:nodeTests",
        "ts:buildNodeTests",
        "copy:childPackageFiles",
        "copy:jsLibs",
        "env:nodeTests",
        "exec:mochaNode", //spawn a new process to use the new NODE_PATH
    ]);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        imagemin: {
            dynamic: {
                files: [{
                    expand: true,
                    cwd: 'dev/',
                    src: ['**/*.{png,jpg,gif}'],
                    dest: 'assets/'
                }]
            }
        }
    });

    // 3. Where we tell Grunt we plan to use this plug-in.
     grunt.loadNpmTasks('grunt-contrib-imagemin');
     grunt.loadNpmTasks('grunt-contrib-watch');
     grunt.loadNpmTasks('grunt-autoprefixer');

    // 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
    grunt.registerTask('images', ['imagemin']);

};
<commit_msg>Added JS tasks<commit_after>module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        imagemin: {
            dynamic: {
                files: [{
                    expand: true,
                    cwd: 'dev/assets/',
                    src: ['**/*.{png,jpg,gif}'],
                    dest: 'assets/'
                }]
            }
        },

        clean: {
            images: ['assets'],
            scripts: ['scripts/compiled.js', 'scripts/dev-compiled.js']
        },

        concat:{

                options: {
                    //banner: "---\n---\n", uncomment if Liquid ever needed
                    separator: '\n',
                    stripBanners: true,
                },
                dist: {
                        src: ['scripts/**/*.js'],
                        dest: 'scripts/dev-compiled.js',
                },

        },

        uglify:{
            my_target:{
                files: {
                    'scripts/compiled.js': ['scripts/dev-compiled.js']
                }
            }
        }

    });

    // 3. Where we tell Grunt we plan to use this plug-in.
    grunt.loadNpmTasks('grunt-contrib-imagemin');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-svgmin');
    grunt.loadNpmTasks('grunt-contrib-clean');

    // 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
    grunt.registerTask('images', ['clean:images', 'imagemin']);
    grunt.registerTask('javascript', ['clean:scripts', 'concat', 'jshint', 'uglify']);
    grunt.registerTask('jsdev', ['clean:scripts', 'concat', 'jshint']);
};
<|endoftext|>


<commit_before>var jobs = {};

jobs.ipadic = require('./ipadic-bot');
jobs.namechanger = require('./namechanger');
jobs.hideoalert = require('./hideoalert');
jobs.autoshindan = require('./autoshindan');
jobs.glyphwikibot = require('./glyphwikibot');
<commit_msg>Disable hideoalert<commit_after>var jobs = {};

jobs.ipadic = require('./ipadic-bot');
jobs.namechanger = require('./namechanger');
// jobs.hideoalert = require('./hideoalert');
jobs.autoshindan = require('./autoshindan');
jobs.glyphwikibot = require('./glyphwikibot');
<|endoftext|>


<commit_before>import Posts from './collection.js'
import marked from 'marked';
import Users from 'meteor/nova:users';

//////////////////////////////////////////////////////
// Collection Hooks                                 //
//////////////////////////////////////////////////////

/**
 * @summary Generate HTML body and excerpt from Markdown on post insert
 */
Posts.before.insert(function (userId, doc) {
  if(!!doc.body) {
    const htmlBody = Telescope.utils.sanitize(marked(doc.body));
    doc.htmlBody = htmlBody;
    doc.excerpt = Telescope.utils.trimHTML(htmlBody,30);
  }
});

/**
 * @summary Generate HTML body and excerpt from Markdown when post body is updated
 */
Posts.before.update(function (userId, doc, fieldNames, modifier) {
  // if body is being modified or $unset, update htmlBody too
  if (Meteor.isServer && modifier.$set && modifier.$set.body) {
    const htmlBody = Telescope.utils.sanitize(marked(modifier.$set.body));
    modifier.$set.htmlBody = htmlBody;
    modifier.$set.excerpt = Telescope.utils.trimHTML(htmlBody,30);
  }
  if (Meteor.isServer && modifier.$unset && (typeof modifier.$unset.body !== "undefined")) {
    modifier.$unset.htmlBody = "";
    modifier.$unset.excerpt = "";
  }
});

/**
 * @summary Generate slug when post title is updated
 */
Posts.before.update(function (userId, doc, fieldNames, modifier) {
  // if title is being modified, update slug too
  if (Meteor.isServer && modifier.$set && modifier.$set.title) {
    modifier.$set.slug = Telescope.utils.slugify(modifier.$set.title);
  }
});

/**
 * @summary Disallow $rename
 */
Posts.before.update(function (userId, doc, fieldNames, modifier) {
  if (!!modifier.$rename) {
    throw new Meteor.Error("illegal $rename operator detected!");
  }
});

//////////////////////////////////////////////////////
// Callbacks                                        //
//////////////////////////////////////////////////////

/*

### posts.new.method

- PostsNewUserCheck
- PostsNewRateLimit
- PostsNewSubmittedPropertiesCheck

### posts.new.sync

- PostsNewDuplicateLinksCheck
- PostsNewRequiredPropertiesCheck

### posts.new.async

- PostsNewIncrementPostCount
- PostsNewUpvoteOwnPost
- PostsNewNotifications

### posts.edit.method

- PostsEditUserCheck
- PostsEditSubmittedPropertiesCheck

### posts.edit.sync

- PostsEditForceStickyToFalse

### posts.edit.async

- PostsEditSetPostedAt
- PostsEditRunPostApprovedCallbacks

### posts.approve.async

- PostsApprovedNotification

### users.remove.async

- UsersRemoveDeletePosts

*/

// ------------------------------------- posts.new.method -------------------------------- //

/**
 * @summary Check that the current user can post
 */
function PostsNewUserCheck (post, user) {
  // check that user can post
  if (!user || !Users.canDo(user, "posts.new"))
    throw new Meteor.Error(601, 'you_need_to_login_or_be_invited_to_post_new_stories');
  return post;
}
Telescope.callbacks.add("posts.new.method", PostsNewUserCheck);

/**
 * @summary Rate limiting
 */
function PostsNewRateLimit (post, user) {

  if(!Users.isAdmin(user)){

    var timeSinceLastPost = Users.timeSinceLast(user, Posts),
      numberOfPostsInPast24Hours = Users.numberOfItemsInPast24Hours(user, Posts),
      postInterval = Math.abs(parseInt(Telescope.settings.get('postInterval', 30))),
      maxPostsPer24Hours = Math.abs(parseInt(Telescope.settings.get('maxPostsPerDay', 30)));

    // check that user waits more than X seconds between posts
    if(timeSinceLastPost < postInterval)
      throw new Meteor.Error(604, 'please_wait'+(postInterval-timeSinceLastPost)+'seconds_before_posting_again');

    // check that the user doesn't post more than Y posts per day
    if(numberOfPostsInPast24Hours > maxPostsPer24Hours)
      throw new Meteor.Error(605, 'sorry_you_cannot_submit_more_than'+maxPostsPer24Hours+'posts_per_day');

  }

  return post;
}
Telescope.callbacks.add("posts.new.method", PostsNewRateLimit);

/**
 * @summary Properties
 */
function PostsNewSubmittedPropertiesCheck (post, user) {

  // admin-only properties
  // status
  // postedAt
  // userId
  // sticky (default to false)

  const schema = Posts.simpleSchema()._schema;

  // go over each schema field and throw an error if it's not editable
  _.keys(post).forEach(function (fieldName) {

    var field = schema[fieldName];
    if (!Users.canSubmitField (user, field)) {
      throw new Meteor.Error("disallowed_property", 'disallowed_property_detected' + ": " + fieldName);
    }

  });
  // note: not needed there anymore, this is already set in the next callback 'posts.new.sync' with other related properties (status, createdAt)
  // if no post status has been set, set it now
  // if (!post.status) {
  //   post.status = Posts.getDefaultStatus(user);
  // }

  // if no userId has been set, default to current user id
  if (!post.userId) {
    post.userId = user._id;
  }

  return post;
}
Telescope.callbacks.add("posts.new.method", PostsNewSubmittedPropertiesCheck);

// ------------------------------------- posts.new.sync -------------------------------- //

/**
 * @summary Check for duplicate links
 */
function PostsNewDuplicateLinksCheck (post, user) {
  if(!!post.url) {
    Posts.checkForSameUrl(post.url, user);
  }
  return post;
}
Telescope.callbacks.add("posts.new.sync", PostsNewDuplicateLinksCheck);

/**
 * @summary Check for necessary properties
 */
function PostsNewRequiredPropertiesCheck (post, user) {

  // initialize default properties
  const defaultProperties = {
    createdAt: new Date(),
    author: Users.getDisplayNameById(post.userId),
    status: Posts.getDefaultStatus(user)
  };

  post = _.extend(defaultProperties, post);

  // generate slug
  post.slug = Telescope.utils.slugify(post.title);

  // post is not pending and has been scheduled to be posted in the future by a moderator/admin
  if (post.status !== Posts.config.STATUS_PENDING && post.postedAt && post.postedAt > post.createdAt) {
    post.status = Posts.config.STATUS_SCHEDULED;
  }

  // if post is approved but doesn't have a postedAt date, give it a default date
  // note: pending posts get their postedAt date only once theyre approved
  if (Posts.isApproved(post) && !post.postedAt) {
    post.postedAt = new Date();
  }

  return post;
}
Telescope.callbacks.add("posts.new.sync", PostsNewRequiredPropertiesCheck);

/**
 * @summary Set the post's isFuture to true if necessary
 */
function PostsNewSetFuture (post, user) {
  post.isFuture = post.postedAt.getTime() > post.createdAt.getTime() + 1000; // round up to the second
  return post;
}
Telescope.callbacks.add("posts.new.sync", PostsNewSetFuture);

// ------------------------------------- posts.new.async -------------------------------- //

/**
 * @summary Increment the user's post count
 */
function PostsNewIncrementPostCount (post) {
  var userId = post.userId;
  Meteor.users.update({_id: userId}, {$inc: {"telescope.postCount": 1}});
}
Telescope.callbacks.add("posts.new.async", PostsNewIncrementPostCount);

/**
 * @summary Make users upvote their own new posts
 */
function PostsNewUpvoteOwnPost (post) {
  if (typeof Telescope.operateOnItem !== "undefined") {
    var postAuthor = Meteor.users.findOne(post.userId);
    Telescope.operateOnItem(Posts, post._id, postAuthor, "upvote");
  }
}
Telescope.callbacks.add("posts.new.async", PostsNewUpvoteOwnPost);

/**
 * @summary Add new post notification callback on post submit
 */
function PostsNewNotifications (post) {

  if (typeof Telescope.notifications !== "undefined") {

    var adminIds = _.pluck(Users.adminUsers({fields: {_id:1}}), '_id');
    var notifiedUserIds = _.pluck(Users.find({'telescope.notifications_posts': true}, {fields: {_id:1}}).fetch(), '_id');
    var notificationData = {
      post: _.pick(post, '_id', 'userId', 'title', 'url')
    };

    // remove post author ID from arrays
    adminIds = _.without(adminIds, post.userId);
    notifiedUserIds = _.without(notifiedUserIds, post.userId);

    if (post.status === Posts.config.STATUS_PENDING && !!adminIds.length) {
      // if post is pending, only notify admins
      Telescope.notifications.create(adminIds, 'newPendingPost', notificationData);
    } else if (!!notifiedUserIds.length) {
      // if post is approved, notify everybody
      Telescope.notifications.create(notifiedUserIds, 'newPost', notificationData);
    }
  }
}
Telescope.callbacks.add("posts.new.async", PostsNewNotifications);

// ------------------------------------- posts.edit.method -------------------------------- //

function PostsEditUserCheck (modifier, post, user) {
  // check that user can edit document
  if (!user || !Users.canEdit(user, post)) {
    throw new Meteor.Error(601, 'sorry_you_cannot_edit_this_post');
  }
  return modifier;
}
Telescope.callbacks.add("posts.edit.method", PostsEditUserCheck);

function PostsEditSubmittedPropertiesCheck (modifier, post, user) {
  const schema = Posts.simpleSchema()._schema;
  // go over each field and throw an error if it's not editable
  // loop over each operation ($set, $unset, etc.)
  _.each(modifier, function (operation) {
    // loop over each property being operated on
    _.keys(operation).forEach(function (fieldName) {

      var field = schema[fieldName];
      if (!Users.canEditField(user, field, post)) {
        throw new Meteor.Error("disallowed_property", 'disallowed_property_detected' + ": " + fieldName);
      }

    });
  });
  return modifier;
}
Telescope.callbacks.add("posts.edit.method", PostsEditSubmittedPropertiesCheck);

// ------------------------------------- posts.edit.sync -------------------------------- //

/**
 * @summary Force sticky to default to false when it's not specified
 * (simpleSchema's defaultValue does not work on edit, so do it manually in callback)
 */
function PostsEditForceStickyToFalse (modifier, post) {
  if (!modifier.$set.sticky) {
    if (modifier.$unset && modifier.$unset.sticky) {
      delete modifier.$unset.sticky;
    }
    modifier.$set.sticky = false;
  }
  return modifier;
}
Telescope.callbacks.add("posts.edit.sync", PostsEditForceStickyToFalse);

/**
 * @summary Set status
 */
function PostsEditSetIsFuture (modifier, post) {
  // if a post's postedAt date is in the future, set isFuture to true
  modifier.$set.isFuture = modifier.$set.postedAt.getTime() > new Date().getTime() + 1000;
  return modifier;
}
Telescope.callbacks.add("posts.edit.sync", PostsEditSetIsFuture);

/**
 * @summary Set postedAt date
 */
function PostsEditSetPostedAt (modifier, post) {
  // if post is approved but doesn't have a postedAt date, give it a default date
  // note: pending posts get their postedAt date only once theyre approved
  if (Posts.isApproved(post) && !post.postedAt) {
    modifier.$set.postedAt = new Date();
  }
  return modifier;
}
Telescope.callbacks.add("posts.edit.sync", PostsEditSetPostedAt);

// ------------------------------------- posts.edit.async -------------------------------- //

function PostsEditRunPostApprovedCallbacks (post, oldPost) {
  var now = new Date();

  if (Posts.isApproved(post) && !Posts.isApproved(oldPost)) {
    Telescope.callbacks.runAsync("posts.approve.async", post);
  }
}
Telescope.callbacks.add("posts.edit.async", PostsEditRunPostApprovedCallbacks);

// ------------------------------------- posts.approve.async -------------------------------- //

/**
 * @summary Add notification callback when a post is approved
 */
function PostsApprovedNotification (post) {
  if (typeof Telescope.notifications !== "undefined") {
    var notificationData = {
      post: _.pick(post, '_id', 'userId', 'title', 'url')
    };

    Telescope.notifications.create(post.userId, 'postApproved', notificationData);
  }
}
Telescope.callbacks.add("posts.approve.async", PostsApprovedNotification);

// ------------------------------------- users.remove.async -------------------------------- //

function UsersRemoveDeletePosts (user, options) {
  if (options.deletePosts) {
    var deletedPosts = Posts.remove({userId: userId});
  } else {
    // not sure if anything should be done in that scenario yet
    // Posts.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
  }
}
Telescope.callbacks.add("users.remove.async", UsersRemoveDeletePosts);
<commit_msg>test for postedAt (for pending posts)<commit_after>import Posts from './collection.js'
import marked from 'marked';
import Users from 'meteor/nova:users';

//////////////////////////////////////////////////////
// Collection Hooks                                 //
//////////////////////////////////////////////////////

/**
 * @summary Generate HTML body and excerpt from Markdown on post insert
 */
Posts.before.insert(function (userId, doc) {
  if(!!doc.body) {
    const htmlBody = Telescope.utils.sanitize(marked(doc.body));
    doc.htmlBody = htmlBody;
    doc.excerpt = Telescope.utils.trimHTML(htmlBody,30);
  }
});

/**
 * @summary Generate HTML body and excerpt from Markdown when post body is updated
 */
Posts.before.update(function (userId, doc, fieldNames, modifier) {
  // if body is being modified or $unset, update htmlBody too
  if (Meteor.isServer && modifier.$set && modifier.$set.body) {
    const htmlBody = Telescope.utils.sanitize(marked(modifier.$set.body));
    modifier.$set.htmlBody = htmlBody;
    modifier.$set.excerpt = Telescope.utils.trimHTML(htmlBody,30);
  }
  if (Meteor.isServer && modifier.$unset && (typeof modifier.$unset.body !== "undefined")) {
    modifier.$unset.htmlBody = "";
    modifier.$unset.excerpt = "";
  }
});

/**
 * @summary Generate slug when post title is updated
 */
Posts.before.update(function (userId, doc, fieldNames, modifier) {
  // if title is being modified, update slug too
  if (Meteor.isServer && modifier.$set && modifier.$set.title) {
    modifier.$set.slug = Telescope.utils.slugify(modifier.$set.title);
  }
});

/**
 * @summary Disallow $rename
 */
Posts.before.update(function (userId, doc, fieldNames, modifier) {
  if (!!modifier.$rename) {
    throw new Meteor.Error("illegal $rename operator detected!");
  }
});

//////////////////////////////////////////////////////
// Callbacks                                        //
//////////////////////////////////////////////////////

/*

### posts.new.method

- PostsNewUserCheck
- PostsNewRateLimit
- PostsNewSubmittedPropertiesCheck

### posts.new.sync

- PostsNewDuplicateLinksCheck
- PostsNewRequiredPropertiesCheck

### posts.new.async

- PostsNewIncrementPostCount
- PostsNewUpvoteOwnPost
- PostsNewNotifications

### posts.edit.method

- PostsEditUserCheck
- PostsEditSubmittedPropertiesCheck

### posts.edit.sync

- PostsEditForceStickyToFalse

### posts.edit.async

- PostsEditSetPostedAt
- PostsEditRunPostApprovedCallbacks

### posts.approve.async

- PostsApprovedNotification

### users.remove.async

- UsersRemoveDeletePosts

*/

// ------------------------------------- posts.new.method -------------------------------- //

/**
 * @summary Check that the current user can post
 */
function PostsNewUserCheck (post, user) {
  // check that user can post
  if (!user || !Users.canDo(user, "posts.new"))
    throw new Meteor.Error(601, 'you_need_to_login_or_be_invited_to_post_new_stories');
  return post;
}
Telescope.callbacks.add("posts.new.method", PostsNewUserCheck);

/**
 * @summary Rate limiting
 */
function PostsNewRateLimit (post, user) {

  if(!Users.isAdmin(user)){

    var timeSinceLastPost = Users.timeSinceLast(user, Posts),
      numberOfPostsInPast24Hours = Users.numberOfItemsInPast24Hours(user, Posts),
      postInterval = Math.abs(parseInt(Telescope.settings.get('postInterval', 30))),
      maxPostsPer24Hours = Math.abs(parseInt(Telescope.settings.get('maxPostsPerDay', 30)));

    // check that user waits more than X seconds between posts
    if(timeSinceLastPost < postInterval)
      throw new Meteor.Error(604, 'please_wait'+(postInterval-timeSinceLastPost)+'seconds_before_posting_again');

    // check that the user doesn't post more than Y posts per day
    if(numberOfPostsInPast24Hours > maxPostsPer24Hours)
      throw new Meteor.Error(605, 'sorry_you_cannot_submit_more_than'+maxPostsPer24Hours+'posts_per_day');

  }

  return post;
}
Telescope.callbacks.add("posts.new.method", PostsNewRateLimit);

/**
 * @summary Properties
 */
function PostsNewSubmittedPropertiesCheck (post, user) {

  // admin-only properties
  // status
  // postedAt
  // userId
  // sticky (default to false)

  const schema = Posts.simpleSchema()._schema;

  // go over each schema field and throw an error if it's not editable
  _.keys(post).forEach(function (fieldName) {

    var field = schema[fieldName];
    if (!Users.canSubmitField (user, field)) {
      throw new Meteor.Error("disallowed_property", 'disallowed_property_detected' + ": " + fieldName);
    }

  });
  // note: not needed there anymore, this is already set in the next callback 'posts.new.sync' with other related properties (status, createdAt)
  // if no post status has been set, set it now
  // if (!post.status) {
  //   post.status = Posts.getDefaultStatus(user);
  // }

  // if no userId has been set, default to current user id
  if (!post.userId) {
    post.userId = user._id;
  }

  return post;
}
Telescope.callbacks.add("posts.new.method", PostsNewSubmittedPropertiesCheck);

// ------------------------------------- posts.new.sync -------------------------------- //

/**
 * @summary Check for duplicate links
 */
function PostsNewDuplicateLinksCheck (post, user) {
  if(!!post.url) {
    Posts.checkForSameUrl(post.url, user);
  }
  return post;
}
Telescope.callbacks.add("posts.new.sync", PostsNewDuplicateLinksCheck);

/**
 * @summary Check for necessary properties
 */
function PostsNewRequiredPropertiesCheck (post, user) {

  // initialize default properties
  const defaultProperties = {
    createdAt: new Date(),
    author: Users.getDisplayNameById(post.userId),
    status: Posts.getDefaultStatus(user)
  };

  post = _.extend(defaultProperties, post);

  // generate slug
  post.slug = Telescope.utils.slugify(post.title);

  // post is not pending and has been scheduled to be posted in the future by a moderator/admin
  if (post.status !== Posts.config.STATUS_PENDING && post.postedAt && post.postedAt > post.createdAt) {
    post.status = Posts.config.STATUS_SCHEDULED;
  }

  // if post is approved but doesn't have a postedAt date, give it a default date
  // note: pending posts get their postedAt date only once theyre approved
  if (Posts.isApproved(post) && !post.postedAt) {
    post.postedAt = new Date();
  }

  return post;
}
Telescope.callbacks.add("posts.new.sync", PostsNewRequiredPropertiesCheck);

/**
 * @summary Set the post's isFuture to true if necessary
 */
function PostsNewSetFuture (post, user) {
  post.isFuture = post.postedAt && post.postedAt.getTime() > post.createdAt.getTime() + 1000; // round up to the second
  return post;
}
Telescope.callbacks.add("posts.new.sync", PostsNewSetFuture);

// ------------------------------------- posts.new.async -------------------------------- //

/**
 * @summary Increment the user's post count
 */
function PostsNewIncrementPostCount (post) {
  var userId = post.userId;
  Meteor.users.update({_id: userId}, {$inc: {"telescope.postCount": 1}});
}
Telescope.callbacks.add("posts.new.async", PostsNewIncrementPostCount);

/**
 * @summary Make users upvote their own new posts
 */
function PostsNewUpvoteOwnPost (post) {
  if (typeof Telescope.operateOnItem !== "undefined") {
    var postAuthor = Meteor.users.findOne(post.userId);
    Telescope.operateOnItem(Posts, post._id, postAuthor, "upvote");
  }
}
Telescope.callbacks.add("posts.new.async", PostsNewUpvoteOwnPost);

/**
 * @summary Add new post notification callback on post submit
 */
function PostsNewNotifications (post) {

  if (typeof Telescope.notifications !== "undefined") {

    var adminIds = _.pluck(Users.adminUsers({fields: {_id:1}}), '_id');
    var notifiedUserIds = _.pluck(Users.find({'telescope.notifications_posts': true}, {fields: {_id:1}}).fetch(), '_id');
    var notificationData = {
      post: _.pick(post, '_id', 'userId', 'title', 'url')
    };

    // remove post author ID from arrays
    adminIds = _.without(adminIds, post.userId);
    notifiedUserIds = _.without(notifiedUserIds, post.userId);

    if (post.status === Posts.config.STATUS_PENDING && !!adminIds.length) {
      // if post is pending, only notify admins
      Telescope.notifications.create(adminIds, 'newPendingPost', notificationData);
    } else if (!!notifiedUserIds.length) {
      // if post is approved, notify everybody
      Telescope.notifications.create(notifiedUserIds, 'newPost', notificationData);
    }
  }
}
Telescope.callbacks.add("posts.new.async", PostsNewNotifications);

// ------------------------------------- posts.edit.method -------------------------------- //

function PostsEditUserCheck (modifier, post, user) {
  // check that user can edit document
  if (!user || !Users.canEdit(user, post)) {
    throw new Meteor.Error(601, 'sorry_you_cannot_edit_this_post');
  }
  return modifier;
}
Telescope.callbacks.add("posts.edit.method", PostsEditUserCheck);

function PostsEditSubmittedPropertiesCheck (modifier, post, user) {
  const schema = Posts.simpleSchema()._schema;
  // go over each field and throw an error if it's not editable
  // loop over each operation ($set, $unset, etc.)
  _.each(modifier, function (operation) {
    // loop over each property being operated on
    _.keys(operation).forEach(function (fieldName) {

      var field = schema[fieldName];
      if (!Users.canEditField(user, field, post)) {
        throw new Meteor.Error("disallowed_property", 'disallowed_property_detected' + ": " + fieldName);
      }

    });
  });
  return modifier;
}
Telescope.callbacks.add("posts.edit.method", PostsEditSubmittedPropertiesCheck);

// ------------------------------------- posts.edit.sync -------------------------------- //

/**
 * @summary Force sticky to default to false when it's not specified
 * (simpleSchema's defaultValue does not work on edit, so do it manually in callback)
 */
function PostsEditForceStickyToFalse (modifier, post) {
  if (!modifier.$set.sticky) {
    if (modifier.$unset && modifier.$unset.sticky) {
      delete modifier.$unset.sticky;
    }
    modifier.$set.sticky = false;
  }
  return modifier;
}
Telescope.callbacks.add("posts.edit.sync", PostsEditForceStickyToFalse);

/**
 * @summary Set status
 */
function PostsEditSetIsFuture (modifier, post) {
  // if a post's postedAt date is in the future, set isFuture to true
  modifier.$set.isFuture = modifier.$set.postedAt && modifier.$set.postedAt.getTime() > new Date().getTime() + 1000;
  return modifier;
}
Telescope.callbacks.add("posts.edit.sync", PostsEditSetIsFuture);

/**
 * @summary Set postedAt date
 */
function PostsEditSetPostedAt (modifier, post) {
  // if post is approved but doesn't have a postedAt date, give it a default date
  // note: pending posts get their postedAt date only once theyre approved
  if (Posts.isApproved(post) && !post.postedAt) {
    modifier.$set.postedAt = new Date();
  }
  return modifier;
}
Telescope.callbacks.add("posts.edit.sync", PostsEditSetPostedAt);

// ------------------------------------- posts.edit.async -------------------------------- //

function PostsEditRunPostApprovedCallbacks (post, oldPost) {
  var now = new Date();

  if (Posts.isApproved(post) && !Posts.isApproved(oldPost)) {
    Telescope.callbacks.runAsync("posts.approve.async", post);
  }
}
Telescope.callbacks.add("posts.edit.async", PostsEditRunPostApprovedCallbacks);

// ------------------------------------- posts.approve.async -------------------------------- //

/**
 * @summary Add notification callback when a post is approved
 */
function PostsApprovedNotification (post) {
  if (typeof Telescope.notifications !== "undefined") {
    var notificationData = {
      post: _.pick(post, '_id', 'userId', 'title', 'url')
    };

    Telescope.notifications.create(post.userId, 'postApproved', notificationData);
  }
}
Telescope.callbacks.add("posts.approve.async", PostsApprovedNotification);

// ------------------------------------- users.remove.async -------------------------------- //

function UsersRemoveDeletePosts (user, options) {
  if (options.deletePosts) {
    var deletedPosts = Posts.remove({userId: userId});
  } else {
    // not sure if anything should be done in that scenario yet
    // Posts.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
  }
}
Telescope.callbacks.add("users.remove.async", UsersRemoveDeletePosts);
<|endoftext|>


<commit_before>/*
 * file             : codenicely.js
 * description      : js part of codenicely project. codenicely intents to play ambient background music for programmers to get better concentration while doing their works
 * dependencies     : jquery3
 * author           : mobihack (mobihack@github), vinay (feat7@github)
 * license          : check license.txt
 * */

//list of audio tracks
var audioList=['piano','rain','birds','fire','bells','people','cricket'];

function soundCheck(id) {

    /*
    * name      : soundCheck()
    * function  : Change volume of specific audio tracks.
    * input     : id - id of audio track whose sound is being changed
    * */

    $('#'+id+'Audio')[0].volume = $('#'+id+'AudioVolume')[0].value/100;
}

function toggleMainAudio() {

    /*
     * name      : toggleMainAudio()
     * function  : Turn ON or OFF all the audio tracks aka. Main Toggle.
     * input     : none
     * */

        var mainIcon=$('#defaultPlay');

        mainIcon.animateCss('fadeIn');

        var flag; //to make sure that all audio are paused/played correctly

        if(mainIcon.hasClass('fa-pause')){

            mainIcon.addClass('fa-play').removeClass('fa-pause');
            flag='paused';

        }
        else{

            flag='play';
            mainIcon.removeClass('fa-play').addClass('fa-pause');

        }

        audioList.forEach(function (id) {

            if (flag=='play')
                if($('#' + id + 'Audio')[0].paused) {
                    toggleSubAudio(id);
                }
            if (flag=='paused')
                if(!$('#' + id + 'Audio')[0].paused) {
                    toggleSubAudio(id);
                }

        });
}

function toggleSubAudio(id) {

    /*
     * name      : toggleSubAudio()
     * function  : Turn ON or OFF specific audio tracks.
     * input     : id - id of audio track which is being toggled
     * */

    var audio = document.getElementById(id+'Audio');

    /* Animations */
    $('#'+id+'Play').animateCss('fadeIn');
    $('#'+id+'AudioPlay').animateCss('fadeIn');

    if(audio.paused) {
        $('#'+id+'AudioPlay').html('Playing Now');
        $('#'+id+'Play').addClass('fa-pause').removeClass('fa-play-circle');
        $('#'+id+'AudioVolume').removeClass('hidden');
        $('#'+id+'AudioVolume').animateCss('slideInDown');
        audio.play();
        audio.loop = true;
    } else {
        $('#'+id+'AudioPlay').html('Paused');
        $('#'+id+'Play').addClass('fa-play-circle').removeClass('fa-pause');
        $('#'+id+'AudioVolume').addClass('hidden');
        $('#'+id+'AudioVolume').animateCss('fadeOut');
        audio.pause();
    }
}

function toggleDarkMode() {

    /*
     * name      : toggleDarkMode()
     * function  : Turn ON or OFF dark mode of site.
     * input     : none
     * */

    var mainSection=$('#mainSection');
    var button=$('#dark-mode-button');
    var icon=$('#icon-dark-mode');
    var optionSection=$('#options');
    var footerSection=$('#footer');

    mainSection.animateCss('tada');

    if(mainSection.hasClass('is-info')){
        mainSection.addClass('is-dark').removeClass('is-info');
        optionSection.addClass('dark-mode');
        footerSection.addClass('dark-mode').removeClass('is-primary');
        button.addClass('is-active');
        icon.addClass('fa-toggle-on').removeClass('fa-toggle-off');

    }
    else{
        mainSection.removeClass('is-dark').addClass('is-info');
        footerSection.removeClass('dark-mode').addClass('is-primary');
        optionSection.removeClass('dark-mode');
        button.removeClass('is-active');
        icon.removeClass('fa-toggle-on').addClass('fa-toggle-off');
    }
}

function toggleModal(name) {

    /*
     * name      : toggleModal()
     * function  : Simple function to toggle a modal box
     * input     : name - name of modal box
     * */

    var modal=$('#modal-'+name);
    if(modal.hasClass('is-active')) {
        modal.removeClass('is-active');
    }
    else{
        modal.addClass('is-active');
    }
}

$('.codenicely-bookmark-me').click(function(e) {

    /*
     * function  : Bookmark
     * input     : name - name of modal box
     * credits   : http://stackoverflow.com/questions/37026847/add-bookmark-this-page-button-2016
     * */

    e.preventDefault();
    var bookmarkURL = window.location.href;
    var bookmarkTitle = document.title;

    if ('addToHomescreen' in window && window.addToHomescreen.isCompatible) {
        // Mobile browsers
        addToHomescreen({ autostart: false, startDelay: 0 }).show(true);
    } else if (window.sidebar && window.sidebar.addPanel) {
        // Firefox version < 23
        window.sidebar.addPanel(bookmarkTitle, bookmarkURL, '');
    } else if ((window.sidebar && /Firefox/i.test(navigator.userAgent)) || (window.opera && window.print)) {
        // Firefox version >= 23 and Opera Hotlist
        $(this).attr({
            href: bookmarkURL,
            title: bookmarkTitle,
            rel: 'sidebar'
        }).off(e);
        return true;
    } else if (window.external && ('AddFavorite' in window.external)) {
        // IE Favorite
        window.external.AddFavorite(bookmarkURL, bookmarkTitle);
    } else {
        // Other browsers (mainly WebKit - Chrome/Safari)
        alert('Pease press ' + (/Mac/i.test(navigator.userAgent) ? 'CMD' : 'Strg') + ' + D to add this page to your favorites.');
    }

    return false;
});

$(function() {

    /*
     * function     : smooth scroll when clicking id href links
     * credits      : https://css-tricks.com/snippets/jquery/smooth-scrolling/
     * */

  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: $(target).offset().top
        }, 1000);
        return false;
      }
    }
  });
});

$.fn.extend(

    /*
     * function     : animateCSS - Extended Function -
     * input        : name - name of modal box
     * credits      : https://daneden.github.io/animate.css/
     * */

    { animateCss: function (animationName) {
        var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
        this.addClass('animated ' + animationName).one(animationEnd,
            function() { $(this).removeClass('animated ' + animationName); });
    }
    });
<commit_msg>Update script.js<commit_after>/*
 * file             : codenicely.js
 * description      : js part of codenicely project. codenicely intents to play ambient background music for programmers to get better concentration while doing their works
 * dependencies     : jquery3
 * author           : mobihack (mobihack@github), vinay (feat7@github)
 * license          : check license.txt
 * */

//list of audio tracks
var audioList=['piano','rain','birds','fire','bells','people','cricket'];

function soundCheck(id) {

    /*
    * name      : soundCheck()
    * function  : Change volume of specific audio tracks.
    * input     : id - id of audio track whose sound is being changed
    * */

    $('#'+id+'Audio')[0].volume = $('#'+id+'AudioVolume')[0].value/100;
}

function toggleMainAudio() {

    /*
     * name      : toggleMainAudio()
     * function  : Turn ON or OFF all the audio tracks aka. Main Toggle.
     * input     : none
     * */

        var mainIcon=$('#defaultPlay');

        mainIcon.animateCss('fadeIn');

        var flag; //to make sure that all audio are paused/played correctly

        if(mainIcon.hasClass('fa-pause')){

            mainIcon.addClass('fa-play').removeClass('fa-pause');
            flag='paused';

        }
        else{

            flag='play';
            mainIcon.removeClass('fa-play').addClass('fa-pause');

        }

        audioList.forEach(function (id) {

            if (flag=='play')
                if($('#' + id + 'Audio')[0].paused) {
                    toggleSubAudio(id);
                }
            if (flag=='paused')
                if(!$('#' + id + 'Audio')[0].paused) {
                    toggleSubAudio(id);
                }

        });
}

function toggleSubAudio(id) {

    /*
     * name      : toggleSubAudio()
     * function  : Turn ON or OFF specific audio tracks.
     * input     : id - id of audio track which is being toggled
     * */

    var audio = document.getElementById(id+'Audio');

    /* Animations */
    $('#'+id+'Play').animateCss('fadeIn');
    $('#'+id+'AudioPlay').animateCss('fadeIn');

    if(audio.paused) {
        $('#'+id+'AudioPlay').html('Playing Now');
        $('#'+id+'Play').addClass('fa-pause').removeClass('fa-play-circle');
        $('#'+id+'AudioVolume').removeClass('hidden');
        $('#'+id+'AudioVolume').animateCss('slideInDown');
        audio.play();
        audio.loop = true;
    } else {
        $('#'+id+'AudioPlay').html('Paused');
        $('#'+id+'Play').addClass('fa-play-circle').removeClass('fa-pause');
        $('#'+id+'AudioVolume').addClass('hidden');
        $('#'+id+'AudioVolume').animateCss('fadeOut');
        audio.pause();
    }
}

function toggleDarkMode() {

    /*
     * name      : toggleDarkMode()
     * function  : Turn ON or OFF dark mode of site.
     * input     : none
     * */

    var mainSection=$('#mainSection');
    var button=$('#dark-mode-button');
    var icon=$('#icon-dark-mode');
    var optionSection=$('#options');
    var footerSection=$('#footer');

    mainSection.animateCss('tada');

    if(mainSection.hasClass('is-info')){
        mainSection.addClass('is-dark').removeClass('is-info');
        optionSection.addClass('dark-mode');
        footerSection.addClass('dark-mode').removeClass('is-primary');
        button.addClass('is-active');
        icon.addClass('fa-toggle-on').removeClass('fa-toggle-off');

    }
    else{
        mainSection.removeClass('is-dark').addClass('is-info');
        footerSection.removeClass('dark-mode').addClass('is-primary');
        optionSection.removeClass('dark-mode');
        button.removeClass('is-active');
        icon.removeClass('fa-toggle-on').addClass('fa-toggle-off');
    }
}

function toggleModal(name) {

    /*
     * name      : toggleModal()
     * function  : Simple function to toggle a modal box
     * input     : name - name of modal box
     * */

    var modal=$('#modal-'+name);
    if(modal.hasClass('is-active')) {
        modal.removeClass('is-active');
    }
    else{
        modal.addClass('is-active');
    }
}

$('.codenicely-bookmark-me').click(function(e) {

    /*
     * function  : Bookmark
     * input     : name - name of modal box
     * credits   : http://stackoverflow.com/questions/37026847/add-bookmark-this-page-button-2016
     * */

    e.preventDefault();
    var bookmarkURL = window.location.href;
    var bookmarkTitle = document.title;

    if ('addToHomescreen' in window && window.addToHomescreen.isCompatible) {
        // Mobile browsers
        addToHomescreen({ autostart: false, startDelay: 0 }).show(true);
    } else if (window.sidebar && window.sidebar.addPanel) {
        // Firefox version < 23
        window.sidebar.addPanel(bookmarkTitle, bookmarkURL, '');
    } else if ((window.sidebar && /Firefox/i.test(navigator.userAgent)) || (window.opera && window.print)) {
        // Firefox version >= 23 and Opera Hotlist
        $(this).attr({
            href: bookmarkURL,
            title: bookmarkTitle,
            rel: 'sidebar'
        }).off(e);
        return true;
    } else if (window.external && ('AddFavorite' in window.external)) {
        // IE Favorite
        window.external.AddFavorite(bookmarkURL, bookmarkTitle);
    } else {
        // Other browsers (mainly WebKit - Chrome/Safari)
        alert('Pease press ' + (/Mac/i.test(navigator.userAgent) ? 'CMD' : 'Strg') + ' + D to add this page to your favorites.');
    }

    return false;
});

$(function() {

    /*
     * function     : smooth scroll when clicking id href links
     * credits      : https://css-tricks.com/snippets/jquery/smooth-scrolling/
     * */

  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});

$.fn.extend(

    /*
     * function     : animateCSS - Extended Function -
     * input        : name - name of modal box
     * credits      : https://daneden.github.io/animate.css/
     * */

    { animateCss: function (animationName) {
        var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
        this.addClass('animated ' + animationName).one(animationEnd,
            function() { $(this).removeClass('animated ' + animationName); });
    }
    });
<|endoftext|>


<commit_before>describe('Plane', function() {
  'use strict';

  var plane;

  beforeEach(function() {
    plane = new Plane();
  });

  it('should be flying when created', function() {
    expect(plane.isFlying).toBeTruthy();
  });

  it('should be able to land', function() {
    plane.land();
    expect(plane.isFlying).toBeFalsy();
  });

  it('should be able to take off', function() {
    plane.takeoff();
    expect(plane.isFlying).toBeTruthy();
  });

});

  // it("should be able to play a Song", function() {
  //   player.play(song);
  //   expect(player.currentlyPlayingSong).toEqual(song);
  //
  //   //demonstrates use of custom matcher
  //   expect(player).toBePlaying(song);
  // });
  //
  // describe("when song has been paused", function() {
  //   beforeEach(function() {
  //     player.play(song);
  //     player.pause();
  //   });
  //
  //   it("should indicate that the song is currently paused", function() {
  //     expect(player.isPlaying).toBeFalsy();
  //
  //     // demonstrates use of 'not' with a custom matcher
  //     expect(player).not.toBePlaying(song);
  //   });
  //
  //   it("should be possible to resume", function() {
  //     player.resume();
  //     expect(player.isPlaying).toBeTruthy();
  //     expect(player.currentlyPlayingSong).toEqual(song);
  //   });
  // });
  //
  // // demonstrates use of spies to intercept and test method calls
  // it("tells the current song if the user has made it a favorite", function() {
  //   spyOn(song, 'persistFavoriteStatus');
  //
  //   player.play(song);
  //   player.makeFavorite();
  //
  //   expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true);
  // });
  //
  // //demonstrates use of expected exceptions
  // describe("#resume", function() {
  //   it("should throw an exception if song is already playing", function() {
  //     player.play(song);
  //
  //     expect(function() {
  //       player.resume();
  //     }).toThrowError("song is already playing");
  //   });
  // });
<commit_msg>removes boilerplate tests<commit_after>describe('Plane', function() {
  'use strict';

  var plane;

  beforeEach(function() {
    plane = new Plane();
  });

  it('should be flying when created', function() {
    expect(plane.isFlying).toBeTruthy();
  });

  it('should be able to land', function() {
    plane.land();
    expect(plane.isFlying).toBeFalsy();
  });

  it('should be able to take off', function() {
    plane.takeoff();
    expect(plane.isFlying).toBeTruthy();
  });

});
<|endoftext|>


<commit_before>module.exports = {
  router: {
    middleware: 'i18n'
  },
  build: {
    vendor: ['axios']
  },
  plugins: ['~plugins/i18n']
}
<commit_msg>Update color<commit_after>module.exports = {
  loading: {
    color: 'cyan'
  },
  router: {
    middleware: 'i18n'
  },
  build: {
    vendor: ['axios']
  },
  plugins: ['~plugins/i18n']
}
<|endoftext|>


<commit_before>var chalk = require("chalk");
var es = require("event-stream");
var messageBuilder = require("./messageBuilder");

function warningsStreamFactory() {
  return es.map(function(chunk, callback) {
    logWarningsAndErrors(chunk);
    callback(null, chunk);
  });
}

function logWarningsAndErrors(chunk) {
  var color = (
    chunk.level === 2 ? chalk.yellow :
    chunk.level === 3 ? chalk.red : null
  );

  if (color) {
    var msgs = messageBuilder(chunk);

    if (msgs.length) {
      console.log(color(">> [" + chunk.name + "]"));
      msgs.forEach(function(d) { console.log("  " + d); });
      console.log("");
    }
  }
}

warningsStreamFactory.logWarningsAndErrors = logWarningsAndErrors;
module.exports = warningsStreamFactory;
<commit_msg>Only print the name of the chunk if one is available<commit_after>var chalk = require("chalk");
var es = require("event-stream");
var messageBuilder = require("./messageBuilder");

function warningsStreamFactory() {
  return es.map(function(chunk, callback) {
    logWarningsAndErrors(chunk);
    callback(null, chunk);
  });
}

function logWarningsAndErrors(chunk) {
  var color = (
    chunk.level === 2 ? chalk.yellow :
    chunk.level === 3 ? chalk.red : null
  );

  if (color) {
    var msgs = messageBuilder(chunk);

    if (msgs.length) {
      if (chunk.name) {
        console.log(color(">> [" + chunk.name + "]"));
      }

      msgs.forEach(function(d) { console.log("  " + d); });
      console.log("");
    }
  }
}

warningsStreamFactory.logWarningsAndErrors = logWarningsAndErrors;
module.exports = warningsStreamFactory;
<|endoftext|>