| Author | Dave Jarvis <email> |
|---|---|
| Date | 2026-01-14 22:40:02 GMT-0800 |
| Commit | 29c698f76e3f2df91739c8ac7a2bb19ca2e5be3d |
| Parent | 04707ac |
| -* { | ||
| - margin: 0; | ||
| - padding: 0; | ||
| - box-sizing: border-box; | ||
| -} | ||
| - | ||
| body { | ||
| - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; | ||
| - line-height: 1.6; | ||
| color: #e6edf3; | ||
| background: #0d1117; | ||
| } | ||
| .header { | ||
| background: #161b22; | ||
| color: white; | ||
| - padding: 1rem 2rem; | ||
| - box-shadow: 0 2px 4px rgba(0,0,0,0.3); | ||
| border-bottom: 1px solid #30363d; | ||
| -} | ||
| - | ||
| -.header h1 { | ||
| - font-size: 1.5rem; | ||
| - font-weight: 600; | ||
| } | ||
| .header a { | ||
| color: #fff; | ||
| - text-decoration: none; | ||
| -} | ||
| - | ||
| -.header a:hover { | ||
| - text-decoration: underline; | ||
| -} | ||
| - | ||
| -.container { | ||
| - max-width: 1200px; | ||
| - margin: 2rem auto; | ||
| - padding: 0 2rem; | ||
| } | ||
| .breadcrumb { | ||
| - margin-bottom: 1.5rem; | ||
| - font-size: 0.95rem; | ||
| color: #8b949e; | ||
| } | ||
| .breadcrumb a { | ||
| color: #58a6ff; | ||
| - text-decoration: none; | ||
| -} | ||
| - | ||
| -.breadcrumb a:hover { | ||
| - text-decoration: underline; | ||
| -} | ||
| - | ||
| -.breadcrumb span { | ||
| - margin: 0 0.5rem; | ||
| } | ||
| .card { | ||
| background: #161b22; | ||
| border: 1px solid #30363d; | ||
| - border-radius: 6px; | ||
| - margin-bottom: 1rem; | ||
| - overflow: hidden; | ||
| } | ||
| .card-header { | ||
| - padding: 1rem 1.5rem; | ||
| border-bottom: 1px solid #30363d; | ||
| background: #0d1117; | ||
| - font-weight: 600; | ||
| -} | ||
| - | ||
| -.card-body { | ||
| - padding: 1.5rem; | ||
| -} | ||
| - | ||
| -.repo-list { | ||
| - list-style: none; | ||
| - display: grid; | ||
| - grid-template-columns: repeat(3, 1fr); | ||
| - gap: 1.5rem; | ||
| - padding: 0; | ||
| -} | ||
| - | ||
| -@media (max-width: 1024px) { | ||
| - .repo-list { | ||
| - grid-template-columns: repeat(2, 1fr); | ||
| - } | ||
| -} | ||
| - | ||
| -@media (max-width: 640px) { | ||
| - .repo-list { | ||
| - grid-template-columns: 1fr; | ||
| - } | ||
| } | ||
| .repo-item { | ||
| - padding: 1.5rem; | ||
| border: 1px solid #30363d; | ||
| - border-radius: 6px; | ||
| background: #161b22; | ||
| - transition: all 0.2s; | ||
| - display: flex; | ||
| - flex-direction: column; | ||
| } | ||
| .repo-item:last-child { | ||
| border-bottom: 1px solid #30363d; | ||
| } | ||
| .repo-item:hover { | ||
| - transform: translateY(-2px); | ||
| box-shadow: 0 4px 12px rgba(0,0,0,0.4); | ||
| border-color: #58a6ff; | ||
| -} | ||
| - | ||
| -.repo-name { | ||
| - font-size: 1.15rem; | ||
| - font-weight: 600; | ||
| - margin-bottom: 0.75rem; | ||
| } | ||
| .repo-name a { | ||
| color: #e6edf3; | ||
| - text-decoration: none; | ||
| } | ||
| .repo-name a:hover { | ||
| color: #58a6ff; | ||
| } | ||
| .repo-desc { | ||
| color: #8b949e; | ||
| - font-size: 0.9rem; | ||
| - margin-bottom: 1rem; | ||
| - flex: 1; | ||
| - line-height: 1.5; | ||
| } | ||
| .repo-meta { | ||
| - font-size: 0.85rem; | ||
| color: #8b949e; | ||
| - display: flex; | ||
| - gap: 0.5rem; | ||
| - flex-wrap: wrap; | ||
| - align-items: center; | ||
| - margin-top: auto; | ||
| - padding-top: 0.5rem; | ||
| border-top: 1px solid #21262d; | ||
| -} | ||
| - | ||
| -.repo-meta span { | ||
| - display: flex; | ||
| - align-items: center; | ||
| - gap: 0.25rem; | ||
| } | ||
| .nav-tabs { | ||
| - display: flex; | ||
| - gap: 0.5rem; | ||
| border-bottom: 1px solid #30363d; | ||
| - margin-bottom: 1.5rem; | ||
| - padding: 0 1.5rem; | ||
| background: #161b22; | ||
| - border-radius: 6px 6px 0 0; | ||
| } | ||
| .nav-tab { | ||
| - padding: 1rem 1.25rem; | ||
| color: #8b949e; | ||
| - text-decoration: none; | ||
| - border-bottom: 2px solid transparent; | ||
| - transition: all 0.15s; | ||
| - font-weight: 500; | ||
| } | ||
| color: #e6edf3; | ||
| border-bottom-color: #f78166; | ||
| -} | ||
| - | ||
| -.commit-list { | ||
| - list-style: none; | ||
| } | ||
| .commit-item { | ||
| - padding: 1rem 1.5rem; | ||
| border-bottom: 1px solid #30363d; | ||
| - display: flex; | ||
| - gap: 1rem; | ||
| - transition: background 0.15s; | ||
| -} | ||
| - | ||
| -.commit-item:last-child { | ||
| - border-bottom: none; | ||
| } | ||
| .commit-item:hover { | ||
| background: #0d1117; | ||
| -} | ||
| - | ||
| -.commit-message { | ||
| - flex: 1; | ||
| } | ||
| .commit-message a { | ||
| color: #e6edf3; | ||
| - text-decoration: none; | ||
| - font-weight: 500; | ||
| } | ||
| .commit-message a:hover { | ||
| color: #58a6ff; | ||
| - text-decoration: underline; | ||
| } | ||
| .commit-meta { | ||
| - font-size: 0.85rem; | ||
| color: #8b949e; | ||
| - margin-top: 0.25rem; | ||
| } | ||
| .commit-hash { | ||
| - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; | ||
| - font-size: 0.85rem; | ||
| color: #8b949e; | ||
| - white-space: nowrap; | ||
| } | ||
| .commit-hash a { | ||
| color: #58a6ff; | ||
| - text-decoration: none; | ||
| -} | ||
| - | ||
| -.file-tree { | ||
| - list-style: none; | ||
| } | ||
| .file-item { | ||
| - padding: 0.75rem 1.5rem; | ||
| border-bottom: 1px solid #30363d; | ||
| - display: flex; | ||
| - align-items: center; | ||
| - gap: 0.75rem; | ||
| - transition: background 0.15s; | ||
| -} | ||
| - | ||
| -.file-item:last-child { | ||
| - border-bottom: none; | ||
| } | ||
| .file-item:hover { | ||
| background: #0d1117; | ||
| -} | ||
| - | ||
| -.file-icon { | ||
| - width: 16px; | ||
| - height: 16px; | ||
| - flex-shrink: 0; | ||
| -} | ||
| - | ||
| -.file-name { | ||
| - flex: 1; | ||
| } | ||
| .file-name a { | ||
| color: #58a6ff; | ||
| - text-decoration: none; | ||
| } | ||
| -.file-name a:hover { | ||
| - text-decoration: underline; | ||
| +.file-meta { | ||
| + color: #8b949e; | ||
| } | ||
| .code-block { | ||
| background: #0d1117; | ||
| border: 1px solid #30363d; | ||
| - border-radius: 6px; | ||
| - overflow-x: auto; | ||
| - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; | ||
| - font-size: 0.85rem; | ||
| } | ||
| .code-block pre { | ||
| - padding: 1rem; | ||
| - margin: 0; | ||
| - overflow-x: auto; | ||
| color: #e6edf3; | ||
| -} | ||
| - | ||
| -.diff { | ||
| - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; | ||
| - font-size: 0.85rem; | ||
| -} | ||
| - | ||
| -.diff-line { | ||
| - padding: 0.1rem 1rem; | ||
| - white-space: pre; | ||
| } | ||
| background: #161b22; | ||
| color: #8b949e; | ||
| - font-weight: 600; | ||
| -} | ||
| - | ||
| -.commit-detail { | ||
| - padding: 1.5rem; | ||
| -} | ||
| - | ||
| -.commit-title { | ||
| - font-size: 1.25rem; | ||
| - font-weight: 600; | ||
| - margin-bottom: 1rem; | ||
| } | ||
| .commit-info { | ||
| background: #0d1117; | ||
| - padding: 1rem; | ||
| - border-radius: 6px; | ||
| - margin-bottom: 1.5rem; | ||
| - font-size: 0.9rem; | ||
| border: 1px solid #30363d; | ||
| -} | ||
| - | ||
| -.commit-info-row { | ||
| - display: flex; | ||
| - gap: 1rem; | ||
| - margin-bottom: 0.5rem; | ||
| -} | ||
| - | ||
| -.commit-info-row:last-child { | ||
| - margin-bottom: 0; | ||
| } | ||
| .commit-info-label { | ||
| - font-weight: 600; | ||
| - min-width: 80px; | ||
| color: #8b949e; | ||
| } | ||
| .empty-state { | ||
| - text-align: center; | ||
| - padding: 3rem; | ||
| color: #8b949e; | ||
| -} | ||
| - | ||
| -.empty-state-icon { | ||
| - font-size: 3rem; | ||
| - margin-bottom: 1rem; | ||
| - opacity: 0.5; | ||
| -} | ||
| - | ||
| -.file-actions { | ||
| - display: flex; | ||
| - gap: 0.5rem; | ||
| - margin-bottom: 1rem; | ||
| - padding: 0 1.5rem; | ||
| - padding-top: 1rem; | ||
| } | ||
| .btn { | ||
| - padding: 0.5rem 1rem; | ||
| background: #21262d; | ||
| border: 1px solid #30363d; | ||
| - border-radius: 6px; | ||
| color: #e6edf3; | ||
| - text-decoration: none; | ||
| - font-size: 0.9rem; | ||
| - font-weight: 500; | ||
| - transition: all 0.15s; | ||
| - display: inline-flex; | ||
| - align-items: center; | ||
| - gap: 0.5rem; | ||
| } | ||
| .btn:hover { | ||
| background: #30363d; | ||
| border-color: #6e7681; | ||
| } | ||
| .image-preview { | ||
| - padding: 1.5rem; | ||
| - text-align: center; | ||
| background: #0d1117; | ||
| } | ||
| .image-preview img { | ||
| - max-width: 100%; | ||
| - height: auto; | ||
| border: 1px solid #30363d; | ||
| - border-radius: 6px; | ||
| background: #161b22; | ||
| +} | ||
| + | ||
| +.theme-toggle { | ||
| + background: #f6f8fa; | ||
| + border: 1px solid #e1e4e8; | ||
| + color: #24292e; | ||
| +} | ||
| + | ||
| +.theme-toggle:hover { | ||
| + background: #e1e4e8; | ||
| + border-color: #d1d5da; | ||
| } | ||
| <?php | ||
| -// Load configuration | ||
| require_once __DIR__ . '/config.php'; | ||
| -// Load function libraries | ||
| require_once __DIR__ . '/includes/git_functions.php'; | ||
| require_once __DIR__ . '/includes/repo_functions.php'; | ||
| require_once __DIR__ . '/includes/helpers.php'; | ||
| -// Get request parameters | ||
| $action = $_GET['action'] ?? 'list'; | ||
| $repo = $_GET['repo'] ?? ''; | ||
| $ref = $_GET['ref'] ?? 'HEAD'; | ||
| $path = $_GET['path'] ?? ''; | ||
| $hash = $_GET['hash'] ?? ''; | ||
| -// Theme selection | ||
| $current_theme = $_GET['theme'] ?? 'dark'; | ||
| $css_file = ($current_theme === 'dark') ? 'dark.css' : 'light.css'; | ||
| -// Handle raw file download | ||
| if ($action === 'raw' && !empty($repo) && !empty($hash)) { | ||
| - $name = $_GET['name'] ?? 'file'; | ||
| - $content = getBlobBinary($repo, $hash); | ||
| + $name = $_GET['name'] ?? 'file'; | ||
| + $content = getBlobBinary($repo, $hash); | ||
| - header('Content-Type: application/octet-stream'); | ||
| - header('Content-Disposition: attachment; filename="' . $name . '"'); | ||
| - header('Content-Length: ' . strlen($content)); | ||
| - echo $content; | ||
| - exit; | ||
| + header('Content-Type: application/octet-stream'); | ||
| + header('Content-Disposition: attachment; filename="' . $name . '"'); | ||
| + header('Content-Length: ' . strlen($content)); | ||
| + echo $content; | ||
| + exit; | ||
| } | ||
| -// Set page title | ||
| $page_title = $action === 'list' ? SITE_TITLE : htmlspecialchars($repo) . ' - ' . SITE_TITLE; | ||
| -// Include header | ||
| include __DIR__ . '/views/header.php'; | ||
| -// Route to appropriate view | ||
| switch ($action) { | ||
| - case 'list': | ||
| - include __DIR__ . '/views/list.php'; | ||
| - break; | ||
| + case 'list': | ||
| + include __DIR__ . '/views/list.php'; | ||
| + break; | ||
| - case 'repo': | ||
| - include __DIR__ . '/views/repo.php'; | ||
| - break; | ||
| + case 'repo': | ||
| + include __DIR__ . '/views/repo.php'; | ||
| + break; | ||
| - case 'commit': | ||
| - include __DIR__ . '/views/commit.php'; | ||
| - break; | ||
| + case 'commit': | ||
| + include __DIR__ . '/views/commit.php'; | ||
| + break; | ||
| - case 'blob': | ||
| - include __DIR__ . '/views/blob.php'; | ||
| - break; | ||
| + case 'blob': | ||
| + include __DIR__ . '/views/blob.php'; | ||
| + break; | ||
| - default: | ||
| - include __DIR__ . '/views/list.php'; | ||
| - break; | ||
| + default: | ||
| + include __DIR__ . '/views/list.php'; | ||
| + break; | ||
| } | ||
| -// Include footer | ||
| include __DIR__ . '/views/footer.php'; | ||
| -* { | ||
| - margin: 0; | ||
| - padding: 0; | ||
| - box-sizing: border-box; | ||
| -} | ||
| - | ||
| body { | ||
| - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; | ||
| - line-height: 1.6; | ||
| color: #24292e; | ||
| background: #f6f8fa; | ||
| } | ||
| .header { | ||
| background: #24292e; | ||
| color: white; | ||
| - padding: 1rem 2rem; | ||
| - box-shadow: 0 2px 4px rgba(0,0,0,0.1); | ||
| - display: flex; | ||
| - justify-content: space-between; | ||
| - align-items: center; | ||
| -} | ||
| - | ||
| -.header h1 { | ||
| - font-size: 1.5rem; | ||
| - font-weight: 600; | ||
| - margin: 0; | ||
| } | ||
| .header a { | ||
| color: #fff; | ||
| - text-decoration: none; | ||
| -} | ||
| - | ||
| -.header a:hover { | ||
| - text-decoration: underline; | ||
| -} | ||
| - | ||
| -.theme-switcher { | ||
| - display: flex; | ||
| - align-items: center; | ||
| -} | ||
| - | ||
| -.theme-toggle { | ||
| - padding: 0.5rem 1rem; | ||
| - background: #f6f8fa; | ||
| - border: 1px solid #e1e4e8; | ||
| - border-radius: 6px; | ||
| - color: #24292e; | ||
| - text-decoration: none; | ||
| - font-size: 0.9rem; | ||
| - font-weight: 500; | ||
| - transition: all 0.15s; | ||
| - display: inline-flex; | ||
| - align-items: center; | ||
| - gap: 0.5rem; | ||
| -} | ||
| - | ||
| -.theme-toggle:hover { | ||
| - background: #e1e4e8; | ||
| - border-color: #d1d5da; | ||
| - text-decoration: none; | ||
| -} | ||
| - | ||
| -.container { | ||
| - max-width: 1200px; | ||
| - margin: 2rem auto; | ||
| - padding: 0 2rem; | ||
| } | ||
| .breadcrumb { | ||
| - margin-bottom: 1.5rem; | ||
| - font-size: 0.95rem; | ||
| color: #586069; | ||
| } | ||
| .breadcrumb a { | ||
| color: #0366d6; | ||
| - text-decoration: none; | ||
| -} | ||
| - | ||
| -.breadcrumb a:hover { | ||
| - text-decoration: underline; | ||
| -} | ||
| - | ||
| -.breadcrumb span { | ||
| - margin: 0 0.5rem; | ||
| } | ||
| .card { | ||
| background: white; | ||
| border: 1px solid #e1e4e8; | ||
| - border-radius: 6px; | ||
| - margin-bottom: 1rem; | ||
| - overflow: hidden; | ||
| } | ||
| .card-header { | ||
| - padding: 1rem 1.5rem; | ||
| border-bottom: 1px solid #e1e4e8; | ||
| background: #f6f8fa; | ||
| - font-weight: 600; | ||
| -} | ||
| - | ||
| -.card-body { | ||
| - padding: 1.5rem; | ||
| -} | ||
| - | ||
| -.repo-list { | ||
| - list-style: none; | ||
| - display: grid; | ||
| - grid-template-columns: repeat(3, 1fr); | ||
| - gap: 1.5rem; | ||
| - padding: 0; | ||
| -} | ||
| - | ||
| -@media (max-width: 1024px) { | ||
| - .repo-list { | ||
| - grid-template-columns: repeat(2, 1fr); | ||
| - } | ||
| -} | ||
| - | ||
| -@media (max-width: 640px) { | ||
| - .repo-list { | ||
| - grid-template-columns: 1fr; | ||
| - } | ||
| } | ||
| .repo-item { | ||
| - padding: 1.5rem; | ||
| border: 1px solid #e1e4e8; | ||
| - border-radius: 6px; | ||
| background: white; | ||
| - transition: all 0.2s; | ||
| - display: flex; | ||
| - flex-direction: column; | ||
| } | ||
| .repo-item:last-child { | ||
| border-bottom: 1px solid #e1e4e8; | ||
| } | ||
| .repo-item:hover { | ||
| - transform: translateY(-2px); | ||
| box-shadow: 0 4px 12px rgba(0,0,0,0.1); | ||
| border-color: #0366d6; | ||
| -} | ||
| - | ||
| -.repo-name { | ||
| - font-size: 1.15rem; | ||
| - font-weight: 600; | ||
| - margin-bottom: 0.75rem; | ||
| } | ||
| .repo-name a { | ||
| color: #24292e; | ||
| - text-decoration: none; | ||
| } | ||
| .repo-name a:hover { | ||
| color: #0366d6; | ||
| } | ||
| .repo-desc { | ||
| color: #586069; | ||
| - font-size: 0.9rem; | ||
| - margin-bottom: 1rem; | ||
| - flex: 1; | ||
| - line-height: 1.5; | ||
| } | ||
| .repo-meta { | ||
| - font-size: 0.85rem; | ||
| color: #586069; | ||
| - display: flex; | ||
| - gap: 0.5rem; | ||
| - flex-wrap: wrap; | ||
| - align-items: center; | ||
| - margin-top: auto; | ||
| - padding-top: 0.5rem; | ||
| border-top: 1px solid #f6f8fa; | ||
| -} | ||
| - | ||
| -.repo-meta span { | ||
| - display: flex; | ||
| - align-items: center; | ||
| - gap: 0.25rem; | ||
| } | ||
| .nav-tabs { | ||
| - display: flex; | ||
| - gap: 0.5rem; | ||
| border-bottom: 1px solid #e1e4e8; | ||
| - margin-bottom: 1.5rem; | ||
| - padding: 0 1.5rem; | ||
| background: white; | ||
| - border-radius: 6px 6px 0 0; | ||
| } | ||
| .nav-tab { | ||
| - padding: 1rem 1.25rem; | ||
| color: #586069; | ||
| - text-decoration: none; | ||
| - border-bottom: 2px solid transparent; | ||
| - transition: all 0.15s; | ||
| - font-weight: 500; | ||
| } | ||
| color: #24292e; | ||
| border-bottom-color: #f9826c; | ||
| -} | ||
| - | ||
| -.commit-list { | ||
| - list-style: none; | ||
| } | ||
| .commit-item { | ||
| - padding: 1rem 1.5rem; | ||
| border-bottom: 1px solid #e1e4e8; | ||
| - display: flex; | ||
| - gap: 1rem; | ||
| - transition: background 0.15s; | ||
| -} | ||
| - | ||
| -.commit-item:last-child { | ||
| - border-bottom: none; | ||
| } | ||
| .commit-item:hover { | ||
| background: #f6f8fa; | ||
| -} | ||
| - | ||
| -.commit-message { | ||
| - flex: 1; | ||
| } | ||
| .commit-message a { | ||
| color: #24292e; | ||
| - text-decoration: none; | ||
| - font-weight: 500; | ||
| } | ||
| .commit-message a:hover { | ||
| color: #0366d6; | ||
| - text-decoration: underline; | ||
| } | ||
| .commit-meta { | ||
| - font-size: 0.85rem; | ||
| color: #586069; | ||
| - margin-top: 0.25rem; | ||
| } | ||
| .commit-hash { | ||
| - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; | ||
| - font-size: 0.85rem; | ||
| color: #586069; | ||
| - white-space: nowrap; | ||
| } | ||
| .commit-hash a { | ||
| color: #0366d6; | ||
| - text-decoration: none; | ||
| -} | ||
| - | ||
| -.file-tree { | ||
| - list-style: none; | ||
| } | ||
| .file-item { | ||
| - padding: 0.75rem 1.5rem; | ||
| border-bottom: 1px solid #e1e4e8; | ||
| - display: flex; | ||
| - align-items: center; | ||
| - gap: 0.75rem; | ||
| - transition: background 0.15s; | ||
| -} | ||
| - | ||
| -.file-item:last-child { | ||
| - border-bottom: none; | ||
| } | ||
| .file-item:hover { | ||
| background: #f6f8fa; | ||
| -} | ||
| - | ||
| -.file-icon { | ||
| - width: 16px; | ||
| - height: 16px; | ||
| - flex-shrink: 0; | ||
| -} | ||
| - | ||
| -.file-name { | ||
| - flex: 1; | ||
| } | ||
| .file-name a { | ||
| color: #0366d6; | ||
| - text-decoration: none; | ||
| } | ||
| -.file-name a:hover { | ||
| - text-decoration: underline; | ||
| +.file-meta { | ||
| + color: #586069; | ||
| } | ||
| .code-block { | ||
| background: #f6f8fa; | ||
| border: 1px solid #e1e4e8; | ||
| - border-radius: 6px; | ||
| - overflow-x: auto; | ||
| - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; | ||
| - font-size: 0.85rem; | ||
| -} | ||
| - | ||
| -.code-block pre { | ||
| - padding: 1rem; | ||
| - margin: 0; | ||
| - overflow-x: auto; | ||
| -} | ||
| - | ||
| -.diff { | ||
| - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; | ||
| - font-size: 0.85rem; | ||
| -} | ||
| - | ||
| -.diff-line { | ||
| - padding: 0.1rem 1rem; | ||
| - white-space: pre; | ||
| } | ||
| background: #f6f8fa; | ||
| color: #586069; | ||
| - font-weight: 600; | ||
| -} | ||
| - | ||
| -.commit-detail { | ||
| - padding: 1.5rem; | ||
| -} | ||
| - | ||
| -.commit-title { | ||
| - font-size: 1.25rem; | ||
| - font-weight: 600; | ||
| - margin-bottom: 1rem; | ||
| } | ||
| .commit-info { | ||
| background: #f6f8fa; | ||
| - padding: 1rem; | ||
| - border-radius: 6px; | ||
| - margin-bottom: 1.5rem; | ||
| - font-size: 0.9rem; | ||
| -} | ||
| - | ||
| -.commit-info-row { | ||
| - display: flex; | ||
| - gap: 1rem; | ||
| - margin-bottom: 0.5rem; | ||
| -} | ||
| - | ||
| -.commit-info-row:last-child { | ||
| - margin-bottom: 0; | ||
| -} | ||
| - | ||
| -.commit-info-label { | ||
| - font-weight: 600; | ||
| - min-width: 80px; | ||
| } | ||
| .empty-state { | ||
| - text-align: center; | ||
| - padding: 3rem; | ||
| color: #586069; | ||
| -} | ||
| - | ||
| -.empty-state-icon { | ||
| - font-size: 3rem; | ||
| - margin-bottom: 1rem; | ||
| - opacity: 0.5; | ||
| -} | ||
| - | ||
| -.file-actions { | ||
| - display: flex; | ||
| - gap: 0.5rem; | ||
| - margin-bottom: 1rem; | ||
| - padding: 0 1.5rem; | ||
| - padding-top: 1rem; | ||
| } | ||
| .btn { | ||
| - padding: 0.5rem 1rem; | ||
| background: #f6f8fa; | ||
| border: 1px solid #e1e4e8; | ||
| - border-radius: 6px; | ||
| color: #24292e; | ||
| - text-decoration: none; | ||
| - font-size: 0.9rem; | ||
| - font-weight: 500; | ||
| - transition: all 0.15s; | ||
| - display: inline-flex; | ||
| - align-items: center; | ||
| - gap: 0.5rem; | ||
| } | ||
| .btn:hover { | ||
| background: #e1e4e8; | ||
| border-color: #d1d5da; | ||
| } | ||
| .image-preview { | ||
| - padding: 1.5rem; | ||
| - text-align: center; | ||
| background: #f6f8fa; | ||
| } | ||
| .image-preview img { | ||
| - max-width: 100%; | ||
| - height: auto; | ||
| border: 1px solid #e1e4e8; | ||
| - border-radius: 6px; | ||
| background: white; | ||
| +} | ||
| + | ||
| +.theme-toggle { | ||
| + background: #f6f8fa; | ||
| + border: 1px solid #e1e4e8; | ||
| + color: #24292e; | ||
| +} | ||
| + | ||
| +.theme-toggle:hover { | ||
| + background: #e1e4e8; | ||
| + border-color: #d1d5da; | ||
| } | ||
| <html lang="en"> | ||
| <head> | ||
| - <meta charset="UTF-8"> | ||
| - <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| - <title><?php echo $page_title ?? SITE_TITLE; ?></title> | ||
| - <link rel="stylesheet" href="<?php echo $css_file; ?>"> | ||
| - <style> | ||
| - .header { | ||
| - display: flex; | ||
| - justify-content: space-between; | ||
| - align-items: center; | ||
| - padding: 10px 20px; | ||
| - } | ||
| - .theme-toggle a { | ||
| - padding: 5px 10px; | ||
| - border: 1px solid currentColor; | ||
| - border-radius: 4px; | ||
| - text-decoration: none; | ||
| - color: <?php echo ($current_theme === 'light') ? '#000000' : '#FFFFFF'; ?>; | ||
| - background-color: <?php echo ($current_theme === 'light') ? '#F0F0F0' : '#333333'; ?>; | ||
| - } | ||
| - .theme-toggle a:hover { | ||
| - opacity: 0.8; | ||
| - } | ||
| - </style> | ||
| + <meta charset="UTF-8"> | ||
| + <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| + <title><?php echo $page_title ?? SITE_TITLE; ?></title> | ||
| + <link rel="stylesheet" href="main.css"> | ||
| + <link rel="stylesheet" href="<?php echo $css_file; ?>"> | ||
| + <style> | ||
| + .header { | ||
| + display: flex; | ||
| + justify-content: space-between; | ||
| + align-items: center; | ||
| + padding: 10px 20px; | ||
| + } | ||
| + .theme-toggle a { | ||
| + padding: 5px 10px; | ||
| + border: 1px solid currentColor; | ||
| + border-radius: 4px; | ||
| + text-decoration: none; | ||
| + color: <?php echo ($current_theme === 'light') ? '#000000' : '#FFFFFF'; ?>; | ||
| + background-color: <?php echo ($current_theme === 'light') ? '#F0F0F0' : '#333333'; ?>; | ||
| + } | ||
| + .theme-toggle a:hover { | ||
| + opacity: 0.8; | ||
| + } | ||
| + </style> | ||
| </head> | ||
| <body> | ||
| - <div class="header"> | ||
| - <h1><a href="?action=list&theme=<?php echo $current_theme; ?>">π <?php echo SITE_TITLE; ?></a></h1> | ||
| - | ||
| - <div class="theme-toggle"> | ||
| - <?php | ||
| - $query_params = $_GET; | ||
| - unset($query_params['theme']); | ||
| - $opposite_theme = ($current_theme === 'light') ? 'dark' : 'light'; | ||
| - $toggle_link = '?' . http_build_query(array_merge($query_params, ['theme' => $opposite_theme])); | ||
| - ?> | ||
| - <a href="<?php echo htmlspecialchars($toggle_link); ?>" class="btn-theme" title="Switch to <?php echo $opposite_theme; ?> Mode"> | ||
| - <?php if ($current_theme === 'light'): ?> | ||
| - π Dark | ||
| - <?php else: ?> | ||
| - βοΈLight | ||
| - <?php endif; ?> | ||
| - </a> | ||
| - </div> | ||
| + <div class="header"> | ||
| + <h1><a href="?action=list&theme=<?php echo $current_theme; ?>">π <?php echo SITE_TITLE; ?></a></h1> | ||
| + <div class="theme-toggle"> | ||
| + <?php | ||
| + $query_params = $_GET; | ||
| + unset($query_params['theme']); | ||
| + $opposite_theme = ($current_theme === 'light') ? 'dark' : 'light'; | ||
| + $toggle_link = '?' . http_build_query(array_merge($query_params, ['theme' => $opposite_theme])); | ||
| + ?> | ||
| + <a href="<?php echo htmlspecialchars($toggle_link); ?>" class="btn-theme" title="Switch to <?php echo $opposite_theme; ?> Mode"> | ||
| + <?php if ($current_theme === 'light'): ?> | ||
| + π Dark | ||
| + <?php else: ?> | ||
| + βοΈLight | ||
| + <?php endif; ?> | ||
| + </a> | ||
| </div> | ||
| - | ||
| - <div class="container"> | ||
| - | ||
| + </div> | ||
| + <div class="container"> | ||
| <?php $repos = getRepositories(); ?> | ||
| <?php if (empty($repos)): ?> | ||
| - <div class="card"> | ||
| - <div class="empty-state"> | ||
| - <div class="empty-state-icon">π</div> | ||
| - <p>No repositories found in <?php echo htmlspecialchars(REPOS_PATH); ?></p> | ||
| - </div> | ||
| + <div class="card"> | ||
| + <div class="empty-state"> | ||
| + <div class="empty-state-icon">π</div> | ||
| + <p>No repositories found in <?php echo htmlspecialchars(REPOS_PATH); ?></p> | ||
| </div> | ||
| + </div> | ||
| <?php else: ?> | ||
| - <ul class="repo-list"> | ||
| - <?php foreach ($repos as $r): ?> | ||
| - <?php $info = getRepoInfo($r); ?> | ||
| - <li class="repo-item"> | ||
| - <div class="repo-name"> | ||
| - <a href="?action=repo&repo=<?php echo urlencode($r); ?>&theme=<?php echo $current_theme; ?>"><?php echo htmlspecialchars($r); ?></a> | ||
| - </div> | ||
| - <div class="repo-desc"><?php echo htmlspecialchars($info['description']); ?></div> | ||
| - <div class="repo-meta"> | ||
| - <?php if (isset($info['last_commit'])): ?> | ||
| - <span>π <?php echo timeAgo($info['last_commit']['date']); ?></span> | ||
| - <?php endif; ?> | ||
| - </div> | ||
| - </li> | ||
| - <?php endforeach; ?> | ||
| - </ul> | ||
| + <ul class="repo-list"> | ||
| + <?php foreach ($repos as $r): ?> | ||
| + <?php $info = getRepoInfo($r); ?> | ||
| + <li class="repo-item"> | ||
| + <div class="repo-name"> | ||
| + <a href="?action=repo&repo=<?php echo urlencode($r); ?>&theme=<?php echo $current_theme; ?>"><?php echo htmlspecialchars($r); ?></a> | ||
| + </div> | ||
| + <div class="repo-desc"><?php echo htmlspecialchars($info['description']); ?></div> | ||
| + <div class="repo-meta"> | ||
| + <?php if (isset($info['last_commit'])): ?> | ||
| + <span>π <?php echo timeAgo($info['last_commit']['date']); ?></span> | ||
| + <?php endif; ?> | ||
| + </div> | ||
| + </li> | ||
| + <?php endforeach; ?> | ||
| + </ul> | ||
| <?php endif; ?> | ||
| <div class="breadcrumb"> | ||
| - <a href="?action=list&theme=<?php echo $current_theme; ?>">Repositories</a> | ||
| + <a href="?action=list&theme=<?php echo $current_theme; ?>">Repositories</a> | ||
| </div> | ||
| <?php | ||
| - $base_repo_link = "?action=repo&repo=" . urlencode($repo) . "&theme=" . $current_theme; | ||
| - $view = $_GET['view'] ?? ''; | ||
| + $base_repo_link = "?action=repo&repo=" . urlencode($repo) . "&theme=" . $current_theme; | ||
| + $view = $_GET['view'] ?? ''; | ||
| ?> | ||
| <div class="nav-tabs"> | ||
| - <a href="<?php echo $base_repo_link; ?>" class="nav-tab <?php echo empty($view) ? 'active' : ''; ?>">π Commits</a> | ||
| - <a href="<?php echo $base_repo_link; ?>&view=tree" class="nav-tab <?php echo $view === 'tree' ? 'active' : ''; ?>">π Files</a> | ||
| - <a href="<?php echo $base_repo_link; ?>&view=branches" class="nav-tab <?php echo $view === 'branches' ? 'active' : ''; ?>">πΏ Branches</a> | ||
| + <a href="<?php echo $base_repo_link; ?>" class="nav-tab <?php echo empty($view) ? 'active' : ''; ?>">π Commits</a> | ||
| + <a href="<?php echo $base_repo_link; ?>&view=tree" class="nav-tab <?php echo $view === 'tree' ? 'active' : ''; ?>">π Files</a> | ||
| + <a href="<?php echo $base_repo_link; ?>&view=branches" class="nav-tab <?php echo $view === 'branches' ? 'active' : ''; ?>">πΏ Branches</a> | ||
| </div> | ||
| <?php | ||
| - if ($view === 'tree') { | ||
| - include __DIR__ . '/repo_tree.php'; | ||
| - } elseif ($view === 'branches') { | ||
| - include __DIR__ . '/repo_branches.php'; | ||
| - } else { | ||
| - include __DIR__ . '/repo_commits.php'; | ||
| - } | ||
| + if ($view === 'tree') { | ||
| + include __DIR__ . '/repo_tree.php'; | ||
| + } elseif ($view === 'branches') { | ||
| + include __DIR__ . '/repo_branches.php'; | ||
| + } else { | ||
| + include __DIR__ . '/repo_commits.php'; | ||
| + } | ||
| ?> | ||
| <?php $items = getTree($repo, $ref, $path); ?> | ||
| <div class="card"> | ||
| - <div class="card-header"> | ||
| - <?php if (empty($path)): ?> | ||
| - Root directory | ||
| - <?php else: ?> | ||
| - <?php echo htmlspecialchars($path); ?> | ||
| - <?php endif; ?> | ||
| - </div> | ||
| - <ul class="file-tree"> | ||
| - <?php if (!empty($path)): ?> | ||
| - <li class="file-item"> | ||
| - <span class="file-icon">π</span> | ||
| - <div class="file-name"> | ||
| - <?php | ||
| - $parentPath = dirname($path); | ||
| - if ($parentPath === '.' || $parentPath === '') { | ||
| - $parentPath = ''; | ||
| - } | ||
| - ?> | ||
| - <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&view=tree&ref=<?php echo urlencode($ref); ?>&path=<?php echo urlencode($parentPath); ?>&theme=<?php echo $current_theme; ?>">../</a> | ||
| - </div> | ||
| - </li> | ||
| - <?php endif; ?> | ||
| - <?php foreach ($items as $item): ?> | ||
| - <li class="file-item"> | ||
| - <span class="file-icon"><?php echo $item['type'] === 'tree' ? 'π' : 'π'; ?></span> | ||
| - <div class="file-name"> | ||
| - <?php if ($item['type'] === 'tree'): ?> | ||
| - <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&view=tree&ref=<?php echo urlencode($ref); ?>&path=<?php echo urlencode($path . ($path ? '/' : '') . $item['name']); ?>&theme=<?php echo $current_theme; ?>"> | ||
| - <?php echo htmlspecialchars($item['name']); ?>/ | ||
| - </a> | ||
| - <?php else: ?> | ||
| - <a href="?action=blob&repo=<?php echo urlencode($repo); ?>&hash=<?php echo urlencode($item['hash']); ?>&name=<?php echo urlencode($item['name']); ?>&theme=<?php echo $current_theme; ?>"> | ||
| - <?php echo htmlspecialchars($item['name']); ?> | ||
| - </a> | ||
| - <?php endif; ?> | ||
| - </div> | ||
| - </li> | ||
| - <?php endforeach; ?> | ||
| - </ul> | ||
| + <div class="card-header"> | ||
| + <?php if (empty($path)): ?> | ||
| + Root directory | ||
| + <?php else: ?> | ||
| + <?php echo htmlspecialchars($path); ?> | ||
| + <?php endif; ?> | ||
| + </div> | ||
| + <ul class="file-tree"> | ||
| + <?php if (!empty($path)): ?> | ||
| + <li class="file-item"> | ||
| + <span class="file-icon">π</span> | ||
| + <div class="file-name"> | ||
| + <?php | ||
| + $parentPath = dirname($path); | ||
| + if ($parentPath === '.' || $parentPath === '') { | ||
| + $parentPath = ''; | ||
| + } | ||
| + ?> | ||
| + <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&view=tree&ref=<?php echo urlencode($ref); ?>&path=<?php echo urlencode($parentPath); ?>&theme=<?php echo $current_theme; ?>">../</a> | ||
| + </div> | ||
| + <div class="file-meta"> | ||
| + <span class="file-size">-</span> | ||
| + <span class="file-date">-</span> | ||
| + </div> | ||
| + </li> | ||
| + <?php endif; ?> | ||
| + <?php foreach ($items as $item): ?> | ||
| + <li class="file-item"> | ||
| + <span class="file-icon"><?php echo $item['type'] === 'tree' ? 'π' : 'π'; ?></span> | ||
| + <div class="file-name"> | ||
| + <?php if ($item['type'] === 'tree'): ?> | ||
| + <a href="?action=repo&repo=<?php echo urlencode($repo); ?>&view=tree&ref=<?php echo urlencode($ref); ?>&path=<?php echo urlencode($path . ($path ? '/' : '') . $item['name']); ?>&theme=<?php echo $current_theme; ?>"> | ||
| + <?php echo htmlspecialchars($item['name']); ?>/ | ||
| + </a> | ||
| + <?php else: ?> | ||
| + <a href="?action=blob&repo=<?php echo urlencode($repo); ?>&hash=<?php echo urlencode($item['hash']); ?>&name=<?php echo urlencode($item['name']); ?>&theme=<?php echo $current_theme; ?>"> | ||
| + <?php echo htmlspecialchars($item['name']); ?> | ||
| + </a> | ||
| + <?php endif; ?> | ||
| + </div> | ||
| + <div class="file-meta"> | ||
| + <span class="file-size"> | ||
| + <?php | ||
| + if ($item['type'] === 'blob' && isset($item['size'])) { | ||
| + $size = $item['size']; | ||
| + if ($size < 1024) { | ||
| + echo $size . ' B'; | ||
| + } elseif ($size < 1024 * 1024) { | ||
| + echo round($size / 1024, 1) . ' KB'; | ||
| + } else { | ||
| + echo round($size / (1024 * 1024), 1) . ' MB'; | ||
| + } | ||
| + } else { | ||
| + echo '-'; | ||
| + } | ||
| + ?> | ||
| + </span> | ||
| + <span class="file-date"> | ||
| + <?php | ||
| + if (isset($item['mtime'])) { | ||
| + echo date('Y-m-d H:i', $item['mtime']); | ||
| + } else { | ||
| + echo '-'; | ||
| + } | ||
| + ?> | ||
| + </span> | ||
| + </div> | ||
| + </li> | ||
| + <?php endforeach; ?> | ||
| + </ul> | ||
| </div> | ||
| Delta | 194 lines added, 646 lines removed, 452-line decrease |
|---|