<commit_before>var gulp = require('gulp');
var watch = require('gulp-watch');
var gutil = require('gulp-util');
var taskListing = require('gulp-task-listing');
var path = require('canonical-path');
var del = require('del');
var _ = require('lodash');
var Git = require("nodegit");
var argv = require('yargs').argv;
var Q = require("q");
// delPromise is a 'promise' version of del
var delPromise =  Q.denodeify(del);
var Minimatch = require("minimatch").Minimatch;
var Dgeni = require('dgeni');
var fsExtra = require('fs-extra');
var fs = fsExtra;
var exec = require('child_process').exec;
var execPromise = Q.denodeify(exec);
var prompt = require('prompt');

// TODO:
//  1. Think about using runSequence
//  2. Think about using spawn instead of exec in case of long error messages.

var docShredder = require('./public/doc-shredder/doc-shredder');

var _devguideShredOptions =  {
  examplesDir: './public/docs/_examples',
  fragmentsDir: './public/docs/_fragments'
};

var _apiShredOptions =  {
  examplesDir: '../angular/modules/angular2/examples',
  fragmentsDir: './public/docs/_fragments/_api'
};

var _excludePatterns = ['**/node_modules/**', '**/typings/**', '**/packages/**'];

var _excludeMatchers = _excludePatterns.map(function(excludePattern){
  return new Minimatch(excludePattern)
});

gulp.task('help', taskListing.withFilters(function(taskName) {
  var isSubTask = taskName.substr(0,1) == "_";
  return isSubTask;
}, function(taskName) {
  var shouldRemove = taskName === 'default';
  return shouldRemove;
}));

gulp.task('serve-and-sync', ['build-docs'], function (cb) {

  // execCommands(['harp server'], {}, cb);
  execCommands(['npm run harp -- server .'], {}, cb);

  var browserSync = require('browser-sync').create();
  browserSync.init({
    proxy: 'localhost:9000',
    files: ["public/docs/**/*/**/*" ],
    logFileChanges: true,
    reloadDelay: 500
  });

  devGuideExamplesWatch(_devguideShredOptions, function() {
    browserSync.reload();
  });

  apiSourceWatch(function() {
    browserSync.reload();
  });

});

gulp.task('build-and-serve', ['build-docs'], function (cb) {
  execCommands(['npm run harp -- server .'], {}, cb);

  var browserSync = require('browser-sync').create();
  browserSync.init({
    proxy: 'localhost:9000',
    files: ["public/docs/**/*/**/*" ],
    logFileChanges: true,
    reloadDelay: 500
  });
});

gulp.task('build-docs', ['_shred-devguide-examples', 'build-api-docs'], function() {
  return buildShredMaps(true);
});

gulp.task('build-devguide-docs', ['_shred-devguide-examples'], function() {
  return buildShredMaps(true);
});

gulp.task('build-api-docs', ['_shred-api-examples'], function() {
  if (!fs.existsSync('../angular')) {
    throw new Error('build-api-docs task requires the angular2 repo to be at ' + path.resolve('../angular'));
  }
  return buildApiDocs();
});

gulp.task('_shred-devguide-examples', ['_shred-clean-devguide'], function() {
  return docShredder.shred( _devguideShredOptions);
});

gulp.task('_shred-clean-devguide', function(cb) {
  var cleanPath = path.join(_devguideShredOptions.fragmentsDir, '**/*.*')
  return delPromise([ cleanPath, '!**/*.ovr.*', '!**/_api/**']);
});

gulp.task('_shred-api-examples', ['_shred-clean-api'], function() {
  return docShredder.shred( _apiShredOptions);
});

gulp.task('_shred-clean-api', function(cb) {
  var cleanPath = path.join(_apiShredOptions.fragmentsDir, '**/*.*')
  return delPromise([ cleanPath, '!**/*.ovr.*' ]);
});

gulp.task('_build-shred-maps', function() {
  return build-shred-maps(true);
});

gulp.task('git-changed-examples', ['_shred-devguide-examples'], function(){
  var after, sha, messageSuffix;
  if (argv.after) {
    try {
      after = new Date(argv.after);
      messageSuffix = ' after: ' + argv.after;
    } catch (e) {
      throw argv.after + " is not a valid date.";
    }
  } else if (argv.sha) {
    sha = argv.sha;
    messageSuffix = ' on commit: ' + (argv.sha.length ? argv.sha : '[last commit]');
  } else {
    console.log('git-changed-examples may be called with either an "--sha" argument like this:');
    console.log('   gulp git-changed-examples --sha=4d2ac96fa247306ddd2d4c4e0c8dee2223502eb2');
    console.log('or with an "--after" argument like this')
    console.log('   gulp git-changed-examples --after="August 1, 2015"');
    return;
  }
  var jadeShredMap;
  return buildShredMaps(false).then(function(docs) {
    jadeShredMap = docs[0];
    if (after) {
      return getChangedExamplesAfter(after);
    } else if (sha) {
      return getChangedExamples(sha);
    } else {
      console.log('git-changed-examples may be called with either an "--sha" argument like this:');
      console.log('   gulp git-changed-examples --sha=4d2ac96fa247306ddd2d4c4e0c8dee2223502eb2');
      console.log('or with an "--after" argument like this')
      console.log('   gulp git-changed-examples --after="August 1, 2015"');
    }
  }).then(function(examplePaths) {
    examplePaths = filterOutExcludedPatterns(examplePaths, _excludeMatchers);
    console.log('\nExamples changed ' + messageSuffix);
    console.log(examplePaths)
    console.log("\nJade files affected by changed example files " + messageSuffix);
    var jadeExampleMap = jadeShredMapToJadeExampleMap(jadeShredMap, examplePaths);
    console.log(JSON.stringify(jadeExampleMap, null, "  "));
    console.log("-----");
  }).catch(function(err) {
    console.log(err);
    throw err;
  });
});

gulp.task('check-deploy', ['build-docs'], function() {
  console.log('running harp compile...');
  return execPromise('npm run harp -- compile . ./www', {}).then(function() {
    execPromise('npm run live-server ./www');
    return askDeploy();
  }).then(function(shouldDeploy) {
    if (shouldDeploy) {
      console.log('deploying...');
      return execPromise('firebase deploy');
    } else {
      return ['Not deploying'];
    }
  }).then(function(s) {
    console.log(s.join(''));
  });
});

// returns a promise;
function askDeploy() {

  prompt.start();
  var schema = {
    name: 'shouldDeploy',
    description: 'Deploy to Firebase? (y/n): ',
    type: 'string',
    pattern: /Y|N|y|n/,
    message: "Respond with either a 'y' or 'n'",
    required: true
  }
  var getPromise = Q.denodeify(prompt.get);
  return getPromise([schema]).then(function(result) {
    return result.shouldDeploy.toLowerCase() === 'y';
  });
}

gulp.task('test-api-builder', function (cb) {
  execCommands(['npm run test-api-builder'], {}, cb);
});

function filterOutExcludedPatterns(fileNames, excludeMatchers) {
  return fileNames.filter(function(fileName) {
    return !excludeMatchers.some(function(excludeMatcher) {
      return excludeMatcher.match(fileName);
    });
  });
}

function apiSourceWatch(postShredAction) {
  var srcPattern = ['../angular/modules/angular2/src/**/*.*'];
  watch(srcPattern, function (event, done) {
    console.log('Event type: ' + event.event); // added, changed, or deleted
    console.log('Event path: ' + event.path); // The path of the modified file
    // need to run just build
    buildApiDocs().then(done);
  });
  var examplesPattern = ['../angular/modules/angular2/examples/**/*.*'];
  watch(examplesPattern, function (event, done) {
    console.log('Event type: ' + event.event); // added, changed, or deleted
    console.log('Event path: ' + event.path); // The path of the modified file
    // need to run shredder
    var cleanPath = path.join(_apiShredOptions.fragmentsDir, '**/*.*');
    return delPromise([ cleanPath, '!**/*.ovr.*' ]).then(function() {
      return docShredder.shred(_apiShredOptions);
    }).then(function() {
      postShredAction && postShredAction();
    });
  });

}

