metadata.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. const babel = require("@babel/core");
  2. const fs = require("fs");
  3. const path = require("path");
  4. const t = babel.types;
  5. const dirs = fs
  6. .readdirSync(path.join(__dirname, "../src/components"))
  7. .filter((file) => file.startsWith("Dage"));
  8. /**
  9. * @type {{[name: string]: string[]}}
  10. */
  11. const mapper = {};
  12. const extensions = [".ts", ".tsx"];
  13. const findFile = (file) => {
  14. if (fs.existsSync(file)) {
  15. if (fs.statSync(file).isDirectory()) {
  16. return findFile(path.join(file, "index"));
  17. }
  18. return file;
  19. }
  20. for (const ext of extensions) {
  21. const f = `${file}${ext}`;
  22. if (fs.existsSync(f)) {
  23. return f;
  24. }
  25. }
  26. return null;
  27. };
  28. const walk = (context, entry) => {
  29. const base = path.basename(context);
  30. const addMapper = (name) => {
  31. mapper[base] = mapper[base] || [];
  32. mapper[base].push(name);
  33. };
  34. /**
  35. * @type {import('@babel/core').PluginObj}
  36. */
  37. const plugin = {
  38. visitor: {
  39. ExportNamedDeclaration(path) {
  40. const decl = path.node.declaration;
  41. if (t.isVariableDeclaration(decl)) {
  42. decl.declarations.forEach((i) => {
  43. if (t.isIdentifier(i.id)) {
  44. addMapper(i.id.name);
  45. }
  46. });
  47. } else if (
  48. (t.isFunctionDeclaration(decl) ||
  49. t.isTSInterfaceDeclaration(decl) ||
  50. t.isTSTypeAliasDeclaration(decl) ||
  51. t.isTSEnumDeclaration(decl) ||
  52. t.isClassDeclaration(decl)) &&
  53. t.isIdentifier(decl.id)
  54. ) {
  55. addMapper(decl.id.name);
  56. } else if (path.node.specifiers?.length) {
  57. path.node.specifiers.forEach((i) => {
  58. addMapper(i.exported.name);
  59. });
  60. }
  61. },
  62. ExportAllDeclaration(p) {
  63. // 递归
  64. if (p.node.source.value.startsWith("./")) {
  65. const relativeEntry = findFile(
  66. path.join(path.dirname(entry), p.node.source.value)
  67. );
  68. walk(context, relativeEntry);
  69. }
  70. },
  71. },
  72. };
  73. babel.transformFileSync(entry, {
  74. root: path.join(__dirname, "../"),
  75. configFile: false,
  76. babelrc: false,
  77. parserOpts: {
  78. plugins: [
  79. "decorators-legacy",
  80. "classProperties",
  81. "dynamicImport",
  82. "typescript",
  83. "jsx",
  84. ],
  85. },
  86. plugins: [plugin],
  87. });
  88. };
  89. dirs.forEach((dir) => {
  90. const context = path.join(__dirname, "../src/components", dir);
  91. const entry = findFile(path.join(context, "index"));
  92. if (entry == null) {
  93. return;
  94. }
  95. walk(context, entry);
  96. });
  97. fs.writeFileSync(
  98. path.join(__dirname, "../dist/metadata.json"),
  99. JSON.stringify(mapper, null, 2)
  100. );