babelParser.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { loadPartialConfig, parseSync } from '@babel/core';
  2. import { extname } from 'path';
  3. const TYPESCRIPT_EXTS = new Set(['.cts', '.mts', '.ts', '.tsx']);
  4. function getDefaultPlugins(options) {
  5. return [
  6. 'jsx',
  7. options.filename && TYPESCRIPT_EXTS.has(extname(options.filename))
  8. ? 'typescript'
  9. : 'flow',
  10. 'asyncDoExpressions',
  11. 'decimal',
  12. ['decorators', { decoratorsBeforeExport: false }],
  13. 'decoratorAutoAccessors',
  14. 'destructuringPrivate',
  15. 'doExpressions',
  16. 'exportDefaultFrom',
  17. 'functionBind',
  18. 'importAssertions',
  19. 'moduleBlocks',
  20. 'partialApplication',
  21. ['pipelineOperator', { proposal: 'minimal' }],
  22. ['recordAndTuple', { syntaxType: 'bar' }],
  23. 'regexpUnicodeSets',
  24. 'throwExpressions',
  25. ];
  26. }
  27. function buildPluginList(options) {
  28. let plugins = [];
  29. if (options.parserOpts?.plugins) {
  30. plugins = [...options.parserOpts.plugins];
  31. }
  32. // Let's check if babel finds a config file for this source file
  33. // If babel does find a config file we do not apply our defaults
  34. const partialConfig = loadPartialConfig(options);
  35. if (plugins.length === 0 &&
  36. partialConfig &&
  37. !partialConfig.hasFilesystemConfig()) {
  38. plugins = getDefaultPlugins(options);
  39. }
  40. // Ensure that the estree plugin is never active
  41. // TODO add test
  42. return plugins.filter((plugin) => plugin !== 'estree');
  43. }
  44. function buildParserOptions(options) {
  45. const plugins = buildPluginList(options);
  46. return {
  47. sourceType: 'unambiguous',
  48. ...(options.parserOpts || {}),
  49. plugins,
  50. tokens: false,
  51. };
  52. }
  53. export default function babelParser(src, options = {}) {
  54. const parserOpts = buildParserOptions(options);
  55. const opts = {
  56. ...options,
  57. parserOpts,
  58. };
  59. const ast = parseSync(src, opts);
  60. if (!ast) {
  61. throw new Error('Unable to parse source code.');
  62. }
  63. return ast;
  64. }