function buildApiDocs() {
  try {
    var dgeni = new Dgeni([require('./public/api-builder/angular.io-package')]);
    return dgeni.generate().then(function() {
      return gulp.src('./public/docs/js/latest/api/**/*.*')
        .pipe(gulp.dest('./public/docs/ts/latest/api'));
    })
  } catch(err) {
    console.log(err);
    console.log(err.stack);
    throw err;
  }
}

function devGuideExamplesWatch(shredOptions, postShredAction) {
  var pattern = path.join(shredOptions.examplesDir, "**/*.*");
  watch([pattern], function (event, done) {
    console.log('Event type: ' + event.event); // added, changed, or deleted
    console.log('Event path: ' + event.path); // The path of the modified file
    docShredder.shredSingleDir(shredOptions, event.path).then(function () {
      postShredAction && postShredAction();
    });
  });
}

function buildShredMaps(shouldWrite) {
  var options = {
    devguideExamplesDir: _devguideShredOptions.examplesDir,
    apiExamplesDir: _apiShredOptions.examplesDir,
    fragmentsDir: _devguideShredOptions.fragmentsDir,
    jadeDir: './public/docs',
    outputDir: './public/docs',
    writeFilesEnabled: shouldWrite
  };
  return docShredder.buildShredMap(options).then(function(docs) {
    return docs;
  });
}

// returns a promise containing filePaths with any changed or added examples;
function getChangedExamples(sha) {
  var examplesPath = _devguideShredOptions.examplesDir;
  var relativePath = path.relative(process.cwd(), examplesPath);
  return Git.Repository.open(".").then(function(repo) {
    if (sha.length) {
      return repo.getCommit(sha);
    } else {
      return repo.getHeadCommit();
    }
  }).then(function(commit) {
    return getChangedExamplesForCommit(commit, relativePath);
  }).catch(function(err) {

  });
}

function getChangedExamplesAfter(date, relativePath) {
  var examplesPath = _devguideShredOptions.examplesDir;
  var relativePath = path.relative(process.cwd(), examplesPath);
  return Git.Repository.open(".").then(function(repo) {
    return repo.getHeadCommit();
  }).then(function(commit) {
    var repo = commit.owner();
    var revWalker = repo.createRevWalk();
    revWalker.sorting(Git.Revwalk.SORT.TIME);
    revWalker.push(commit.id());
    return revWalker.getCommitsUntil(function (commit) {
      return commit.date().getTime() > date.getTime();
    });
  }).then(function(commits) {
    return Q.all(commits.map(function(commit) {
      return getChangedExamplesForCommit(commit, relativePath);
    }));
  }).then(function(arrayOfPaths) {
    var pathMap = {};
    arrayOfPaths.forEach(function(paths) {
      paths.forEach(function(path) {
        pathMap[path] = true;
      });
    });
    var uniqPaths = _.keys(pathMap);
    return uniqPaths;
  }).catch(function(err) {
    var x = err;
  });

}

function getChangedExamplesForCommit(commit, relativePath) {
  return commit.getDiff().then(function(diffList) {
    var filePaths = [];
    diffList.forEach(function (diff) {
      diff.patches().forEach(function (patch) {
        if (patch.isAdded() || patch.isModified) {
          var filePath = path.normalize(patch.newFile().path());
          var isExample = filePath.indexOf(relativePath) >= 0;
          // console.log(filePath + " isExample: " + isExample);
          if (isExample) {
            filePaths.push(filePath);
          }
        }
      });
    });
    return filePaths;
  });
}

function jadeShredMapToJadeExampleMap(jadeShredMap, examplePaths) {
  // remove dups in examplePaths
  var exampleSet = {};
  examplePaths.forEach(function(examplePath) {
    exampleSet[examplePath] = examplePath;
  });
  var basePath = path.resolve(".");
  var jadeToFragMap = jadeShredMap.jadeToFragMap;
  var jadeExampleMap = {};
  for (var jadePath in jadeToFragMap) {
    var relativeJadePath = path.relative(basePath, jadePath);
    var vals = jadeToFragMap[jadePath];
    vals.forEach(function(val) {
      var relativeExamplePath = path.relative(basePath, val.examplePath);
      if (exampleSet[relativeExamplePath] != null) {
        addKeyValue(jadeExampleMap, relativeJadePath, relativeExamplePath);
      }
    });
  }
  return jadeExampleMap;
}

function jadeShredMapToExampleJadeMap(jadeShredMap) {

  var jadeToFragMap = jadeShredMap.jadeToFragMap;
  var exampleJadeMap = {};
  for (var jadePath in jadeToFragMap) {
    var vals = jadeToFragMap[jadePath];
    vals.forEach(function(val) {
      var examplePath = val.examplePath;
      addKeyValue(exampleJadeMap, examplePath, jadePath);
    });
  }
  return exampleJadeMap;
}

function addKeyValue(map, key, value) {
  var vals = map[key];
  if (vals) {
    if (vals.indexOf(value) == -1) {
      vals.push(value);
    }
  } else {
    map[key] = [value];
  }
}

// Synchronously execute a chain of commands.
// cmds: an array of commands
// options: { shouldLog: true,  shouldThrow: true }
// cb: function(err, stdout, stderr)
function execCommands(cmds, options, cb) {
  options = options || {};
  options.shouldThrow = options.shouldThrow == null ? true : options.shouldThrow;
  options.shouldLog = options.shouldLog == null ? true : options.shouldLog;
  if (!cmds || cmds.length == 0) cb(null, null, null);
  var exec = require('child_process').exec;  // just to make it more portable.
  exec(cmds[0], options, function(err, stdout, stderr) {
    if (err == null) {
      if (options.shouldLog) {
        gutil.log('cmd: ' + cmds[0]);
        gutil.log('stdout: ' + stdout);
      }
      if (cmds.length == 1) {
        cb(err, stdout, stderr);
      } else {
        execCommands(cmds.slice(1), options, cb);
      }
    } else {
      if (options.shouldLog) {
        gutil.log('exec error on cmd: ' + cmds[0]);
        gutil.log('exec error: ' + err);
        if (stdout) gutil.log('stdout: ' + stdout);
        if (stderr) gutil.log('stderr: ' + stderr);
      }
      if (err && options.shouldThrow) throw err;
      cb(err, stdout, stderr);
    }
  });
}

gulp.task('default', ['help']);<commit_msg>reduce nodegit dependency to just those tasks that need it.<commit_after>var gulp = require('gulp');
var watch = require('gulp-watch');
var gutil = require('gulp-util');
var taskListing = require('gulp-task-listing');
var path = require('canonical-path');
var del = require('del');
var _ = require('lodash');
var argv = require('yargs').argv;
var Q = require("q");
// delPromise is a 'promise' version of del
var delPromise =  Q.denodeify(del);
var Minimatch = require("minimatch").Minimatch;
var Dgeni = require('dgeni');
var fsExtra = require('fs-extra');
var fs = fsExtra;
var exec = require('child_process').exec;
var execPromise = Q.denodeify(exec);
var prompt = require('prompt');

// TODO:
//  1. Think about using runSequence
//  2. Think about using spawn instead of exec in case of long error messages.

var docShredder = require('./public/doc-shredder/doc-shredder');

var _devguideShredOptions =  {
  examplesDir: './public/docs/_examples',
  fragmentsDir: './public/docs/_fragments'
};

var _apiShredOptions =  {
  examplesDir: '../angular/modules/angular2/examples',
  fragmentsDir: './public/docs/_fragments/_api'
};

var _excludePatterns = ['**/node_modules/**', '**/typings/**', '**/packages/**'];

var _excludeMatchers = _excludePatterns.map(function(excludePattern){
  return new Minimatch(excludePattern)
});

