Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions web_src/js/features/repo-common.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {substituteRepoOpenWithUrl} from './repo-common.ts';

test('substituteRepoOpenWithUrl', () => {
expect(substituteRepoOpenWithUrl('proto://a/{url}', 'https://gitea')).toEqual('proto://a/https://gitea');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Erm, what?
Is that really a valid URL?
It looks wrong to me…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it is not a URL since the "protocol" is not http(s).

There is no requirement to encode that part.

image

Copy link
Member

@silverwind silverwind Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is a valid URL according to URL standard:

> new URL("proto://a/https://gitea")
URL {
  href: 'proto://a/https://gitea',
  origin: 'null',
  protocol: 'proto:',
  username: '',
  password: '',
  host: 'a',
  hostname: 'a',
  port: '',
  pathname: '/https://gitea',
  search: '',
  searchParams: URLSearchParams {},
  hash: ''
}

expect(substituteRepoOpenWithUrl('proto://a?link={url}', 'https://gitea')).toEqual('proto://a?link=https%3A%2F%2Fgitea');
});
10 changes: 9 additions & 1 deletion web_src/js/features/repo-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export function initRepoActivityTopAuthorsChart() {
}
}

export function substituteRepoOpenWithUrl(tmpl: string, url: string): string {
const pos = tmpl.indexOf('{url}');
if (pos === -1) return tmpl;
const posQuestionMark = tmpl.indexOf('?');
const needEncode = posQuestionMark >= 0 && posQuestionMark < pos;
return tmpl.replace('{url}', needEncode ? encodeURIComponent(url) : url);
}

function initCloneSchemeUrlSelection(parent: Element) {
const elCloneUrlInput = parent.querySelector<HTMLInputElement>('.repo-clone-url');

Expand Down Expand Up @@ -70,7 +78,7 @@ function initCloneSchemeUrlSelection(parent: Element) {
}
}
for (const el of parent.querySelectorAll<HTMLAnchorElement>('.js-clone-url-editor')) {
el.href = el.getAttribute('data-href-template').replace('{url}', encodeURIComponent(link));
el.href = substituteRepoOpenWithUrl(el.getAttribute('data-href-template'), link);
}
};

Expand Down