diff options
author | 2021-09-26 10:38:53 +0530 | |
---|---|---|
committer | 2021-09-26 12:08:53 +0700 | |
commit | 17d55029b7224038a2daaecf524ce5ec9f5c9ef6 (patch) | |
tree | 0482edd616d4d11663a53aa7a8484eda72108be5 | |
parent | fdd2e33dbc61675685eaa914f869c955a305764c (diff) | |
download | refined-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.md | 10 | ||||
-rw-r--r-- | source/features/comment-on-draft-pr-indicator.tsx | 6 | ||||
-rw-r--r-- | source/features/comments-time-machine-links.tsx | 6 | ||||
-rw-r--r-- | source/features/copy-file.tsx | 6 | ||||
-rw-r--r-- | source/features/enable-file-links-in-compare-view.tsx | 8 | ||||
-rw-r--r-- | source/features/fork-source-link-same-view.tsx | 4 | ||||
-rw-r--r-- | source/features/index.tsx | 24 | ||||
-rw-r--r-- | source/features/link-to-github-io.tsx | 4 | ||||
-rw-r--r-- | source/features/no-duplicate-list-update-time.tsx | 6 | ||||
-rw-r--r-- | source/features/no-unnecessary-split-diff-view.tsx | 6 | ||||
-rw-r--r-- | source/features/show-associated-branch-prs-on-fork.tsx | 6 | ||||
-rw-r--r-- | source/features/show-open-prs-of-forks.tsx | 12 | ||||
-rw-r--r-- | source/features/useful-not-found-page.tsx | 31 | ||||
-rw-r--r-- | source/features/view-last-pr-deployment.tsx | 6 | ||||
-rw-r--r-- | source/features/wait-for-build.tsx | 8 | ||||
-rw-r--r-- | source/github-helpers/index.ts | 13 | ||||
-rw-r--r-- | test/helpers.ts | 48 |
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`'); +}); |