gulp.task('help', taskListing.withFilters(function(taskName) {
  var isSubTask = taskName.substr(0,1) == "_";
  return isSubTask;
}, function(taskName) {
  var shouldRemove = taskName === 'default';
  return shouldRemove;
}));

gulp.task('serve-and-sync', ['build-docs'], function (cb) {

  // execCommands(['harp server'], {}, cb);
  execCommands(['npm run harp -- server .'], {}, cb);

  var browserSync = require('browser-sync').create();
  browserSync.init({
    proxy: 'localhost:9000',
    files: ["public/docs/**/*/**/*" ],
    logFileChanges: true,
    reloadDelay: 500
  });

  devGuideExamplesWatch(_devguideShredOptions, function() {
    browserSync.reload();
  });

  apiSourceWatch(function() {
    browserSync.reload();
  });

});

gulp.task('build-and-serve', ['build-docs'], function (cb) {
  execCommands(['npm run harp -- server .'], {}, cb);

  var browserSync = require('browser-sync').create();
  browserSync.init({
    proxy: 'localhost:9000',
    files: ["public/docs/**/*/**/*" ],
    logFileChanges: true,
    reloadDelay: 500
  });
});

gulp.task('build-docs', ['_shred-devguide-examples', 'build-api-docs'], function() {
  return buildShredMaps(true);
});

gulp.task('build-devguide-docs', ['_shred-devguide-examples'], function() {
  return buildShredMaps(true);
});

gulp.task('build-api-docs', ['_shred-api-examples'], function() {
  if (!fs.existsSync('../angular')) {
    throw new Error('build-api-docs task requires the angular2 repo to be at ' + path.resolve('../angular'));
  }
  return buildApiDocs();
});

gulp.task('_shred-devguide-examples', ['_shred-clean-devguide'], function() {
  return docShredder.shred( _devguideShredOptions);
});

gulp.task('_shred-clean-devguide', function(cb) {
  var cleanPath = path.join(_devguideShredOptions.fragmentsDir, '**/*.*')
  return delPromise([ cleanPath, '!**/*.ovr.*', '!**/_api/**']);
});

gulp.task('_shred-api-examples', ['_shred-clean-api'], function() {
  return docShredder.shred( _apiShredOptions);
});

gulp.task('_shred-clean-api', function(cb) {
  var cleanPath = path.join(_apiShredOptions.fragmentsDir, '**/*.*')
  return delPromise([ cleanPath, '!**/*.ovr.*' ]);
});

gulp.task('_build-shred-maps', function() {
  return build-shred-maps(true);
});

gulp.task('git-changed-examples', ['_shred-devguide-examples'], function(){
  var after, sha, messageSuffix;
  if (argv.after) {
    try {
      after = new Date(argv.after);
      messageSuffix = ' after: ' + argv.after;
    } catch (e) {
      throw argv.after + " is not a valid date.";
    }
  } else if (argv.sha) {
    sha = argv.sha;
    messageSuffix = ' on commit: ' + (argv.sha.length ? argv.sha : '[last commit]');
  } else {
    console.log('git-changed-examples may be called with either an "--sha" argument like this:');
    console.log('   gulp git-changed-examples --sha=4d2ac96fa247306ddd2d4c4e0c8dee2223502eb2');
    console.log('or with an "--after" argument like this')
    console.log('   gulp git-changed-examples --after="August 1, 2015"');
    return;
  }
  var jadeShredMap;
  return buildShredMaps(false).then(function(docs) {
    jadeShredMap = docs[0];
    if (after) {
      return getChangedExamplesAfter(after);
    } else if (sha) {
      return getChangedExamples(sha);
    } else {
      console.log('git-changed-examples may be called with either an "--sha" argument like this:');
      console.log('   gulp git-changed-examples --sha=4d2ac96fa247306ddd2d4c4e0c8dee2223502eb2');
      console.log('or with an "--after" argument like this')
      console.log('   gulp git-changed-examples --after="August 1, 2015"');
    }
  }).then(function(examplePaths) {
    examplePaths = filterOutExcludedPatterns(examplePaths, _excludeMatchers);
    console.log('\nExamples changed ' + messageSuffix);
    console.log(examplePaths)
    console.log("\nJade files affected by changed example files " + messageSuffix);
    var jadeExampleMap = jadeShredMapToJadeExampleMap(jadeShredMap, examplePaths);
    console.log(JSON.stringify(jadeExampleMap, null, "  "));
    console.log("-----");
  }).catch(function(err) {
    console.log(err);
    throw err;
  });
});

gulp.task('check-deploy', ['build-docs'], function() {
  console.log('running harp compile...');
  return execPromise('npm run harp -- compile . ./www', {}).then(function() {
    execPromise('npm run live-server ./www');
    return askDeploy();
  }).then(function(shouldDeploy) {
    if (shouldDeploy) {
      console.log('deploying...');
      return execPromise('firebase deploy');
    } else {
      return ['Not deploying'];
    }
  }).then(function(s) {
    console.log(s.join(''));
  });
});

// returns a promise;
function askDeploy() {

  prompt.start();
  var schema = {
    name: 'shouldDeploy',
    description: 'Deploy to Firebase? (y/n): ',
    type: 'string',
    pattern: /Y|N|y|n/,
    message: "Respond with either a 'y' or 'n'",
    required: true
  }
  var getPromise = Q.denodeify(prompt.get);
  return getPromise([schema]).then(function(result) {
    return result.shouldDeploy.toLowerCase() === 'y';
  });
}

gulp.task('test-api-builder', function (cb) {
  execCommands(['npm run test-api-builder'], {}, cb);
});

function filterOutExcludedPatterns(fileNames, excludeMatchers) {
  return fileNames.filter(function(fileName) {
    return !excludeMatchers.some(function(excludeMatcher) {
      return excludeMatcher.match(fileName);
    });
  });
}

function apiSourceWatch(postShredAction) {
  var srcPattern = ['../angular/modules/angular2/src/**/*.*'];
  watch(srcPattern, function (event, done) {
    console.log('Event type: ' + event.event); // added, changed, or deleted
    console.log('Event path: ' + event.path); // The path of the modified file
    // need to run just build
    buildApiDocs().then(done);
  });
  var examplesPattern = ['../angular/modules/angular2/examples/**/*.*'];
  watch(examplesPattern, function (event, done) {
    console.log('Event type: ' + event.event); // added, changed, or deleted
    console.log('Event path: ' + event.path); // The path of the modified file
    // need to run shredder
    var cleanPath = path.join(_apiShredOptions.fragmentsDir, '**/*.*');
    return delPromise([ cleanPath, '!**/*.ovr.*' ]).then(function() {
      return docShredder.shred(_apiShredOptions);
    }).then(function() {
      postShredAction && postShredAction();
    });
  });

}

function buildApiDocs() {
  try {
    var dgeni = new Dgeni([require('./public/api-builder/angular.io-package')]);
    return dgeni.generate().then(function() {
      return gulp.src('./public/docs/js/latest/api/**/*.*')
        .pipe(gulp.dest('./public/docs/ts/latest/api'));
    })
  } catch(err) {
    console.log(err);
    console.log(err.stack);
    throw err;
  }
}

function devGuideExamplesWatch(shredOptions, postShredAction) {
  var pattern = path.join(shredOptions.examplesDir, "**/*.*");
  watch([pattern], function (event, done) {
    console.log('Event type: ' + event.event); // added, changed, or deleted
    console.log('Event path: ' + event.path); // The path of the modified file
    docShredder.shredSingleDir(shredOptions, event.path).then(function () {
      postShredAction && postShredAction();
    });
  });
}

function buildShredMaps(shouldWrite) {
  var options = {
    devguideExamplesDir: _devguideShredOptions.examplesDir,
    apiExamplesDir: _apiShredOptions.examplesDir,
    fragmentsDir: _devguideShredOptions.fragmentsDir,
    jadeDir: './public/docs',
    outputDir: './public/docs',
    writeFilesEnabled: shouldWrite
  };
  return docShredder.buildShredMap(options).then(function(docs) {
    return docs;
  });
}

