summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vedant K <gamemaker0042@gmail.com> 2021-09-26 10:38:53 +0530
committerGravatar GitHub <noreply@github.com> 2021-09-26 12:08:53 +0700
commit17d55029b7224038a2daaecf524ce5ec9f5c9ef6 (patch)
tree0482edd616d4d11663a53aa7a8484eda72108be5
parentfdd2e33dbc61675685eaa914f869c955a305764c (diff)
downloadrefined-github-17d55029b7224038a2daaecf524ce5ec9f5c9ef6.tar.gz
refined-github-17d55029b7224038a2daaecf524ce5ec9f5c9ef6.tar.zst
refined-github-17d55029b7224038a2daaecf524ce5ec9f5c9ef6.zip
Meta: Add an `asLongAs` option to `features.add()` (#4800)
Co-authored-by: yakov116 <16872793+yakov116@users.noreply.github.com> Co-authored-by: Federico Brigante <me@fregante.com>
-rw-r--r--contributing.md10
-rw-r--r--source/features/comment-on-draft-pr-indicator.tsx6
-rw-r--r--source/features/comments-time-machine-links.tsx6
-rw-r--r--source/features/copy-file.tsx6
-rw-r--r--source/features/enable-file-links-in-compare-view.tsx8
-rw-r--r--source/features/fork-source-link-same-view.tsx4
-rw-r--r--source/features/index.tsx24
-rw-r--r--source/features/link-to-github-io.tsx4
-rw-r--r--source/features/no-duplicate-list-update-time.tsx6
-rw-r--r--source/features/no-unnecessary-split-diff-view.tsx6
-rw-r--r--source/features/show-associated-branch-prs-on-fork.tsx6
-rw-r--r--source/features/show-open-prs-of-forks.tsx12
-rw-r--r--source/features/useful-not-found-page.tsx31
-rw-r--r--source/features/view-last-pr-deployment.tsx6
-rw-r--r--source/features/wait-for-build.tsx8
-rw-r--r--source/github-helpers/index.ts13
-rw-r--r--test/helpers.ts48
17 files changed, 139 insertions, 65 deletions
diff --git a/contributing.md b/contributing.md
index 446dbd29..7e4ed623 100644
--- a/contributing.md
+++ b/contributing.md
@@ -64,12 +64,16 @@ void features.add(__filebasename, {
// When pressing the back button, DOM changes and listeners are still there, so normally `init` isn’t called again thanks to an automatic duplicate detection.
// This detection however might cause problems or not work correctly in some cases #3945, so it can be disabled with `false`
deduplicate: false,
+ asLongAs: [
+ pageDetect.isForkedRepo,
+ ],
include: [
- pageDetect.isUserProfile,
- pageDetect.isRepo
+ pageDetect.isSingleFile,
+ pageDetect.isRepoTree,
+ pageDetect.isEditingFile,
],
exclude: [
- pageDetect.isOwnUserProfile
+ pageDetect.isRepoRoot,
],
init
}, {
diff --git a/source/features/comment-on-draft-pr-indicator.tsx b/source/features/comment-on-draft-pr-indicator.tsx
index 34cc9f86..50436a63 100644
--- a/source/features/comment-on-draft-pr-indicator.tsx
+++ b/source/features/comment-on-draft-pr-indicator.tsx
@@ -26,12 +26,12 @@ function init(): void {
}
void features.add(__filebasename, {
+ asLongAs: [
+ pageDetect.isDraftPR,
+ ],
include: [
pageDetect.isPRConversation,
pageDetect.isPRFiles,
],
- exclude: [
- () => !pageDetect.isDraftPR(),
- ],
init,
});
diff --git a/source/features/comments-time-machine-links.tsx b/source/features/comments-time-machine-links.tsx
index 511e7c57..a4bc84cf 100644
--- a/source/features/comments-time-machine-links.tsx
+++ b/source/features/comments-time-machine-links.tsx
@@ -140,14 +140,14 @@ void features.add(__filebasename, {
deduplicate: 'has-rgh-inner',
init,
}, {
+ asLongAs: [
+ () => new URLSearchParams(location.search).has('rgh-link-date'),
+ ],
include: [
pageDetect.is404,
pageDetect.isSingleFile,
pageDetect.isRepoTree,
],
- exclude: [
- () => !new URLSearchParams(location.search).has('rgh-link-date'),
- ],
awaitDomReady: false,
init: showTimemachineBar,
});
diff --git a/source/features/copy-file.tsx b/source/features/copy-file.tsx
index c0b2e9ca..91bd188c 100644
--- a/source/features/copy-file.tsx
+++ b/source/features/copy-file.tsx
@@ -45,13 +45,13 @@ function init(): void {
}
void features.add(__filebasename, {
+ asLongAs: [
+ () => select.exists('table.highlight'), // Rendered page
+ ],
include: [
pageDetect.isSingleFile,
pageDetect.isGist,
],
- exclude: [
- () => !select.exists('table.highlight'), // Rendered page
- ],
deduplicate: '.rgh-copy-file', // #3945
init,
});
diff --git a/source/features/enable-file-links-in-compare-view.tsx b/source/features/enable-file-links-in-compare-view.tsx
index a81d2126..85df3a7a 100644
--- a/source/features/enable-file-links-in-compare-view.tsx
+++ b/source/features/enable-file-links-in-compare-view.tsx
@@ -68,12 +68,12 @@ void features.add(__filebasename, {
],
init,
}, {
+ asLongAs: [
+ // Only enable if you can create a PR or view an existing PR, if you can't you are probably looking at a permalink.
+ () => select.exists('.existing-pull-button, [data-ga-click*="text:Create pull request"]'),
+ ],
include: [
pageDetect.isCompare,
],
- exclude: [
- // Only enable if you can create a PR or view an existing PR, if you cant you are probably looking at a permalink.
- () => !select.exists('.existing-pull-button, [data-ga-click*="text:Create pull request"]'),
- ],
init,
});
diff --git a/source/features/fork-source-link-same-view.tsx b/source/features/fork-source-link-same-view.tsx
index 27697ecd..b74dc074 100644
--- a/source/features/fork-source-link-same-view.tsx
+++ b/source/features/fork-source-link-same-view.tsx
@@ -22,13 +22,15 @@ async function init(): Promise<void> {
}
void features.add(__filebasename, {
+ asLongAs: [
+ pageDetect.isForkedRepo,
+ ],
include: [
pageDetect.isSingleFile,
pageDetect.isRepoTree,
pageDetect.isEditingFile,
],
exclude: [
- () => !pageDetect.isForkedRepo(),
pageDetect.isRepoRoot,
],
deduplicate: false,
diff --git a/source/features/index.tsx b/source/features/index.tsx
index 32ab7e3c..e017197c 100644
--- a/source/features/index.tsx
+++ b/source/features/index.tsx
@@ -8,6 +8,7 @@ import * as pageDetect from 'github-url-detection';
import waitFor from '../helpers/wait-for';
import onNewComments from '../github-events/on-new-comments';
import bisectFeatures from '../helpers/bisect';
+import {shouldFeatureRun} from '../github-helpers';
import optionsStorage, {RGHOptions} from '../options-storage';
import {getLocalHotfixesAsOptions, updateHotfixes} from '../helpers/hotfix';
@@ -34,8 +35,9 @@ interface FeatureLoader extends Partial<InternalRunConfig> {
}
interface InternalRunConfig {
- include: BooleanFunction[];
- exclude: BooleanFunction[];
+ asLongAs: BooleanFunction[] | undefined;
+ include: BooleanFunction[] | undefined;
+ exclude: BooleanFunction[] | undefined;
init: FeatureInit;
deinit?: VoidFunction | VoidFunction[];
additionalListeners: CallerFunction[];
@@ -138,10 +140,9 @@ const globalReady: Promise<RGHOptions> = new Promise(async resolve => {
});
const setupPageLoad = async (id: FeatureID, config: InternalRunConfig): Promise<void> => {
- const {include, exclude, init, deinit, additionalListeners, onlyAdditionalListeners} = config;
+ const {asLongAs, include, exclude, init, deinit, additionalListeners, onlyAdditionalListeners} = config;
- // If every `include` is false and no `exclude` is true, don’t run the feature
- if (include.every(c => !c()) || exclude.some(c => c())) {
+ if (!shouldFeatureRun({asLongAs, include, exclude})) {
return;
}
@@ -192,7 +193,7 @@ function enforceDefaults(
additionalListeners: InternalRunConfig['additionalListeners'],
): void {
for (const [detection, listener] of defaultPairs) {
- if (!include.includes(detection)) {
+ if (!include?.includes(detection)) {
continue;
}
@@ -218,8 +219,9 @@ const add = async (id: FeatureID, ...loaders: FeatureLoader[]): Promise<void> =>
// Input defaults and validation
const {
shortcuts = {},
- include = [() => true], // Default: every page
- exclude = [], // Default: nothing
+ asLongAs,
+ include,
+ exclude,
init,
deinit,
awaitDomReady = true,
@@ -234,13 +236,13 @@ const add = async (id: FeatureID, ...loaders: FeatureLoader[]): Promise<void> =>
}
// 404 pages should only run 404-only features
- if (pageDetect.is404() && !include.includes(pageDetect.is404)) {
+ if (pageDetect.is404() && !include?.includes(pageDetect.is404) && !asLongAs?.includes(pageDetect.is404)) {
continue;
}
enforceDefaults(id, include, additionalListeners);
- const details = {include, exclude, init, deinit, additionalListeners, onlyAdditionalListeners};
+ const details = {asLongAs, include, exclude, init, deinit, additionalListeners, onlyAdditionalListeners};
if (awaitDomReady) {
(async () => {
await domLoaded;
@@ -258,7 +260,7 @@ const add = async (id: FeatureID, ...loaders: FeatureLoader[]): Promise<void> =>
}
};
-const addCssFeature = async (id: FeatureID, include: BooleanFunction[], deduplicate?: false | string): Promise<void> => {
+const addCssFeature = async (id: FeatureID, include: BooleanFunction[] | undefined, deduplicate?: false | string): Promise<void> => {
void add(id, {
include,
deduplicate,
diff --git a/source/features/link-to-github-io.tsx b/source/features/link-to-github-io.tsx
index d3eac55d..2da0559b 100644
--- a/source/features/link-to-github-io.tsx
+++ b/source/features/link-to-github-io.tsx
@@ -42,8 +42,8 @@ async function initRepo(): Promise<void> {
}
void features.add(__filebasename, {
- exclude: [
- () => !getRepo()?.name.endsWith('.github.io'),
+ asLongAs: [
+ () => Boolean(getRepo()?.name.endsWith('.github.io')),
],
init: initRepo,
}, {
diff --git a/source/features/no-duplicate-list-update-time.tsx b/source/features/no-duplicate-list-update-time.tsx
index 8357d1f0..03a2bdcb 100644
--- a/source/features/no-duplicate-list-update-time.tsx
+++ b/source/features/no-duplicate-list-update-time.tsx
@@ -17,11 +17,11 @@ function init(): void {
}
void features.add(__filebasename, {
+ asLongAs: [
+ () => location.search.includes('sort%3Aupdated-'),
+ ],
include: [
pageDetect.isConversationList,
],
- exclude: [
- () => !location.search.includes('sort%3Aupdated-'),
- ],
init,
});
diff --git a/source/features/no-unnecessary-split-diff-view.tsx b/source/features/no-unnecessary-split-diff-view.tsx
index ea9ca151..74b4f54c 100644
--- a/source/features/no-unnecessary-split-diff-view.tsx
+++ b/source/features/no-unnecessary-split-diff-view.tsx
@@ -26,6 +26,10 @@ function init(): void {
}
void features.add(__filebasename, {
+ asLongAs: [
+ // Make sure the class names we need exist on the page #4483
+ () => select.exists('.js-diff-table :is([data-split-side="left"], [data-split-side="right"]):is(.blob-code-addition, .blob-code-deletion)'),
+ ],
include: [
pageDetect.isCommit,
pageDetect.isCompare,
@@ -33,8 +37,6 @@ void features.add(__filebasename, {
],
exclude: [
isUnifiedDiff,
- // Make sure the class names we need exist on the page #4483
- () => !select.exists('.js-diff-table :is([data-split-side="left"], [data-split-side="right"]):is(.blob-code-addition, .blob-code-deletion)'),
],
additionalListeners: [
onDiffFileLoad,
diff --git a/source/features/show-associated-branch-prs-on-fork.tsx b/source/features/show-associated-branch-prs-on-fork.tsx
index 589e9f27..80a9fedf 100644
--- a/source/features/show-associated-branch-prs-on-fork.tsx
+++ b/source/features/show-associated-branch-prs-on-fork.tsx
@@ -105,12 +105,12 @@ async function init(): Promise<void> {
}
void features.add(__filebasename, {
+ asLongAs: [
+ pageDetect.isForkedRepo,
+ ],
include: [
pageDetect.isBranches,
],
- exclude: [
- () => !pageDetect.isForkedRepo(),
- ],
awaitDomReady: false,
init: onetime(init),
});
diff --git a/source/features/show-open-prs-of-forks.tsx b/source/features/show-open-prs-of-forks.tsx
index f4d0d34e..08a10f1c 100644
--- a/source/features/show-open-prs-of-forks.tsx
+++ b/source/features/show-open-prs-of-forks.tsx
@@ -89,21 +89,21 @@ async function initDeleteHint(): Promise<void | false> {
}
void features.add(__filebasename, {
+ asLongAs: [
+ pageDetect.isForkedRepo,
+ ],
include: [
pageDetect.isRepo,
],
- exclude: [
- () => !pageDetect.isForkedRepo(),
- ],
awaitDomReady: false,
init: initHeadHint,
}, {
+ asLongAs: [
+ pageDetect.isForkedRepo,
+ ],
include: [
pageDetect.isRepoMainSettings,
],
- exclude: [
- () => !pageDetect.isForkedRepo(),
- ],
awaitDomReady: false,
init: initDeleteHint,
});
diff --git a/source/features/useful-not-found-page.tsx b/source/features/useful-not-found-page.tsx
index bebbe1e4..fddc3917 100644
--- a/source/features/useful-not-found-page.tsx
+++ b/source/features/useful-not-found-page.tsx
@@ -143,18 +143,9 @@ async function showAlternateLink(): Promise<void> {
);
}
-function init(): false | void {
- const parts = parseCurrentURL();
- if (parts.length < 2) {
- return false;
- }
-
- void showMissingPart();
-
- if (['tree', 'blob', 'edit'].includes(parts[2])) {
- void showDefaultBranchLink();
- void showAlternateLink();
- }
+function init(): void {
+ void showDefaultBranchLink();
+ void showAlternateLink();
}
async function initPRCommit(): Promise<void | false> {
@@ -169,10 +160,22 @@ async function initPRCommit(): Promise<void | false> {
);
}
-void features.add(__filebasename, {
- include: [
+void features.add(__filebasename, {
+ asLongAs: [
+ pageDetect.is404,
+ () => parseCurrentURL().length > 1,
+ ],
+ init: showMissingPart,
+},
+{
+ asLongAs: [
pageDetect.is404,
],
+ include: [
+ pageDetect.isSingleFile,
+ pageDetect.isRepoTree,
+ pageDetect.isEditingFile,
+ ],
init: onetime(init),
}, {
include: [
diff --git a/source/features/view-last-pr-deployment.tsx b/source/features/view-last-pr-deployment.tsx
index b6b983f4..f90e7fe4 100644
--- a/source/features/view-last-pr-deployment.tsx
+++ b/source/features/view-last-pr-deployment.tsx
@@ -27,12 +27,12 @@ function init(): void {
}
void features.add(__filebasename, {
+ asLongAs: [
+ () => select.exists(deploymentSelector),
+ ],
include: [
pageDetect.isPRConversation,
],
- exclude: [
- () => !select.exists(deploymentSelector),
- ],
additionalListeners: [
onConversationHeaderUpdate,
],
diff --git a/source/features/wait-for-build.tsx b/source/features/wait-for-build.tsx
index ca1edb1d..f345119a 100644
--- a/source/features/wait-for-build.tsx
+++ b/source/features/wait-for-build.tsx
@@ -99,12 +99,12 @@ function init(): void {
}
void features.add(__filebasename, {
+ asLongAs: [
+ // The user cannot merge
+ () => select.exists('[data-details-container=".js-merge-pr"]:not(:disabled)'),
+ ],
include: [
pageDetect.isPRConversation,
],
- exclude: [
- // The user cannot merge
- () => !select.exists('[data-details-container=".js-merge-pr"]:not(:disabled)'),
- ],
init,
});
diff --git a/source/github-helpers/index.ts b/source/github-helpers/index.ts
index 6f24a6b1..70ad2707 100644
--- a/source/github-helpers/index.ts
+++ b/source/github-helpers/index.ts
@@ -116,3 +116,16 @@ export async function isPermalink(): Promise<boolean> {
export function isNotRefinedGitHubRepo(): boolean {
return !location.pathname.startsWith('/sindresorhus/refined-github/');
}
+
+export function shouldFeatureRun({
+ /** Every condition must be true */
+ asLongAs = [() => true],
+
+ /** At least one condition must be true */
+ include = [() => true],
+
+ /** No conditions must be true */
+ exclude = [() => false],
+}): boolean {
+ return asLongAs.every(c => c()) && include.some(c => c()) && exclude.every(c => !c());
+}
diff --git a/test/helpers.ts b/test/helpers.ts
index 95d30b0e..41d8fbdf 100644
--- a/test/helpers.ts
+++ b/test/helpers.ts
@@ -8,6 +8,7 @@ import {
parseTag,
compareNames,
getLatestVersionTag,
+ shouldFeatureRun,
} from '../source/github-helpers';
test('getConversationNumber', t => {
@@ -135,3 +136,50 @@ test('getLatestVersionTag', t => {
'v1.0-1',
]), 'lol v0.0.0', 'Non-version tags should short-circuit the sorting and return the first tag');
});
+
+test('shouldFeatureRun', t => {
+ const yes = (): boolean => true;
+ const no = (): boolean => false;
+ const yesYes = [yes, yes];
+ const yesNo = [yes, no];
+ const noNo = [no, no];
+
+ t.true(shouldFeatureRun({}), 'A lack of conditions should mean "run everywhere"');
+
+ t.false(shouldFeatureRun({
+ asLongAs: yesNo,
+ }), 'Every `asLongAs` should be true to run');
+
+ t.false(shouldFeatureRun({
+ asLongAs: yesNo,
+ include: [yes],
+ }), 'Every `asLongAs` should be true to run, regardless of `include`');
+
+ t.false(shouldFeatureRun({
+ include: noNo,
+ }), 'At least one `include` should be true to run');
+
+ t.true(shouldFeatureRun({
+ include: yesNo,
+ }), 'If one `include` is true, then it should run');
+
+ t.false(shouldFeatureRun({
+ exclude: yesNo,
+ }), 'If any `exclude` is true, then it should not run');
+
+ t.false(shouldFeatureRun({
+ include: [yes],
+ exclude: yesNo,
+ }), 'If any `exclude` is true, then it should not run, regardless of `include`');
+
+ t.false(shouldFeatureRun({
+ asLongAs: [yes],
+ exclude: yesNo,
+ }), 'If any `exclude` is true, then it should not run, regardless of `asLongAs`');
+
+ t.false(shouldFeatureRun({
+ asLongAs: [yes],
+ include: yesYes,
+ exclude: yesNo,
+ }), 'If any `exclude` is true, then it should not run, regardless of `asLongAs` and `include`');
+});