babel-transform-roll20
Advanced tools
Comparing version 0.0.2 to 0.1.0
{ | ||
"name": "babel-transform-roll20", | ||
"version": "0.0.2", | ||
"version": "0.1.0", | ||
"description": "A babel transform tool for transpiling scripts for the Roll20 sandbox.", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
145
src/index.js
@@ -8,2 +8,34 @@ const babelParser = require('@babel/parser') | ||
module.exports = function roll20Transform ({ types: t }) { | ||
function guaranteeModulePath (programPath, modulePath, moduleName) { | ||
if (!programPath.__visited_files[modulePath]) { | ||
const moduleContents = fs.readFileSync(modulePath, { | ||
encoding: 'UTF-8' | ||
}) | ||
const parsedModule = babelParser.parse(moduleContents, { | ||
sourceType: 'module' | ||
}).program.body | ||
programPath.unshiftContainer('body', t.variableDeclarator( | ||
t.memberExpression( | ||
t.identifier('modules'), | ||
t.identifier(moduleName), | ||
true | ||
), | ||
t.callExpression( | ||
t.parenthesizedExpression( | ||
t.functionExpression( | ||
null, | ||
[], | ||
t.blockStatement( | ||
parsedModule | ||
) | ||
) | ||
), | ||
[] | ||
) | ||
)) | ||
} | ||
} | ||
return { | ||
@@ -39,13 +71,24 @@ name: 'babel-transform-roll20', | ||
const exportAllKeys = Object.keys(path.__exports).filter(exportKey => exportKey.startsWith('__export__') && exportKey !== '__export__default') | ||
const exportKeys = Object.keys(path.__exports).filter(exportKey => !exportKey.startsWith('__export__') || exportKey === '__export__default') | ||
path.pushContainer('body', t.returnStatement( | ||
t.objectExpression( | ||
Object.keys(path.__exports).map(exportKey => { | ||
const exportValue = path.__exports[exportKey] | ||
t.callExpression( | ||
t.memberExpression( | ||
t.identifier('Object'), | ||
t.identifier('assign') | ||
), | ||
[ | ||
t.objectExpression([]), | ||
...exportAllKeys.map(exportKey => t.identifier(exportKey)), | ||
t.objectExpression(exportKeys.map(exportKey => { | ||
const exportValue = path.__exports[exportKey] | ||
if (exportKey === '__export__default') { | ||
return t.objectProperty(t.identifier('default'), exportValue === true ? t.identifier(exportKey) : exportValue) | ||
} | ||
if (exportKey === '__export__default') { | ||
return t.objectProperty(t.identifier('default'), exportValue === true ? t.identifier(exportKey) : exportValue) | ||
} | ||
return t.objectProperty(t.identifier(exportKey), exportValue === true ? t.identifier(exportKey) : exportValue) | ||
}) | ||
return t.objectProperty(t.identifier(exportKey), exportValue === true ? t.identifier(exportKey) : exportValue) | ||
})) | ||
] | ||
) | ||
@@ -56,2 +99,43 @@ )) | ||
}, | ||
ExportAllDeclaration: { | ||
exit (path) { | ||
const exportBlock = path.findParent((parent) => parent.__module) | ||
if (!exportBlock) { | ||
return | ||
} | ||
const [, dotStart, fileRoot, fileName] = fileRegExp.exec(path.node.source.value) | ||
const programPath = path.findParent((parent) => parent.isProgram()) | ||
const roots = [...programPath.__roots] | ||
if (dotStart.length === 2) { | ||
roots.pop() | ||
} | ||
if (fileRoot.length !== 0 && roots[roots.length - 1] !== fileRoot) { | ||
roots.push(fileRoot) | ||
} | ||
const modulePath = `/${roots.join('/')}${fileName}.js` | ||
const moduleName = `'${modulePath.slice(process.cwd().length + 1, -3)}'` | ||
const exportName = `__export__${modulePath.slice(process.cwd().length + 1, -3).replace(/[\/-]/g, '_')}` | ||
exportBlock.__exports[exportName] = true | ||
guaranteeModulePath(programPath, modulePath, moduleName) | ||
path.replaceWith( | ||
t.variableDeclaration('const', [ | ||
t.variableDeclarator( | ||
t.identifier(exportName), | ||
t.memberExpression( | ||
t.identifier('modules'), | ||
t.identifier(moduleName), | ||
true | ||
) | ||
) | ||
]) | ||
) | ||
} | ||
}, | ||
ExportDefaultDeclaration: { | ||
@@ -157,32 +241,4 @@ exit (path) { | ||
if (!programPath.__visited_files[modulePath]) { | ||
const moduleContents = fs.readFileSync(modulePath, { | ||
encoding: 'UTF-8' | ||
}) | ||
guaranteeModulePath(programPath, modulePath, moduleName) | ||
const parsedModule = babelParser.parse(moduleContents, { | ||
sourceType: 'module' | ||
}).program.body | ||
programPath.unshiftContainer('body', t.variableDeclarator( | ||
t.memberExpression( | ||
t.identifier('modules'), | ||
t.identifier(moduleName), | ||
true | ||
), | ||
t.callExpression( | ||
t.parenthesizedExpression( | ||
t.functionExpression( | ||
null, | ||
[], | ||
t.blockStatement( | ||
parsedModule | ||
) | ||
) | ||
), | ||
[] | ||
) | ||
)) | ||
} | ||
path.replaceWithMultiple( | ||
@@ -220,2 +276,17 @@ path.node.specifiers.map(specifier => { | ||
]) | ||
case 'ImportNamespaceSpecifier': | ||
return t.variableDeclaration('const', [ | ||
t.variableDeclarator( | ||
t.identifier(specifier.local.name), | ||
t.memberExpression( | ||
t.identifier('modules'), | ||
t.identifier(moduleName), | ||
true | ||
) | ||
) | ||
]) | ||
default: | ||
throw new Error(`Unsupported import type: ${specifier.type}`) | ||
} | ||
@@ -222,0 +293,0 @@ }) |
@@ -67,1 +67,8 @@ import * as babel from '@babel/core' | ||
}) | ||
test('transforms collected imports', async (t) => { | ||
const result = await loadFile('./test/transforms/import-all.js') | ||
const { code } = await transform('./test/fixtures/import-all.js') | ||
t.is(code, result) | ||
}) |
@@ -6,5 +6,5 @@ const modules = {}; | ||
}; | ||
return { | ||
return Object.assign({}, { | ||
default: __export__default | ||
}; | ||
}); | ||
})() | ||
@@ -16,5 +16,5 @@ modules['test/fixtures/default-import/function'] = (function () { | ||
return { | ||
return Object.assign({}, { | ||
default: example | ||
}; | ||
}); | ||
})() | ||
@@ -37,5 +37,5 @@ modules['test/fixtures/default-import/class'] = (function () { | ||
return { | ||
return Object.assign({}, { | ||
default: ExampleClass | ||
}; | ||
}); | ||
})() | ||
@@ -42,0 +42,0 @@ const ExampleClass = modules['test/fixtures/default-import/class'].default; |
@@ -33,6 +33,6 @@ const modules = {}; | ||
return { | ||
return Object.assign({}, { | ||
default: ExampleClass, | ||
ClassA: ClassA | ||
}; | ||
}); | ||
})() | ||
@@ -46,6 +46,6 @@ modules['test/fixtures/mixed-import/object'] = (function () { | ||
}; | ||
return { | ||
return Object.assign({}, { | ||
default: __export__default, | ||
objectA: objectA | ||
}; | ||
}); | ||
})() | ||
@@ -52,0 +52,0 @@ const objectDefault = modules['test/fixtures/mixed-import/object'].default; |
@@ -9,6 +9,6 @@ const modules = {}; | ||
}; | ||
return { | ||
return Object.assign({}, { | ||
objectA: objectA, | ||
objectB: objectB | ||
}; | ||
}); | ||
})() | ||
@@ -20,5 +20,5 @@ modules['test/fixtures/named-import/function'] = (function () { | ||
return { | ||
return Object.assign({}, { | ||
example: example | ||
}; | ||
}); | ||
})() | ||
@@ -41,5 +41,5 @@ modules['test/fixtures/named-import/class'] = (function () { | ||
return { | ||
return Object.assign({}, { | ||
ExampleClass: ExampleClass | ||
}; | ||
}); | ||
})() | ||
@@ -46,0 +46,0 @@ const ExampleClass = modules['test/fixtures/named-import/class'].ExampleClass; |
@@ -6,5 +6,5 @@ const modules = {}; | ||
}; | ||
return { | ||
return Object.assign({}, { | ||
default: __export__default | ||
}; | ||
}); | ||
})() | ||
@@ -14,7 +14,7 @@ modules['test/fixtures/nested-import/level-a'] = (function () { | ||
const __export__default = levelB; | ||
return { | ||
return Object.assign({}, { | ||
default: __export__default | ||
}; | ||
}); | ||
})() | ||
const levelA = modules['test/fixtures/nested-import/level-a'].default; | ||
console.log(levelA); |
19924
29
587