// returns a promise containing filePaths with any changed or added examples;
function getChangedExamples(sha) {
  var Git = require("nodegit");
  var examplesPath = _devguideShredOptions.examplesDir;
  var relativePath = path.relative(process.cwd(), examplesPath);
  return Git.Repository.open(".").then(function(repo) {
    if (sha.length) {
      return repo.getCommit(sha);
    } else {
      return repo.getHeadCommit();
    }
  }).then(function(commit) {
    return getChangedExamplesForCommit(commit, relativePath);
  }).catch(function(err) {

  });
}

function getChangedExamplesAfter(date, relativePath) {
  var Git = require("nodegit");
  var examplesPath = _devguideShredOptions.examplesDir;
  var relativePath = path.relative(process.cwd(), examplesPath);
  return Git.Repository.open(".").then(function(repo) {
    return repo.getHeadCommit();
  }).then(function(commit) {
    var repo = commit.owner();
    var revWalker = repo.createRevWalk();
    revWalker.sorting(Git.Revwalk.SORT.TIME);
    revWalker.push(commit.id());
    return revWalker.getCommitsUntil(function (commit) {
      return commit.date().getTime() > date.getTime();
    });
  }).then(function(commits) {
    return Q.all(commits.map(function(commit) {
      return getChangedExamplesForCommit(commit, relativePath);
    }));
  }).then(function(arrayOfPaths) {
    var pathMap = {};
    arrayOfPaths.forEach(function(paths) {
      paths.forEach(function(path) {
        pathMap[path] = true;
      });
    });
    var uniqPaths = _.keys(pathMap);
    return uniqPaths;
  }).catch(function(err) {
    var x = err;
  });

}

function getChangedExamplesForCommit(commit, relativePath) {
  return commit.getDiff().then(function(diffList) {
    var filePaths = [];
    diffList.forEach(function (diff) {
      diff.patches().forEach(function (patch) {
        if (patch.isAdded() || patch.isModified) {
          var filePath = path.normalize(patch.newFile().path());
          var isExample = filePath.indexOf(relativePath) >= 0;
          // console.log(filePath + " isExample: " + isExample);
          if (isExample) {
            filePaths.push(filePath);
          }
        }
      });
    });
    return filePaths;
  });
}

function jadeShredMapToJadeExampleMap(jadeShredMap, examplePaths) {
  // remove dups in examplePaths
  var exampleSet = {};
  examplePaths.forEach(function(examplePath) {
    exampleSet[examplePath] = examplePath;
  });
  var basePath = path.resolve(".");
  var jadeToFragMap = jadeShredMap.jadeToFragMap;
  var jadeExampleMap = {};
  for (var jadePath in jadeToFragMap) {
    var relativeJadePath = path.relative(basePath, jadePath);
    var vals = jadeToFragMap[jadePath];
    vals.forEach(function(val) {
      var relativeExamplePath = path.relative(basePath, val.examplePath);
      if (exampleSet[relativeExamplePath] != null) {
        addKeyValue(jadeExampleMap, relativeJadePath, relativeExamplePath);
      }
    });
  }
  return jadeExampleMap;
}

function jadeShredMapToExampleJadeMap(jadeShredMap) {

  var jadeToFragMap = jadeShredMap.jadeToFragMap;
  var exampleJadeMap = {};
  for (var jadePath in jadeToFragMap) {
    var vals = jadeToFragMap[jadePath];
    vals.forEach(function(val) {
      var examplePath = val.examplePath;
      addKeyValue(exampleJadeMap, examplePath, jadePath);
    });
  }
  return exampleJadeMap;
}

function addKeyValue(map, key, value) {
  var vals = map[key];
  if (vals) {
    if (vals.indexOf(value) == -1) {
      vals.push(value);
    }
  } else {
    map[key] = [value];
  }
}

// Synchronously execute a chain of commands.
// cmds: an array of commands
// options: { shouldLog: true,  shouldThrow: true }
// cb: function(err, stdout, stderr)
function execCommands(cmds, options, cb) {
  options = options || {};
  options.shouldThrow = options.shouldThrow == null ? true : options.shouldThrow;
  options.shouldLog = options.shouldLog == null ? true : options.shouldLog;
  if (!cmds || cmds.length == 0) cb(null, null, null);
  var exec = require('child_process').exec;  // just to make it more portable.
  exec(cmds[0], options, function(err, stdout, stderr) {
    if (err == null) {
      if (options.shouldLog) {
        gutil.log('cmd: ' + cmds[0]);
        gutil.log('stdout: ' + stdout);
      }
      if (cmds.length == 1) {
        cb(err, stdout, stderr);
      } else {
        execCommands(cmds.slice(1), options, cb);
      }
    } else {
      if (options.shouldLog) {
        gutil.log('exec error on cmd: ' + cmds[0]);
        gutil.log('exec error: ' + err);
        if (stdout) gutil.log('stdout: ' + stdout);
        if (stderr) gutil.log('stderr: ' + stderr);
      }
      if (err && options.shouldThrow) throw err;
      cb(err, stdout, stderr);
    }
  });
}

gulp.task('default', ['help']);<|endoftext|>


<commit_before>const gulp = require('gulp');
const babel = require('gulp-babel');
const rename = require("gulp-rename");
const eslint = require('gulp-eslint');
const uglify = require('gulp-uglifyjs');
const minify = require("gulp-babel-minify");
const browserSync = require('browser-sync');

// Live reload task
gulp.task('sync', function () {
  browserSync.init({
    server: "./example/"
  });

  // Watch for file changes
  gulp.watch(['./src/*.js'], ['test', 'uglify', 'minify']);
  gulp.watch(["./example/*.html", "./example/js/*.js"], browserSync.reload);
});

// Minify task using babel-minify (for es7)
gulp.task('minify', function () {
  gulp.src(['./src/turtle.js'])
    .pipe(minify({
      mangle: {
        keepClassName: true
      }
    }))
    .pipe(rename('turtle.es7.min.js'))
    .pipe(gulp.dest('./dist'))
});

// Minify task using uglifyjs (for es5)
gulp.task('uglify', function () {
  gulp.src('./src/turtle.js')
    .pipe(babel({
			presets: ['env']
		}))
    .pipe(uglify())
    .pipe(rename('turtle.min.js'))
    .pipe(gulp.dest('./dist'))
    .pipe(gulp.dest('./example/js'))
});

// Tests task
gulp.task('test', function () {
  return gulp.src(['./src/*.js'])
    .pipe(eslint({
      "parser": "babel-eslint",
      rules: {
    		"camelcase": 2,
    		"curly": 1,
    		"eqeqeq": 0,
    		"no-empty": 2,
        "no-const-assign": 2,
        "no-var": 2,
        "prefer-const": 1
      },
      env: {
        "es6": true
      },
      "parserOptions": {
        "ecmaVersion": 7
      }
    }))
    .pipe(eslint.format())
});

// Set the defaukt task as 'sync'
gulp.task('default', ['sync']);
<commit_msg>Update tasks<commit_after>const gulp = require('gulp');
const babel = require('gulp-babel');
const rename = require("gulp-rename");
const eslint = require('gulp-eslint');
const uglify = require('gulp-uglifyjs');
const minify = require("gulp-babel-minify");
const browserSync = require('browser-sync');

// Live reload task
gulp.task('sync', function () {
  browserSync.init({
    server: "./example/"
  });

  // Watch for file changes
  gulp.watch(['./src/*.js'], ['lint', 'uglify', 'minify']);
  gulp.watch(['./example/*.html', './example/js/*.js', './example/css/*.css'], browserSync.reload);
});

// Minify task using babel-minify (for es7)
gulp.task('minify', function () {
  gulp.src(['./src/turtle.js'])
    .pipe(rename('turtle.es7.js'))
    .pipe(gulp.dest('./dist'))
    .pipe(minify({
      mangle: {
        keepClassName: true
      }
    }))
    .pipe(rename('turtle.es7.min.js'))
    .pipe(gulp.dest('./dist'))
});

