OverviewFilesCommitsIssuesDocsReleasesPeers

pear-git commits / 7b7094b

Fix file viewer: parse branch from URL, fix missing imports
handleViewFile now splits the *path param into branch + file path by matching against known branches. Fixes 404 on blob URLs. repo-pages-ui.js: fix server.pathPrefix → pathPrefix param, add missing buildBreadcrumb import. Fixes 500 error on file view. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7b7094b92ff0a8d34a0ee8a8abaa44fa15e413cb
by plankatron <fleeky@gmail.com> · 2026-04-06T16:20:59.000Z

Changed files (2) +39 -4

lib/repo-pages-ui.js +3 -2
……@@ -8,6 +8,7 @@
88import { escapeHtml } from './response.js'
99import { renderIdentityScript } from './identity-ui.js'
1010import { detectLanguage, getPrismAssets } from './syntax.js'
11import { buildBreadcrumb } from './breadcrumb.js'
1112import { getBreadcrumbStyles } from './breadcrumb.js'
1213import { parseDiff, getDiffStats, getStatusLabel } from './diff-parser.js'
1314
……@@ -110,7 +111,7 @@ function renderTreePage(username, repoName, dirPath, files, breadcrumb, pathPref
110111
111112function renderFilePage(repoName, filePath, content, pathPrefix, options = {}) {
112113 const { username = 'user', language = 'plaintext', lineCount = 0, isBinary = false } = options
113 const prismAssets = getPrismAssets(language, server.pathPrefix)
114 const prismAssets = getPrismAssets(language, pathPrefix)
114115 const isMarkdown = filePath.toLowerCase().endsWith('.md')
115116
116117 // Build breadcrumb
……@@ -135,7 +136,7 @@ function renderFilePage(repoName, filePath, content, pathPrefix, options = {}) {
135136<head>
136137 <meta charset="UTF-8">
137138 <title>${escapeHtml(filePath)} - ${escapeHtml(repoName)}</title>
138 ${isMarkdown ? '<script src="${server.pathPrefix}/vendor/marked.min.js"></script>' : ''}
139 ${isMarkdown ? `<script src="${pathPrefix}/vendor/marked.min.js"></script>` : ''}
139140 <!-- Prism.js CSS -->
140141 ${prismAssets.css.map(url => `<link rel="stylesheet" href="${url}">`).join('\n ')}
141142 <style>
lib/routes/repo-viewer.js +36 -2
……@@ -447,8 +447,42 @@ async function handleViewFile(req, res, server) {
447447 const { backendManager } = server.repoData
448448 const { pathPrefix } = server.config
449449 try {
450 const { username, repoName, path: filePath } = req.params
451 const content = await backendManager.readFile(repoName, filePath)
450 const { username, repoName, path: fullPath } = req.params
451
452 // fullPath is "branch/path/to/file" — split into ref and file path
453 // Try common branch names first, fall back to treating first segment as ref
454 const parts = fullPath.split('/')
455 let ref = 'HEAD'
456 let filePath = fullPath
457
458 // Check if first segment is a known branch
459 try {
460 const branches = await backendManager.getBranches(repoName)
461 const branchNames = branches.map(b => b.name || b)
462
463 // Try matching longest branch name first (handles branches with slashes)
464 let matched = false
465 for (const branch of branchNames.sort((a, b) => b.length - a.length)) {
466 if (fullPath.startsWith(branch + '/')) {
467 ref = branch
468 filePath = fullPath.slice(branch.length + 1)
469 matched = true
470 break
471 }
472 }
473 if (!matched && parts.length > 1) {
474 ref = parts[0]
475 filePath = parts.slice(1).join('/')
476 }
477 } catch {
478 // Can't get branches — use first segment as ref
479 if (parts.length > 1) {
480 ref = parts[0]
481 filePath = parts.slice(1).join('/')
482 }
483 }
484
485 const content = await backendManager.readFile(repoName, filePath, ref)
452486
453487 // Detect language from file extension
454488 const language = detectLanguage(filePath)