From 2c6cc0b8c982b3d49a5b208f75e15b2269584312 Mon Sep 17 00:00:00 2001
From: wxiaoguang <wxiaoguang@gmail.com>
Date: Wed, 8 Feb 2023 00:08:44 +0800
Subject: [PATCH] Fix links for the menus in the view file page (#22795)

---
 templates/repo/view_file.tmpl    |  3 +--
 web_src/js/features/repo-code.js | 14 ++++++++------
 web_src/js/utils.js              | 14 ++++++++++----
 web_src/js/utils.test.js         |  5 +++++
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl
index 85ff0120b22..e92aeb0702b 100644
--- a/templates/repo/view_file.tmpl
+++ b/templates/repo/view_file.tmpl
@@ -110,8 +110,7 @@
 				</table>
 				<div class="code-line-menu ui vertical pointing menu tippy-target">
 					{{if $.Permission.CanRead $.UnitTypeIssues}}
-						{{/* FIXME: Here we use HTMLURL but not link, see https://github.com/go-gitea/gitea/pull/21986/files#r1096532186*/}}
-						<a class="item ref-in-new-issue" href="{{.RepoLink}}/issues/new?body={{.Repository.HTMLURL}}{{printf "/src/commit/"}}{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}" rel="nofollow noindex">{{.locale.Tr "repo.issues.context.reference_issue"}}</a>
+						<a class="item ref-in-new-issue" data-url-issue-new="{{.RepoLink}}/issues/new" data-url-param-body-link="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}" rel="nofollow noindex">{{.locale.Tr "repo.issues.context.reference_issue"}}</a>
 					{{end}}
 					<a class="item view_git_blame" href="{{.Repository.Link}}/blame/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{.locale.Tr "repo.view_git_blame"}}</a>
 					<a class="item copy-line-permalink" data-url="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{.locale.Tr "repo.file_copy_permalink"}}</a>
diff --git a/web_src/js/features/repo-code.js b/web_src/js/features/repo-code.js
index 083a17bf216..1c599131329 100644
--- a/web_src/js/features/repo-code.js
+++ b/web_src/js/features/repo-code.js
@@ -3,6 +3,7 @@ import {svg} from '../svg.js';
 import {invertFileFolding} from './file-fold.js';
 import {createTippy} from '../modules/tippy.js';
 import {copyToClipboard} from './clipboard.js';
+import {toAbsoluteUrl} from '../utils.js';
 
 export const singleAnchorRegex = /^#(L|n)([1-9][0-9]*)$/;
 export const rangeAnchorRegex = /^#(L[1-9][0-9]*)-(L[1-9][0-9]*)$/;
@@ -19,17 +20,18 @@ function selectRange($list, $select, $from) {
   $list.removeClass('active');
 
   // add hashchange to permalink
-  const $issue = $('a.ref-in-new-issue');
+  const $refInNewIssue = $('a.ref-in-new-issue');
   const $copyPermalink = $('a.copy-line-permalink');
   const $viewGitBlame = $('a.view_git_blame');
 
   const updateIssueHref = function (anchor) {
-    if ($issue.length === 0) {
+    if ($refInNewIssue.length === 0) {
       return;
     }
-    let href = $issue.attr('href');
-    href = `${href.replace(/%23L\d+$|%23L\d+-L\d+$/, '')}%23${anchor}`;
-    $issue.attr('href', href);
+    const urlIssueNew = $refInNewIssue.attr('data-url-issue-new');
+    const urlParamBodyLink = $refInNewIssue.attr('data-url-param-body-link');
+    const issueContent = `${toAbsoluteUrl(urlParamBodyLink)}#${anchor}`; // the default content for issue body
+    $refInNewIssue.attr('href', `${urlIssueNew}?body=${encodeURIComponent(issueContent)}`);
   };
 
   const updateViewGitBlameFragment = function (anchor) {
@@ -188,7 +190,7 @@ export function initRepoCodeView() {
     currentTarget.closest('tr').outerHTML = blob;
   });
   $(document).on('click', '.copy-line-permalink', async (e) => {
-    const success = await copyToClipboard(e.currentTarget.getAttribute('data-url'));
+    const success = await copyToClipboard(toAbsoluteUrl(e.currentTarget.getAttribute('data-url')));
     if (!success) return;
     document.querySelector('.code-line-button')?._tippy?.hide();
   });
diff --git a/web_src/js/utils.js b/web_src/js/utils.js
index b9cd69e15aa..c7624404c74 100644
--- a/web_src/js/utils.js
+++ b/web_src/js/utils.js
@@ -134,9 +134,15 @@ export function convertImage(blob, mime) {
   });
 }
 
-export function toAbsoluteUrl(relUrl) {
-  if (relUrl.startsWith('http://') || relUrl.startsWith('https://')) {
-    return relUrl;
+export function toAbsoluteUrl(url) {
+  if (url.startsWith('http://') || url.startsWith('https://')) {
+    return url;
   }
-  return `${window.location.origin}${relUrl}`;
+  if (url.startsWith('//')) {
+    return `${window.location.protocol}${url}`; // it's also a somewhat absolute URL (with the current scheme)
+  }
+  if (url && !url.startsWith('/')) {
+    throw new Error('unsupported url, it should either start with / or http(s)://');
+  }
+  return `${window.location.origin}${url}`;
 }
diff --git a/web_src/js/utils.test.js b/web_src/js/utils.test.js
index 4efe916231d..306acd34afe 100644
--- a/web_src/js/utils.test.js
+++ b/web_src/js/utils.test.js
@@ -139,6 +139,11 @@ test('blobToDataURI', async () => {
 });
 
 test('toAbsoluteUrl', () => {
+  expect(toAbsoluteUrl('//host/dir')).toEqual('http://host/dir');
+  expect(toAbsoluteUrl('https://host/dir')).toEqual('https://host/dir');
+
   expect(toAbsoluteUrl('')).toEqual('http://localhost:3000');
   expect(toAbsoluteUrl('/user/repo')).toEqual('http://localhost:3000/user/repo');
+
+  expect(() => toAbsoluteUrl('path')).toThrowError('unsupported');
 });