klei / gulp-angular-filesort

Automatically sort AngularJS app files depending on module definitions and usage
MIT License
132 stars 46 forks source link

Non-reversed option and simple debug options #27

Open lborupj opened 9 years ago

lborupj commented 9 years ago

Hi,

When used to sort bower components, the non-reversed order is needed, hence reverse should be an option. Perhaps something like (index.js):


var es = require('event-stream');
var ngDep = require('ng-dependencies');
var toposort = require('toposort');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;

var PLUGIN_NAME = 'gulp-angular-filesort';
var ANGULAR_MODULE = 'ng';

module.exports = function angularFilesort (opts) {
  var files = [];
  var angmods = {};
  var toSort = [];
  var dbgTitle = 'angularFilesort: ';
  var lOpts = opts || {debug: false, reverse: true};

  return es.through(function collectFilesToSort (file) {
      if(!file.contents) {
        return this.emit('error', new PluginError(PLUGIN_NAME, 'File: "' + file.relative + '" without content. You have to read it with gulp.src(..)'));
      }

      var deps;
      try {
        deps = ngDep(file.contents);
      } catch (err) {
        return this.emit('error', new PluginError(PLUGIN_NAME, 'Error in parsing: "' + file.relative + '", ' + err.message));
      }

      if (lOpts.debug) {
            gutil.log(dbgTitle + file.path + ' Modules={' + Object.keys(deps.modules) + '}, dependencies={' + deps.dependencies +'}');
      }

      if (deps.modules) {
        // Store references to each file with a declaration:
        Object.keys(deps.modules).forEach(function (name) {
          angmods[name] = file;
        });
      }

      if (deps.dependencies) {
        // Add each file with dependencies to the array to sort:
        deps.dependencies.forEach(function (dep) {
          if (isDependecyUsedInAnyDeclaration(dep, deps)) {
            return;
          }
          if (dep === ANGULAR_MODULE) {
            return;
          }
          toSort.push([file, dep]);
        });
      }

      // Collect all files:
      files.push(file);

    }, function afterFileCollection () {
      // Convert all module names to actual files with declarations:
      for (var i = 0; i < toSort.length; i++) {
        var moduleName = toSort[i][1];
        var declarationFile = angmods[moduleName];
        if (declarationFile) {
          toSort[i][1] = declarationFile;
        } else {
          // Depending on module outside stream (possibly a 3rd party one),
          // don't care when sorting:
          toSort.splice(i--, 1);
        }
      }

      // Sort `files` with `toSort` as dependency tree:
      var sorted = toposort.array(files, toSort);
      if (lOpts.reverse) {
          sorted = sorted.reverse();
      }
      sorted.forEach(function (file) {
          this.emit('data', file);
      }.bind(this));

      this.emit('end');
    });
};

function isDependecyUsedInAnyDeclaration (dependency, ngDeps) {
  if (!ngDeps.modules) {
    return false;
  }
  if (dependency in ngDeps.modules) {
    return true;
  }
  return Object.keys(ngDeps.modules).some(function (module) {
    return ngDeps.modules[module].indexOf(dependency) > -1;
  });
}

and then use

    return gulp.src(bowerFiles(), {base : 'bower_components/'})
        .pipe(filterScriptsOnly)
        .pipe(plugins.angularFilesort({debug: false, reverse: false}))
        .pipe(plugins.order(['**/jquery.js', '**/angular.js']))
        .pipe(debug({title: 'sorted-vendor-scripts:'}))
        .pipe(filterScriptsOnly.restore()); 

to sort correctly (and prefer jquery)