puter/tools/module-docgen/main.js
2024-12-04 16:58:45 -05:00

112 lines
3.2 KiB
JavaScript

const fs = require("fs");
const path_ = require("path");
const rootdir = path_.resolve(process.argv[2] ?? '.');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const { ModuleDoc } = require("./defs");
const processors = require("./processors");
const doc_module = new ModuleDoc();
const handle_file = (code, context) => {
const ast = parser.parse(code);
const traverse_callbacks = {};
for ( const processor of processors ) {
if ( processor.match(context) ) {
for ( const key in processor.traverse ) {
if ( ! traverse_callbacks[key] ) {
traverse_callbacks[key] = [];
}
traverse_callbacks[key].push(processor.traverse[key]);
}
}
}
for ( const key in traverse_callbacks ) {
traverse(ast, {
[key] (path) {
context.skip = false;
for ( const callback of traverse_callbacks[key] ) {
callback(path, context);
if ( context.skip ) return;
}
}
});
}
}
// Module and class files
{
const files = fs.readdirSync(rootdir);
for ( const file of files ) {
const stat = fs.statSync(path_.join(rootdir, file));
if ( stat.isDirectory() ) {
continue;
}
if ( ! file.endsWith('.js') ) continue;
const type =
file.endsWith('Service.js') ? 'service' :
file.endsWith('Module.js') ? 'module' :
null;
if ( type === null ) continue;
console.log('file', file);
const code = fs.readFileSync(path_.join(rootdir, file), 'utf8');
const firstLine = code.slice(0, code.indexOf('\n'));
let metadata = {};
const METADATA_PREFIX = '// METADATA // ';
if ( firstLine.startsWith(METADATA_PREFIX) ) {
metadata = JSON.parse(firstLine.slice(METADATA_PREFIX.length));
}
const context = {
metadata,
type,
doc_module,
filename: file,
};
handle_file(code, context);
}
}
// Library files
if ( fs.existsSync(path_.join(rootdir, 'lib')) ) {
const files = fs.readdirSync(path_.join(rootdir, 'lib'));
for ( const file of files ) {
if ( file.startsWith('_') ) continue;
const code = fs.readFileSync(path_.join(rootdir, 'lib', file), 'utf8');
const firstLine = code.slice(0, code.indexOf('\n'));
let metadata = {};
const METADATA_PREFIX = '// METADATA // ';
if ( firstLine.startsWith(METADATA_PREFIX) ) {
metadata = JSON.parse(firstLine.slice(METADATA_PREFIX.length));
}
const doc_item = doc_module.add_lib();
doc_item.name = metadata.def ?? file.slice(0, -3);
const context = {
metadata,
type: 'lib',
doc_module,
doc_item,
filename: file,
};
handle_file(code, context);
}
}
const outfile = path_.join(rootdir, 'README.md');
const out = doc_module.toMarkdown();
fs.writeFileSync(outfile, out);