🐘
index.php
Back
📝 Php ⚡ Executable Ctrl+S: Save • Ctrl+R: Run • Ctrl+F: Find
/** * Editor Index (Simplified Universal Version) * ------------------------------------------- * - Loads the active file from localStorage * - Parses markers or auto-splits into blocks * - No Ace, overlay, or navigation dependencies * - Works directly with block_editor.js */ (function () { 'use strict'; console.log("[editor_index.js] Loading simplified index module..."); const ACTIVE_FILES_KEY = "sftp_active_files"; // ========================================================================= // LOCALSTORAGE HELPERS // ========================================================================= function getActiveFileContent() { try { const files = JSON.parse(localStorage.getItem(ACTIVE_FILES_KEY) || "[]"); const active = files.find(f => f.active); return { content: active?.content || "", name: active?.name || "Untitled", path: active?.path || "" }; } catch (err) { console.error("[editor_index.js] Failed to load file:", err); return { content: "", name: "Untitled", path: "" }; } } function getLines() { const { content } = getActiveFileContent(); return content.split("\n"); } function getLine(index) { const lines = getLines(); return lines[index] || ""; } function getLineCount() { return getLines().length; } // ========================================================================= // MARKER & LANGUAGE HELPERS // ========================================================================= function parseMarkerName(name) { const cleaned = name.replace(/[\[\]]/g, "").trim(); const parts = cleaned.split("_"); if (parts.length === 1) return { component: parts[0], language: null, number: null, fullName: cleaned }; if (parts.length === 2) return { component: parts[0], language: parts[1], number: null, fullName: cleaned }; const num = parseInt(parts[2]); return { component: parts[0], language: parts[1], number: isNaN(num) ? null : num, fullName: cleaned }; } function findMarkerEnd(startRow, markerName) { const lineCount = getLineCount(); for (let row = startRow + 1; row < lineCount; row++) { const line = getLine(row).trim(); if (line.includes(">")) { const m = line.match(/(?:<!--|\/\*|\/\/\/|\/\/)\s*([\w\-\[\]_]+)\s*>/); if (m && m[1].trim() === markerName) return row; } } return startRow; } function detectLanguage(fileName) { const ext = (fileName.split(".").pop() || "").toLowerCase(); if (["js", "jsx", "ts"].includes(ext)) return "javascript"; if (["html", "htm"].includes(ext)) return "html"; if (["css"].includes(ext)) return "css"; if (["php"].includes(ext)) return "php"; return "text"; } // ========================================================================= // BLOCK / INDEX GENERATION // ========================================================================= function generateDocumentIndex() { const { content, name } = getActiveFileContent(); const lines = content.split("\n"); const lineCount = lines.length; const components = {}; const unmarked = []; const markerRanges = []; // pass 1: find explicit markers for (let row = 0; row < lineCount; row++) { const line = lines[row].trim(); if (!line) continue; const open = line.match(/(?:<!--|\/\*|\/\/\/|\/\/)\s*([\w\-\[\]_]+)\s*</); if (open) { const markerName = open[1].trim(); const parsed = parseMarkerName(markerName); const endRow = findMarkerEnd(row, markerName); const markerItem = { type: "marker", row, endRow, label: markerName, parsed, children: [] }; markerRanges.push({ startRow: row, endRow, markerItem }); if (parsed.language) { if (!components[parsed.component]) components[parsed.component] = {}; if (!components[parsed.component][parsed.language]) components[parsed.component][parsed.language] = []; components[parsed.component][parsed.language].push(markerItem); } else { unmarked.push(markerItem); } } } // pass 2: detect functions/tags/classes for (let row = 0; row < lineCount; row++) { const line = lines[row].trim(); if (!line || line.match(/(?:<!--|\/\*|\/\/\/|\/\/)\s*[\w\-\[\]_]+\s*[<>]/)) continue; let match, item = null; if ((match = line.match(/(?:function|class)\s+(\w+)/))) { item = { type: "function", row, label: match[1] + "()", icon: "⚙️" }; } else if ((match = line.match(/^\.([\w-]+)\s*\{/))) { item = { type: "css", row, label: "." + match[1], icon: "🎨" }; } else if ((match = line.match(/^#([\w-]+)\s*\{/))) { item = { type: "css", row, label: "#" + match[1], icon: "🎨" }; } else if ((match = line.match(/^<(\w+)/))) { item = { type: "html", row, label: "<" + match[1] + ">", icon: "📦" }; } if (!item) continue; let belongsTo = null; for (const range of markerRanges) { if (row > range.startRow && row < range.endRow) { belongsTo = range.markerItem; break; } } if (belongsTo) belongsTo.children.push(item); else unmarked.push(item); } // fallback: if nothing found, split automatically if (Object.keys(components).length === 0 && unmarked.length === 0) { const lang = detectLanguage(name); const size = 30; for (let i = 0; i < lineCount; i += size) { unmarked.push({ label: `Block ${Math.floor(i / size) + 1}`, row: i, endRow: Math.min(i + size - 1, lineCount - 1), type: "auto", lang }); } } return { components, unmarked }; } // ========================================================================= // PUBLIC API // ========================================================================= window.EditorIndex = { generateDocumentIndex, findMarkerEnd, parseMarkerName, getActiveFileContent, getLines, getLine, getLineCount }; console.log("[editor_index.js] Ready (simplified)."); })();