Front end of the Slack clone application.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /**
  2. * archiver-utils
  3. *
  4. * Copyright (c) 2012-2014 Chris Talkington, contributors.
  5. * Licensed under the MIT license.
  6. * https://github.com/archiverjs/node-archiver/blob/master/LICENSE-MIT
  7. */
  8. var fs = require('graceful-fs');
  9. var path = require('path');
  10. var _ = require('lodash');
  11. var glob = require('glob');
  12. var file = module.exports = {};
  13. var pathSeparatorRe = /[\/\\]/g;
  14. // Process specified wildcard glob patterns or filenames against a
  15. // callback, excluding and uniquing files in the result set.
  16. var processPatterns = function(patterns, fn) {
  17. // Filepaths to return.
  18. var result = [];
  19. // Iterate over flattened patterns array.
  20. _.flatten(patterns).forEach(function(pattern) {
  21. // If the first character is ! it should be omitted
  22. var exclusion = pattern.indexOf('!') === 0;
  23. // If the pattern is an exclusion, remove the !
  24. if (exclusion) { pattern = pattern.slice(1); }
  25. // Find all matching files for this pattern.
  26. var matches = fn(pattern);
  27. if (exclusion) {
  28. // If an exclusion, remove matching files.
  29. result = _.difference(result, matches);
  30. } else {
  31. // Otherwise add matching files.
  32. result = _.union(result, matches);
  33. }
  34. });
  35. return result;
  36. };
  37. // True if the file path exists.
  38. file.exists = function() {
  39. var filepath = path.join.apply(path, arguments);
  40. return fs.existsSync(filepath);
  41. };
  42. // Return an array of all file paths that match the given wildcard patterns.
  43. file.expand = function() {
  44. var args = _.toArray(arguments);
  45. // If the first argument is an options object, save those options to pass
  46. // into the File.prototype.glob.sync method.
  47. var options = _.isPlainObject(args[0]) ? args.shift() : {};
  48. // Use the first argument if it's an Array, otherwise convert the arguments
  49. // object to an array and use that.
  50. var patterns = Array.isArray(args[0]) ? args[0] : args;
  51. // Return empty set if there are no patterns or filepaths.
  52. if (patterns.length === 0) { return []; }
  53. // Return all matching filepaths.
  54. var matches = processPatterns(patterns, function(pattern) {
  55. // Find all matching files for this pattern.
  56. return glob.sync(pattern, options);
  57. });
  58. // Filter result set?
  59. if (options.filter) {
  60. matches = matches.filter(function(filepath) {
  61. filepath = path.join(options.cwd || '', filepath);
  62. try {
  63. if (typeof options.filter === 'function') {
  64. return options.filter(filepath);
  65. } else {
  66. // If the file is of the right type and exists, this should work.
  67. return fs.statSync(filepath)[options.filter]();
  68. }
  69. } catch(e) {
  70. // Otherwise, it's probably not the right type.
  71. return false;
  72. }
  73. });
  74. }
  75. return matches;
  76. };
  77. // Build a multi task "files" object dynamically.
  78. file.expandMapping = function(patterns, destBase, options) {
  79. options = _.defaults({}, options, {
  80. rename: function(destBase, destPath) {
  81. return path.join(destBase || '', destPath);
  82. }
  83. });
  84. var files = [];
  85. var fileByDest = {};
  86. // Find all files matching pattern, using passed-in options.
  87. file.expand(options, patterns).forEach(function(src) {
  88. var destPath = src;
  89. // Flatten?
  90. if (options.flatten) {
  91. destPath = path.basename(destPath);
  92. }
  93. // Change the extension?
  94. if (options.ext) {
  95. destPath = destPath.replace(/(\.[^\/]*)?$/, options.ext);
  96. }
  97. // Generate destination filename.
  98. var dest = options.rename(destBase, destPath, options);
  99. // Prepend cwd to src path if necessary.
  100. if (options.cwd) { src = path.join(options.cwd, src); }
  101. // Normalize filepaths to be unix-style.
  102. dest = dest.replace(pathSeparatorRe, '/');
  103. src = src.replace(pathSeparatorRe, '/');
  104. // Map correct src path to dest path.
  105. if (fileByDest[dest]) {
  106. // If dest already exists, push this src onto that dest's src array.
  107. fileByDest[dest].src.push(src);
  108. } else {
  109. // Otherwise create a new src-dest file mapping object.
  110. files.push({
  111. src: [src],
  112. dest: dest,
  113. });
  114. // And store a reference for later use.
  115. fileByDest[dest] = files[files.length - 1];
  116. }
  117. });
  118. return files;
  119. };
  120. // reusing bits of grunt's multi-task source normalization
  121. file.normalizeFilesArray = function(data) {
  122. var files = [];
  123. data.forEach(function(obj) {
  124. var prop;
  125. if ('src' in obj || 'dest' in obj) {
  126. files.push(obj);
  127. }
  128. });
  129. if (files.length === 0) {
  130. return [];
  131. }
  132. files = _(files).chain().forEach(function(obj) {
  133. if (!('src' in obj) || !obj.src) { return; }
  134. // Normalize .src properties to flattened array.
  135. if (Array.isArray(obj.src)) {
  136. obj.src = _.flatten(obj.src);
  137. } else {
  138. obj.src = [obj.src];
  139. }
  140. }).map(function(obj) {
  141. // Build options object, removing unwanted properties.
  142. var expandOptions = _.extend({}, obj);
  143. delete expandOptions.src;
  144. delete expandOptions.dest;
  145. // Expand file mappings.
  146. if (obj.expand) {
  147. return file.expandMapping(obj.src, obj.dest, expandOptions).map(function(mapObj) {
  148. // Copy obj properties to result.
  149. var result = _.extend({}, obj);
  150. // Make a clone of the orig obj available.
  151. result.orig = _.extend({}, obj);
  152. // Set .src and .dest, processing both as templates.
  153. result.src = mapObj.src;
  154. result.dest = mapObj.dest;
  155. // Remove unwanted properties.
  156. ['expand', 'cwd', 'flatten', 'rename', 'ext'].forEach(function(prop) {
  157. delete result[prop];
  158. });
  159. return result;
  160. });
  161. }
  162. // Copy obj properties to result, adding an .orig property.
  163. var result = _.extend({}, obj);
  164. // Make a clone of the orig obj available.
  165. result.orig = _.extend({}, obj);
  166. if ('src' in result) {
  167. // Expose an expand-on-demand getter method as .src.
  168. Object.defineProperty(result, 'src', {
  169. enumerable: true,
  170. get: function fn() {
  171. var src;
  172. if (!('result' in fn)) {
  173. src = obj.src;
  174. // If src is an array, flatten it. Otherwise, make it into an array.
  175. src = Array.isArray(src) ? _.flatten(src) : [src];
  176. // Expand src files, memoizing result.
  177. fn.result = file.expand(expandOptions, src);
  178. }
  179. return fn.result;
  180. }
  181. });
  182. }
  183. if ('dest' in result) {
  184. result.dest = obj.dest;
  185. }
  186. return result;
  187. }).flatten().value();
  188. return files;
  189. };