summaryrefslogtreecommitdiff
path: root/source/features/fork-source-link-same-view.tsx
blob: fd0de58bbc1f89ead84ffac51a6b791a3bee6095 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';

import features from '../feature-manager.js';
import GitHubURL from '../github-helpers/github-url.js';
import doesFileExist from '../github-helpers/does-file-exist.js';
import {getDefaultBranchOfRepo} from '../github-helpers/get-default-branch.js';
import {getRepo, getForkedRepo} from '../github-helpers/index.js';

const isFilePath = (): boolean =>
	pageDetect.isSingleFile()
	|| pageDetect.isRepoTree()
	|| pageDetect.hasFileEditor();

// Only enable the feature on known-shared pages

const isLikelyToBeOnBothRepos = (): boolean =>
	isFilePath()
	|| pageDetect.isIssueOrPRList()
	|| pageDetect.isTags();

async function getEquivalentURL(): Promise<string> {
	const forkedRepository = getRepo(getForkedRepo())!;
	const defaultUrl = '/' + forkedRepository.nameWithOwner;

	if (!isLikelyToBeOnBothRepos()) {
		// We must reset the link because the header is outside the ajaxed area
		return defaultUrl;
	}

	const sameViewUrl = new GitHubURL(location.href).assign({
		user: forkedRepository.owner,
		repository: forkedRepository.name,
	});

	if (isFilePath()) {
		sameViewUrl.branch = await getDefaultBranchOfRepo(forkedRepository);
		if (!await doesFileExist(sameViewUrl)) {
			return defaultUrl;
		}
	}

	return sameViewUrl.href;
}

async function init(): Promise<void> {
	// The link must always be updated/reset. This pattern ensures that the link is always updated and never fails through some conditions.
	const equivalentUrl = await getEquivalentURL();
	const forkLink = await elementReady(`a[data-hovercard-url="/${getForkedRepo()!}/hovercard"]`);
	forkLink!.href = equivalentUrl;
}

void features.add(import.meta.url, {
	include: [
		pageDetect.isForkedRepo,
	],
	// We can't use `exclude` because the header is outside the ajaxed area so it must be manually reset even when the feature doesn't apply there
	init,
});

/*

Test URLs

- Folder: https://github.com/fregante/refined-github/tree/main/.github
- PR list: https://github.com/fregante/refined-github/pulls
- Tags list: https://github.com/fregante/refined-github/tags

*/