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
JavaScript
"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