summaryrefslogtreecommitdiff
path: root/source/features/repo-age.tsx
blob: ffedcd559b088487bb2828bd3a64b69e087071f3 (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import twas from 'twas';
import React from 'dom-chef';
import cache from 'webext-storage-cache';
import select from 'select-dom';
import RepoIcon from 'octicon/repo.svg';
import elementReady from 'element-ready';
import features from '../libs/features';
import * as pageDetect from '../libs/page-detect';
import fetchDom from '../libs/fetch-dom';
import {getRepoURL, looseParseInt} from '../libs/utils';

const dateFormatter = new Intl.DateTimeFormat('en-US', {
	year: 'numeric',
	month: 'long',
	day: 'numeric'
});

const getFirstCommitDate = cache.function(async (): Promise<string | undefined> => {
	const commitInfo = await elementReady<HTMLAnchorElement | HTMLScriptElement>('a.commit-tease-sha, include-fragment.commit-tease');
	const commitUrl = commitInfo instanceof HTMLAnchorElement ? commitInfo.href : commitInfo!.src;
	const commitSha = commitUrl.split('/').pop()!;

	const commitsCount = looseParseInt(select('li.commits .num')!.textContent!);

	// Returning undefined will make sure that it is not cached. It will check again for commits on the next load.
	// Reference: https://github.com/fregante/webext-storage-cache/#getter
	if (commitsCount === 0) {
		return;
	}

	if (commitsCount === 1) {
		return select('.commit-tease-sha + span relative-time')!.attributes.datetime.value;
	}

	const relativeTime = await fetchDom(
		`${getRepoURL()}/commits?after=${commitSha}+${commitsCount - 2}`,
		'.commit-meta relative-time'
	);

	return relativeTime!.attributes.datetime.value;
}, {
	cacheKey: () => __filebasename + ':' + getRepoURL()
});

async function init(): Promise<void> {
	const firstCommitDate = await getFirstCommitDate();

	if (!firstCommitDate) {
		return;
	}

	const date = new Date(firstCommitDate);

	// `twas` could also return `an hour ago` or `just now`
	const [value, unit] = twas(date.getTime())
		.replace('just now', '1 second')
		.replace(/^an?/, '1')
		.split(' ');

	const element = (
		<li className="text-gray" title={`First commit dated ${dateFormatter.format(date)}`}>
			<RepoIcon/> <span className="num text-emphasized">{value}</span> {unit} old
		</li>
	);

	await elementReady('.overall-summary + *');
	const license = select('.numbers-summary .octicon-law');
	if (license) {
		license.closest('li')!.before(element);
	} else {
		select('.numbers-summary')!.append(element);
	}
}

features.add({
	id: __filebasename,
	description: 'Adds the age of the repository to the stats/numbers bar',
	screenshot: 'https://user-images.githubusercontent.com/3848317/69256318-95e6af00-0bb9-11ea-84c8-c6996d39da80.png'
}, {
	include: [
		pageDetect.isRepoRoot
	],
	waitForDomReady: false,
	init
});