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 ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	gotemplate "html/template" | ||||||
|  | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"path" | 	"path" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | @ -180,20 +182,30 @@ func prepareOrgProfileReadme(ctx *context.Context, profileGitRepo *git.Repositor | ||||||
| 	} else { | 	} else { | ||||||
| 		defer rc.Close() | 		defer rc.Close() | ||||||
| 
 | 
 | ||||||
| 		if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | 		if markupType := markup.Type(profileReadme.Name()); markupType != "" { | ||||||
| 			Ctx:     ctx, | 			if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | ||||||
| 			GitRepo: profileGitRepo, | 				Ctx:     ctx, | ||||||
| 			Links: markup.Links{ | 				Type:    markupType, | ||||||
| 				// Pass repo link to markdown render for the full link of media elements. | 				GitRepo: profileGitRepo, | ||||||
| 				// The profile of default branch would be shown. | 				Links: markup.Links{ | ||||||
| 				Base:       profileDbRepo.Link(), | 					// Pass repo link to markdown render for the full link of media elements. | ||||||
| 				BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | 					// The profile of default branch would be shown. | ||||||
| 			}, | 					Base:       profileDbRepo.Link(), | ||||||
| 			Metas: map[string]string{"mode": "document"}, | 					BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | ||||||
| 		}, rc); err != nil { | 				}, | ||||||
| 			log.Error("failed to RenderString: %v", err) | 				Metas: map[string]string{"mode": "document"}, | ||||||
|  | 			}, rc); err != nil { | ||||||
|  | 				log.Error("failed to RenderString: %v", err) | ||||||
|  | 			} else { | ||||||
|  | 				ctx.Data["ProfileReadme"] = profileContent | ||||||
|  | 			} | ||||||
| 		} else { | 		} 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/markup/markdown" | ||||||
| 	"forgejo.org/modules/optional" | 	"forgejo.org/modules/optional" | ||||||
| 	"forgejo.org/modules/setting" | 	"forgejo.org/modules/setting" | ||||||
|  | 	"forgejo.org/routers/web/repo" | ||||||
| 	"forgejo.org/services/context" | 	"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 { | 				if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil { | ||||||
| 					log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err) | 					log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err) | ||||||
| 				} else { | 				} 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 ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	gotemplate "html/template" | ||||||
|  | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"path" | 	"path" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | @ -269,23 +271,33 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb | ||||||
| 		} else { | 		} else { | ||||||
| 			defer rc.Close() | 			defer rc.Close() | ||||||
| 
 | 
 | ||||||
| 			if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | 			if markupType := markup.Type(profileReadme.Name()); markupType != "" { | ||||||
| 				Ctx:     ctx, | 				if profileContent, err := markdown.RenderReader(&markup.RenderContext{ | ||||||
| 				GitRepo: profileGitRepo, | 					Ctx:     ctx, | ||||||
| 				Links: markup.Links{ | 					Type:    markupType, | ||||||
| 					// Give the repo link to the markdown render for the full link of media element. | 					GitRepo: profileGitRepo, | ||||||
| 					// the media link usually be like /[user]/[repoName]/media/branch/[branchName], | 					Links: markup.Links{ | ||||||
| 					// 	Eg. /Tom/.profile/media/branch/main | 						// Give the repo link to the markdown render for the full link of media element. | ||||||
| 					// The branch shown on the profile page is the default branch, this need to be in sync with doc, see: | 						// the media link usually be like /[user]/[repoName]/media/branch/[branchName], | ||||||
| 					//	https://docs.gitea.com/usage/profile-readme | 						// 	Eg. /Tom/.profile/media/branch/main | ||||||
| 					Base:       profileDbRepo.Link(), | 						// The branch shown on the profile page is the default branch, this need to be in sync with doc, see: | ||||||
| 					BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | 						//	https://docs.gitea.com/usage/profile-readme | ||||||
| 				}, | 						Base:       profileDbRepo.Link(), | ||||||
| 				Metas: map[string]string{"mode": "document"}, | 						BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), | ||||||
| 			}, rc); err != nil { | 					}, | ||||||
| 				log.Error("failed to RenderString: %v", err) | 					Metas: map[string]string{"mode": "document"}, | ||||||
|  | 				}, rc); err != nil { | ||||||
|  | 					log.Error("failed to RenderString: %v", err) | ||||||
|  | 				} else { | ||||||
|  | 					ctx.Data["ProfileReadme"] = profileContent | ||||||
|  | 				} | ||||||
| 			} else { | 			} 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" | 	default: // default to "repositories" | ||||||
|  |  | ||||||
|  | @ -11,7 +11,13 @@ | ||||||
| 		<div class="ui mobile reversed stackable grid"> | 		<div class="ui mobile reversed stackable grid"> | ||||||
| 			<div class="ui {{if .ShowMemberAndTeamTab}}eleven wide{{end}} column"> | 			<div class="ui {{if .ShowMemberAndTeamTab}}eleven wide{{end}} column"> | ||||||
| 				{{if .ProfileReadme}} | 				{{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}} | 				{{end}} | ||||||
| 				{{template "shared/repo_search" .}} | 				{{template "shared/repo_search" .}} | ||||||
| 				{{template "explore/repo_list" .}} | 				{{template "explore/repo_list" .}} | ||||||
|  |  | ||||||
|  | @ -51,7 +51,13 @@ | ||||||
| 				{{else if eq .TabName "followers"}} | 				{{else if eq .TabName "followers"}} | ||||||
| 					{{template "repo/user_cards" .}} | 					{{template "repo/user_cards" .}} | ||||||
| 				{{else if eq .TabName "overview"}} | 				{{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}} | 				{{else}} | ||||||
| 					{{template "shared/repo_search" .}} | 					{{template "shared/repo_search" .}} | ||||||
| 					{{template "explore/repo_list" .}} | 					{{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.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) { | 		t.Run("readme-size", func(t *testing.T) { | ||||||
| 			defer tests.PrintCurrentTest(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.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) { | 		t.Run("readme-size", func(t *testing.T) { | ||||||
| 			defer tests.PrintCurrentTest(t)() | 			defer tests.PrintCurrentTest(t)() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue