From b103210c6e6a72c605cad092ebf54dbe74d9147a Mon Sep 17 00:00:00 2001 From: whereareiam Date: Thu, 22 Oct 2026 21:59:50 +0200 Subject: [PATCH] fix(repo): show the repository title row only on the code home GitHub shows the repository name, visibility and Watch/Fork/Star only on the code home; every other repository page starts 24px below the tabs. repo/header now renders nothing, repo/home and repo/empty render the title row from repo/home_header, and the per-page rules that hid it on releases, tags, the commit page and projects are gone. Co-Authored-By: Claude Opus 5.5 --- src/build-output.test.ts | 20 ++++++- src/repo-mirror.test.ts | 2 +- styles/pages/projects.css | 6 +- styles/pages/releases.css | 17 ++---- styles/templates/repo/commit_page.ts | 4 -- styles/templates/repo/header.ts | 6 ++ templates/repo/diff/compare.tmpl | 1 - templates/repo/empty.tmpl | 83 +++++++++++++++++++++++++++ templates/repo/header.tmpl | 85 +--------------------------- templates/repo/home.tmpl | 2 +- templates/repo/home_header.tmpl | 83 +++++++++++++++++++++++++++ templates/repo/projects/view.tmpl | 1 - templates/repo/release/list.tmpl | 1 - templates/repo/tag/list.tmpl | 1 - 14 files changed, 199 insertions(+), 113 deletions(-) create mode 100644 templates/repo/empty.tmpl create mode 100644 templates/repo/home_header.tmpl diff --git a/src/build-output.test.ts b/src/build-output.test.ts index 0d369c50..a1a0b6b9 100644 --- a/src/build-output.test.ts +++ b/src/build-output.test.ts @@ -318,6 +318,8 @@ describe("Forgejo 15 native integration", () => { "repo/global_header.tmpl", "repo/header.tmpl", "repo/home.tmpl", + "repo/home_header.tmpl", + "repo/empty.tmpl", "repo/home_sidebar_bottom.tmpl", "repo/home_sidebar_top.tmpl", "repo/view_content.tmpl", @@ -476,9 +478,23 @@ describe("Forgejo 15 native integration", () => { expect(repoContentStyle).toContain(".repo-code-actions > li > a:hover"); }); + it("shows the repository title row only on the code home, as GitHub does", () => { + const read = (...parts: string[]) => fs.readFileSync(path.join(ROOT_DIR, "templates", ...parts), "utf-8"); + + expect(read("repo", "header.tmpl")).not.toContain("<"); + expect(read("repo", "home.tmpl")).toContain('{{template "repo/home_header" .}}'); + expect(read("repo", "empty.tmpl")).toContain('{{template "repo/home_header" .}}'); + for (const page of [ + ["repo", "release", "list.tmpl"], + ["repo", "tag", "list.tmpl"], + ["repo", "diff", "compare.tmpl"], + ]) + expect(read(...page)).not.toContain('template "repo/header"'); + }); + it("matches GitHub's repository About, visibility, and code-search details", () => { const headerStyle = fs.readFileSync(path.join(ROOT_DIR, "styles", "templates", "repo", "header.ts"), "utf-8"); - const headerTemplate = fs.readFileSync(path.join(ROOT_DIR, "templates", "repo", "header.tmpl"), "utf-8"); + const headerTemplate = fs.readFileSync(path.join(ROOT_DIR, "templates", "repo", "home_header.tmpl"), "utf-8"); const repoContentStyle = fs.readFileSync( path.join(ROOT_DIR, "styles", "templates", "repo", "view_content.ts"), "utf-8" @@ -597,9 +613,9 @@ describe("Forgejo 15 native integration", () => { expect(diffBoxTemplate).toContain( "const diffTreeVisible = localStorage?.getItem('diff_file_tree_visible') !== 'false';" ); - expect(commitPageStyle).toContain("> .repository-content-header"); const diffViewStyle = fs.readFileSync(path.join(ROOT_DIR, "styles", "components", "repo", "diff_view.ts"), "utf8"); expect(diffViewStyle).toContain("min-height: 40px;"); + expect(commitPageStyle).not.toContain("repository-content-header"); expect(diffBoxTemplate).toContain('template "repo/diff/file_header"'); expect(commitPageTemplate).toContain('template "repo/diff/change_summary"'); }); diff --git a/src/repo-mirror.test.ts b/src/repo-mirror.test.ts index e2e060a8..3f01b844 100644 --- a/src/repo-mirror.test.ts +++ b/src/repo-mirror.test.ts @@ -95,7 +95,7 @@ describe("mirror badge disclosure", () => { it("keeps native mirror address sanitization, visibility precedence and relative sync time", () => { const template = readFileSync(new URL("../templates/repo/mirror_badge.tmpl", import.meta.url), "utf8"); - const header = readFileSync(new URL("../templates/repo/header.tmpl", import.meta.url), "utf8"); + const header = readFileSync(new URL("../templates/repo/home_header.tmpl", import.meta.url), "utf8"); expect(header).toContain('{{if $.PullMirror}}\n\t\t\t\t\t\t{{template "repo/mirror_badge" $}}'); expect(header).not.toContain('ctx.Locale.Tr "repo.mirror_from"'); expect(template).toContain("MirrorRemoteAddress .Context .PullMirror"); diff --git a/styles/pages/projects.css b/styles/pages/projects.css index 6cddccb2..7e989d92 100644 --- a/styles/pages/projects.css +++ b/styles/pages/projects.css @@ -1,10 +1,7 @@ /* Project board in GitHub's layout, and the side panel that opens a card's issue. Kept as a page stylesheet, outside the size-limited theme files. */ -/* Page: GitHub shows a project without the repository header, at full width. */ -.page-content.repository.github-project-page .repository-content-header { - display: none; -} +/* Page: GitHub shows a project at full width. */ .full.height > .page-content.github-project-page { margin-top: 0; padding-top: 0; @@ -437,7 +434,6 @@ .github-embedded #navbar-drawer, .github-embedded .repository-tab-nav, .github-embedded .secondary-nav, -.github-embedded .repository-content-header, .github-embedded .page-footer { display: none !important; } diff --git a/styles/pages/releases.css b/styles/pages/releases.css index 06a8d17f..78b819d5 100644 --- a/styles/pages/releases.css +++ b/styles/pages/releases.css @@ -1,8 +1,5 @@ /* Releases, tags and the release form. Kept as a page stylesheet, outside the size-limited theme files. */ -.page-content.repository.github-releases .repository-content-header { - display: none; -} .page-content.repository.github-releases > .ui.container { box-sizing: border-box; max-width: calc(100% - 32px); @@ -17,7 +14,7 @@ gap: 16px; justify-content: space-between; margin: 0 0 32px; - padding: 24px 0; + padding: 0 0 24px; } .github-release-actions { align-items: center; @@ -470,13 +467,13 @@ > .ui.container { max-width: calc(100% - 32px); width: calc(100% - 32px) !important; - margin: 0 auto !important; + margin: 24px auto 0 !important; padding: 0; } .github-release-toolbar { gap: 8px; margin: 0 14px 16px; - padding: 24px 0 16px; + padding: 0 0 16px; } .github-release-content { display: block; @@ -635,9 +632,6 @@ } } /* New and edit release: GitHub's form page, on Forgejo's own template. */ -.page-content.repository.new.release .repository-content-header { - display: none; -} .page-content.repository.new.release { > .ui.container { box-sizing: border-box; @@ -711,9 +705,6 @@ font-weight: 500; } } -.page-content.repository.github-tags .repository-content-header { - display: none; -} .page-content.repository.github-tags > .ui.container { box-sizing: border-box; max-width: calc(100% - 32px); @@ -726,7 +717,7 @@ display: flex; justify-content: space-between; margin-bottom: 16px; - padding: 24px 0; + padding: 0 0 24px; } .github-tags-search { width: 248px; diff --git a/styles/templates/repo/commit_page.ts b/styles/templates/repo/commit_page.ts index a3287060..fd927ed1 100644 --- a/styles/templates/repo/commit_page.ts +++ b/styles/templates/repo/commit_page.ts @@ -21,10 +21,6 @@ import { css, cssCombine, otherThemeVars, themeVars } from "@lutinglt/gitea-gith const commitPage = css` .page-content.repository.diff.commit-page { - > .repository-content-header { - display: none; - } - > .commit-page-container.ui.container.fluid.padded { margin: 0; max-width: none; diff --git a/styles/templates/repo/header.ts b/styles/templates/repo/header.ts index 9d6730b4..72c1641d 100644 --- a/styles/templates/repo/header.ts +++ b/styles/templates/repo/header.ts @@ -165,6 +165,12 @@ const repositoryHeader = css` margin: -1px 0 0; } + /* GitHub starts a repository page 24px below the tabs. Same specificity as Forgejo's 16px rule, so page layouts such + as the sidebar still set their own. */ + .page-content.repository > :first-child:where(:not(.secondary-nav)) { + margin-top: 24px; + } + .page-content.repository > .repository-content-header { border-bottom: 0; margin-bottom: 24px; diff --git a/templates/repo/diff/compare.tmpl b/templates/repo/diff/compare.tmpl index ba692fea..ab0508ed 100644 --- a/templates/repo/diff/compare.tmpl +++ b/templates/repo/diff/compare.tmpl @@ -2,7 +2,6 @@ {{/* Forgejo 17 compare.tmpl, laid out like GitHub's "Compare changes": centred container, the create box with its text and the button on the right, and the equal-branches notice with a disabled button. */}}
- {{template "repo/header" .}} {{$showDiffBox := false}} {{$canReadPullRequests := .Permission.CanRead $.UnitTypePullRequests}}
diff --git a/templates/repo/empty.tmpl b/templates/repo/empty.tmpl new file mode 100644 index 00000000..4099897f --- /dev/null +++ b/templates/repo/empty.tmpl @@ -0,0 +1,83 @@ +{{/* Forgejo 17 template; the only change is the title row, which GitHub shows on an empty repository too. */}} +{{template "base/head" .}} +
+ {{template "repo/home_header" .}} +
+
+
+ {{template "base/alert" .}} + {{if .Repository.IsArchived}} +
+ {{if .Repository.ArchivedUnix.IsZero}} + {{ctx.Locale.Tr "repo.archive.title"}} + {{else}} + {{ctx.Locale.Tr "repo.archive.title_date" (DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} + {{end}} +
+ {{end}} + {{if .Repository.IsBroken}} +
+ {{ctx.Locale.Tr "repo.broken_message"}} +
+ {{else if .CanWriteCode}} +

+ {{ctx.Locale.Tr "repo.quick_guide"}} +

+
+
+

{{ctx.Locale.Tr "repo.clone_this_repo"}} {{ctx.Locale.Tr "repo.clone_helper" "http://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository"}}

+ +
+ {{if and .CanWriteCode (not .Repository.IsArchived)}} + + {{ctx.Locale.Tr "file_editor.new_file"}} + + {{if .RepositoryUploadEnabled}} + + {{ctx.Locale.Tr "file_editor.upload_file"}} + + {{end}} + {{end}} +
+ {{template "repo/clone_buttons" .}} +
+
+
+ + {{if not .Repository.IsArchived}} +
+ +
+

{{ctx.Locale.Tr "repo.create_new_repo_command"}}

+
+
touch README.md
+git init{{if eq .Repository.ObjectFormatName "sha256"}} --object-format=sha256{{end}}
+{{if ne .Repository.DefaultBranch "master"}}git switch -c {{.Repository.DefaultBranch}}{{end}}
+git add README.md
+git commit -m "first commit"
+git remote add origin {{$.CloneButtonOriginLink.HTTPS}}
+git push -u origin {{.Repository.DefaultBranch}}
+
+
+
+ +
+

{{ctx.Locale.Tr "repo.push_exist_repo"}}

+
+
git remote add origin {{$.CloneButtonOriginLink.HTTPS}}
+git push -u origin {{.Repository.DefaultBranch}}
+
+
+ {{end}} + {{else}} +
+ {{ctx.Locale.Tr "repo.empty_message"}} +
+ {{end}} + {{template "repo/clone_script" .}} +
+
+
+
+
+{{template "base/footer" .}} diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index e93f2da8..cef9c2e8 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -1,83 +1,2 @@ -{{/* Repository content header adapted to Forgejo template data. */}} -
-{{with .Repository}} -
-
-
- -
-
- {{.Name}} -
-
-
- {{if .IsArchived}} - {{ctx.Locale.Tr "repo.desc.archived"}} -
{{svg "octicon-archive" 18}}
- {{end}} - {{if $.PullMirror}} - {{template "repo/mirror_badge" $}} - {{else if .IsPrivate}} - {{ctx.Locale.Tr "repo.desc.private"}} -
{{svg "octicon-lock" 18}}
- {{else if .Owner.Visibility.IsPrivate}} - {{ctx.Locale.Tr "repo.desc.internal"}} -
{{svg "octicon-shield-lock" 18}}
- {{else}} - {{ctx.Locale.Tr "user.visibility.public.title"}} - {{end}} - {{if .IsTemplate}} - {{ctx.Locale.Tr "repo.desc.template"}} -
{{svg "octicon-repo-template" 18}}
- {{end}} - {{if eq .ObjectFormatName "sha256"}} - {{ctx.Locale.Tr "repo.desc.sha256"}} - {{end}} -
-
- {{if not (or .IsBeingCreated .IsBroken)}} -
- {{if $.RepoTransfer}} -
-
- -
-
-
-
- -
-
- {{end}} - {{/* GitHub has no feed button here; the feed stays linked from the page head. */}} - {{template "repo/watch_unwatch" $}} - {{if not $.DisableForks}} - {{template "repo/header_fork" $}} - {{end}} - {{if not $.DisableStars}} - {{template "repo/star_unstar" $}} - {{end}} - {{if and $.IsModerationEnabled $.IsSigned (not $.IsRepositoryAdmin)}} - - {{end}} -
- {{end}} -
- {{if .IsFork}}
{{ctx.Locale.Tr "repo.forked_from"}} {{.BaseRepo.FullName}}
{{end}} - {{if .IsGenerated}}
{{ctx.Locale.Tr "repo.generated_from"}} {{(.TemplateRepo ctx).FullName}}
{{end}} -
-{{end}} -
+{{/* Forgejo calls this from every repository page. GitHub shows the title row only on the code home, so repo/home and +repo/empty render repo/home_header themselves and every other page starts below the tabs. */}} diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl index 29f7c2e8..f7ec040b 100644 --- a/templates/repo/home.tmpl +++ b/templates/repo/home.tmpl @@ -3,7 +3,7 @@ {{$showSidebar := and (not .TreeNames) (not .HideRepoInfo) (not .IsBlame)}} {{/* Layout classes instead of CSS :has(): a :has() on .page-content restyles the whole page, every line of a large file included, on any DOM change. */}}
- {{if not .TreeNames}}{{template "repo/header" .}}{{end}} + {{if not .TreeNames}}{{template "repo/home_header" .}}{{end}}
{{template "base/alert" .}} diff --git a/templates/repo/home_header.tmpl b/templates/repo/home_header.tmpl new file mode 100644 index 00000000..7f0e1ca4 --- /dev/null +++ b/templates/repo/home_header.tmpl @@ -0,0 +1,83 @@ +{{/* Repository title row: GitHub shows the name, visibility and Watch/Fork/Star only on the code home. */}} +
+{{with .Repository}} +
+
+
+ +
+
+ {{.Name}} +
+
+
+ {{if .IsArchived}} + {{ctx.Locale.Tr "repo.desc.archived"}} +
{{svg "octicon-archive" 18}}
+ {{end}} + {{if $.PullMirror}} + {{template "repo/mirror_badge" $}} + {{else if .IsPrivate}} + {{ctx.Locale.Tr "repo.desc.private"}} +
{{svg "octicon-lock" 18}}
+ {{else if .Owner.Visibility.IsPrivate}} + {{ctx.Locale.Tr "repo.desc.internal"}} +
{{svg "octicon-shield-lock" 18}}
+ {{else}} + {{ctx.Locale.Tr "user.visibility.public.title"}} + {{end}} + {{if .IsTemplate}} + {{ctx.Locale.Tr "repo.desc.template"}} +
{{svg "octicon-repo-template" 18}}
+ {{end}} + {{if eq .ObjectFormatName "sha256"}} + {{ctx.Locale.Tr "repo.desc.sha256"}} + {{end}} +
+
+ {{if not (or .IsBeingCreated .IsBroken)}} +
+ {{if $.RepoTransfer}} +
+
+ +
+
+
+
+ +
+
+ {{end}} + {{/* GitHub has no feed button here; the feed stays linked from the page head. */}} + {{template "repo/watch_unwatch" $}} + {{if not $.DisableForks}} + {{template "repo/header_fork" $}} + {{end}} + {{if not $.DisableStars}} + {{template "repo/star_unstar" $}} + {{end}} + {{if and $.IsModerationEnabled $.IsSigned (not $.IsRepositoryAdmin)}} + + {{end}} +
+ {{end}} +
+ {{if .IsFork}}
{{ctx.Locale.Tr "repo.forked_from"}} {{.BaseRepo.FullName}}
{{end}} + {{if .IsGenerated}}
{{ctx.Locale.Tr "repo.generated_from"}} {{(.TemplateRepo ctx).FullName}}
{{end}} +
+{{end}} +
diff --git a/templates/repo/projects/view.tmpl b/templates/repo/projects/view.tmpl index 93cf6901..94b6196d 100644 --- a/templates/repo/projects/view.tmpl +++ b/templates/repo/projects/view.tmpl @@ -9,7 +9,6 @@ {{end}}
- {{template "repo/header" .}}
{{template "projects/view" .}}
diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index d50f2298..8978f537 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -1,7 +1,6 @@ {{template "base/head" .}} {{$single := StringUtils.Contains .Link "/releases/tag/"}}
- {{template "repo/header" .}}
{{template "base/alert" .}} {{if and $single .Releases}} diff --git a/templates/repo/tag/list.tmpl b/templates/repo/tag/list.tmpl index 9a555ca8..2e2a8b94 100644 --- a/templates/repo/tag/list.tmpl +++ b/templates/repo/tag/list.tmpl @@ -1,6 +1,5 @@ {{template "base/head" .}}
- {{template "repo/header" .}}
{{template "base/alert" .}} {{$canReadReleases := $.Permission.CanRead $.UnitTypeReleases}}