From 4a7493ee410954779638fceac1bc512bc5755e92 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Mon, 7 Jan 2019 16:25:43 +0700 Subject: [PATCH 01/22] Move loading logic into each feature --- package-lock.json | 29 +- package.json | 1 + source/content.js | 407 ++++-------------- source/features/add-branch-buttons.js | 14 +- source/features/add-ci-link.js | 15 +- source/features/add-commented-menu-item.js | 20 +- .../features/add-create-release-shortcut.js | 12 +- source/features/add-delete-fork-link.js | 36 +- ...add-diff-view-without-whitespace-option.js | 14 +- source/features/add-download-folder-button.js | 39 +- source/features/add-filter-comments-by-you.js | 16 +- source/features/add-gists-link-to-profile.js | 18 +- source/features/add-jump-to-bottom-link.js | 18 +- ...dd-keyboard-shortcuts-to-comment-fields.js | 8 +- source/features/add-milestone-navigation.js | 16 +- source/features/add-patch-diff-links.js | 16 +- source/features/add-profile-hotkey.js | 11 +- source/features/add-pull-request-hotkey.js | 12 +- source/features/add-quick-review-buttons.js | 14 +- source/features/add-releases-tab.js | 18 +- source/features/add-selection-in-new-tab.js | 8 +- source/features/add-star-repo-hotkey.js | 12 +- .../features/add-swap-branches-on-compare.js | 17 +- .../add-time-machine-links-to-comments.js | 17 +- source/features/add-title-to-emojis.js | 9 +- source/features/add-toggle-files-button.js | 14 +- source/features/add-trending-menu-item.js | 19 +- source/features/add-yours-menu-item.js | 17 +- source/features/batch-open-issues.js | 20 +- source/features/bypass-checks-travis.js | 12 +- source/features/close-out-of-view-modals.js | 8 +- source/features/copy-file.js | 13 +- source/features/copy-on-y.js | 24 +- source/features/embed-gist-inline.js | 15 +- source/features/exclude-filter-shortcut.js | 14 +- source/features/extend-diff-expander.js | 12 +- source/features/extend-status-labels.js | 21 +- .../features/fix-squash-and-merge-message.js | 14 +- source/features/fix-squash-and-merge-title.js | 14 +- source/features/focus-confirmation-buttons.js | 8 +- source/features/hide-comments-faster.js | 20 +- source/features/hide-empty-meta.js | 21 +- source/features/hide-inactive-deployments.js | 32 +- .../features/hide-issue-list-autocomplete.js | 12 +- .../hide-navigation-hover-highlight.js | 9 +- source/features/hide-own-stars.js | 12 +- source/features/hide-readme-header.js | 10 +- source/features/hide-useless-comments.js | 17 +- .../features/hide-useless-newsfeed-events.js | 14 +- .../highlight-closing-prs-in-open-issues.js | 13 +- source/features/improve-shortcut-help.js | 11 +- source/features/infinite-scroll.js | 19 +- source/features/linkify-branch-refs.js | 13 +- source/features/linkify-commit-sha.js | 12 +- source/features/linkify-issues-in-titles.js | 13 +- source/features/linkify-urls-in-code.js | 15 +- .../make-discussion-sidebar-sticky.js | 26 +- source/features/make-headers-sticky.js | 12 +- source/features/mark-merge-commits-in-list.js | 12 +- source/features/mark-private-orgs.js | 29 +- source/features/mark-unread.js | 90 ++-- source/features/monospace-textareas.js | 11 +- source/features/more-dropdown.js | 23 +- ...ve-marketplace-link-to-profile-dropdown.js | 22 +- .../navigate-pages-with-arrow-keys.js | 9 +- source/features/op-labels.js | 27 +- source/features/open-all-notifications.js | 19 +- source/features/open-ci-details-in-new-tab.js | 12 +- .../preserve-whitespace-option-in-nav.js | 18 +- source/features/prev-next-commit-buttons.js | 17 +- source/features/reactions-avatars.js | 15 +- source/features/remove-projects-tab.js | 14 +- source/features/remove-upload-files-button.js | 27 +- source/features/scroll-to-top-on-collapse.js | 14 +- ...et-default-repositories-type-to-sources.js | 17 +- source/features/shorten-links.js | 9 +- source/features/show-followers-you-know.js | 25 +- source/features/show-names.js | 21 +- ...-recently-pushed-branches-on-more-pages.js | 20 +- source/features/show-user-top-repositories.js | 20 +- source/features/sort-issues-by-update-time.js | 9 +- .../sort-milestones-by-closest-due-date.js | 12 +- source/features/upload-button.js | 34 +- source/features/useful-not-found-page.js | 14 +- .../features/user-profile-follower-badge.js | 30 +- source/features/wait-for-build.js | 53 ++- source/libs/features.js | 153 +++++++ source/libs/on-new-comments.js | 16 +- source/libs/utils.js | 56 --- 89 files changed, 1398 insertions(+), 753 deletions(-) create mode 100644 source/libs/features.js diff --git a/package-lock.json b/package-lock.json index 8f10a62717e..6b95575be73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8380,6 +8380,14 @@ "map-age-cleaner": "^0.1.1", "mimic-fn": "^1.0.0", "p-is-promise": "^1.1.0" + }, + "dependencies": { + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + } } }, "memory-fs": { @@ -9377,10 +9385,9 @@ "dev": true }, "p-is-promise": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==" }, "p-limit": { "version": "1.3.0", @@ -9565,7 +9572,7 @@ }, "path-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -12801,7 +12808,7 @@ }, "tty-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, @@ -13292,7 +13299,7 @@ }, "vm-browserify": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { @@ -13621,6 +13628,14 @@ "map-age-cleaner": "^0.1.1", "mimic-fn": "^1.0.0", "p-is-promise": "^1.1.0" + }, + "dependencies": { + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + } } }, "os-locale": { diff --git a/package.json b/package.json index bb4a8cb5028..f7a3a529149 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "linkify-issues": "^1.3.0", "linkify-urls": "^2.2.0", "onetime": "^2.0.1", + "p-is-promise": "^2.0.0", "select-dom": "^4.1.3", "shorten-repo-url": "^1.5.0", "storm-textarea": "2.0.1", diff --git a/source/content.js b/source/content.js index 71249ab2f03..ebbfe8b7d80 100644 --- a/source/content.js +++ b/source/content.js @@ -1,317 +1,100 @@ -import 'webext-dynamic-content-scripts'; import {h} from 'dom-chef'; import select from 'select-dom'; -import domLoaded from 'dom-loaded'; - -import markUnread from './features/mark-unread'; -import addOpenAllNotificationsButton from './features/open-all-notifications'; -import batchOpenIssues from './features/batch-open-issues'; -import addUploadBtn from './features/upload-button'; -import enableCopyOnY from './features/copy-on-y'; -import addReactionParticipants from './features/reactions-avatars'; -import showRealNames from './features/show-names'; -import addPrevNextButtonsToPRs from './features/prev-next-commit-buttons'; -import addFileCopyButton from './features/copy-file'; -import linkifyCode from './features/linkify-urls-in-code'; -import infiniteScroll from './features/infinite-scroll'; -import addOPLabels from './features/op-labels'; -import addMoreDropdown from './features/more-dropdown'; -import addReleasesTab from './features/add-releases-tab'; -import addGistsLink from './features/add-gists-link-to-profile'; -import addTimeMachineLinksToComments from './features/add-time-machine-links-to-comments'; -import removeUploadFilesButton from './features/remove-upload-files-button'; -import scrollToTopOnCollapse from './features/scroll-to-top-on-collapse'; -import linkifyBranchRefs from './features/linkify-branch-refs'; -import hideEmptyMeta from './features/hide-empty-meta'; -import hideInactiveDeployments from './features/hide-inactive-deployments'; -import hideOwnStars from './features/hide-own-stars'; -import moveMarketplaceLinkToProfileDropdown from './features/move-marketplace-link-to-profile-dropdown'; -import addTrendingMenuItem from './features/add-trending-menu-item'; -import addProfileHotkey from './features/add-profile-hotkey'; -import addYoursMenuItem from './features/add-yours-menu-item'; -import addCommentedMenuItem from './features/add-commented-menu-item'; -import addToggleFilesButton from './features/add-toggle-files-button'; -import hideReadmeHeader from './features/hide-readme-header'; -import addBranchButtons from './features/add-branch-buttons'; -import addDeleteForkLink from './features/add-delete-fork-link'; -import linkifyIssuesInTitles from './features/linkify-issues-in-titles'; -import addPatchDiffLinks from './features/add-patch-diff-links'; -import markMergeCommitsInList from './features/mark-merge-commits-in-list'; -import showRecentlyPushedBranchesOnMorePages from './features/show-recently-pushed-branches-on-more-pages'; -import addDiffViewWithoutWhitespaceOption from './features/add-diff-view-without-whitespace-option'; -import preserveWhitespaceOptionInNav from './features/preserve-whitespace-option-in-nav'; -import addMilestoneNavigation from './features/add-milestone-navigation'; -import addFilterCommentsByYou from './features/add-filter-comments-by-you'; -import excludeFilterShortcut from './features/exclude-filter-shortcut'; -import removeProjectsTab from './features/remove-projects-tab'; -import hideUselessComments from './features/hide-useless-comments'; -import fixSquashAndMergeTitle from './features/fix-squash-and-merge-title'; -import fixSquashAndMergeMessage from './features/fix-squash-and-merge-message'; -import addTitleToEmojis from './features/add-title-to-emojis'; -import sortMilestonesByClosestDueDate from './features/sort-milestones-by-closest-due-date'; -import openCIDetailsInNewTab from './features/open-ci-details-in-new-tab'; -import focusConfirmationButtons from './features/focus-confirmation-buttons'; -import addKeyboardShortcutsToCommentFields from './features/add-keyboard-shortcuts-to-comment-fields'; -import addCreateReleaseShortcut from './features/add-create-release-shortcut'; -import addCILink from './features/add-ci-link'; -import embedGistInline from './features/embed-gist-inline'; -import extendStatusLabels from './features/extend-status-labels'; -import highlightClosingPrsInOpenIssues from './features/highlight-closing-prs-in-open-issues'; -import addJumpToBottomLink from './features/add-jump-to-bottom-link'; -import addQuickReviewButtons from './features/add-quick-review-buttons'; -import extendDiffExpander from './features/extend-diff-expander'; -import sortIssuesByUpdateTime from './features/sort-issues-by-update-time'; -import makeDiscussionSidebarSticky from './features/make-discussion-sidebar-sticky'; -import makeHeadersSticky from './features/make-headers-sticky'; -import shortenLinks from './features/shorten-links'; -import waitForBuild from './features/wait-for-build'; -import addDownloadFolderButton from './features/add-download-folder-button'; -import hideUselessNewsfeedEvents from './features/hide-useless-newsfeed-events'; -import closeOutOfViewModals from './features/close-out-of-view-modals'; -import monospaceTextareas from './features/monospace-textareas'; -import improveShortcutHelp from './features/improve-shortcut-help'; -import hideNavigationHoverHighlight from './features/hide-navigation-hover-highlight'; -import addPullRequestHotkey from './features/add-pull-request-hotkey'; -import openSelectionInNewTab from './features/add-selection-in-new-tab'; -import addSwapBranchesOnCompare from './features/add-swap-branches-on-compare'; -import showFollowersYouKnow from './features/show-followers-you-know'; -import hideCommentsFaster from './features/hide-comments-faster'; -import linkifyCommitSha from './features/linkify-commit-sha'; -import hideIssueListAutocomplete from './features/hide-issue-list-autocomplete'; -import showUserTopRepositories from './features/show-user-top-repositories'; -import userProfileFollowerBadge from './features/user-profile-follower-badge'; -import usefulNotFoundPage from './features/useful-not-found-page'; -import setDefaultRepositoriesTypeToSources from './features/set-default-repositories-type-to-sources'; -import markPrivateOrgs from './features/mark-private-orgs'; -import navigatePagesWithArrowKeys from './features/navigate-pages-with-arrow-keys'; -import addStarRepoHotkey from './features/add-star-repo-hotkey'; -import bypassChecksTravis from './features/bypass-checks-travis'; - -import * as pageDetect from './libs/page-detect'; -import {safeElementReady, enableFeature, safeOnAjaxedPages, injectCustomCSS} from './libs/utils'; - -// Add globals for easier debugging +import 'webext-dynamic-content-scripts'; +import features from './libs/features'; + +import './features/useful-not-found-page'; +import './features/add-trending-menu-item'; +import './features/hide-useless-newsfeed-events'; +import './features/more-dropdown'; +import './features/add-releases-tab'; +import './features/remove-projects-tab'; +import './features/focus-confirmation-buttons'; +import './features/add-keyboard-shortcuts-to-comment-fields'; +import './features/hide-navigation-hover-highlight'; +import './features/monospace-textareas'; +import './features/add-selection-in-new-tab'; +import './features/hide-comments-faster'; +import './features/mark-unread'; +import './features/open-all-notifications'; +import './features/copy-on-y'; +import './features/add-profile-hotkey'; +import './features/make-discussion-sidebar-sticky'; +import './features/close-out-of-view-modals'; +import './features/improve-shortcut-help'; +import './features/upload-button'; +import './features/move-marketplace-link-to-profile-dropdown'; +import './features/copy-file'; +import './features/hide-own-stars'; +import './features/infinite-scroll'; +import './features/hide-empty-meta'; +import './features/remove-upload-files-button'; +import './features/add-title-to-emojis'; +import './features/shorten-links'; +import './features/linkify-urls-in-code'; +import './features/add-download-folder-button'; +import './features/linkify-branch-refs'; +import './features/batch-open-issues'; +import './features/hide-useless-comments'; +import './features/navigate-pages-with-arrow-keys'; +import './features/make-headers-sticky'; +import './features/add-yours-menu-item'; +import './features/add-commented-menu-item'; +import './features/sort-issues-by-update-time'; // Must be after add-yours-menu-item + add-commented-menu-item +import './features/hide-readme-header'; +import './features/add-branch-buttons'; +import './features/add-diff-view-without-whitespace-option'; +import './features/add-ci-link'; +import './features/add-milestone-navigation'; +import './features/sort-milestones-by-closest-due-date'; // Needs to be after add-milestone-navigation +import './features/add-star-repo-hotkey'; +import './features/add-toggle-files-button'; +import './features/scroll-to-top-on-collapse'; +import './features/add-delete-fork-link'; +import './features/fix-squash-and-merge-title'; +import './features/fix-squash-and-merge-message'; +import './features/open-ci-details-in-new-tab'; +import './features/wait-for-build'; +import './features/hide-inactive-deployments'; +import './features/add-pull-request-hotkey'; +import './features/add-quick-review-buttons'; +import './features/linkify-issues-in-titles'; +import './features/embed-gist-inline'; +import './features/extend-status-labels'; +import './features/highlight-closing-prs-in-open-issues'; +import './features/op-labels'; +import './features/add-time-machine-links-to-comments'; +import './features/add-jump-to-bottom-link'; +import './features/add-filter-comments-by-you'; +import './features/hide-issue-list-autocomplete'; +import './features/exclude-filter-shortcut'; +import './features/show-recently-pushed-branches-on-more-pages'; +import './features/add-create-release-shortcut'; +import './features/add-patch-diff-links'; +import './features/add-swap-branches-on-compare'; +import './features/reactions-avatars'; +import './features/show-names'; +import './features/mark-merge-commits-in-list'; +import './features/prev-next-commit-buttons'; +import './features/preserve-whitespace-option-in-nav'; +import './features/extend-diff-expander'; +import './features/add-gists-link-to-profile'; +import './features/show-followers-you-know'; +import './features/show-user-top-repositories'; +import './features/set-default-repositories-type-to-sources'; +import './features/user-profile-follower-badge'; +import './features/mark-private-orgs'; +import './features/linkify-commit-sha'; +import './features/bypass-checks-travis'; + +// Add global for easier debugging window.select = select; -async function init() { - await safeElementReady('body'); - - if (pageDetect.is500()) { - return; - } - - if (pageDetect.is404()) { - enableFeature(usefulNotFoundPage); - return; - } - if (document.body.classList.contains('logged-out')) { - console.warn('%cRefined GitHub%c only works when you’re logged in to GitHub.', 'font-weight: bold', ''); - return; - } - - if (select.exists('html.refined-github')) { - console.warn('Refined GitHub has been loaded twice. If you didn’t install the developer version, this may be a bug. Please report it to: https://github.com/sindresorhus/refined-github/issues/565'); - return; - } - - document.documentElement.classList.add('refined-github'); - - injectCustomCSS(); - - if (!pageDetect.isGist()) { - enableFeature(addTrendingMenuItem); - } - - if (pageDetect.isDashboard() && !pageDetect.isGist()) { - enableFeature(hideUselessNewsfeedEvents); - } - - if (pageDetect.isRepo()) { - safeOnAjaxedPages(async () => { - // Wait for the tab bar to be loaded - await safeElementReady('.pagehead + *'); - enableFeature(addMoreDropdown); - enableFeature(addReleasesTab); - enableFeature(removeProjectsTab); - }); - } - - enableFeature(focusConfirmationButtons); - enableFeature(addKeyboardShortcutsToCommentFields); - enableFeature(hideNavigationHoverHighlight); - enableFeature(monospaceTextareas); - enableFeature(openSelectionInNewTab); - enableFeature(hideCommentsFaster); - enableFeature(markUnread); - - await domLoaded; - onDomReady(); -} - -async function onDomReady() { - enableFeature(addOpenAllNotificationsButton); - enableFeature(enableCopyOnY); - enableFeature(addProfileHotkey); - enableFeature(makeDiscussionSidebarSticky); - enableFeature(closeOutOfViewModals); - enableFeature(improveShortcutHelp); - enableFeature(addUploadBtn); - - if (!pageDetect.isGist()) { - enableFeature(moveMarketplaceLinkToProfileDropdown); - } - - if (pageDetect.isGist()) { - enableFeature(addFileCopyButton); - } - - if (pageDetect.isDashboard()) { - enableFeature(hideOwnStars); - enableFeature(infiniteScroll); - } - - // Push safeOnAjaxedPages on the next tick so it happens in the correct order - // (specifically for addOpenAllNotificationsButton) - await Promise.resolve(); - - safeOnAjaxedPages(() => { - ajaxedPagesHandler(); - - // Mark current page as "done" - // so history.back() won't reapply the same changes - const ajaxContainer = select('#js-repo-pjax-container,#js-pjax-container'); - if (ajaxContainer) { - ajaxContainer.append(); - } - }); -} - -// eslint-disable-next-line complexity -function ajaxedPagesHandler() { - enableFeature(hideEmptyMeta); - enableFeature(removeUploadFilesButton); - enableFeature(addTitleToEmojis); - enableFeature(shortenLinks); - enableFeature(linkifyCode); - enableFeature(addDownloadFolderButton); - enableFeature(linkifyBranchRefs); - enableFeature(batchOpenIssues); - enableFeature(hideUselessComments); - enableFeature(navigatePagesWithArrowKeys); - enableFeature(makeHeadersSticky); - - if (pageDetect.isGlobalIssueSearch() || pageDetect.isGlobalPRSearch()) { - enableFeature(addYoursMenuItem); - enableFeature(addCommentedMenuItem); - } - - enableFeature(sortIssuesByUpdateTime); // Must be after addYoursMenuItem + addCommentedMenuItem - - if (pageDetect.isMilestone()) { - enableFeature(addMilestoneNavigation); // Needs to be before sortMilestonesByClosestDueDate - } - - if (pageDetect.isRepo()) { - enableFeature(hideReadmeHeader); - enableFeature(addBranchButtons); - enableFeature(addDiffViewWithoutWhitespaceOption); - enableFeature(addCILink); - enableFeature(sortMilestonesByClosestDueDate); // Needs to be after addMilestoneNavigation - enableFeature(addStarRepoHotkey); - } - - if (pageDetect.isRepoRoot()) { - enableFeature(addToggleFilesButton); - } - - if (pageDetect.isPR()) { - enableFeature(scrollToTopOnCollapse); - enableFeature(addDeleteForkLink); - enableFeature(fixSquashAndMergeTitle); - enableFeature(fixSquashAndMergeMessage); - enableFeature(openCIDetailsInNewTab); - enableFeature(waitForBuild); - enableFeature(hideInactiveDeployments); - enableFeature(addPullRequestHotkey); - enableFeature(addQuickReviewButtons); - } - - if (pageDetect.isPR() || pageDetect.isIssue()) { - enableFeature(linkifyIssuesInTitles); - enableFeature(embedGistInline); - enableFeature(extendStatusLabels); - enableFeature(highlightClosingPrsInOpenIssues); - enableFeature(addOPLabels); - enableFeature(addTimeMachineLinksToComments); - } - - if (pageDetect.isIssue() || pageDetect.isPRConversation()) { - enableFeature(addJumpToBottomLink); - } - - if (pageDetect.isIssueList()) { - enableFeature(addFilterCommentsByYou); - enableFeature(hideIssueListAutocomplete); - enableFeature(excludeFilterShortcut); - } - - if (pageDetect.isIssueList() || pageDetect.isPR() || pageDetect.isIssue()) { - enableFeature(showRecentlyPushedBranchesOnMorePages); - } - - if (pageDetect.isReleasesOrTags()) { - enableFeature(addCreateReleaseShortcut); - } - - if (pageDetect.isCommit()) { - enableFeature(addPatchDiffLinks); - } - - if (pageDetect.isCompare()) { - enableFeature(addSwapBranchesOnCompare); +// Must be called after all the features were added to safeOnAjaxedPages +// to mark the current load as "done", so history.back() won't reapply the same DOM changes +features.safeOnAjaxedPages(() => { + const ajaxContainer = select('#js-repo-pjax-container,#js-pjax-container'); + if (ajaxContainer) { + ajaxContainer.append(); } - - if (pageDetect.isPR() || pageDetect.isIssue() || pageDetect.isCommit() || pageDetect.isDiscussion()) { - enableFeature(addReactionParticipants); - enableFeature(showRealNames); - } - - if (pageDetect.isCommitList()) { - enableFeature(markMergeCommitsInList); - } - - if (pageDetect.isPRFiles() || pageDetect.isPRCommit()) { - enableFeature(addPrevNextButtonsToPRs); - enableFeature(preserveWhitespaceOptionInNav); - } - - if (pageDetect.isPRFiles()) { - enableFeature(extendDiffExpander); - } - - if (pageDetect.isSingleFile()) { - enableFeature(addFileCopyButton); - } - - if (pageDetect.isUserProfile()) { - enableFeature(addGistsLink); - enableFeature(showFollowersYouKnow); - enableFeature(showUserTopRepositories); - enableFeature(setDefaultRepositoriesTypeToSources); - enableFeature(userProfileFollowerBadge); - } - - if (pageDetect.isOwnUserProfile()) { - enableFeature(markPrivateOrgs); - } - - if (pageDetect.isPRCommit()) { - enableFeature(linkifyCommitSha); - } - - if (pageDetect.isPRConversation()) { - enableFeature(bypassChecksTravis); - } -} - -init(); +}); diff --git a/source/features/add-branch-buttons.js b/source/features/add-branch-buttons.js index 2dc66c3ff91..1292647e194 100644 --- a/source/features/add-branch-buttons.js +++ b/source/features/add-branch-buttons.js @@ -3,6 +3,7 @@ import select from 'select-dom'; import compareVersions from 'tiny-version-compare'; import * as api from '../libs/api'; import * as icons from '../libs/icons'; +import features from '../libs/features'; import {appendBefore} from '../libs/utils'; import {groupSiblings} from '../libs/group-buttons'; import getDefaultBranch from '../libs/get-default-branch'; @@ -90,10 +91,10 @@ async function getDefaultBranchLink() { ); } -export default async function () { +async function init() { const container = select('.file-navigation'); if (!container) { - return; + return false; } const [defaultLink = '', tagLink = ''] = await Promise.all([ getDefaultBranchLink(), @@ -115,3 +116,12 @@ export default async function () { groupSiblings(wrapper.firstElementChild); } } + +features.add({ + id: 'add-branch-buttons', + dependencies: [ + features.isRepo + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-ci-link.js b/source/features/add-ci-link.js index 0e43a424e1a..559e42b5c10 100644 --- a/source/features/add-ci-link.js +++ b/source/features/add-ci-link.js @@ -1,5 +1,6 @@ import select from 'select-dom'; import domify from '../libs/domify'; +import features from '../libs/features'; import {getRepoURL, getRepoBranch} from '../libs/page-detect'; import {appendBefore} from '../libs/utils'; @@ -23,10 +24,10 @@ async function fetchStatus() { return icon; } -export default async function () { +async function init() { // Avoid on pages that already failed to load if (request === false) { - return; + return false; } try { @@ -44,5 +45,15 @@ export default async function () { // Network failure or no CI status found. // Don’t try again request = false; + return false; } } + +features.add({ + id: 'add-ci-link', + dependencies: [ + features.isRepo + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-commented-menu-item.js b/source/features/add-commented-menu-item.js index 8ad95402f9d..c68b0f85d0a 100644 --- a/source/features/add-commented-menu-item.js +++ b/source/features/add-commented-menu-item.js @@ -1,14 +1,14 @@ import {h} from 'dom-chef'; import select from 'select-dom'; -import * as pageDetect from '../libs/page-detect'; +import features from '../libs/features'; import {getUsername} from '../libs/utils'; +import {isGlobalIssueSearch} from '../libs/page-detect'; -export default function () { - const pageName = pageDetect.isGlobalIssueSearch() ? 'issues' : 'pulls'; - const type = pageDetect.isGlobalIssueSearch() ? 'issue' : 'pr'; +function init() { const username = getUsername(); + const type = isGlobalIssueSearch() ? 'issue' : 'pr'; - const commentedMenuItem = Commented; + const commentedMenuItem = Commented; if (!select.exists('.subnav-links .selected') && location.search.includes(`commenter%3A${username}`)) { commentedMenuItem.classList.add('selected'); @@ -19,3 +19,13 @@ export default function () { select('.subnav-links').append(commentedMenuItem); } + +features.add({ + id: 'add-commented-menu-item', + dependencies: [ + features.isGlobalIssueSearch, + features.isGlobalPRSearch + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-create-release-shortcut.js b/source/features/add-create-release-shortcut.js index 77c0765c74b..bd52e454639 100644 --- a/source/features/add-create-release-shortcut.js +++ b/source/features/add-create-release-shortcut.js @@ -1,10 +1,20 @@ import select from 'select-dom'; +import features from '../libs/features'; import {registerShortcut} from './improve-shortcut-help'; -export default function () { +function init() { registerShortcut('releases', 'c', 'Create a new release'); const createReleaseButton = select('a[href$="/releases/new"]:not([data-hotkey])'); if (createReleaseButton) { createReleaseButton.setAttribute('data-hotkey', 'c'); } } + +features.add({ + id: 'add-create-release-shortcut', + dependencies: [ + features.isReleasesOrTags + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-delete-fork-link.js b/source/features/add-delete-fork-link.js index 4e7b52391dc..ac7db6bb2ee 100644 --- a/source/features/add-delete-fork-link.js +++ b/source/features/add-delete-fork-link.js @@ -1,28 +1,32 @@ import {h} from 'dom-chef'; import select from 'select-dom'; -import onNewComments from '../libs/on-new-comments'; -import * as pageDetect from '../libs/page-detect'; +import features from '../libs/features'; +import {getRepoURL} from '../libs/page-detect'; -const repoUrl = pageDetect.getRepoURL(); - -function addLink() { +function init() { const currentBranch = select('#partial-pull-merging .merge-branch-description .commit-ref'); if (!currentBranch) { - return; + return false; } const [forkPath] = currentBranch.title.split(':'); - if (forkPath !== repoUrl) { - currentBranch.parentElement.append( - - Delete fork - - ); + if (forkPath === getRepoURL()) { + return false; } -} -export default function () { - addLink(); - onNewComments(addLink); + currentBranch.parentElement.append( + + Delete fork + + ); } + +features.add({ + id: 'add-delete-fork-link', + dependencies: [ + features.isPRConversation + ], + load: features.onNewComments, + init +}); diff --git a/source/features/add-diff-view-without-whitespace-option.js b/source/features/add-diff-view-without-whitespace-option.js index 1e00d396812..8a48e41458b 100644 --- a/source/features/add-diff-view-without-whitespace-option.js +++ b/source/features/add-diff-view-without-whitespace-option.js @@ -1,16 +1,17 @@ import {h} from 'dom-chef'; import select from 'select-dom'; import * as icons from '../libs/icons'; +import features from '../libs/features'; import {registerShortcut} from './improve-shortcut-help'; -export default function () { +function init() { const container = select([ '.table-of-contents.Details .BtnGroup', // In single commit view '.pr-review-tools > .diffbar-item' // In review view ].join(',')); if (!container) { - return; + return false; } const url = new URL(location.href); @@ -42,3 +43,12 @@ export default function () { uselessCopy.firstChild.remove(); } } + +features.add({ + id: 'add-diff-view-without-whitespace-option', + dependencies: [ + features.isRepo + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-download-folder-button.js b/source/features/add-download-folder-button.js index 6a01e166c28..ec14b1ae27d 100644 --- a/source/features/add-download-folder-button.js +++ b/source/features/add-download-folder-button.js @@ -1,19 +1,28 @@ import {h} from 'dom-chef'; import select from 'select-dom'; -import * as pageDetect from '../libs/page-detect'; +import features from '../libs/features'; -export default () => { - // Add to folder listings, excluding the repo root (that already has an official download ZIP button) - if (pageDetect.isRepoTree() && !pageDetect.isRepoRoot()) { - const buttonGroup = select('.file-navigation .BtnGroup.float-right'); - if (buttonGroup) { - buttonGroup.prepend( - - Download - - ); - } +function init() { + const buttonGroup = select('.file-navigation .BtnGroup.float-right'); + if (buttonGroup) { + buttonGroup.prepend( + + Download + + ); } -}; +} + +features.add({ + id: 'add-download-folder-button', + dependencies: [ + features.and( + features.isRepoTree, + features.not(features.isRepoRoot) // Already has an native download ZIP button + ) + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-filter-comments-by-you.js b/source/features/add-filter-comments-by-you.js index fca789e21fb..11926e41df2 100644 --- a/source/features/add-filter-comments-by-you.js +++ b/source/features/add-filter-comments-by-you.js @@ -1,11 +1,12 @@ import {h} from 'dom-chef'; import select from 'select-dom'; -import * as pageDetect from '../libs/page-detect'; +import features from '../libs/features'; +import {getRepoURL} from '../libs/page-detect'; import {getUsername} from '../libs/utils'; -const repoUrl = pageDetect.getRepoURL(); +const repoUrl = getRepoURL(); -export default function () { +function init() { select('.subnav-search-context li:last-child') .before(
  • @@ -18,3 +19,12 @@ export default function () {
  • ); } + +features.add({ + id: 'add-filter-comments-by-you', + dependencies: [ + features.isIssueList + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-gists-link-to-profile.js b/source/features/add-gists-link-to-profile.js index 4b77ad7ef87..dc79c713aaa 100644 --- a/source/features/add-gists-link-to-profile.js +++ b/source/features/add-gists-link-to-profile.js @@ -1,13 +1,14 @@ import {h} from 'dom-chef'; import select from 'select-dom'; -import {getCleanPathname, isEnterprise} from '../libs/page-detect'; import * as api from '../libs/api'; +import features from '../libs/features'; +import {getCleanPathname, isEnterprise} from '../libs/page-detect'; -export default async () => { +async function init() { const container = select('body.page-profile .UnderlineNav-body'); if (!container) { - return; + return false; } const username = getCleanPathname(); @@ -19,4 +20,13 @@ export default async () => { if (userData.public_gists) { link.append({userData.public_gists}); } -}; +} + +features.add({ + id: 'add-gists-link-to-profile', + dependencies: [ + features.isUserProfile + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-jump-to-bottom-link.js b/source/features/add-jump-to-bottom-link.js index 6e6ed4727cb..8359942cc27 100644 --- a/source/features/add-jump-to-bottom-link.js +++ b/source/features/add-jump-to-bottom-link.js @@ -1,12 +1,12 @@ import {h} from 'dom-chef'; import select from 'select-dom'; +import features from '../libs/features'; import observeEl from '../libs/simplified-element-observer'; function add() { const meta = select('.gh-header-meta > .TableObject-item--primary'); - const jumpToBottomLink = select('#rgh-jump-to-bottom-link'); - if (!meta || jumpToBottomLink) { - return; + if (!meta || select.exists('#rgh-jump-to-bottom-link')) { + return false; } meta.append( @@ -15,7 +15,17 @@ function add() { ); } -export default function () { +function init() { // The issue header changes when new comments are added or the issue status changes observeEl('.js-issues-results', add); } + +features.add({ + id: 'add-jump-to-bottom-link', + dependencies: [ + features.isIssue, + features.isPRConversation + ], + load: features.safeOnAjaxedPages, + init +}); diff --git a/source/features/add-keyboard-shortcuts-to-comment-fields.js b/source/features/add-keyboard-shortcuts-to-comment-fields.js index 76015611133..245c5cf7021 100644 --- a/source/features/add-keyboard-shortcuts-to-comment-fields.js +++ b/source/features/add-keyboard-shortcuts-to-comment-fields.js @@ -1,5 +1,6 @@ import select from 'select-dom'; import delegate from 'delegate'; +import features from '../libs/features'; import indentTextarea from '../libs/indent-textarea'; import {registerShortcut} from './improve-shortcut-help'; @@ -18,7 +19,7 @@ function blurAccessibly(field) { focusHolder.remove(); } -export default function () { +function init() { registerShortcut('issues', '↑', 'Edit your last comment'); delegate('.js-comment-field', 'keydown', event => { @@ -61,3 +62,8 @@ export default function () { } }); } + +features.add({ + id: 'add-keyboard-shortcuts-to-comment-fields', + init +}); diff --git a/source/features/add-milestone-navigation.js b/source/features/add-milestone-navigation.js index ff3c23bd2eb..5afd005d133 100644 --- a/source/features/add-milestone-navigation.js +++ b/source/features/add-milestone-navigation.js @@ -1,10 +1,11 @@ import {h} from 'dom-chef'; import select from 'select-dom'; -import * as pageDetect from '../libs/page-detect'; +import features from '../libs/features'; +import {getRepoURL} from '../libs/page-detect'; -const repoUrl = pageDetect.getRepoURL(); +const repoUrl = getRepoURL(); -export default function () { +function init() { select('.repository-content').before(