overleaf/services/web/frontend/macros/import-overleaf-module.macro.js
Alasdair Smith 2c556366e2 Merge pull request #3464 from overleaf/as-import-from-settings-macro
Load modules in React using importOverleafModules Babel macro

GitOrigin-RevId: 5553ede59d75306a7085424b5e0a20dabe0792f5
2020-12-17 03:07:42 +00:00

71 lines
2.2 KiB
JavaScript

const { createMacro, MacroError } = require('babel-plugin-macros')
const Settings = require('settings-sharelatex')
const macro = createMacro(importOverleafModuleMacro)
function importOverleafModuleMacro({ references, state, babel }) {
references.default.forEach(referencePath => {
const { types: t } = babel
const modulePaths = getModulePaths(referencePath.parentPath)
const { importNodes, importedVariables } = modulePaths.reduce(
(all, path) => {
// Generate a unique variable name for the module
const id = referencePath.scope.generateUidIdentifier(path)
// Generate an import statement for the module
// In the form: import * as __ID__ from "__PATH__"
all.importNodes.push(
t.importDeclaration(
[t.importNamespaceSpecifier(id)],
t.stringLiteral(path)
)
)
// Also keep track of the imported variable, so it can be added to
// the assigned array
all.importedVariables.push(
t.objectExpression([
t.objectProperty(t.identifier('import'), id),
t.objectProperty(t.identifier('path'), t.stringLiteral(path))
])
)
return all
},
{ importNodes: [], importedVariables: [] }
)
// Generate an array of imported variables
const arrayExpression = t.arrayExpression(importedVariables)
// Inject the import statements at the top of the file
const program = state.file.path
program.node.body.unshift(...importNodes)
// Replace the importFromSettings line with the generated array of imported
// variables
referencePath.parentPath.replaceWith(arrayExpression)
})
}
function getModulePaths(callExpressionPath) {
// Get the first argument to importFromSettings
const key = callExpressionPath.get('arguments')[0].evaluate().value
if (!Settings.overleafModuleImports) {
throw new MacroError('Settings.overleafModuleImports not found')
}
// Get the module paths
const modulePaths = Settings.overleafModuleImports[key]
if (!modulePaths) {
throw new MacroError(`Overleaf module '${key}' not found`)
}
return modulePaths
}
module.exports = macro