vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
7.2 KiB

  1. var fs = require('fs');
  2. var async = require('async');
  3. var gulp = require('gulp');
  4. var eslint = require('gulp-eslint');
  5. var gutil = require('gulp-util');
  6. var concat = require('gulp-concat');
  7. var cleanCSS = require('gulp-clean-css');
  8. var rename = require("gulp-rename");
  9. var webpack = require('webpack');
  10. var uglify = require('uglify-js');
  11. var rimraf = require('rimraf');
  12. var argv = require('yargs').argv;
  13. var child_exec = require('child_process').exec;
  14. var ENTRY = './index.js';
  15. var HEADER = './lib/header.js';
  16. var DIST = __dirname + '/dist';
  17. var VIS_JS = 'vis.js';
  18. var VIS_MAP = 'vis.map';
  19. var VIS_MIN_JS = 'vis.min.js';
  20. var VIS_CSS = 'vis.css';
  21. var VIS_MIN_CSS = 'vis.min.css';
  22. var INDIVIDUAL_JS_BUNDLES = [
  23. {entry: './index-timeline-graph2d.js', filename: 'vis-timeline-graph2d.min.js'},
  24. {entry: './index-network.js', filename: 'vis-network.min.js'},
  25. {entry: './index-graph3d.js', filename: 'vis-graph3d.min.js'}
  26. ];
  27. var INDIVIDUAL_CSS_BUNDLES = [
  28. {entry: ['./lib/shared/**/*.css', './lib/timeline/**/*.css'], filename: 'vis-timeline-graph2d.min.css'},
  29. {entry: ['./lib/shared/**/*.css', './lib/network/**/*.css'], filename: 'vis-network.min.css'}
  30. ];
  31. /**
  32. * Generate banner with today's date and correct version
  33. *
  34. * @returns {string} banner text
  35. */
  36. function createBanner() {
  37. var today = gutil.date(new Date(), 'yyyy-mm-dd'); // today, formatted as yyyy-mm-dd
  38. var version = require('./package.json').version;
  39. return String(fs.readFileSync(HEADER))
  40. .replace('@@date', today)
  41. .replace('@@version', version);
  42. }
  43. var bannerPlugin = new webpack.BannerPlugin({
  44. banner: createBanner(),
  45. entryOnly: true,
  46. raw: true
  47. });
  48. var webpackModule = {
  49. loaders: [
  50. {
  51. test: /\.js$/,
  52. exclude: /node_modules/,
  53. loader: 'babel-loader',
  54. query: {
  55. cacheDirectory: true, // use cache to improve speed
  56. babelrc: true // use the .baberc file
  57. }
  58. }
  59. ],
  60. // exclude requires of moment.js language files
  61. wrappedContextRegExp: /$^/
  62. };
  63. var webpackConfig = {
  64. entry: ENTRY,
  65. output: {
  66. library: 'vis',
  67. libraryTarget: 'umd',
  68. path: DIST,
  69. filename: VIS_JS,
  70. sourcePrefix: ' '
  71. },
  72. module: webpackModule,
  73. plugins: [ bannerPlugin ],
  74. cache: true,
  75. // generate details sourcempas of webpack modules
  76. devtool: 'source-map'
  77. //debug: true,
  78. //bail: true
  79. };
  80. var uglifyConfig = {
  81. outSourceMap: VIS_MAP,
  82. output: {
  83. comments: /@license/
  84. }
  85. };
  86. // create a single instance of the compiler to allow caching
  87. var compiler = webpack(webpackConfig);
  88. /**
  89. * Callback for handling errors for a compiler run
  90. *
  91. * @param {object} err
  92. * @param {objects} stats
  93. */
  94. function handleCompilerCallback (err, stats) {
  95. if (err) {
  96. gutil.log(err.toString());
  97. }
  98. if (stats && stats.compilation && stats.compilation.errors) {
  99. // output soft errors
  100. stats.compilation.errors.forEach(function (err) {
  101. gutil.log(err.toString());
  102. });
  103. if (err || stats.compilation.errors.length > 0) {
  104. gutil.beep(); // TODO: this does not work on my system
  105. }
  106. }
  107. }
  108. // clean the dist/img directory
  109. gulp.task('clean', function (cb) {
  110. rimraf(DIST + '/img', cb);
  111. });
  112. gulp.task('bundle-js', function (cb) {
  113. // update the banner contents (has a date in it which should stay up to date)
  114. bannerPlugin.banner = createBanner();
  115. compiler.run(function (err, stats) {
  116. handleCompilerCallback(err, stats);
  117. cb();
  118. });
  119. });
  120. // create individual bundles for timeline+graph2d, network, graph3d
  121. gulp.task('bundle-js-individual', function (cb) {
  122. // update the banner contents (has a date in it which should stay up to date)
  123. bannerPlugin.banner = createBanner();
  124. async.each(INDIVIDUAL_JS_BUNDLES, function (item, callback) {
  125. var webpackTimelineConfig = {
  126. entry: item.entry,
  127. output: {
  128. library: 'vis',
  129. libraryTarget: 'umd',
  130. path: DIST,
  131. filename: item.filename,
  132. sourcePrefix: ' '
  133. },
  134. module: webpackModule,
  135. plugins: [ bannerPlugin, new webpack.optimize.UglifyJsPlugin() ],
  136. cache: true
  137. };
  138. var compiler = webpack(webpackTimelineConfig);
  139. compiler.run(function (err, stats) {
  140. handleCompilerCallback(err, stats);
  141. callback();
  142. });
  143. }, cb);
  144. });
  145. // bundle and minify css
  146. gulp.task('bundle-css', function () {
  147. return gulp.src('./lib/**/*.css')
  148. .pipe(concat(VIS_CSS))
  149. .pipe(gulp.dest(DIST))
  150. // TODO: nicer to put minifying css in a separate task?
  151. .pipe(cleanCSS())
  152. .pipe(rename(VIS_MIN_CSS))
  153. .pipe(gulp.dest(DIST));
  154. });
  155. // bundle and minify individual css
  156. gulp.task('bundle-css-individual', function (cb) {
  157. async.each(INDIVIDUAL_CSS_BUNDLES, function (item, callback) {
  158. return gulp.src(item.entry)
  159. .pipe(concat(item.filename))
  160. .pipe(cleanCSS())
  161. .pipe(rename(item.filename))
  162. .pipe(gulp.dest(DIST))
  163. .on('end', callback);
  164. }, cb);
  165. });
  166. gulp.task('copy', ['clean'], function () {
  167. var network = gulp.src('./lib/network/img/**/*')
  168. .pipe(gulp.dest(DIST + '/img/network'));
  169. return network;
  170. });
  171. gulp.task('minify', ['bundle-js'], function (cb) {
  172. var result = uglify.minify([DIST + '/' + VIS_JS], uglifyConfig);
  173. // note: we add a newline '\n' to the end of the minified file to prevent
  174. // any issues when concatenating the file downstream (the file ends
  175. // with a comment).
  176. fs.writeFileSync(DIST + '/' + VIS_MIN_JS, result.code + '\n');
  177. fs.writeFileSync(DIST + '/' + VIS_MAP, result.map.replace(/"\.\/dist\//g, '"'));
  178. cb();
  179. });
  180. gulp.task('bundle', ['bundle-js', 'bundle-js-individual', 'bundle-css', 'bundle-css-individual', 'copy']);
  181. // read command line arguments --bundle and --minify
  182. var bundle = 'bundle' in argv;
  183. var minify = 'minify' in argv;
  184. var watchTasks = [];
  185. if (bundle || minify) {
  186. // do bundling and/or minifying only when specified on the command line
  187. watchTasks = [];
  188. if (bundle) watchTasks.push('bundle');
  189. if (minify) watchTasks.push('minify');
  190. }
  191. else {
  192. // by default, do both bundling and minifying
  193. watchTasks = ['bundle', 'minify'];
  194. }
  195. // The watch task (to automatically rebuild when the source code changes)
  196. gulp.task('watch', watchTasks, function () {
  197. gulp.watch(['index.js', 'lib/**/*'], watchTasks);
  198. });
  199. //
  200. // Linting usage:
  201. //
  202. // > gulp lint
  203. // or > npm run lint
  204. //
  205. gulp.task('lint', function () {
  206. return gulp.src(['lib/**/*.js', '!node_modules/**'])
  207. .pipe(eslint())
  208. .pipe(eslint.format())
  209. .pipe(eslint.failAfterError());
  210. });
  211. // Generate the documentation files
  212. gulp.task('docs', function(cb) {
  213. var targetDir = 'gen/docs';
  214. // Not sure if this is the best way to handle 'cb'; at least it works.
  215. var hasError = false;
  216. var onError = function(error) {
  217. if (error !== undefined && error !== null) {
  218. console.error('Error while running task: ' + error);
  219. hasError = true;
  220. cb();
  221. }
  222. }
  223. rimraf(__dirname + '/' + targetDir, onError); // Clean up previous generation
  224. if (!hasError) {
  225. var params = '-c ./jsdoc.json -r -t docs -d ' + targetDir;
  226. child_exec('node ./node_modules/jsdoc/jsdoc.js ' + params + ' lib', undefined, cb);
  227. }
  228. });
  229. // The default task (called when you run `gulp`)
  230. gulp.task('default', ['clean', 'bundle', 'minify']);