// Minify task using uglifyjs (for es5)
gulp.task('uglify', function () {
  gulp.src('./src/turtle.js')
    .pipe(babel({
			presets: ['env']
		}))
    .pipe(gulp.dest('./dist'))
    .pipe(uglify())
    .pipe(rename('turtle.min.js'))
    .pipe(gulp.dest('./dist'))
    .pipe(gulp.dest('./example/js'))
});

// Lint task
gulp.task('lint', function () {
  return gulp.src(['./src/*.js'])
    .pipe(eslint({
      "parser": "babel-eslint",
      rules: {
    		"camelcase": 2,
    		"curly": 1,
    		"eqeqeq": 0,
    		"no-empty": 2,
        "no-const-assign": 2,
        "no-var": 2,
        "prefer-const": 1
      },
      env: {
        "es6": true
      },
      "parserOptions": {
        "ecmaVersion": 7
      }
    }))
    .pipe(eslint.format())
});

// Set the defaukt task as 'sync'
gulp.task('default', ['sync']);
<|endoftext|>


<commit_before>var gulp = require('gulp');
var sass = require('gulp-sass');
var browserSync = require('browser-sync').create();
var useref = require('gulp-useref');
var uglify = require('gulp-uglify');
var gulpIf = require('gulp-if');
var cssnano = require('gulp-cssnano');
var imagemin = require('gulp-imagemin');
var cache = require('gulp-cache');
var del = require('del');
var runSequence = require('run-sequence').use(gulp);
var pug = require('gulp-pug');
var eslint = require('gulp-eslint');
var watch = require('gulp-watch')

gulp.task('browserSync', function() {
  browserSync.init({
    server: {
      baseDir: './app'
    }
  });
});

gulp.task('sass', function() {
  return gulp.src('app/sass/**/*.sass') //Source all files ending with.scss in scss directory and its subdirectories
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
    .pipe(browserSync.reload({
      stream: true
    }))
});

gulp.task('watch', function() {
  gulp.watch('app/sass/**/*.sass', ['sass']);
  gulp.watch('app/views/**/*.pug', ['pug'], browserSync.reload);
  gulp.watch('app/js/index.js', ['lint']);
  gulp.watch('app/js/**/*.js', browserSync.reload);
  gulp.watch('app/*.html', browserSync.reload);
});

gulp.task('useref', function() {
  return gulp.src('app/*.html') //Source all html files
    .pipe(useref())
    .pipe(gulpIf('*.js', uglify())) //Minifies only if it is js file
    .pipe(gulpIf('*.css', cssnano())) //Minifies only if it is css file
    .pipe(gulp.dest('dist'))
});

gulp.task('imagemin', function() {
  return gulp.src('app/images/*.+(png|jpg|gif|swg)')
    .pipe(cache(imagemin({
      gif: {
        interlaced: true
      }
    })))
    .pipe(gulp.dest('dist/images'))
});

gulp.task('fonts', function() {
  return gulp.src('app/fonts/**/*')
    .pipe(gulp.dest('dist/fonts'))
});

gulp.task('clean:dist', function() {
  return del.sync(['dist/**/*', '!dist/images', '!dist/images/**/*']);
});

gulp.task('clean:app', function() {
  return del.sync(['app/css/main.css', 'app/index.html', 'app/js/bundle.js', 'dist']);
});

gulp.task('pug', function buildHTML() {
  return gulp.src(['app/views/index.pug', 'app/views/thanks.pug'])
    .pipe(pug({
      pretty: true
    }))
    .pipe(gulp.dest('app'))
});

gulp.task('default', function(callback) {
  runSequence(['sass', 'pug', 'browserSync', 'watch'],
    callback
  );
});

gulp.task('build', function(callback) {
  runSequence('clean:dist', ['sass', 'pug', 'useref', 'imagemin', 'fonts'], callback);
});

gulp.task('lint', function() {
  return gulp.src('app/js/index.js')
    // Load a specific ESLint config
    .pipe(eslint('.eslintrc.js'))
    .pipe(eslint.format());
});
<commit_msg>Makes sure to watch all pug files<commit_after>var gulp = require('gulp');
var sass = require('gulp-sass');
var browserSync = require('browser-sync').create();
var useref = require('gulp-useref');
var uglify = require('gulp-uglify');
var gulpIf = require('gulp-if');
var cssnano = require('gulp-cssnano');
var imagemin = require('gulp-imagemin');
var cache = require('gulp-cache');
var del = require('del');
var runSequence = require('run-sequence').use(gulp);
var pug = require('gulp-pug');
var eslint = require('gulp-eslint');
var watch = require('gulp-watch')

gulp.task('browserSync', function() {
  browserSync.init({
    server: {
      baseDir: './app'
    }
  });
});

gulp.task('sass', function() {
  return gulp.src('app/sass/**/*.sass') //Source all files ending with.scss in scss directory and its subdirectories
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
    .pipe(browserSync.reload({
      stream: true
    }))
});

gulp.task('watch', function() {
  gulp.watch('app/sass/**/*.sass', ['sass']);
  gulp.watch('app/views/**/*.pug', ['pug']);
  gulp.watch('app/js/index.js', ['lint']);
  gulp.watch('app/js/**/*.js', browserSync.reload);
  gulp.watch('app/*.html', browserSync.reload);
});

gulp.task('useref', function() {
  return gulp.src('app/*.html') //Source all html files
    .pipe(useref())
    .pipe(gulpIf('*.js', uglify())) //Minifies only if it is js file
    .pipe(gulpIf('*.css', cssnano())) //Minifies only if it is css file
    .pipe(gulp.dest('dist'))
});

gulp.task('imagemin', function() {
  return gulp.src('app/images/*.+(png|jpg|gif|swg)')
    .pipe(cache(imagemin({
      gif: {
        interlaced: true
      }
    })))
    .pipe(gulp.dest('dist/images'))
});

gulp.task('fonts', function() {
  return gulp.src('app/fonts/**/*')
    .pipe(gulp.dest('dist/fonts'))
});

gulp.task('clean:dist', function() {
  return del.sync(['dist/**/*', '!dist/images', '!dist/images/**/*']);
});

gulp.task('clean:app', function() {
  return del.sync(['app/css/main.css', 'app/index.html', 'app/js/bundle.js', 'dist']);
});

gulp.task('pug', function buildHTML() {
  return gulp.src(['app/views/index.pug', 'app/views/thanks.pug'])
    .pipe(pug({
      pretty: true
    }))
    .pipe(gulp.dest('app'))
});

gulp.task('default', function(callback) {
  runSequence(['sass', 'pug', 'browserSync', 'watch'],
    callback
  );
});

gulp.task('build', function(callback) {
  runSequence('clean:dist', ['sass', 'pug', 'useref', 'imagemin', 'fonts'], callback);
});

gulp.task('lint', function() {
  return gulp.src('app/js/index.js')
    // Load a specific ESLint config
    .pipe(eslint('.eslintrc.js'))
    .pipe(eslint.format());
});
<|endoftext|>


<commit_before>require.config({
  paths: {
    jsroot                    : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootCore"),
    "jsroot/painter"          : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootPainter"),
    "jsroot/d3"               : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/d3.v3.min"),
    "jsroot/jquery.mousewheel": vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/jquery.mousewheel"),
    "mathjax"                 : vispa.url.dynamic("extensions/jsroot/static/vendor/mathjax/MathJax.js?config=TeX-AMS-MML_SVG" +
                                // vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/mathjax_config.js")),
                                "&delayStartupUntil=configured"),
  },
  shim: {
    jsroot: {
      exports: "JSROOT"
    },
    // "jsroot/painter": [ "jsroot", "jsroot/d3", "jsroot/jquery.mousewheel" ],
    "jsroot/painter": [ "jsroot", "jsroot/d3", "jsroot/jquery.mousewheel", "mathjax" ],
    mathjax: {
      exports: "MathJax",
      deps: ['jsroot'],
      init: function () {
        MathJax.Hub.Config({ TeX: { extensions: ["color.js"] }});
        MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () {
           var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;
           VARIANT["normal"].fonts.unshift("MathJax_SansSerif");
           VARIANT["bold"].fonts.unshift("MathJax_SansSerif-bold");
           VARIANT["italic"].fonts.unshift("MathJax_SansSerif");
           VARIANT["-tex-mathit"].fonts.unshift("MathJax_SansSerif");
        });
        MathJax.Hub.Startup.onload();
        return MathJax;
      }
    }
  }
});

