import-overleaf-module.macro.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. const { createMacro, MacroError } = require('babel-plugin-macros')
  2. // This copy of the settings will be taken when webpack starts.
  3. // Be sure to restart webpack after making changes to the settings.
  4. const Settings = require('@overleaf/settings')
  5. const macro = createMacro(importOverleafModuleMacro)
  6. function importOverleafModuleMacro({ references, state, babel }) {
  7. references.default.forEach(referencePath => {
  8. const { types: t } = babel
  9. const modulePaths = getModulePaths(referencePath.parentPath)
  10. const { importNodes, importedVariables } = modulePaths.reduce(
  11. (all, path) => {
  12. // Generate a unique variable name for the module
  13. const id = referencePath.scope.generateUidIdentifier(path)
  14. // Generate an import statement for the module
  15. // In the form: import * as __ID__ from "__PATH__"
  16. all.importNodes.push(
  17. t.importDeclaration(
  18. [t.importNamespaceSpecifier(id)],
  19. t.stringLiteral(path)
  20. )
  21. )
  22. // Also keep track of the imported variable, so it can be added to
  23. // the assigned array
  24. all.importedVariables.push(
  25. t.objectExpression([
  26. t.objectProperty(t.identifier('import'), id),
  27. t.objectProperty(t.identifier('path'), t.stringLiteral(path)),
  28. ])
  29. )
  30. return all
  31. },
  32. { importNodes: [], importedVariables: [] }
  33. )
  34. // Generate an array of imported variables
  35. const arrayExpression = t.arrayExpression(importedVariables)
  36. // Inject the import statements at the top of the file
  37. const program = state.file.path
  38. program.node.body.unshift(...importNodes)
  39. // Replace the importFromSettings line with the generated array of imported
  40. // variables
  41. referencePath.parentPath.replaceWith(arrayExpression)
  42. })
  43. }
  44. function getModulePaths(callExpressionPath) {
  45. // Get the first argument to importFromSettings
  46. const key = callExpressionPath.get('arguments')[0].evaluate().value
  47. if (!Settings.overleafModuleImports) {
  48. throw new MacroError('Settings.overleafModuleImports not found')
  49. }
  50. // Get the module paths
  51. const modulePaths = Settings.overleafModuleImports[key]
  52. if (!modulePaths) {
  53. throw new MacroError(`Overleaf module '${key}' not found`)
  54. }
  55. return modulePaths
  56. }
  57. module.exports = macro