UNPKG

@conjecture-dev/g-std

Version:

A collection of TypeScript utility functions for common programming tasks

132 lines 6.27 kB
import * as fs from 'fs'; import * as path from 'path'; import * as ts from 'typescript'; // Read the files const sourceFile = fs.readFileSync(path.join(__dirname, '../index.ts'), 'utf-8'); const outcomeFile = fs.readFileSync(path.join(__dirname, '../outcome.ts'), 'utf-8'); const outcomeTestFile = fs.readFileSync(path.join(__dirname, '../examples/outcome.test.ts'), 'utf-8'); const examplesTestFile = fs.readFileSync(path.join(__dirname, '../examples/examples.test.ts'), 'utf-8'); // Parse the source files const sourceSourceFile = ts.createSourceFile('index.ts', sourceFile, ts.ScriptTarget.Latest, true); const outcomeSourceFile = ts.createSourceFile('outcome.ts', outcomeFile, ts.ScriptTarget.Latest, true); // Parse the test files const outcomeTestSourceFile = ts.createSourceFile('outcome.test.ts', outcomeTestFile, ts.ScriptTarget.Latest, true); const examplesTestSourceFile = ts.createSourceFile('examples.test.ts', examplesTestFile, ts.ScriptTarget.Latest, true); // Extract examples from test files const examples = new Map(); const functionSignatures = new Map(); const typeDefinitions = new Map(); // First pass: collect function signatures and type definitions const collectSignatures = (node) => { if (ts.isFunctionDeclaration(node) || ts.isVariableStatement(node)) { const name = ts.isFunctionDeclaration(node) ? node.name?.text : node.declarationList.declarations[0].name.getText(); if (name) { const signature = node.getText(); functionSignatures.set(name, signature); } } else if (ts.isTypeAliasDeclaration(node)) { const name = node.name.text; const signature = node.getText(); typeDefinitions.set(name, signature); } ts.forEachChild(node, collectSignatures); }; // Collect signatures from both source files collectSignatures(outcomeSourceFile); collectSignatures(sourceSourceFile); // Second pass: collect examples and match them to functions const visitTest = (node) => { if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'test') { const testBody = node.getText(); const sourceFile = node.getSourceFile(); const text = sourceFile.getFullText(); const lastCommentMatch = text.substring(Math.max(0, text.lastIndexOf('//', node.pos) - 100), node.pos) .match(/\/\/\s*@function\s+(\w+)\s*$/m); if (lastCommentMatch) { const functionName = lastCommentMatch[1]; const bodyMatch = testBody.match(/\(\s*\)\s*=>\s*{([\s\S]+)}/); if (bodyMatch) { const testContent = bodyMatch[1].trim(); examples.set(functionName, testContent); } } } ts.forEachChild(node, visitTest); }; // Visit both test files visitTest(outcomeTestSourceFile); visitTest(examplesTestSourceFile); // Log collected examples console.log('\nCollected examples:'); for (const [funcName, example] of examples) { console.log(`\nExample for ${funcName}:`); console.log(example); } // Generate markdown let markdown = '# g-std Documentation\n\n'; const visitSource = (node) => { if (ts.isFunctionDeclaration(node) || ts.isVariableStatement(node) || ts.isTypeAliasDeclaration(node)) { const name = ts.isFunctionDeclaration(node) ? node.name?.text : ts.isVariableStatement(node) ? node.declarationList.declarations[0].name.getText() : node.name.text; if (name) { // Get JSDoc comment const jsDocComment = ts.getJSDocCommentsAndTags(node); if (jsDocComment.length > 0) { const jsDocText = jsDocComment[0].getText() || ''; // Extract description and parameters const description = jsDocText.match(/\/\*\*\s*\n\s*\*([^*\n]+)/)?.[1]?.trim() || ''; const params = Array.from(jsDocText.matchAll(/\* @param\s+(\w+)\s+([^*\n]+)/g)) .map((match) => ({ name: match[1], description: match[2].trim(), })); const returns = jsDocText.match(/\* @returns\s+([^*\n]+)/)?.[1]?.trim() || ''; const templates = Array.from(jsDocText.matchAll(/\* @template\s+(\w+)\s*-?\s*([^*\n]+)?/g)) .map((match) => ({ name: match[1], description: match[2]?.trim() || '', })); // Get example const example = examples.get(name); // Generate markdown markdown += `## ${name}\n\n`; markdown += `${description}\n\n`; if (templates.length > 0) { markdown += '### Type Parameters\n\n'; templates.forEach(template => { markdown += `- \`${template.name}\`${template.description ? `: ${template.description}` : ''}\n`; }); markdown += '\n'; } if (params.length > 0) { markdown += '### Parameters\n\n'; params.forEach(param => { markdown += `- \`${param.name}\`: ${param.description}\n`; }); markdown += '\n'; } if (returns) { markdown += `### Returns\n\n${returns}\n\n`; } if (example) { markdown += '### Example\n\n'; markdown += '```typescript\n'; // Remove leading spaces from each line while preserving relative indentation const formattedExample = example.split('\n') .map(line => line.replace(/^\s+/, '')) .join('\n'); markdown += formattedExample; markdown += '\n```\n\n'; } markdown += '---\n\n'; } } } ts.forEachChild(node, visitSource); }; // Visit both source files visitSource(outcomeSourceFile); visitSource(sourceSourceFile); // Write the markdown file fs.writeFileSync(path.join(__dirname, '../docs/g-std-docs.md'), markdown); console.log('Documentation has been generated in g-std-docs.md'); //# sourceMappingURL=generate-docs.js.map