@conjecture-dev/g-std
Version:
A collection of TypeScript utility functions for common programming tasks
132 lines • 6.27 kB
JavaScript
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