Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more features #37

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ AMD and RequireJS are great, but ES6 modules provide a nicer syntax for writing
### Installing

```sh
npm install amd-to-es6 -g
npm install amd-to-es6-other -g
```

### Usage
Expand Down
202 changes: 142 additions & 60 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ var falafel = require('falafel');
var jsx = require('acorn-jsx');
var acorn = require('acorn');
var beautify = require('js-beautify').js_beautify;
var classFields = require('acorn-class-fields');
var staticClassFeatures = require('acorn-static-class-features');

module.exports = convert;

var JSXParser = acorn.Parser.extend(jsx());

var JSXParser = acorn.Parser.extend(jsx(), classFields, staticClassFeatures);
/**
* Converts some code from AMD to ES6
* @param {string} source
* @param {object} [options]
* @returns {string}
*/
function convert (source, options) {
function convert(source, options) {

options = options || {};

Expand All @@ -24,45 +26,49 @@ function convert (source, options) {
var mainCallExpression = null;

var result = falafel(source, {
parser: {
parse: JSXParser.parse.bind(JSXParser)
parser: {
parse: JSXParser.parse.bind(JSXParser)
},
ecmaVersion: 10,
plugins: {
jsx: true
},
},
ecmaVersion: 9
}, function (node) {
if (isNamedDefine(node)) {
throw new Error('Found a named define - this is not supported.');
}
function (node) {
if (isNamedDefine(node)) {
throw new Error('Found a named define - this is not supported.');
}

if (isDefineUsingIdentifier(node)) {
throw new Error('Found a define using a variable as the callback - this is not supported.');
}
if (isDefineUsingIdentifier(node)) {
throw new Error('Found a define using a variable as the callback - this is not supported.');
}

if (isModuleDefinition(node)) {
if (isModuleDefinition(node)) {

if (mainCallExpression) {
throw new Error('Found multiple module definitions in one file.');
}
if (mainCallExpression) {
throw new Error('Found multiple module definitions in one file.');
}

mainCallExpression = node;
mainCallExpression = node;
}

else if (isSyncRequire(node)) {
syncRequires.push(node);
syncRequires.push(node);
}

else if (isRequireWithNoCallback(node)) {
requiresWithSideEffects.push(node);
requiresWithSideEffects.push(node);
}

else if (isRequireWithDynamicModuleName(node)) {
throw new Error('Dynamic module names are not supported.');
}
throw new Error('Dynamic module names are not supported.');
}

if (isUseStrict(node)) {
node.parent.update('');
}
if (isUseStrict(node)) {
node.parent.update('');
}

});
});

// no module definition found - return source untouched
if (!mainCallExpression) {
Expand Down Expand Up @@ -94,17 +100,17 @@ function convert (source, options) {
}, {}));
}

syncRequires.forEach(function (node) {
var moduleName = node.arguments[0].raw;

// if no import name assigned then create one
if (!dependenciesMap[moduleName]) {
dependenciesMap[moduleName] = makeImportName(node.arguments[0].value);
}

// replace with the import name
node.update(dependenciesMap[moduleName]);
});
// syncRequires.forEach(function (node) {
// var moduleName = node.arguments[0].raw;
//
// // if no import name assigned then create one
// if (!dependenciesMap[moduleName]) {
// dependenciesMap[moduleName] = makeImportName(node.arguments[0].value);
// }
//
// // replace with the import name
// node.update(dependenciesMap[moduleName]);
// });

