UNPKG

structure-maker

Version:

Generate a folder structure with tech-specific icons

138 lines (113 loc) 4.1 kB
#!/usr/bin/env node import fs from 'fs'; import path from 'path'; import chalk from 'chalk'; import minimist from 'minimist'; const FILE_TYPE_ICONS = { '.js': '💻', '.ts': '💻', '.py': '💻', '.java': '💻', '.md': '📜', '.txt': '📜', '.json': '📊', '.jpg': '🖼️', '.png': '🖼️', '.gif': '🖼️', '.mp4': '🎥', '.avi': '🎥', '.mp3': '🎵', '.wav': '🎵', '.pdf': '📚', '.docx': '📚', }; function getFileIcon(fileName) { const ext = path.extname(fileName).toLowerCase(); return FILE_TYPE_ICONS[ext] || '📄'; } function generateTree(dir, prefix = "", colorize = false, depth = Infinity, currentDepth = 0, ignorePatterns = []) { if (currentDepth > depth) return { tree: '', fileCount: 0, folderCount: 0, fileTypes: {} }; const entries = fs .readdirSync(dir, { withFileTypes: true }) .filter( (e) => !['node_modules', '.git', '.expo', '.next', '.DS_Store', ...ignorePatterns].includes(e.name) ) .sort((a, b) => (a.isDirectory() ? -1 : 1)); let tree = ''; let fileCount = 0; let folderCount = 0; let fileTypes = {}; entries.forEach((entry, index) => { const isLast = index === entries.length - 1; const connector = isLast ? '└─' : '├─'; const fullPath = path.join(dir, entry.name); const icon = entry.isDirectory() ? '📁' : getFileIcon(entry.name); let displayName = colorize ? entry.isDirectory() ? `${chalk.blue(icon)} ${chalk.blue.bold(entry.name)}` : `${chalk.green(icon)} ${chalk.green(entry.name)}` : `${icon} ${entry.name}`; if (entry.isFile()) { const stats = fs.statSync(fullPath); const size = (stats.size / 1024).toFixed(1); displayName += ` (${size} KB)`; fileCount++; const ext = path.extname(entry.name).toLowerCase() || 'other'; fileTypes[ext] = (fileTypes[ext] || 0) + 1; } else { folderCount++; } tree += `${prefix}${connector} ${displayName}\n`; if (entry.isDirectory()) { const nextPrefix = prefix + (isLast ? ' ' : '│ '); const subtree = generateTree(fullPath, nextPrefix, colorize, depth, currentDepth + 1, ignorePatterns); tree += subtree.tree || ''; fileCount += subtree.fileCount || 0; folderCount += subtree.folderCount || 0; for (const [ext, count] of Object.entries(subtree.fileTypes || {})) { fileTypes[ext] = (fileTypes[ext] || 0) + count; } } }); return { tree, fileCount, folderCount, fileTypes }; } function main() { try { const args = minimist(process.argv.slice(2), { string: ['ignore', 'depth'], default: { ignore: '', depth: Infinity }, }); const ignorePatterns = args.ignore ? args.ignore.split(',').map((s) => s.trim()) : []; const depth = parseInt(args.depth) || Infinity; const currentDir = process.cwd(); const outputFile = 'folder-structure.md'; const rootName = path.basename(currentDir); const { tree, fileCount, folderCount, fileTypes } = generateTree(currentDir, '', false, depth, 0, ignorePatterns); const fileTypesSummary = Object.entries(fileTypes) .map(([ext, count]) => `- **${ext || 'other'}**: ${count}`) .join('\n'); const markdownContent = ` # Folder Structure ## Summary - **Total Folders**: ${folderCount} - **Total Files**: ${fileCount} - **Root Directory**: ${rootName} ### File Types ${fileTypesSummary} ## Table of Contents - [Directory Structure](#directory-structure) ## Directory Structure \`\`\` ${rootName}/ ${tree} \`\`\` `; fs.writeFileSync(outputFile, markdownContent); console.log(chalk.cyan(`✔ Folder structure saved to ${outputFile}`)); console.log(chalk.cyan(`Summary: ${folderCount} folders, ${fileCount} files`)); console.log(`${rootName}/\n${generateTree(currentDir, '', true, depth, 0, ignorePatterns).tree}`); } catch (err) { console.error(chalk.red('Error:', err.message)); } } main();