feat(bpmn-js): build modeler / navigated viewer bundle

Closes #154
This commit is contained in:
Nico Rehwaldt 2015-01-11 23:42:27 +01:00
parent 5735a8bc3a
commit 92141ccd43
5 changed files with 196 additions and 110 deletions

View File

@ -9,43 +9,15 @@ module.exports = function(grunt) {
// any of [ 'PhantomJS', 'Chrome', 'Firefox', 'IE']
var TEST_BROWSERS = ((process.env.TEST_BROWSERS || '').replace(/^\s+|\s+$/, '') || 'PhantomJS').split(/\s*,\s*/g);
function extractSourceMap(file) {
var content = grunt.file.read(file, { encoding: 'utf-8' });
var match = /\/\/# sourceMappingURL=data:application\/json;base64,(.*)/.exec(content);
if (match) {
var b = new Buffer(match[1] + '==', 'base64');
var s = b.toString();
s = s.replace(/\\\\/g, '/'); // convert \\ -> /
var dir = __dirname;
var dirPattern = dir.replace(/\\/g, '/').replace(/\./g, '\\.') + '/';
var pattern = new RegExp(dirPattern, 'g');
s = s.replace(pattern, '');
grunt.file.write('tmp/sourceMap.json', s, { encoding: 'utf-8' });
return 'tmp/sourceMap.json';
} else {
return null;
}
}
// project configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
config: {
sources: 'lib',
tests: 'test',
dist: 'dist',
bowerDist: '../bower-bpmn-js'
dist: '../bower-bpmn-js'
},
jshint: {
@ -80,47 +52,6 @@ module.exports = function(grunt) {
}
},
browserify: {
options: {
browserifyOptions: {
builtins: false
},
bundleOptions: {
detectGlobals: false,
insertGlobalVars: [],
debug: true
}
},
bowerViewer: {
files: {
'<%= config.bowerDist %>/bpmn-viewer.js': [ '<%= config.sources %>/Viewer.js' ]
},
options: {
browserifyOptions: {
builtins: false
},
bundleOptions: {
standalone: 'BpmnJS',
detectGlobals: false,
insertGlobalVars: [],
debug: false
},
transform: [
[ 'exposify', {
global: true,
expose: {
sax: 'sax',
snapsvg: 'Snap',
lodash: '_',
jquery: '$',
'jquery-mousewheel': '$'
}
} ]
]
}
}
},
jsdoc: {
dist: {
src: [ '<%= config.sources %>/**/*.js' ],
@ -131,52 +62,49 @@ module.exports = function(grunt) {
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> - ' +
'http://bpmn.io/license - ' +
'https://github.com/bpmn-io/bpmn-js */',
sourceMap: true,
sourceMapIncludeSources: true,
sourceMapIn: function(file) {
return extractSourceMap(file);
bundle: {
viewer: {
name: 'bpmn-viewer',
src: '<%= config.sources %>/Viewer.js',
dest: '<%= config.dist %>'
},
navigated_viewer: {
name: 'bpmn-navigated-viewer',
src: '<%= config.sources %>/NavigatedViewer.js',
dest: '<%= config.dist %>'
},
modeler: {
name: 'bpmn-modeler',
src: '<%= config.sources %>/Modeler.js',
dest: '<%= config.dist %>'
}
},
bowerViewer: {
files: {
'<%= config.bowerDist %>/bpmn-viewer.min.js': [ '<%= config.bowerDist %>/bpmn-viewer.js' ]
}
copy: {
bpmn_js: {
files: [
{ expand: true, cwd: 'assets', src: [ '**' ], dest: '<%= config.dist %>/assets' }
]
},
diagram_js: {
files: [
{ expand: true, cwd: 'node_modules/diagram-js/assets', src: [ '**' ], dest: '<%= config.dist %>/assets' }
]
}
}
});
grunt.loadTasks('tasks');
// tasks
grunt.registerTask('test', [ 'karma:single' ]);
/////
//
// the main build task that bundles bpmn-js files
//
// valid executions are
//
// * build -> build:all
// * build:all -> build:bower
// * build:bower
//
grunt.registerTask('build', function(target) {
if (target === 'bower') {
return grunt.task.run([ 'browserify:bowerViewer', 'uglify:bowerViewer' ]);
}
if (!target || target === 'all') {
return grunt.task.run([ 'build:bower' ]);
}
});
grunt.registerTask('auto-test', [ 'karma:unit' ]);
grunt.registerTask('build', [ 'bundle', 'copy' ]);
grunt.registerTask('default', [ 'jshint', 'test', 'build', 'jsdoc' ]);
};

View File

@ -31,12 +31,14 @@
"license": "http://bpmn.io/license",
"devDependencies": {
"brfs": "^1.2.0",
"browserify": "^8.1.0",
"bundle-collapser": "^1.1.1",
"derequire": "^1.2.0",
"diagram-js": "^0.7.0",
"exposify": "https://github.com/Nikku/exposify/archive/v0.2.0-transform-arguments-0.tar.gz",
"grunt": "^0.4.4",
"grunt-browserify": "^2.1.2",
"grunt-contrib-copy": "^0.7.0",
"grunt-contrib-jshint": "^0.7.2",
"grunt-contrib-uglify": "https://github.com/gruntjs/grunt-contrib-uglify/archive/master.tar.gz",
"grunt-jsdoc": "^0.5.1",
"grunt-karma": "^0.8.0",
"grunt-release": "^0.7.0",
@ -50,7 +52,9 @@
"karma-jasmine": "https://github.com/Nikku/karma-jasmine/archive/jasmine-v2.0.0-latest-1.tar.gz",
"karma-phantomjs-launcher": "^0.1.2",
"load-grunt-tasks": "^0.3.0",
"time-grunt": "^0.3.2"
"source-map-concat": "^0.4.0",
"time-grunt": "^0.3.2",
"uglify-js": "^2.4.16"
},
"dependencies": {
"bpmn-moddle": "^0.4.0",

1
tasks/banner-min.txt Normal file
View File

@ -0,0 +1 @@
/*! <%= pkg.name %> - <%= config.variant %> v<%= pkg.version %> | (c) 2014, 2015 camunda Services GmbH | bpmn.io/license */

12
tasks/banner.txt Normal file
View File

@ -0,0 +1,12 @@
/*!
* <%= pkg.name %> - <%= config.variant %> v<%= pkg.version %>
* Copyright 2014, 2015 camunda Services GmbH and other contributors
*
* Released under the bpmn.io license
* http://bpmn.io/license
*
* Source Code: https://github.com/bpmn-io/bpmn-js
*
* Date: <%= grunt.template.today("yyyy-mm-dd") %>
*/

141
tasks/bundle.js Normal file
View File

@ -0,0 +1,141 @@
var browserify = require('browserify'),
derequire = require('derequire'),
UglifyJS = require('uglify-js'),
exposify = require('exposify'),
collapse = require('bundle-collapser/plugin'),
concat = require('source-map-concat'),
fs = require('fs'),
path = require('path');
var BANNER = fs.readFileSync(__dirname + '/banner.txt', 'utf8'),
BANNER_MIN = fs.readFileSync(__dirname + '/banner-min.txt', 'utf8');
var EXTERNALS = {
sax: 'sax',
snapsvg: 'Snap',
lodash: '_',
hammerjs: 'Hammer',
jquery: '$',
'jquery-mousewheel': '$'
};
function extractSourceMap(content) {
var SOURCE_MAP_HEADER = '//# sourceMappingURL=data:application/json;base64,';
var idx = content.indexOf(SOURCE_MAP_HEADER),
map, code;
if (idx !== -1) {
code = content.substring(0, idx);
map = content.substring(idx + SOURCE_MAP_HEADER.length);
map = new Buffer(map, 'base64').toString();
map = map.replace(/\\\\/g, '/'); // convert \\ -> /
var dir = __dirname;
var dirPattern = dir.replace(/\\/g, '/').replace(/\./g, '\\.') + '/';
var pattern = new RegExp(dirPattern, 'g');
map = map.replace(pattern, '');
return {
code: code,
map: JSON.parse(map)
};
} else {
throw new Error('no attached source map');
}
}
function uglify(bundle, preamble) {
return UglifyJS.minify(bundle.code, {
fromString: true,
output: {
preamble: preamble
}
});
}
module.exports = function(grunt) {
grunt.registerMultiTask('bundle', function(target) {
var data = this.data,
variant = data.name,
dest = data.dest,
src = path.resolve(data.src);
grunt.config.set('config.variant', variant);
var done = this.async();
var browserifyOptions = {
builtins: false,
standalone: 'BpmnJS',
detectGlobals: false,
insertGlobalVars: [],
debug: true
};
var exposifyOptions = {
global: true,
expose: EXTERNALS
};
var targetFileBase = path.join(dest, variant);
var banner = grunt.template.process(BANNER, grunt.config.get()),
bannerMin = grunt.template.process(BANNER_MIN, grunt.config.get());
browserify(browserifyOptions)
.transform(exposify, exposifyOptions)
.plugin(collapse)
.add(src)
.bundle(function(err, result) {
if (err) {
return done(err);
}
var bundled, minified;
bundled = extractSourceMap(derequire(result.toString('utf8')));
try {
minified = uglify(bundled, bannerMin);
} catch (e) {
return done(e);
}
var bannerBundled;
try {
bannerBundled = concat([ bundled ])
.prepend(banner + '\n')
.add('//# sourceMappingURL=' + variant + '.js.map')
.toStringWithSourceMap();
} catch (e) {
console.error(e.stack);
throw e;
}
grunt.file.write(targetFileBase + '.js', bannerBundled.code, 'utf8');
grunt.file.write(targetFileBase + '.js.map', bannerBundled.map, 'utf8');
grunt.file.write(targetFileBase + '.min.js', minified.code, 'utf8');
done();
});
});
};