requiresWithSideEffects.forEach(function (node) {

Expand Down Expand Up @@ -132,7 +138,7 @@ function convert (source, options) {

// fix indentation
if (options.beautify) {
moduleCode = beautify(moduleCode, { indent_size: options.indent });
moduleCode = beautify(moduleCode, {indent_size: options.indent});

// jsbeautify doesn't understand es6 module syntax yet
moduleCode = moduleCode.replace(/export[\s\S]default[\s\S]/, 'export default ');
Expand All @@ -150,16 +156,16 @@ function convert (source, options) {
* @param {object} dependencies
* @returns {string}
*/
function getImportStatements (dependencies) {
function getImportStatements(dependencies) {
var statements = [];

for (var key in dependencies) {

if (!dependencies[key]) {
statements.push('import ' + key + ';');
}
else {
} else {
statements.push('import ' + dependencies[key] + ' from ' + key + ';');
// statements.push('import * as ' + "'" + dependencies[key] + "'" + ' from ' + key + ';');
}
}

Expand All @@ -170,21 +176,82 @@ function getImportStatements (dependencies) {
* Updates the return statement of a FunctionExpression to be an 'export default'.
* @param {object} functionExpression
*/
function updateReturnStatement (functionExpression) {
functionExpression.body.body.forEach(function (node) {
if (node.type === 'ReturnStatement') {
node.update(node.source().replace(/\breturn\b/, 'export default'));
function updateReturnStatement(functionExpression) {
try {
functionExpression.body.body.forEach(function (node) {
if (node.type === 'ReturnStatement') {
node.update(node.source().replace(/\breturn\b/, 'export default'));
}
});

} catch (e) {
if (e.message == "Cannot read property 'forEach' of undefined") {
if (functionExpression.type === "ArrowFunctionExpression") {
functionExpression.body.update(` export default ${functionExpression.body.source()}; `)
}
}
});
}

}


function updateImportStatement(functionExpression) {
try {
functionExpression.body.body.forEach(function (node) {
if (node.type === 'VariableDeclaration') {
// for friendly read pls use https://regex101.com/ to get result
// this to handle const|let|var XXX|{ XXX } = require("some");
const normalImportRegex = /\s*(const|var|let)\b\s*(\{.+\}|\w+|\$)\s*(=)\s*(require\(\s*){1}.*(\))\s*;\s*$/g;

// this to handle const some = require("some").name;
const regex = /\s*(const|var|let)\b\s*(\{.+\}|\w+|\$)\s*(=)\s*(require\(\s*){1}.*(\))(\.)(\w+)\s*;\s*$/g

const group = normalImportRegex.exec(node.source())
if (group != null) {
node.update(node.source()
.replace(group[1], " import ")
.replace(group[2], group[2] == "$" ? " * as $ ": group[2] == "_" ? " * as _ " : group[2])
.replace(group[3], "")
.replace(group[4], ' from ')
.replace(group[5], ""))
} else {
var group2 = regex.exec(node.source())
if(group2 !=null) {
let tempResult = node.source()
.replace(group2[1], " import ")
.replace(group2[2], "{ " + group2[7] + " }")
.replace(group2[3], "")
.replace(group2[4], " from ")
.replace(group2[5], "")

node.update(tempResult.replace(/(?<=(from\s*['"]\w*['"]))\s*\.\w*(?=\s*;)/g, ""))
}
}
} else if (node.type === "ExpressionStatement") {
const regex = /\s*require\b\(.*\)\s*;$/g;
if (regex.test(node.source())) {
node.update(node.source()
.replace("require", 'import')
.replace("(", " ")
.replace(")", " "))
}
}
});
} catch (e) {
if (e.message != "Cannot read property 'forEach' of undefined") {
throw e;
}
}
}

/**
*
* @param {object} moduleFuncNode
* @returns {string}
*/
function getModuleCode (moduleFuncNode) {
function getModuleCode(moduleFuncNode) {

updateImportStatement(moduleFuncNode);
updateReturnStatement(moduleFuncNode);

var moduleCode = moduleFuncNode.body.source();
Expand All @@ -201,7 +268,7 @@ function getModuleCode (moduleFuncNode) {
* @param {object} callExpression
* @returns {array}
*/
function getArgumentsTypes (callExpression) {
function getArgumentsTypes(callExpression) {
return callExpression.arguments.map(function (arg) {
return arg.type;
});
Expand All @@ -212,7 +279,7 @@ function getArgumentsTypes (callExpression) {
* @param {object} node
* @returns {boolean}
*/
function isRequireOrDefine (node) {
function isRequireOrDefine(node) {
return isRequire(node) || isDefine(node);
}

Expand All @@ -221,7 +288,7 @@ function isRequireOrDefine (node) {
* @param {object} node
* @returns {boolean}
*/
function isRequire (node) {
function isRequire(node) {
return node.type === 'CallExpression' && node.callee.name === 'require';
}

Expand All @@ -230,7 +297,7 @@ function isRequire (node) {
* @param {object} node
* @returns {boolean}
*/
function isDefine (node) {
function isDefine(node) {
return node.type === 'CallExpression' && node.callee.name === 'define';
}

Expand All @@ -240,7 +307,7 @@ function isDefine (node) {
* @param {array} arr2
* @returns {boolean}
*/
function arrayEquals (arr1, arr2) {
function arrayEquals(arr1, arr2) {

if (arr1.length !== arr2.length) {
return false;
Expand All @@ -255,14 +322,28 @@ function arrayEquals (arr1, arr2) {
return true;
}

function isConstImport(node) {
if (node.type === 'VariableDeclaration' && node.kind === "const") {
const regex = /const\s.+=\srequire\('.+'\)/g;
if (regex.test(node.source())) {
node.update(node.source()
.replace("const", " import ")
.replace("require", 'from')
.replace("(", " ")
.replace(")", " "))
}
}

}

/**
* Returns true if node is a require() call where the module name is a literal.
* @param {object} node
* @returns {boolean}
*/
function isSyncRequire (node) {
function isSyncRequire(node) {
return isRequire(node) &&
arrayEquals(getArgumentsTypes(node), ['Literal']);
arrayEquals(getArgumentsTypes(node), ['Literal']);
}

/**
Expand All @@ -283,7 +364,7 @@ function isRequireWithDynamicModuleName(node) {
* @param {object} target
* @param {object} source
*/
function extend (target, source) {
function extend(target, source) {
for (var key in source) {
target[key] = source[key];
}
Expand All @@ -294,7 +375,7 @@ function extend (target, source) {
* @param {object} node
* @returns {boolean}
*/
function isModuleDefinition (node) {
function isModuleDefinition(node) {

if (!isRequireOrDefine(node)) {
return false;
Expand Down Expand Up @@ -333,7 +414,7 @@ function isModuleDefinition (node) {
* @param {object} node
* @returns {boolean}
*/
function isRequireWithNoCallback (node) {
function isRequireWithNoCallback(node) {
return isRequire(node) && arrayEquals(getArgumentsTypes(node), ['ArrayExpression']);
}

Expand All @@ -342,7 +423,7 @@ function isRequireWithNoCallback (node) {
* @param {object} node
* @returns {boolean}
*/
function isNamedDefine (node) {
function isNamedDefine(node) {
return isDefine(node) && getArgumentsTypes(node)[0] === 'Literal';
}

Expand All @@ -364,15 +445,16 @@ function isDefineUsingIdentifier(node) {
* @param {string} moduleName
* @returns {string}
*/
function makeImportName (moduleName) {
return '$__' + moduleName.replace(/[^a-zA-Z]/g, '_');
function makeImportName(moduleName) {
return moduleName;
// return '$__' + moduleName.replace(/[^a-zA-Z]/g, '_');
}

/**
* Returns true if node represents a 'use strict'-statement
* @param {object} node
* @returns {boolean}
*/
function isUseStrict (node) {
function isUseStrict(node) {
return node.type === 'Literal' && node.value === 'use strict';
}
Loading