define([
  "vispa/extensions",
  "vispa/views/center",
  "css!../css/styles",
  "css!../vendor/jsroot/style/JSRootPainter"
], function(Extensions, CenterView) {

  var JsROOTExtension = Extensions.Extension._extend({

    init: function init() {
      init._super.call(this, "jsroot");

      var self = this;

      this.addView("jsroot", JsROOTView);

      this.addMenuEntry("Open ROOT File", {
        iconClass: "jsroot-icon-menu",
        priority : 1,
        callback : this.openViaFileSelector.bind(this)
      });

      // default preferences
      this.setDefaultPreferences(JsROOTView, {
        sidebarWidth: {
          type       : "integer",
          value      : 200,
          description: "Width of the sidebar in pixels."
        }
      }, {
        title: "ROOT File Browser"
      });

      // tell other extensions to open root files with this jsROOTView
      this.addFileHandler("root", function(workspaceId, path) {
        self.createInstance(workspaceId, JsROOTView, { path: path });
      });

      // default fast menu entries
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "open" ];
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "help" ];

    },

    openViaFileSelector: function(workspaceId, callback) {
      var self = this;

      if (callback === undefined) {
        callback = function(workspaceId, path) {
          self.createInstance(workspaceId, JsROOTView, { path: path });
        };
      }

      var args = {
        callback: function(path) {
          // a root file?
          var ext = path.split(".").pop().toLowerCase();
          if (ext != "root") {
            vispa.messenger.alert("The selected file is not a root file. Please select a different one!");
            self.openViaFileSelector(workspaceId, callback);
          } else {
            callback(workspaceId, path);
          }
        }
      };

      vispa.extensions.createInstance(workspaceId, "file", "FileSelector", 0, args);
    }

  });

  var JsROOTView = CenterView._extend({

    init: function init(obj) {
      init._super.apply(this, arguments);

      var self = this;

      require(["jsroot", "mathjax"]);

      this.path    = (obj || {}).path;
      this.painter = null;
      this.nodes   = {};

      this.addMenuEntry("open", {
        label      : "Open File ...",
        iconClass  : "glyphicon glyphicon-folder-open",
        buttonClass: "btn-primary",
        callback: function() {
          self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
            self.openFile(path);
          });
        }
      });

      this.addMenuEntry("help", {
        label      : "Help",
        iconClass  : "glyphicon glyphicon-question-sign",
        buttonClass: "btn-primary",
        callback: function() {
          self.openHelpDialog();
        }
      });

      // look if file has been deleted or modified
      this.onSocket("watch", function(data) {
        console.log(data);
        if (data.watch_id != "jsroot")
          return;
        // in case file deleting or renamings
        if (data.event == "vanish" && data.mtime == -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been deleted or renamed. \n Please open a new file or the browser is closed.",
          function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
                self.openFile(path);
              });
            }
          });
        }
        // in case up file modification
        if (data.event == "vanish" && data.mtime != -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }
        if (data.event == "modify") {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }

      });

    },

    applyPreferences: function applyPreferences() {
      applyPreferences._super.call(this);

      this.layout(this.getPreference("sidebarWidth"));
    },

    render: function($node) {
      var self = this;

      // set icon for tab
      this.setIcon("jsroot-icon-tab");

      // get html template
      this.getTemplate("html/main.html", function(err, tmpl) {
        if (err) throw err;

        var $main        = $(tmpl).appendTo($node);
        var $sidebar     = $main.find(".sidebar-resize-wrapper");
        var $content     = $main.find(".content-wrapper");
        var $placeholder = $main.find(".placeholder");
        var $canvas      = $main.find(".canvas-wrapper");

        // make divs resizable
        $sidebar.resizable({
          start: function() {
            var mainWidth  = $main.width();
            $sidebar.resizable("option", "grid", [mainWidth * 0.01, 1]);
            $sidebar.resizable("option", "minWidth", 0);
            $sidebar.resizable("option", "maxWidth", mainWidth);
          },
          resize: function() {
            var mainWidth    = $main.width();
            var sidebarWidth = $sidebar.width();
            var contentWidth = mainWidth - sidebarWidth;
            $sidebar.css({
              left : 0,
              width: sidebarWidth
            });
            $content.css({
              left : sidebarWidth,
              width: contentWidth
            });
          },
          stop: function() {
            // tell the preferences about the new width
            self.setPreference("sidebarWidth", parseInt(Math.floor($sidebar.width())));
            // self.pushPreferences();
          }
        });

        // make canvas wrapper resizable
        $canvas.resizable({
          start: function() {
            // set max dimensions
            $canvas.resizable("option", "maxWidth",  $content.width());
            $canvas.resizable("option", "maxHeight", $content.height());
          }
        });

        // store nodes
        self.nodes.$main        = $main;
        self.nodes.$sidebar     = $sidebar;
        self.nodes.$content     = $content;
        self.nodes.$placeholder = $placeholder;
        self.nodes.$canvas      = $canvas;

        // apply preferences
        self.applyPreferences();

        // open initial path?
        self.openFile(self.path);

      });
    },

    layout: function(sidebarWidth) {
      if (!this.nodes.$main) return;

      // limit the sidebar width
      var width = Math.min(Math.max(sidebarWidth, 0), this.nodes.$main.width());
      if (width != sidebarWidth) {
        this.setPreference("sidebarWidth", width);
        this.pushPreferences();
        return;
      }

      // set sidebar and content layout
      this.nodes.$sidebar.css({
        left : 0,
        width: sidebarWidth
      });
      this.nodes.$content.css({
        left : sidebarWidth,
        width: ""
      });

      // maybe update the canvas width
      var contentWidth = this.nodes.$content.width();
      if (this.nodes.$canvas.width() > contentWidth) {
        this.nodes.$canvas.width(contentWidth);
      }
    },

    openFile: function(path) {
      var self = this;

      if (!path || !this.nodes.$main) return;
      this.setLoading(true);
      this.path = path;
      this.setLabel(path, true);

      require(["jsroot", "jsroot/painter"], function(JSROOT) {
        JSROOT.MathJax = 2;
        self.nodes.$placeholder.hide();
        self.nodes.$canvas.show().find("> div.pad").empty();

        // set new ids
        var treeId = "tree-" + vispa.uuid();
        var padId  = "pad-"  + vispa.uuid();

        self.nodes.$main.find(".tree").attr("id", treeId);
        self.nodes.$main.find(".pad").attr("id", padId);

        // build the root file path
        var workspaceId = self.getWorkspaceId();
        path = "fs/getfile?path=" + path + "&_workspaceId=" + workspaceId;
        path = vispa.url.dynamic(path);

        // load root file
        self.painter = new JSROOT.HierarchyPainter("painter-" + vispa.uuid(), treeId);
        JSROOT.RegisterForResize(self.painter);
        self.painter.SetDisplay("simple", padId);
        self.painter.OpenRootFile(path, function() {
          self.setLoading(false);
        });
      });

      // watch
      this.POST("/ajax/fs/watch", {
        path    : this.path,
        watch_id: "jsroot"
      });

    },

    openHelpDialog: function() {
      var self    = this;
      var header  = " Help";
      var body    = "
Why are my root files not shown correctely?

VISPA adopts" +
                    " the jsroot  library to draw" +
                    " ROOT objects. Currently, the classes" +
                    "

TH1

TH2

TH3

TProfile

TGraph

TF1
" +
                    "
TPaveText

TCanvas

 are supported, as well as LaTeX strings." +
                    "
For more information, visit the jsroot  documentation site.";
      var $footer = $("
<button class='btn btn-primary'>Close</button>
");
      self.dialog({
        header  : header,
        body    : body,
        footer  : $footer,
        onRender: function() {
          var self = this;
          $footer.find("button").click(function() {
            self.close();
          });
        }
      });
    },

    onClose: function() {
      this.POST("/ajax/fs/unwatch");
    }

  });

  return JsROOTExtension;
});
<commit_msg>Update require.js for jsroot 3.7<commit_after>require.config({
  paths: {
    "JSRootCore"    : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootCore"),
    "JSRootPainter" : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootPainter"),
    "mathjax"       : vispa.url.dynamic("extensions/jsroot/static/vendor/mathjax/MathJax.js?config=TeX-AMS-MML_SVG&delayStartupUntil=configured")
  }
});

