diff --git a/packages/dox/build/generate.js b/packages/dox/build/generate.js index 648432a7..452950c5 100644 --- a/packages/dox/build/generate.js +++ b/packages/dox/build/generate.js @@ -306,7 +306,10 @@ exports.generateJson = async function generate(flecks) { }))); if (config.length > 0) { let fleck = root; - if ('build/flecks.bootstrap.js' !== path) { + if (path.match(/@flecks\/core\.config(?:\.[^.]+)*/)) { + fleck = join(root, path).split('/').slice(0, -4).join('/'); + } + else if ('build/flecks.bootstrap.js' !== path) { fleck = join(fleck, path.startsWith('src') ? path.slice(4) : path); fleck = join(dirname(fleck), basename(fleck, extname(fleck))); fleck = fleck.endsWith('/index') ? fleck.slice(0, -6) : fleck; diff --git a/packages/dox/build/parser.js b/packages/dox/build/parser.js index d9b23fdc..56ff0c0a 100644 --- a/packages/dox/build/parser.js +++ b/packages/dox/build/parser.js @@ -13,8 +13,11 @@ const {glob} = require('@flecks/core/src/server'); const { buildFileVisitor, + buildFileVisitorRaw, configVisitor, + configVisitorRaw, hookBaseVisitor, + hookExportVisitor, hookImplementationVisitor, hookInvocationVisitor, hookSpecificationVisitor, @@ -104,7 +107,7 @@ exports.parseNormalSource = async (path, source, root, request, options) => { }; }; -exports.parseHookSpecificationSource = async (path, source, options) => { +exports.parseHookSpecificationSource = async (source, options) => { const ast = await exports.parseCode(source, options); const hookSpecifications = []; traverse(ast, hookSpecificationVisitor((hookSpecification) => { @@ -119,9 +122,37 @@ exports.parseHookSpecificationSource = async (path, source, options) => { }; }; +exports.parseHookExportSource = async (source, options, fn) => { + traverse(await exports.parseCode(source, options), hookExportVisitor(fn)); +}; + exports.parseSource = async (path, source, root, request, options) => { if (path.match(/build\/flecks\.hooks\.js$/)) { - return exports.parseHookSpecificationSource(path, source, options); + return exports.parseHookSpecificationSource(source, options); + } + if (path.match(/@flecks\/build\.files(?:\.[^.]+)*/)) { + const buildFiles = []; + exports.parseHookExportSource(source, options, (node) => { + buildFileVisitorRaw(node, (buildFile) => { + buildFiles.push(buildFile); + }); + }); + return {buildFiles}; + } + if (path.match(/@flecks\/core\.config(?:\.[^.]+)*/)) { + const configs = []; + // console.log(path); + exports.parseHookExportSource(source, options, (node) => { + configVisitorRaw(node, (config) => { + const {description, key, location: {start: {index: start}, end: {index: end}}} = config; + configs.push({ + defaultValue: source.slice(start, end), + description, + key, + }); + }); + }); + return {config: configs}; } return exports.parseNormalSource(path, source, root, request, options); }; diff --git a/packages/dox/build/visitors.js b/packages/dox/build/visitors.js index fcc4ab2b..3f5a3ddb 100644 --- a/packages/dox/build/visitors.js +++ b/packages/dox/build/visitors.js @@ -13,6 +13,7 @@ const { isFunction, isCallExpression, } = require('@babel/types'); +const {Flecks} = require('@flecks/core/build/flecks'); const {parse: parseComment} = require('comment-parser'); function visitProperties(properties, fn) { @@ -124,62 +125,70 @@ function functionResultVisitor(value, fn) { } } +exports.buildFileVisitorRaw = (node, fn) => { + if (isArrayExpression(node)) { + node.elements + .map((element) => { + let filename; + if (isStringLiteral(element)) { + filename = element.value; + } + if (!filename) { + return undefined; + } + return { + filename, + description: ( + (element.leadingComments?.length > 0) + ? element.leadingComments.pop().value.split('\n') + .map((line) => line.trim()) + .map((line) => line.replace(/^\*/, '')) + .map((line) => line.trim()) + .join('\n') + .trim() + : undefined + ), + }; + }) + .filter((buildFile) => buildFile) + .forEach(fn); + } +}; + exports.buildFileVisitor = (fn) => exports.hookVisitor('@flecks/build.files')( (property) => { functionResultVisitor(property.value, (node) => { - if (isArrayExpression(node)) { - node.elements - .map((element) => { - let filename; - if (isStringLiteral(element)) { - filename = element.value; - } - if (!filename) { - return undefined; - } - return { - filename, - description: ( - (element.leadingComments?.length > 0) - ? element.leadingComments.pop().value.split('\n') - .map((line) => line.trim()) - .map((line) => line.replace(/^\*/, '')) - .map((line) => line.trim()) - .join('\n') - .trim() - : undefined - ), - }; - }) - .filter((buildFile) => buildFile) - .forEach(fn); - } + exports.buildFileVisitorRaw(node, fn); }); }, ); +exports.configVisitorRaw = (node, fn) => { + if (isObjectExpression(node)) { + node.properties.forEach((property) => { + if (isIdentifier(property.key) || isStringLiteral(property.key)) { + fn({ + key: property.key.name || property.key.value, + description: (property.leadingComments?.length > 0) + ? property.leadingComments.pop().value.split('\n') + .map((line) => line.trim()) + .map((line) => line.replace(/^\*/, '')) + .map((line) => line.trim()) + .filter((line) => !!line) + .join(' ') + .trim() + : undefined, + location: property.value.loc, + }); + } + }); + } +}; + exports.configVisitor = (fn) => exports.hookVisitor('@flecks/core.config')( (property) => { functionResultVisitor(property.value, (node) => { - if (isObjectExpression(node)) { - node.properties.forEach((property) => { - if (isIdentifier(property.key) || isStringLiteral(property.key)) { - fn({ - key: property.key.name || property.key.value, - description: (property.leadingComments?.length > 0) - ? property.leadingComments.pop().value.split('\n') - .map((line) => line.trim()) - .map((line) => line.replace(/^\*/, '')) - .map((line) => line.trim()) - .filter((line) => !!line) - .join(' ') - .trim() - : undefined, - location: property.value.loc, - }); - } - }); - } + exports.configVisitorRaw(node, fn); }); }, ); @@ -293,3 +302,30 @@ exports.todoVisitor = (fn) => ({ } }, }); + +exports.hookExportVisitor = (fn) => ({ + AssignmentExpression(path) { + const {left, right} = path.node; + if (isMemberExpression(left)) { + if (isIdentifier(left.object) && 'exports' === left.object.name) { + if (isIdentifier(left.property) && 'hook' === left.property.name) { + if (isFunction(right)) { + functionResultVisitor(right, fn); + } + } + } + } + }, + ExportNamedDeclaration(path) { + if (isVariableDeclaration(path.node.declaration)) { + if ('hook' === Flecks.get(path, 'node.declaration.declarations[0].id.name')) { + if (isFunction(path.node.declaration.declarations[0].id.init)) { + functionResultVisitor(path.node.declaration.declarations[0].id.init, fn); + } + } + } + if (isFunction(path.node.declaration)) { + functionResultVisitor(path.node.declaration, fn); + } + }, +});