diff --git a/web_src/js/features/repo-common.test.ts b/web_src/js/features/repo-common.test.ts new file mode 100644 index 0000000000000..009dfc86b1016 --- /dev/null +++ b/web_src/js/features/repo-common.test.ts @@ -0,0 +1,7 @@ +import {substituteRepoOpenWithUrl} from './repo-common.ts'; + +test('substituteRepoOpenWithUrl', () => { + // For example: "x-github-client://openRepo/https://github.com/go-gitea/gitea" + expect(substituteRepoOpenWithUrl('proto://a/{url}', 'https://gitea')).toEqual('proto://a/https://gitea'); + expect(substituteRepoOpenWithUrl('proto://a?link={url}', 'https://gitea')).toEqual('proto://a?link=https%3A%2F%2Fgitea'); +}); diff --git a/web_src/js/features/repo-common.ts b/web_src/js/features/repo-common.ts index 2f62d51597c44..444cb163bf140 100644 --- a/web_src/js/features/repo-common.ts +++ b/web_src/js/features/repo-common.ts @@ -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('.repo-clone-url'); @@ -70,7 +78,7 @@ function initCloneSchemeUrlSelection(parent: Element) { } } for (const el of parent.querySelectorAll('.js-clone-url-editor')) { - el.href = el.getAttribute('data-href-template').replace('{url}', encodeURIComponent(link)); + el.href = substituteRepoOpenWithUrl(el.getAttribute('data-href-template'), link); } };