{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 repoOwnerPubkey} showRepoMenu = !showRepoMenu} showMenu={showRepoMenu} userPubkey={userPubkey} isBookmarked={isBookmarked} loadingBookmark={loadingBookmark} onToggleBookmark={toggleBookmark} onFork={forkRepository} forking={forking} onCloneToServer={cloneRepository} cloning={cloning} checkingCloneStatus={checkingCloneStatus} onCreateIssue={() => showCreateIssueDialog = true} onCreatePR={() => showCreatePRDialog = true} onCreatePatch={() => showCreatePatchDialog = true} onCreateBranch={async () => { if (!userPubkey || !isMaintainer || needsClone) return; try { const settings = await settingsStore.getSettings(); defaultBranchName = settings.defaultBranch || 'master'; } catch { defaultBranchName = 'master'; } showCreateBranchDialog = true; }} onSettings={() => goto(`/signup?npub=${npub}&repo=${repo}`)} onGenerateVerification={pageData.repoOwnerPubkey && userPubkeyHex === pageData.repoOwnerPubkey && verificationStatus?.verified !== true ? generateAnnouncementFileForRepo : undefined} onDeleteAnnouncement={pageData.repoOwnerPubkey && userPubkeyHex === pageData.repoOwnerPubkey ? deleteAnnouncement : undefined} deletingAnnouncement={deletingAnnouncement} hasUnlimitedAccess={hasUnlimitedAccess($userStore.userLevel)} needsClone={needsClone} allMaintainers={allMaintainers} onCopyEventId={copyEventId} /> {/if} {#if pageData.repoWebsite || (pageData.repoCloneUrls && pageData.repoCloneUrls.length > 0) || pageData.repoLanguage || (pageData.repoTopics && pageData.repoTopics.length > 0) || forkInfo?.isFork} {/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 === 'patches'} {/if} {#if activeTab === 'discussions'} {/if} {#if activeTab === 'docs'} {/if}
{#if activeTab === 'files' && readmeContent && !currentFile}

README

View Raw Download ZIP
{#if loadingReadme}
Loading README...
{:else if readmeIsMarkdown && readmeHtml && readmeHtml.trim()}
{@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 === 'patches'}
{#if patches.length === 0}

No patches found. Create one to get started!

{:else if selectedPatch} {#each patches.filter(p => p.id === selectedPatch) as patch}

{patch.subject}

#{patch.id.slice(0, 7)} Created {new Date(patch.created_at * 1000).toLocaleString()}
{patch.content}
{/each} {:else}

Select a patch from the sidebar to view it

{/if}
{/if} {#if activeTab === 'discussions'}
{#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 if selectedDiscussion} {#each discussions.filter(d => d.id === selectedDiscussion) as discussion} {@const isExpanded = discussion.type === 'thread' && expandedThreads.has(discussion.id)} {@const hasComments = discussion.comments && discussion.comments.length > 0}

{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' && hasComments} {@const totalReplies = countAllReplies(discussion.comments)}

Replies ({totalReplies})

{#each discussion.comments! as comment}
{new Date(comment.createdAt * 1000).toLocaleString()} {#if userPubkey} {/if}
{#if true} {@const commentEvent = getDiscussionEvent(comment.id)} {@const referencedEvent = commentEvent ? getReferencedEventFromDiscussion(commentEvent) : undefined} {@const parts = processContentWithNostrLinks(comment.content)}
{#if referencedEvent}
{formatDiscussionTime(referencedEvent.created_at)}
{referencedEvent.content || '(No content)'}
{/if}
{#each parts as part} {#if part.type === 'text'} {part.value} {:else if part.type === 'event' && part.event} {:else if part.type === 'profile' && part.pubkey} {:else} {part.value} {/if} {/each}
{/if} {#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}
{#if true} {@const commentEvent = getDiscussionEvent(comment.id)} {@const referencedEvent = commentEvent ? getReferencedEventFromDiscussion(commentEvent) : undefined} {@const parts = processContentWithNostrLinks(comment.content)}
{#if referencedEvent}
{formatDiscussionTime(referencedEvent.created_at)}
{referencedEvent.content || '(No content)'}
{/if}
{#each parts as part} {#if part.type === 'text'} {part.value} {:else if part.type === 'event' && part.event} {:else if part.type === 'profile' && part.pubkey} {:else} {part.value} {/if} {/each}
{/if}
{/each}
{/if}
{/each} {:else}

Select a discussion from the sidebar to view it

{/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 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 showCreatePatchDialog && userPubkey} {/if} {#if showCommitDialog && userPubkey && isMaintainer} {/if} {#if showVerificationDialog && verificationFileContent} {/if}