import-overleaf-module.macro.js 2.2 KB

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