forceAtlas2.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * grunt-forceAtlas2
  3. *
  4. * This task crush and minify Force Atlas 2 code.
  5. */
  6. var uglify = require('uglify-js');
  7. // Shorteners
  8. function minify(string) {
  9. return uglify.minify(string, {fromString: true}).code;
  10. }
  11. // Crushing function
  12. function crush(fnString) {
  13. var pattern,
  14. i,
  15. l;
  16. var np = [
  17. 'x',
  18. 'y',
  19. 'dx',
  20. 'dy',
  21. 'old_dx',
  22. 'old_dy',
  23. 'mass',
  24. 'convergence',
  25. 'size',
  26. 'fixed'
  27. ];
  28. var ep = [
  29. 'source',
  30. 'target',
  31. 'weight'
  32. ];
  33. var rp = [
  34. 'node',
  35. 'centerX',
  36. 'centerY',
  37. 'size',
  38. 'nextSibling',
  39. 'firstChild',
  40. 'mass',
  41. 'massCenterX',
  42. 'massCenterY'
  43. ];
  44. // Replacing matrix accessors by incremented indexes
  45. for (i = 0, l = rp.length; i < l; i++) {
  46. pattern = new RegExp('rp\\(([^,]*), \'' + rp[i] + '\'\\)', 'g');
  47. fnString = fnString.replace(
  48. pattern,
  49. (i === 0) ? '$1' : '$1 + ' + i
  50. );
  51. }
  52. for (i = 0, l = np.length; i < l; i++) {
  53. pattern = new RegExp('np\\(([^,]*), \'' + np[i] + '\'\\)', 'g');
  54. fnString = fnString.replace(
  55. pattern,
  56. (i === 0) ? '$1' : '$1 + ' + i
  57. );
  58. }
  59. for (i = 0, l = ep.length; i < l; i++) {
  60. pattern = new RegExp('ep\\(([^,]*), \'' + ep[i] + '\'\\)', 'g');
  61. fnString = fnString.replace(
  62. pattern,
  63. (i === 0) ? '$1' : '$1 + ' + i
  64. );
  65. }
  66. return fnString;
  67. }
  68. // Cleaning function
  69. function clean(string) {
  70. return string.replace(
  71. /function crush\(fnString\)/,
  72. 'var crush = null; function no_crush(fnString)'
  73. );
  74. }
  75. module.exports = function(grunt) {
  76. // Force atlas grunt multitask
  77. function multitask() {
  78. // Merge task-specific and/or target-specific options with these defaults.
  79. var options = this.options({});
  80. // Iterate over all specified file groups.
  81. this.files.forEach(function(f) {
  82. // Concat specified files.
  83. var src = f.src.filter(function(filepath) {
  84. // Warn on and remove invalid source files (if nonull was set).
  85. if (!grunt.file.exists(filepath)) {
  86. grunt.log.warn('Source file "' + filepath + '" not found.');
  87. return false;
  88. } else {
  89. return true;
  90. }
  91. }).map(function(filepath) {
  92. // Read file source.
  93. return grunt.file.read(filepath);
  94. }).join('\n');
  95. // Crushing, cleaning and minifying
  96. src = minify(clean(crush(src)));
  97. // Write the destination file.
  98. grunt.file.write(f.dest, src);
  99. // Print a success message.
  100. grunt.log.writeln('File "' + f.dest + '" created.');
  101. });
  102. }
  103. // Registering the task
  104. grunt.registerMultiTask(
  105. 'forceAtlas2',
  106. 'A grunt task to crush and minify ForceAtlas2.',
  107. multitask
  108. );
  109. };