view hg-web/src/index.html @ 113:7a4e942814bc

[MrJuneJune] Fixed static assets
author June Park <parkjune1995@gmail.com>
date Sun, 04 Jan 2026 14:42:54 -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>