UNPKG

lookatni-file-markers

Version:

Advanced file organization system with unique markers for code sharing and project management. Extract files from marked content, generate markers, and validate project integrity.

195 lines (194 loc) 7.82 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.MarkerGenerator = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); class MarkerGenerator { constructor(logger) { this.logger = logger; this.FS_CHAR = String.fromCharCode(28); } async generateMarkers(sourceFolder, outputFile, options, progressCallback) { const results = { sourceFolder, totalFiles: 0, totalBytes: 0, skippedFiles: [], fileTypes: {} }; const allFiles = this.getAllFiles(sourceFolder, options.excludePatterns); this.logger.info(`Found ${allFiles.length} files to process`); const filesToProcess = allFiles.filter(filePath => { try { const stats = fs.statSync(filePath); const sizeKB = stats.size / 1024; if (options.maxFileSize !== -1 && sizeKB > options.maxFileSize) { results.skippedFiles.push({ path: path.relative(sourceFolder, filePath), reason: `File too large (${sizeKB.toFixed(1)} KB > ${options.maxFileSize} KB)` }); return false; } if (this.isBinaryFile(filePath)) { results.skippedFiles.push({ path: path.relative(sourceFolder, filePath), reason: 'Binary file' }); return false; } return true; } catch (error) { results.skippedFiles.push({ path: path.relative(sourceFolder, filePath), reason: `Error reading file: ${error}` }); return false; } }); this.logger.info(`Processing ${filesToProcess.length} files after filtering`); let output = `//${this.FS_CHAR}/ PROJECT_INFO /${this.FS_CHAR}//\n`; output += `Project: ${path.basename(sourceFolder)}\n`; output += `Generated: ${new Date().toISOString()}\n`; output += `Total Files: ${filesToProcess.length}\n`; output += `Source: ${sourceFolder}\n\n`; for (let i = 0; i < filesToProcess.length; i++) { const filePath = filesToProcess[i]; const relativePath = path.relative(sourceFolder, filePath); if (progressCallback) { progressCallback(i + 1, filesToProcess.length); } try { const content = fs.readFileSync(filePath, 'utf-8'); const stats = fs.statSync(filePath); results.totalFiles++; results.totalBytes += stats.size; const ext = path.extname(filePath).toLowerCase() || 'no-extension'; results.fileTypes[ext] = (results.fileTypes[ext] || 0) + 1; output += `//${this.FS_CHAR}/ ${relativePath} /${this.FS_CHAR}//\n`; output += content; if (!content.endsWith('\n')) { output += '\n'; } output += '\n'; this.logger.debug(`Processed: ${relativePath} (${stats.size} bytes)`); } catch (error) { this.logger.error(`Error processing ${relativePath}:`, error); results.skippedFiles.push({ path: relativePath, reason: `Read error: ${error}` }); } } fs.writeFileSync(outputFile, output, 'utf-8'); this.logger.info(`Generated markers file: ${outputFile}`); return results; } getAllFiles(dir, excludePatterns) { const files = []; const traverse = (currentDir) => { try { const entries = fs.readdirSync(currentDir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(currentDir, entry.name); const relativePath = path.relative(dir, fullPath); if (this.shouldExclude(entry.name, relativePath, excludePatterns)) { continue; } if (entry.isDirectory()) { traverse(fullPath); } else if (entry.isFile()) { files.push(fullPath); } } } catch (error) { this.logger.warn(`Cannot read directory ${currentDir}:`, error); } }; traverse(dir); return files; } shouldExclude(name, relativePath, patterns) { for (const pattern of patterns) { if (pattern.includes('*')) { const regex = new RegExp(pattern.replace(/\*/g, '.*')); if (regex.test(name) || regex.test(relativePath)) { return true; } } else if (name === pattern || relativePath.includes(pattern)) { return true; } } return false; } isBinaryFile(filePath) { const binaryExtensions = [ '.exe', '.dll', '.so', '.dylib', '.bin', '.obj', '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.ico', '.webp', '.mp3', '.mp4', '.avi', '.mov', '.wav', '.ogg', '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.class', '.jar', '.war', '.ear', '.pyc', '.pyo', '.pyd', '.woff', '.woff2', '.ttf', '.otf', '.eot' ]; const ext = path.extname(filePath).toLowerCase(); if (binaryExtensions.includes(ext)) { return true; } try { const buffer = fs.readFileSync(filePath, { encoding: null, flag: 'r' }); if (buffer.length === 0) { return false; } const sampleSize = Math.min(1024, buffer.length); for (let i = 0; i < sampleSize; i++) { if (buffer[i] === 0) { return true; } } return false; } catch { return true; } } } exports.MarkerGenerator = MarkerGenerator;