<commit_before>exports.isClient = typeof global != "object";

var _;

if (!exports.isClient) {
  var npm = require("npm/lib/npm.js");
  var readInstalled = require("./read-installed.js");
  var relativize = require("npm/lib/utils/relativize.js");
  var readJson = require("npm/lib/utils/read-json.js");
  var path = require("path");
  var async = require("async");
  var fs = require("fs");
  var tsort = require("./tsort");
  var util = require("util");
  _ = require("underscore");
}else{
  var $, jQuery;
  $ = jQuery = require("ep_etherpad-lite/static/js/rjquery").$;
  _ = require("ep_etherpad-lite/static/js/underscore");
}

exports.prefix = 'ep_';
exports.loaded = false;
exports.plugins = {};
exports.parts = [];
exports.hooks = {};

exports.ensure = function (cb) {
  if (!exports.loaded)
    exports.update(cb);
  else
    cb();
};

exports.formatPlugins = function () {
  return _.keys(exports.plugins).join(", ");
};

exports.formatParts = function () {
  return _.map(exports.parts, function (part) { return part.full_name; }).join("\n");
};

exports.formatHooks = function () {
  var res = [];
  _.chain(exports.hooks).keys().forEach(function (hook_name) {
    _.forEach(exports.hooks[hook_name], function (hook) {
      res.push(hook.hook_name + ": " + hook.hook_fn_name + " from " + hook.part.full_name);
    });
  });
  return res.join("\n");
};

exports.loadFn = function (path, hookName) {
  var x = path.split(":");
  var fn = require(x[0]);
  var functionName = x[1] ? x[1] : hookName;  
  
  _.each(functionName.split("."), function (name) {
    fn = fn[name];
  });
  return fn;
};

exports.extractHooks = function (parts, hook_set_name) {
  var hooks = {};
  _.each(parts,function (part) {
    _.chain(part[hook_set_name] || {})
    .keys()
    .each(function (hook_name) {
      if (hooks[hook_name] === undefined) hooks[hook_name] = [];
      
      
      var hook_fn_name = part[hook_set_name][hook_name];
      var hook_fn = exports.loadFn(hook_fn_name, hook_name);
      if (hook_fn) {
        hooks[hook_name].push({"hook_name": hook_name, "hook_fn": hook_fn, "hook_fn_name": hook_fn_name, "part": part});
      } else {
        console.error("Unable to load hook function for " + part.full_name + " for hook " + hook_name + ": " + part.hooks[hook_name]);
      }	
    });
  });
  return hooks;
};


if (exports.isClient) {
  exports.update = function (cb) {
    jQuery.getJSON('/pluginfw/plugin-definitions.json', function(data) {
      exports.plugins = data.plugins;
      exports.parts = data.parts;
      exports.hooks = exports.extractHooks(exports.parts, "client_hooks");
      exports.loaded = true;
      cb();
     }).error(function(xhr, s, err){
       console.error("Failed to load plugin-definitions: " + err);
       cb();
     });
  };
} else {

exports.callInit = function (cb) {
  var hooks = require("./hooks");<commit_msg>Work around strange order of execution bug in Firefox. Fixes #620<commit_after>exports.isClient = typeof global != "object";

var _;

if (!exports.isClient) {
  var npm = require("npm/lib/npm.js");
  var readInstalled = require("./read-installed.js");
  var relativize = require("npm/lib/utils/relativize.js");
  var readJson = require("npm/lib/utils/read-json.js");
  var path = require("path");
  var async = require("async");
  var fs = require("fs");
  var tsort = require("./tsort");
  var util = require("util");
  _ = require("underscore");
}else{
  var $, jQuery;
  $ = jQuery = require("ep_etherpad-lite/static/js/rjquery").$;
  _ = require("ep_etherpad-lite/static/js/underscore");
}

exports.prefix = 'ep_';
exports.loaded = false;
exports.plugins = {};
exports.parts = [];
exports.hooks = {};

exports.ensure = function (cb) {
  if (!exports.loaded)
    exports.update(cb);
  else
    cb();
};

exports.formatPlugins = function () {
  return _.keys(exports.plugins).join(", ");
};

exports.formatParts = function () {
  return _.map(exports.parts, function (part) { return part.full_name; }).join("\n");
};

exports.formatHooks = function () {
  var res = [];
  _.chain(exports.hooks).keys().forEach(function (hook_name) {
    _.forEach(exports.hooks[hook_name], function (hook) {
      res.push(hook.hook_name + ": " + hook.hook_fn_name + " from " + hook.part.full_name);
    });
  });
  return res.join("\n");
};

exports.loadFn = function (path, hookName) {
  var x = path.split(":");
  var fn = require(x[0]);
  var functionName = x[1] ? x[1] : hookName;  
  
  _.each(functionName.split("."), function (name) {
    fn = fn[name];
  });
  return fn;
};

exports.extractHooks = function (parts, hook_set_name) {
  var hooks = {};
  _.each(parts,function (part) {
    _.chain(part[hook_set_name] || {})
    .keys()
    .each(function (hook_name) {
      if (hooks[hook_name] === undefined) hooks[hook_name] = [];
      
      
      var hook_fn_name = part[hook_set_name][hook_name];
      var hook_fn = exports.loadFn(hook_fn_name, hook_name);
      if (hook_fn) {
        hooks[hook_name].push({"hook_name": hook_name, "hook_fn": hook_fn, "hook_fn_name": hook_fn_name, "part": part});
      } else {
        console.error("Unable to load hook function for " + part.full_name + " for hook " + hook_name + ": " + part.hooks[hook_name]);
      }	
    });
  });
  return hooks;
};


if (exports.isClient) {
  exports.update = function (cb) {
    // It appears that this response (see #620) may interrupt the current thread
    // of execution on Firefox. This schedules the response in the run-loop,
    // which appears to fix the issue.
    var callback = function () {setTimeout(cb, 0);};

    jQuery.getJSON('/pluginfw/plugin-definitions.json', function(data) {
      exports.plugins = data.plugins;
      exports.parts = data.parts;
      exports.hooks = exports.extractHooks(exports.parts, "client_hooks");
      exports.loaded = true;
      callback();
     }).error(function(xhr, s, err){
       console.error("Failed to load plugin-definitions: " + err);
       callback();
     });
  };
} else {

exports.callInit = function (cb) {
  var hooks = require("./hooks");
{'fraction_non_alphanumeric': 0.17643175441491996, 'fraction_numerical': 0.002145568575672553, 'mean_word_length': 3.3817787418655096, 'pattern_counts': {'":': 14, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5505336', 'n_tokens_mistral': 2051, 'n_tokens_neox': 2043, 'n_words': 415}