define([
  "vispa/extensions",
  "vispa/views/center",
  "css!../css/styles",
  "css!../vendor/jsroot/style/JSRootPainter"
], function(Extensions, CenterView) {

  var JsROOTExtension = Extensions.Extension._extend({

    init: function init() {
      init._super.call(this, "jsroot");

      var self = this;

      this.addView("jsroot", JsROOTView);

      this.addMenuEntry("Open ROOT File", {
        iconClass: "jsroot-icon-menu",
        priority : 1,
        callback : this.openViaFileSelector.bind(this)
      });

      // default preferences
      this.setDefaultPreferences(JsROOTView, {
        sidebarWidth: {
          type       : "integer",
          value      : 200,
          description: "Width of the sidebar in pixels."
        }
      }, {
        title: "ROOT File Browser"
      });

      // tell other extensions to open root files with this jsROOTView
      this.addFileHandler("root", function(workspaceId, path) {
        self.createInstance(workspaceId, JsROOTView, { path: path });
      });

      // default fast menu entries
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "open" ];
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "help" ];

    },

    openViaFileSelector: function(workspaceId, callback) {
      var self = this;

      if (callback === undefined) {
        callback = function(workspaceId, path) {
          self.createInstance(workspaceId, JsROOTView, { path: path });
        };
      }

      var args = {
        callback: function(path) {
          // a root file?
          var ext = path.split(".").pop().toLowerCase();
          if (ext != "root") {
            vispa.messenger.alert("The selected file is not a root file. Please select a different one!");
            self.openViaFileSelector(workspaceId, callback);
          } else {
            callback(workspaceId, path);
          }
        }
      };

      vispa.extensions.createInstance(workspaceId, "file", "FileSelector", 0, args);
    }

  });

  var JsROOTView = CenterView._extend({

    init: function init(obj) {
      init._super.apply(this, arguments);

      var self = this;

      require(["JSRootCore", "mathjax", "JSRootPainter"]);

      this.path    = (obj || {}).path;
      this.painter = null;
      this.nodes   = {};

      this.addMenuEntry("open", {
        label      : "Open File ...",
        iconClass  : "glyphicon glyphicon-folder-open",
        buttonClass: "btn-primary",
        callback: function() {
          self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
            self.openFile(path);
          });
        }
      });

      this.addMenuEntry("help", {
        label      : "Help",
        iconClass  : "glyphicon glyphicon-question-sign",
        buttonClass: "btn-primary",
        callback: function() {
          self.openHelpDialog();
        }
      });

      // look if file has been deleted or modified
      this.onSocket("watch", function(data) {
        console.log(data);
        if (data.watch_id != "jsroot")
          return;
        // in case file deleting or renamings
        if (data.event == "vanish" && data.mtime == -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been deleted or renamed. \n Please open a new file or the browser is closed.",
          function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
                self.openFile(path);
              });
            }
          });
        }
        // in case up file modification
        if (data.event == "vanish" && data.mtime != -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }
        if (data.event == "modify") {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }

      });

    },

    applyPreferences: function applyPreferences() {
      applyPreferences._super.call(this);

      this.layout(this.getPreference("sidebarWidth"));
    },

    render: function($node) {
      var self = this;

      // set icon for tab
      this.setIcon("jsroot-icon-tab");

      // get html template
      this.getTemplate("html/main.html", function(err, tmpl) {
        if (err) throw err;

        var $main        = $(tmpl).appendTo($node);
        var $sidebar     = $main.find(".sidebar-resize-wrapper");
        var $content     = $main.find(".content-wrapper");
        var $placeholder = $main.find(".placeholder");
        var $canvas      = $main.find(".canvas-wrapper");

        // make divs resizable
        $sidebar.resizable({
          start: function() {
            var mainWidth  = $main.width();
            $sidebar.resizable("option", "grid", [mainWidth * 0.01, 1]);
            $sidebar.resizable("option", "minWidth", 0);
            $sidebar.resizable("option", "maxWidth", mainWidth);
          },
          resize: function() {
            var mainWidth    = $main.width();
            var sidebarWidth = $sidebar.width();
            var contentWidth = mainWidth - sidebarWidth;
            $sidebar.css({
              left : 0,
              width: sidebarWidth
            });
            $content.css({
              left : sidebarWidth,
              width: contentWidth
            });
          },
          stop: function() {
            // tell the preferences about the new width
            self.setPreference("sidebarWidth", parseInt(Math.floor($sidebar.width())));
            // self.pushPreferences();
          }
        });

        // make canvas wrapper resizable
        $canvas.resizable({
          start: function() {
            // set max dimensions
            $canvas.resizable("option", "maxWidth",  $content.width());
            $canvas.resizable("option", "maxHeight", $content.height());
          }
        });

        // store nodes
        self.nodes.$main        = $main;
        self.nodes.$sidebar     = $sidebar;
        self.nodes.$content     = $content;
        self.nodes.$placeholder = $placeholder;
        self.nodes.$canvas      = $canvas;

        // apply preferences
        self.applyPreferences();

        // open initial path?
        self.openFile(self.path);

      });
    },

    layout: function(sidebarWidth) {
      if (!this.nodes.$main) return;

      // limit the sidebar width
      var width = Math.min(Math.max(sidebarWidth, 0), this.nodes.$main.width());
      if (width != sidebarWidth) {
        this.setPreference("sidebarWidth", width);
        this.pushPreferences();
        return;
      }

      // set sidebar and content layout
      this.nodes.$sidebar.css({
        left : 0,
        width: sidebarWidth
      });
      this.nodes.$content.css({
        left : sidebarWidth,
        width: ""
      });

      // maybe update the canvas width
      var contentWidth = this.nodes.$content.width();
      if (this.nodes.$canvas.width() > contentWidth) {
        this.nodes.$canvas.width(contentWidth);
      }
    },

    openFile: function(path) {
      var self = this;

      if (!path || !this.nodes.$main) return;
      this.setLoading(true);
      this.path = path;
      this.setLabel(path, true);

      require(["JSRootPainter"], function(JSROOT) {
        JSROOT.MathJax = 2;
        self.nodes.$placeholder.hide();
        self.nodes.$canvas.show().find("> div.pad").empty();

        // set new ids
        var treeId = "tree-" + vispa.uuid();
        var padId  = "pad-"  + vispa.uuid();

        self.nodes.$main.find(".tree").attr("id", treeId);
        self.nodes.$main.find(".pad").attr("id", padId);

        // build the root file path
        var workspaceId = self.getWorkspaceId();
        path = "fs/getfile?path=" + path + "&_workspaceId=" + workspaceId;
        path = vispa.url.dynamic(path);

        // load root file
        self.painter = new JSROOT.HierarchyPainter("painter-" + vispa.uuid(), treeId);
        JSROOT.RegisterForResize(self.painter);
        self.painter.SetDisplay("simple", padId);
        self.painter.OpenRootFile(path, function() {
          self.setLoading(false);
        });
      });

      // watch
      this.POST("/ajax/fs/watch", {
        path    : this.path,
        watch_id: "jsroot"
      });

    },

    openHelpDialog: function() {
      var self    = this;
      var header  = " Help";
      var body    = "
Why are my root files not shown correctely?

VISPA adopts" +
                    " the jsroot  library to draw" +
                    " ROOT objects. Currently, the classes" +
                    "

TH1

TH2

TH3

TProfile

TGraph

TF1
" +
                    "
TPaveText

TCanvas

 are supported, as well as LaTeX strings." +
                    "
For more information, visit the jsroot  documentation site.";
      var $footer = $("
<button class='btn btn-primary'>Close</button>
");
      self.dialog({
        header  : header,
        body    : body,
        footer  : $footer,
        onRender: function() {
          var self = this;
          $footer.find("button").click(function() {
            self.close();
          });
        }
      });
    },

    onClose: function() {
      this.POST("/ajax/fs/unwatch");
    }

  });

  return JsROOTExtension;
});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var typescript = require('gulp-typescript');
var archiver = require('archiver');
var fs = require('fs');
var path = require('path');
var pkg = require('./package.json');
var webserver = require('gulp-webserver');

