main.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. const fs = require("fs");
  2. const path_ = require("path");
  3. const rootdir = path_.resolve(process.argv[2] ?? '.');
  4. const parser = require('@babel/parser');
  5. const traverse = require('@babel/traverse').default;
  6. const { ModuleDoc } = require("./defs");
  7. const processors = require("./processors");
  8. const doc_module = new ModuleDoc();
  9. const handle_file = (code, context) => {
  10. const ast = parser.parse(code);
  11. const traverse_callbacks = {};
  12. for ( const processor of processors ) {
  13. if ( processor.match(context) ) {
  14. for ( const key in processor.traverse ) {
  15. if ( ! traverse_callbacks[key] ) {
  16. traverse_callbacks[key] = [];
  17. }
  18. traverse_callbacks[key].push(processor.traverse[key]);
  19. }
  20. }
  21. }
  22. for ( const key in traverse_callbacks ) {
  23. traverse(ast, {
  24. [key] (path) {
  25. context.skip = false;
  26. for ( const callback of traverse_callbacks[key] ) {
  27. callback(path, context);
  28. if ( context.skip ) return;
  29. }
  30. }
  31. });
  32. }
  33. }
  34. // Module and class files
  35. {
  36. const files = fs.readdirSync(rootdir);
  37. for ( const file of files ) {
  38. const stat = fs.statSync(path_.join(rootdir, file));
  39. if ( stat.isDirectory() ) {
  40. continue;
  41. }
  42. if ( ! file.endsWith('.js') ) continue;
  43. const type =
  44. file.endsWith('Service.js') ? 'service' :
  45. file.endsWith('Module.js') ? 'module' :
  46. null;
  47. if ( type === null ) continue;
  48. console.log('file', file);
  49. const code = fs.readFileSync(path_.join(rootdir, file), 'utf8');
  50. const firstLine = code.slice(0, code.indexOf('\n'));
  51. let metadata = {};
  52. const METADATA_PREFIX = '// METADATA // ';
  53. if ( firstLine.startsWith(METADATA_PREFIX) ) {
  54. metadata = JSON.parse(firstLine.slice(METADATA_PREFIX.length));
  55. }
  56. const context = {
  57. metadata,
  58. type,
  59. doc_module,
  60. filename: file,
  61. };
  62. handle_file(code, context);
  63. }
  64. }
  65. // Library files
  66. {
  67. const files = fs.readdirSync(path_.join(rootdir, 'lib'));
  68. for ( const file of files ) {
  69. if ( file.startsWith('_') ) continue;
  70. const code = fs.readFileSync(path_.join(rootdir, 'lib', file), 'utf8');
  71. const firstLine = code.slice(0, code.indexOf('\n'));
  72. let metadata = {};
  73. const METADATA_PREFIX = '// METADATA // ';
  74. if ( firstLine.startsWith(METADATA_PREFIX) ) {
  75. metadata = JSON.parse(firstLine.slice(METADATA_PREFIX.length));
  76. }
  77. const doc_item = doc_module.add_lib();
  78. doc_item.name = metadata.def ?? file.slice(0, -3);
  79. const context = {
  80. metadata,
  81. type: 'lib',
  82. doc_module,
  83. doc_item,
  84. filename: file,
  85. };
  86. handle_file(code, context);
  87. }
  88. }
  89. const outfile = path_.join(rootdir, 'README.md');
  90. const out = doc_module.toMarkdown();
  91. fs.writeFileSync(outfile, out);