Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lint #3684

Merged
merged 17 commits into from Oct 26, 2020
Merged

Lint #3684

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24,360 changes: 10,926 additions & 13,434 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Expand Up @@ -104,12 +104,12 @@
"stylelint-config-xo": "^0.20.0",
"ts-node": "^9.0.0",
"type-fest": "^0.18.0",
"typescript": "^4.0.2",
"typescript": "^4.0.3",
"web-ext": "^5.0.0",
"web-ext-submit": "^5.0.2",
"webpack": "^5.1.0",
"webpack-cli": "^4.0.0",
"xo": "^0.33.0"
"webpack": "^5.2.0",
"webpack-cli": "^4.1.0",
"xo": "^0.34.1"
},
"webExt": {
"sourceDir": "distribution",
Expand Down
2 changes: 1 addition & 1 deletion source/features/bugs-tab.tsx
Expand Up @@ -94,7 +94,7 @@ async function init(): Promise<void | false> {
// Update bugs count
try {
bugsCounter.textContent = numberFormatter.format(await countPromise);
} catch (error) {
} catch (error: unknown) {
bugsCounter.remove();
features.error(__filebasename, error);
}
Expand Down
3 changes: 1 addition & 2 deletions source/features/bypass-checks.tsx
Expand Up @@ -4,7 +4,6 @@ import * as pageDetect from 'github-url-detection';

import features from '.';
import * as api from '../github-helpers/api';
import {getRepoURL} from '../github-helpers';

async function bypass(detailsLink: HTMLAnchorElement): Promise<void> {
const runId = pageDetect.isActionJobRun(detailsLink) ?
Expand All @@ -15,7 +14,7 @@ async function bypass(detailsLink: HTMLAnchorElement): Promise<void> {
return;
}

const directLink = await api.v3(`repos/${getRepoURL()}/check-runs/${runId}`);
const directLink = await api.v3(`check-runs/${runId}`);
detailsLink.href = directLink.details_url;
}

Expand Down
4 changes: 2 additions & 2 deletions source/features/clone-branch.tsx
Expand Up @@ -10,7 +10,7 @@ import * as textFieldEdit from 'text-field-edit';
import features from '.';
import * as api from '../github-helpers/api';
import LoadingIcon from '../github-helpers/icon-loading';
import {getRepoURL, getRepoGQL} from '../github-helpers';
import {getRepoGQL} from '../github-helpers';

const getBranchBaseSha = async (branchName: string): Promise<string> => {
const {repository} = await api.v4(`
Expand All @@ -27,7 +27,7 @@ const getBranchBaseSha = async (branchName: string): Promise<string> => {
};

async function createBranch(newBranchName: string, baseSha: string): Promise<true | string> {
const response = await api.v3(`repos/${getRepoURL()}/git/refs`, {
const response = await api.v3('git/refs', {
method: 'POST',
body: {
sha: baseSha,
Expand Down
5 changes: 2 additions & 3 deletions source/features/convert-release-to-draft.tsx
Expand Up @@ -6,14 +6,13 @@ import * as pageDetect from 'github-url-detection';
import features from '.';
import * as api from '../github-helpers/api';
import LoadingIcon from '../github-helpers/icon-loading';
import {getRepoURL} from '../github-helpers';

async function convertToDraft({delegateTarget: draftButton}: delegate.Event<MouseEvent, HTMLButtonElement>): Promise<void> {
try {
draftButton.append(<LoadingIcon className="ml-2 v-align-text-bottom" width={16}/>);

const tagName = location.pathname.split('/').pop()!;
const release = await api.v3(`repos/${getRepoURL()}/releases/tags/${tagName}`);
const release = await api.v3(`releases/tags/${tagName}`);
await api.v3(release.url, {
method: 'PATCH',
body: {
Expand All @@ -22,7 +21,7 @@ async function convertToDraft({delegateTarget: draftButton}: delegate.Event<Mous
});

select('.BtnGroup a[href*="releases/edit"]')!.click(); // Visit "Edit release" page
} catch (error) {
} catch (error: unknown) {
draftButton.textContent = 'Error. Check console or retry';
features.error(__filebasename, error);
}
Expand Down
4 changes: 2 additions & 2 deletions source/features/deep-reblame.tsx
Expand Up @@ -75,9 +75,9 @@ async function redirectToBlameCommit(event: delegate.Event<MouseEvent, HTMLAncho
blameUrl.branch = await getPullRequestBlameCommit(prCommit, prNumber, blameUrl.filePath);
blameUrl.hash = 'L' + select('.js-line-number', blameHunk)!.textContent!;
location.href = String(blameUrl);
} catch (error) {
} catch (error: unknown) {
yakov116 marked this conversation as resolved.
Show resolved Hide resolved
spinner.replaceWith(<VersionIcon/>);
alert(error.message);
alert((error as Error).message);
}
}

Expand Down
6 changes: 2 additions & 4 deletions source/features/enable-file-links-in-compare-view.tsx
Expand Up @@ -6,17 +6,15 @@ import * as pageDetect from 'github-url-detection';

import features from '.';
import GitHubURL from '../github-helpers/github-url';
import {getCurrentBranch} from '../github-helpers';
import {getCurrentBranch, getPRRepositoryInfo} from '../github-helpers';

/** Rebuilds the "View file" link because it points to the base repo and to the commit, instead of the head repo and its branch */
function handlePRMenuOpening({delegateTarget: dropdown}: delegate.Event): void {
dropdown.classList.add('rgh-actionable-link'); // Mark this as processed

const [, user, repository] = select<HTMLAnchorElement>('.commit-ref.head-ref a')!.pathname.split('/', 3);
const filePath = dropdown.closest('[data-path]')!.getAttribute('data-path')!;

const viewFile = select<HTMLAnchorElement>('[data-ga-click^="View file"]', dropdown)!;
viewFile.pathname = [user, repository, 'blob', getCurrentBranch()!, filePath].join('/'); // Do not replace with `GitHubURL` #3152 #3111 #2595
viewFile.pathname = [getPRRepositoryInfo().url!, 'blob', getCurrentBranch()!, filePath].join('/'); // Do not replace with `GitHubURL` #3152 #3111 #2595
}

function handleCompareMenuOpening({delegateTarget: dropdown}: delegate.Event): void {
Expand Down
3 changes: 1 addition & 2 deletions source/features/follow-file-renames.tsx
Expand Up @@ -5,7 +5,6 @@ import * as pageDetect from 'github-url-detection';
import features from '.';
import * as api from '../github-helpers/api';
import GitHubURL from '../github-helpers/github-url';
import {getRepoURL} from '../github-helpers';

interface File {
previous_filename: string;
Expand All @@ -15,7 +14,7 @@ interface File {

async function findRename(lastCommitOnPage: string): Promise<File[]> {
// API v4 doesn't support it: https://github.community/t5/GitHub-API-Development-and/What-is-the-corresponding-object-in-GraphQL-API-v4-for-patch/m-p/14502?collapse_discussion=true&filter=location&location=board:api&q=files%20changed%20commit&search_type=thread
const {files} = await api.v3(`repos/${getRepoURL()}/commits/${lastCommitOnPage}`);
const {files} = await api.v3(`commits/${lastCommitOnPage}`);
return files;
}

Expand Down
6 changes: 3 additions & 3 deletions source/features/index.tsx
Expand Up @@ -43,12 +43,12 @@ interface InternalRunConfig {

let log: typeof console.log;

function logError(id: FeatureID, error: Error | string, ...extras: unknown[]): void {
function logError(id: FeatureID, error: Error | string | unknown, ...extras: unknown[]): void {
if (error instanceof TypeError && error.message === 'Object(...)(...) is null') {
error.message = 'The element wasn’t found, the selector needs to be updated.';
}

const message = typeof error === 'string' ? error : error.message;
const message = error instanceof Error ? error.message : String(error);

if (message.includes('token')) {
console.log(`ℹ️ Refined GitHub → ${id} →`, message);
Expand Down Expand Up @@ -126,7 +126,7 @@ const setupPageLoad = async (id: FeatureID, config: InternalRunConfig): Promise<
if (await init() !== false && id !== __filebasename) {
log('✅', id);
}
} catch (error) {
} catch (error: unknown) {
logError(id, error);
}

Expand Down
2 changes: 1 addition & 1 deletion source/features/mark-private-orgs.tsx
Expand Up @@ -12,7 +12,7 @@ import {getUsername} from '../github-helpers';
const getPublicOrganizationsNames = cache.function(async (username: string): Promise<string[]> => {
// API v4 seems to *require* `org:read` permission AND it includes private organizations as well, which defeats the purpose. There's no way to filter them.
// GitHub's API explorer inexplicably only includes public organizations.
const response = await api.v3(`users/${username}/orgs`);
const response = await api.v3(`/users/${username}/orgs`);
return response.map((organization: AnyObject) => organization.login);
}, {
maxAge: {days: 10},
Expand Down
3 changes: 1 addition & 2 deletions source/features/new-repo-disable-projects-and-wikis.tsx
Expand Up @@ -6,12 +6,11 @@ import * as pageDetect from 'github-url-detection';

import features from '.';
import * as api from '../github-helpers/api';
import {getRepoURL} from '../github-helpers';

async function disableWikiAndProjects(): Promise<void> {
delete sessionStorage.rghNewRepo;

await api.v3(`repos/${getRepoURL()}`, {
await api.v3('', {
method: 'PATCH',
body: {
has_projects: false,
Expand Down
4 changes: 1 addition & 3 deletions source/features/release-download-count.tsx
Expand Up @@ -12,9 +12,7 @@ interface Asset {
name: string;
downloadCount: number;
}
interface Tag {
[key: string]: Asset[];
}
type Tag = Record<string, Asset[]>;
async function getAssetsForTag(tags: string[]): Promise<Tag> {
const {repository} = await api.v4(`
repository(${getRepoGQL()}) {
Expand Down
6 changes: 3 additions & 3 deletions source/features/remove-label-faster.tsx
Expand Up @@ -9,7 +9,7 @@ import * as pageDetect from 'github-url-detection';

import features from '.';
import * as api from '../github-helpers/api';
import {getRepoURL, getConversationNumber} from '../github-helpers';
import {getConversationNumber} from '../github-helpers';

const canNotEditLabels = onetime((): boolean => !select.exists('.sidebar-labels .octicon-gear'));

Expand All @@ -19,7 +19,7 @@ async function removeLabelButtonClickHandler(event: delegate.Event<MouseEvent, H
const removeLabelButton = event.delegateTarget;

removeLabelButton.disabled = true;
await api.v3(`repos/${getRepoURL()}/issues/${getConversationNumber()!}/labels/${removeLabelButton.dataset.name!}`, {
await api.v3(`issues/${getConversationNumber()!}/labels/${removeLabelButton.dataset.name!}`, {
method: 'DELETE'
});

Expand Down Expand Up @@ -47,7 +47,7 @@ async function init(): Promise<void> {
aria-label="Remove this label"
className="btn-link tooltipped tooltipped-nw rgh-remove-label-faster"
data-name={label.dataset.name}
style={/* eslint-disable-line @typescript-eslint/consistent-type-assertions */{
style={{
'--rgh-remove-label-faster-color': label.style.backgroundColor
} as React.CSSProperties}
>
Expand Down
7 changes: 3 additions & 4 deletions source/features/restore-file.tsx
Expand Up @@ -8,7 +8,7 @@ import features from '.';
import * as api from '../github-helpers/api';
import fetchDom from '../helpers/fetch-dom';
import postForm from '../helpers/post-form';
import {getConversationNumber, getRepoGQL, getCurrentBranch} from '../github-helpers';
import {getConversationNumber, getRepoGQL, getCurrentBranch, getPRRepositoryInfo} from '../github-helpers';

function showError(menuItem: HTMLButtonElement, error: string): void {
menuItem.disabled = true;
Expand Down Expand Up @@ -50,8 +50,7 @@ async function commitFileContent(menuItem: Element, content: string, filePath: s
// Check if file was deleted by PR
if (menuItem.closest('[data-file-deleted="true"]')) {
menuItem.textContent = 'Undeleting…';
const [, user, repository] = select<HTMLAnchorElement>('.commit-ref.head-ref a')!.pathname.split('/', 3);
pathname = `/${user}/${repository}/new/${getCurrentBranch()!}?filename=${filePath}`;
pathname = `/${getPRRepositoryInfo().url!}/new/${getCurrentBranch()!}?filename=${filePath}`;
} else {
menuItem.textContent = 'Committing…';
}
Expand Down Expand Up @@ -99,7 +98,7 @@ async function handleRestoreFileClick(event: delegate.Event<MouseEvent, HTMLButt

// Hide file from view
menuItem.closest('.file')!.remove();
} catch (error) {
} catch (error: unknown) {
showError(menuItem, 'Restore failed. See console for details');
features.error(__filebasename, error);
}
Expand Down
2 changes: 1 addition & 1 deletion source/features/submit-review-as-single-comment.tsx
Expand Up @@ -91,7 +91,7 @@ async function handleSubmitSingle(event: delegate.Event): Promise<void> {
// Wait for the comment to be added
await observeOneMutation(lineBeingCommentedOn.parentElement!);
commentForm.hidden = false;
} catch (error) {
} catch (error: unknown) {
commentForm.hidden = false;

// Place comment in console to allow recovery
Expand Down
6 changes: 2 additions & 4 deletions source/features/tags-on-commits-list.tsx
Expand Up @@ -9,9 +9,7 @@ import * as api from '../github-helpers/api';
import {getCommitHash} from './mark-merge-commits-in-list';
import {buildRepoURL, getRepoURL, getRepoGQL} from '../github-helpers';

interface CommitTags {
[name: string]: string[];
}
type CommitTags = Record<string, string[]>;

interface BaseTarget {
commitResourcePath: string;
Expand Down Expand Up @@ -125,7 +123,7 @@ async function init(): Promise<void | false> {
'.js-commits-list-item'
]);
const lastCommitOnPage = getCommitHash(commitsOnPage[commitsOnPage.length - 1]);
let cached = await cache.get<{[commit: string]: string[]}>(cacheKey) ?? {};
let cached = await cache.get<Record<string, string[]>>(cacheKey) ?? {};
const commitsWithNoTags = [];
for (const commit of commitsOnPage) {
const targetCommit = getCommitHash(commit);
Expand Down
6 changes: 1 addition & 5 deletions source/features/toggle-files-button.tsx
Expand Up @@ -38,11 +38,7 @@ function addButton(): void {

async function toggleHandler(): Promise<void> {
const isHidden = select('.repository-content')!.classList.toggle('rgh-files-hidden');
if (isHidden) {
await cache.set(cacheKey, true);
} else {
await cache.delete(cacheKey);
}
await (isHidden ? cache.set(cacheKey, true) : cache.delete(cacheKey));
}

async function init(): Promise<void> {
Expand Down
6 changes: 3 additions & 3 deletions source/features/update-pr-from-base-branch.tsx
Expand Up @@ -7,7 +7,7 @@ import * as pageDetect from 'github-url-detection';
import features from '.';
import * as api from '../github-helpers/api';
import observeElement from '../helpers/simplified-element-observer';
import {getRepoURL, getConversationNumber} from '../github-helpers';
import {getConversationNumber} from '../github-helpers';

let observer: MutationObserver;

Expand All @@ -19,7 +19,7 @@ function getBranches(): {base: string; head: string} {
}

async function mergeBranches(): Promise<AnyObject> {
return api.v3(`repos/${getRepoURL()}/pulls/${getConversationNumber()!}/update-branch`, {
return api.v3(`pulls/${getConversationNumber()!}/update-branch`, {
method: 'PUT',
headers: {
Accept: 'application/vnd.github.lydian-preview+json'
Expand Down Expand Up @@ -85,7 +85,7 @@ async function addButton(): Promise<void> {
return;
}

const {status} = await api.v3(`repos/${getRepoURL()}/compare/${base}...${head}`);
const {status} = await api.v3(`compare/${base}...${head}`);
if (status !== 'diverged') {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion source/features/user-local-time.tsx
Expand Up @@ -34,7 +34,7 @@ async function loadCommitPatch(commitUrl: string): Promise<string> {
}

const getLastCommitDate = cache.function(async (login: string): Promise<string | false> => {
for await (const page of api.v3paginated(`users/${login}/events`)) {
for await (const page of api.v3paginated(`/users/${login}/events`)) {
for (const event of page as any) {
if (event.type !== 'PushEvent') {
continue;
Expand Down
8 changes: 5 additions & 3 deletions source/github-helpers/api.ts
Expand Up @@ -6,7 +6,8 @@ next to the name of the feature that caused them.
Usage:

import * as api from '../github-helpers/api';
const user = await api.v3(`users/${username}`);
const user = await api.v3(`/users/${username}`);
const repositoryCommits = await api.v3('commits'); // Without a leading `/`, this is equivalent to `/repo/$current-repository/commits`
const data = await api.v4('{user(login: "user") {name}}');

Returns:
Expand All @@ -29,6 +30,7 @@ import * as pageDetect from 'github-url-detection';
import {JsonObject, AsyncReturnType} from 'type-fest';

import optionsStorage from '../options-storage';
import {getRepoURL} from '.';

interface JsonError {
message: string;
Expand Down Expand Up @@ -102,8 +104,8 @@ export const v3 = mem(async (
const {ignoreHTTPStatus, method, body, headers, json} = {...v3defaults, ...options};
const {personalToken} = await settings;

if (query.startsWith('/')) {
throw new TypeError('The query parameter must not start with a slash.');
if (!query.startsWith('https')) {
query = query.startsWith('/') ? query.slice(1) : 'repos/' + getRepoURL() + '/' + query;
}

const url = new URL(query, api3);
Expand Down
10 changes: 8 additions & 2 deletions source/github-helpers/index.ts
Expand Up @@ -39,7 +39,7 @@ export const getCurrentBranch = (): string | undefined => {

export const isFirefox = navigator.userAgent.includes('Firefox/');

export const getRepoURL = (): string => location.pathname.slice(1).split('/', 2).join('/').toLowerCase();
export const getRepoURL = (): string => getRepositoryInfo().url!.toLowerCase();

// The type requires at least one parameter https://stackoverflow.com/a/49910890
export const buildRepoURL = (...pathParts: Array<string | number> & {0: string}): string => {
Expand All @@ -62,10 +62,16 @@ export const getRepoGQL = (): string => {
export interface RepositoryInfo {
owner: string;
name: string;
url: string;
}
export const getRepositoryInfo = (repoUrl: string = location.pathname.slice(1)): Partial<RepositoryInfo> => {
const [owner, name] = repoUrl.split('/', 2);
return {owner, name};
return {owner, name, url: owner + '/' + name};
};

export const getPRRepositoryInfo = (): Partial<RepositoryInfo> => {
const {pathname} = select<HTMLAnchorElement>('.commit-ref.head-ref a')!;
return getRepositoryInfo(pathname.slice(1));
};

export function getForkedRepo(): string | undefined {
Expand Down
2 changes: 1 addition & 1 deletion source/github-helpers/parse-backticks.tsx
Expand Up @@ -10,7 +10,7 @@ export function getParsedBackticksParts(string: string): string[] {
export default function parseBackticks(description: string): DocumentFragment {
const fragment = new DocumentFragment();
for (const [index, text] of getParsedBackticksParts(description).entries()) {
if (index % 2 && text.length >= 1) {
if (index % 2 && text.length > 0) {
fregante marked this conversation as resolved.
Show resolved Hide resolved
// `span.sr-only` keeps the backticks copy-pastable but invisible
fragment.append(
<span className="sr-only">`</span>,
Expand Down