Gruntfile.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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. 'conversation.html',
  101. 'options.html',
  102. '_locales/**',
  103. 'protos/*',
  104. 'js/**',
  105. 'stylesheets/*.css',
  106. '!js/register.js'
  107. ],
  108. res: [
  109. 'audio/**',
  110. 'images/**',
  111. 'fonts/*',
  112. ]
  113. },
  114. copy: {
  115. res: {
  116. files: [{ expand: true, dest: 'dist/', src: ['<%= dist.res %>'] }],
  117. },
  118. src: {
  119. files: [{ expand: true, dest: 'dist/', src: ['<%= dist.src %>'] }],
  120. options: {
  121. process: function(content, srcpath) {
  122. if (srcpath.match('background.js')) {
  123. return content.replace(
  124. /textsecure-service-staging.whispersystems.org/g,
  125. 'textsecure-service-ca.whispersystems.org').replace(
  126. /whispersystems-textsecure-attachments-staging.s3.amazonaws.com/g,
  127. 'whispersystems-textsecure-attachments.s3.amazonaws.com');
  128. } else if (srcpath.match('expire.js')) {
  129. var gitinfo = grunt.config.get('gitinfo');
  130. var commited = gitinfo.local.branch.current.lastCommitTime;
  131. var time = Date.parse(commited) + 1000 * 60 * 60 * 24 * 90;
  132. return content.replace(
  133. /var BUILD_EXPIRATION = 0/,
  134. "var BUILD_EXPIRATION = " + time
  135. );
  136. } else {
  137. return content;
  138. }
  139. }
  140. }
  141. }
  142. },
  143. jscs: {
  144. all: {
  145. src: [
  146. 'Gruntfile',
  147. 'js/**/*.js',
  148. '!js/libtextsecure.js',
  149. '!js/WebAudioRecorderMp3.js',
  150. '!js/Mp3LameEncoder.min.js',
  151. '!js/libsignal-protocol-worker.js',
  152. '!js/components.js',
  153. 'test/**/*.js',
  154. '!test/blanket_mocha.js',
  155. '!test/test.js',
  156. ]
  157. }
  158. },
  159. watch: {
  160. sass: {
  161. files: ['./stylesheets/*.scss'],
  162. tasks: ['sass']
  163. },
  164. libtextsecure: {
  165. files: ['./libtextsecure/*.js', './libtextsecure/storage/*.js'],
  166. tasks: ['concat:libtextsecure']
  167. },
  168. dist: {
  169. files: ['<%= dist.src %>', '<%= dist.res %>'],
  170. tasks: ['copy_dist']
  171. },
  172. scripts: {
  173. files: ['<%= jshint.files %>', './js/**/*.js'],
  174. tasks: ['jshint']
  175. },
  176. style: {
  177. files: ['<%= jscs.all.src %>', './js/**/*.js'],
  178. tasks: ['jscs']
  179. },
  180. },
  181. connect: {
  182. server: {
  183. options: {
  184. base: '.',
  185. port: 9999
  186. }
  187. }
  188. },
  189. 'saucelabs-mocha': {
  190. all: {
  191. options: {
  192. urls: [
  193. 'http://127.0.0.1:9999/test/index.html',
  194. 'http://127.0.0.1:9999/libtextsecure/test/index.html',
  195. ],
  196. build: process.env.TRAVIS_JOB_ID,
  197. browsers: [
  198. { browserName: 'chrome', version: '41' },
  199. { platform: 'linux', browserName: 'firefox', version: '34' }
  200. ],
  201. testname: 'TextSecure-Browser Tests',
  202. 'max-duration': 300,
  203. statusCheckAttempts: 200
  204. }
  205. }
  206. },
  207. exec: {
  208. 'tx-pull': {
  209. cmd: 'tx pull'
  210. }
  211. },
  212. gitinfo: {} // to be populated by grunt gitinfo
  213. });
  214. Object.keys(grunt.config.get('pkg').devDependencies).forEach(function(key) {
  215. if (/^grunt(?!(-cli)?$)/.test(key)) { // ignore grunt and grunt-cli
  216. grunt.loadNpmTasks(key);
  217. }
  218. });
  219. // Transifex does not understand placeholders, so this task patches all non-en
  220. // locales with missing placeholders
  221. grunt.registerTask('locale-patch', function(){
  222. var en = grunt.file.readJSON('_locales/en/messages.json');
  223. grunt.file.recurse('_locales', function(abspath, rootdir, subdir, filename){
  224. if (subdir === 'en' || filename !== 'messages.json'){
  225. return;
  226. }
  227. var messages = grunt.file.readJSON(abspath);
  228. for (var key in messages){
  229. if (en[key] !== undefined && messages[key] !== undefined){
  230. if (en[key].placeholders !== undefined && messages[key].placeholders === undefined){
  231. messages[key].placeholders = en[key].placeholders;
  232. }
  233. }
  234. }
  235. grunt.file.write(abspath, JSON.stringify(messages, null, 4) + '\n');
  236. });
  237. });
  238. grunt.registerTask('tx', ['exec:tx-pull', 'locale-patch']);
  239. grunt.registerTask('dev', ['default', 'connect', 'watch']);
  240. grunt.registerTask('test', ['jshint', 'jscs', 'connect', 'saucelabs-mocha']);
  241. grunt.registerTask('copy_dist', ['gitinfo', 'copy']);
  242. grunt.registerTask('default', ['concat', 'sass', 'copy_dist']);
  243. };