mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-09-13 14:27:17 +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