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.

1,363 lines (1,326 loc) 112 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/extension.ts var extension_exports = {}; __export(extension_exports, { activate: () => activate, deactivate: () => deactivate }); module.exports = __toCommonJS(extension_exports); var vscode17 = __toESM(require("vscode")); // src/commands/automatedDemo.ts var vscode = __toESM(require("vscode")); var fs = __toESM(require("fs")); var path = __toESM(require("path")); var AutomatedDemoController = class { FS_CHAR = String.fromCharCode(28); demoDir; outputChannel; workspaceRoot; constructor() { this.workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || ""; this.demoDir = path.join(this.workspaceRoot, "demo-automated"); this.outputChannel = vscode.window.createOutputChannel("LookAtni Demo"); } async runAutomatedDemo() { try { this.outputChannel.show(); this.outputChannel.appendLine("\u{1F3AC} Starting Automated LookAtni Demo for Recording..."); this.outputChannel.appendLine("\u{1F4F9} Perfect for screen recording - smooth, automated workflow!"); await this.showWelcomeMessage(); await this.cleanEnvironment(); await this.createAIGeneratedContent(); await this.openAndShowcaseDemoFile(); await this.executeAICodeExtraction(); await this.showcaseResults(); await this.showCompletionMessage(); } catch (error) { this.outputChannel.appendLine(`\u274C Demo failed: ${error}`); vscode.window.showErrorMessage(`Demo failed: ${error}`); } } async showWelcomeMessage() { this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F680} Welcome to LookAtni File Markers Demo!"); this.outputChannel.appendLine("\u{1F4A1} The Golden Feature: AI Code Extraction"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F3AF} What you'll see:"); this.outputChannel.appendLine(" 1. AI-generated project in single document"); this.outputChannel.appendLine(" 2. Invisible Unicode markers (completely hidden)"); this.outputChannel.appendLine(" 3. One-click extraction to perfect file structure"); this.outputChannel.appendLine(" 4. Complete project ready to run!"); this.outputChannel.appendLine(""); await this.delay(3e3); } async showCompletionMessage() { this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F389} DEMO COMPLETED SUCCESSFULLY!"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u2728 What just happened:"); this.outputChannel.appendLine(" \u{1F916} AI generated a complete React project"); this.outputChannel.appendLine(" \u{1F4C4} Single document with invisible markers"); this.outputChannel.appendLine(" \u26A1 One command extracted perfect file structure"); this.outputChannel.appendLine(" \u{1F3D7}\uFE0F Ready-to-run project created instantly!"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F3AF} The Golden Feature in action!"); this.outputChannel.appendLine("\u{1F4AB} From AI chat to working project in seconds!"); this.outputChannel.appendLine(""); await this.delay(2e3); } /** * Comprehensive environment cleanup for demo recording */ async cleanEnvironment() { this.outputChannel.appendLine("\u{1F9F9} Performing comprehensive environment cleanup..."); await vscode.commands.executeCommand("workbench.action.closeAllEditors"); await this.delay(500); this.outputChannel.clear(); const cleanupPaths = [ "demo-automated", "lookatni-demo-*", "extracted-project", "ai-generated-*", "demo-*", "test-*" ]; for (const pattern of cleanupPaths) { await this.removeDirectoriesMatching(pattern); } fs.mkdirSync(this.demoDir, { recursive: true }); await this.resetWorkspaceView(); this.outputChannel.appendLine("\u2705 Environment completely cleaned and prepared for recording"); await this.delay(1e3); } /** * Remove directories matching a pattern */ async removeDirectoriesMatching(pattern) { try { const entries = fs.readdirSync(this.workspaceRoot, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory()) { const shouldRemove = pattern.includes("*") ? entry.name.startsWith(pattern.replace("*", "")) : entry.name === pattern; if (shouldRemove) { const fullPath = path.join(this.workspaceRoot, entry.name); fs.rmSync(fullPath, { recursive: true, force: true }); this.outputChannel.appendLine(`\u{1F5D1}\uFE0F Removed: ${entry.name}`); } } } } catch (error) { } } /** * Reset VS Code workspace view for clean recording */ async resetWorkspaceView() { await vscode.commands.executeCommand("workbench.action.closeSidebar"); await vscode.commands.executeCommand("workbench.action.closePanel"); await this.delay(300); await vscode.commands.executeCommand("workbench.view.explorer"); await this.delay(300); await vscode.commands.executeCommand("workbench.files.action.collapseExplorerFolders"); await this.delay(500); } async createAIGeneratedContent() { this.outputChannel.appendLine("\u{1F916} Creating AI-generated React project..."); this.outputChannel.appendLine('\u{1F4AD} Simulating: "ChatGPT, create a React project with LookAtni markers"'); const demoContent = this.generateDemoContent(); const demoFile = path.join(this.demoDir, "ai-generated-react-project.txt"); fs.writeFileSync(demoFile, demoContent); this.outputChannel.appendLine("\u2705 AI response received with invisible markers!"); this.outputChannel.appendLine(`\u{1F4CD} Saved to: ai-generated-react-project.txt`); this.outputChannel.appendLine("\u{1F50D} Notice: Markers are completely invisible to you!"); await this.delay(2e3); } async openAndShowcaseDemoFile() { this.outputChannel.appendLine("\u{1F4D6} Opening the AI-generated content..."); const demoFile = path.join(this.demoDir, "ai-generated-react-project.txt"); const document = await vscode.workspace.openTextDocument(demoFile); await vscode.window.showTextDocument(document); await vscode.commands.executeCommand("workbench.action.focusActiveEditorGroup"); this.outputChannel.appendLine("\u{1F440} Look at this - a complete React project in one document!"); this.outputChannel.appendLine("\u{1F52E} The invisible markers are there, but you can't see them"); this.outputChannel.appendLine("\u26A1 Ready for the magic extraction..."); await this.delay(3e3); return document; } async executeAICodeExtraction() { this.outputChannel.appendLine("\u{1F3AF} Executing the Golden Feature - AI Code Extraction!"); this.outputChannel.appendLine("\u26A1 Right-click \u2192 LookAtni: Extract Files"); await this.delay(1e3); try { const extractDir = path.join(this.demoDir, "extracted-react-project"); fs.mkdirSync(extractDir, { recursive: true }); this.outputChannel.appendLine("\u{1F680} Executing extraction command..."); await vscode.commands.executeCommand("lookatni-file-markers.extractFiles"); this.outputChannel.appendLine("\u2705 Extraction command executed!"); await this.delay(2e3); } catch (error) { this.outputChannel.appendLine("\u{1F4CB} Extraction command triggered - follow VS Code prompts"); this.outputChannel.appendLine("\u{1F4A1} Select the extracted-react-project folder as destination"); await this.delay(3e3); } } async showcaseResults() { this.outputChannel.appendLine("\u{1F38A} Showcasing the Amazing Results!"); const extractDir = path.join(this.demoDir, "extracted-react-project"); if (fs.existsSync(extractDir)) { this.outputChannel.appendLine("\uFFFD Opening extracted project structure..."); await this.displayProjectStructure(extractDir); await this.showcaseExtractedFiles(extractDir); } else { this.outputChannel.appendLine("\u{1F4CB} Check your file explorer - perfect project structure created!"); } await this.delay(2e3); } async displayProjectStructure(extractDir) { this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F3D7}\uFE0F EXTRACTED PROJECT STRUCTURE:"); this.outputChannel.appendLine("\u251C\u2500\u2500 package.json (Complete package config)"); this.outputChannel.appendLine("\u251C\u2500\u2500 README.md (Project documentation)"); this.outputChannel.appendLine("\u251C\u2500\u2500 public/"); this.outputChannel.appendLine("\u2502 \u2514\u2500\u2500 index.html (HTML template)"); this.outputChannel.appendLine("\u2514\u2500\u2500 src/"); this.outputChannel.appendLine(" \u251C\u2500\u2500 index.js (React entry point)"); this.outputChannel.appendLine(" \u251C\u2500\u2500 App.js (Main component)"); this.outputChannel.appendLine(" \u2514\u2500\u2500 App.css (Styling)"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F3AF} From AI chat to ready project in ONE CLICK!"); this.outputChannel.appendLine(""); } async showcaseExtractedFiles(extractDir) { const filesToShow = [ "package.json", "src/App.js" ]; for (const file of filesToShow) { const filePath = path.join(extractDir, file); if (fs.existsSync(filePath)) { const document = await vscode.workspace.openTextDocument(filePath); await vscode.window.showTextDocument(document, vscode.ViewColumn.Beside); await this.delay(1500); } } this.outputChannel.appendLine("\u{1F440} See? Real, working files extracted perfectly!"); this.outputChannel.appendLine("\u{1F680} Project is ready to run: npm start"); } generateDemoContent() { return `\u{1F916} AI-Generated React Project with LookAtni File Markers This content was generated by AI and can be extracted into a complete project structure! ${this.FS_CHAR}/ package.json /${this.FS_CHAR}// { "name": "ai-demo-project", "version": "1.0.0", "description": "Demo project generated by AI with LookAtni markers", "main": "src/index.js", "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test" }, "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1" } } ${this.FS_CHAR}/ README.md /${this.FS_CHAR}// # \u{1F680} AI Demo Project This project was generated by AI and extracted using **LookAtni File Markers**! ## The Magic - Generated in a single document by AI - Extracted automatically with invisible markers - Perfect file structure created instantly - Zero manual file creation needed ## Features - \u26A1 React-based frontend - \u{1F3A8} Modern styling - \u{1F504} Hot reloading - \u{1F4E6} Production builds Generated with invisible Unicode markers! ${this.FS_CHAR}/ src/index.js /${this.FS_CHAR}// import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> ); ${this.FS_CHAR}/ src/App.js /${this.FS_CHAR}// import React, { useState } from 'react'; import './App.css'; function App() { const [count, setCount] = useState(0); return ( <div className="App"> <header className="App-header"> <h1>\u{1F916} AI-Generated React App</h1> <p>Extracted with LookAtni File Markers!</p> <div className="counter"> <button onClick={() => setCount(count - 1)}>-</button> <span className="count">{count}</span> <button onClick={() => setCount(count + 1)}>+</button> </div> <p className="description"> This entire project was generated by AI in a single document, then extracted into perfect file structure using invisible markers. \u{1F3AF} The Golden Feature in action! </p> </header> </div> ); } export default App; ${this.FS_CHAR}/ src/App.css /${this.FS_CHAR}// .App { text-align: center; } .App-header { background-color: #282c34; padding: 20px; color: white; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); } .counter { margin: 20px 0; display: flex; align-items: center; gap: 20px; } .counter button { background: #61dafb; border: none; color: #282c34; font-size: 24px; font-weight: bold; width: 50px; height: 50px; border-radius: 50%; cursor: pointer; transition: transform 0.2s; } .counter button:hover { transform: scale(1.1); } .count { font-size: 48px; font-weight: bold; color: #61dafb; min-width: 100px; } .description { font-size: 16px; max-width: 600px; line-height: 1.5; margin-top: 30px; opacity: 0.8; } ${this.FS_CHAR}/ public/index.html /${this.FS_CHAR}// <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="AI-generated React app extracted with LookAtni" /> <title>\u{1F916} AI Demo Project - LookAtni File Markers</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> </body> </html>`; } delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } }; function registerAutomatedDemoCommand(context) { const disposable = vscode.commands.registerCommand("lookatni.automatedDemo", async () => { const demo = new AutomatedDemoController(); await demo.runAutomatedDemo(); }); context.subscriptions.push(disposable); } // src/commands/configurationCommand.ts var vscode3 = __toESM(require("vscode")); // src/utils/configManager.ts var vscode2 = __toESM(require("vscode")); var ConfigurationManager = class _ConfigurationManager { static DEFAULT_CONFIG = { visualMarkers: { readIcon: "\u2713", unreadIcon: "\u25CF", favoriteIcon: "\u2605", importantIcon: "!", todoIcon: "\u25CB", customIcon: "\u25C6", autoSave: true, showInStatusBar: true }, defaultMaxFileSize: 1e3, showStatistics: true, autoValidate: false }; static instance; config; constructor() { this.config = this.loadConfiguration(); this.setupConfigurationWatcher(); } static getInstance() { if (!_ConfigurationManager.instance) { _ConfigurationManager.instance = new _ConfigurationManager(); } return _ConfigurationManager.instance; } loadConfiguration() { try { const vscodeConfig = vscode2.workspace.getConfiguration("lookatni"); return { visualMarkers: { readIcon: this.getSafeConfig(vscodeConfig, "visualMarkers.readIcon", "\u2713"), unreadIcon: this.getSafeConfig(vscodeConfig, "visualMarkers.unreadIcon", "\u25CF"), favoriteIcon: this.getSafeConfig(vscodeConfig, "visualMarkers.favoriteIcon", "\u2605"), importantIcon: this.getSafeConfig(vscodeConfig, "visualMarkers.importantIcon", "!"), todoIcon: this.getSafeConfig(vscodeConfig, "visualMarkers.todoIcon", "\u25CB"), customIcon: this.getSafeConfig(vscodeConfig, "visualMarkers.customIcon", "\u25C6"), autoSave: this.getSafeConfig(vscodeConfig, "visualMarkers.autoSave", true), showInStatusBar: this.getSafeConfig(vscodeConfig, "visualMarkers.showInStatusBar", true) }, defaultMaxFileSize: this.getSafeConfig(vscodeConfig, "defaultMaxFileSize", 1e3), showStatistics: this.getSafeConfig(vscodeConfig, "showStatistics", true), autoValidate: this.getSafeConfig(vscodeConfig, "autoValidate", false) }; } catch (error) { console.warn("Failed to load LookAtni configuration, using defaults:", error); return { ..._ConfigurationManager.DEFAULT_CONFIG }; } } getSafeConfig(config, key, defaultValue) { try { const value = config.get(key); if (value !== void 0 && value !== null) { if (typeof defaultValue === "string" && typeof value === "string") { const trimmedValue = value.trim(); return trimmedValue || defaultValue; } return value; } return defaultValue; } catch (error) { console.warn(`Failed to get config for ${key}, using default:`, error); return defaultValue; } } setupConfigurationWatcher() { vscode2.workspace.onDidChangeConfiguration((event) => { if (event.affectsConfiguration("lookatni")) { this.config = this.loadConfiguration(); this.notifyConfigurationChange(); } }); } notifyConfigurationChange() { vscode2.commands.executeCommand("lookatni.internal.configChanged"); } getConfig() { return { ...this.config }; } getVisualMarkersConfig() { return { ...this.config.visualMarkers }; } getIconForMarkerType(type) { const config = this.config.visualMarkers; const iconMap = { "read": config.readIcon, "unread": config.unreadIcon, "favorite": config.favoriteIcon, "important": config.importantIcon, "todo": config.todoIcon, "custom": config.customIcon }; return iconMap[type] || config.customIcon; } async validateConfiguration() { const issues = []; const config = this.config; Object.entries(config.visualMarkers).forEach(([key, value]) => { if (key.endsWith("Icon") && typeof value === "string" && !value.trim()) { issues.push(`Visual marker icon for ${key} is empty`); } }); if (config.defaultMaxFileSize <= 0) { issues.push("Default max file size must be greater than 0"); } const iconRegex = /^[\p{L}\p{N}\p{P}\p{S}\p{M}]+$/u; Object.entries(config.visualMarkers).forEach(([key, value]) => { if (key.endsWith("Icon") && typeof value === "string" && value && !iconRegex.test(value)) { issues.push(`Invalid characters in ${key}: ${value}`); } }); return { isValid: issues.length === 0, issues }; } async resetToDefaults() { const config = vscode2.workspace.getConfiguration("lookatni"); try { for (const [section, values] of Object.entries(_ConfigurationManager.DEFAULT_CONFIG)) { if (typeof values === "object" && values !== null) { for (const [key, defaultValue] of Object.entries(values)) { await config.update(`${section}.${key}`, defaultValue, vscode2.ConfigurationTarget.Global); } } else { await config.update(section, values, vscode2.ConfigurationTarget.Global); } } vscode2.window.showInformationMessage("LookAtni configuration reset to defaults"); } catch (error) { vscode2.window.showErrorMessage(`Failed to reset configuration: ${error}`); } } async exportConfiguration() { return JSON.stringify({ version: "1.0.0", exportDate: (/* @__PURE__ */ new Date()).toISOString(), configuration: this.config }, null, 2); } async importConfiguration(configJson) { try { const importData = JSON.parse(configJson); const config = vscode2.workspace.getConfiguration("lookatni"); if (importData.configuration) { for (const [section, values] of Object.entries(importData.configuration)) { if (typeof values === "object" && values !== null) { for (const [key, value] of Object.entries(values)) { await config.update(`${section}.${key}`, value, vscode2.ConfigurationTarget.Global); } } else { await config.update(section, values, vscode2.ConfigurationTarget.Global); } } } vscode2.window.showInformationMessage("Configuration imported successfully"); } catch (error) { throw new Error(`Failed to import configuration: ${error}`); } } }; // src/commands/configurationCommand.ts var ConfigurationCommand = class { constructor(context, logger, outputChannel) { this.context = context; this.logger = logger; this.outputChannel = outputChannel; } commandId = "lookatni.configuration"; async execute() { this.logger.info("\u{1F527} Starting configuration management..."); try { const action = await this.showConfigurationMenu(); if (action) { await this.executeAction(action); } } catch (error) { this.logger.error("Error in configuration command:", error); vscode3.window.showErrorMessage(`Configuration Error: ${error}`); } } async showConfigurationMenu() { const options = [ { label: "$(gear) Validate Configuration", description: "Check current configuration for issues", action: "validate" }, { label: "$(refresh) Reset to Defaults", description: "Reset all LookAtni settings to default values", action: "reset" }, { label: "$(export) Export Configuration", description: "Export current configuration to file", action: "export" }, { label: "$(import) Import Configuration", description: "Import configuration from file", action: "import" }, { label: "$(eye) Show Current Settings", description: "Display current configuration values", action: "show" }, { label: "$(settings-gear) Open Settings", description: "Open VS Code settings for LookAtni", action: "openSettings" } ]; const selected = await vscode3.window.showQuickPick(options, { placeHolder: "LookAtni Configuration Management", title: "Configuration Options" }); return selected?.action; } async executeAction(action) { const configManager = ConfigurationManager.getInstance(); switch (action) { case "validate": await this.validateConfiguration(configManager); break; case "reset": await this.resetConfiguration(configManager); break; case "export": await this.exportConfiguration(configManager); break; case "import": await this.importConfiguration(configManager); break; case "show": await this.showCurrentConfiguration(configManager); break; case "openSettings": await vscode3.commands.executeCommand("workbench.action.openSettings", "lookatni"); break; } } async validateConfiguration(configManager) { const validation = await configManager.validateConfiguration(); this.outputChannel.appendLine("\n=== CONFIGURATION VALIDATION ==="); if (validation.isValid) { this.outputChannel.appendLine("\u2705 Configuration is valid"); vscode3.window.showInformationMessage("\u2705 LookAtni configuration is valid"); } else { this.outputChannel.appendLine("\u274C Configuration has issues:"); validation.issues.forEach((issue) => { this.outputChannel.appendLine(` \u2022 ${issue}`); }); const action = await vscode3.window.showWarningMessage( `Configuration has ${validation.issues.length} issue(s). View details?`, "View Details", "Reset to Defaults", "Ignore" ); if (action === "View Details") { this.outputChannel.show(); } else if (action === "Reset to Defaults") { await this.resetConfiguration(configManager); } } } async resetConfiguration(configManager) { const confirmation = await vscode3.window.showWarningMessage( "Are you sure you want to reset all LookAtni settings to defaults?", { modal: true }, "Yes, Reset All", "Cancel" ); if (confirmation === "Yes, Reset All") { await configManager.resetToDefaults(); this.outputChannel.appendLine("\n=== CONFIGURATION RESET ==="); this.outputChannel.appendLine("\u2705 Configuration reset to defaults"); } } async exportConfiguration(configManager) { try { const configJson = await configManager.exportConfiguration(); const saveUri = await vscode3.window.showSaveDialog({ defaultUri: vscode3.Uri.file("lookatni-config-export.json"), filters: { "JSON": ["json"], "All Files": ["*"] } }); if (saveUri) { await vscode3.workspace.fs.writeFile(saveUri, Buffer.from(configJson)); vscode3.window.showInformationMessage(`Configuration exported to ${saveUri.fsPath}`); this.outputChannel.appendLine(`\u2705 Configuration exported to: ${saveUri.fsPath}`); } } catch (error) { vscode3.window.showErrorMessage(`Export failed: ${error}`); } } async importConfiguration(configManager) { try { const openUri = await vscode3.window.showOpenDialog({ filters: { "JSON": ["json"], "All Files": ["*"] }, canSelectMany: false }); if (openUri && openUri[0]) { const fileData = await vscode3.workspace.fs.readFile(openUri[0]); const jsonData = Buffer.from(fileData).toString(); await configManager.importConfiguration(jsonData); this.outputChannel.appendLine(`\u2705 Configuration imported from: ${openUri[0].fsPath}`); } } catch (error) { vscode3.window.showErrorMessage(`Import failed: ${error}`); } } async showCurrentConfiguration(configManager) { const config = configManager.getConfig(); let content = "# LookAtni Configuration\n\n"; content += `**Generated:** ${(/* @__PURE__ */ new Date()).toLocaleString()} `; content += "## Visual Markers\n\n"; content += `- **Read Icon:** ${config.visualMarkers.readIcon} `; content += `- **Unread Icon:** ${config.visualMarkers.unreadIcon} `; content += `- **Favorite Icon:** ${config.visualMarkers.favoriteIcon} `; content += `- **Important Icon:** ${config.visualMarkers.importantIcon} `; content += `- **Todo Icon:** ${config.visualMarkers.todoIcon} `; content += `- **Custom Icon:** ${config.visualMarkers.customIcon} `; content += `- **Auto Save:** ${config.visualMarkers.autoSave} `; content += `- **Show in Status Bar:** ${config.visualMarkers.showInStatusBar} `; content += "## File Processing\n\n"; content += `- **Default Max File Size:** ${config.defaultMaxFileSize} KB `; content += `- **Show Statistics:** ${config.showStatistics} `; content += `- **Auto Validate:** ${config.autoValidate} `; content += "## Configuration Commands\n\n"; content += "Use `LookAtni: Configuration` to manage these settings.\n"; const doc = await vscode3.workspace.openTextDocument({ content, language: "markdown" }); await vscode3.window.showTextDocument(doc); } async validateConfigurationOnStartup() { const configManager = ConfigurationManager.getInstance(); const validation = await configManager.validateConfiguration(); if (!validation.isValid) { this.logger.warn("Configuration validation failed on startup"); validation.issues.forEach((issue) => { this.logger.warn(`Config issue: ${issue}`); }); const action = await vscode3.window.showWarningMessage( "LookAtni configuration has issues. Would you like to fix them?", "Fix Now", "Later" ); if (action === "Fix Now") { await this.execute(); } } } }; // src/commands/extractFiles.ts var vscode4 = __toESM(require("vscode")); var fs2 = __toESM(require("fs")); // src/utils/coreBridge.ts var path2 = __toESM(require("path")); function tryLoadCore() { try { return require("../../core/dist/lib/index.js"); } catch (_) { try { return require(path2.join(__dirname, "..", "..", "..", "core", "dist", "lib", "index.js")); } catch (e) { return null; } } } function extractWithCore(markedFile, destFolder, options, logger) { const core = tryLoadCore(); if (!core) { throw new Error("LookAtni core library not found. Build core first (cd core && npm run build)."); } const extractor = core.createExtractor ? core.createExtractor() : new core.MarkerExtractor(); return extractor.extractFromFile( markedFile, destFolder, { overwriteExisting: options.overwrite ?? false, createDirectories: options.createDirs ?? true, validateChecksums: false, preserveTimestamps: true, progressCallback: () => { }, conflictCallback: () => "skip", dryRun: options.dryRun ?? false, conflictResolution: "skip" } ); } async function generateWithCore(sourceFolder, outputFile, options, onProgress) { const core = tryLoadCore(); if (!core) { throw new Error("LookAtni core library not found. Build core first (cd core && npm run build)."); } const generator = core.createGenerator ? core.createGenerator() : new core.MarkerGenerator(); return generator.generateToFile( sourceFolder, outputFile, { maxFileSize: options.maxFileSize, excludePatterns: options.excludePatterns, includeMetadata: true, includeBinaryFiles: false, encoding: "utf-8", preserveTimestamps: true, customMetadata: {}, validateBeforeGeneration: false, progressCallback: (p) => { if (onProgress) { onProgress(p.percentage ?? 0, p.currentFile ?? ""); } } } ); } async function validateWithCore(markerFile) { const core = tryLoadCore(); if (!core) { throw new Error("LookAtni core library not found. Build core first (cd core && npm run build)."); } const validator = core.createValidator ? core.createValidator() : new core.MarkerValidator(); return validator.validateFile(markerFile); } // src/commands/extractFiles.ts var ExtractFilesCommand = class { constructor(context, logger, outputChannel) { this.context = context; this.logger = logger; this.outputChannel = outputChannel; } commandId = "lookatni-file-markers.extractFiles"; async execute(uri) { this.logger.info("\u{1F504} Starting file extraction..."); try { const markedFile = await this.getMarkedFile(uri); if (!markedFile) { return; } const destFolder = await this.getDestinationFolder(); if (!destFolder) { return; } const options = await this.getExtractionOptions(); if (!options) { return; } const results = await vscode4.window.withProgress({ location: vscode4.ProgressLocation.Notification, title: "Extracting files...", cancellable: false }, async () => { const res = await extractWithCore(markedFile, destFolder, options, this.logger); return { success: res.success, extractedFiles: res.extractedFiles, errors: res.errors }; }); this.showResults(results, destFolder); const openFolder = await vscode4.window.showInformationMessage( `\u2705 Extracted ${results.extractedFiles.length} files`, "Open Folder" ); if (openFolder === "Open Folder") { vscode4.commands.executeCommand("revealFileInOS", vscode4.Uri.file(destFolder)); } } catch (error) { this.logger.error("Error during extraction:", error); vscode4.window.showErrorMessage(`Extraction failed: ${error}`); } } async getMarkedFile(uri) { if (uri && uri.fsPath && fs2.existsSync(uri.fsPath)) { return uri.fsPath; } const fileUri = await vscode4.window.showOpenDialog({ canSelectMany: false, canSelectFiles: true, canSelectFolders: false, openLabel: "Select marked file to extract", filters: { "LookAtni Files": ["txt", "md"], "All Files": ["*"] } }); return fileUri?.[0]?.fsPath; } async getDestinationFolder() { const folderUri = await vscode4.window.showOpenDialog({ canSelectMany: false, canSelectFiles: false, canSelectFolders: true, openLabel: "Select destination folder" }); return folderUri?.[0]?.fsPath; } async getExtractionOptions() { return { overwrite: true, createDirs: true }; } showResults(results, destFolder) { this.outputChannel.appendLine("\n=== EXTRACTION RESULTS ==="); this.outputChannel.appendLine(`\u{1F4C1} Destination: ${destFolder}`); this.outputChannel.appendLine(`\u2705 Files extracted: ${results.extractedFiles.length}`); this.outputChannel.show(); } }; // src/commands/generateMarkers.ts var vscode5 = __toESM(require("vscode")); var fs3 = __toESM(require("fs")); var path3 = __toESM(require("path")); var GenerateMarkersCommand = class { constructor(context, logger, outputChannel) { this.context = context; this.logger = logger; this.outputChannel = outputChannel; } commandId = "lookatni-file-markers.generateMarkers"; async execute(uri) { this.logger.info("\u{1F504} Starting marker generation..."); try { const sourceFolder = await this.getSourceFolder(uri); if (!sourceFolder) { return; } const outputFile = await this.getOutputFile(sourceFolder); if (!outputFile) { return; } const options = await this.getGenerationOptions(); if (!options) { return; } const results = await vscode5.window.withProgress({ location: vscode5.ProgressLocation.Notification, title: "Generating markers...", cancellable: false }, async (progress) => { await generateWithCore(sourceFolder, outputFile, options, (pct) => { progress.report({ increment: 0, message: `${pct}%` }); }); return { sourceFolder, totalFiles: 0, totalBytes: 0, skippedFiles: [], fileTypes: {} }; }); this.showResults(results, outputFile); const openFile = await vscode5.window.showInformationMessage( `\u2705 Generated markers for ${results.totalFiles} files`, "Open File", "Copy Path" ); if (openFile === "Open File") { const document = await vscode5.workspace.openTextDocument(outputFile); vscode5.window.showTextDocument(document); } else if (openFile === "Copy Path") { vscode5.env.clipboard.writeText(outputFile); vscode5.window.showInformationMessage("Path copied to clipboard!"); } } catch (error) { this.logger.error("Error during generation:", error); vscode5.window.showErrorMessage(`Generation failed: ${error}`); } } async getSourceFolder(uri) { if (uri && uri.fsPath) { const stat = fs3.statSync(uri.fsPath); if (stat.isDirectory()) { return uri.fsPath; } } if (vscode5.workspace.workspaceFolders && vscode5.workspace.workspaceFolders.length > 0) { const workspaceRoot = vscode5.workspace.workspaceFolders[0].uri.fsPath; const choice = await vscode5.window.showQuickPick([ { label: "\u{1F4C1} Entire Workspace", description: "Generate from workspace root", path: workspaceRoot }, { label: "\u{1F4C2} Choose Subfolder...", description: "Select specific folder", path: "custom" } ], { placeHolder: "Select source folder" }); if (!choice) { return void 0; } if (choice.path === "custom") { const folderUri2 = await vscode5.window.showOpenDialog({ canSelectMany: false, canSelectFiles: false, canSelectFolders: true, openLabel: "Select source folder" }); return folderUri2?.[0]?.fsPath; } return choice.path; } const folderUri = await vscode5.window.showOpenDialog({ canSelectMany: false, canSelectFiles: false, canSelectFolders: true, openLabel: "Select source folder" }); return folderUri?.[0]?.fsPath; } async getOutputFile(sourceFolder) { const baseName = path3.basename(sourceFolder); const defaultName = `${baseName}-lookatni.lkt.txt`; const result = await vscode5.window.showInputBox({ prompt: "Enter output file name", value: defaultName, validateInput: (value) => { if (!value.trim()) { return "File name cannot be empty"; } if (!/\.(txt|md)$/i.test(value)) { return "File should have .txt or .md extension"; } return null; } }); if (!result) { return void 0; } if (vscode5.workspace.workspaceFolders && vscode5.workspace.workspaceFolders.length > 0) { const workspaceRoot = vscode5.workspace.workspaceFolders[0].uri.fsPath; return path3.join(workspaceRoot, result); } return path3.join(path3.dirname(sourceFolder), result); } async getGenerationOptions() { const options = {}; const maxSize = await vscode5.window.showQuickPick([ { label: "500 KB", description: "Small files only", value: 500 }, { label: "1 MB", description: "Medium files (recommended)", value: 1e3 }, { label: "5 MB", description: "Large files", value: 5e3 }, { label: "No limit", description: "Include all files", value: -1 } ], { placeHolder: "Select maximum file size to include" }); if (!maxSize) { return void 0; } options.maxFileSize = maxSize.value; const excludeChoice = await vscode5.window.showQuickPick([ { label: "Standard exclusions", description: "node_modules, .git, build folders", value: "standard" }, { label: "Minimal exclusions", description: "Only hidden files", value: "minimal" }, { label: "Custom exclusions", description: "Specify patterns", value: "custom" } ], { placeHolder: "Select exclusion strategy" }); if (!excludeChoice) { return void 0; } switch (excludeChoice.value) { case "standard": options.excludePatterns = [ "node_modules", ".git", ".svn", ".hg", "build", "dist", "out", "target", "__pycache__", ".pytest_cache", ".vscode", "*.log", "*.tmp", "*.cache" ]; break; case "minimal": options.excludePatterns = [".*"]; break; case "custom": const patterns = await vscode5.window.showInputBox({ prompt: "Enter exclusion patterns (comma-separated)", placeHolder: "e.g., node_modules, *.log, build", value: "node_modules, .git, build" }); if (patterns) { options.excludePatterns = patterns.split(",").map((p) => p.trim()); } else { options.excludePatterns = []; } break; } return options; } showResults(results, outputFile) { const { totalFiles, totalBytes, skippedFiles } = results; this.outputChannel.appendLine("\n=== GENERATION RESULTS ==="); this.outputChannel.appendLine(`\u{1F4C1} Source: ${results.sourceFolder}`); this.outputChannel.appendLine(`\u{1F4C4} Output: ${outputFile}`); this.outputChannel.appendLine(`\u2705 Files processed: ${totalFiles}`); this.outputChannel.appendLine(`\u{1F4CA} Total size: ${this.formatBytes(totalBytes)}`); this.outputChannel.appendLine(`\u23ED\uFE0F Files skipped: ${skippedFiles.length}`); if (skippedFiles.length > 0) { this.outputChannel.appendLine("\n=== SKIPPED FILES ==="); skippedFiles.forEach((file) => { this.outputChannel.appendLine(`\u23ED\uFE0F ${file.path}: ${file.reason}`); }); } const config = vscode5.workspace.getConfiguration("lookatni"); if (config.get("showStatistics", true)) { vscode5.commands.executeCommand("lookatni-file-markers.showStatistics", results); } } formatBytes(bytes) { if (bytes === 0) { return "0 B"; } const k = 1024; const sizes = ["B", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i]; } }; // src/commands/openCLI.ts var fs4 = __toESM(require("fs")); var path4 = __toESM(require("path")); var vscode6 = __toESM(require("vscode")); var OpenCLICommand = class { constructor(context, logger, outputChannel) { this.context = context; this.logger = logger; this.outputChannel = outputChannel; } commandId = "lookatni-file-markers.openCLI"; // ASCII 28 (File Separator) character for invisible markers FS_CHAR = String.fromCharCode(28); async execute() { this.logger.info("\u{1F527} Opening LookAtni CLI tools..."); try { const cliPath = await this.findCLITools(); if (cliPath) { await this.showCLIOptions(cliPath); } else { await this.offerCLIInstallation(); } } catch (error) { this.logger.error("Error opening CLI:", error); vscode6.window.showErrorMessage(`CLI access failed: ${error}`); } } async findCLITools() { const possiblePaths = [ // Check extension resources path4.join(this.context.extensionPath, "cli"), // Check workspace vscode6.workspace.workspaceFolders?.[0]?.uri.fsPath + "/cli", // Check parent directories vscode6.workspace.workspaceFolders?.[0]?.uri.fsPath + "/../kortex", // Check common locations path4.join(require("os").homedir(), ".lookatni"), "/usr/local/bin/lookatni", "C:\\Program Files\\LookAtni" ]; for (const possiblePath of possiblePaths) { if (possiblePath && fs4.existsSync(possiblePath)) { const packageJsonPath = path4.join(possiblePath, "package.json"); if (fs4.existsSync(packageJsonPath)) { try { const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf8")); if (packageJson.scripts && packageJson.scripts["lookatni:extract"] && packageJson.scripts["lookatni:generate"]) { this.logger.info(`Found LookAtni npm scripts at: ${possiblePath}`); return possiblePath; } } catch (error) { } } } } return void 0; } async showCLIOptions(cliPath) { const choice = await vscode6.window.showQuickPick([ { label: "\u{1F4C2} Open CLI Folder", description: "Open the CLI tools folder in file explorer", action: "folder" }, { label: "\u26A1 Extract Files", description: "Run npm script: lookatni:extract", action: "extract" }, { label: "\u{1F3F7}\uFE0F Generate Markers", description: "Run npm script: lookatni:generate", action: "generate" }, { label: "\u{1F9EA} Run Tests", description: "Run npm script: lookatni:test", action: "test" }, { label: "\u{1F3AF} Quick Demo", description: "Run npm script: lookatni:demo", action: "demo" }, { label: "\u{1F4D6} Show Help", description: "Display CLI usage information", action: "help" } ], { placeHolder: "Choose CLI action" }); if (!choice) { return; } switch (choice.action) { case "folder": vscode6.commands.executeCommand("revealFileInOS", vscode6.Uri.file(cliPath)); break; case "extract": await this.runNpmScript("lookatni:extract"); break; case "generate": await this.runNpmScript("lookatni:generate"); break; case "test": await this.runNpmScript("lookatni:test"); break; case "demo": await this.runNpmScript("lookatni:demo"); break; case "help": this.showCLIHelp(cliPath); break; } } async runNpmScript(scriptName) { const workspaceRoot = vscode6.workspace.workspaceFolders?.[0]?.uri.fsPath; if (!workspaceRoot) { vscode6.window.showErrorMessage("No workspace folder found. Please open a folder first."); return; } const packageJsonPath = path4.join(workspaceRoot, "package.json"); if (!fs4.existsSync(packageJsonPath)) { vscode6.window.showErrorMessage("No package.json found in workspace root."); return; } let args = ""; if (scriptName === "lookatni:extract" || scriptName === "lookatni:generate") { const inputArgs = await vscode6.window.showInputBox({ prompt: `Enter arguments for ${scriptName} (or leave empty for interactive mode)`, placeHolder: "e.g., input.txt output_folder" }); if (inputArgs !== void 0) { args = inputArgs; } else { return; } } const terminal = vscode6.window.createTerminal({ name: `LookAtni CLI - ${scriptName}`, cwd: workspaceRoot }); const command = `npm run ${scriptName} ${args}`.trim(); terminal.sendText(command); terminal.show(); this.outputChannel.appendLine(`\u2705 Started ${scriptName} in terminal`); this.outputChannel.appendLine(`Working directory: ${workspaceRoot}`); this.outputChannel.appendLine(`Command: ${command}`); if (args) { this.outputChannel.appendLine(`Arguments: ${args}`); } } showCLIHelp(cliPath) { this.outputChannel.clear(); this.outputChannel.appendLine("=== LOOKATNI CLI TOOLS HELP ==="); this.outputChannel.appendLine(`\u{1F4C1} Location: ${cliPath}`); this.outputChannel.appendLine(""); this.outputChannel.appendLine("=== AVAILABLE SCRIPTS ==="); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F4E4} npm run lookatni:extract"); this.outputChannel.appendLine(" Extract files from marked content"); this.outputChannel.appendLine(" Usage: npm run lookatni:extract [marked_file] [output_dir]"); this.outputChannel.appendLine(" Options: --dry-run, --interactive, --force"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F4E5} npm run lookatni:generate"); this.outputChannel.appendLine(" Generate marked file from source directory"); this.outputChannel.appendLine(" Usage: npm run lookatni:generate [source_dir] [output_file]"); this.outputChannel.appendLine(" Options: --max-size, --exclude"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F9EA} npm run lookatni:test"); this.outputChannel.appendLine(" Run comprehensive tests of the LookAtni system"); this.outputChannel.appendLine(" Usage: npm run lookatni:test"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("\u{1F3AF} npm run lookatni:demo"); this.outputChannel.appendLine(" Run interactive demonstration"); this.outputChannel.appendLine(" Usage: npm run lookatni:demo"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("=== MARKER FORMAT ==="); this.outputChannel.appendLine("LookAtni uses invisible Unicode markers to separate files:"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("// Markers are invisible - shown as \u241C for demonstration only"); this.outputChannel.appendLine("//\u241C/ filename.ext /\u241C//"); this.outputChannel.appendLine("file content here..."); this.outputChannel.appendLine(""); this.outputChannel.appendLine("//\u241C/ another/file.txt /\u241C//"); this.outputChannel.appendLine("more content..."); this.outputChannel.appendLine(""); this.outputChannel.appendLine("=== EXAMPLES ==="); this.outputChannel.appendLine(""); this.outputChannel.appendLine("# Extract files from marked content:"); this.outputChannel.appendLine("npm run lookatni:extract project-marked.txt ./extracted"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("# Generate markers from a project:"); this.outputChannel.appendLine("npm run lookatni:generate ./my-project output.txt"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("# Interactive mode:"); this.outputChannel.appendLine("npm run lookatni:extract --interactive"); this.outputChannel.appendLine(""); this.outputChannel.appendLine("=== FEATURES ==="); this.outputChannel.appendLine("\u2705 Unique marker syntax that never conflicts"); this.outputChannel.appendLine("\u2705 Preserves directory structure"); this.outputChannel.appendLine("\u2705 Binary file detection and exclu