gulpfile.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. var gulp = require('gulp');
  2. var concat = require('gulp-concat');
  3. var connect = require('gulp-connect');
  4. var eslint = require('gulp-eslint');
  5. var file = require('gulp-file');
  6. var insert = require('gulp-insert');
  7. var replace = require('gulp-replace');
  8. var size = require('gulp-size');
  9. var streamify = require('gulp-streamify');
  10. var uglify = require('gulp-uglify');
  11. var util = require('gulp-util');
  12. var zip = require('gulp-zip');
  13. var exec = require('child-process-promise').exec;
  14. var karma = require('karma');
  15. var browserify = require('browserify');
  16. var source = require('vinyl-source-stream');
  17. var merge = require('merge-stream');
  18. var collapse = require('bundle-collapser/plugin');
  19. var yargs = require('yargs');
  20. var path = require('path');
  21. var fs = require('fs');
  22. var htmllint = require('gulp-htmllint');
  23. var package = require('./package.json');
  24. var argv = yargs
  25. .option('force-output', {default: false})
  26. .option('silent-errors', {default: false})
  27. .option('verbose', {default: false})
  28. .argv
  29. var srcDir = './src/';
  30. var outDir = './dist/';
  31. var header = "/*!\n" +
  32. " * Chart.js\n" +
  33. " * http://chartjs.org/\n" +
  34. " * Version: {{ version }}\n" +
  35. " *\n" +
  36. " * Copyright " + (new Date().getFullYear()) + " Chart.js Contributors\n" +
  37. " * Released under the MIT license\n" +
  38. " * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md\n" +
  39. " */\n";
  40. if (argv.verbose) {
  41. util.log("Gulp running with options: " + JSON.stringify(argv, null, 2));
  42. }
  43. gulp.task('bower', bowerTask);
  44. gulp.task('build', buildTask);
  45. gulp.task('package', packageTask);
  46. gulp.task('watch', watchTask);
  47. gulp.task('lint', ['lint-html', 'lint-js']);
  48. gulp.task('lint-html', lintHtmlTask);
  49. gulp.task('lint-js', lintJsTask);
  50. gulp.task('docs', docsTask);
  51. gulp.task('test', ['lint', 'unittest']);
  52. gulp.task('size', ['library-size', 'module-sizes']);
  53. gulp.task('server', serverTask);
  54. gulp.task('unittest', unittestTask);
  55. gulp.task('library-size', librarySizeTask);
  56. gulp.task('module-sizes', moduleSizesTask);
  57. gulp.task('_open', _openTask);
  58. gulp.task('dev', ['server', 'default']);
  59. gulp.task('default', ['build', 'watch']);
  60. /**
  61. * Generates the bower.json manifest file which will be pushed along release tags.
  62. * Specs: https://github.com/bower/spec/blob/master/json.md
  63. */
  64. function bowerTask() {
  65. var json = JSON.stringify({
  66. name: package.name,
  67. description: package.description,
  68. homepage: package.homepage,
  69. license: package.license,
  70. version: package.version,
  71. main: outDir + "Chart.js",
  72. ignore: [
  73. '.github',
  74. '.codeclimate.yml',
  75. '.gitignore',
  76. '.npmignore',
  77. '.travis.yml',
  78. 'scripts'
  79. ]
  80. }, null, 2);
  81. return file('bower.json', json, { src: true })
  82. .pipe(gulp.dest('./'));
  83. }
  84. function buildTask() {
  85. var errorHandler = function (err) {
  86. if(argv.forceOutput) {
  87. var browserError = 'console.error("Gulp: ' + err.toString() + '")';
  88. ['Chart', 'Chart.min', 'Chart.bundle', 'Chart.bundle.min'].forEach(function(fileName) {
  89. fs.writeFileSync(outDir+fileName+'.js', browserError);
  90. });
  91. }
  92. if(argv.silentErrors) {
  93. util.log(util.colors.red('[Error]'), err.toString());
  94. this.emit('end');
  95. } else {
  96. throw err;
  97. }
  98. }
  99. var bundled = browserify('./src/chart.js', { standalone: 'Chart' })
  100. .plugin(collapse)
  101. .bundle()
  102. .on('error', errorHandler)
  103. .pipe(source('Chart.bundle.js'))
  104. .pipe(insert.prepend(header))
  105. .pipe(streamify(replace('{{ version }}', package.version)))
  106. .pipe(gulp.dest(outDir))
  107. .pipe(streamify(uglify()))
  108. .pipe(insert.prepend(header))
  109. .pipe(streamify(replace('{{ version }}', package.version)))
  110. .pipe(streamify(concat('Chart.bundle.min.js')))
  111. .pipe(gulp.dest(outDir));
  112. var nonBundled = browserify('./src/chart.js', { standalone: 'Chart' })
  113. .ignore('moment')
  114. .plugin(collapse)
  115. .bundle()
  116. .on('error', errorHandler)
  117. .pipe(source('Chart.js'))
  118. .pipe(insert.prepend(header))
  119. .pipe(streamify(replace('{{ version }}', package.version)))
  120. .pipe(gulp.dest(outDir))
  121. .pipe(streamify(uglify()))
  122. .pipe(insert.prepend(header))
  123. .pipe(streamify(replace('{{ version }}', package.version)))
  124. .pipe(streamify(concat('Chart.min.js')))
  125. .pipe(gulp.dest(outDir));
  126. return merge(bundled, nonBundled);
  127. }
  128. function packageTask() {
  129. return merge(
  130. // gather "regular" files landing in the package root
  131. gulp.src([outDir + '*.js', 'LICENSE.md']),
  132. // since we moved the dist files one folder up (package root), we need to rewrite
  133. // samples src="../dist/ to src="../ and then copy them in the /samples directory.
  134. gulp.src('./samples/**/*', { base: '.' })
  135. .pipe(streamify(replace(/src="((?:\.\.\/)+)dist\//g, 'src="$1')))
  136. )
  137. // finally, create the zip archive
  138. .pipe(zip('Chart.js.zip'))
  139. .pipe(gulp.dest(outDir));
  140. }
  141. function lintJsTask() {
  142. var files = [
  143. 'samples/**/*.html',
  144. 'samples/**/*.js',
  145. 'src/**/*.js',
  146. 'test/**/*.js'
  147. ];
  148. // NOTE(SB) codeclimate has 'complexity' and 'max-statements' eslint rules way too strict
  149. // compare to what the current codebase can support, and since it's not straightforward
  150. // to fix, let's turn them as warnings and rewrite code later progressively.
  151. var options = {
  152. rules: {
  153. 'complexity': [1, 10],
  154. 'max-statements': [1, 30]
  155. }
  156. };
  157. return gulp.src(files)
  158. .pipe(eslint(options))
  159. .pipe(eslint.format())
  160. .pipe(eslint.failAfterError());
  161. }
  162. function lintHtmlTask() {
  163. return gulp.src('samples/**/*.html')
  164. .pipe(htmllint({
  165. failOnError: true,
  166. }));
  167. }
  168. function docsTask(done) {
  169. const script = require.resolve('gitbook-cli/bin/gitbook.js');
  170. const cmd = process.execPath;
  171. exec([cmd, script, 'install', './'].join(' ')).then(() => {
  172. return exec([cmd, script, 'build', './', './dist/docs'].join(' '));
  173. }).catch((err) => {
  174. console.error(err.stdout);
  175. }).then(() => {
  176. done();
  177. });
  178. }
  179. function startTest() {
  180. return [
  181. {pattern: './test/fixtures/**/*.json', included: false},
  182. {pattern: './test/fixtures/**/*.png', included: false},
  183. './node_modules/moment/min/moment.min.js',
  184. './test/jasmine.index.js',
  185. './src/**/*.js',
  186. ].concat(
  187. argv.inputs ?
  188. argv.inputs.split(';') :
  189. ['./test/specs/**/*.js']
  190. );
  191. }
  192. function unittestTask(done) {
  193. new karma.Server({
  194. configFile: path.join(__dirname, 'karma.conf.js'),
  195. singleRun: !argv.watch,
  196. files: startTest(),
  197. args: {
  198. coverage: !!argv.coverage
  199. }
  200. },
  201. // https://github.com/karma-runner/gulp-karma/issues/18
  202. function(error) {
  203. error = error ? new Error('Karma returned with the error code: ' + error) : undefined;
  204. done(error);
  205. }).start();
  206. }
  207. function librarySizeTask() {
  208. return gulp.src('dist/Chart.bundle.min.js')
  209. .pipe(size({
  210. gzip: true
  211. }));
  212. }
  213. function moduleSizesTask() {
  214. return gulp.src(srcDir + '**/*.js')
  215. .pipe(uglify())
  216. .pipe(size({
  217. showFiles: true,
  218. gzip: true
  219. }));
  220. }
  221. function watchTask() {
  222. if (util.env.test) {
  223. return gulp.watch('./src/**', ['build', 'unittest', 'unittestWatch']);
  224. }
  225. return gulp.watch('./src/**', ['build']);
  226. }
  227. function serverTask() {
  228. connect.server({
  229. port: 8000
  230. });
  231. }
  232. // Convenience task for opening the project straight from the command line
  233. function _openTask() {
  234. exec('open http://localhost:8000');
  235. exec('subl .');
  236. }