mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Refactor some Str2html code (#29397)
This PR touches the most interesting part of the "template refactoring".
1. Unclear variable type. Especially for "web/feed/convert.go":
sometimes it uses text, sometimes it uses HTML.
2. Assign text content to "RenderedContent" field, for example: `
project.RenderedContent = project.Description` in web/org/projects.go
3. Assign rendered content to text field, for example: `r.Note =
rendered content` in web/repo/release.go
4. (possible) Incorrectly calling `{{Str2html
.PackageDescriptor.Metadata.ReleaseNotes}}` in
package/content/nuget.tmpl, I guess the name Str2html misleads
developers to use it to "render string to html", but it only sanitizes.
if ReleaseNotes really contains HTML, then this is not a problem.
			
			
This commit is contained in:
		| @@ -8,6 +8,7 @@ package issues | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"html/template" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"unicode/utf8" | 	"unicode/utf8" | ||||||
|  |  | ||||||
| @@ -260,7 +261,7 @@ type Comment struct { | |||||||
| 	Line            int64 // - previous line / + proposed line | 	Line            int64 // - previous line / + proposed line | ||||||
| 	TreePath        string | 	TreePath        string | ||||||
| 	Content         string        `xorm:"LONGTEXT"` | 	Content         string        `xorm:"LONGTEXT"` | ||||||
| 	RenderedContent string `xorm:"-"` | 	RenderedContent template.HTML `xorm:"-"` | ||||||
|  |  | ||||||
| 	// Path represents the 4 lines of code cemented by this comment | 	// Path represents the 4 lines of code cemented by this comment | ||||||
| 	Patch       string `xorm:"-"` | 	Patch       string `xorm:"-"` | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ package issues | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"html/template" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 	"slices" | 	"slices" | ||||||
|  |  | ||||||
| @@ -105,7 +106,7 @@ type Issue struct { | |||||||
| 	OriginalAuthorID int64                  `xorm:"index"` | 	OriginalAuthorID int64                  `xorm:"index"` | ||||||
| 	Title            string                 `xorm:"name"` | 	Title            string                 `xorm:"name"` | ||||||
| 	Content          string                 `xorm:"LONGTEXT"` | 	Content          string                 `xorm:"LONGTEXT"` | ||||||
| 	RenderedContent  string                 `xorm:"-"` | 	RenderedContent  template.HTML          `xorm:"-"` | ||||||
| 	Labels           []*Label               `xorm:"-"` | 	Labels           []*Label               `xorm:"-"` | ||||||
| 	MilestoneID      int64                  `xorm:"INDEX"` | 	MilestoneID      int64                  `xorm:"INDEX"` | ||||||
| 	Milestone        *Milestone             `xorm:"-"` | 	Milestone        *Milestone             `xorm:"-"` | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ package issues | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"html/template" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/models/db" | 	"code.gitea.io/gitea/models/db" | ||||||
| @@ -48,7 +49,7 @@ type Milestone struct { | |||||||
| 	Repo            *repo_model.Repository `xorm:"-"` | 	Repo            *repo_model.Repository `xorm:"-"` | ||||||
| 	Name            string | 	Name            string | ||||||
| 	Content         string        `xorm:"TEXT"` | 	Content         string        `xorm:"TEXT"` | ||||||
| 	RenderedContent string `xorm:"-"` | 	RenderedContent template.HTML `xorm:"-"` | ||||||
| 	IsClosed        bool | 	IsClosed        bool | ||||||
| 	NumIssues       int | 	NumIssues       int | ||||||
| 	NumClosedIssues int | 	NumClosedIssues int | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ package project | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"html/template" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/models/db" | 	"code.gitea.io/gitea/models/db" | ||||||
| 	repo_model "code.gitea.io/gitea/models/repo" | 	repo_model "code.gitea.io/gitea/models/repo" | ||||||
| @@ -100,7 +101,7 @@ type Project struct { | |||||||
| 	CardType    CardType | 	CardType    CardType | ||||||
| 	Type        Type | 	Type        Type | ||||||
|  |  | ||||||
| 	RenderedContent string `xorm:"-"` | 	RenderedContent template.HTML `xorm:"-"` | ||||||
|  |  | ||||||
| 	CreatedUnix    timeutil.TimeStamp `xorm:"INDEX created"` | 	CreatedUnix    timeutil.TimeStamp `xorm:"INDEX created"` | ||||||
| 	UpdatedUnix    timeutil.TimeStamp `xorm:"INDEX updated"` | 	UpdatedUnix    timeutil.TimeStamp `xorm:"INDEX updated"` | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ package repo | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"html/template" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| @@ -80,7 +81,7 @@ type Release struct { | |||||||
| 	NumCommits       int64 | 	NumCommits       int64 | ||||||
| 	NumCommitsBehind int64              `xorm:"-"` | 	NumCommitsBehind int64              `xorm:"-"` | ||||||
| 	Note             string             `xorm:"TEXT"` | 	Note             string             `xorm:"TEXT"` | ||||||
| 	RenderedNote     string             `xorm:"-"` | 	RenderedNote     template.HTML      `xorm:"-"` | ||||||
| 	IsDraft          bool               `xorm:"NOT NULL DEFAULT false"` | 	IsDraft          bool               `xorm:"NOT NULL DEFAULT false"` | ||||||
| 	IsPrerelease     bool               `xorm:"NOT NULL DEFAULT false"` | 	IsPrerelease     bool               `xorm:"NOT NULL DEFAULT false"` | ||||||
| 	IsTag            bool               `xorm:"NOT NULL DEFAULT false"` // will be true only if the record is a tag and has no related releases | 	IsTag            bool               `xorm:"NOT NULL DEFAULT false"` // will be true only if the record is a tag and has no related releases | ||||||
|   | |||||||
| @@ -397,7 +397,7 @@ func TestRender_ShortLinks(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, input) | 		}, input) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) | 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) | ||||||
| 		buffer, err = markdown.RenderString(&markup.RenderContext{ | 		buffer, err = markdown.RenderString(&markup.RenderContext{ | ||||||
| 			Ctx: git.DefaultContext, | 			Ctx: git.DefaultContext, | ||||||
| 			Links: markup.Links{ | 			Links: markup.Links{ | ||||||
| @@ -407,7 +407,7 @@ func TestRender_ShortLinks(t *testing.T) { | |||||||
| 			IsWiki: true, | 			IsWiki: true, | ||||||
| 		}, input) | 		}, input) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(buffer)) | 		assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer))) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	mediatree := util.URLJoin(markup.TestRepoURL, "media", "master") | 	mediatree := util.URLJoin(markup.TestRepoURL, "media", "master") | ||||||
| @@ -510,7 +510,7 @@ func TestRender_RelativeImages(t *testing.T) { | |||||||
| 			Metas: localMetas, | 			Metas: localMetas, | ||||||
| 		}, input) | 		}, input) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) | 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) | ||||||
| 		buffer, err = markdown.RenderString(&markup.RenderContext{ | 		buffer, err = markdown.RenderString(&markup.RenderContext{ | ||||||
| 			Ctx: git.DefaultContext, | 			Ctx: git.DefaultContext, | ||||||
| 			Links: markup.Links{ | 			Links: markup.Links{ | ||||||
| @@ -520,7 +520,7 @@ func TestRender_RelativeImages(t *testing.T) { | |||||||
| 			IsWiki: true, | 			IsWiki: true, | ||||||
| 		}, input) | 		}, input) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(buffer)) | 		assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer))) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	rawwiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw") | 	rawwiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw") | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ package markdown | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"html/template" | ||||||
| 	"io" | 	"io" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| @@ -262,12 +263,12 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error | |||||||
| } | } | ||||||
|  |  | ||||||
| // RenderString renders Markdown string to HTML with all specific handling stuff and return string | // RenderString renders Markdown string to HTML with all specific handling stuff and return string | ||||||
| func RenderString(ctx *markup.RenderContext, content string) (string, error) { | func RenderString(ctx *markup.RenderContext, content string) (template.HTML, error) { | ||||||
| 	var buf strings.Builder | 	var buf strings.Builder | ||||||
| 	if err := Render(ctx, strings.NewReader(content), &buf); err != nil { | 	if err := Render(ctx, strings.NewReader(content), &buf); err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	return buf.String(), nil | 	return template.HTML(buf.String()), nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // RenderRaw renders Markdown to HTML without handling special links. | // RenderRaw renders Markdown to HTML without handling special links. | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ package markdown_test | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"html/template" | ||||||
| 	"os" | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
| @@ -56,7 +57,7 @@ func TestRender_StandardLinks(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, input) | 		}, input) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) | 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) | ||||||
|  |  | ||||||
| 		buffer, err = markdown.RenderString(&markup.RenderContext{ | 		buffer, err = markdown.RenderString(&markup.RenderContext{ | ||||||
| 			Ctx: git.DefaultContext, | 			Ctx: git.DefaultContext, | ||||||
| @@ -66,7 +67,7 @@ func TestRender_StandardLinks(t *testing.T) { | |||||||
| 			IsWiki: true, | 			IsWiki: true, | ||||||
| 		}, input) | 		}, input) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(buffer)) | 		assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer))) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	googleRendered := `<p><a href="https://google.com/" rel="nofollow">https://google.com/</a></p>` | 	googleRendered := `<p><a href="https://google.com/" rel="nofollow">https://google.com/</a></p>` | ||||||
| @@ -90,7 +91,7 @@ func TestRender_Images(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, input) | 		}, input) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) | 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	url := "../../.images/src/02/train.jpg" | 	url := "../../.images/src/02/train.jpg" | ||||||
| @@ -299,7 +300,7 @@ func TestTotal_RenderWiki(t *testing.T) { | |||||||
| 			IsWiki: true, | 			IsWiki: true, | ||||||
| 		}, sameCases[i]) | 		}, sameCases[i]) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, answers[i], line) | 		assert.Equal(t, template.HTML(answers[i]), line) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testCases := []string{ | 	testCases := []string{ | ||||||
| @@ -324,7 +325,7 @@ func TestTotal_RenderWiki(t *testing.T) { | |||||||
| 			IsWiki: true, | 			IsWiki: true, | ||||||
| 		}, testCases[i]) | 		}, testCases[i]) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, testCases[i+1], line) | 		assert.Equal(t, template.HTML(testCases[i+1]), line) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -343,7 +344,7 @@ func TestTotal_RenderString(t *testing.T) { | |||||||
| 			Metas: localMetas, | 			Metas: localMetas, | ||||||
| 		}, sameCases[i]) | 		}, sameCases[i]) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, answers[i], line) | 		assert.Equal(t, template.HTML(answers[i]), line) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testCases := []string{} | 	testCases := []string{} | ||||||
| @@ -356,7 +357,7 @@ func TestTotal_RenderString(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, testCases[i]) | 		}, testCases[i]) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Equal(t, testCases[i+1], line) | 		assert.Equal(t, template.HTML(testCases[i+1]), line) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -423,7 +424,7 @@ func TestRenderEmojiInLinks_Issue12331(t *testing.T) { | |||||||
| ` | ` | ||||||
| 	res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase) | 	res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, expected, res) | 	assert.Equal(t, template.HTML(expected), res) | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestColorPreview(t *testing.T) { | func TestColorPreview(t *testing.T) { | ||||||
| @@ -457,7 +458,7 @@ func TestColorPreview(t *testing.T) { | |||||||
| 	for _, test := range positiveTests { | 	for _, test := range positiveTests { | ||||||
| 		res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) | 		res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) | ||||||
| 		assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) | 		assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) | ||||||
| 		assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase) | 		assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -524,7 +525,7 @@ func TestMathBlock(t *testing.T) { | |||||||
| 	for _, test := range testcases { | 	for _, test := range testcases { | ||||||
| 		res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) | 		res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) | ||||||
| 		assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) | 		assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) | ||||||
| 		assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase) | 		assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -562,12 +563,12 @@ foo: bar | |||||||
| 	for _, test := range testcases { | 	for _, test := range testcases { | ||||||
| 		res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) | 		res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) | ||||||
| 		assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) | 		assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) | ||||||
| 		assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase) | 		assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestRenderLinks(t *testing.T) { | func TestRenderLinks(t *testing.T) { | ||||||
| 	input := `  space @mention-user   | 	input := `  space @mention-user${SPACE}${SPACE} | ||||||
| /just/a/path.bin | /just/a/path.bin | ||||||
| https://example.com/file.bin | https://example.com/file.bin | ||||||
| [local link](file.bin) | [local link](file.bin) | ||||||
| @@ -588,8 +589,9 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit | |||||||
| mail@domain.com | mail@domain.com | ||||||
| @mention-user test | @mention-user test | ||||||
| #123 | #123 | ||||||
|   space   |   space${SPACE}${SPACE} | ||||||
| ` | ` | ||||||
|  | 	input = strings.ReplaceAll(input, "${SPACE}", " ") // replace ${SPACE} with " ", to avoid some editor's auto-trimming | ||||||
| 	cases := []struct { | 	cases := []struct { | ||||||
| 		Links    markup.Links | 		Links    markup.Links | ||||||
| 		IsWiki   bool | 		IsWiki   bool | ||||||
| @@ -952,6 +954,6 @@ space</p> | |||||||
| 	for i, c := range cases { | 	for i, c := range cases { | ||||||
| 		result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background(), Links: c.Links, IsWiki: c.IsWiki}, input) | 		result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background(), Links: c.Links, IsWiki: c.IsWiki}, input) | ||||||
| 		assert.NoError(t, err, "Unexpected error in testcase: %v", i) | 		assert.NoError(t, err, "Unexpected error in testcase: %v", i) | ||||||
| 		assert.Equal(t, c.Expected, result, "Unexpected result in testcase %v", i) | 		assert.Equal(t, template.HTML(c.Expected), result, "Unexpected result in testcase %v", i) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -208,7 +208,7 @@ func RenderMarkdownToHtml(ctx context.Context, input string) template.HTML { //n | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("RenderString: %v", err) | 		log.Error("RenderString: %v", err) | ||||||
| 	} | 	} | ||||||
| 	return template.HTML(output) | 	return output | ||||||
| } | } | ||||||
|  |  | ||||||
| func RenderLabels(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML { | func RenderLabels(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML { | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ | |||||||
| package templates | package templates | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"html/template" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| @@ -17,6 +19,19 @@ func NewStringUtils() *StringUtils { | |||||||
| 	return &stringUtils | 	return &stringUtils | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (su *StringUtils) ToString(v any) string { | ||||||
|  | 	switch v := v.(type) { | ||||||
|  | 	case string: | ||||||
|  | 		return v | ||||||
|  | 	case template.HTML: | ||||||
|  | 		return string(v) | ||||||
|  | 	case fmt.Stringer: | ||||||
|  | 		return v.String() | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Sprint(v) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (su *StringUtils) HasPrefix(s, prefix string) bool { | func (su *StringUtils) HasPrefix(s, prefix string) bool { | ||||||
| 	return strings.HasPrefix(s, prefix) | 	return strings.HasPrefix(s, prefix) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -50,7 +50,7 @@ func toReleaseLink(ctx *context.Context, act *activities_model.Action) string { | |||||||
|  |  | ||||||
| // renderMarkdown creates a minimal markdown render context from an action. | // renderMarkdown creates a minimal markdown render context from an action. | ||||||
| // If rendering fails, the original markdown text is returned | // If rendering fails, the original markdown text is returned | ||||||
| func renderMarkdown(ctx *context.Context, act *activities_model.Action, content string) string { | func renderMarkdown(ctx *context.Context, act *activities_model.Action, content string) template.HTML { | ||||||
| 	markdownCtx := &markup.RenderContext{ | 	markdownCtx := &markup.RenderContext{ | ||||||
| 		Ctx: ctx, | 		Ctx: ctx, | ||||||
| 		Links: markup.Links{ | 		Links: markup.Links{ | ||||||
| @@ -64,7 +64,7 @@ func renderMarkdown(ctx *context.Context, act *activities_model.Action, content | |||||||
| 	} | 	} | ||||||
| 	markdown, err := markdown.RenderString(markdownCtx, content) | 	markdown, err := markdown.RenderString(markdownCtx, content) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return content | 		return templates.Str2html(content) // old code did so: use Str2html to render in tmpl | ||||||
| 	} | 	} | ||||||
| 	return markdown | 	return markdown | ||||||
| } | } | ||||||
| @@ -74,7 +74,11 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio | |||||||
| 	for _, act := range actions { | 	for _, act := range actions { | ||||||
| 		act.LoadActUser(ctx) | 		act.LoadActUser(ctx) | ||||||
|  |  | ||||||
| 		var content, desc, title string | 		// TODO: the code seems quite strange (maybe not right) | ||||||
|  | 		// sometimes it uses text content but sometimes it uses HTML content | ||||||
|  | 		// it should clearly defines which kind of content it should use for the feed items: plan text or rich HTML | ||||||
|  | 		var title, desc string | ||||||
|  | 		var content template.HTML | ||||||
|  |  | ||||||
| 		link := &feeds.Link{Href: act.GetCommentHTMLURL(ctx)} | 		link := &feeds.Link{Href: act.GetCommentHTMLURL(ctx)} | ||||||
|  |  | ||||||
| @@ -228,7 +232,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio | |||||||
| 				desc = act.GetIssueTitle(ctx) | 				desc = act.GetIssueTitle(ctx) | ||||||
| 				comment := act.GetIssueInfos()[1] | 				comment := act.GetIssueInfos()[1] | ||||||
| 				if len(comment) != 0 { | 				if len(comment) != 0 { | ||||||
| 					desc += "\n\n" + renderMarkdown(ctx, act, comment) | 					desc += "\n\n" + string(renderMarkdown(ctx, act, comment)) | ||||||
| 				} | 				} | ||||||
| 			case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: | 			case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: | ||||||
| 				desc = act.GetIssueInfos()[1] | 				desc = act.GetIssueInfos()[1] | ||||||
| @@ -239,7 +243,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if len(content) == 0 { | 		if len(content) == 0 { | ||||||
| 			content = desc | 			content = templates.Str2html(desc) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		items = append(items, &feeds.Item{ | 		items = append(items, &feeds.Item{ | ||||||
| @@ -253,7 +257,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio | |||||||
| 			}, | 			}, | ||||||
| 			Id:      fmt.Sprintf("%v: %v", strconv.FormatInt(act.ID, 10), link.Href), | 			Id:      fmt.Sprintf("%v: %v", strconv.FormatInt(act.ID, 10), link.Href), | ||||||
| 			Created: act.CreatedUnix.AsTime(), | 			Created: act.CreatedUnix.AsTime(), | ||||||
| 			Content: content, | 			Content: string(content), | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| 	return items, err | 	return items, err | ||||||
| @@ -282,7 +286,8 @@ func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, i | |||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		var title, content string | 		var title string | ||||||
|  | 		var content template.HTML | ||||||
|  |  | ||||||
| 		if rel.IsTag { | 		if rel.IsTag { | ||||||
| 			title = rel.TagName | 			title = rel.TagName | ||||||
| @@ -311,7 +316,7 @@ func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, i | |||||||
| 				Email: rel.Publisher.GetEmail(), | 				Email: rel.Publisher.GetEmail(), | ||||||
| 			}, | 			}, | ||||||
| 			Id:      fmt.Sprintf("%v: %v", strconv.FormatInt(rel.ID, 10), link.Href), | 			Id:      fmt.Sprintf("%v: %v", strconv.FormatInt(rel.ID, 10), link.Href), | ||||||
| 			Content: content, | 			Content: string(content), | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ func showUserFeed(ctx *context.Context, formatType string) { | |||||||
| 	feed := &feeds.Feed{ | 	feed := &feeds.Feed{ | ||||||
| 		Title:       ctx.Locale.TrString("home.feed_of", ctx.ContextUser.DisplayName()), | 		Title:       ctx.Locale.TrString("home.feed_of", ctx.ContextUser.DisplayName()), | ||||||
| 		Link:        &feeds.Link{Href: ctx.ContextUser.HTMLURL()}, | 		Link:        &feeds.Link{Href: ctx.ContextUser.HTMLURL()}, | ||||||
| 		Description: ctxUserDescription, | 		Description: string(ctxUserDescription), | ||||||
| 		Created:     time.Now(), | 		Created:     time.Now(), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| 	"code.gitea.io/gitea/modules/json" | 	"code.gitea.io/gitea/modules/json" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
|  | 	"code.gitea.io/gitea/modules/templates" | ||||||
| 	"code.gitea.io/gitea/modules/util" | 	"code.gitea.io/gitea/modules/util" | ||||||
| 	"code.gitea.io/gitea/modules/web" | 	"code.gitea.io/gitea/modules/web" | ||||||
| 	shared_user "code.gitea.io/gitea/routers/web/shared/user" | 	shared_user "code.gitea.io/gitea/routers/web/shared/user" | ||||||
| @@ -104,7 +105,7 @@ func Projects(ctx *context.Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, project := range projects { | 	for _, project := range projects { | ||||||
| 		project.RenderedContent = project.Description | 		project.RenderedContent = templates.Str2html(project.Description) // FIXME: is it right? why not render? | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	err = shared_user.LoadHeaderCount(ctx) | 	err = shared_user.LoadHeaderCount(ctx) | ||||||
| @@ -395,7 +396,7 @@ func ViewProject(ctx *context.Context) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	project.RenderedContent = project.Description | 	project.RenderedContent = templates.Str2html(project.Description) // FIXME: is it right? why not render? | ||||||
| 	ctx.Data["LinkedPRs"] = linkedPrsMap | 	ctx.Data["LinkedPRs"] = linkedPrsMap | ||||||
| 	ctx.Data["PageIsViewProjects"] = true | 	ctx.Data["PageIsViewProjects"] = true | ||||||
| 	ctx.Data["CanWriteProjects"] = canWriteProjects(ctx) | 	ctx.Data["CanWriteProjects"] = canWriteProjects(ctx) | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ import ( | |||||||
| 	repo_module "code.gitea.io/gitea/modules/repository" | 	repo_module "code.gitea.io/gitea/modules/repository" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/modules/templates" | ||||||
| 	"code.gitea.io/gitea/modules/templates/vars" | 	"code.gitea.io/gitea/modules/templates/vars" | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
| 	"code.gitea.io/gitea/modules/util" | 	"code.gitea.io/gitea/modules/util" | ||||||
| @@ -1760,7 +1761,7 @@ func ViewIssue(ctx *context.Context) { | |||||||
| 				// so "|" is used as delimeter to mark the new format | 				// so "|" is used as delimeter to mark the new format | ||||||
| 				if comment.Content[0] != '|' { | 				if comment.Content[0] != '|' { | ||||||
| 					// handle old time comments that have formatted text stored | 					// handle old time comments that have formatted text stored | ||||||
| 					comment.RenderedContent = comment.Content | 					comment.RenderedContent = templates.Str2html(comment.Content) | ||||||
| 					comment.Content = "" | 					comment.Content = "" | ||||||
| 				} else { | 				} else { | ||||||
| 					// else it's just a duration in seconds to pass on to the frontend | 					// else it's just a duration in seconds to pass on to the frontend | ||||||
|   | |||||||
| @@ -113,7 +113,7 @@ func getReleaseInfos(ctx *context.Context, opts *repo_model.FindReleasesOptions) | |||||||
| 			cacheUsers[r.PublisherID] = r.Publisher | 			cacheUsers[r.PublisherID] = r.Publisher | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		r.Note, err = markdown.RenderString(&markup.RenderContext{ | 		r.RenderedNote, err = markdown.RenderString(&markup.RenderContext{ | ||||||
| 			Links: markup.Links{ | 			Links: markup.Links{ | ||||||
| 				Base: ctx.Repo.RepoLink, | 				Base: ctx.Repo.RepoLink, | ||||||
| 			}, | 			}, | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ | |||||||
| 		{{.locale.Tr "mail.release.note"}}<br> | 		{{.locale.Tr "mail.release.note"}}<br> | ||||||
| 		{{- if eq .Release.RenderedNote ""}} | 		{{- if eq .Release.RenderedNote ""}} | ||||||
| 		{{else}} | 		{{else}} | ||||||
| 			{{.Release.RenderedNote | Str2html}} | 			{{.Release.RenderedNote}} | ||||||
| 		{{end -}} | 		{{end -}} | ||||||
| 	</p> | 	</p> | ||||||
| 	<br><br> | 	<br><br> | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ | |||||||
| 				{{end}} | 				{{end}} | ||||||
| 			</span> | 			</span> | ||||||
| 		</div> | 		</div> | ||||||
| 		{{if .RenderedDescription}}<div class="render-content markup">{{.RenderedDescription | Str2html}}</div>{{end}} | 		{{if .RenderedDescription}}<div class="render-content markup">{{.RenderedDescription}}</div>{{end}} | ||||||
| 		<div class="text light meta gt-mt-2"> | 		<div class="text light meta gt-mt-2"> | ||||||
| 			{{if .Org.Location}}<div class="flex-text-block">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>{{end}} | 			{{if .Org.Location}}<div class="flex-text-block">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>{{end}} | ||||||
| 			{{if .Org.Website}}<div class="flex-text-block">{{svg "octicon-link"}} <a class="muted" target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}} | 			{{if .Org.Website}}<div class="flex-text-block">{{svg "octicon-link"}} <a class="muted" target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}} | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
| 		<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 | Str2html}}</div> | 					<div id="readme_profile" class="markup">{{.ProfileReadme}}</div> | ||||||
| 				{{end}} | 				{{end}} | ||||||
| 				{{template "explore/repo_search" .}} | 				{{template "explore/repo_search" .}} | ||||||
| 				{{template "explore/repo_list" .}} | 				{{template "explore/repo_list" .}} | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
| 		<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4> | 		<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4> | ||||||
| 		<div class="ui attached segment"> | 		<div class="ui attached segment"> | ||||||
| 			{{if .PackageDescriptor.Metadata.Description}}{{.PackageDescriptor.Metadata.Description}}{{end}} | 			{{if .PackageDescriptor.Metadata.Description}}{{.PackageDescriptor.Metadata.Description}}{{end}} | ||||||
| 			{{if .PackageDescriptor.Metadata.ReleaseNotes}}{{Str2html .PackageDescriptor.Metadata.ReleaseNotes}}{{end}} | 			{{if .PackageDescriptor.Metadata.ReleaseNotes}}{{.PackageDescriptor.Metadata.ReleaseNotes}}{{end}} | ||||||
| 		</div> | 		</div> | ||||||
| 	{{end}} | 	{{end}} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -75,7 +75,7 @@ | |||||||
| 			</div> | 			</div> | ||||||
| 			{{if .Description}} | 			{{if .Description}} | ||||||
| 			<div class="content"> | 			<div class="content"> | ||||||
| 				{{.RenderedContent|Str2html}} | 				{{.RenderedContent}} | ||||||
| 			</div> | 			</div> | ||||||
| 			{{end}} | 			{{end}} | ||||||
| 		</li> | 		</li> | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ | |||||||
| 		{{end}} | 		{{end}} | ||||||
| 	</div> | 	</div> | ||||||
|  |  | ||||||
| 	<div class="content">{{$.Project.RenderedContent|Str2html}}</div> | 	<div class="content">{{$.Project.RenderedContent}}</div> | ||||||
|  |  | ||||||
| 	<div class="divider"></div> | 	<div class="divider"></div> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -55,7 +55,7 @@ | |||||||
| 		<div class="ui attached segment comment-body"> | 		<div class="ui attached segment comment-body"> | ||||||
| 			<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | 			<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | ||||||
| 			{{if .RenderedContent}} | 			{{if .RenderedContent}} | ||||||
| 				{{.RenderedContent|Str2html}} | 				{{.RenderedContent}} | ||||||
| 			{{else}} | 			{{else}} | ||||||
| 				<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | 				<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | ||||||
| 			{{end}} | 			{{end}} | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ | |||||||
| 		</div> | 		</div> | ||||||
| 		{{if .Milestone.RenderedContent}} | 		{{if .Milestone.RenderedContent}} | ||||||
| 		<div class="markup content gt-mb-4"> | 		<div class="markup content gt-mb-4"> | ||||||
| 				{{.Milestone.RenderedContent|Str2html}} | 				{{.Milestone.RenderedContent}} | ||||||
| 		</div> | 		</div> | ||||||
| 		{{end}} | 		{{end}} | ||||||
| 		<div class="gt-df gt-fc gt-gap-3"> | 		<div class="gt-df gt-fc gt-gap-3"> | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ | |||||||
| 					</div> | 					</div> | ||||||
| 					{{if .Content}} | 					{{if .Content}} | ||||||
| 						<div class="markup content"> | 						<div class="markup content"> | ||||||
| 							{{.RenderedContent|Str2html}} | 							{{.RenderedContent}} | ||||||
| 						</div> | 						</div> | ||||||
| 					{{end}} | 					{{end}} | ||||||
| 				</li> | 				</li> | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ | |||||||
| 					<div class="ui attached segment comment-body" role="article"> | 					<div class="ui attached segment comment-body" role="article"> | ||||||
| 						<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission $.IsIssuePoster}}data-can-edit="true"{{end}}> | 						<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission $.IsIssuePoster}}data-can-edit="true"{{end}}> | ||||||
| 							{{if .Issue.RenderedContent}} | 							{{if .Issue.RenderedContent}} | ||||||
| 								{{.Issue.RenderedContent|Str2html}} | 								{{.Issue.RenderedContent}} | ||||||
| 							{{else}} | 							{{else}} | ||||||
| 								<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | 								<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | ||||||
| 							{{end}} | 							{{end}} | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
| 			<div class="gt-f1 gt-p-3"> | 			<div class="gt-f1 gt-p-3"> | ||||||
| 				<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title="{{ctx.Locale.Tr "repo.issues.attachment.open_tab" .Name}}"> | 				<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title="{{ctx.Locale.Tr "repo.issues.attachment.open_tab" .Name}}"> | ||||||
| 					{{if FilenameIsImage .Name}} | 					{{if FilenameIsImage .Name}} | ||||||
| 						{{if not (StringUtils.Contains $.Content .UUID)}} | 						{{if not (StringUtils.Contains (StringUtils.ToString $.Content) .UUID)}} | ||||||
| 							{{$hasThumbnails = true}} | 							{{$hasThumbnails = true}} | ||||||
| 						{{end}} | 						{{end}} | ||||||
| 						{{svg "octicon-file"}} | 						{{svg "octicon-file"}} | ||||||
| @@ -29,7 +29,7 @@ | |||||||
| 		<div class="ui small thumbnails"> | 		<div class="ui small thumbnails"> | ||||||
| 			{{- range .Attachments -}} | 			{{- range .Attachments -}} | ||||||
| 				{{if FilenameIsImage .Name}} | 				{{if FilenameIsImage .Name}} | ||||||
| 					{{if not (StringUtils.Contains $.Content .UUID)}} | 					{{if not (StringUtils.Contains (StringUtils.ToString $.Content) .UUID)}} | ||||||
| 					<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}"> | 					<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}"> | ||||||
| 						<img alt="{{.Name}}" src="{{.DownloadURL}}" title="{{ctx.Locale.Tr "repo.issues.attachment.open_tab" .Name}}"> | 						<img alt="{{.Name}}" src="{{.DownloadURL}}" title="{{ctx.Locale.Tr "repo.issues.attachment.open_tab" .Name}}"> | ||||||
| 					</a> | 					</a> | ||||||
|   | |||||||
| @@ -61,7 +61,7 @@ | |||||||
| 					<div class="ui attached segment comment-body" role="article"> | 					<div class="ui attached segment comment-body" role="article"> | ||||||
| 						<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | 						<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | ||||||
| 							{{if .RenderedContent}} | 							{{if .RenderedContent}} | ||||||
| 								{{.RenderedContent|Str2html}} | 								{{.RenderedContent}} | ||||||
| 							{{else}} | 							{{else}} | ||||||
| 								<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | 								<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| @@ -432,7 +432,7 @@ | |||||||
| 						<div class="ui attached segment comment-body"> | 						<div class="ui attached segment comment-body"> | ||||||
| 							<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | 							<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | ||||||
| 								{{if .RenderedContent}} | 								{{if .RenderedContent}} | ||||||
| 									{{.RenderedContent|Str2html}} | 									{{.RenderedContent}} | ||||||
| 								{{else}} | 								{{else}} | ||||||
| 									<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | 									<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | ||||||
| 								{{end}} | 								{{end}} | ||||||
| @@ -631,7 +631,7 @@ | |||||||
| 							<div class="ui attached segment"> | 							<div class="ui attached segment"> | ||||||
| 								<div class="render-content markup"> | 								<div class="render-content markup"> | ||||||
| 									{{if .RenderedContent}} | 									{{if .RenderedContent}} | ||||||
| 										{{.RenderedContent|Str2html}} | 										{{.RenderedContent}} | ||||||
| 									{{else}} | 									{{else}} | ||||||
| 										<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | 										<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | ||||||
| 									{{end}} | 									{{end}} | ||||||
|   | |||||||
| @@ -87,7 +87,7 @@ | |||||||
| 						<div class="text comment-content"> | 						<div class="text comment-content"> | ||||||
| 							<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | 							<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> | ||||||
| 							{{if .RenderedContent}} | 							{{if .RenderedContent}} | ||||||
| 								{{.RenderedContent|Str2html}} | 								{{.RenderedContent}} | ||||||
| 							{{else}} | 							{{else}} | ||||||
| 								<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | 								<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span> | ||||||
| 							{{end}} | 							{{end}} | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ | |||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</p> | 						</p> | ||||||
| 						<div class="markup desc"> | 						<div class="markup desc"> | ||||||
| 							{{Str2html $release.Note}} | 							{{$release.RenderedNote}} | ||||||
| 						</div> | 						</div> | ||||||
| 						<div class="divider"></div> | 						<div class="divider"></div> | ||||||
| 						<details class="download" {{if eq $idx 0}}open{{end}}> | 						<details class="download" {{if eq $idx 0}}open{{end}}> | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ | |||||||
| 			{{end}} | 			{{end}} | ||||||
| 			{{if $.RenderedDescription}} | 			{{if $.RenderedDescription}} | ||||||
| 				<li> | 				<li> | ||||||
| 					<div class="render-content markup">{{$.RenderedDescription|Str2html}}</div> | 					<div class="render-content markup">{{$.RenderedDescription}}</div> | ||||||
| 				</li> | 				</li> | ||||||
| 			{{end}} | 			{{end}} | ||||||
| 			{{range .OpenIDs}} | 			{{range .OpenIDs}} | ||||||
|   | |||||||
| @@ -141,7 +141,7 @@ | |||||||
| 							</div> | 							</div> | ||||||
| 							{{if .Content}} | 							{{if .Content}} | ||||||
| 								<div class="markup content"> | 								<div class="markup content"> | ||||||
| 									{{.RenderedContent|Str2html}} | 									{{.RenderedContent}} | ||||||
| 								</div> | 								</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| 						</li> | 						</li> | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ | |||||||
| 				{{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 | Str2html}}</div> | 					<div id="readme_profile" class="markup">{{.ProfileReadme}}</div> | ||||||
| 				{{else}} | 				{{else}} | ||||||
| 					{{template "explore/repo_search" .}} | 					{{template "explore/repo_search" .}} | ||||||
| 					{{template "explore/repo_list" .}} | 					{{template "explore/repo_list" .}} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 wxiaoguang
					wxiaoguang