feat: autodoc for build config

This commit is contained in:
cha0s 2022-03-09 08:51:10 -06:00
parent 45cf391c7d
commit fd4050e0e9
6 changed files with 94 additions and 2 deletions

View File

@ -17,7 +17,7 @@
- [ ] hints for hook types
- [x] localConfig discovered by hook
- [x] renamed to 'build/config'?
- [ ] automatically generated list of build config
- [x] automatically generated list of build config
- [ ] static documentation site generator
- [ ] autogenerated config dox page
- [x] remove `invokeParallel()`

View File

@ -38,10 +38,26 @@ export default {
);
},
'@flecks/core.build.config': () => [
/**
* Babel configuration. See: https://babeljs.io/docs/en/config-files
*/
'babel.config.js',
/**
* ESLint defaults. The default .eslintrc.js just reads from this file so that the build
* process can dynamically configure parts of ESLint.
*/
['.eslint.defaults.js', {specifier: (specific) => `${specific}.eslint.defaults.js`}],
/**
* ESLint configuration. See: https://eslint.org/docs/user-guide/configuring/
*/
['.eslintrc.js', {specifier: (specific) => `${specific}.eslintrc.js`}],
/**
* Neutrino build configuration. See: https://neutrinojs.org/usage/
*/
['.neutrinorc.js', {specifier: (specific) => `${specific}.neutrinorc.js`}],
/**
* Webpack (v4) configuration. See: https://v4.webpack.js.org/configuration/
*/
'webpack.config.js',
],
'@flecks/core.commands': commands,

View File

@ -3,7 +3,11 @@ import {join} from 'path';
import {D} from '@flecks/core';
import {generateHookPage, generateTodoPage} from './generate';
import {
generateBuildConfigsPage,
generateHookPage,
generateTodoPage,
} from './generate';
import {parseFlecks} from './parser';
const {
@ -26,6 +30,9 @@ export default (program, flecks) => {
debug('Generating TODO page...');
const todoPage = generateTodoPage(state.todos, flecks);
debug('generated');
debug('Generating build configs page...');
const buildConfigsPage = generateBuildConfigsPage(state.buildConfigs);
debug('generated');
const output = join(FLECKS_CORE_ROOT, 'dox');
await mkdir(output, {recursive: true});
/* eslint-disable no-console */
@ -37,6 +44,9 @@ export default (program, flecks) => {
debug('Writing TODO page...');
await writeFile(join(output, 'TODO.md'), todoPage);
console.log('TODO.md');
debug('Writing build configs page...');
await writeFile(join(output, 'build-configs.md'), buildConfigsPage);
console.log('build-configs.md');
console.groupEnd();
console.log('');
/* eslint-enable no-console */

View File

@ -6,6 +6,25 @@ const makeFilenameRewriter = (filenameRewriters) => (filename, line, column) =>
)
);
export const generateBuildConfigsPage = (buildConfigs) => {
const source = [];
source.push('# Build configuration files');
source.push('');
source.push('This page documents all the build configuration files in this project.');
source.push('');
if (buildConfigs.length > 0) {
buildConfigs
.sort(({config: l}, {config: r}) => (l < r ? -1 : 1))
.forEach(({config, comment}) => {
source.push(`## \`${config}\``);
source.push('');
source.push(comment);
source.push('');
});
}
return source.join('\n');
};
export const generateHookPage = (hooks, flecks) => {
const {filenameRewriters} = flecks.get('@flecks/dox/server');
const rewriteFilename = makeFilenameRewriter(filenameRewriters);

View File

@ -4,6 +4,8 @@ import {dirname, join} from 'path';
import {transformAsync} from '@babel/core';
import traverse from '@babel/traverse';
import {
isArrayExpression,
isArrowFunctionExpression,
isIdentifier,
isLiteral,
isMemberExpression,
@ -20,10 +22,15 @@ const flecksCorePath = dirname(__non_webpack_require__.resolve('@flecks/core/pac
class ParserState {
constructor() {
this.buildConfigs = [];
this.hooks = {};
this.todos = [];
}
addBuildConfig(config, comment) {
this.buildConfigs.push({comment, config});
}
addImplementation(hook, filename, loc) {
this.hooks[hook] = this.hooks[hook] || {};
this.hooks[hook].implementations = this.hooks[hook].implementations || [];
@ -70,6 +77,40 @@ const implementationVisitor = (fn) => ({
},
});
const FlecksBuildConfigs = (state, filename) => (
implementationVisitor((property) => {
if ('@flecks/core.build.config' === property.key.value) {
if (isArrowFunctionExpression(property.value)) {
if (isArrayExpression(property.value.body)) {
property.value.body.elements.forEach((element) => {
let config;
if (isStringLiteral(element)) {
config = element.value;
}
if (isArrayExpression(element)) {
if (element.elements.length > 0 && isStringLiteral(element.elements[0])) {
config = element.elements[0].value;
}
}
if (config && element.leadingComments.length > 0) {
state.addBuildConfig(
config,
element.leadingComments.pop().value.split('\n')
.map((line) => line.trim())
.map((line) => line.replace(/^\*/, ''))
.map((line) => line.trim())
.filter((line) => !!line)
.join(' ')
.trim(),
);
}
});
}
}
}
})
);
const FlecksInvocations = (state, filename) => ({
CallExpression(path) {
if (isMemberExpression(path.node.callee)) {
@ -192,6 +233,7 @@ export const parseCode = async (code) => {
export const parseFile = async (filename, resolved, state) => {
const buffer = await readFile(filename);
const ast = await parseCode(buffer.toString('utf8'));
traverse(ast, FlecksBuildConfigs(state, resolved));
traverse(ast, FlecksInvocations(state, resolved));
traverse(ast, FlecksImplementations(state, resolved));
traverse(ast, FlecksTodos(state, resolved));

View File

@ -37,6 +37,11 @@ export default {
delete neutrinoConfigs.http;
},
'@flecks/core.build.config': () => [
/**
* Template file used to generate the client HTML.
*
* See: https://github.com/jantimon/html-webpack-plugin/blob/main/docs/template-option.md
*/
'template.ejs',
],
'@flecks/core.config': () => ({