-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Improve template helper #24417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Improve template helper #24417
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
d605833
improve string/json utils
wxiaoguang 6ef01c7
refactor
wxiaoguang f80d674
Merge branch 'main' into improve-template-helper
GiteaBot 407367c
use global variable for StringUtils and JsonUtils
wxiaoguang 203a50e
Merge branch 'main' into improve-template-helper
GiteaBot 6367856
Merge branch 'main' into improve-template-helper
GiteaBot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package templates | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"html" | ||
"html/template" | ||
|
||
activities_model "code.gitea.io/gitea/models/activities" | ||
"code.gitea.io/gitea/models/avatars" | ||
"code.gitea.io/gitea/models/organization" | ||
repo_model "code.gitea.io/gitea/models/repo" | ||
user_model "code.gitea.io/gitea/models/user" | ||
gitea_html "code.gitea.io/gitea/modules/html" | ||
"code.gitea.io/gitea/modules/setting" | ||
) | ||
|
||
// AvatarHTML creates the HTML for an avatar | ||
func AvatarHTML(src string, size int, class, name string) template.HTML { | ||
sizeStr := fmt.Sprintf(`%d`, size) | ||
|
||
if name == "" { | ||
name = "avatar" | ||
} | ||
|
||
return template.HTML(`<img class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`) | ||
} | ||
|
||
// Avatar renders user avatars. args: user, size (int), class (string) | ||
func Avatar(ctx context.Context, item interface{}, others ...interface{}) template.HTML { | ||
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...) | ||
|
||
switch t := item.(type) { | ||
case *user_model.User: | ||
src := t.AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor) | ||
if src != "" { | ||
return AvatarHTML(src, size, class, t.DisplayName()) | ||
} | ||
case *repo_model.Collaborator: | ||
src := t.AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor) | ||
if src != "" { | ||
return AvatarHTML(src, size, class, t.DisplayName()) | ||
} | ||
case *organization.Organization: | ||
src := t.AsUser().AvatarLinkWithSize(ctx, size*setting.Avatar.RenderedSizeFactor) | ||
if src != "" { | ||
return AvatarHTML(src, size, class, t.AsUser().DisplayName()) | ||
} | ||
} | ||
|
||
return template.HTML("") | ||
} | ||
|
||
// AvatarByAction renders user avatars from action. args: action, size (int), class (string) | ||
func AvatarByAction(ctx context.Context, action *activities_model.Action, others ...interface{}) template.HTML { | ||
action.LoadActUser(ctx) | ||
return Avatar(ctx, action.ActUser, others...) | ||
} | ||
|
||
// RepoAvatar renders repo avatars. args: repo, size(int), class (string) | ||
func RepoAvatar(repo *repo_model.Repository, others ...interface{}) template.HTML { | ||
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...) | ||
|
||
src := repo.RelAvatarLink() | ||
if src != "" { | ||
return AvatarHTML(src, size, class, repo.FullName()) | ||
} | ||
return template.HTML("") | ||
} | ||
|
||
// AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string) | ||
func AvatarByEmail(ctx context.Context, email, name string, others ...interface{}) template.HTML { | ||
size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, avatars.DefaultAvatarClass, others...) | ||
src := avatars.GenerateEmailAvatarFastLink(ctx, email, size*setting.Avatar.RenderedSizeFactor) | ||
|
||
if src != "" { | ||
return AvatarHTML(src, size, class, name) | ||
} | ||
|
||
return template.HTML("") | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package templates | ||
|
||
import ( | ||
"bytes" | ||
|
||
"code.gitea.io/gitea/modules/json" | ||
) | ||
|
||
type JsonUtils struct{} //nolint:revive | ||
silverwind marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
var jsonUtils = JsonUtils{} | ||
|
||
func NewJsonUtils() *JsonUtils { //nolint:revive | ||
return &jsonUtils | ||
} | ||
|
||
func (su *JsonUtils) EncodeToString(v any) string { | ||
out, err := json.Marshal(v) | ||
if err != nil { | ||
return "" | ||
} | ||
return string(out) | ||
} | ||
|
||
func (su *JsonUtils) PrettyIndent(s string) string { | ||
var out bytes.Buffer | ||
err := json.Indent(&out, []byte(s), "", " ") | ||
if err != nil { | ||
return "" | ||
} | ||
return out.String() | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package templates | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"html/template" | ||
"mime" | ||
"path/filepath" | ||
"strings" | ||
"time" | ||
|
||
activities_model "code.gitea.io/gitea/models/activities" | ||
repo_model "code.gitea.io/gitea/models/repo" | ||
"code.gitea.io/gitea/modules/git" | ||
giturl "code.gitea.io/gitea/modules/git/url" | ||
"code.gitea.io/gitea/modules/json" | ||
"code.gitea.io/gitea/modules/log" | ||
"code.gitea.io/gitea/modules/repository" | ||
"code.gitea.io/gitea/modules/svg" | ||
|
||
"github.com/editorconfig/editorconfig-core-go/v2" | ||
) | ||
|
||
func SortArrow(normSort, revSort, urlSort string, isDefault bool) template.HTML { | ||
// if needed | ||
if len(normSort) == 0 || len(urlSort) == 0 { | ||
return "" | ||
} | ||
|
||
if len(urlSort) == 0 && isDefault { | ||
wxiaoguang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// if sort is sorted as default add arrow tho this table header | ||
if isDefault { | ||
return svg.RenderHTML("octicon-triangle-down", 16) | ||
} | ||
} else { | ||
// if sort arg is in url test if it correlates with column header sort arguments | ||
// the direction of the arrow should indicate the "current sort order", up means ASC(normal), down means DESC(rev) | ||
if urlSort == normSort { | ||
// the table is sorted with this header normal | ||
return svg.RenderHTML("octicon-triangle-up", 16) | ||
} else if urlSort == revSort { | ||
// the table is sorted with this header reverse | ||
return svg.RenderHTML("octicon-triangle-down", 16) | ||
} | ||
} | ||
// the table is NOT sorted with this header | ||
return "" | ||
} | ||
|
||
// IsMultilineCommitMessage checks to see if a commit message contains multiple lines. | ||
func IsMultilineCommitMessage(msg string) bool { | ||
return strings.Count(strings.TrimSpace(msg), "\n") >= 1 | ||
} | ||
|
||
// Actioner describes an action | ||
type Actioner interface { | ||
GetOpType() activities_model.ActionType | ||
GetActUserName() string | ||
GetRepoUserName() string | ||
GetRepoName() string | ||
GetRepoPath() string | ||
GetRepoLink() string | ||
GetBranch() string | ||
GetContent() string | ||
GetCreate() time.Time | ||
GetIssueInfos() []string | ||
} | ||
|
||
// ActionIcon accepts an action operation type and returns an icon class name. | ||
func ActionIcon(opType activities_model.ActionType) string { | ||
switch opType { | ||
case activities_model.ActionCreateRepo, activities_model.ActionTransferRepo, activities_model.ActionRenameRepo: | ||
return "repo" | ||
case activities_model.ActionCommitRepo, activities_model.ActionPushTag, activities_model.ActionDeleteTag, activities_model.ActionDeleteBranch: | ||
return "git-commit" | ||
case activities_model.ActionCreateIssue: | ||
return "issue-opened" | ||
case activities_model.ActionCreatePullRequest: | ||
return "git-pull-request" | ||
case activities_model.ActionCommentIssue, activities_model.ActionCommentPull: | ||
return "comment-discussion" | ||
case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: | ||
return "git-merge" | ||
case activities_model.ActionCloseIssue, activities_model.ActionClosePullRequest: | ||
return "issue-closed" | ||
case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest: | ||
return "issue-reopened" | ||
case activities_model.ActionMirrorSyncPush, activities_model.ActionMirrorSyncCreate, activities_model.ActionMirrorSyncDelete: | ||
return "mirror" | ||
case activities_model.ActionApprovePullRequest: | ||
return "check" | ||
case activities_model.ActionRejectPullRequest: | ||
return "diff" | ||
case activities_model.ActionPublishRelease: | ||
return "tag" | ||
case activities_model.ActionPullReviewDismissed: | ||
return "x" | ||
default: | ||
return "question" | ||
} | ||
} | ||
|
||
// ActionContent2Commits converts action content to push commits | ||
func ActionContent2Commits(act Actioner) *repository.PushCommits { | ||
push := repository.NewPushCommits() | ||
|
||
if act == nil || act.GetContent() == "" { | ||
return push | ||
} | ||
|
||
if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil { | ||
log.Error("json.Unmarshal:\n%s\nERROR: %v", act.GetContent(), err) | ||
} | ||
|
||
if push.Len == 0 { | ||
push.Len = len(push.Commits) | ||
} | ||
|
||
return push | ||
} | ||
|
||
// DiffLineTypeToStr returns diff line type name | ||
func DiffLineTypeToStr(diffType int) string { | ||
switch diffType { | ||
case 2: | ||
return "add" | ||
case 3: | ||
return "del" | ||
case 4: | ||
return "tag" | ||
} | ||
return "same" | ||
} | ||
|
||
// MigrationIcon returns a SVG name matching the service an issue/comment was migrated from | ||
func MigrationIcon(hostname string) string { | ||
switch hostname { | ||
case "github.com": | ||
return "octicon-mark-github" | ||
default: | ||
return "gitea-git" | ||
} | ||
} | ||
|
||
type remoteAddress struct { | ||
Address string | ||
Username string | ||
Password string | ||
} | ||
|
||
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string, ignoreOriginalURL bool) remoteAddress { | ||
a := remoteAddress{} | ||
|
||
remoteURL := m.OriginalURL | ||
if ignoreOriginalURL || remoteURL == "" { | ||
var err error | ||
remoteURL, err = git.GetRemoteAddress(ctx, m.RepoPath(), remoteName) | ||
if err != nil { | ||
log.Error("GetRemoteURL %v", err) | ||
return a | ||
} | ||
} | ||
|
||
u, err := giturl.Parse(remoteURL) | ||
if err != nil { | ||
log.Error("giturl.Parse %v", err) | ||
return a | ||
} | ||
|
||
if u.Scheme != "ssh" && u.Scheme != "file" { | ||
if u.User != nil { | ||
a.Username = u.User.Username() | ||
a.Password, _ = u.User.Password() | ||
} | ||
u.User = nil | ||
} | ||
a.Address = u.String() | ||
|
||
return a | ||
} | ||
|
||
func FilenameIsImage(filename string) bool { | ||
mimeType := mime.TypeByExtension(filepath.Ext(filename)) | ||
return strings.HasPrefix(mimeType, "image/") | ||
} | ||
|
||
func TabSizeClass(ec interface{}, filename string) string { | ||
var ( | ||
value *editorconfig.Editorconfig | ||
ok bool | ||
) | ||
if ec != nil { | ||
if value, ok = ec.(*editorconfig.Editorconfig); !ok || value == nil { | ||
return "tab-size-8" | ||
} | ||
def, err := value.GetDefinitionForFilename(filename) | ||
if err != nil { | ||
log.Error("tab size class: getting definition for filename: %v", err) | ||
return "tab-size-8" | ||
} | ||
if def.TabWidth > 0 { | ||
return fmt.Sprintf("tab-size-%d", def.TabWidth) | ||
} | ||
} | ||
return "tab-size-8" | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.