Gruntfile.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. module.exports = function(grunt) {
  2. 'use strict';
  3. var bower = grunt.file.readJSON('bower.json');
  4. var components = [];
  5. for (var i in bower.concat.app) {
  6. components.push('components/' + bower.concat.app[i] + '/**/*.js');
  7. }
  8. components.push('components/' + 'webaudiorecorder/lib/WebAudioRecorder.js');
  9. var libtextsecurecomponents = [];
  10. for (i in bower.concat.libtextsecure) {
  11. libtextsecurecomponents.push('components/' + bower.concat.libtextsecure[i] + '/**/*.js');
  12. }
  13. grunt.initConfig({
  14. pkg: grunt.file.readJSON('package.json'),
  15. concat: {
  16. components: {
  17. src: components,
  18. dest: 'js/components.js',
  19. },
  20. libtextsecurecomponents: {
  21. src: libtextsecurecomponents,
  22. dest: 'libtextsecure/components.js',
  23. },
  24. test: {
  25. src: [
  26. 'components/mocha/mocha.js',
  27. 'components/chai/chai.js',
  28. 'test/_test.js'
  29. ],
  30. dest: 'test/test.js',
  31. },
  32. //TODO: Move errors back down?
  33. libtextsecure: {
  34. options: {
  35. banner: ";(function() {\n",
  36. footer: "})();\n",
  37. },
  38. src: [
  39. 'libtextsecure/errors.js',
  40. 'libtextsecure/libsignal-protocol.js',
  41. 'libtextsecure/protocol_wrapper.js',
  42. 'libtextsecure/crypto.js',
  43. 'libtextsecure/storage.js',
  44. 'libtextsecure/storage/user.js',
  45. 'libtextsecure/storage/groups.js',
  46. 'libtextsecure/protobufs.js',
  47. 'libtextsecure/websocket-resources.js',
  48. 'libtextsecure/helpers.js',
  49. 'libtextsecure/stringview.js',
  50. 'libtextsecure/event_target.js',
  51. 'libtextsecure/api.js',
  52. 'libtextsecure/account_manager.js',
  53. 'libtextsecure/message_receiver.js',
  54. 'libtextsecure/outgoing_message.js',
  55. 'libtextsecure/sendmessage.js',
  56. 'libtextsecure/sync_request.js',
  57. 'libtextsecure/contacts_parser.js',
  58. 'libtextsecure/ProvisioningCipher.js',
  59. ],
  60. dest: 'js/libtextsecure.js',
  61. },
  62. libtextsecuretest: {
  63. src: [
  64. 'components/jquery/dist/jquery.js',
  65. 'components/mock-socket/dist/mock-socket.js',
  66. 'components/mocha/mocha.js',
  67. 'components/chai/chai.js',
  68. 'libtextsecure/test/_test.js'
  69. ],
  70. dest: 'libtextsecure/test/test.js',
  71. }
  72. },
  73. sass: {
  74. stylesheets: {
  75. files: {
  76. 'stylesheets/manifest.css': 'stylesheets/manifest.scss',
  77. 'stylesheets/options.css': 'stylesheets/options.scss'
  78. }
  79. }
  80. },
  81. jshint: {
  82. files: [
  83. 'Gruntfile.js',
  84. 'js/**/*.js',
  85. '!js/libtextsecure.js',
  86. '!js/WebAudioRecorderMp3.js',
  87. '!js/Mp3LameEncoder.min.js',
  88. '!js/libsignal-protocol-worker.js',
  89. '!js/components.js',
  90. '!js/signal_protocol_store.js',
  91. '_locales/**/*'
  92. ],
  93. options: { jshintrc: '.jshintrc' },
  94. },
  95. dist: {
  96. src: [
  97. 'manifest.json',
  98. 'background.html',
  99. 'index.html',
  100. 'options.html',
  101. '_locales/**',
  102. 'protos/*',
  103. 'js/**',
  104. 'stylesheets/*.css',
  105. '!js/register.js'
  106. ],
  107. res: [
  108. 'audio/**',
  109. 'images/**',
  110. 'fonts/*',
  111. ]
  112. },
  113. copy: {
  114. res: {
  115. files: [{ expand: true, dest: 'dist/', src: ['<%= dist.res %>'] }],
  116. },
  117. src: {
  118. files: [{ expand: true, dest: 'dist/', src: ['<%= dist.src %>'] }],
  119. options: {
  120. process: function(content, srcpath) {
  121. if (srcpath.match('background.js')) {
  122. return content.replace(
  123. /textsecure-service-staging.whispersystems.org/g,
  124. 'cable-service-ca.pantelegrafo.cable.im');
  125. } else if (srcpath.match('expire.js')) {
  126. var gitinfo = grunt.config.get('gitinfo');
  127. var commited = gitinfo.local.branch.current.lastCommitTime;
  128. var time = Date.parse(commited) + 1000 * 60 * 60 * 24 * 90;
  129. return content.replace(
  130. /var BUILD_EXPIRATION = 0/,
  131. "var BUILD_EXPIRATION = " + time
  132. );
  133. } else {
  134. return content;
  135. }
  136. }
  137. }
  138. }
  139. },
  140. jscs: {
  141. all: {
  142. src: [
  143. 'Gruntfile',
  144. 'js/**/*.js',
  145. '!js/libtextsecure.js',
  146. '!js/WebAudioRecorderMp3.js',
  147. '!js/Mp3LameEncoder.min.js',
  148. '!js/libsignal-protocol-worker.js',
  149. '!js/components.js',
  150. 'test/**/*.js',
  151. '!test/blanket_mocha.js',
  152. '!test/test.js',
  153. ]
  154. }
  155. },
  156. watch: {
  157. sass: {
  158. files: ['./stylesheets/*.scss'],
  159. tasks: ['sass']
  160. },
  161. libtextsecure: {
  162. files: ['./libtextsecure/*.js', './libtextsecure/storage/*.js'],
  163. tasks: ['concat:libtextsecure']
  164. },
  165. dist: {
  166. files: ['<%= dist.src %>', '<%= dist.res %>'],
  167. tasks: ['copy_dist']
  168. },
  169. scripts: {
  170. files: ['<%= jshint.files %>', './js/**/*.js'],
  171. tasks: ['jshint']
  172. },
  173. style: {
  174. files: ['<%= jscs.all.src %>', './js/**/*.js'],
  175. tasks: ['jscs']
  176. },
  177. },
  178. connect: {
  179. server: {
  180. options: {
  181. base: '.',
  182. port: 9999
  183. }
  184. }
  185. },
  186. 'saucelabs-mocha': {
  187. all: {
  188. options: {
  189. urls: [
  190. 'http://127.0.0.1:9999/test/index.html',
  191. 'http://127.0.0.1:9999/libtextsecure/test/index.html',
  192. ],
  193. build: process.env.TRAVIS_JOB_ID,
  194. browsers: [
  195. { browserName: 'chrome', version: '41' },
  196. { platform: 'linux', browserName: 'firefox', version: '34' }
  197. ],
  198. testname: 'TextSecure-Browser Tests',
  199. 'max-duration': 300,
  200. statusCheckAttempts: 200
  201. }
  202. }
  203. },
  204. exec: {
  205. 'tx-pull': {
  206. cmd: 'tx pull'
  207. }
  208. },
  209. gitinfo: {} // to be populated by grunt gitinfo
  210. });
  211. Object.keys(grunt.config.get('pkg').devDependencies).forEach(function(key) {
  212. if (/^grunt(?!(-cli)?$)/.test(key)) { // ignore grunt and grunt-cli
  213. grunt.loadNpmTasks(key);
  214. }
  215. });
  216. // Transifex does not understand placeholders, so this task patches all non-en
  217. // locales with missing placeholders
  218. grunt.registerTask('locale-patch', function(){
  219. var en = grunt.file.readJSON('_locales/en/messages.json');
  220. grunt.file.recurse('_locales', function(abspath, rootdir, subdir, filename){
  221. if (subdir === 'en' || filename !== 'messages.json'){
  222. return;
  223. }
  224. var messages = grunt.file.readJSON(abspath);
  225. for (var key in messages){
  226. if (en[key] !== undefined && messages[key] !== undefined){
  227. if (en[key].placeholders !== undefined && messages[key].placeholders === undefined){
  228. messages[key].placeholders = en[key].placeholders;
  229. }
  230. }
  231. }
  232. grunt.file.write(abspath, JSON.stringify(messages, null, 4) + '\n');
  233. });
  234. });
  235. grunt.registerTask('tx', ['exec:tx-pull', 'locale-patch']);
  236. grunt.registerTask('dev', ['default', 'connect', 'watch']);
  237. grunt.registerTask('test', ['jshint', 'jscs', 'connect', 'saucelabs-mocha']);
  238. grunt.registerTask('copy_dist', ['gitinfo', 'copy']);
  239. grunt.registerTask('default', ['concat', 'sass', 'copy_dist']);
  240. };