{pageData.title || `${repo} - Repository`} {#if (pageData.image || repoImage) && String(pageData.image || repoImage).trim()} {/if} {#if (pageData.banner || repoBanner) && String(pageData.banner || repoBanner).trim()} {/if} {#if pageData.banner || repoBanner} {:else if pageData.image || repoImage} {/if}
{#if repoBanner}
{ console.error('[Repo Images] Failed to load banner:', repoBanner); const target = e.target as HTMLImageElement; if (target) target.style.display = 'none'; }} />
{/if}
{#if repoImage} { console.error('[Repo Images] Failed to load image:', repoImage); const target = e.target as HTMLImageElement; if (target) target.style.display = 'none'; }} /> {/if}

{pageData.repoName || repo}

{#if pageData.repoDescription}

{pageData.repoDescription}

{:else}

No description

{/if}
{#if pageData.repoLanguage} {pageData.repoLanguage} {/if} {#if pageData.repoIsPrivate} Private {:else} Public {/if} {#if forkInfo?.isFork && forkInfo.originalRepo} Forked from {forkInfo.originalRepo.repo} {/if}
{#if pageData.repoOwnerPubkey || (pageData.repoMaintainers && pageData.repoMaintainers.length > 0)}
Contributors:
{#if pageData.repoOwnerPubkey} Owner {/if} {#if pageData.repoMaintainers} {#each pageData.repoMaintainers.filter(m => m !== pageData.repoOwnerPubkey) as maintainerPubkey} Maintainer {/each} {/if}
{/if} {#if pageData.repoTopics && pageData.repoTopics.length > 0}
{#each pageData.repoTopics as topic} {topic} {/each}
{/if} {#if pageData.repoWebsite} {/if} {#if pageData.repoCloneUrls && pageData.repoCloneUrls.length > 0}
Clone: {#each pageData.repoCloneUrls.slice(0, 3) as cloneUrl} {@const cloneVerification = verificationStatus?.cloneVerifications?.find(cv => { // Match URLs more flexibly (handle trailing slashes, http/https differences) const normalizeUrl = (url: string) => url.replace(/\/$/, '').toLowerCase().replace(/^https?:\/\//, ''); const normalizedCv = normalizeUrl(cv.url); const normalizedClone = normalizeUrl(cloneUrl); const matches = normalizedCv === normalizedClone || normalizedCv.includes(normalizedClone) || normalizedClone.includes(normalizedCv); if (matches) { console.log('[Verification] Matched clone URL:', cloneUrl, 'with verification:', cv); } return matches; })}
{cloneUrl} {#if loadingVerification} {:else if cloneVerification !== undefined} {#if cloneVerification.verified} Verified {:else} Unverified {/if} {:else if verificationStatus} {#if verificationStatus.cloneVerifications && verificationStatus.cloneVerifications.length > 0} Unknown {:else} Not verified {/if} {:else} Not checked {/if}
{/each} {#if pageData.repoCloneUrls.length > 3} +{pageData.repoCloneUrls.length - 3} more {/if}
{/if} {#if pageData.repoOwnerPubkey && userPubkey === pageData.repoOwnerPubkey} {/if}
{#if userPubkey} {#if hasUnlimitedAccess($userStore.userLevel) && (isRepoCloned === false || (isRepoCloned === null && !checkingCloneStatus))} {/if} {#if isMaintainer} Settings {/if} {#if pageData.repoOwnerPubkey && userPubkeyHex === pageData.repoOwnerPubkey} {#if verificationStatus?.verified !== true} {/if} {/if} {#if isMaintainer} {/if} {/if}
{#if isMaintainer && branches.length > 0 && currentBranch && branches.length > 1} {@const canDelete = defaultBranch !== null && currentBranch !== defaultBranch} {#if canDelete && currentBranch} {/if} {/if}
{#if error}
Error: {error}
{/if}
{#if activeTab === 'files'} {/if} {#if activeTab === 'history'} {/if} {#if activeTab === 'tags'} {/if} {#if activeTab === 'issues'} {/if} {#if activeTab === 'prs'} {/if}
{#if activeTab === 'files' && readmeContent && !currentFile}

README

View Raw Download ZIP
{#if loadingReadme}
Loading README...
{:else if readmeIsMarkdown && readmeHtml}
{@html readmeHtml}
{:else if readmeContent}
{readmeContent}
{/if}
{/if} {#if activeTab === 'files' && currentFile}
{currentFile}
{#if hasChanges} ● Unsaved changes {/if} {#if isMaintainer} {:else if userPubkey} Only maintainers can edit files. Submit a PR instead. {/if}
{#if loading}
Loading file...
{:else}
{#if isMaintainer} {:else}
{#if highlightedFileContent} {@html highlightedFileContent} {:else}
{fileContent}
{/if}
{/if}
{/if} {:else if activeTab === 'files'}

Select a file from the sidebar to view and edit it

{/if} {#if activeTab === 'history' && showDiff}

Diff for commit {selectedCommit?.slice(0, 7)}

{#each diffData as diff}
{diff.file} +{diff.additions} -{diff.deletions}
{diff.diff}
{/each}
{:else if activeTab === 'history'}

Select a commit to view its diff

{/if} {#if activeTab === 'tags'}

Tags are displayed in the sidebar

{/if} {#if activeTab === 'issues'}
{#if issues.length === 0}

No issues found. Create one to get started!

{:else} {#each issues as issue}

{issue.subject}

{issue.status} Created {new Date(issue.created_at * 1000).toLocaleString()}
{@html issue.content.replace(/\n/g, '
')}
{/each} {/if}
{/if} {#if activeTab === 'prs'}
{#if prs.length === 0}

No pull requests found. Create one to get started!

{:else if selectedPR} {#each prs.filter(p => p.id === selectedPR) as pr} {@const decoded = nip19.decode(npub)} {#if decoded.type === 'npub'} {@const repoOwnerPubkey = decoded.data as string} {/if} {/each} {:else} {#each prs as pr}
selectedPR = pr.id} onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); selectedPR = pr.id; } }} style="cursor: pointer;">

{pr.subject}

{pr.status} {#if pr.commitId} Commit: {pr.commitId.slice(0, 7)} {/if} Created {new Date(pr.created_at * 1000).toLocaleString()}
{@html pr.content.replace(/\n/g, '
')}
{/each} {/if}
{/if} {#if activeTab === 'docs'}
{#if loadingDocs}
Loading documentation...
{:else if documentationHtml}
{@html documentationHtml}
{:else if documentationContent === null}

No documentation found for this repository.

{:else}

Documentation content is empty.

{/if}
{/if} {#if activeTab === 'discussions'}

Discussions

{#if userPubkey} {/if}
{#if loadingDiscussions}
Loading discussions...
{:else if discussions.length === 0}

No discussions found. {#if userPubkey}Create a new discussion thread to get started!{:else}Log in to create a discussion thread.{/if}

{:else} {#each discussions as discussion} {@const isExpanded = discussion.type === 'thread' && expandedThreads.has(discussion.id)} {@const hasComments = discussion.comments && discussion.comments.length > 0}
{#if discussion.type === 'thread'} {/if}

{discussion.title}

{#if discussion.type === 'thread'} Thread {#if hasComments} {@const totalReplies = countAllReplies(discussion.comments)} {totalReplies} {totalReplies === 1 ? 'reply' : 'replies'} {/if} {:else} Comments {/if} Created {new Date(discussion.createdAt * 1000).toLocaleString()} {#if discussion.type === 'thread' && userPubkey} {/if}
{#if discussion.content}

{discussion.content}

{/if} {#if discussion.type === 'thread' && isExpanded && hasComments} {@const totalReplies = countAllReplies(discussion.comments)}

Replies ({totalReplies})

{#each discussion.comments! as comment}
{new Date(comment.createdAt * 1000).toLocaleString()} {#if userPubkey} {/if}

{comment.content}

{#if comment.replies && comment.replies.length > 0}
{#each comment.replies as reply}
{new Date(reply.createdAt * 1000).toLocaleString()} {#if userPubkey} {/if}

{reply.content}

{#if reply.replies && reply.replies.length > 0}
{#each reply.replies as nestedReply}
{new Date(nestedReply.createdAt * 1000).toLocaleString()} {#if userPubkey} {/if}

{nestedReply.content}

{/each}
{/if}
{/each}
{/if}
{/each}
{:else if discussion.type === 'comments' && hasComments} {@const totalReplies = countAllReplies(discussion.comments)}

Comments ({totalReplies})

{#each discussion.comments! as comment}
{new Date(comment.createdAt * 1000).toLocaleString()} {#if userPubkey} {/if}

{comment.content}

{#if comment.replies && comment.replies.length > 0}
{#each comment.replies as reply}
{new Date(reply.createdAt * 1000).toLocaleString()} {#if userPubkey} {/if}

{reply.content}

{#if reply.replies && reply.replies.length > 0}
{#each reply.replies as nestedReply}
{new Date(nestedReply.createdAt * 1000).toLocaleString()} {#if userPubkey} {/if}

{nestedReply.content}

{/each}
{/if}
{/each}
{/if}
{/each}
{/if}
{/each} {/if}
{/if}
{#if showCreateFileDialog && userPubkey && isMaintainer} {/if} {#if showCreateBranchDialog && userPubkey && isMaintainer} {/if} {#if showCreateTagDialog && userPubkey && isMaintainer} {/if} {#if showCreateIssueDialog && userPubkey} {/if} {#if showCreateThreadDialog && userPubkey} {/if} {#if showReplyDialog && userPubkey && (replyingToThread || replyingToComment)} {/if} {#if showCreatePRDialog && userPubkey} {/if} {#if showCommitDialog && userPubkey && isMaintainer} {/if} {#if showVerificationDialog && verificationFileContent} {/if}