// compile sass and concatenate to single css file in build dir
gulp.task('convert-sass', function() {

	return gulp.src('src/scss/app.scss')
	  	.pipe(sass({includePaths: [
			'node_modules/mdbootstrap/sass/',
			'node_modules/mdi/scss/'
		], precision: 8}))
	  	.pipe(concat(pkg.name + '.css'))
	    .pipe(gulp.dest('src/css'));
});

function watch() {
    gulp.watch('src/scss/**/*.scss', ['convert-sass']);
}

gulp.task('webserver-watch', function() {
	gulp.src('./')
        .pipe(webserver({
			fallback: 'index.html',
			port: 8083
		}));
	watch();
});

const tscConfig = require('./tsconfig.json');
gulp.task('compile',['convert-sass'], function () {
    // fonts
    gulp.src([
            'node_modules/mdi/fonts/**/*',
            'node_modules/mdbootstrap/font/**/*'
        ])
        .pipe(gulp.dest('fonts'));

    // sources
    gulp
        .src('*.ts')
        .pipe(typescript(tscConfig.compilerOptions))
        .pipe(gulp.dest('./'));

    gulp
		.src('demo/app/**/*.ts')
		.pipe(typescript(tscConfig.compilerOptions))
		.pipe(gulp.dest('demo/app/'));

    gulp
        .src('src/app/**/*.ts')
        .pipe(typescript(tscConfig.compilerOptions))
        .pipe(gulp.dest('src/app/'));

	// test sources
    return gulp
		.src('src/test/**/*.ts')
		.pipe(typescript(tscConfig.compilerOptions))
		.pipe(gulp.dest('src/test/'));
});

function createConfig(path) {
	fs.access(path, fs.F_OK, function (err) {

		if (err) {
			fs.createReadStream(path+'.template').pipe(fs.createWriteStream(path));
		} else {
			console.log('Will not create '+path+' from template because file already exists.');
		}
	});
}

// Creates config file if it doesn't exist already
gulp.task('create-configs', function (callback) {
	createConfig('./demo/config/Configuration.json');
});
<commit_msg>Add missing bootstrap styles.<commit_after>var gulp = require('gulp');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var typescript = require('gulp-typescript');
var archiver = require('archiver');
var fs = require('fs');
var path = require('path');
var pkg = require('./package.json');
var webserver = require('gulp-webserver');

// compile sass and concatenate to single css file in build dir
gulp.task('convert-sass', function () {

    return gulp.src([
        'src/scss/app.scss',
        'node_modules/mdbootstrap/css/bootstrap.css'
    ])
        .pipe(sass({
            includePaths: [
                'node_modules/mdbootstrap/sass/',
                'node_modules/mdi/scss/'
            ], precision: 8
        }))
        .pipe(concat(pkg.name + '.css'))
        .pipe(gulp.dest('src/css'));
});

function watch() {
    gulp.watch('src/scss/**/*.scss', ['convert-sass']);
}

gulp.task('webserver-watch', function () {
    gulp.src('./')
        .pipe(webserver({
            fallback: 'index.html',
            port: 8083
        }));
    watch();
});

const tscConfig = require('./tsconfig.json');
gulp.task('compile', ['convert-sass'], function () {
    // fonts
    gulp.src([
        'node_modules/mdi/fonts/**/*',
        'node_modules/mdbootstrap/font/**/*'
    ])
        .pipe(gulp.dest('fonts'));

    // sources
    gulp
        .src('*.ts')
        .pipe(typescript(tscConfig.compilerOptions))
        .pipe(gulp.dest('./'));

    gulp
        .src('demo/app/**/*.ts')
        .pipe(typescript(tscConfig.compilerOptions))
        .pipe(gulp.dest('demo/app/'));

    gulp
        .src('src/app/**/*.ts')
        .pipe(typescript(tscConfig.compilerOptions))
        .pipe(gulp.dest('src/app/'));

    // test sources
    return gulp
        .src('src/test/**/*.ts')
        .pipe(typescript(tscConfig.compilerOptions))
        .pipe(gulp.dest('src/test/'));
});

function createConfig(path) {
    fs.access(path, fs.F_OK, function (err) {

        if (err) {
            fs.createReadStream(path + '.template').pipe(fs.createWriteStream(path));
        } else {
            console.log('Will not create ' + path + ' from template because file already exists.');
        }
    });
}

// Creates config file if it doesn't exist already
gulp.task('create-configs', function (callback) {
    createConfig('./demo/config/Configuration.json');
});
<|endoftext|>


<commit_before>var os = require('os');
var gulp = require('gulp')
var open = require('gulp-open');
var Server = require('karma').Server;

/* Check the platform before selecting a browswer */
var browser = os.platform() === 'linux' ? 'google-chrome' :  'firefox'(
  os.platform() === 'darwin' ? 'google chrome' : 'safari' (
  os.platform() === 'win32' ? 'chrome' : 'iexplore'));

/* Run every unit test once, then quit */
gulp.task('unitTests', function(done) {
    new Server({
        configFile: __dirname + '/karma.conf.js',
        singleRun: true
    }, done).start();
});

/* Wait for unitTests to finish, then open the generated report */
gulp.task('openCodeCoverage', ['unitTests'], function(){
  gulp.src('./reports/*/index.html')
  .pipe(open({app: browser}));
});

/* Can run `gulp test` to just run unit tests */
gulp.task('test', ['unitTests']);

/* Can run `gulp test-coverage` run unit tests and then show the code coverage */
gulp.task('test-coverage', ['unitTests', 'openCodeCoverage']);
<commit_msg>Modify browser selection statement<commit_after>var os = require('os');
var gulp = require('gulp')
var open = require('gulp-open');
var Server = require('karma').Server;

/* Check the platform before selecting a browswer */
var browser = os.platform() === 'linux' ? ('google-chrome' || 'firefox') : (
  os.platform() === 'darwin' ? ('google chrome' || 'safarai') : (
  os.platform() === 'win32' ? 'chrome' : 'iexplore'));

/* Run every unit test once, then quit */
gulp.task('unitTests', function(done) {
    new Server({
        configFile: __dirname + '/karma.conf.js',
        singleRun: true
    }, done).start();
});

/* Wait for unitTests to finish, then open the generated report */
gulp.task('openCodeCoverage', ['unitTests'], function(){
  gulp.src('./reports/*/index.html')
  .pipe(open({app: browser}));
});

/* Can run `gulp test` to just run unit tests */
gulp.task('test', ['unitTests']);

/* Can run `gulp test-coverage` run unit tests and then show the code coverage */
gulp.task('test-coverage', ['unitTests', 'openCodeCoverage']);
<|endoftext|>