Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
dist
esm
bower_components
node_modules
.sizecache.json
Expand Down
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ grunt.registerTask( "update-authors", function() {
} );
} );

grunt.registerTask( "default", [ "lint", "requirejs", "test" ] );
grunt.registerTask( "default", [ "lint", "esmify", "requirejs", "test" ] );
grunt.registerTask( "jenkins", [ "default", "concat" ] );
grunt.registerTask( "lint", [ "asciilint", "jshint", "jscs", "csslint", "htmllint" ] );
grunt.registerTask( "test", [ "qunit" ] );
Expand Down
103 changes: 103 additions & 0 deletions build/tasks/esmify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
var jscodeshift = require( "jscodeshift" );

/**
* This turns AMD-module-style files into ES6 modules.
*/
function transform( source ) {
var j = jscodeshift;
var root = j( source );

// Get the comment on top of every page
var leadingComment = root.find( j.Program ).get( "body", 0 ).node.leadingComments;

root
.find( j.CallExpression, {
callee: {
type: "FunctionExpression",
params: [ {
name: "factory"
} ]
},
arguments: [ { type: "FunctionExpression" } ]
} )
.forEach( function( amdRoot ) {

// Paths to where we import modules from
var importPaths = [];

// Extract import paths from the AMD header.
// Example: define(["jquery", "./foo", "./bar"], factory)
j( amdRoot ).find( j.CallExpression, {
callee: { name: "define" },
arguments: [ {
type: "ArrayExpression"
}, {
name: "factory"
} ]
} )
.forEach( function( defineCall ) {
importPaths = defineCall.value.arguments[ 0 ].elements;
} );

var definitionFunction = amdRoot.value.arguments[ 0 ];

// Extract import identifiers from the AMD body function's parameters.
// Example: function ($) { ...
// which will transform into: import $ from "jquery"
var imports = definitionFunction.params;

// Replace the module's return statement with an export default statement.
var moduleBody = definitionFunction.body.body.map( function( statement ) {

if ( statement.type === "ReturnStatement" ) {
return j.exportDeclaration( true, statement.argument );
}
return statement;

} );

// Combine import paths from define() with parameters from the factory,
// to generate import statements.
var importDeclarations = [];
for ( var i = 0; i < importPaths.length; i++ ) {

// Add .js extension to the import path (unless we import "jquery")
var importPath = importPaths[ i ].value === "jquery" ?
importPaths[ i ] : j.literal( importPaths[ i ].value + ".js" );
var specifier = i < imports.length ?
[ j.importDefaultSpecifier( imports[ i ] ) ] : [];
importDeclarations.push(
j.importDeclaration( specifier, importPath )
);
}

var moduleBodyWithImports = [].concat(
importDeclarations,
moduleBody
);

j( amdRoot.parent ).replaceWith( moduleBodyWithImports );

// re-add comment to to the top
root.get().node.comments = leadingComment;
} );

return root.toSource();
}

module.exports = function( grunt ) {
grunt.registerTask( "esmify", "", function() {
grunt.file.recurse( "./ui", function callback( abspath, rootdir, subdir, filename ) {
if ( !filename.endsWith( ".js" ) || filename.endsWith( "core.js" ) ) {
return;
}

var code = grunt.file.read( abspath );
var transformedCode = transform( code );
grunt.file.write(
"esm" + ( subdir ? "/" + subdir + "/" : "/" ) + filename,
transformedCode
);
} );
} );
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"grunt-git-authors": "3.2.0",
"grunt-html": "14.2.0",
"grunt-jscs": "2.1.0",
"jscodeshift": "^0.12.0",
"load-grunt-tasks": "5.1.0",
"rimraf": "3.0.2",
"testswarm": "1.1.2"
Expand Down