1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-04 01:27:20 +00:00

Refactor wiki (#34805)

Remove unclear code
This commit is contained in:
wxiaoguang
2025-06-22 18:53:33 +08:00
committed by GitHub
parent 94c6d46faa
commit f114c388ff
12 changed files with 71 additions and 173 deletions

View File

@ -4,6 +4,7 @@
package markup package markup
import ( import (
"html/template"
"io" "io"
"net/url" "net/url"
"regexp" "regexp"
@ -92,9 +93,9 @@ func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy {
return policy return policy
} }
// Sanitize takes a string that contains a HTML fragment or document and applies policy whitelist. // Sanitize use default sanitizer policy to sanitize a string
func Sanitize(s string) string { func Sanitize(s string) template.HTML {
return GetDefaultSanitizer().defaultPolicy.Sanitize(s) return template.HTML(GetDefaultSanitizer().defaultPolicy.Sanitize(s))
} }
// SanitizeReader sanitizes a Reader // SanitizeReader sanitizes a Reader

View File

@ -69,6 +69,6 @@ func TestSanitizer(t *testing.T) {
} }
for i := 0; i < len(testCases); i += 2 { 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])))
} }
} }

View File

@ -176,9 +176,9 @@ func safeHTML(s any) template.HTML {
panic(fmt.Sprintf("unexpected type %T", s)) 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 { func SanitizeHTML(s string) template.HTML {
return template.HTML(markup.Sanitize(s)) return markup.Sanitize(s)
} }
func htmlEscape(s any) template.HTML { func htmlEscape(s any) template.HTML {

View File

@ -7,6 +7,7 @@ package repo
import ( import (
"bytes" "bytes"
gocontext "context" gocontext "context"
"html/template"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
@ -61,9 +62,9 @@ func MustEnableWiki(ctx *context.Context) {
return return
} }
unit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalWiki) repoUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalWiki)
if err == nil { if err == nil {
ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL) ctx.Redirect(repoUnit.ExternalWikiConfig().ExternalWikiURL)
return 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) { 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 { if errGitRepo != nil {
ctx.ServerError("OpenRepository", errGitRepo) ctx.ServerError("OpenRepository", errGitRepo)
return nil, nil, 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) { func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
wikiRepo, commit, err := findWikiRepoCommit(ctx) wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
if err != nil { if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
if !git.IsErrNotExist(err) { if !git.IsErrNotExist(err) {
ctx.ServerError("GetBranchCommit", err) ctx.ServerError("GetBranchCommit", err)
} }
return nil, nil return nil, nil
} }
// Get page list. // get the wiki pages list.
entries, err := commit.ListEntries() entries, err := commit.ListEntries()
if err != nil { if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("ListEntries", err) ctx.ServerError("ListEntries", err)
return nil, nil return nil, nil
} }
@ -208,9 +203,6 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
if repo_model.IsErrWikiInvalidFileName(err) { if repo_model.IsErrWikiInvalidFileName(err) {
continue continue
} }
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("WikiFilenameToName", err) ctx.ServerError("WikiFilenameToName", err)
return nil, nil return nil, nil
} else if wikiName == "_Sidebar" || wikiName == "_Footer" { } 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))) ctx.Redirect(util.URLJoin(ctx.Repo.RepoLink, "wiki/raw", string(pageName)))
} }
if entry == nil || ctx.Written() { if entry == nil || ctx.Written() {
if wikiRepo != nil {
wikiRepo.Close()
}
return nil, nil return nil, nil
} }
// get filecontent // get page content
data := wikiContentsByEntry(ctx, entry) data := wikiContentsByEntry(ctx, entry)
if ctx.Written() { if ctx.Written() {
if wikiRepo != nil {
wikiRepo.Close()
}
return nil, nil 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) rctx := renderhelper.NewRenderContextRepoWiki(ctx, ctx.Repo.Repository)
buf := &strings.Builder{} renderFn := func(data []byte) (escaped *charset.EscapeStatus, output template.HTML, err error) {
renderFn := func(data []byte) (escaped *charset.EscapeStatus, output string, err error) { buf := &strings.Builder{}
markupRd, markupWr := io.Pipe() markupRd, markupWr := io.Pipe()
defer markupWr.Close() defer markupWr.Close()
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
// We allow NBSP here this is rendered // We allow NBSP here this is rendered
escaped, _ = charset.EscapeControlReader(markupRd, buf, ctx.Locale, charset.RuneNBSP) escaped, _ = charset.EscapeControlReader(markupRd, buf, ctx.Locale, charset.RuneNBSP)
output = buf.String() output = template.HTML(buf.String())
buf.Reset() buf.Reset()
close(done) close(done)
}() }()
@ -311,75 +271,61 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
return escaped, output, err 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 err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("Render", err) ctx.ServerError("Render", err)
return nil, nil return nil, nil
} }
if rctx.SidebarTocNode != nil { if rctx.SidebarTocNode != nil {
sb := &strings.Builder{} sb := strings.Builder{}
err = markdown.SpecializedMarkdown(rctx).Renderer().Render(sb, nil, rctx.SidebarTocNode) if err = markdown.SpecializedMarkdown(rctx).Renderer().Render(&sb, nil, rctx.SidebarTocNode); err != nil {
if err != nil {
log.Error("Failed to render wiki sidebar TOC: %v", err) 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 { if !isSideBar {
buf.Reset() sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
ctx.Data["sidebarEscapeStatus"], ctx.Data["sidebarContent"], err = renderFn(sidebarContent) if ctx.Written() {
return nil, nil
}
ctx.Data["WikiSidebarEscapeStatus"], ctx.Data["WikiSidebarHTML"], err = renderFn(sidebarContent)
if err != nil { if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("Render", err) ctx.ServerError("Render", err)
return nil, nil return nil, nil
} }
ctx.Data["sidebarPresent"] = sidebarContent != nil
} else {
ctx.Data["sidebarPresent"] = false
} }
if !isFooter { if !isFooter {
buf.Reset() footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
ctx.Data["footerEscapeStatus"], ctx.Data["footerContent"], err = renderFn(footerContent) if ctx.Written() {
return nil, nil
}
ctx.Data["WikiFooterEscapeStatus"], ctx.Data["WikiFooterHTML"], err = renderFn(footerContent)
if err != nil { if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("Render", err) ctx.ServerError("Render", err)
return nil, nil return nil, nil
} }
ctx.Data["footerPresent"] = footerContent != nil
} else {
ctx.Data["footerPresent"] = false
} }
// get commit count - wiki revisions // 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 ctx.Data["CommitCount"] = commitsCount
return wikiRepo, entry return wikiGitRepo, entry
} }
func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
wikiRepo, commit, err := findWikiRepoCommit(ctx) wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
if err != nil { if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
if !git.IsErrNotExist(err) { if !git.IsErrNotExist(err) {
ctx.ServerError("GetBranchCommit", err) ctx.ServerError("GetBranchCommit", err)
} }
return nil, nil return nil, nil
} }
// get requested pagename // get requested page name
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*")) pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
if len(pageName) == 0 { if len(pageName) == 0 {
pageName = "Home" pageName = "Home"
@ -394,50 +340,35 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Username"] = ctx.Repo.Owner.Name
ctx.Data["Reponame"] = ctx.Repo.Repository.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name
// lookup filename in wiki - get filecontent, gitTree entry , real filename // lookup filename in wiki - get page content, gitTree entry , real filename
data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) _, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
if noEntry { if noEntry {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages") ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
} }
if entry == nil || ctx.Written() { if entry == nil || ctx.Written() {
if wikiRepo != nil {
wikiRepo.Close()
}
return nil, nil 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 // 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 ctx.Data["CommitCount"] = commitsCount
// get page // get page
page := max(ctx.FormInt("page"), 1) page := max(ctx.FormInt("page"), 1)
// get Commit Count // get Commit Count
commitsHistory, err := wikiRepo.CommitsByFileAndRange( commitsHistory, err := wikiGitRepo.CommitsByFileAndRange(
git.CommitsByFileAndRangeOptions{ git.CommitsByFileAndRangeOptions{
Revision: ctx.Repo.Repository.DefaultWikiBranch, Revision: ctx.Repo.Repository.DefaultWikiBranch,
File: pageFilename, File: pageFilename,
Page: page, Page: page,
}) })
if err != nil { if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("CommitsByFileAndRange", err) ctx.ServerError("CommitsByFileAndRange", err)
return nil, nil return nil, nil
} }
ctx.Data["Commits"], err = git_service.ConvertFromGitCommit(ctx, commitsHistory, ctx.Repo.Repository) ctx.Data["Commits"], err = git_service.ConvertFromGitCommit(ctx, commitsHistory, ctx.Repo.Repository)
if err != nil { if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("ConvertFromGitCommit", err) ctx.ServerError("ConvertFromGitCommit", err)
return nil, nil return nil, nil
} }
@ -446,16 +377,11 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
pager.AddParamFromRequest(ctx.Req) pager.AddParamFromRequest(ctx.Req)
ctx.Data["Page"] = pager ctx.Data["Page"] = pager
return wikiRepo, entry return wikiGitRepo, entry
} }
func renderEditPage(ctx *context.Context) { func renderEditPage(ctx *context.Context) {
wikiRepo, commit, err := findWikiRepoCommit(ctx) _, commit, err := findWikiRepoCommit(ctx)
defer func() {
if wikiRepo != nil {
_ = wikiRepo.Close()
}
}()
if err != nil { if err != nil {
if !git.IsErrNotExist(err) { if !git.IsErrNotExist(err) {
ctx.ServerError("GetBranchCommit", err) ctx.ServerError("GetBranchCommit", err)
@ -463,7 +389,7 @@ func renderEditPage(ctx *context.Context) {
return return
} }
// get requested pagename // get requested page name
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*")) pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
if len(pageName) == 0 { if len(pageName) == 0 {
pageName = "Home" pageName = "Home"
@ -487,17 +413,13 @@ func renderEditPage(ctx *context.Context) {
return return
} }
// get filecontent // get wiki page content
data := wikiContentsByEntry(ctx, entry) data := wikiContentsByEntry(ctx, entry)
if ctx.Written() { if ctx.Written() {
return return
} }
ctx.Data["content"] = string(data) ctx.Data["WikiEditContent"] = string(data)
ctx.Data["sidebarPresent"] = false
ctx.Data["sidebarContent"] = ""
ctx.Data["footerPresent"] = false
ctx.Data["footerContent"] = ""
} }
// WikiPost renders post of wiki page // WikiPost renders post of wiki page
@ -559,12 +481,7 @@ func Wiki(ctx *context.Context) {
return return
} }
wikiRepo, entry := renderViewPage(ctx) wikiGitRepo, entry := renderViewPage(ctx)
defer func() {
if wikiRepo != nil {
wikiRepo.Close()
}
}()
if ctx.Written() { if ctx.Written() {
return return
} }
@ -580,7 +497,7 @@ func Wiki(ctx *context.Context) {
ctx.Data["FormatWarning"] = ext + " rendering is not supported at the moment. Rendered as Markdown." ctx.Data["FormatWarning"] = ext + " rendering is not supported at the moment. Rendered as Markdown."
} }
// Get last change information. // Get last change information.
lastCommit, err := wikiRepo.GetCommitByPath(wikiPath) lastCommit, err := wikiGitRepo.GetCommitByPath(wikiPath)
if err != nil { if err != nil {
ctx.ServerError("GetCommitByPath", err) ctx.ServerError("GetCommitByPath", err)
return return
@ -600,13 +517,7 @@ func WikiRevision(ctx *context.Context) {
return return
} }
wikiRepo, entry := renderRevisionPage(ctx) wikiGitRepo, entry := renderRevisionPage(ctx)
defer func() {
if wikiRepo != nil {
wikiRepo.Close()
}
}()
if ctx.Written() { if ctx.Written() {
return return
} }
@ -618,7 +529,7 @@ func WikiRevision(ctx *context.Context) {
// Get last change information. // Get last change information.
wikiPath := entry.Name() wikiPath := entry.Name()
lastCommit, err := wikiRepo.GetCommitByPath(wikiPath) lastCommit, err := wikiGitRepo.GetCommitByPath(wikiPath)
if err != nil { if err != nil {
ctx.ServerError("GetCommitByPath", err) ctx.ServerError("GetCommitByPath", err)
return return
@ -638,12 +549,7 @@ func WikiPages(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.wiki.pages") ctx.Data["Title"] = ctx.Tr("repo.wiki.pages")
ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
wikiRepo, commit, err := findWikiRepoCommit(ctx) _, commit, err := findWikiRepoCommit(ctx)
defer func() {
if wikiRepo != nil {
_ = wikiRepo.Close()
}
}()
if err != nil { if err != nil {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki") ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
return return
@ -697,13 +603,7 @@ func WikiPages(ctx *context.Context) {
// WikiRaw outputs raw blob requested by user (image for example) // WikiRaw outputs raw blob requested by user (image for example)
func WikiRaw(ctx *context.Context) { func WikiRaw(ctx *context.Context) {
wikiRepo, commit, err := findWikiRepoCommit(ctx) _, commit, err := findWikiRepoCommit(ctx)
defer func() {
if wikiRepo != nil {
wikiRepo.Close()
}
}()
if err != nil { if err != nil {
if git.IsErrNotExist(err) { if git.IsErrNotExist(err) {
ctx.NotFound(nil) ctx.NotFound(nil)

View File

@ -164,7 +164,7 @@ func TestEditWiki(t *testing.T) {
EditWiki(ctx) EditWiki(ctx)
assert.Equal(t, http.StatusOK, ctx.Resp.WrittenStatus()) assert.Equal(t, http.StatusOK, ctx.Resp.WrittenStatus())
assert.EqualValues(t, "Home", ctx.Data["Title"]) 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, _ = contexttest.MockContext(t, "user2/repo1/wiki/jpeg.jpg?action=_edit")
ctx.SetPathParam("*", "jpeg.jpg") ctx.SetPathParam("*", "jpeg.jpg")

View File

@ -195,7 +195,7 @@ func (telegramConvertor) WorkflowJob(p *api.WorkflowJobPayload) (TelegramPayload
func createTelegramPayloadHTML(msgHTML string) TelegramPayload { func createTelegramPayloadHTML(msgHTML string) TelegramPayload {
// https://core.telegram.org/bots/api#formatting-options // https://core.telegram.org/bots/api#formatting-options
return TelegramPayload{ return TelegramPayload{
Message: strings.TrimSpace(markup.Sanitize(msgHTML)), Message: strings.TrimSpace(string(markup.Sanitize(msgHTML))),
ParseMode: "HTML", ParseMode: "HTML",
DisableWebPreview: true, DisableWebPreview: true,
} }

View File

@ -1,22 +1,22 @@
{{if .EscapeStatus}} {{if .EscapeStatus}}
{{if .EscapeStatus.HasInvisible}} {{if .EscapeStatus.HasInvisible}}
<div class="ui warning message unicode-escape-prompt tw-text-left"> <div class="ui warning message unicode-escape-prompt">
<button class="btn close icon hide-panel" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button> <button class="btn close icon hide-panel" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button>
<div class="header"> <div class="header">
{{ctx.Locale.Tr "repo.invisible_runes_header"}} {{ctx.Locale.Tr "repo.invisible_runes_header"}}
</div> </div>
<p>{{ctx.Locale.Tr "repo.invisible_runes_description"}}</p> <div>{{ctx.Locale.Tr "repo.invisible_runes_description"}}</div>
{{if .EscapeStatus.HasAmbiguous}} {{if .EscapeStatus.HasAmbiguous}}
<p>{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}</p> <div>{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}</div>
{{end}} {{end}}
</div> </div>
{{else if .EscapeStatus.HasAmbiguous}} {{else if .EscapeStatus.HasAmbiguous}}
<div class="ui warning message unicode-escape-prompt tw-text-left"> <div class="ui warning message unicode-escape-prompt">
<button class="btn close icon hide-panel" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button> <button class="btn close icon hide-panel" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button>
<div class="header"> <div class="header">
{{ctx.Locale.Tr "repo.ambiguous_runes_header"}} {{ctx.Locale.Tr "repo.ambiguous_runes_header"}}
</div> </div>
<p>{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}</p> <div>{{ctx.Locale.Tr "repo.ambiguous_runes_description"}}</div>
</div> </div>
{{end}} {{end}}
{{end}} {{end}}

View File

@ -18,7 +18,7 @@
{{ctx.Locale.Tr "repo.wiki.page_name_desc"}} {{ctx.Locale.Tr "repo.wiki.page_name_desc"}}
</div> </div>
{{$content := .content}} {{$content := .WikiEditContent}}
{{if not .PageIsWikiEdit}} {{if not .PageIsWikiEdit}}
{{$content = ctx.Locale.Tr "repo.wiki.welcome"}} {{$content = ctx.Locale.Tr "repo.wiki.welcome"}}
{{end}} {{end}}

View File

@ -62,36 +62,34 @@
{{end}} {{end}}
<div class="wiki-content-parts"> <div class="wiki-content-parts">
{{if .sidebarTocContent}} {{if .WikiSidebarTocHTML}}
<div class="render-content markup wiki-content-sidebar wiki-content-toc"> <div class="render-content markup wiki-content-sidebar wiki-content-toc">
{{.sidebarTocContent | SafeHTML}} {{.WikiSidebarTocHTML}}
</div> </div>
{{end}} {{end}}
<div class="render-content markup wiki-content-main {{if or .sidebarTocContent .sidebarPresent}}with-sidebar{{end}}"> <div class="render-content markup wiki-content-main {{if or .WikiSidebarTocHTML .WikiSidebarHTML}}with-sidebar{{end}}">
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus "root" $}} {{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus}}
{{.content | SafeHTML}} {{.WikiContentHTML}}
</div> </div>
{{if .sidebarPresent}} {{if .WikiSidebarHTML}}
<div class="render-content markup wiki-content-sidebar"> <div class="render-content markup wiki-content-sidebar">
{{if and .CanWriteWiki (not .Repository.IsMirror)}} {{if and .CanWriteWiki (not .Repository.IsMirror)}}
<a class="tw-float-right muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{ctx.Locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a> <a class="tw-float-right muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{ctx.Locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
{{end}} {{end}}
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}} {{.WikiSidebarHTML}}
{{.sidebarContent | SafeHTML}}
</div> </div>
{{end}} {{end}}
<div class="tw-clear-both"></div> <div class="tw-clear-both"></div>
{{if .footerPresent}} {{if .WikiFooterHTML}}
<div class="render-content markup wiki-content-footer"> <div class="render-content markup wiki-content-footer">
{{if and .CanWriteWiki (not .Repository.IsMirror)}} {{if and .CanWriteWiki (not .Repository.IsMirror)}}
<a class="tw-float-right muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{ctx.Locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a> <a class="tw-float-right muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{ctx.Locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
{{end}} {{end}}
{{template "repo/unicode_escape_prompt" dict "footerEscapeStatus" .sidebarEscapeStatus "root" $}} {{.WikiFooterHTML}}
{{.footerContent | SafeHTML}}
</div> </div>
{{end}} {{end}}
</div> </div>

View File

@ -134,7 +134,9 @@
margin-bottom: 16px; margin-bottom: 16px;
} }
/* override p:last-child from base.css */ /* override p:last-child from base.css.
Fomantic assumes that <p>/<hX> 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 { .markup p:last-child {
margin-bottom: 16px; margin-bottom: 16px;
} }

View File

@ -1834,6 +1834,7 @@ tbody.commit-list {
border-radius: 0; border-radius: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.5em;
} }
/* fomantic's last-child selector does not work with hidden last child */ /* fomantic's last-child selector does not work with hidden last child */

View File

@ -39,10 +39,6 @@
min-width: 150px; min-width: 150px;
} }
.repository.wiki .wiki-content-sidebar .ui.message.unicode-escape-prompt p {
display: none;
}
.repository.wiki .wiki-content-footer { .repository.wiki .wiki-content-footer {
margin-top: 1em; margin-top: 1em;
} }