mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 14:31:02 +00:00 
			
		
		
		
	feat: allow any README for .profile (#8798)
		
	closes #1624 Co-authored-by: Maxim Slipenko <maks1ms@altlinux.org> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8798 Reviewed-by: Otto <otto@codeberg.org> Co-authored-by: Maxim Slipenko <maks1ms@noreply.codeberg.org> Co-committed-by: Maxim Slipenko <maks1ms@noreply.codeberg.org>
This commit is contained in:
		
					parent
					
						
							
								a87153b089
							
						
					
				
			
			
				commit
				
					
						ed3b70cbb9
					
				
			
		
					 7 changed files with 102 additions and 34 deletions
				
			
		|  | @ -5,6 +5,8 @@ package org | |||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	gotemplate "html/template" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"path" | ||||
| 	"strings" | ||||
|  | @ -180,20 +182,30 @@ func prepareOrgProfileReadme(ctx *context.Context, profileGitRepo *git.Repositor | |||
| 	} else { | ||||
| 		defer rc.Close() | ||||
| 
 | ||||
| 		if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | ||||
| 			Ctx:     ctx, | ||||
| 			GitRepo: profileGitRepo, | ||||
| 			Links: markup.Links{ | ||||
| 				// Pass repo link to markdown render for the full link of media elements. | ||||
| 				// The profile of default branch would be shown. | ||||
| 				Base:       profileDbRepo.Link(), | ||||
| 				BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | ||||
| 			}, | ||||
| 			Metas: map[string]string{"mode": "document"}, | ||||
| 		}, rc); err != nil { | ||||
| 			log.Error("failed to RenderString: %v", err) | ||||
| 		if markupType := markup.Type(profileReadme.Name()); markupType != "" { | ||||
| 			if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | ||||
| 				Ctx:     ctx, | ||||
| 				Type:    markupType, | ||||
| 				GitRepo: profileGitRepo, | ||||
| 				Links: markup.Links{ | ||||
| 					// Pass repo link to markdown render for the full link of media elements. | ||||
| 					// The profile of default branch would be shown. | ||||
| 					Base:       profileDbRepo.Link(), | ||||
| 					BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | ||||
| 				}, | ||||
| 				Metas: map[string]string{"mode": "document"}, | ||||
| 			}, rc); err != nil { | ||||
| 				log.Error("failed to RenderString: %v", err) | ||||
| 			} else { | ||||
| 				ctx.Data["ProfileReadme"] = profileContent | ||||
| 			} | ||||
| 		} else { | ||||
| 			ctx.Data["ProfileReadme"] = profileContent | ||||
| 			content, err := io.ReadAll(rc) | ||||
| 			if err != nil { | ||||
| 				log.Error("Read readme content failed: %v", err) | ||||
| 			} | ||||
| 			ctx.Data["ProfileReadme"] = gotemplate.HTMLEscapeString(util.UnsafeBytesToString(content)) | ||||
| 			ctx.Data["IsProfileReadmePlain"] = true | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ import ( | |||
| 	"forgejo.org/modules/markup/markdown" | ||||
| 	"forgejo.org/modules/optional" | ||||
| 	"forgejo.org/modules/setting" | ||||
| 	"forgejo.org/routers/web/repo" | ||||
| 	"forgejo.org/services/context" | ||||
| ) | ||||
| 
 | ||||
|  | @ -104,7 +105,22 @@ func FindUserProfileReadme(ctx *context.Context, doer *user_model.User) (profile | |||
| 				if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil { | ||||
| 					log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err) | ||||
| 				} else { | ||||
| 					profileReadmeBlob, _ = commit.GetBlobByFoldedPath("README.md") | ||||
| 					tree, err := commit.SubTree("") | ||||
| 					if err != nil { | ||||
| 						log.Error("FindUserProfileReadme failed to get SubTree: %v", err) | ||||
| 					} else { | ||||
| 						entries, err := tree.ListEntries() | ||||
| 						if err != nil { | ||||
| 							log.Error("FindUserProfileReadme failed to list entries: %v", err) | ||||
| 						} else { | ||||
| 							_, readmeEntry, err := repo.FindReadmeFileInEntries(ctx, entries, true) | ||||
| 							if err != nil { | ||||
| 								log.Error("FindUserProfileReadme failed to find readme in entries: %v", err) | ||||
| 							} else if readmeEntry != nil { | ||||
| 								profileReadmeBlob = readmeEntry.Blob() | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ package user | |||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	gotemplate "html/template" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"path" | ||||
| 	"strings" | ||||
|  | @ -269,23 +271,33 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb | |||
| 		} else { | ||||
| 			defer rc.Close() | ||||
| 
 | ||||
| 			if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | ||||
| 				Ctx:     ctx, | ||||
| 				GitRepo: profileGitRepo, | ||||
| 				Links: markup.Links{ | ||||
| 					// Give the repo link to the markdown render for the full link of media element. | ||||
| 					// the media link usually be like /[user]/[repoName]/media/branch/[branchName], | ||||
| 					// 	Eg. /Tom/.profile/media/branch/main | ||||
| 					// The branch shown on the profile page is the default branch, this need to be in sync with doc, see: | ||||
| 					//	https://docs.gitea.com/usage/profile-readme | ||||
| 					Base:       profileDbRepo.Link(), | ||||
| 					BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | ||||
| 				}, | ||||
| 				Metas: map[string]string{"mode": "document"}, | ||||
| 			}, rc); err != nil { | ||||
| 				log.Error("failed to RenderString: %v", err) | ||||
| 			if markupType := markup.Type(profileReadme.Name()); markupType != "" { | ||||
| 				if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | ||||
| 					Ctx:     ctx, | ||||
| 					Type:    markupType, | ||||
| 					GitRepo: profileGitRepo, | ||||
| 					Links: markup.Links{ | ||||
| 						// Give the repo link to the markdown render for the full link of media element. | ||||
| 						// the media link usually be like /[user]/[repoName]/media/branch/[branchName], | ||||
| 						// 	Eg. /Tom/.profile/media/branch/main | ||||
| 						// The branch shown on the profile page is the default branch, this need to be in sync with doc, see: | ||||
| 						//	https://docs.gitea.com/usage/profile-readme | ||||
| 						Base:       profileDbRepo.Link(), | ||||
| 						BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | ||||
| 					}, | ||||
| 					Metas: map[string]string{"mode": "document"}, | ||||
| 				}, rc); err != nil { | ||||
| 					log.Error("failed to RenderString: %v", err) | ||||
| 				} else { | ||||
| 					ctx.Data["ProfileReadme"] = profileContent | ||||
| 				} | ||||
| 			} else { | ||||
| 				ctx.Data["ProfileReadme"] = profileContent | ||||
| 				content, err := io.ReadAll(rc) | ||||
| 				if err != nil { | ||||
| 					log.Error("Read readme content failed: %v", err) | ||||
| 				} | ||||
| 				ctx.Data["ProfileReadme"] = gotemplate.HTMLEscapeString(util.UnsafeBytesToString(content)) | ||||
| 				ctx.Data["IsProfileReadmePlain"] = true | ||||
| 			} | ||||
| 		} | ||||
| 	default: // default to "repositories" | ||||
|  |  | |||
|  | @ -11,7 +11,13 @@ | |||
| 		<div class="ui mobile reversed stackable grid"> | ||||
| 			<div class="ui {{if .ShowMemberAndTeamTab}}eleven wide{{end}} column"> | ||||
| 				{{if .ProfileReadme}} | ||||
| 					<div id="readme_profile" class="markup">{{.ProfileReadme}}</div> | ||||
| 					<div id="readme_profile" class="{{if not .IsProfileReadmePlain}}markup{{end}}"> | ||||
| 					{{if .IsProfileReadmePlain}} | ||||
| 						<pre>{{.ProfileReadme}}</pre> | ||||
| 					{{else}} | ||||
| 						{{.ProfileReadme}} | ||||
| 					{{end}} | ||||
| 					</div> | ||||
| 				{{end}} | ||||
| 				{{template "shared/repo_search" .}} | ||||
| 				{{template "explore/repo_list" .}} | ||||
|  |  | |||
|  | @ -51,7 +51,13 @@ | |||
| 				{{else if eq .TabName "followers"}} | ||||
| 					{{template "repo/user_cards" .}} | ||||
| 				{{else if eq .TabName "overview"}} | ||||
| 					<div id="readme_profile" class="markup">{{.ProfileReadme}}</div> | ||||
| 					<div id="readme_profile" class="{{if not .IsProfileReadmePlain}}markup{{end}}"> | ||||
| 					{{if .IsProfileReadmePlain}} | ||||
| 						<pre>{{.ProfileReadme}}</pre> | ||||
| 					{{else}} | ||||
| 						{{.ProfileReadme}} | ||||
| 					{{end}} | ||||
| 					</div> | ||||
| 				{{else}} | ||||
| 					{{template "shared/repo_search" .}} | ||||
| 					{{template "explore/repo_list" .}} | ||||
|  |  | |||
|  | @ -64,7 +64,15 @@ func TestOrgProfile(t *testing.T) { | |||
| 		checkReadme(t, "README.md", "README.md", 1) | ||||
| 		checkReadme(t, "readme.md", "readme.md", 1) | ||||
| 		checkReadme(t, "ReadMe.mD", "ReadMe.mD", 1) | ||||
| 		checkReadme(t, "readme.org does not render", "README.org", 0) | ||||
| 		checkReadme(t, "readme.org", "README.org", 1) | ||||
| 		checkReadme(t, "README.en-us.md", "README.en-us.md", 1) | ||||
| 		checkReadme(t, "README.en.md", "README.en.md", 1) | ||||
| 		checkReadme(t, "README.txt", "README.txt", 1) | ||||
| 		checkReadme(t, "README", "README", 1) | ||||
| 		checkReadme(t, "README.mdown", "README.mdown", 1) | ||||
| 		checkReadme(t, "README.i18n.md", "README.i18n.md", 1) | ||||
| 		checkReadme(t, "readmee", "readmee", 0) | ||||
| 		checkReadme(t, "test.md", "test.md", 0) | ||||
| 
 | ||||
| 		t.Run("readme-size", func(t *testing.T) { | ||||
| 			defer tests.PrintCurrentTest(t)() | ||||
|  |  | |||
|  | @ -64,7 +64,15 @@ func TestUserProfile(t *testing.T) { | |||
| 		checkReadme(t, "README.md", "README.md", 1) | ||||
| 		checkReadme(t, "readme.md", "readme.md", 1) | ||||
| 		checkReadme(t, "ReadMe.mD", "ReadMe.mD", 1) | ||||
| 		checkReadme(t, "readme.org does not render", "README.org", 0) | ||||
| 		checkReadme(t, "readme.org", "README.org", 1) | ||||
| 		checkReadme(t, "README.en-us.md", "README.en-us.md", 1) | ||||
| 		checkReadme(t, "README.en.md", "README.en.md", 1) | ||||
| 		checkReadme(t, "README.txt", "README.txt", 1) | ||||
| 		checkReadme(t, "README", "README", 1) | ||||
| 		checkReadme(t, "README.mdown", "README.mdown", 1) | ||||
| 		checkReadme(t, "README.i18n.md", "README.i18n.md", 1) | ||||
| 		checkReadme(t, "readmee", "readmee", 0) | ||||
| 		checkReadme(t, "test.md", "test.md", 0) | ||||
| 
 | ||||
| 		t.Run("readme-size", func(t *testing.T) { | ||||
| 			defer tests.PrintCurrentTest(t)() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue