Mercurial
view hg-web/src/index.html @ 120:cbbf78b17cfa
[Seobeo][Websocket] Created Web socket client logic.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Thu, 08 Jan 2026 03:19:59 -0800 |
| parents | 2301aeb7503b |
| children | ffb764d2fcc5 |
line wrap: on
line source
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Zenbu Repository</title> <link rel="stylesheet" href="/base.css"> <link rel="stylesheet" href="/index.css"> </head> <body> <main> <div class="header"> <h1>Zenbu Repository</h1> <p class="description">Browse and clone this mercurial repository</p> </div> <div class="clone-info"> <strong>Clone this repository:</strong><br> <code>hg clone http://zenbu.babocoder.com</code> </div> <div class="breadcrumb" id="breadcrumb"></div> <div class="file-list" id="fileList"></div> <div class="readme-section" id="readmeSection" style="display: none;"> <h2>README</h2> <div class="readme-content" id="readmeContent"></div> </div> <div class="empty-state" id="emptyState" style="display: none;"> <p>No files found in this directory</p> </div> </main> <script src="/markdown_to_html.js"></script> <script> const API_BASE = '/api/repo'; // Get current path from URL function getCurrentPath() { const params = new URLSearchParams(window.location.search); return params.get('path') || ''; } // Update URL without reloading function updateURL(path) { const url = path ? `?path=${encodeURIComponent(path)}` : '/'; window.history.pushState({path}, '', url); } // Render breadcrumb function renderBreadcrumb(path) { const breadcrumb = document.getElementById('breadcrumb'); if (!path) { breadcrumb.innerHTML = '<a href="/">Root</a>'; return; } const parts = path.split('/').filter(p => p); let currentPath = ''; let html = '<a href="/">Root</a>'; parts.forEach((part, index) => { currentPath += (currentPath ? '/' : '') + part; html += ` <span>/</span> `; if (index === parts.length - 1) { html += `<span>${part}</span>`; } else { html += `<a href="?path=${encodeURIComponent(currentPath)}">${part}</a>`; } }); breadcrumb.innerHTML = html; } // Render file list function renderFiles(files) { const fileList = document.getElementById('fileList'); const emptyState = document.getElementById('emptyState'); if (!files || files.length === 0) { fileList.style.display = 'none'; emptyState.style.display = 'block'; return; } emptyState.style.display = 'none'; fileList.style.display = 'block'; // Sort: directories first, then files, alphabetically files.sort((a, b) => { if (a.type !== b.type) { return a.type === 'directory' ? -1 : 1; } return a.name.localeCompare(b.name); }); let html = ''; files.forEach(file => { const icon = file.type === 'directory' ? '📁' : '📄'; const className = file.type; const href = file.type === 'directory' ? `?path=${encodeURIComponent(file.path)}` : `/api/repo/file?path=${encodeURIComponent(file.path)}`; const target = file.type === 'directory' ? '' : 'target="_blank"'; html += ` <div class="file-item ${className}"> <span class="icon">${icon}</span> <span class="name"> <a href="${href}" ${target}>${file.name}</a> </span> </div> `; }); fileList.innerHTML = html; } // Load and render README async function loadReadme(path) { const readmeSection = document.getElementById('readmeSection'); const readmeContent = document.getElementById('readmeContent'); try { const readmePath = path ? `${path}/README.md` : 'README.md'; const response = await fetch(`/api/repo/readme?path=${encodeURIComponent(readmePath)}`); if (response.ok) { const markdown = await response.text(); readmeSection.style.display = 'block'; renderMarkdown(readmeContent, markdown); } else { readmeSection.style.display = 'none'; } } catch (error) { readmeSection.style.display = 'none'; } } // Load directory contents async function loadDirectory(path) { try { const url = path ? `${API_BASE}/list?path=${encodeURIComponent(path)}` : `${API_BASE}/list`; const response = await fetch(url); const data = await response.json(); if (data.error) { throw new Error(data.error); } renderBreadcrumb(path); renderFiles(data.files); loadReadme(path); } catch (error) { console.error('Error loading directory:', error); document.getElementById('fileList').innerHTML = ` <div class="error-message">Error loading directory: ${error.message}</div> `; } } // Handle browser back/forward window.addEventListener('popstate', (event) => { const path = event.state?.path || ''; loadDirectory(path); }); // Initial load const currentPath = getCurrentPath(); loadDirectory(currentPath); </script> </body> </html>