hdjs
Version:
hdjs framework
193 lines (155 loc) • 6.13 kB
JavaScript
/**
* @fileOverview 负责合并amd modules为一个单文件。
*/
;
var requirejs = require('requirejs'),
fs = require('fs'),
path = require('path');
// convert relative path to absolute path.
function convert( name, _path, contents ) {
var rDefine = /(define\s*\(\s*('|").*?\2\s*,\s*\[)([\s\S]*?)\]/ig,
rDeps = /('|")(.*?)\1/g,
root = _path.substr( 0, _path.length - name.length - 3 ),
dir = path.dirname( _path ),
m, m2, deps, dep, _path2;
contents = contents.replace( rDefine, function( m, m1, m2, m3 ) {
return m1 + m3.replace( rDeps, function( m, m1, m2 ) {
m2 = path.join( dir, m2 );
m2 = path.relative( root, m2 );
m2 = m2.replace(/\\/g, '/');
return m1 + m2 + m1;
}) + ']';
});
return contents;
}
module.exports = function( grunt ) {
grunt.registerMultiTask( 'build', '合并amd modules为一个单文件', function() {
var done = this.async(),
options = this.options({
banner: '',
footer: '',
process: null,
builtin: {
dollar: false,
promise: false
}
}),
pkg = grunt.config.get('pkg'),
dest = this.data.dest,
config, flag, custom;
config = {
baseUrl: 'src',
name: '',
out: '',
// We have multiple minify steps
optimize: 'none',
// Include dependencies loaded with require
findNestedDependencies: true,
// Avoid breaking semicolons inserted by r.js
skipSemiColonInsertion: true,
wrap: {
startFile: 'build/intro.js',
endFile: 'build/outro.js'
},
rawText: {},
onBuildWrite: function( name, _path ) {
var compiled = convert.apply( null, arguments );
if ( options.process ) {
compiled = options.process( compiled, _path );
}
// 调整缩进
compiled = compiled.replace( /(^|\r\n|\r|\n)/g, '$1 ');
compiled = compiled.replace(/@version@/g, function() {
return pkg.version;
});
return compiled;
},
paths: [],
include: []
};
options = grunt.util._.extend( options, this.data );
config.name = 'webuploader';
if ( options.builtin.dollar ) {
config.rawText.dollar = 'define([\n' +
' \'./dollar-builtin\'\n' +
'], function( $ ) {\n' +
' return $;\n' +
'});';
}
if ( options.builtin.promise ) {
config.rawText.promise = 'define([\n' +
' \'./promise-builtin\'\n' +
'], function( $ ) {\n' +
' return $;\n' +
'});';
}
if ( this.data.preset === 'custom' ) {
custom = [];
this.files.forEach(function( file ) {
var files = file.src,
cwd = file.cwd || '';
files.filter(function( filepath ) {
filepath = path.join( cwd, filepath );
// Warn on and remove invalid source files (if nonull was set).
if (!grunt.file.exists(filepath)) {
grunt.log.warn('Source file "' + filepath + '" not found.');
return false;
} else {
return true;
}
}).forEach(function( filepath ) {
custom.push( '\'' + filepath.replace( /\.\w+$/, '' ) + '\'' );
});
});
custom.unshift('\'./base\'');
custom = 'define([\n ' + custom.join(',\n ') + '\n], function( Base ) {\n return Base;\n});';
config.rawText.webuploader = custom;
} else if (this.data.preset) {
config.rawText.webuploader = 'define([\n ' + ['\'./preset/' +
this.data.preset +'\''].join(',\n ') +
'\n], function( preset ) {\n return preset;\n});';
} else {
config.name = this.data.name;
}
// 处理最终输出
config.out = function( compiled ) {
var arr = [],
banner = grunt.template.process(options.banner),
footer = grunt.template.process(options.footer),
sep = '\n\n';
banner && arr.push( banner );
if ( options.builtin.dollar ) {
compiled = compiled.replace('define([ \'jquery\' ], exports );', 'define([], exports);');
}
arr.push(compiled);
footer && arr.push( footer );
// Write concatenated source to file
grunt.file.write( dest, arr.join( sep ) );
process.nextTick(function() {
// requirejs有bug, callback不一定会执行,目前调试的结果是
// prim的promise实现有问题。
if ( flag ) return;
grunt.log.ok( "File '" + dest + "' created." );
done();
flag = true;
});
};
if (options.fis) {
config.wrap = {
startFile: 'build/fis/intro.js',
endFile: 'build/fis/outro.js'
}
}
requirejs.optimize( config, function( response ) {
// requirejs有bug, callback不一定会执行,目前调试的结果是
// prim的promise实现有问题。
if ( flag ) return;
grunt.verbose.writeln( response );
grunt.log.ok( "File '" + name + "' created." );
done();
flag = true;
}, function( err ) {
done( err );
});
});
};