From 51789ba12d0585ebf5d52a550cb979067b2f0c2b Mon Sep 17 00:00:00 2001
From: Giteabot <teabot@gitea.io>
Date: Fri, 23 Jun 2023 22:16:15 -0400
Subject: [PATCH] Improve wiki sidebar and TOC (#25460) (#25477)

Backport #25460 by @wxiaoguang

Close #20976
Close #20975

1. Fix the bug: the TOC in footer was incorrectly rendered as main
content's TOC
2. Fix the layout: on mobile, the TOC is put above the main content,
while the sidebar is put below the main content
3. Auto collapse the TOC on mobile

ps: many styles of "wiki.css" are moved from old css files, so leave
nits to following PRs.

### for desktop


![image](https://github.com/go-gitea/gitea/assets/2114189/6c84201c-0648-465a-99e6-c53cdaee53c0)

### for mobile


![image](https://github.com/go-gitea/gitea/assets/2114189/9cb4fdfe-b6ab-4e6f-ae82-219ddb8fa27e)

### other changed pages

<details>


![image](https://github.com/go-gitea/gitea/assets/2114189/ef077736-2c3e-4e3d-82fe-d9bf1ebcca98)


![image](https://github.com/go-gitea/gitea/assets/2114189/bb528429-ad5f-4258-a5c4-05f997c624ea)

</details>

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
---
 routers/web/repo/wiki.go          | 20 +++++-----
 templates/repo/wiki/revision.tmpl | 20 +++++-----
 templates/repo/wiki/start.tmpl    |  4 +-
 templates/repo/wiki/view.tmpl     | 52 +++++++++++++------------
 web_src/css/helpers.css           |  1 +
 web_src/css/index.css             |  1 +
 web_src/css/markup/content.css    | 14 -------
 web_src/css/repo.css              | 57 ----------------------------
 web_src/css/repo/wiki.css         | 63 +++++++++++++++++++++++++++++++
 web_src/js/features/repo-wiki.js  | 12 ++++++
 web_src/js/modules/fomantic.js    |  2 +
 11 files changed, 129 insertions(+), 117 deletions(-)
 create mode 100644 web_src/css/repo/wiki.css

diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index 115418887d..22cfe6dd25 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -273,6 +273,16 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
 		return nil, nil
 	}
 
+	if rctx.SidebarTocNode != nil {
+		sb := &strings.Builder{}
+		err = markdown.SpecializedMarkdown().Renderer().Render(sb, nil, rctx.SidebarTocNode)
+		if err != nil {
+			log.Error("Failed to render wiki sidebar TOC: %v", err)
+		} else {
+			ctx.Data["sidebarTocContent"] = sb.String()
+		}
+	}
+
 	if !isSideBar {
 		buf.Reset()
 		ctx.Data["sidebarEscapeStatus"], ctx.Data["sidebarContent"], err = renderFn(sidebarContent)
@@ -303,16 +313,6 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
 		ctx.Data["footerPresent"] = false
 	}
 
-	if rctx.SidebarTocNode != nil {
-		sb := &strings.Builder{}
-		err = markdown.SpecializedMarkdown().Renderer().Render(sb, nil, rctx.SidebarTocNode)
-		if err != nil {
-			log.Error("Failed to render wiki sidebar TOC: %v", err)
-		} else {
-			ctx.Data["sidebarTocContent"] = sb.String()
-		}
-	}
-
 	// get commit count - wiki revisions
 	commitsCount, _ := wikiRepo.FileCommitsCount(wiki_service.DefaultBranch, pageFilename)
 	ctx.Data["CommitCount"] = commitsCount
diff --git a/templates/repo/wiki/revision.tmpl b/templates/repo/wiki/revision.tmpl
index 803c8629a6..b2d6e63924 100644
--- a/templates/repo/wiki/revision.tmpl
+++ b/templates/repo/wiki/revision.tmpl
@@ -4,20 +4,22 @@
 	{{$title := .title}}
 	<div class="ui container">
 		<div class="ui stackable grid">
-			<div class="ui eight wide column text right gt-df gt-ac gt-je">
+			<div class="ui eight wide column">
+				<div class="ui header">
+					<a class="file-revisions-btn ui basic button" title="{{.locale.Tr "repo.wiki.back_to_wiki"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}"><span>{{.revision}}</span> {{svg "octicon-home"}}</a>
+					{{$title}}
+					<div class="ui sub header gt-word-break">
+						{{$timeSince := TimeSince .Author.When $.locale}}
+						{{.locale.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
+					</div>
+				</div>
+			</div>
+			<div class="ui eight wide column text right">
 				<div class="ui action small input" id="clone-panel">
 					{{template "repo/clone_buttons" .}}
 					{{template "repo/clone_script" .}}
 				</div>
 			</div>
-			<div class="ui header eight wide column">
-				<a class="file-revisions-btn ui basic button" title="{{.locale.Tr "repo.wiki.back_to_wiki"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}" ><span>{{.revision}}</span> {{svg "octicon-home"}}</a>
-				{{$title}}
-				<div class="ui sub header gt-word-break">
-					{{$timeSince := TimeSince .Author.When $.locale}}
-					{{.locale.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
-				</div>
-			</div>
 		</div>
 		<h2 class="ui top header">{{.locale.Tr "repo.wiki.wiki_page_revisions"}}</h2>
 		<div class="gt-mt-4">
diff --git a/templates/repo/wiki/start.tmpl b/templates/repo/wiki/start.tmpl
index c98ee6f3c9..4885042fd8 100644
--- a/templates/repo/wiki/start.tmpl
+++ b/templates/repo/wiki/start.tmpl
@@ -2,8 +2,8 @@
 <div role="main" aria-label="{{.Title}}" class="page-content repository wiki start">
 	{{template "repo/header" .}}
 	<div class="ui container">
-		<div class="ui center segment">
-			{{svg "octicon-book" 32}}
+		<div class="ui center segment gt-py-5">
+			{{svg "octicon-book" 48}}
 			<h2>{{.locale.Tr "repo.wiki.welcome"}}</h2>
 			<p>{{.locale.Tr "repo.wiki.welcome_desc"}}</p>
 			{{if and .CanWriteWiki (not .Repository.IsMirror)}}
diff --git a/templates/repo/wiki/view.tmpl b/templates/repo/wiki/view.tmpl
index ee9a3b2142..c294af3160 100644
--- a/templates/repo/wiki/view.tmpl
+++ b/templates/repo/wiki/view.tmpl
@@ -63,39 +63,41 @@
 				<p>{{.FormatWarning}}</p>
 			</div>
 		{{end}}
-		<div class="ui gt-mt-0 {{if or .sidebarPresent .sidebarTocContent}}grid equal width{{end}}">
-			<div class="ui {{if or .sidebarPresent .sidebarTocContent}}eleven wide column{{else}}gt-ml-0{{end}} segment markup wiki-content-main">
+
+		<div class="wiki-content-parts">
+			{{if .sidebarTocContent}}
+			<div class="markup wiki-content-sidebar wiki-content-toc">
+				{{.sidebarTocContent | Safe}}
+			</div>
+			{{end}}
+
+			<div class="markup wiki-content-main {{if or .sidebarTocContent .sidebarPresent}}with-sidebar{{end}}">
 				{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus "root" $}}
 				{{.content | Safe}}
 			</div>
-			{{if or .sidebarPresent .sidebarTocContent}}
-			<div class="column gt-pt-0">
-				{{if .sidebarTocContent}}
-					<div class="ui segment wiki-content-toc">
-						{{.sidebarTocContent | Safe}}
-					</div>
+
+			{{if .sidebarPresent}}
+			<div class="markup wiki-content-sidebar">
+				{{if and .CanWriteWiki (not .Repository.IsMirror)}}
+					<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
 				{{end}}
-				{{if .sidebarPresent}}
-					<div class="ui segment wiki-content-sidebar">
-						{{if and .CanWriteWiki (not .Repository.IsMirror)}}
-							<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
-						{{end}}
-						{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}}
-						{{.sidebarContent | Safe}}
-					</div>
+				{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}}
+				{{.sidebarContent | Safe}}
+			</div>
+			{{end}}
+
+			<div class="gt-clear-both"></div>
+
+			{{if .footerPresent}}
+			<div class="markup wiki-content-footer">
+				{{if and .CanWriteWiki (not .Repository.IsMirror)}}
+					<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
 				{{end}}
+				{{template "repo/unicode_escape_prompt" dict "footerEscapeStatus" .sidebarEscapeStatus "root" $}}
+				{{.footerContent | Safe}}
 			</div>
 			{{end}}
 		</div>
-		{{if .footerPresent}}
-		<div class="ui segment wiki-content-footer">
-			{{if and .CanWriteWiki (not .Repository.IsMirror)}}
-				<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
-			{{end}}
-			{{template "repo/unicode_escape_prompt" dict "footerEscapeStatus" .sidebarEscapeStatus "root" $}}
-			{{.footerContent | Safe}}
-		</div>
-		{{end}}
 	</div>
 </div>
 
diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css
index eb0cf02068..dcb0410522 100644
--- a/web_src/css/helpers.css
+++ b/web_src/css/helpers.css
@@ -86,6 +86,7 @@ Gitea's private styles use `g-` prefix.
 
 .gt-float-left { float: left !important; }
 .gt-float-right { float: right !important; }
+.gt-clear-both { clear: both !important; }
 
 .gt-font-light { font-weight: var(--font-weight-light) !important; }
 .gt-font-normal { font-weight: var(--font-weight-normal) !important; }
diff --git a/web_src/css/index.css b/web_src/css/index.css
index 125249ceab..8353305e35 100644
--- a/web_src/css/index.css
+++ b/web_src/css/index.css
@@ -44,6 +44,7 @@
 @import "./repo/issue-list.css";
 @import "./repo/list-header.css";
 @import "./repo/linebutton.css";
+@import "./repo/wiki.css";
 
 @import "./editor/fileeditor.css";
 @import "./editor/combomarkdowneditor.css";
diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css
index e300995b31..faed8edb33 100644
--- a/web_src/css/markup/content.css
+++ b/web_src/css/markup/content.css
@@ -517,20 +517,6 @@
   padding-left: 2em;
 }
 
-.repository.wiki.revisions .ui.container > .ui.stackable.grid {
-  -ms-flex-direction: row-reverse;
-  flex-direction: row-reverse;
-}
-
-.repository.wiki.revisions .ui.container > .ui.stackable.grid > .header {
-  margin-top: 0;
-}
-
-.repository.wiki.revisions .ui.container > .ui.stackable.grid > .header .sub.header {
-  padding-left: 52px;
-  word-break: break-word;
-}
-
 .file-revisions-btn {
   display: block;
   float: left;
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index 071a0603d3..d7bd08079b 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -1891,50 +1891,9 @@
   white-space: nowrap;
 }
 
-.repository.wiki.start .ui.segment {
-  padding-top: 70px;
-  padding-bottom: 100px;
-}
-
-.repository.wiki.start .ui.segment .svg {
-  height: 48px;
-}
-
-.repository.wiki.new .ui.attached.tabular.menu.previewtabs {
-  margin-bottom: 15px;
-}
-
 .file-view.markup {
   padding: 1em 2em;
 }
-
-.wiki-content-main {
-  padding: 1em 2em !important;
-  margin-left: 1em !important;
-}
-
-.wiki-pages-list .wiki-git-entry {
-  margin-left: 10px;
-  display: none;
-}
-
-.wiki-pages-list td:hover .wiki-git-entry {
-  display: inline-block;
-}
-
-@media (max-width: 767.98px) {
-  .repository.wiki .dividing.header .stackable.grid .button {
-    margin-top: 2px;
-    margin-bottom: 2px;
-  }
-}
-
-@media (max-width: 767.98px) {
-  .repository.wiki #clone-panel #repo-clone-url {
-    width: 160px;
-  }
-}
-
 .repository .activity-header {
   display: flex;
   justify-content: space-between;
@@ -2992,22 +2951,6 @@ tbody.commit-list {
   flex-direction: column;
 }
 
-.wiki-content-sidebar .ui.message.unicode-escape-prompt p,
-.wiki-content-footer .ui.message.unicode-escape-prompt p {
-  display: none;
-}
-
-.wiki-content-toc ul {
-  margin: 0;
-  list-style: none;
-  padding: 5px 0 5px 1em;
-}
-
-.wiki-content-toc ul ul {
-  border-left:  1px var(--color-secondary);
-  border-left-style: dashed;
-}
-
 /* fomantic's last-child selector does not work with hidden last child */
 .ui.buttons .unescape-button {
   border-top-right-radius: 0.28571429rem;
diff --git a/web_src/css/repo/wiki.css b/web_src/css/repo/wiki.css
new file mode 100644
index 0000000000..b13679f615
--- /dev/null
+++ b/web_src/css/repo/wiki.css
@@ -0,0 +1,63 @@
+.repository.wiki .wiki-pages-list .wiki-git-entry {
+  margin-left: 10px;
+  display: none;
+}
+
+.repository.wiki .wiki-pages-list td:hover .wiki-git-entry {
+  display: inline-block;
+}
+
+.repository.wiki .markup {
+  overflow: visible;
+}
+
+.repository.wiki .wiki-content-parts .markup {
+  border: 1px solid var(--color-secondary);
+  padding: 1em;
+  margin-top: 1em;
+  font-size: 1em;
+}
+
+.repository.wiki .wiki-content-main.with-sidebar {
+  float: left;
+  width: 80%;
+  max-width: calc(100% - 150px - 1em); /* match the min-width of .wiki-content-sidebar */
+}
+
+.repository.wiki .wiki-content-sidebar {
+  float: right;
+  width: calc(20% - 1em);
+  min-width: 150px;
+}
+
+.repository.wiki .wiki-content-sidebar .ui.message.unicode-escape-prompt p {
+  display: none;
+}
+
+.repository.wiki .wiki-content-footer {
+  margin-top: 1em;
+}
+
+.repository.wiki .wiki-content-toc ul {
+  margin: 0;
+  list-style: none;
+  padding: 5px 0 5px 1em;
+}
+
+.repository.wiki .wiki-content-toc ul ul {
+  border-left:  1px var(--color-secondary);
+  border-left-style: dashed;
+}
+
+@media (max-width: 767.98px) {
+  .repository.wiki #clone-panel #repo-clone-url {
+    width: 160px;
+  }
+  .repository.wiki .wiki-content-main.with-sidebar,
+  .repository.wiki .wiki-content-sidebar {
+    float: none;
+    width: 100%;
+    min-width: unset;
+    max-width: unset;
+  }
+}
diff --git a/web_src/js/features/repo-wiki.js b/web_src/js/features/repo-wiki.js
index c37da45994..58036fde37 100644
--- a/web_src/js/features/repo-wiki.js
+++ b/web_src/js/features/repo-wiki.js
@@ -1,6 +1,7 @@
 import $ from 'jquery';
 import {initMarkupContent} from '../markup/content.js';
 import {validateTextareaNonEmpty, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.js';
+import {fomanticMobileScreen} from '../modules/fomantic.js';
 
 const {csrfToken} = window.config;
 
@@ -70,6 +71,17 @@ async function initRepoWikiFormEditor() {
   });
 }
 
+function collapseWikiTocForMobile(collapse) {
+  if (collapse) {
+    document.querySelector('.wiki-content-toc details')?.removeAttribute('open');
+  }
+}
+
 export function initRepoWikiForm() {
+  if (!document.querySelector('.page-content.repository.wiki')) return;
+
+  fomanticMobileScreen.addEventListener('change', (e) => collapseWikiTocForMobile(e.matches));
+  collapseWikiTocForMobile(fomanticMobileScreen.matches);
+
   initRepoWikiFormEditor();
 }
diff --git a/web_src/js/modules/fomantic.js b/web_src/js/modules/fomantic.js
index 1495b311ca..5988584aca 100644
--- a/web_src/js/modules/fomantic.js
+++ b/web_src/js/modules/fomantic.js
@@ -3,6 +3,8 @@ import {initAriaCheckboxPatch} from './aria/checkbox.js';
 import {initAriaDropdownPatch} from './aria/dropdown.js';
 import {svg} from '../svg.js';
 
+export const fomanticMobileScreen = window.matchMedia('only screen and (max-width: 767.98px)');
+
 export function initGiteaFomantic() {
   // Silence fomantic's error logging when tabs are used without a target content element
   $.fn.tab.settings.silent = true;