diff --git a/modules/markup/sanitizer_default.go b/modules/markup/sanitizer_default.go
index 9288be3b280a9..0fbf0f0b24c08 100644
--- a/modules/markup/sanitizer_default.go
+++ b/modules/markup/sanitizer_default.go
@@ -4,6 +4,7 @@
package markup
import (
+ "html/template"
"io"
"net/url"
"regexp"
@@ -92,9 +93,9 @@ func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy {
return policy
}
-// Sanitize takes a string that contains a HTML fragment or document and applies policy whitelist.
-func Sanitize(s string) string {
- return GetDefaultSanitizer().defaultPolicy.Sanitize(s)
+// Sanitize use default sanitizer policy to sanitize a string
+func Sanitize(s string) template.HTML {
+ return template.HTML(GetDefaultSanitizer().defaultPolicy.Sanitize(s))
}
// SanitizeReader sanitizes a Reader
diff --git a/modules/markup/sanitizer_default_test.go b/modules/markup/sanitizer_default_test.go
index 5282916944dc6..e5ba018e1be15 100644
--- a/modules/markup/sanitizer_default_test.go
+++ b/modules/markup/sanitizer_default_test.go
@@ -69,6 +69,6 @@ func TestSanitizer(t *testing.T) {
}
for i := 0; i < len(testCases); i += 2 {
- assert.Equal(t, testCases[i+1], Sanitize(testCases[i]))
+ assert.Equal(t, testCases[i+1], string(Sanitize(testCases[i])))
}
}
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index d55d4f87c5f87..052f9c47abbd3 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -176,9 +176,9 @@ func safeHTML(s any) template.HTML {
panic(fmt.Sprintf("unexpected type %T", s))
}
-// SanitizeHTML sanitizes the input by pre-defined markdown rules
+// SanitizeHTML sanitizes the input by default sanitization rules.
func SanitizeHTML(s string) template.HTML {
- return template.HTML(markup.Sanitize(s))
+ return markup.Sanitize(s)
}
func htmlEscape(s any) template.HTML {
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index a1e10c380d024..69858c969254a 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -7,6 +7,7 @@ package repo
import (
"bytes"
gocontext "context"
+ "html/template"
"io"
"net/http"
"net/url"
@@ -61,9 +62,9 @@ func MustEnableWiki(ctx *context.Context) {
return
}
- unit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalWiki)
+ repoUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalWiki)
if err == nil {
- ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
+ ctx.Redirect(repoUnit.ExternalWikiConfig().ExternalWikiURL)
return
}
}
@@ -95,7 +96,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
}
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
- wikiGitRepo, errGitRepo := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
+ wikiGitRepo, errGitRepo := gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository.WikiStorageRepo())
if errGitRepo != nil {
ctx.ServerError("OpenRepository", errGitRepo)
return nil, nil, errGitRepo
@@ -178,23 +179,17 @@ func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_
}
func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
- wikiRepo, commit, err := findWikiRepoCommit(ctx)
+ wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
if !git.IsErrNotExist(err) {
ctx.ServerError("GetBranchCommit", err)
}
return nil, nil
}
- // Get page list.
+ // get the wiki pages list.
entries, err := commit.ListEntries()
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
ctx.ServerError("ListEntries", err)
return nil, nil
}
@@ -208,9 +203,6 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
if repo_model.IsErrWikiInvalidFileName(err) {
continue
}
- if wikiRepo != nil {
- wikiRepo.Close()
- }
ctx.ServerError("WikiFilenameToName", err)
return nil, nil
} else if wikiName == "_Sidebar" || wikiName == "_Footer" {
@@ -249,58 +241,26 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
ctx.Redirect(util.URLJoin(ctx.Repo.RepoLink, "wiki/raw", string(pageName)))
}
if entry == nil || ctx.Written() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
return nil, nil
}
- // get filecontent
+ // get page content
data := wikiContentsByEntry(ctx, entry)
if ctx.Written() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
return nil, nil
}
- var sidebarContent []byte
- if !isSideBar {
- sidebarContent, _, _, _ = wikiContentsByName(ctx, commit, "_Sidebar")
- if ctx.Written() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
- return nil, nil
- }
- } else {
- sidebarContent = data
- }
-
- var footerContent []byte
- if !isFooter {
- footerContent, _, _, _ = wikiContentsByName(ctx, commit, "_Footer")
- if ctx.Written() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
- return nil, nil
- }
- } else {
- footerContent = data
- }
-
rctx := renderhelper.NewRenderContextRepoWiki(ctx, ctx.Repo.Repository)
- buf := &strings.Builder{}
- renderFn := func(data []byte) (escaped *charset.EscapeStatus, output string, err error) {
+ renderFn := func(data []byte) (escaped *charset.EscapeStatus, output template.HTML, err error) {
+ buf := &strings.Builder{}
markupRd, markupWr := io.Pipe()
defer markupWr.Close()
done := make(chan struct{})
go func() {
// We allow NBSP here this is rendered
escaped, _ = charset.EscapeControlReader(markupRd, buf, ctx.Locale, charset.RuneNBSP)
- output = buf.String()
+ output = template.HTML(buf.String())
buf.Reset()
close(done)
}()
@@ -311,75 +271,61 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
return escaped, output, err
}
- ctx.Data["EscapeStatus"], ctx.Data["content"], err = renderFn(data)
+ ctx.Data["EscapeStatus"], ctx.Data["WikiContentHTML"], err = renderFn(data)
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
ctx.ServerError("Render", err)
return nil, nil
}
if rctx.SidebarTocNode != nil {
- sb := &strings.Builder{}
- err = markdown.SpecializedMarkdown(rctx).Renderer().Render(sb, nil, rctx.SidebarTocNode)
- if err != nil {
+ sb := strings.Builder{}
+ if err = markdown.SpecializedMarkdown(rctx).Renderer().Render(&sb, nil, rctx.SidebarTocNode); err != nil {
log.Error("Failed to render wiki sidebar TOC: %v", err)
- } else {
- ctx.Data["sidebarTocContent"] = sb.String()
}
+ ctx.Data["WikiSidebarTocHTML"] = templates.SanitizeHTML(sb.String())
}
if !isSideBar {
- buf.Reset()
- ctx.Data["sidebarEscapeStatus"], ctx.Data["sidebarContent"], err = renderFn(sidebarContent)
+ sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
+ if ctx.Written() {
+ return nil, nil
+ }
+ ctx.Data["WikiSidebarEscapeStatus"], ctx.Data["WikiSidebarHTML"], err = renderFn(sidebarContent)
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
ctx.ServerError("Render", err)
return nil, nil
}
- ctx.Data["sidebarPresent"] = sidebarContent != nil
- } else {
- ctx.Data["sidebarPresent"] = false
}
if !isFooter {
- buf.Reset()
- ctx.Data["footerEscapeStatus"], ctx.Data["footerContent"], err = renderFn(footerContent)
+ footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
+ if ctx.Written() {
+ return nil, nil
+ }
+ ctx.Data["WikiFooterEscapeStatus"], ctx.Data["WikiFooterHTML"], err = renderFn(footerContent)
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
ctx.ServerError("Render", err)
return nil, nil
}
- ctx.Data["footerPresent"] = footerContent != nil
- } else {
- ctx.Data["footerPresent"] = false
}
// get commit count - wiki revisions
- commitsCount, _ := wikiRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
+ commitsCount, _ := wikiGitRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
ctx.Data["CommitCount"] = commitsCount
- return wikiRepo, entry
+ return wikiGitRepo, entry
}
func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
- wikiRepo, commit, err := findWikiRepoCommit(ctx)
+ wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
if !git.IsErrNotExist(err) {
ctx.ServerError("GetBranchCommit", err)
}
return nil, nil
}
- // get requested pagename
+ // get requested page name
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
if len(pageName) == 0 {
pageName = "Home"
@@ -394,50 +340,35 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
ctx.Data["Username"] = ctx.Repo.Owner.Name
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
- // lookup filename in wiki - get filecontent, gitTree entry , real filename
- data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
+ // lookup filename in wiki - get page content, gitTree entry , real filename
+ _, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
if noEntry {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
}
if entry == nil || ctx.Written() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
return nil, nil
}
- ctx.Data["content"] = string(data)
- ctx.Data["sidebarPresent"] = false
- ctx.Data["sidebarContent"] = ""
- ctx.Data["footerPresent"] = false
- ctx.Data["footerContent"] = ""
-
// get commit count - wiki revisions
- commitsCount, _ := wikiRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
+ commitsCount, _ := wikiGitRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
ctx.Data["CommitCount"] = commitsCount
// get page
page := max(ctx.FormInt("page"), 1)
// get Commit Count
- commitsHistory, err := wikiRepo.CommitsByFileAndRange(
+ commitsHistory, err := wikiGitRepo.CommitsByFileAndRange(
git.CommitsByFileAndRangeOptions{
Revision: ctx.Repo.Repository.DefaultWikiBranch,
File: pageFilename,
Page: page,
})
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
ctx.ServerError("CommitsByFileAndRange", err)
return nil, nil
}
ctx.Data["Commits"], err = git_service.ConvertFromGitCommit(ctx, commitsHistory, ctx.Repo.Repository)
if err != nil {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
ctx.ServerError("ConvertFromGitCommit", err)
return nil, nil
}
@@ -446,16 +377,11 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
pager.AddParamFromRequest(ctx.Req)
ctx.Data["Page"] = pager
- return wikiRepo, entry
+ return wikiGitRepo, entry
}
func renderEditPage(ctx *context.Context) {
- wikiRepo, commit, err := findWikiRepoCommit(ctx)
- defer func() {
- if wikiRepo != nil {
- _ = wikiRepo.Close()
- }
- }()
+ _, commit, err := findWikiRepoCommit(ctx)
if err != nil {
if !git.IsErrNotExist(err) {
ctx.ServerError("GetBranchCommit", err)
@@ -463,7 +389,7 @@ func renderEditPage(ctx *context.Context) {
return
}
- // get requested pagename
+ // get requested page name
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
if len(pageName) == 0 {
pageName = "Home"
@@ -487,17 +413,13 @@ func renderEditPage(ctx *context.Context) {
return
}
- // get filecontent
+ // get wiki page content
data := wikiContentsByEntry(ctx, entry)
if ctx.Written() {
return
}
- ctx.Data["content"] = string(data)
- ctx.Data["sidebarPresent"] = false
- ctx.Data["sidebarContent"] = ""
- ctx.Data["footerPresent"] = false
- ctx.Data["footerContent"] = ""
+ ctx.Data["WikiEditContent"] = string(data)
}
// WikiPost renders post of wiki page
@@ -559,12 +481,7 @@ func Wiki(ctx *context.Context) {
return
}
- wikiRepo, entry := renderViewPage(ctx)
- defer func() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
- }()
+ wikiGitRepo, entry := renderViewPage(ctx)
if ctx.Written() {
return
}
@@ -580,7 +497,7 @@ func Wiki(ctx *context.Context) {
ctx.Data["FormatWarning"] = ext + " rendering is not supported at the moment. Rendered as Markdown."
}
// Get last change information.
- lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
+ lastCommit, err := wikiGitRepo.GetCommitByPath(wikiPath)
if err != nil {
ctx.ServerError("GetCommitByPath", err)
return
@@ -600,13 +517,7 @@ func WikiRevision(ctx *context.Context) {
return
}
- wikiRepo, entry := renderRevisionPage(ctx)
- defer func() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
- }()
-
+ wikiGitRepo, entry := renderRevisionPage(ctx)
if ctx.Written() {
return
}
@@ -618,7 +529,7 @@ func WikiRevision(ctx *context.Context) {
// Get last change information.
wikiPath := entry.Name()
- lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
+ lastCommit, err := wikiGitRepo.GetCommitByPath(wikiPath)
if err != nil {
ctx.ServerError("GetCommitByPath", err)
return
@@ -638,12 +549,7 @@ func WikiPages(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.wiki.pages")
ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
- wikiRepo, commit, err := findWikiRepoCommit(ctx)
- defer func() {
- if wikiRepo != nil {
- _ = wikiRepo.Close()
- }
- }()
+ _, commit, err := findWikiRepoCommit(ctx)
if err != nil {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
return
@@ -697,13 +603,7 @@ func WikiPages(ctx *context.Context) {
// WikiRaw outputs raw blob requested by user (image for example)
func WikiRaw(ctx *context.Context) {
- wikiRepo, commit, err := findWikiRepoCommit(ctx)
- defer func() {
- if wikiRepo != nil {
- wikiRepo.Close()
- }
- }()
-
+ _, commit, err := findWikiRepoCommit(ctx)
if err != nil {
if git.IsErrNotExist(err) {
ctx.NotFound(nil)
diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go
index 73f9970a072d9..59bf6ed79b817 100644
--- a/routers/web/repo/wiki_test.go
+++ b/routers/web/repo/wiki_test.go
@@ -164,7 +164,7 @@ func TestEditWiki(t *testing.T) {
EditWiki(ctx)
assert.Equal(t, http.StatusOK, ctx.Resp.WrittenStatus())
assert.EqualValues(t, "Home", ctx.Data["Title"])
- assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["content"])
+ assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["WikiEditContent"])
ctx, _ = contexttest.MockContext(t, "user2/repo1/wiki/jpeg.jpg?action=_edit")
ctx.SetPathParam("*", "jpeg.jpg")
diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go
index ae195758b9721..fdd428b45c7a0 100644
--- a/services/webhook/telegram.go
+++ b/services/webhook/telegram.go
@@ -195,7 +195,7 @@ func (telegramConvertor) WorkflowJob(p *api.WorkflowJobPayload) (TelegramPayload
func createTelegramPayloadHTML(msgHTML string) TelegramPayload {
// https://core.telegram.org/bots/api#formatting-options
return TelegramPayload{
- Message: strings.TrimSpace(markup.Sanitize(msgHTML)),
+ Message: strings.TrimSpace(string(markup.Sanitize(msgHTML))),
ParseMode: "HTML",
DisableWebPreview: true,
}
diff --git a/templates/repo/unicode_escape_prompt.tmpl b/templates/repo/unicode_escape_prompt.tmpl
index 8bceafa8bbca1..f8226ec72842f 100644
--- a/templates/repo/unicode_escape_prompt.tmpl
+++ b/templates/repo/unicode_escape_prompt.tmpl
@@ -1,22 +1,22 @@
{{if .EscapeStatus}}
{{if .EscapeStatus.HasInvisible}}
-
+
{{svg "octicon-x" 16 "close inside"}}
-
{{ctx.Locale.Tr "repo.invisible_runes_description"}}
+
{{ctx.Locale.Tr "repo.invisible_runes_description"}}
{{if .EscapeStatus.HasAmbiguous}}
-
{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}
+
{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}
{{end}}
{{else if .EscapeStatus.HasAmbiguous}}
-
+
{{svg "octicon-x" 16 "close inside"}}
-
{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}
+
{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}
{{end}}
{{end}}
diff --git a/templates/repo/wiki/new.tmpl b/templates/repo/wiki/new.tmpl
index 5ebccc69e9095..12f0983904670 100644
--- a/templates/repo/wiki/new.tmpl
+++ b/templates/repo/wiki/new.tmpl
@@ -18,7 +18,7 @@
{{ctx.Locale.Tr "repo.wiki.page_name_desc"}}
- {{$content := .content}}
+ {{$content := .WikiEditContent}}
{{if not .PageIsWikiEdit}}
{{$content = ctx.Locale.Tr "repo.wiki.welcome"}}
{{end}}
diff --git a/templates/repo/wiki/view.tmpl b/templates/repo/wiki/view.tmpl
index 89befcd7c53ef..f6f82fb52dcc0 100644
--- a/templates/repo/wiki/view.tmpl
+++ b/templates/repo/wiki/view.tmpl
@@ -62,36 +62,34 @@
{{end}}
- {{if .sidebarTocContent}}
+ {{if .WikiSidebarTocHTML}}
{{end}}
-
- {{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus "root" $}}
- {{.content | SafeHTML}}
+
+ {{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus}}
+ {{.WikiContentHTML}}
- {{if .sidebarPresent}}
+ {{if .WikiSidebarHTML}}
{{end}}
- {{if .footerPresent}}
+ {{if .WikiFooterHTML}}
{{end}}
diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css
index 8f92a517493c1..c6a89edf25e58 100644
--- a/web_src/css/markup/content.css
+++ b/web_src/css/markup/content.css
@@ -134,7 +134,9 @@
margin-bottom: 16px;
}
-/* override p:last-child from base.css */
+/* override p:last-child from base.css.
+Fomantic assumes that
/ elements only have margins between elements, but not for the first's top or last's bottom.
+In markup content, we always use bottom margin for all elements */
.markup p:last-child {
margin-bottom: 16px;
}
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index 85522a0a69efd..1a05b68dd4ec2 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -1834,6 +1834,7 @@ tbody.commit-list {
border-radius: 0;
display: flex;
flex-direction: column;
+ gap: 0.5em;
}
/* fomantic's last-child selector does not work with hidden last child */
diff --git a/web_src/css/repo/wiki.css b/web_src/css/repo/wiki.css
index ca59dadb9c806..144cb1206c46e 100644
--- a/web_src/css/repo/wiki.css
+++ b/web_src/css/repo/wiki.css
@@ -39,10 +39,6 @@
min-width: 150px;
}
-.repository.wiki .wiki-content-sidebar .ui.message.unicode-escape-prompt p {
- display: none;
-}
-
.repository.wiki .wiki-content-footer {
margin-top: 1em;
}