mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-05 10:51:49 +09:00
Backport #39436 by @breken-ai The `org` render meta is lower-cased (`Repository.composeCommonMetas` sets `metas["org"] = strings.ToLower(repo.OwnerName)`), but `mentionProcessor` compares it with the org part of the mention exactly as typed, while the team part is lower-cased before its lookup. So in a repository of the org `MyOrg`, `@MyOrg/developers` stays plain text, although `ResolveIssueMentionsByVisibility` lower-cases the name and still notifies that team. This compares the org part case-insensitively and adds a render test for team mentions. The code is the same on `release/v1.27`, so it could be backported. ### Verification - `go test ./modules/markup/ -run TestRender_TeamMention -count=1`: the `@Org1/Developers` case renders as plain text on current main and as the team link with this change; `go test ./modules/markup/...` passes. - `golangci-lint run ./modules/markup/` (v2.13.2): 0 issues. ### AI assistance This contribution was prepared with AI assistance. The behavior, the metas and mention-resolution code paths, the patch and the test were reviewed manually. > Built by breken, your AI support engineer - breken.ai - this one's on us. Co-authored-by: breken <support@brekfuz.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
57 lines
1.7 KiB
Go
57 lines
1.7 KiB
Go
// Copyright 2024 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package markup
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"gitea.dev/modules/references"
|
|
"gitea.dev/modules/util"
|
|
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
func mentionProcessor(ctx *RenderContext, node *html.Node) {
|
|
start := 0
|
|
nodeStop := node.NextSibling
|
|
for node != nodeStop {
|
|
found, loc := references.FindFirstMentionBytes(util.UnsafeStringToBytes(node.Data[start:]))
|
|
if !found {
|
|
node = node.NextSibling
|
|
start = 0
|
|
continue
|
|
}
|
|
loc.Start += start
|
|
loc.End += start
|
|
mention := node.Data[loc.Start:loc.End]
|
|
orgLowerTeams, checkOrgTeams := ctx.RenderOptions.Metas["teams"] // in format ",team1,team2,...,team-n,", always lowercase
|
|
|
|
if checkOrgTeams && strings.Contains(mention, "/") {
|
|
mentionOrg, teamName, _ := strings.Cut(mention, "/")
|
|
orgName := mentionOrg[1:] // remove the '@' prefix
|
|
if strings.EqualFold(orgName, ctx.RenderOptions.Metas["org"]) && strings.Contains(orgLowerTeams, ","+strings.ToLower(teamName)+",") {
|
|
link := fmt.Sprintf("/:root/org/%s/teams/%s", url.PathEscape(orgName), url.PathEscape(teamName))
|
|
replaceContent(node, loc.Start, loc.End, createLink(ctx, link, mention, "" /*mention*/))
|
|
node = node.NextSibling.NextSibling
|
|
start = 0
|
|
continue
|
|
}
|
|
start = loc.End
|
|
continue
|
|
}
|
|
mentionedUsername := mention[1:]
|
|
|
|
if DefaultRenderHelperFuncs != nil && DefaultRenderHelperFuncs.IsUsernameMentionable(ctx, mentionedUsername) {
|
|
link := "/:root/" + url.PathEscape(mentionedUsername)
|
|
replaceContent(node, loc.Start, loc.End, createLink(ctx, link, mention, "" /*mention*/))
|
|
node = node.NextSibling.NextSibling
|
|
start = 0
|
|
} else {
|
|
start = loc.End
|
|
}
|
|
}
|
|
}
|