summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contributing.md2
-rw-r--r--package-lock.json14
-rw-r--r--package.json2
-rw-r--r--source/feature-manager.tsx14
-rw-r--r--source/features/action-used-by-link.tsx4
-rw-r--r--source/features/actionable-pr-view-file.tsx6
-rw-r--r--source/features/avoid-accidental-submissions.tsx6
-rw-r--r--source/features/batch-mark-files-as-viewed.tsx6
-rw-r--r--source/features/bugs-tab.tsx14
-rw-r--r--source/features/clean-conversation-filters.tsx4
-rw-r--r--source/features/clean-conversation-headers.tsx10
-rw-r--r--source/features/clean-conversation-sidebar.tsx28
-rw-r--r--source/features/clean-repo-filelist-actions.tsx8
-rw-r--r--source/features/clean-repo-sidebar.tsx12
-rw-r--r--source/features/clean-repo-tabs.tsx10
-rw-r--r--source/features/clear-pr-merge-commit-message.tsx4
-rw-r--r--source/features/close-out-of-view-modals.tsx4
-rw-r--r--source/features/closing-remarks.tsx4
-rw-r--r--source/features/comment-fields-keyboard-shortcuts.tsx20
-rw-r--r--source/features/comments-time-machine-links.tsx8
-rw-r--r--source/features/conversation-activity-filter.tsx36
-rw-r--r--source/features/conversation-links-on-repo-lists.tsx6
-rw-r--r--source/features/convert-pr-to-draft-improvements.tsx8
-rw-r--r--source/features/convert-release-to-draft.tsx8
-rw-r--r--source/features/cross-deleted-pr-branches.tsx10
-rw-r--r--source/features/deep-reblame.tsx12
-rw-r--r--source/features/dim-bots.tsx10
-rw-r--r--source/features/easy-toggle-commit-messages.tsx4
-rw-r--r--source/features/easy-toggle-files.tsx4
-rw-r--r--source/features/embed-gist-via-iframe.tsx10
-rw-r--r--source/features/esc-to-cancel.tsx4
-rw-r--r--source/features/expand-all-hidden-comments.tsx4
-rw-r--r--source/features/extend-conversation-status-filters.tsx8
-rw-r--r--source/features/extend-diff-expander.tsx4
-rw-r--r--source/features/github-actions-indicators.tsx6
-rw-r--r--source/features/global-conversation-list-filters.tsx6
-rw-r--r--source/features/hidden-review-comments-indicator.tsx4
-rw-r--r--source/features/hide-inactive-deployments.tsx6
-rw-r--r--source/features/hide-issue-list-autocomplete.tsx4
-rw-r--r--source/features/hide-low-quality-comments.tsx26
-rw-r--r--source/features/highest-rated-comment.tsx20
-rw-r--r--source/features/highlight-collaborators-and-own-conversations.tsx9
-rw-r--r--source/features/highlight-non-default-base-branch.tsx4
-rw-r--r--source/features/improve-shortcut-help.tsx8
-rw-r--r--source/features/infinite-scroll.tsx4
-rw-r--r--source/features/jump-to-change-requested-comment.tsx6
-rw-r--r--source/features/jump-to-conversation-close-event.tsx4
-rw-r--r--source/features/keyboard-navigation.tsx20
-rw-r--r--source/features/last-notification-page-button.tsx4
-rw-r--r--source/features/link-to-changelog-file.tsx4
-rw-r--r--source/features/link-to-compare-diff.tsx4
-rw-r--r--source/features/linkify-code.tsx6
-rw-r--r--source/features/linkify-commit-sha.tsx4
-rw-r--r--source/features/linkify-labels-on-dashboard.tsx6
-rw-r--r--source/features/linkify-symbolic-links.tsx6
-rw-r--r--source/features/mark-merge-commits-in-list.tsx8
-rw-r--r--source/features/mark-private-orgs.tsx4
-rw-r--r--source/features/more-conversation-filters.tsx10
-rw-r--r--source/features/more-dropdown-links.tsx6
-rw-r--r--source/features/more-file-links.tsx4
-rw-r--r--source/features/netiquette.tsx6
-rw-r--r--source/features/new-or-deleted-file.tsx8
-rw-r--r--source/features/new-repo-disable-projects-and-wikis.tsx10
-rw-r--r--source/features/no-duplicate-list-update-time.tsx4
-rw-r--r--source/features/one-click-diff-options.tsx16
-rw-r--r--source/features/one-click-pr-or-gist.tsx12
-rw-r--r--source/features/one-click-review-submission.tsx2
-rw-r--r--source/features/open-all-conversations.tsx6
-rw-r--r--source/features/open-all-notifications.tsx10
-rw-r--r--source/features/open-issue-to-latest-comment.tsx6
-rw-r--r--source/features/pinned-issues-update-time.tsx6
-rw-r--r--source/features/pr-base-commit.tsx4
-rw-r--r--source/features/pr-branch-auto-delete.tsx4
-rw-r--r--source/features/pr-filters.tsx8
-rw-r--r--source/features/pr-jump-to-first-non-viewed-file.tsx4
-rw-r--r--source/features/prevent-link-loss.tsx8
-rw-r--r--source/features/prevent-pr-merge-panel-opening.tsx4
-rw-r--r--source/features/preview-hidden-comments.tsx4
-rw-r--r--source/features/previous-next-commit-buttons.tsx6
-rw-r--r--source/features/profile-gists-link.tsx6
-rw-r--r--source/features/pull-request-hotkeys.tsx4
-rw-r--r--source/features/quick-comment-edit.tsx6
-rw-r--r--source/features/quick-comment-hiding.tsx10
-rw-r--r--source/features/quick-label-removal.tsx4
-rw-r--r--source/features/quick-mention.tsx8
-rw-r--r--source/features/quick-repo-deletion.tsx10
-rw-r--r--source/features/quick-review-comment-deletion.tsx4
-rw-r--r--source/features/quick-review.tsx4
-rw-r--r--source/features/reactions-avatars.tsx10
-rw-r--r--source/features/release-download-count.tsx6
-rw-r--r--source/features/repo-header-info.tsx6
-rw-r--r--source/features/repo-wide-file-finder.tsx4
-rw-r--r--source/features/rgh-improve-new-issue-form.tsx8
-rw-r--r--source/features/rgh-welcome-issue.tsx6
-rw-r--r--source/features/same-branch-author-commits.tsx4
-rw-r--r--source/features/select-all-notifications-shortcut.tsx4
-rw-r--r--source/features/select-notifications.tsx26
-rw-r--r--source/features/selection-in-new-tab.tsx4
-rw-r--r--source/features/show-open-prs-of-forks.tsx6
-rw-r--r--source/features/sort-conversations-by-update-time.tsx6
-rw-r--r--source/features/submission-via-ctrl-enter-everywhere.tsx4
-rw-r--r--source/features/swap-branches-on-compare.tsx6
-rw-r--r--source/features/sync-pr-commit-title.tsx8
-rw-r--r--source/features/tag-changes-link.tsx14
-rw-r--r--source/features/tags-on-commits-list.tsx6
-rw-r--r--source/features/toggle-files-button.tsx6
-rw-r--r--source/features/unfinished-comments.tsx4
-rw-r--r--source/features/unwrap-unnecessary-dropdowns.tsx8
-rw-r--r--source/features/update-pr-from-base-branch.tsx6
-rw-r--r--source/features/use-first-commit-message-for-new-prs.tsx12
-rw-r--r--source/features/useful-not-found-page.tsx8
-rw-r--r--source/features/user-local-time.tsx8
-rw-r--r--source/features/vertical-front-matter.tsx6
-rw-r--r--source/features/view-last-pr-deployment.tsx4
-rw-r--r--source/features/wait-for-attachments.tsx6
-rw-r--r--source/features/wait-for-checks.tsx12
-rw-r--r--source/features/warn-pr-from-master.tsx8
-rw-r--r--source/features/warning-for-disallow-edits.tsx4
-rw-r--r--source/github-events/on-field-keydown.tsx4
-rw-r--r--source/github-helpers/dom-formatters.tsx6
-rw-r--r--source/github-helpers/get-current-git-ref.ts6
-rw-r--r--source/github-helpers/get-tab-count.ts4
-rw-r--r--source/github-helpers/get-user-avatar.ts4
-rw-r--r--source/github-helpers/index.ts8
-rw-r--r--source/github-helpers/load-details-menu.ts4
-rw-r--r--source/github-helpers/pr-branches.ts6
-rw-r--r--source/github-helpers/pr-ci-status.ts8
-rw-r--r--source/helpers/attach-element.ts8
-rw-r--r--source/helpers/bisect.tsx6
-rw-r--r--source/helpers/click-all.ts4
-rw-r--r--source/helpers/dom-utils.ts6
-rw-r--r--source/helpers/on-element-replacement.ts6
-rw-r--r--source/options.tsx72
133 files changed, 528 insertions, 529 deletions
diff --git a/contributing.md b/contributing.md
index e98c2e1f..d542024a 100644
--- a/contributing.md
+++ b/contributing.md
@@ -46,7 +46,7 @@ Here's an example using all of the possible `feature.add` options:
```tsx
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
diff --git a/package-lock.json b/package-lock.json
index 0eb09b64..63347bc2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -35,7 +35,7 @@
"pretty-bytes": "^6.1.1",
"push-form": "^1.0.1",
"regex-join": "^2.0.0",
- "select-dom": "^8.0.0",
+ "select-dom": "^9.0.0",
"shorten-repo-url": "^3.0.0",
"strip-indent": "^4.0.0",
"text-field-edit": "^3.2.0",
@@ -8552,9 +8552,9 @@
"dev": true
},
"node_modules/select-dom": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/select-dom/-/select-dom-8.0.0.tgz",
- "integrity": "sha512-U0/vlppYeRVFNv3N78I9Kj+wNfm5szZGCsFsoF8rmAOhXF9kXKdtJJeXYS/ghubvRblqjJDyRI/1aOoiJgw+0g==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/select-dom/-/select-dom-9.0.0.tgz",
+ "integrity": "sha512-AD1NfASSwJQc1Sy713R1vT9CMmUSUo2tg0j1FtkRGIxllTphDrkuH2pYYvhRlGaoq3pS6tcKkKS/diEZLy+7BQ==",
"dependencies": {
"typed-query-selector": "^2.11.0"
},
@@ -17030,9 +17030,9 @@
}
},
"select-dom": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/select-dom/-/select-dom-8.0.0.tgz",
- "integrity": "sha512-U0/vlppYeRVFNv3N78I9Kj+wNfm5szZGCsFsoF8rmAOhXF9kXKdtJJeXYS/ghubvRblqjJDyRI/1aOoiJgw+0g==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/select-dom/-/select-dom-9.0.0.tgz",
+ "integrity": "sha512-AD1NfASSwJQc1Sy713R1vT9CMmUSUo2tg0j1FtkRGIxllTphDrkuH2pYYvhRlGaoq3pS6tcKkKS/diEZLy+7BQ==",
"requires": {
"typed-query-selector": "^2.11.0"
}
diff --git a/package.json b/package.json
index a74612fb..4baf268f 100644
--- a/package.json
+++ b/package.json
@@ -80,7 +80,7 @@
"pretty-bytes": "^6.1.1",
"push-form": "^1.0.1",
"regex-join": "^2.0.0",
- "select-dom": "^8.0.0",
+ "select-dom": "^9.0.0",
"shorten-repo-url": "^3.0.0",
"strip-indent": "^4.0.0",
"text-field-edit": "^3.2.0",
diff --git a/source/feature-manager.tsx b/source/feature-manager.tsx
index e1b02136..6ec2f361 100644
--- a/source/feature-manager.tsx
+++ b/source/feature-manager.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import domLoaded from 'dom-loaded';
import stripIndent from 'strip-indent';
import {Promisable} from 'type-fest';
@@ -112,7 +112,7 @@ const globalReady = new Promise<RGHOptions>(async resolve => {
return;
}
- if (select.exists('[refined-github]')) {
+ if (elementExists('[refined-github]')) {
console.warn(stripIndent(`
Refined GitHub has been loaded twice. This may be because:
@@ -147,7 +147,7 @@ const globalReady = new Promise<RGHOptions>(async resolve => {
log.info = options.logging ? console.log : () => {/* No logging */};
log.http = options.logHTTP ? console.log : () => {/* No logging */};
- if (select.exists('body.logged-out')) {
+ if (elementExists('body.logged-out')) {
console.warn('Refined GitHub is only expected to work when you’re logged in to GitHub. Errors will not be shown.');
features.log.error = () => {/* No logging */};
}
@@ -266,7 +266,7 @@ async function add(url: string, ...loaders: FeatureLoader[]): Promise<void> {
}
document.addEventListener('turbo:render', () => {
- if (!deduplicate || !select.exists(deduplicate)) {
+ if (!deduplicate || !elementExists(deduplicate)) {
void setupPageLoad(id, details);
}
});
@@ -311,9 +311,9 @@ void add('rgh-deduplicator' as FeatureID, {
async init() {
// `await` kicks it to the next tick, after the other features have checked for 'has-rgh', so they can run once.
await Promise.resolve();
- select('has-rgh')?.remove(); // https://github.com/refined-github/refined-github/issues/6568
- select(_`#js-repo-pjax-container, #js-pjax-container`)?.append(<has-rgh/>);
- select(_`turbo-frame`)?.append(<has-rgh-inner/>); // #4567
+ $('has-rgh')?.remove(); // https://github.com/refined-github/refined-github/issues/6568
+ $(_`#js-repo-pjax-container, #js-pjax-container`)?.append(<has-rgh/>);
+ $(_`turbo-frame`)?.append(<has-rgh-inner/>); // #4567
},
});
diff --git a/source/features/action-used-by-link.tsx b/source/features/action-used-by-link.tsx
index 04ec9269..6c3d0bc4 100644
--- a/source/features/action-used-by-link.tsx
+++ b/source/features/action-used-by-link.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {SearchIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -19,7 +19,7 @@ function init(): void {
o: 'desc',
}).toString();
- select('.d-block.mb-2[href^="/contact"]')!.after(
+ $('.d-block.mb-2[href^="/contact"]')!.after(
<a href={actionURL.href} className="d-block mb-2">
<SearchIcon width={14} className="color-fg-default mr-2"/>Usage examples
</a>,
diff --git a/source/features/actionable-pr-view-file.tsx b/source/features/actionable-pr-view-file.tsx
index 6fe2f4fd..5a5af0e6 100644
--- a/source/features/actionable-pr-view-file.tsx
+++ b/source/features/actionable-pr-view-file.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -25,9 +25,9 @@ void features.add(import.meta.url, {
exclude: [
// Editing files doesn't make sense after a PR is closed/merged
pageDetect.isClosedPR,
- () => select('.head-ref')!.title === 'This repository has been deleted',
+ () => $('.head-ref')!.title === 'This repository has been deleted',
// If you're viewing changes from partial commits, ensure you're on the latest one.
- () => select.exists('.js-commits-filtered') && !select.exists('[aria-label="You are viewing the latest commit"]'),
+ () => elementExists('.js-commits-filtered') && !elementExists('[aria-label="You are viewing the latest commit"]'),
],
awaitDomReady: true, // DOM-based filters, feature is invisible and inactive until dropdown is opened
init,
diff --git a/source/features/avoid-accidental-submissions.tsx b/source/features/avoid-accidental-submissions.tsx
index 2aa93d13..13d6324d 100644
--- a/source/features/avoid-accidental-submissions.tsx
+++ b/source/features/avoid-accidental-submissions.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -14,7 +14,7 @@ function onKeyDown(event: DelegateEvent<KeyboardEvent, HTMLInputElement>): void
|| event.ctrlKey
|| event.metaKey
|| event.isComposing // #4323
- || select.exists([
+ || elementExists([
'.suggester', // GitHub’s autocomplete dropdown
'.rgh-avoid-accidental-submissions',
], form)
@@ -22,7 +22,7 @@ function onKeyDown(event: DelegateEvent<KeyboardEvent, HTMLInputElement>): void
return;
}
- if (select.exists('.btn-primary[type="submit"]:disabled', form)) {
+ if (elementExists('.btn-primary[type="submit"]:disabled', form)) {
return;
}
diff --git a/source/features/batch-mark-files-as-viewed.tsx b/source/features/batch-mark-files-as-viewed.tsx
index dc691b1b..02431523 100644
--- a/source/features/batch-mark-files-as-viewed.tsx
+++ b/source/features/batch-mark-files-as-viewed.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import debounceFn from 'debounce-fn';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -31,7 +31,7 @@ const batchToggle = debounceFn((event: DelegateEvent<MouseEvent, HTMLFormElement
event.stopImmediatePropagation();
- const files = select.all('.js-file');
+ const files = $$('.js-file');
const thisFile = event.delegateTarget.closest('.js-file')!;
const isThisBeingFileChecked = !isChecked(thisFile); // Flip it because the value hasn't changed yet
@@ -39,7 +39,7 @@ const batchToggle = debounceFn((event: DelegateEvent<MouseEvent, HTMLFormElement
const selectedFiles = getItemsBetween(files, previousFile, thisFile);
for (const file of selectedFiles) {
if (file !== thisFile && isChecked(file) !== isThisBeingFileChecked) {
- select('.js-reviewed-checkbox', file)!.click();
+ $('.js-reviewed-checkbox', file)!.click();
}
}
diff --git a/source/features/bugs-tab.tsx b/source/features/bugs-tab.tsx
index 001da2d4..88d02039 100644
--- a/source/features/bugs-tab.tsx
+++ b/source/features/bugs-tab.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import {BugIcon} from '@primer/octicons-react';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -87,13 +87,13 @@ async function addBugsTab(): Promise<void | false> {
bugsTab.removeAttribute('id');
// Update its appearance
- const bugsTabTitle = select('[data-content]', bugsTab)!;
+ const bugsTabTitle = $('[data-content]', bugsTab)!;
bugsTabTitle.dataset.content = 'Bugs';
bugsTabTitle.textContent = 'Bugs';
- select('.octicon', bugsTab)!.replaceWith(<BugIcon className="UnderlineNav-octicon d-none d-sm-inline"/>);
+ $('.octicon', bugsTab)!.replaceWith(<BugIcon className="UnderlineNav-octicon d-none d-sm-inline"/>);
// Set temporary counter
- const bugsCounter = select('.Counter', bugsTab)!;
+ const bugsCounter = $('.Counter', bugsTab)!;
bugsCounter.textContent = '0';
bugsCounter.title = '';
@@ -123,8 +123,8 @@ async function addBugsTab(): Promise<void | false> {
// TODO: Use native highlighting https://github.com/refined-github/refined-github/pull/6909#discussion_r1322607091
function highlightBugsTab(): void {
// Remove highlighting from "Issues" tab
- unhighlightTab(select('.UnderlineNav-item[data-hotkey="g i"]')!);
- highlightTab(select('.rgh-bugs-tab')!);
+ unhighlightTab($('.UnderlineNav-item[data-hotkey="g i"]')!);
+ highlightTab($('.rgh-bugs-tab')!);
}
async function removePinnedIssues(): Promise<void> {
@@ -156,7 +156,7 @@ async function updateBugsTagHighlighting(): Promise<void | false> {
}
async function init(): Promise<void | false> {
- if (!select.exists('.rgh-bugs-tab')) {
+ if (!elementExists('.rgh-bugs-tab')) {
await addBugsTab();
}
diff --git a/source/features/clean-conversation-filters.tsx b/source/features/clean-conversation-filters.tsx
index 9d4c72b0..8853a6ce 100644
--- a/source/features/clean-conversation-filters.tsx
+++ b/source/features/clean-conversation-filters.tsx
@@ -1,5 +1,5 @@
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -15,7 +15,7 @@ const hasAnyProjects = new CachedFunction('has-projects', {
return true;
}
- const isOrganization = select.exists('[rel=author][data-hovercard-type="organization"]');
+ const isOrganization = elementExists('[rel=author][data-hovercard-type="organization"]');
if (!activeProjectsCounter && !isOrganization) {
// No tab = Projects disabled in repo
// No organization = no Projects in organization
diff --git a/source/features/clean-conversation-headers.tsx b/source/features/clean-conversation-headers.tsx
index 7d9249c8..7476a1ca 100644
--- a/source/features/clean-conversation-headers.tsx
+++ b/source/features/clean-conversation-headers.tsx
@@ -1,6 +1,6 @@
import './clean-conversation-headers.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import elementReady from 'element-ready';
import {ArrowLeftIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -14,7 +14,7 @@ async function cleanIssueHeader(byline: HTMLElement): Promise<void> {
// Shows on issues: octocat opened this issue on 1 Jan · [1 comments]
// Removes on issues: octocat opened this issue on 1 Jan [·] 1 comments
- const commentCount = select('relative-time', byline)!.nextSibling!;
+ const commentCount = $('relative-time', byline)!.nextSibling!;
commentCount.replaceWith(<span>{commentCount.textContent.replace('·', '')}</span>);
}
@@ -23,13 +23,13 @@ async function cleanPrHeader(byline: HTMLElement): Promise<void> {
// Extra author name is only shown on `isPRConversation`
// Hide if it's the same as the opener (always) or merger
- const shouldHideAuthor = pageDetect.isPRConversation() && select('.author', byline)!.textContent === (await elementReady('.TimelineItem .author'))!.textContent;
+ const shouldHideAuthor = pageDetect.isPRConversation() && $('.author', byline)!.textContent === (await elementReady('.TimelineItem .author'))!.textContent;
if (shouldHideAuthor) {
byline.classList.add('rgh-clean-conversation-headers-hide-author');
}
- const base = select('.commit-ref', byline)!;
- const baseBranchDropdown = select('.commit-ref-dropdown', byline);
+ const base = $('.commit-ref', byline)!;
+ const baseBranchDropdown = $('.commit-ref-dropdown', byline);
// Shows on PRs: main [←] feature
const arrowIcon = <ArrowLeftIcon className="v-align-middle mx-1"/>;
diff --git a/source/features/clean-conversation-sidebar.tsx b/source/features/clean-conversation-sidebar.tsx
index 8a4aa0dd..22906be6 100644
--- a/source/features/clean-conversation-sidebar.tsx
+++ b/source/features/clean-conversation-sidebar.tsx
@@ -1,6 +1,6 @@
import './clean-conversation-sidebar.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import onetime from 'onetime';
import * as pageDetect from 'github-url-detection';
@@ -10,7 +10,7 @@ import observe from '../helpers/selector-observer.js';
import {removeTextNodeContaining} from '../helpers/dom-utils.js';
import {isHasSelectorSupported} from '../helpers/select-has.js';
-const canEditSidebar = onetime((): boolean => select.exists('.discussion-sidebar-item [data-hotkey="l"]'));
+const canEditSidebar = onetime((): boolean => elementExists('.discussion-sidebar-item [data-hotkey="l"]'));
function getNodesAfter(node: Node): Range {
const range = new Range();
@@ -20,12 +20,12 @@ function getNodesAfter(node: Node): Range {
}
async function cleanReviewers(): Promise<void> {
- const possibleReviewers = select('[src$="/suggested-reviewers"]');
+ const possibleReviewers = $('[src$="/suggested-reviewers"]');
if (possibleReviewers) {
await onElementRemoval(possibleReviewers);
}
- const content = select('[aria-label="Select reviewers"] > .css-truncate')!;
+ const content = $('[aria-label="Select reviewers"] > .css-truncate')!;
if (!content.firstElementChild) {
removeTextNodeContaining(content, 'No reviews');
}
@@ -47,7 +47,7 @@ Expected DOM:
@param selector Element that contains `details` or `.discussion-sidebar-heading` or distinctive element inside it
*/
function cleanSection(selector: string): boolean {
- const container = select(`:is(form, .discussion-sidebar-item):has(${selector})`);
+ const container = $(`:is(form, .discussion-sidebar-item):has(${selector})`);
if (!container) {
return false;
}
@@ -59,7 +59,7 @@ function cleanSection(selector: string): boolean {
'[aria-label="Select projects"] .Link--primary',
];
- const heading = select([
+ const heading = $([
'details:has(> .discussion-sidebar-heading)', // Can edit sidebar, has a dropdown
'.discussion-sidebar-heading', // Cannot editor sidebar, has a plain heading
], container)!;
@@ -79,17 +79,17 @@ function cleanSection(selector: string): boolean {
}
async function cleanSidebar(): Promise<void> {
- select('#partial-discussion-sidebar')!.classList.add('rgh-clean-sidebar');
+ $('#partial-discussion-sidebar')!.classList.add('rgh-clean-sidebar');
// Assignees
- const assignees = select('.js-issue-assignees')!;
+ const assignees = $('.js-issue-assignees')!;
if (assignees.children.length === 0) {
assignees.closest('.discussion-sidebar-item')!.remove();
} else {
- const assignYourself = select('.js-issue-assign-self');
+ const assignYourself = $('.js-issue-assign-self');
if (assignYourself) {
removeTextNodeContaining(assignYourself.previousSibling!, 'No one—');
- select('[aria-label="Select assignees"] summary')!.append(
+ $('[aria-label="Select assignees"] summary')!.append(
<span style={{fontWeight: 'normal'}}> – {assignYourself}</span>,
);
assignees.closest('.discussion-sidebar-item')!.classList.add('rgh-clean-sidebar');
@@ -104,20 +104,20 @@ async function cleanSidebar(): Promise<void> {
// Labels
if (!cleanSection('.js-issue-labels') && !canEditSidebar()) {
// Hide heading in any case except `canEditSidebar`
- select('.discussion-sidebar-item:has(.js-issue-labels) .discussion-sidebar-heading')!
+ $('.discussion-sidebar-item:has(.js-issue-labels) .discussion-sidebar-heading')!
.remove();
}
// Development (linked issues/PRs)
- const developmentHint = select('[aria-label="Link issues"] p');
+ const developmentHint = $('[aria-label="Link issues"] p');
if (developmentHint) { // This may not exist if issues are disabled
removeTextNodeContaining(developmentHint, /No branches or pull requests|Successfully merging/);
}
- const createBranchLink = select('button[data-action="click:create-issue-branch#openDialog"]');
+ const createBranchLink = $('button[data-action="click:create-issue-branch#openDialog"]');
if (createBranchLink) {
createBranchLink.classList.add('Link--muted');
- select('[aria-label="Link issues"] summary')!.append(
+ $('[aria-label="Link issues"] summary')!.append(
<span style={{fontWeight: 'normal'}}> – {createBranchLink}</span>,
);
}
diff --git a/source/features/clean-repo-filelist-actions.tsx b/source/features/clean-repo-filelist-actions.tsx
index 11bc1add..1c47242c 100644
--- a/source/features/clean-repo-filelist-actions.tsx
+++ b/source/features/clean-repo-filelist-actions.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {CodeIcon, PlusIcon, SearchIcon} from '@primer/octicons-react';
@@ -38,11 +38,11 @@ function cleanFilelistActions(searchButton: Element): void {
return;
}
- const codeDropdownButton = select('get-repo summary')!;
+ const codeDropdownButton = $('get-repo summary')!;
addTooltipToSummary(codeDropdownButton, 'Clone, open or download');
- const label = select('.Button-label', codeDropdownButton)!;
- if (!select.exists('.octicon-code', codeDropdownButton)) {
+ const label = $('.Button-label', codeDropdownButton)!;
+ if (!elementExists('.octicon-code', codeDropdownButton)) {
// The icon is missing for users without Codespaces https://github.com/refined-github/refined-github/pull/5074#issuecomment-983251719
label.before(<span className="Button-visual Button-leadingVisual"><CodeIcon/></span>);
}
diff --git a/source/features/clean-repo-sidebar.tsx b/source/features/clean-repo-sidebar.tsx
index 313a3b06..a941d3b1 100644
--- a/source/features/clean-repo-sidebar.tsx
+++ b/source/features/clean-repo-sidebar.tsx
@@ -1,5 +1,5 @@
import './clean-repo-sidebar.css';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import domLoaded from 'dom-loaded';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -15,7 +15,7 @@ async function cleanReleases(): Promise<void> {
}
const releasesSection = sidebarReleases.closest('.BorderGrid-cell')!;
- if (!select.exists('.octicon-tag', releasesSection)) {
+ if (!elementExists('.octicon-tag', releasesSection)) {
// Hide the whole section if there's no releases
releasesSection.hidden = true;
return;
@@ -39,7 +39,7 @@ async function hideEmptyPackages(): Promise<void> {
async function hideLanguageHeader(): Promise<void> {
await domLoaded;
- const lastSidebarHeader = select('.Layout-sidebar .BorderGrid-row:last-of-type h2');
+ const lastSidebarHeader = $('.Layout-sidebar .BorderGrid-row:last-of-type h2');
if (lastSidebarHeader?.textContent === 'Languages') {
lastSidebarHeader.hidden = true;
}
@@ -50,17 +50,17 @@ async function hideEmptyMeta(): Promise<void> {
await domLoaded;
if (!pageDetect.canUserEditRepo()) {
- select('.Layout-sidebar .BorderGrid-cell > .text-italic')?.remove();
+ $('.Layout-sidebar .BorderGrid-cell > .text-italic')?.remove();
}
}
async function moveReportLink(): Promise<void> {
await domLoaded;
- const reportLink = select('.Layout-sidebar a[href^="/contact/report-content"]')?.parentElement;
+ const reportLink = $('.Layout-sidebar a[href^="/contact/report-content"]')?.parentElement;
if (reportLink) {
// Your own repos don't include this link
- select('.Layout-sidebar .BorderGrid-row:last-of-type .BorderGrid-cell')!.append(reportLink);
+ $('.Layout-sidebar .BorderGrid-row:last-of-type .BorderGrid-cell')!.append(reportLink);
}
}
diff --git a/source/features/clean-repo-tabs.tsx b/source/features/clean-repo-tabs.tsx
index 9b9b45f6..8ba3e550 100644
--- a/source/features/clean-repo-tabs.tsx
+++ b/source/features/clean-repo-tabs.tsx
@@ -1,5 +1,5 @@
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -27,24 +27,24 @@ function mustKeepTab(tab: HTMLElement): boolean {
}
function setTabCounter(tab: HTMLElement, count: number): void {
- const tabCounter = select('.Counter', tab)!;
+ const tabCounter = $('.Counter', tab)!;
tabCounter.textContent = abbreviateNumber(count);
tabCounter.title = count > 999 ? String(count) : '';
}
function onlyShowInDropdown(id: string): void {
- const tabItem = select(`[data-tab-item$="${id}"]`);
+ const tabItem = $(`[data-tab-item$="${id}"]`);
if (!tabItem && pageDetect.isEnterprise()) { // GHE #3962
return;
}
(tabItem!.closest('li') ?? tabItem!.closest('.UnderlineNav-item'))!.classList.add('d-none');
- const menuItem = select(`[data-menu-item$="${id}"]`)!;
+ const menuItem = $(`[data-menu-item$="${id}"]`)!;
menuItem.removeAttribute('data-menu-item');
menuItem.hidden = false;
// The item has to be moved somewhere else because the overflow nav is order-dependent
- select('.UnderlineNav-actions ul')!.append(menuItem);
+ $('.UnderlineNav-actions ul')!.append(menuItem);
}
const wikiPageCount = new CachedFunction('wiki-page-count', {
diff --git a/source/features/clear-pr-merge-commit-message.tsx b/source/features/clear-pr-merge-commit-message.tsx
index 275c111d..ee1819b0 100644
--- a/source/features/clear-pr-merge-commit-message.tsx
+++ b/source/features/clear-pr-merge-commit-message.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -51,7 +51,7 @@ void features.add(import.meta.url, {
],
exclude: [
// Don't clear 1-commit PRs #3140
- () => select.all('.TimelineItem.js-commit').length === 1,
+ () => $$('.TimelineItem.js-commit').length === 1,
],
awaitDomReady: true, // Appears near the end of the page anyway
init,
diff --git a/source/features/close-out-of-view-modals.tsx b/source/features/close-out-of-view-modals.tsx
index 47eec3bc..0fd98065 100644
--- a/source/features/close-out-of-view-modals.tsx
+++ b/source/features/close-out-of-view-modals.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$$} from 'select-dom';
import onetime from 'onetime';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -38,7 +38,7 @@ function menuActivatedHandler(event: DelegateEvent): void {
lastOpen = Date.now();
- const modals = select.all([
+ const modals = $$([
':scope > details-menu', // "Watch repo" dropdown
':scope > details-dialog', // "Watch repo" dropdown
':scope > div > .dropdown-menu', // "Clone or download" and "Repo nav overflow"
diff --git a/source/features/closing-remarks.tsx b/source/features/closing-remarks.tsx
index 39049f31..03858779 100644
--- a/source/features/closing-remarks.tsx
+++ b/source/features/closing-remarks.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {TagIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -43,7 +43,7 @@ function createReleaseUrl(): string | undefined {
}
async function init(signal: AbortSignal): Promise<void> {
- const mergeCommit = select(`.TimelineItem.js-details-container.Details a[href^="/${getRepo()!.nameWithOwner}/commit/" i] > code`)!.textContent;
+ const mergeCommit = $(`.TimelineItem.js-details-container.Details a[href^="/${getRepo()!.nameWithOwner}/commit/" i] > code`)!.textContent;
const tagName = await firstTag.get(mergeCommit);
if (tagName) {
diff --git a/source/features/comment-fields-keyboard-shortcuts.tsx b/source/features/comment-fields-keyboard-shortcuts.tsx
index b765cb3c..e81ff0be 100644
--- a/source/features/comment-fields-keyboard-shortcuts.tsx
+++ b/source/features/comment-fields-keyboard-shortcuts.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import {DelegateEvent} from 'delegate-it';
import * as pageDetect from 'github-url-detection';
import filterAlteredClicks from 'filter-altered-clicks';
@@ -9,7 +9,7 @@ import {onCommentFieldKeydown} from '../github-events/on-field-keydown.js';
function handleEscapeKey(event: DelegateEvent<KeyboardEvent, HTMLTextAreaElement>, targetField: HTMLTextAreaElement): void {
// Cancel buttons have different classes for inline comments and editable comments
- const cancelButton = select(`
+ const cancelButton = $(`
button.js-hide-inline-comment-form,
button.js-comment-cancel-button
`, targetField.form!);
@@ -32,13 +32,13 @@ function handleArrowUpKey(targetField: HTMLTextAreaElement): void {
'#all_commit_comments', // Single commit comments at the bottom
])!;
- const lastOwnComment = select
- .all('.js-comment.current-user', currentConversationContainer)
- .reverse()
- .find(comment => {
- const collapsible = comment.closest('details');
- return !collapsible || collapsible.open;
- });
+ const lastOwnComment
+ = $$('.js-comment.current-user', currentConversationContainer)
+ .reverse()
+ .find(comment => {
+ const collapsible = comment.closest('details');
+ return !collapsible || collapsible.open;
+ });
if (!lastOwnComment) {
return;
@@ -56,7 +56,7 @@ function handleArrowUpKey(targetField: HTMLTextAreaElement): void {
// Move caret to end of the field
requestAnimationFrame(() => {
- select('textarea.js-comment-field', lastOwnComment)!.selectionStart = Number.MAX_SAFE_INTEGER;
+ $('textarea.js-comment-field', lastOwnComment)!.selectionStart = Number.MAX_SAFE_INTEGER;
});
}
diff --git a/source/features/comments-time-machine-links.tsx b/source/features/comments-time-machine-links.tsx
index 6ea729d4..2c932650 100644
--- a/source/features/comments-time-machine-links.tsx
+++ b/source/features/comments-time-machine-links.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -17,7 +17,7 @@ async function updateURLtoDatedSha(url: GitHubFileURL, date: string): Promise<vo
const {repository} = await api.v4(GetCommitAtDate, {variables: {date, branch: url.branch}});
const [{oid}] = repository.ref.target.history.nodes;
- select('a.rgh-link-date')!.pathname = url.assign({branch: oid}).pathname;
+ $('a.rgh-link-date')!.pathname = url.assign({branch: oid}).pathname;
}
async function showTimeMachineBar(): Promise<void | false> {
@@ -65,7 +65,7 @@ async function showTimeMachineBar(): Promise<void | false> {
function addInlineLinks(menu: HTMLElement, timestamp: string): void {
const comment = menu.closest('.js-comment')!;
// TODO: Move selector directly to observer
- const links = select.all(`
+ const links = $$(`
a[href^="${location.origin}"][href*="/blob/"]:not(.${linkifiedURLClass}),
a[href^="${location.origin}"][href*="/tree/"]:not(.${linkifiedURLClass})
`, comment);
@@ -86,7 +86,7 @@ function addInlineLinks(menu: HTMLElement, timestamp: string): void {
}
function addDropdownLink(menu: HTMLElement, timestamp: string): void {
- select('.show-more-popover', menu.parentElement!)!.append(
+ $('.show-more-popover', menu.parentElement!)!.append(
<div className="dropdown-divider"/>,
<a
href={buildRepoURL(`tree/HEAD@{${timestamp}}`)}
diff --git a/source/features/conversation-activity-filter.tsx b/source/features/conversation-activity-filter.tsx
index 22157c27..2525d27b 100644
--- a/source/features/conversation-activity-filter.tsx
+++ b/source/features/conversation-activity-filter.tsx
@@ -1,7 +1,7 @@
import './conversation-activity-filter.css';
import delay from 'delay';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {CheckIcon, EyeClosedIcon, EyeIcon, XIcon} from '@primer/octicons-react';
@@ -26,7 +26,7 @@ const collapsedClassName = 'rgh-conversation-activity-collapsed';
function processTimelineEvent(item: HTMLElement): void {
// Don't hide commits in PR conversation timelines #5581
- if (pageDetect.isPR() && select.exists('.TimelineItem-badge .octicon-git-commit', item)) {
+ if (pageDetect.isPR() && elementExists('.TimelineItem-badge .octicon-git-commit', item)) {
return;
}
@@ -35,7 +35,7 @@ function processTimelineEvent(item: HTMLElement): void {
function processSimpleComment(item: HTMLElement): void {
// Hide comments marked as resolved/hidden
- if (select.exists('.minimized-comment > details', item)) {
+ if (elementExists('.minimized-comment > details', item)) {
item.classList.add(collapsedClassName);
}
}
@@ -44,19 +44,19 @@ function processDissmissedReviewEvent(item: HTMLElement): void {
item.classList.add(hiddenClassName);
// Find and hide stale reviews referenced by dismissed review events
- for (const {hash: staleReviewId} of select.all<HTMLAnchorElement>('.TimelineItem-body > [href^="#pullrequestreview-"]', item)) {
- select(staleReviewId)!
+ for (const {hash: staleReviewId} of $$('.TimelineItem-body > a[href^="#pullrequestreview-"]', item)) {
+ $(staleReviewId)!
.closest('.js-timeline-item')!
.classList.add(collapsedClassName);
}
}
function processReview(review: HTMLElement): void {
- const hasMainComment = select.exists('.js-comment[id^=pullrequestreview] .timeline-comment', review);
+ const hasMainComment = elementExists('.js-comment[id^=pullrequestreview] .timeline-comment', review);
// Don't combine the selectors or use early returns without understanding what a thread or thread comment is
- const unresolvedThreads = select.all('.js-resolvable-timeline-thread-container[data-resolved="false"]', review);
- const unresolvedThreadComments = select.all('.timeline-comment-group:not(.minimized-comment)', review);
+ const unresolvedThreads = $$('.js-resolvable-timeline-thread-container[data-resolved="false"]', review);
+ const unresolvedThreadComments = $$('.timeline-comment-group:not(.minimized-comment)', review);
if (!hasMainComment && (unresolvedThreads.length === 0 || unresolvedThreadComments.length === 0)) {
review.classList.add(collapsedClassName); // The whole review is essentially resolved
@@ -73,15 +73,15 @@ function processReview(review: HTMLElement): void {
function processItem(item: HTMLElement): void {
// Exclude deep-linked comment
- if (location.hash.startsWith('#issuecomment-') && select.exists(location.hash, item)) {
+ if (location.hash.startsWith('#issuecomment-') && elementExists(location.hash, item)) {
return;
}
- if (select.exists('.js-comment[id^=pullrequestreview]', item)) {
+ if (elementExists('.js-comment[id^=pullrequestreview]', item)) {
processReview(item);
- } else if (select.exists('.TimelineItem-badge .octicon-x', item)) {
+ } else if (elementExists('.TimelineItem-badge .octicon-x', item)) {
processDissmissedReviewEvent(item);
- } else if (select.exists('.comment-body', item)) {
+ } else if (elementExists('.comment-body', item)) {
processSimpleComment(item);
} else {
processTimelineEvent(item);
@@ -92,12 +92,12 @@ async function handleSelection({target}: Event): Promise<void> {
// The event is fired before the DOM is updated. Extensions can't access the event’s `detail` where the widget would normally specify which element was selected
await delay(1);
- const state = select('[aria-checked="true"]', target as Element)!.dataset.value as State;
+ const state = $('[aria-checked="true"]', target as Element)!.dataset.value as State;
applyState(state);
}
function applyState(state: State): void {
- const container = select('.js-issues-results')!;
+ const container = $('.js-issues-results')!;
container.classList.toggle(
'rgh-conversation-activity-is-filtered',
state !== 'default',
@@ -108,11 +108,11 @@ function applyState(state: State): void {
);
// Update the state of the dropdowns
- for (const dropdownItem of select.all(`.${dropdownClass} [aria-checked="false"][data-value="${state}"]`)) {
+ for (const dropdownItem of $$(`.${dropdownClass} [aria-checked="false"][data-value="${state}"]`)) {
dropdownItem.setAttribute('aria-checked', 'true');
}
- for (const dropdownItem of select.all(`.${dropdownClass} [aria-checked="true"]:not([data-value="${state}"])`)) {
+ for (const dropdownItem of $$(`.${dropdownClass} [aria-checked="true"]:not([data-value="${state}"])`)) {
dropdownItem.setAttribute('aria-checked', 'false');
}
}
@@ -194,12 +194,12 @@ const minorFixesIssuePages = [
function uncollapseTargetedComment(): void {
if (location.hash.startsWith('#issuecomment-')) {
- select(`.${collapsedClassName} ${location.hash}`)?.closest('.js-timeline-item')?.classList.remove(collapsedClassName);
+ $(`.${collapsedClassName} ${location.hash}`)?.closest('.js-timeline-item')?.classList.remove(collapsedClassName);
}
}
function switchToNextFilter(): void {
- const state = select(`.${dropdownClass} [aria-checked="true"]`)!.dataset.value as State;
+ const state = $(`.${dropdownClass} [aria-checked="true"]`)!.dataset.value as State;
// eslint-disable-next-line default-case
switch (state) {
case 'default': {
diff --git a/source/features/conversation-links-on-repo-lists.tsx b/source/features/conversation-links-on-repo-lists.tsx
index 2f1f688b..69dba775 100644
--- a/source/features/conversation-links-on-repo-lists.tsx
+++ b/source/features/conversation-links-on-repo-lists.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {GitPullRequestIcon, IssueOpenedIcon} from '@primer/octicons-react';
@@ -11,11 +11,11 @@ function addConversationLinks(repositoryLink: HTMLAnchorElement): void {
const repository = repositoryLink.closest('li')!;
// Remove the "X issues need help" link
- select('[href*="issues?q=label%3A%22help+wanted"]', repository)?.remove();
+ $('[href*="issues?q=label%3A%22help+wanted"]', repository)?.remove();
// Place before the update date
assertNodeContent(
- select('relative-time', repository)!.previousSibling,
+ $('relative-time', repository)!.previousSibling,
'Updated',
).before(
<a
diff --git a/source/features/convert-pr-to-draft-improvements.tsx b/source/features/convert-pr-to-draft-improvements.tsx
index def1efbc..cd377ed9 100644
--- a/source/features/convert-pr-to-draft-improvements.tsx
+++ b/source/features/convert-pr-to-draft-improvements.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -13,14 +13,14 @@ function closeModal({delegateTarget: button}: DelegateEvent<MouseEvent, HTMLButt
}
function addConvertToDraftButton(alternativeActions: Element): void {
- const existingButton = select('[data-url$="/convert_to_draft"]');
+ const existingButton = $('[data-url$="/convert_to_draft"]');
// Needs to check the existence of both to guarantee the non-draft state
- if (!existingButton || select.exists('[action$="/ready_for_review"]')) {
+ if (!existingButton || elementExists('[action$="/ready_for_review"]')) {
return;
}
const convertToDraft = existingButton.closest('details')!.cloneNode(true);
- select('.Link--muted', convertToDraft)!.classList.remove('Link--muted');
+ $('.Link--muted', convertToDraft)!.classList.remove('Link--muted');
alternativeActions.prepend(convertToDraft);
}
diff --git a/source/features/convert-release-to-draft.tsx b/source/features/convert-release-to-draft.tsx
index ed576ecb..47c5f3be 100644
--- a/source/features/convert-release-to-draft.tsx
+++ b/source/features/convert-release-to-draft.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate from 'delegate-it';
@@ -21,7 +21,7 @@ async function convertToDraft(): Promise<void> {
},
});
- select(getReleaseEditLinkSelector())!.click(); // Visit "Edit release" page
+ $(getReleaseEditLinkSelector())!.click(); // Visit "Edit release" page
}
const confirmMessage = 'The release will be effectively deleted and a new draft will be created.';
@@ -29,7 +29,7 @@ const confirmMessageWithReactions = 'Existing user reactions will be lost.';
const confirmMessageQuestion = 'Continue?';
async function onConvertClick(): Promise<void> {
- const message = select.exists('.js-reaction-group-button')
+ const message = elementExists('.js-reaction-group-button')
? [confirmMessage, confirmMessageWithReactions, confirmMessageQuestion]
: [confirmMessage, confirmMessageQuestion];
if (!confirm(message.join(' '))) {
@@ -44,7 +44,7 @@ async function onConvertClick(): Promise<void> {
}
function attachButton(editButton: HTMLAnchorElement): void {
- if (select.exists('[title="Draft"]')) {
+ if (elementExists('[title="Draft"]')) {
return;
}
diff --git a/source/features/cross-deleted-pr-branches.tsx b/source/features/cross-deleted-pr-branches.tsx
index da4bfd7b..49ba577b 100644
--- a/source/features/cross-deleted-pr-branches.tsx
+++ b/source/features/cross-deleted-pr-branches.tsx
@@ -1,15 +1,15 @@
import './cross-deleted-pr-branches.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, lastElement} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {wrap} from '../helpers/dom-utils.js';
import features from '../feature-manager.js';
function init(): void | false {
- const lastBranchAction = select.last('.TimelineItem-body .user-select-contain.commit-ref');
+ const lastBranchAction = lastElement('.TimelineItem-body .user-select-contain.commit-ref');
- const headReferenceLink = select('.head-ref a');
+ const headReferenceLink = $('.head-ref a');
if (!headReferenceLink && !lastBranchAction) {
return; // Don't return false, This feature’s CSS already takes care of this
}
@@ -20,7 +20,7 @@ function init(): void | false {
const deletedBranchName = lastBranchAction.textContent.trim();
const repoRootUrl = headReferenceLink?.href.split('/', 5).join('/');
- for (const element of select.all('.commit-ref')) {
+ for (const element of $$('.commit-ref')) {
const branchName = element.textContent.trim();
if (branchName === deletedBranchName) {
element.title = 'This branch has been deleted';
@@ -30,7 +30,7 @@ function init(): void | false {
}
if (element.classList.contains('head-ref')) {
- select('a', element)!.href = repoRootUrl!;
+ $('a', element)!.href = repoRootUrl!;
} else {
wrap(element, <a href={repoRootUrl}/>);
}
diff --git a/source/features/deep-reblame.tsx b/source/features/deep-reblame.tsx
index 78fb90e7..3402794a 100644
--- a/source/features/deep-reblame.tsx
+++ b/source/features/deep-reblame.tsx
@@ -1,7 +1,7 @@
import './deep-reblame.css';
import mem from 'mem';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import {VersionsIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -45,13 +45,13 @@ async function redirectToBlameCommit(event: DelegateEvent<MouseEvent, HTMLAnchor
blameElement.blur(); // Hide tooltip after click, it’s shown on :focus
const blameHunk = blameElement.closest('.blame-hunk')!;
- const prNumbers = select.all('.issue-link', blameHunk).map(pr => looseParseInt(pr));
- const prCommit = select('a.message', blameHunk)!.pathname.split('/').pop()!;
+ const prNumbers = $$('.issue-link', blameHunk).map(pr => looseParseInt(pr));
+ const prCommit = $('a.message', blameHunk)!.pathname.split('/').pop()!;
const blameUrl = new GitHubFileURL(location.href);
await showToast(async () => {
blameUrl.branch = await getPullRequestBlameCommit(prCommit, prNumbers, blameUrl.filePath);
- blameUrl.hash = 'L' + select('.js-line-number', blameHunk)!.textContent;
+ blameUrl.hash = 'L' + $('.js-line-number', blameHunk)!.textContent;
location.href = blameUrl.href;
}, {
message: 'Fetching pull request',
@@ -62,12 +62,12 @@ async function redirectToBlameCommit(event: DelegateEvent<MouseEvent, HTMLAnchor
function addButton(pullRequest: HTMLElement): void {
const hunk = pullRequest.closest('.blame-hunk')!;
- const reblameLink = select('.reblame-link', hunk);
+ const reblameLink = $('.reblame-link', hunk);
if (reblameLink) {
reblameLink.setAttribute('aria-label', 'View blame prior to this change. Hold `Alt` to extract commits from this PR first');
reblameLink.classList.add('rgh-deep-reblame');
} else {
- select('.blob-reblame', hunk)!.append(
+ $('.blob-reblame', hunk)!.append(
<button
type="button"
aria-label="View blame prior to this change (extracts commits from this PR first)"
diff --git a/source/features/dim-bots.tsx b/source/features/dim-bots.tsx
index 53093b57..36c8a3a7 100644
--- a/source/features/dim-bots.tsx
+++ b/source/features/dim-bots.tsx
@@ -1,5 +1,5 @@
import './dim-bots.css';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -43,7 +43,7 @@ function undimBots(event: DelegateEvent): void {
}
const resetScroll = preserveScroll(target);
- for (const bot of select.all(dimBots.selector)) {
+ for (const bot of $$(dimBots.selector)) {
bot.classList.add('rgh-interacted');
}
@@ -51,14 +51,14 @@ function undimBots(event: DelegateEvent): void {
}
function init(signal: AbortSignal): void {
- for (const bot of select.all(commitSelectors)) {
+ for (const bot of $$(commitSelectors)) {
// Exclude co-authored commits
- if (select.all('a', bot.parentElement!).every(link => link.matches(commitSelectors))) {
+ if ($$('a', bot.parentElement!).every(link => link.matches(commitSelectors))) {
bot.closest('.commit, .Box-row')!.classList.add(dimBots.class);
}
}
- for (const bot of select.all(prSelectors)) {
+ for (const bot of $$(prSelectors)) {
bot.closest('.commit, .Box-row')!.classList.add(dimBots.class);
}
diff --git a/source/features/easy-toggle-commit-messages.tsx b/source/features/easy-toggle-commit-messages.tsx
index 3c40d38f..d38078b1 100644
--- a/source/features/easy-toggle-commit-messages.tsx
+++ b/source/features/easy-toggle-commit-messages.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -16,7 +16,7 @@ function toggleCommitMessage(event: DelegateEvent<MouseEvent>): void {
return;
}
- select('.ellipsis-expander', event.delegateTarget)?.dispatchEvent(
+ $('.ellipsis-expander', event.delegateTarget)?.dispatchEvent(
new MouseEvent('click', {bubbles: true, altKey: event.altKey}),
);
}
diff --git a/source/features/easy-toggle-files.tsx b/source/features/easy-toggle-files.tsx
index a6a30c48..db6d0381 100644
--- a/source/features/easy-toggle-files.tsx
+++ b/source/features/easy-toggle-files.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import delegate, {DelegateEvent} from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -10,7 +10,7 @@ function toggleFile(event: DelegateEvent<MouseEvent>): void {
// The clicked element is either the bar itself or one of its 2 children
if (elementClicked === headerBar || elementClicked.parentElement === headerBar) {
- select('[aria-label="Toggle diff contents"]', headerBar)!
+ $('[aria-label="Toggle diff contents"]', headerBar)!
.dispatchEvent(new MouseEvent('click', {bubbles: true, altKey: event.altKey}));
}
}
diff --git a/source/features/embed-gist-via-iframe.tsx b/source/features/embed-gist-via-iframe.tsx
index ffd037dc..570fdcdb 100644
--- a/source/features/embed-gist-via-iframe.tsx
+++ b/source/features/embed-gist-via-iframe.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import onetime from 'onetime';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -16,12 +16,12 @@ async function init(): Promise<void> {
// Set required content
embedViaIframe.setAttribute('aria-checked', 'false');
embedViaIframe.value = `<iframe src="${location.origin}${location.pathname}.pibb"></iframe>`;
- select('.select-menu-item-heading', embedViaIframe)!.textContent = 'Embed via <iframe>';
- select('.description', embedViaIframe)!.textContent = 'Embed this gist in your website via <iframe>.';
+ $('.select-menu-item-heading', embedViaIframe)!.textContent = 'Embed via <iframe>';
+ $('.description', embedViaIframe)!.textContent = 'Embed this gist in your website via <iframe>.';
// Modify description of the original embed type to distinguish the two items
- select('.select-menu-item-heading', embedViaScript)!.textContent = 'Embed via <script>';
- select('.description', embedViaScript)!.textContent = 'Embed this gist in your website via <script>.';
+ $('.select-menu-item-heading', embedViaScript)!.textContent = 'Embed via <script>';
+ $('.description', embedViaScript)!.textContent = 'Embed this gist in your website via <script>.';
embedViaScript!.after(embedViaIframe);
}
diff --git a/source/features/esc-to-cancel.tsx b/source/features/esc-to-cancel.tsx
index f22cfb31..307df683 100644
--- a/source/features/esc-to-cancel.tsx
+++ b/source/features/esc-to-cancel.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import {DelegateEvent} from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -7,7 +7,7 @@ import {onConversationTitleFieldKeydown} from '../github-events/on-field-keydown
function handleEscPress(event: DelegateEvent<KeyboardEvent>): void {
if (event.key === 'Escape') {
- select('.js-cancel-issue-edit')!.click();
+ $('.js-cancel-issue-edit')!.click();
event.stopImmediatePropagation();
event.preventDefault();
diff --git a/source/features/expand-all-hidden-comments.tsx b/source/features/expand-all-hidden-comments.tsx
index 8f65fac4..017c3e53 100644
--- a/source/features/expand-all-hidden-comments.tsx
+++ b/source/features/expand-all-hidden-comments.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import oneEvent from 'one-event';
import delegate, {DelegateEvent} from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -21,7 +21,7 @@ async function expandHidden(paginationButton: HTMLButtonElement | undefined) {
wrapper = wrapper.lastElementChild!;
}
- paginationButton = select(`:scope > ${paginationButtonSelector}`, wrapper);
+ paginationButton = $(`:scope > ${paginationButtonSelector}`, wrapper);
paginationButton?.click();
}
}
diff --git a/source/features/extend-conversation-status-filters.tsx b/source/features/extend-conversation-status-filters.tsx
index af04f4d3..8ccce012 100644
--- a/source/features/extend-conversation-status-filters.tsx
+++ b/source/features/extend-conversation-status-filters.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import {CheckIcon} from '@primer/octicons-react';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -15,7 +15,7 @@ function addMergeLink(): void {
// The links in `.table-list-header-toggle` are either:
// 1 Open | 1 Closed
// 1 Total // Apparently appears with is:merged/is:unmerged
- for (const lastLink of select.all('.table-list-header-toggle.states a:last-child')) {
+ for (const lastLink of $$('.table-list-header-toggle.states a:last-child')) {
const lastLinkQuery = SearchQuery.from(lastLink);
if (lastLinkQuery.includes('is:merged')) {
@@ -40,8 +40,8 @@ function addMergeLink(): void {
}
function togglableFilters(): void {
- for (const link of select.all('.table-list-header-toggle.states a')) {
- select('.octicon', link)?.remove();
+ for (const link of $$('.table-list-header-toggle.states a')) {
+ $('.octicon', link)?.remove();
if (link.classList.contains('selected')) {
link.prepend(<CheckIcon/>);
link.href = SearchQuery
diff --git a/source/features/extend-diff-expander.tsx b/source/features/extend-diff-expander.tsx
index 2c6de210..510040d3 100644
--- a/source/features/extend-diff-expander.tsx
+++ b/source/features/extend-diff-expander.tsx
@@ -1,5 +1,5 @@
import './extend-diff-expander.css';
-import select from 'select-dom';
+import {$} from 'select-dom';
import delegate, {DelegateEvent} from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -8,7 +8,7 @@ import features from '../feature-manager.js';
function expandDiff(event: DelegateEvent): void {
// Skip if the user clicked directly on the icon
if (!(event.target as Element).closest('.js-expand')) {
- select('.js-expand', event.delegateTarget)!.click();
+ $('.js-expand', event.delegateTarget)!.click();
}
}
diff --git a/source/features/github-actions-indicators.tsx b/source/features/github-actions-indicators.tsx
index 8d6e2e57..e3ae4034 100644
--- a/source/features/github-actions-indicators.tsx
+++ b/source/features/github-actions-indicators.tsx
@@ -1,6 +1,6 @@
import {CachedFunction} from 'webext-storage-cache';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import {StopIcon, PlayIcon} from '@primer/octicons-react';
import {parseCron} from '@cheap-glitch/mi-cron';
import * as pageDetect from 'github-url-detection';
@@ -90,7 +90,7 @@ const workflowDetails = new CachedFunction('workflows-details', {
async function addIndicators(workflowListItem: HTMLAnchorElement): Promise<void> {
// There might be a disabled indicator already
- if (select.exists('.octicon-stop', workflowListItem)) {
+ if (elementExists('.octicon-stop', workflowListItem)) {
return;
}
@@ -125,7 +125,7 @@ async function addIndicators(workflowListItem: HTMLAnchorElement): Promise<void>
}
const relativeTime = <relative-time datetime={String(nextTime)}/>;
- select('.ActionList-item-label', workflowListItem)!.append(
+ $('.ActionList-item-label', workflowListItem)!.append(
<em>
({relativeTime})
</em>,
diff --git a/source/features/global-conversation-list-filters.tsx b/source/features/global-conversation-list-filters.tsx
index b324bfb6..d9734294 100644
--- a/source/features/global-conversation-list-filters.tsx
+++ b/source/features/global-conversation-list-filters.tsx
@@ -1,6 +1,6 @@
import './global-conversation-list-filters.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -29,11 +29,11 @@ function addLinks(container: HTMLElement): void {
const isCurrentPage = SearchQuery.from(location).includes(query);
// Highlight it, if that's the current page
- if (isCurrentPage && !select.exists('.subnav-links .selected')) {
+ if (isCurrentPage && !elementExists('.subnav-links .selected')) {
link.classList.add('selected');
// Other links will keep the current query, that's not what we want
- for (const otherLink of select.all('.subnav-links a')) {
+ for (const otherLink of $$('.subnav-links a')) {
otherLink.href = SearchQuery.from(otherLink).remove(query).href;
}
}
diff --git a/source/features/hidden-review-comments-indicator.tsx b/source/features/hidden-review-comments-indicator.tsx
index 7533cc44..97f9652e 100644
--- a/source/features/hidden-review-comments-indicator.tsx
+++ b/source/features/hidden-review-comments-indicator.tsx
@@ -1,7 +1,7 @@
import './hidden-review-comments-indicator.css';
import mem from 'mem';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import {CommentIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -45,7 +45,7 @@ const indicatorToggleObserver = new MutationObserver(mutations => {
const wasVisible = mutation.oldValue!.includes('show-inline-notes');
const isHidden = !file.classList.contains('show-inline-notes');
if (wasVisible && isHidden) {
- for (const thread of select.all('tr.inline-comments', file)) {
+ for (const thread of $$('tr.inline-comments', file)) {
addIndicator(thread);
}
}
diff --git a/source/features/hide-inactive-deployments.tsx b/source/features/hide-inactive-deployments.tsx
index 4f762c29..44d1f76f 100644
--- a/source/features/hide-inactive-deployments.tsx
+++ b/source/features/hide-inactive-deployments.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -6,12 +6,12 @@ import features from '../feature-manager.js';
// This feature doesn't need an active observer
function init(): void {
// Selects all the deployments first so that we can leave the last one on the page
- const deployments = select.all('.js-socket-channel[data-url*="/partials/deployed_event/"]');
+ const deployments = $$('.js-socket-channel[data-url*="/partials/deployed_event/"]');
deployments.pop(); // Don't hide the last deployment, even if it is inactive
for (const deployment of deployments) {
// TODO: Rewrite with :has selector, CSS-only feature
- if (select.exists('[title="Deployment Status Label: Inactive"]', deployment)) {
+ if (elementExists('[title="Deployment Status Label: Inactive"]', deployment)) {
deployment.remove();
}
}
diff --git a/source/features/hide-issue-list-autocomplete.tsx b/source/features/hide-issue-list-autocomplete.tsx
index acad714b..c30a9c0a 100644
--- a/source/features/hide-issue-list-autocomplete.tsx
+++ b/source/features/hide-issue-list-autocomplete.tsx
@@ -1,10 +1,10 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
function init(): void {
- select('.subnav-search')!.setAttribute('autocomplete', 'off');
+ $('.subnav-search')!.setAttribute('autocomplete', 'off');
}
void features.add(import.meta.url, {
diff --git a/source/features/hide-low-quality-comments.tsx b/source/features/hide-low-quality-comments.tsx
index 43d1ad0b..5271c3ee 100644
--- a/source/features/hide-low-quality-comments.tsx
+++ b/source/features/hide-low-quality-comments.tsx
@@ -1,7 +1,7 @@
import './hide-low-quality-comments.css';
import delay from 'delay';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -11,18 +11,18 @@ import isLowQualityComment from '../helpers/is-low-quality-comment.js';
export const singleParagraphCommentSelector = '.comment-body > p:only-child';
async function unhide(event: DelegateEvent): Promise<void> {
- for (const comment of select.all('.rgh-hidden-comment')) {
+ for (const comment of $$('.rgh-hidden-comment')) {
comment.hidden = false;
}
await delay(10); // "Similar comments" aren't expanded without this in Safari #3830
// Expand all "similar comments" boxes
- for (const similarCommentsExpandButton of select.all('.rgh-hidden-comment > summary')) {
+ for (const similarCommentsExpandButton of $$('.rgh-hidden-comment > summary')) {
similarCommentsExpandButton.click();
}
- select('.rgh-hidden-comment')!.scrollIntoView();
+ $('.rgh-hidden-comment')!.scrollIntoView();
event.delegateTarget.parentElement!.remove();
}
@@ -32,13 +32,13 @@ function hideComment(comment: HTMLElement): void {
}
function init(): void {
- for (const similarCommentsBox of select.all('.js-discussion .Details-element:not([data-body-version])')) {
+ for (const similarCommentsBox of $$('.js-discussion .Details-element:not([data-body-version])')) {
hideComment(similarCommentsBox);
}
- const linkedComment = location.hash.startsWith('#issuecomment-') ? select(`${location.hash} ${singleParagraphCommentSelector}`) : undefined;
+ const linkedComment = location.hash.startsWith('#issuecomment-') ? $(`${location.hash} ${singleParagraphCommentSelector}`) : undefined;
- for (const commentText of select.all(singleParagraphCommentSelector)) {
+ for (const commentText of $$(singleParagraphCommentSelector)) {
// Exclude explicitely linked comments #5363
if (commentText === linkedComment) {
continue;
@@ -51,22 +51,22 @@ function init(): void {
// Comments that contain useful images or links shouldn't be removed
// Images are wrapped in <a> tags on GitHub hence included in the selector
// TODO: use :has()
- if (select.exists('a', commentText)) {
+ if (elementExists('a', commentText)) {
continue;
}
// Ensure that they're not by VIPs (owner, collaborators, etc)
// TODO: use :has()
const comment = commentText.closest('.js-timeline-item')!;
- if (select.exists('.Label', comment)) {
+ if (elementExists('.Label', comment)) {
continue;
}
// If the person is having a conversation, then don't hide it
- const author = select('.author', comment)!.getAttribute('href')!;
+ const author = $('.author', comment)!.getAttribute('href')!;
// If the first comment left by the author isn't a low quality comment
// (previously hidden or about to be hidden), then leave this one as well
- const previousComment = select(`.js-timeline-item:not([hidden]) .unminimized-comment .author[href="${author}"]`);
+ const previousComment = $(`.js-timeline-item:not([hidden]) .unminimized-comment .author[href="${author}"]`);
if (previousComment?.closest('.js-timeline-item') !== comment) {
continue;
}
@@ -74,9 +74,9 @@ function init(): void {
hideComment(comment);
}
- const lowQualityCount = select.all('.rgh-hidden-comment').length;
+ const lowQualityCount = $$('.rgh-hidden-comment').length;
if (lowQualityCount > 0) {
- select('.discussion-timeline-actions')!.prepend(
+ $('.discussion-timeline-actions')!.prepend(
<p className="rgh-low-quality-comments-note">
{`${lowQualityCount} unhelpful comment${lowQualityCount > 1 ? 's were' : ' was'} automatically hidden. `}
<button className="btn-link text-emphasized rgh-unhide-low-quality-comments" type="button">Show</button>
diff --git a/source/features/highest-rated-comment.tsx b/source/features/highest-rated-comment.tsx
index af91975f..3dd29971 100644
--- a/source/features/highest-rated-comment.tsx
+++ b/source/features/highest-rated-comment.tsx
@@ -1,7 +1,7 @@
import './highest-rated-comment.css';
import mem from 'mem';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {ArrowDownIcon, CheckCircleFillIcon} from '@primer/octicons-react';
@@ -38,7 +38,7 @@ const getPositiveReactions = mem((comment: HTMLElement): number | void => {
function getBestComment(): HTMLElement | undefined {
let highest;
- for (const reaction of select.all(positiveReactionsSelector)) {
+ for (const reaction of $$(positiveReactionsSelector)) {
const comment = reaction.closest(commentSelector)!;
const positiveReactions = getPositiveReactions(comment);
if (positiveReactions && (!highest || positiveReactions > highest.count)) {
@@ -50,8 +50,8 @@ function getBestComment(): HTMLElement | undefined {
}
function highlightBestComment(bestComment: Element): void {
- select('.unminimized-comment', bestComment)!.classList.add('rgh-highest-rated-comment');
- select('.unminimized-comment .timeline-comment-header > h3', bestComment)!.before(
+ $('.unminimized-comment', bestComment)!.classList.add('rgh-highest-rated-comment');
+ $('.unminimized-comment .timeline-comment-header > h3', bestComment)!.before(
<span
className="color-fg-success tooltipped tooltipped-s"
aria-label="This comment has the most positive reactions on this issue."
@@ -63,16 +63,16 @@ function highlightBestComment(bestComment: Element): void {
function linkBestComment(bestComment: HTMLElement): void {
// Find position of comment in thread
- const position = select.all(commentSelector).indexOf(bestComment);
+ const position = $$(commentSelector).indexOf(bestComment);
// Only link to it if it doesn't already appear at the top of the conversation
if (position < 3) {
return;
}
- const text = select('.comment-body', bestComment)!.textContent.slice(0, 100);
- const {hash} = select('a.js-timestamp', bestComment)!;
- const avatar = select('img.avatar', bestComment)!.cloneNode();
+ const text = $('.comment-body', bestComment)!.textContent.slice(0, 100);
+ const {hash} = $('a.js-timestamp', bestComment)!;
+ const avatar = $('img.avatar', bestComment)!.cloneNode();
bestComment.parentElement!.firstElementChild!.after(
<a href={hash} className="no-underline rounded-1 rgh-highest-rated-comment timeline-comment color-bg-subtle px-2 d-flex flex-items-center">
@@ -90,7 +90,7 @@ function linkBestComment(bestComment: HTMLElement): void {
}
function selectSum(selector: string, container: HTMLElement): number {
- return select.all(selector, container).reduce((sum, element) => sum + looseParseInt(element), 0);
+ return $$(selector, container).reduce((sum, element) => sum + looseParseInt(element), 0);
}
function init(): false | void {
@@ -99,7 +99,7 @@ function init(): false | void {
return false;
}
- const commentText = select(singleParagraphCommentSelector, bestComment)?.textContent;
+ const commentText = $(singleParagraphCommentSelector, bestComment)?.textContent;
if (commentText && isLowQualityComment(commentText)) { // #5567
return false;
}
diff --git a/source/features/highlight-collaborators-and-own-conversations.tsx b/source/features/highlight-collaborators-and-own-conversations.tsx
index eba3b7ae..38790c3a 100644
--- a/source/features/highlight-collaborators-and-own-conversations.tsx
+++ b/source/features/highlight-collaborators-and-own-conversations.tsx
@@ -1,6 +1,6 @@
import './highlight-collaborators-and-own-conversations.css';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import domLoaded from 'dom-loaded';
import * as pageDetect from 'github-url-detection';
@@ -11,8 +11,7 @@ import {buildRepoURL, cacheByRepo, getUsername} from '../github-helpers/index.js
const collaborators = new CachedFunction('repo-collaborators', {
async updater(): Promise<string[]> {
const dom = await fetchDom(buildRepoURL('issues/show_menu_content?partial=issues/filters/authors_content'));
- return select
- .all('.SelectMenu-item img[alt]', dom)
+ return $$('.SelectMenu-item img[alt]', dom)
.map(avatar => avatar.alt.slice(1));
},
maxAge: {days: 1},
@@ -23,7 +22,7 @@ const collaborators = new CachedFunction('repo-collaborators', {
async function highlightCollaborators(): Promise<void> {
const list = await collaborators.get();
await domLoaded;
- for (const author of select.all('.js-issue-row [data-hovercard-type="user"]')) {
+ for (const author of $$('.js-issue-row [data-hovercard-type="user"]')) {
if (list.includes(author.textContent.trim())) {
author.classList.add('rgh-collaborator');
}
@@ -32,7 +31,7 @@ async function highlightCollaborators(): Promise<void> {
function highlightSelf(): void {
// "Opened by {user}" and "Created by {user}"
- for (const author of select.all(`.opened-by a[title$="ed by ${CSS.escape(getUsername()!)}"]`)) {
+ for (const author of $$(`.opened-by a[title$="ed by ${CSS.escape(getUsername()!)}"]`)) {
author.classList.add('rgh-collaborator');
author.style.fontStyle = 'italic';
}
diff --git a/source/features/highlight-non-default-base-branch.tsx b/source/features/highlight-non-default-base-branch.tsx
index 6fc4b798..f119abb3 100644
--- a/source/features/highlight-non-default-base-branch.tsx
+++ b/source/features/highlight-non-default-base-branch.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {GitPullRequestIcon} from '@primer/octicons-react';
@@ -31,7 +31,7 @@ function buildQuery(issueIds: string[]): string {
}
async function init(): Promise<false | void> {
- const prLinks = select.all('.js-issue-row .js-navigation-open[data-hovercard-type="pull_request"]');
+ const prLinks = $$('.js-issue-row .js-navigation-open[data-hovercard-type="pull_request"]');
if (prLinks.length === 0) {
return false;
}
diff --git a/source/features/improve-shortcut-help.tsx b/source/features/improve-shortcut-help.tsx
index 4a9ee78c..14ccdee6 100644
--- a/source/features/improve-shortcut-help.tsx
+++ b/source/features/improve-shortcut-help.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import onetime from 'onetime';
import features from '../feature-manager.js';
@@ -10,7 +10,7 @@ function splitKeys(keys: string): DocumentFragment[] {
}
function improveShortcutHelp(dialog: Element): void {
- select('.Box-body .col-5 .Box:first-child', dialog)!.after(
+ $('.Box-body .col-5 .Box:first-child', dialog)!.after(
<div className="Box Box--condensed m-4">
<div className="Box-header">
<h2 className="Box-title">Refined GitHub</h2>
@@ -33,7 +33,7 @@ function improveShortcutHelp(dialog: Element): void {
}
const observer = new MutationObserver(([{target}]) => {
- if (target instanceof Element && !select.exists('.js-details-dialog-spinner', target)) {
+ if (target instanceof Element && !elementExists('.js-details-dialog-spinner', target)) {
improveShortcutHelp(target);
observer.disconnect();
}
@@ -44,7 +44,7 @@ function observeShortcutModal({key, target}: KeyboardEvent): void {
return;
}
- const modal = select('body > details:not(.js-command-palette-dialog) > details-dialog');
+ const modal = $('body > details:not(.js-command-palette-dialog) > details-dialog');
if (modal) {
observer.observe(modal, {childList: true});
}
diff --git a/source/features/infinite-scroll.tsx b/source/features/infinite-scroll.tsx
index f5df3ea9..be4f4022 100644
--- a/source/features/infinite-scroll.tsx
+++ b/source/features/infinite-scroll.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import debounce from 'debounce-fn';
import * as pageDetect from 'github-url-detection';
@@ -34,7 +34,7 @@ function copyFooter(originalFooter: HTMLElement): void {
child.classList.remove('pl-lg-4', 'col-xl-3');
}
- select('[aria-label^="Explore"]')!.append(
+ $('[aria-label^="Explore"]')!.append(
<div className="footer mt-4 py-4 border-top">
{footer}
</div>,
diff --git a/source/features/jump-to-change-requested-comment.tsx b/source/features/jump-to-change-requested-comment.tsx
index 3a6b72c4..e2809d94 100644
--- a/source/features/jump-to-change-requested-comment.tsx
+++ b/source/features/jump-to-change-requested-comment.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {wrap} from '../helpers/dom-utils.js';
@@ -7,9 +7,9 @@ import features from '../feature-manager.js';
import observe from '../helpers/selector-observer.js';
function linkify(textLine: HTMLElement): void {
- const url = select('a.dropdown-item[href^="#pullrequestreview-"]', textLine.parentElement!);
+ const url = $('a.dropdown-item[href^="#pullrequestreview-"]', textLine.parentElement!)!;
// `lastChild` is a textNode
- wrap(textLine.lastChild!, <a href={url!.hash}/>);
+ wrap(textLine.lastChild!, <a href={url.hash}/>);
}
function init(signal: AbortSignal): void {
diff --git a/source/features/jump-to-conversation-close-event.tsx b/source/features/jump-to-conversation-close-event.tsx
index 6ca8b97b..609cd649 100644
--- a/source/features/jump-to-conversation-close-event.tsx
+++ b/source/features/jump-to-conversation-close-event.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {css} from 'code-tag';
-import select from 'select-dom';
+import {lastElement} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {wrap} from '../helpers/dom-utils.js';
@@ -15,7 +15,7 @@ export const closedOrMergedMarkerSelector = css`
`;
export function getLastCloseEvent(): HTMLElement | undefined {
- return select.last(`
+ return lastElement(`
.TimelineItem-badge :is(
.octicon-issue-closed,
.octicon-git-merge,
diff --git a/source/features/keyboard-navigation.tsx b/source/features/keyboard-navigation.tsx
index ed781bd3..63a70c15 100644
--- a/source/features/keyboard-navigation.tsx
+++ b/source/features/keyboard-navigation.tsx
@@ -1,11 +1,11 @@
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
import {isEditable} from '../helpers/dom-utils.js';
const isCommentGroupMinimized = (comment: HTMLElement): boolean =>
- select.exists('.minimized-comment:not(.d-none)', comment)
+ elementExists('.minimized-comment:not(.d-none)', comment)
|| Boolean(comment.closest([
'.js-resolvable-thread-contents.d-none', // Regular comments
'details.js-resolvable-timeline-thread-container:not([open])', // Review comments
@@ -18,17 +18,17 @@ function runShortcuts(event: KeyboardEvent): void {
event.preventDefault();
- const focusedComment = select(':target')!;
- const items = select
- .all([
+ const focusedComment = $(':target')!;
+ const items
+ = $$([
'.js-targetable-element[id^="diff-"]', // Files in diffs
'.js-minimizable-comment-group', // Comments (to be `.filter()`ed)
])
- .filter(element =>
- element.classList.contains('js-minimizable-comment-group')
- ? !isCommentGroupMinimized(element)
- : true,
- );
+ .filter(element =>
+ element.classList.contains('js-minimizable-comment-group')
+ ? !isCommentGroupMinimized(element)
+ : true,
+ );
// `j` goes to the next comment, `k` goes back a comment
const direction = event.key === 'j' ? 1 : -1;
diff --git a/source/features/last-notification-page-button.tsx b/source/features/last-notification-page-button.tsx
index 5adc326d..1daaf319 100644
--- a/source/features/last-notification-page-button.tsx
+++ b/source/features/last-notification-page-button.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -10,7 +10,7 @@ import observe from '../helpers/selector-observer.js';
const itemsPerNotificationsPage = 25;
function linkify(nextButton: HTMLAnchorElement): void {
- const totalNotificationsNode = select('.js-notifications-list-paginator-counts')!.lastChild!;
+ const totalNotificationsNode = $('.js-notifications-list-paginator-counts')!.lastChild!;
assertNodeContent(totalNotificationsNode, /^of \d+$/);
const totalNotificationsNumber = looseParseInt(totalNotificationsNode);
const lastCursor = Math.floor((totalNotificationsNumber - 1) / itemsPerNotificationsPage) * itemsPerNotificationsPage;
diff --git a/source/features/link-to-changelog-file.tsx b/source/features/link-to-changelog-file.tsx
index b357ef0f..08661d12 100644
--- a/source/features/link-to-changelog-file.tsx
+++ b/source/features/link-to-changelog-file.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import {BookIcon} from '@primer/octicons-react';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -22,7 +22,7 @@ function findChangelogName(files: string[]): string | false {
}
function parseFromDom(): false {
- const files = select.all('[aria-labelledby="files"] .js-navigation-open[href*="/blob/"').map(file => file.title);
+ const files = $$('[aria-labelledby="files"] .js-navigation-open[href*="/blob/"').map(file => file.title);
void changelogName.applyOverride(
[findChangelogName(files) as string] /* TODO: Type mistake */,
getRepo()!.nameWithOwner,
diff --git a/source/features/link-to-compare-diff.tsx b/source/features/link-to-compare-diff.tsx
index e1fecce8..da5df859 100644
--- a/source/features/link-to-compare-diff.tsx
+++ b/source/features/link-to-compare-diff.tsx
@@ -1,6 +1,6 @@
import './link-to-compare-diff.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -20,7 +20,7 @@ void features.add(import.meta.url, {
pageDetect.isCompare,
],
exclude: [
- () => select.exists('.tabnav'), // The commit list and compare diff are in two separate tabs
+ () => elementExists('.tabnav'), // The commit list and compare diff are in two separate tabs
],
deduplicate: 'has-rgh-inner',
awaitDomReady: true, // DOM-based filter
diff --git a/source/features/linkify-code.tsx b/source/features/linkify-code.tsx
index e7d444b5..d272e906 100644
--- a/source/features/linkify-code.tsx
+++ b/source/features/linkify-code.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import observe from '../helpers/selector-observer.js';
@@ -13,7 +13,7 @@ function initTitle(signal: AbortSignal): void {
observe('.js-issue-title', title => {
// TODO: Replace with :has
- if (!select.exists('a', title)) {
+ if (!elementExists('a', title)) {
linkifyIssues(currentRepo, title);
}
}, {signal});
@@ -30,7 +30,7 @@ function linkifyContent(wrapper: Element): void {
// https://github.com/refined-github/refined-github/pull/3844#issuecomment-751427568
if (!pageDetect.isGist()) {
const currentRepo = getRepo() ?? {};
- for (const element of select.all('.pl-c', wrapper)) {
+ for (const element of $$('.pl-c', wrapper)) {
linkifyIssues(currentRepo, element);
}
}
diff --git a/source/features/linkify-commit-sha.tsx b/source/features/linkify-commit-sha.tsx
index d33ffdca..bd43f7f0 100644
--- a/source/features/linkify-commit-sha.tsx
+++ b/source/features/linkify-commit-sha.tsx
@@ -1,12 +1,12 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {wrap} from '../helpers/dom-utils.js';
import features from '../feature-manager.js';
function init(): void {
- const element = select('.sha.user-select-contain:not(a *)');
+ const element = $('.sha.user-select-contain:not(a *)');
if (element) {
wrap(element, <a href={location.pathname.replace(/pull\/\d+\/commits/, 'commit')}/>);
}
diff --git a/source/features/linkify-labels-on-dashboard.tsx b/source/features/linkify-labels-on-dashboard.tsx
index 1916abf8..78ca2eb9 100644
--- a/source/features/linkify-labels-on-dashboard.tsx
+++ b/source/features/linkify-labels-on-dashboard.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {wrap} from '../helpers/dom-utils.js';
@@ -8,8 +8,8 @@ import observe from '../helpers/selector-observer.js';
function linkifyLabel(label: Element): void {
const activity = label.closest('div:not([class])')!;
- const isPR = select.exists('.octicon-git-pull-request', activity);
- const repository = select('a[data-hovercard-type="repository"]', activity)!;
+ const isPR = elementExists('.octicon-git-pull-request', activity);
+ const repository = $('a[data-hovercard-type="repository"]', activity)!;
const url = new URL(`${repository.href}/${isPR ? 'pulls' : 'issues'}`);
const labelName = label.textContent.trim();
diff --git a/source/features/linkify-symbolic-links.tsx b/source/features/linkify-symbolic-links.tsx
index bc4f4884..01b2c627 100644
--- a/source/features/linkify-symbolic-links.tsx
+++ b/source/features/linkify-symbolic-links.tsx
@@ -1,13 +1,13 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {wrap} from '../helpers/dom-utils.js';
import features from '../feature-manager.js';
function init(): void {
- if (select('.file-mode')?.textContent === 'symbolic link') {
- const line = select('.js-file-line')!;
+ if ($('.file-mode')?.textContent === 'symbolic link') {
+ const line = $('.js-file-line')!;
wrap(line.firstChild!, <a href={line.textContent} data-turbo-frame="repo-content-turbo-frame"/>);
}
}
diff --git a/source/features/mark-merge-commits-in-list.tsx b/source/features/mark-merge-commits-in-list.tsx
index 6e9bb93d..4767038d 100644
--- a/source/features/mark-merge-commits-in-list.tsx
+++ b/source/features/mark-merge-commits-in-list.tsx
@@ -1,6 +1,6 @@
import './mark-merge-commits-in-list.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import {GitMergeIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
import {objectEntries} from 'ts-extras';
@@ -35,11 +35,11 @@ const filterMergeCommits = async (commits: string[]): Promise<string[]> => {
};
export function getCommitHash(commit: HTMLElement): string {
- return select('a.markdown-title', commit)!.pathname.split('/').pop()!;
+ return $('a.markdown-title', commit)!.pathname.split('/').pop()!;
}
async function init(): Promise<void> {
- const pageCommits = select.all([
+ const pageCommits = $$([
'.js-commits-list-item', // `isCommitList`
'.js-timeline-item .TimelineItem:has(.octicon-git-commit)', // `isPRConversation`, "js-timeline-item" to exclude "isCommitList"
]);
@@ -52,7 +52,7 @@ async function init(): Promise<void> {
for (const commit of pageCommits) {
if (mergeCommits.includes(getCommitHash(commit))) {
commit.classList.add('rgh-merge-commit');
- select('a.markdown-title', commit)!.before(<GitMergeIcon className="mr-1"/>);
+ $('a.markdown-title', commit)!.before(<GitMergeIcon className="mr-1"/>);
}
}
}
diff --git a/source/features/mark-private-orgs.tsx b/source/features/mark-private-orgs.tsx
index 60c0ccea..855c24fa 100644
--- a/source/features/mark-private-orgs.tsx
+++ b/source/features/mark-private-orgs.tsx
@@ -1,7 +1,7 @@
import './mark-private-orgs.css';
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import {EyeClosedIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -21,7 +21,7 @@ const publicOrganizationsNames = new CachedFunction('public-organizations', {
});
async function init(): Promise<false | void> {
- const orgs = select.all('a.avatar-group-item[data-hovercard-type="organization"][itemprop="follows"]'); // `itemprop` excludes sponsorships #3770
+ const orgs = $$('a.avatar-group-item[data-hovercard-type="organization"][itemprop="follows"]'); // `itemprop` excludes sponsorships #3770
if (orgs.length === 0) {
return false;
}
diff --git a/source/features/more-conversation-filters.tsx b/source/features/more-conversation-filters.tsx
index 37387a04..cb80ccfc 100644
--- a/source/features/more-conversation-filters.tsx
+++ b/source/features/more-conversation-filters.tsx
@@ -1,11 +1,11 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
import SearchQuery from '../github-helpers/search-query.js';
function init(): void {
- const sourceItem = select('#filters-select-menu a:nth-last-child(2)')!;
+ const sourceItem = $('#filters-select-menu a:nth-last-child(2)')!;
// "Involved" filter
const commentsLink = sourceItem.cloneNode(true);
@@ -17,14 +17,14 @@ function init(): void {
sourceItem.after(commentsLink);
// "Subscribed" external link
- const searchSyntaxLink = select('#filters-select-menu a:last-child')!;
+ const searchSyntaxLink = $('#filters-select-menu a:last-child')!;
const subscriptionsLink = searchSyntaxLink.cloneNode(true);
subscriptionsLink.lastElementChild!.textContent = 'Everything you subscribed to';
const subscriptionsUrl = new URL('https://github.com/notifications/subscriptions');
const repositoryId
- = select('meta[name="octolytics-dimension-repository_id"]')?.content
- ?? select('input[name="repository_id"]')!.value;
+ = $('meta[name="octolytics-dimension-repository_id"]')?.content
+ ?? $('input[name="repository_id"]')!.value;
subscriptionsUrl.searchParams.set('repository', btoa(`010:Repository${repositoryId}`));
subscriptionsLink.href = subscriptionsUrl.href;
diff --git a/source/features/more-dropdown-links.tsx b/source/features/more-dropdown-links.tsx
index cd2451fd..2c10626d 100644
--- a/source/features/more-dropdown-links.tsx
+++ b/source/features/more-dropdown-links.tsx
@@ -1,6 +1,6 @@
import './more-dropdown-links.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -15,7 +15,7 @@ export async function unhideOverflowDropdown(): Promise<boolean> {
const repoNavigationBar = await elementReady('.UnderlineNav-body');
// No dropdown on mobile #5781
- if (!select.exists('.js-responsive-underlinenav')) {
+ if (!elementExists('.js-responsive-underlinenav')) {
return false;
}
@@ -50,7 +50,7 @@ void features.add(import.meta.url, {
pageDetect.isEmptyRepo,
// No dropdown on mobile #5781
- () => !select.exists('.js-responsive-underlinenav'),
+ () => !elementExists('.js-responsive-underlinenav'),
],
deduplicate: 'has-rgh',
awaitDomReady: true, // DOM-based filter
diff --git a/source/features/more-file-links.tsx b/source/features/more-file-links.tsx
index 8d0b85f2..d6866836 100644
--- a/source/features/more-file-links.tsx
+++ b/source/features/more-file-links.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -9,7 +9,7 @@ import GitHubFileURL from '../github-helpers/github-file-url.js';
function handleMenuOpening({delegateTarget: dropdown}: DelegateEvent): void {
dropdown.classList.add('rgh-more-file-links'); // Mark this as processed
- const viewFile = select('a[data-ga-click^="View file"]', dropdown)!;
+ const viewFile = $('a[data-ga-click^="View file"]', dropdown)!;
const getDropdownLink = (name: string, route: string): JSX.Element => {
const {href} = new GitHubFileURL(viewFile.href).assign({route});
return (
diff --git a/source/features/netiquette.tsx b/source/features/netiquette.tsx
index 0117f76a..57c4d52c 100644
--- a/source/features/netiquette.tsx
+++ b/source/features/netiquette.tsx
@@ -1,7 +1,7 @@
import React from 'dom-chef';
import * as pageDetect from 'github-url-detection';
import toMilliseconds from '@sindresorhus/to-milliseconds';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import twas from 'twas';
import {InfoIcon} from '@primer/octicons-react';
@@ -11,7 +11,7 @@ import observe from '../helpers/selector-observer.js';
import {buildRepoURL, isAnyRefinedGitHubRepo} from '../github-helpers/index.js';
import {closedOrMergedMarkerSelector, getLastCloseEvent} from './jump-to-conversation-close-event.js';
-const isClosedOrMerged = (): boolean => select.exists(closedOrMergedMarkerSelector);
+const isClosedOrMerged = (): boolean => elementExists(closedOrMergedMarkerSelector);
/** Returns milliseconds passed since `date` */
function timeAgo(date: Date): number {
@@ -19,7 +19,7 @@ function timeAgo(date: Date): number {
}
function getCloseDate(): Date {
- const datetime = select('relative-time', getLastCloseEvent())!.getAttribute('datetime')!;
+ const datetime = $('relative-time', getLastCloseEvent())!.getAttribute('datetime')!;
console.assert(datetime, 'Datetime attribute missing from relative-time');
return new Date(datetime);
}
diff --git a/source/features/new-or-deleted-file.tsx b/source/features/new-or-deleted-file.tsx
index bcc60bd8..2256e319 100644
--- a/source/features/new-or-deleted-file.tsx
+++ b/source/features/new-or-deleted-file.tsx
@@ -1,25 +1,25 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
import observe from '../helpers/selector-observer.js';
function add(filename: HTMLAnchorElement): void {
- const list = select('ul[aria-label="File Tree"]');
+ const list = $('ul[aria-label="File Tree"]');
if (!list && pageDetect.isCommit()) {
// Silence error, single-file commits don't have the file list
return;
}
- const fileInList = select(`[href="${filename.hash}"]`, list);
+ const fileInList = $(`[href="${filename.hash}"]`, list);
if (!fileInList) {
features.log.error(import.meta.url, 'Could not find file in sidebar, is the sidebar loaded?');
features.unload(import.meta.url);
return;
}
- const icon = select('.octicon-diff-removed, .octicon-diff-added', fileInList)
+ const icon = $('.octicon-diff-removed, .octicon-diff-added', fileInList)
?.cloneNode(true);
if (icon) {
// `span` needed for native vertical alignment
diff --git a/source/features/new-repo-disable-projects-and-wikis.tsx b/source/features/new-repo-disable-projects-and-wikis.tsx
index 5ee56662..a2bf25dd 100644
--- a/source/features/new-repo-disable-projects-and-wikis.tsx
+++ b/source/features/new-repo-disable-projects-and-wikis.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, lastElement} from 'select-dom';
import onetime from 'onetime';
import delegate from 'delegate-it';
import domLoaded from 'dom-loaded';
@@ -23,14 +23,14 @@ async function disableWikiAndProjects(): Promise<void> {
},
});
await domLoaded;
- select('[data-menu-item$="wiki-tab"]')?.remove();
- select('[data-menu-item$="projects-tab"]')?.remove();
+ $('[data-menu-item$="wiki-tab"]')?.remove();
+ $('[data-menu-item$="projects-tab"]')?.remove();
selectHas('li:has([data-content="Wiki"]')?.remove();
selectHas('li:has([data-content="Projects"])')?.remove();
}
function setStorage(): void {
- if (select('input#rgh-disable-project')!.checked) {
+ if ($('input#rgh-disable-project')!.checked) {
sessionStorage.rghNewRepo = true;
}
}
@@ -38,7 +38,7 @@ function setStorage(): void {
async function init(signal: AbortSignal): Promise<void> {
await api.expectToken();
- const anchor = select.last([
+ const anchor = lastElement([
'.js-repo-init-setting-container', // IsNewRepo
'.form-checkbox', // IsNewRepoTemplate
]);
diff --git a/source/features/no-duplicate-list-update-time.tsx b/source/features/no-duplicate-list-update-time.tsx
index 1effedeb..d4fd3805 100644
--- a/source/features/no-duplicate-list-update-time.tsx
+++ b/source/features/no-duplicate-list-update-time.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -9,7 +9,7 @@ function parseTime(element: HTMLElement): number {
}
function remove(issue: HTMLElement): void {
- const [stateChangeTime, updateTime] = select.all('relative-time', issue);
+ const [stateChangeTime, updateTime] = $$('relative-time', issue);
if (parseTime(updateTime) - parseTime(stateChangeTime) < 10_000) { // Hide if within 10 seconds
updateTime.parentElement!.remove();
}
diff --git a/source/features/one-click-diff-options.tsx b/source/features/one-click-diff-options.tsx
index 6f1eb6f0..091f5408 100644
--- a/source/features/one-click-diff-options.tsx
+++ b/source/features/one-click-diff-options.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {BookIcon, CheckIcon, DiffIcon, DiffModifiedIcon} from '@primer/octicons-react';
@@ -9,7 +9,7 @@ import {removeTextNodeContaining} from '../helpers/dom-utils.js';
function isHidingWhitespace(): boolean {
// The selector is the native button
- return new URL(location.href).searchParams.get('w') === '1' || select.exists('button[name="w"][value="0"]:not([hidden])');
+ return new URL(location.href).searchParams.get('w') === '1' || elementExists('button[name="w"][value="0"]:not([hidden])');
}
function createWhitespaceButton(): HTMLElement {
@@ -36,11 +36,11 @@ function createWhitespaceButton(): HTMLElement {
function attachPRButtons(dropdownIcon: SVGElement): void {
// TODO: Replace with :has selector
const dropdown = dropdownIcon.closest('details.diffbar-item')!;
- const diffSettingsForm = select('form[action$="/diffview"]', dropdown)!;
+ const diffSettingsForm = $('form[action$="/diffview"]', dropdown)!;
// Preserve data before emption the form
const isUnified = new FormData(diffSettingsForm).get('diff') === 'unified';
- const token = select('[name="authenticity_token"]', diffSettingsForm)!;
+ const token = $('[name="authenticity_token"]', diffSettingsForm)!;
// Empty form except the token field
diffSettingsForm.replaceChildren(token);
@@ -77,20 +77,20 @@ function attachPRButtons(dropdownIcon: SVGElement): void {
dropdown.replaceWith(diffSettingsForm);
// Trim title
- const prTitle = select('.pr-toolbar .js-issue-title');
- if (prTitle && select.exists('.pr-toolbar progress-bar')) { // Only review view has progress-bar
+ const prTitle = $('.pr-toolbar .js-issue-title');
+ if (prTitle && elementExists('.pr-toolbar progress-bar')) { // Only review view has progress-bar
prTitle.style.maxWidth = '24em';
prTitle.title = prTitle.textContent;
}
// Make space for the new button #655
removeTextNodeContaining(
- select('[data-hotkey="c"] strong')!.previousSibling!,
+ $('[data-hotkey="c"] strong')!.previousSibling!,
'Changes from',
);
// Remove extraneous padding around "Clear filters" button
- select('.subset-files-tab')?.classList.replace('px-sm-3', 'ml-sm-2');
+ $('.subset-files-tab')?.classList.replace('px-sm-3', 'ml-sm-2');
}
function initPR(signal: AbortSignal): void {
diff --git a/source/features/one-click-pr-or-gist.tsx b/source/features/one-click-pr-or-gist.tsx
index 4b964bab..edafda1c 100644
--- a/source/features/one-click-pr-or-gist.tsx
+++ b/source/features/one-click-pr-or-gist.tsx
@@ -1,6 +1,6 @@
import './one-click-pr-or-gist.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -14,10 +14,10 @@ function init(): void | false {
return false;
}
- for (const dropdownItem of select.all('.select-menu-item', initialGroupedButtons)) {
- let title = select('.select-menu-item-heading', dropdownItem)!.textContent.trim();
- const description = select('.description', dropdownItem)!.textContent.trim();
- const radioButton = select('input[type=radio]', dropdownItem)!;
+ for (const dropdownItem of $$('.select-menu-item', initialGroupedButtons)) {
+ let title = $('.select-menu-item-heading', dropdownItem)!.textContent.trim();
+ const description = $('.description', dropdownItem)!.textContent.trim();
+ const radioButton = $('input[type=radio]', dropdownItem)!;
const classList = ['btn', 'ml-2', 'tooltipped', 'tooltipped-s'];
if (/\bdraft\b/i.test(title)) {
@@ -49,7 +49,7 @@ void features.add(import.meta.url, {
pageDetect.isGist,
],
exclude: [
- () => select.exists('[data-show-dialog-id="drafts-upgrade-dialog"]'),
+ () => elementExists('[data-show-dialog-id="drafts-upgrade-dialog"]'),
],
deduplicate: 'has-rgh',
awaitDomReady: true,
diff --git a/source/features/one-click-review-submission.tsx b/source/features/one-click-review-submission.tsx
index 942ba758..0d7cd60f 100644
--- a/source/features/one-click-review-submission.tsx
+++ b/source/features/one-click-review-submission.tsx
@@ -12,7 +12,7 @@ function replaceCheckboxes(originalSubmitButton: HTMLButtonElement): void {
const actionsRow = originalSubmitButton.closest('.form-actions')!;
const formAttribute = originalSubmitButton.getAttribute('form')!;
- // Do not use `select.all` because elements can be outside `form`
+ // Do not use `$$` because elements can be outside `form`
// `RadioNodeList` is dynamic, so we need to make a copy
const radios = [...form.elements.namedItem('pull_request_review[event]') as RadioNodeList] as HTMLInputElement[];
if (radios.length === 0) {
diff --git a/source/features/open-all-conversations.tsx b/source/features/open-all-conversations.tsx
index d6d22257..f6ba04b8 100644
--- a/source/features/open-all-conversations.tsx
+++ b/source/features/open-all-conversations.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import delegate, {DelegateEvent} from 'delegate-it';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -21,9 +21,9 @@ const issueListSelector = pageDetect.isGlobalIssueOrPRList()
function onButtonClick(event: DelegateEvent<MouseEvent, HTMLButtonElement>): void {
const onlySelected = event.delegateTarget.closest('.table-list-triage');
- const issues = select.all(`${issueListSelector} .js-issue-row`)
+ const issues = $$(`${issueListSelector} .js-issue-row`)
// TODO: Use conditional :has(:checked) instead
- .filter(issue => onlySelected ? select.exists(':checked', issue) : true);
+ .filter(issue => onlySelected ? elementExists(':checked', issue) : true);
void openTabs(issues.map(issue => getUrlFromItem(issue)));
}
diff --git a/source/features/open-all-notifications.tsx b/source/features/open-all-notifications.tsx
index 1e2b3639..7af28417 100644
--- a/source/features/open-all-notifications.tsx
+++ b/source/features/open-all-notifications.tsx
@@ -1,6 +1,6 @@
import './open-all-notifications.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {LinkExternalIcon} from '@primer/octicons-react';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -20,7 +20,7 @@ const openUnread = features.getIdentifiers('open-notifications-button');
const openSelected = features.getIdentifiers('open-selected-button');
function getUnreadNotifications(container: ParentNode = document): HTMLElement[] {
- return select.all('.notification-unread', container);
+ return $$('.notification-unread', container);
}
async function openNotifications(notifications: Element[], markAsDone = false): Promise<void> {
@@ -52,17 +52,17 @@ async function openUnreadNotifications({delegateTarget, altKey}: DelegateEvent<M
}
async function openSelectedNotifications(): Promise<void> {
- const selectedNotifications = select.all('.notifications-list-item :checked')
+ const selectedNotifications = $$('.notifications-list-item :checked')
.map(checkbox => checkbox.closest('.notifications-list-item')!);
await openNotifications(selectedNotifications);
- if (!select.exists('.notification-unread')) {
+ if (!elementExists('.notification-unread')) {
removeOpenUnreadButtons();
}
}
function removeOpenUnreadButtons(container: ParentNode = document): void {
- for (const button of select.all(openUnread.selector, container)) {
+ for (const button of $$(openUnread.selector, container)) {
button.remove();
}
}
diff --git a/source/features/open-issue-to-latest-comment.tsx b/source/features/open-issue-to-latest-comment.tsx
index 070f960c..fdc04b22 100644
--- a/source/features/open-issue-to-latest-comment.tsx
+++ b/source/features/open-issue-to-latest-comment.tsx
@@ -1,15 +1,15 @@
-import select from 'select-dom';
+import {$$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
const selector = `
:is(.js-issue-row, .js-pinned-issue-list-item)
- .Link--muted:is([aria-label$="comment"], [aria-label$="comments"])
+ .Link--muted:is(a[aria-label$="comment"], a[aria-label$="comments"])
`;
function init(): void {
- for (const link of select.all<HTMLAnchorElement>(selector)) {
+ for (const link of $$(selector)) {
link.hash = '#partial-timeline';
}
}
diff --git a/source/features/pinned-issues-update-time.tsx b/source/features/pinned-issues-update-time.tsx
index c840b16d..cfce8777 100644
--- a/source/features/pinned-issues-update-time.tsx
+++ b/source/features/pinned-issues-update-time.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$} from 'select-dom';
import batchedFunction from 'batched-function';
import * as pageDetect from 'github-url-detection';
@@ -33,7 +33,7 @@ const getLastUpdated = new CachedFunction('last-updated', {
});
function getPinnedIssueNumber(pinnedIssue: HTMLElement): number {
- return looseParseInt(select('.opened-by', pinnedIssue)!.firstChild!);
+ return looseParseInt($('.opened-by', pinnedIssue)!.firstChild!);
}
async function update(pinnedIssues: HTMLElement[]): Promise<void> {
@@ -41,7 +41,7 @@ async function update(pinnedIssues: HTMLElement[]): Promise<void> {
for (const pinnedIssue of pinnedIssues) {
const issueNumber = getPinnedIssueNumber(pinnedIssue);
const {updatedAt} = lastUpdated[api.escapeKey(issueNumber)];
- const originalLine = select('.opened-by', pinnedIssue)!;
+ const originalLine = $('.opened-by', pinnedIssue)!;
originalLine.after(
// .rgh class enables tweakers to hide the number
<span className="text-small color-fg-muted">
diff --git a/source/features/pr-base-commit.tsx b/source/features/pr-base-commit.tsx
index c03a4423..c9e0688c 100644
--- a/source/features/pr-base-commit.tsx
+++ b/source/features/pr-base-commit.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
@@ -60,7 +60,7 @@ void features.add(import.meta.url, {
],
exclude: [
pageDetect.isClosedPR,
- () => select('.head-ref')!.title === 'This repository has been deleted',
+ () => $('.head-ref')!.title === 'This repository has been deleted',
],
awaitDomReady: true, // DOM-based exclusions
init,
diff --git a/source/features/pr-branch-auto-delete.tsx b/source/features/pr-branch-auto-delete.tsx
index ca798774..e2d35d01 100644
--- a/source/features/pr-branch-auto-delete.tsx
+++ b/source/features/pr-branch-auto-delete.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {InfoIcon} from '@primer/octicons-react';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -14,7 +14,7 @@ import {canEditEveryComment} from './quick-comment-edit.js';
const canCreateRelease = canEditEveryComment;
async function init(): Promise<void> {
- const deleteButton = select('[action$="/cleanup"] [type="submit"]');
+ const deleteButton = $('[action$="/cleanup"] [type="submit"]');
if (!deleteButton) {
return;
}
diff --git a/source/features/pr-filters.tsx b/source/features/pr-filters.tsx
index c1487037..e06f3802 100644
--- a/source/features/pr-filters.tsx
+++ b/source/features/pr-filters.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {CheckIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -72,10 +72,10 @@ async function addChecksFilter(reviewsFilter: HTMLElement): Promise<void> {
const checksFilter = reviewsFilter.cloneNode(true);
checksFilter.id = '';
- select('summary', checksFilter)!.firstChild!.textContent = 'Checks\u00A0'; // Only replace text node, keep caret
- select('.SelectMenu-title', checksFilter)!.textContent = 'Filter by checks status';
+ $('summary', checksFilter)!.firstChild!.textContent = 'Checks\u00A0'; // Only replace text node, keep caret
+ $('.SelectMenu-title', checksFilter)!.textContent = 'Filter by checks status';
- const dropdown = select('.SelectMenu-list', checksFilter)!;
+ const dropdown = $('.SelectMenu-list', checksFilter)!;
dropdown.textContent = ''; // Drop previous filters
for (const status of ['Success', 'Failure', 'Pending']) {
diff --git a/source/features/pr-jump-to-first-non-viewed-file.tsx b/source/features/pr-jump-to-first-non-viewed-file.tsx
index 119a4c13..eb1f2d2c 100644
--- a/source/features/pr-jump-to-first-non-viewed-file.tsx
+++ b/source/features/pr-jump-to-first-non-viewed-file.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import elementReady from 'element-ready';
import delegate from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -6,7 +6,7 @@ import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
function jumpToFirstNonViewed(): void {
- const firstNonViewedFile = select('.file:not([data-file-user-viewed])')!;
+ const firstNonViewedFile = $('.file:not([data-file-user-viewed])')!;
if (firstNonViewedFile) {
// Scroll to file without pushing to history
location.replace('#' + firstNonViewedFile.id);
diff --git a/source/features/prevent-link-loss.tsx b/source/features/prevent-link-loss.tsx
index 19adde33..a300403a 100644
--- a/source/features/prevent-link-loss.tsx
+++ b/source/features/prevent-link-loss.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {AlertIcon} from '@primer/octicons-react';
import debounceFn from 'debounce-fn';
import * as pageDetect from 'github-url-detection';
@@ -29,7 +29,7 @@ function handleButtonClick({currentTarget: fixButton}: React.MouseEvent<HTMLButt
}
function getUI(field: HTMLTextAreaElement, ...classes: string[]): HTMLElement {
- return select('.rgh-prevent-link-loss-container', field.form!) ?? (createBanner({
+ return $('.rgh-prevent-link-loss-container', field.form!) ?? (createBanner({
icon: <AlertIcon className="m-0"/>,
text: (
<>
@@ -57,11 +57,11 @@ const updateUI = debounceFn(({delegateTarget: field}: DelegateEvent<Event, HTMLT
if (!isVulnerableToLinkLoss(field.value)) {
getUI(field).remove();
} else if (pageDetect.isNewIssue() || pageDetect.isNewRelease() || pageDetect.isCompare()) {
- select('file-attachment', field.form!)!.append(
+ $('file-attachment', field.form!)!.append(
getUI(field, 'mt-2', 'mx-0', 'mx-md-2'),
);
} else {
- select('.form-actions', field.form!)!.before(
+ $('.form-actions', field.form!)!.before(
getUI(field, 'mx-md-2', 'mb-2'),
);
}
diff --git a/source/features/prevent-pr-merge-panel-opening.tsx b/source/features/prevent-pr-merge-panel-opening.tsx
index 13bd7db7..f7d6473f 100644
--- a/source/features/prevent-pr-merge-panel-opening.tsx
+++ b/source/features/prevent-pr-merge-panel-opening.tsx
@@ -1,11 +1,11 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
async function sessionResumeHandler(): Promise<void> {
await Promise.resolve(); // The `session:resume` event fires a bit too early
- const cancelMergeButton = select('.merge-branch-form .js-details-target');
+ const cancelMergeButton = $('.merge-branch-form .js-details-target');
if (cancelMergeButton) {
cancelMergeButton.click();
document.removeEventListener('session:resume', sessionResumeHandler);
diff --git a/source/features/preview-hidden-comments.tsx b/source/features/preview-hidden-comments.tsx
index dd2c6cc7..ae89e98e 100644
--- a/source/features/preview-hidden-comments.tsx
+++ b/source/features/preview-hidden-comments.tsx
@@ -1,6 +1,6 @@
import './preview-hidden-comments.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -11,7 +11,7 @@ function preview(hiddenCommentHeader: HTMLElement): void {
const details = hiddenCommentHeader.closest('details')!;
details.classList.add('rgh-preview-hidden-comments'); // Used in CSS
- const comment = select('.comment-body', details)!;
+ const comment = $('.comment-body', details)!;
const commentText = comment.textContent.trim();
if (commentText.length === 0) {
return;
diff --git a/source/features/previous-next-commit-buttons.tsx b/source/features/previous-next-commit-buttons.tsx
index 71ffd615..a983c59c 100644
--- a/source/features/previous-next-commit-buttons.tsx
+++ b/source/features/previous-next-commit-buttons.tsx
@@ -1,17 +1,17 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
function init(): false | void {
- const originalPreviousNext = select('.commit .BtnGroup.float-right');
+ const originalPreviousNext = $('.commit .BtnGroup.float-right');
if (!originalPreviousNext) {
return false;
}
// Wrap the button in a <div> to avoid #4503
- select('#files')!.after(
+ $('#files')!.after(
<div className="d-flex flex-justify-end mb-3">
{originalPreviousNext.cloneNode(true)}
</div>,
diff --git a/source/features/profile-gists-link.tsx b/source/features/profile-gists-link.tsx
index 737cdcf7..eaa18f76 100644
--- a/source/features/profile-gists-link.tsx
+++ b/source/features/profile-gists-link.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {CodeSquareIcon} from '@primer/octicons-react';
@@ -49,8 +49,8 @@ async function appendTab(navigationBar: Element): Promise<void> {
navigationBar.replaceWith(navigationBar);
// There are two UnderlineNav items (responsive…) that point to the same dropdown
- const overflowNav = select('.js-responsive-underlinenav .dropdown-menu ul')!;
- if (!select.exists('[data-rgh-label="Gists"]', overflowNav)) {
+ const overflowNav = $('.js-responsive-underlinenav .dropdown-menu ul')!;
+ if (!elementExists('[data-rgh-label="Gists"]', overflowNav)) {
overflowNav.append(
createDropdownItem('Gists', user.url),
);
diff --git a/source/features/pull-request-hotkeys.tsx b/source/features/pull-request-hotkeys.tsx
index 64929964..ce4b3df8 100644
--- a/source/features/pull-request-hotkeys.tsx
+++ b/source/features/pull-request-hotkeys.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$$} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -7,7 +7,7 @@ import {addHotkey} from '../github-helpers/hotkey.js';
async function init(): Promise<void> {
const tabnav = await elementReady('#partial-discussion-header + .tabnav');
- const tabs = select.all('a.tabnav-tab', tabnav);
+ const tabs = $$('a.tabnav-tab', tabnav);
const lastTab = tabs.length - 1;
const selectedIndex = tabs.findIndex(tab => tab.classList.contains('selected'));
diff --git a/source/features/quick-comment-edit.tsx b/source/features/quick-comment-edit.tsx
index a9d343a6..9b60b369 100644
--- a/source/features/quick-comment-edit.tsx
+++ b/source/features/quick-comment-edit.tsx
@@ -1,6 +1,6 @@
import './quick-comment-edit.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import {PencilIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -11,7 +11,7 @@ import {isArchivedRepoAsync} from '../github-helpers/index.js';
function addQuickEditButton(commentForm: Element): void {
const commentBody = commentForm.closest('.js-comment')!;
// We can't rely on a class for deduplication because the whole comment might be replaced by GitHub #5572
- if (select.exists('.rgh-quick-comment-edit-button', commentBody)) {
+ if (elementExists('.rgh-quick-comment-edit-button', commentBody)) {
return;
}
@@ -30,7 +30,7 @@ function addQuickEditButton(commentForm: Element): void {
}
export function canEditEveryComment(): boolean {
- return select.exists([
+ return elementExists([
// If you can lock conversations, you have write access
'.lock-toggle-link > .octicon-lock',
diff --git a/source/features/quick-comment-hiding.tsx b/source/features/quick-comment-hiding.tsx
index 15075f2c..c37c4c4f 100644
--- a/source/features/quick-comment-hiding.tsx
+++ b/source/features/quick-comment-hiding.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import delegate, {DelegateEvent} from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -20,7 +20,7 @@ function generateSubmenu(hideButton: Element): void {
detailsElement.classList.add('rgh-quick-comment-hiding-details');
const comment = hideButton.closest('.unminimized-comment')!;
- const hideCommentForm: HTMLFormElement = select(formSelector, comment)!;
+ const hideCommentForm: HTMLFormElement = $(formSelector, comment)!;
// Generate dropdown
const newForm = hideCommentForm.cloneNode();
@@ -31,7 +31,7 @@ function generateSubmenu(hideButton: Element): void {
// Imitate existing menu, reset classes
newForm.className = ['dropdown-menu', 'dropdown-menu-sw', 'color-fg-default', 'show-more-popover', 'anim-scale-in'].join(' ');
- for (const reason of select.all('option:not([value=""])', hideCommentForm.elements.classifier)) {
+ for (const reason of $$('option:not([value=""])', hideCommentForm.elements.classifier)) {
newForm.append(
<button
type="submit"
@@ -60,10 +60,10 @@ function toggleSubMenu(hideButton: Element, show: boolean): void {
const dropdown = hideButton.closest('details')!;
// Native dropdown
- select('details-menu', dropdown)!.classList.toggle('v-hidden', show);
+ $('details-menu', dropdown)!.classList.toggle('v-hidden', show);
// "Hide comment" dropdown
- select(formSelector, dropdown)!.classList.toggle('v-hidden', !show);
+ $(formSelector, dropdown)!.classList.toggle('v-hidden', !show);
}
function resetDropdowns(event: DelegateEvent): void {
diff --git a/source/features/quick-label-removal.tsx b/source/features/quick-label-removal.tsx
index ef0efeab..99b7e35f 100644
--- a/source/features/quick-label-removal.tsx
+++ b/source/features/quick-label-removal.tsx
@@ -1,6 +1,6 @@
import './quick-label-removal.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import onetime from 'onetime';
import {XIcon} from '@primer/octicons-react';
import {assertError} from 'ts-extras';
@@ -13,7 +13,7 @@ import showToast from '../github-helpers/toast.js';
import {getConversationNumber} from '../github-helpers/index.js';
import observe from '../helpers/selector-observer.js';
-const canNotEditLabels = onetime((): boolean => !select.exists('.label-select-menu .octicon-gear'));
+const canNotEditLabels = onetime((): boolean => !elementExists('.label-select-menu .octicon-gear'));
async function removeLabelButtonClickHandler(event: DelegateEvent<MouseEvent, HTMLButtonElement>): Promise<void> {
event.preventDefault();
diff --git a/source/features/quick-mention.tsx b/source/features/quick-mention.tsx
index 20377d5b..6d0a10e2 100644
--- a/source/features/quick-mention.tsx
+++ b/source/features/quick-mention.tsx
@@ -1,6 +1,6 @@
import './quick-mention.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import {ReplyIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
import * as textFieldEdit from 'text-field-edit';
@@ -18,7 +18,7 @@ function prefixUserMention(userMention: string): string {
function mentionUser({delegateTarget: button}: DelegateEvent): void {
const userMention = button.parentElement!.querySelector('img')!.alt;
- const newComment = select('textarea#new_comment_field')!;
+ const newComment = $('textarea#new_comment_field')!;
newComment.focus();
// If the new comment field has selected text, don’t replace it
@@ -53,7 +53,7 @@ function add(avatar: HTMLElement): void {
if (
// TODO: Rewrite with :has()
// Exclude events that aren't tall enough, like hidden comments or reviews without comments
- !select.exists('.unminimized-comment, .js-comment-container', timelineItem)
+ !elementExists('.unminimized-comment, .js-comment-container', timelineItem)
) {
return;
}
@@ -68,7 +68,7 @@ function add(avatar: HTMLElement): void {
wrap(avatar, <div className="avatar-parent-child TimelineItem-avatar d-none d-md-block"/>);
}
- const userMention = select('img', avatar)!.alt;
+ const userMention = $('img', avatar)!.alt;
avatar.classList.add('rgh-quick-mention');
avatar.after(
<button
diff --git a/source/features/quick-repo-deletion.tsx b/source/features/quick-repo-deletion.tsx
index 08a01939..72a59206 100644
--- a/source/features/quick-repo-deletion.tsx
+++ b/source/features/quick-repo-deletion.tsx
@@ -1,7 +1,7 @@
import './quick-repo-deletion.css';
import delay from 'delay';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import {TrashIcon} from '@primer/octicons-react';
import elementReady from 'element-ready';
import {assertError} from 'ts-extras';
@@ -18,7 +18,7 @@ import parseBackticks from '../github-helpers/parse-backticks.js';
import observe from '../helpers/selector-observer.js';
function handleToggle(event: DelegateEvent<Event, HTMLDetailsElement>): void {
- const hasContent = select.exists([
+ const hasContent = elementExists([
'[data-hotkey="g i"] .Counter:not([hidden])', // Open issues
'[data-hotkey="g p"] .Counter:not([hidden])', // Open PRs
'.rgh-open-prs-of-forks', // PRs opened in the source repo
@@ -71,7 +71,7 @@ async function buttonTimeout(buttonContainer: HTMLDetailsElement): Promise<boole
void verifyScopesWhileWaiting(abortController);
let secondsLeft = 5;
- const button = select('.btn', buttonContainer)!;
+ const button = $('.btn', buttonContainer)!;
try {
do {
button.style.transform = `scale(${1.2 - ((secondsLeft - 5) / 3)})`; // Dividend is zoom speed
@@ -91,7 +91,7 @@ async function start(buttonContainer: HTMLDetailsElement): Promise<void> {
return;
}
- select('.btn', buttonContainer)!.textContent = 'Deleting repo…';
+ $('.btn', buttonContainer)!.textContent = 'Deleting repo…';
const {nameWithOwner, owner} = getRepo()!;
try {
await api.v3('/repos/' + nameWithOwner, {
@@ -120,7 +120,7 @@ async function start(buttonContainer: HTMLDetailsElement): Promise<void> {
<><TrashIcon/> <span>Repository <strong>{nameWithOwner}</strong> deleted. <a href={restoreURL}>Restore it</a>, <a href={forkSource}>visit the source repo</a>, or see <a href={otherForksURL}>your other forks.</a></span></>,
{action: false},
);
- select('.application-main')!.remove();
+ $('.application-main')!.remove();
if (document.hidden) {
// Try closing the tab if in the background. Could fail, so we still update the UI above
void browser.runtime.sendMessage({closeTab: true});
diff --git a/source/features/quick-review-comment-deletion.tsx b/source/features/quick-review-comment-deletion.tsx
index 447acfb5..f5e6f154 100644
--- a/source/features/quick-review-comment-deletion.tsx
+++ b/source/features/quick-review-comment-deletion.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {TrashIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -23,7 +23,7 @@ function onButtonClick({delegateTarget: button}: DelegateEvent): void {
async function preloadDropdown({delegateTarget: button}: DelegateEvent): Promise<void> {
const comment = button.closest('.js-comment')!;
- await loadDetailsMenu(select('details-menu.show-more-popover', comment)!);
+ await loadDetailsMenu($('details-menu.show-more-popover', comment)!);
}
function addDeleteButton(cancelButton: Element): void {
diff --git a/source/features/quick-review.tsx b/source/features/quick-review.tsx
index ac159dd4..14c5f38a 100644
--- a/source/features/quick-review.tsx
+++ b/source/features/quick-review.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import delay from 'delay';
-import select from 'select-dom';
+import {$} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -28,7 +28,7 @@ function initSidebarReviewButton(signal: AbortSignal): void {
function focusReviewTextarea({delegateTarget}: DelegateEvent<Event, HTMLDetailsElement>): void {
if (delegateTarget.open) {
- select('textarea', delegateTarget)!.focus();
+ $('textarea', delegateTarget)!.focus();
}
}
diff --git a/source/features/reactions-avatars.tsx b/source/features/reactions-avatars.tsx
index 0e1d590c..29d868f8 100644
--- a/source/features/reactions-avatars.tsx
+++ b/source/features/reactions-avatars.tsx
@@ -1,6 +1,6 @@
import './reactions-avatars.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import {flatZip} from 'flat-zip';
import * as pageDetect from 'github-url-detection';
@@ -58,12 +58,12 @@ const viewportObserver = new IntersectionObserver(changes => {
});
function showAvatarsOn(commentReactions: Element): void {
- const reactionTypes = select.all('.social-reaction-summary-item', commentReactions).length;
+ const reactionTypes = $$('.social-reaction-summary-item', commentReactions).length;
const avatarLimit = arbitraryAvatarLimit - (reactionTypes * approximateHeaderLength);
- const participantByReaction = select
- .all(':scope > button.social-reaction-summary-item', commentReactions)
- .map(button => getParticipants(button));
+ const participantByReaction
+ = $$(':scope > button.social-reaction-summary-item', commentReactions)
+ .map(button => getParticipants(button));
const flatParticipants = flatZip(participantByReaction, avatarLimit);
for (const {button, username, imageUrl} of flatParticipants) {
diff --git a/source/features/release-download-count.tsx b/source/features/release-download-count.tsx
index 97e30e01..9cbe8acb 100644
--- a/source/features/release-download-count.tsx
+++ b/source/features/release-download-count.tsx
@@ -1,6 +1,6 @@
import './release-download-count.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import {DownloadIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
import {abbreviateNumber} from 'js-abbreviation-number';
@@ -24,7 +24,7 @@ async function getAssetsForTag(tag: string): Promise<Record<string, number>> {
async function addCounts(assetsList: HTMLElement): Promise<void> {
// TODO: Use :has selector instead
- if (!select.exists('.octicon-package', assetsList)) {
+ if (!elementExists('.octicon-package', assetsList)) {
return;
}
@@ -40,7 +40,7 @@ async function addCounts(assetsList: HTMLElement): Promise<void> {
const assets = await getAssetsForTag(releaseName);
const calculateHeatIndex = createHeatIndexFunction(Object.values(assets));
- for (const assetLink of select.all('.octicon-package ~ a', assetsList)) {
+ for (const assetLink of $$('.octicon-package ~ a', assetsList)) {
// Match the asset in the DOM to the asset in the API response
const downloadCount = assets[assetLink.pathname.split('/').pop()!] ?? 0;
diff --git a/source/features/repo-header-info.tsx b/source/features/repo-header-info.tsx
index 56963078..1942f22a 100644
--- a/source/features/repo-header-info.tsx
+++ b/source/features/repo-header-info.tsx
@@ -1,7 +1,7 @@
import * as pageDetect from 'github-url-detection';
import {LockIcon, RepoForkedIcon, StarIcon} from '@primer/octicons-react';
import React from 'dom-chef';
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import {CachedFunction} from 'webext-storage-cache';
import observe from '../helpers/selector-observer.js';
@@ -31,14 +31,14 @@ async function add(repoLink: HTMLAnchorElement): Promise<void> {
const {isFork, isPrivate, stargazerCount} = await repositoryInfo.get();
// GitHub may already show this icon natively, so we match its position
- if (isPrivate && !select.exists('.octicon-lock', repoLink)) {
+ if (isPrivate && !elementExists('.octicon-lock', repoLink)) {
repoLink.append(
<LockIcon className="ml-1" width={12} height={12}/>,
);
}
// GitHub may already show this icon natively, so we match its position
- if (isFork && !select.exists('.octicon-repo-forked', repoLink)) {
+ if (isFork && !elementExists('.octicon-repo-forked', repoLink)) {
repoLink.append(
<RepoForkedIcon className="ml-1" width={12} height={12}/>,
);
diff --git a/source/features/repo-wide-file-finder.tsx b/source/features/repo-wide-file-finder.tsx
index 26599177..407be229 100644
--- a/source/features/repo-wide-file-finder.tsx
+++ b/source/features/repo-wide-file-finder.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -18,7 +18,7 @@ void features.add(import.meta.url, {
pageDetect.isRepo,
],
exclude: [
- () => select.exists('[data-hotkey="t"]'),
+ () => elementExists('[data-hotkey="t"]'),
pageDetect.isEmptyRepo,
pageDetect.isPRFiles,
pageDetect.isFileFinder,
diff --git a/source/features/rgh-improve-new-issue-form.tsx b/source/features/rgh-improve-new-issue-form.tsx
index 33ed0890..b574412f 100644
--- a/source/features/rgh-improve-new-issue-form.tsx
+++ b/source/features/rgh-improve-new-issue-form.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -9,7 +9,7 @@ import {expectToken, expectTokenScope} from '../github-helpers/api.js';
import {isRefinedGitHubRepo} from '../github-helpers/index.js';
function addNotice(adjective: JSX.Element | string): void {
- select('#issue_body_template_name')!.before(
+ $('#issue_body_template_name')!.before(
<div className="flash flash-warn m-2">
Your Personal Access Token is {adjective}. Some Refined GitHub features will not work without it.
You can update it <button className="btn-link" type="button" onClick={openOptions as unknown as React.MouseEventHandler}>in the options</button>.
@@ -34,11 +34,11 @@ async function checkToken(): Promise<void> {
async function setVersion(): Promise<void> {
const {version} = browser.runtime.getManifest();
- select('input#issue_form_version')!.value = version;
+ $('input#issue_form_version')!.value = version;
}
async function linkifyCacheRefresh(): Promise<void> {
- select('[href="#clear-cache"]')!.replaceWith(
+ $('[href="#clear-cache"]')!.replaceWith(
<button
className="btn"
type="button"
diff --git a/source/features/rgh-welcome-issue.tsx b/source/features/rgh-welcome-issue.tsx
index 86a2de2f..62b07af2 100644
--- a/source/features/rgh-welcome-issue.tsx
+++ b/source/features/rgh-welcome-issue.tsx
@@ -1,5 +1,5 @@
import './rgh-welcome-issue.css';
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import delegate from 'delegate-it';
import features from '../feature-manager.js';
@@ -23,11 +23,11 @@ const placeholdersSelector = 'a[href="#rgh-linkify-welcome-issue"]';
function init(signal: AbortSignal): void {
delegate(placeholdersSelector, 'click', openOptions, {signal});
- if (select.exists('.rgh-linkify-welcome-issue')) {
+ if (elementExists('.rgh-linkify-welcome-issue')) {
return;
}
- const [opening, closing] = select.all<HTMLAnchorElement>(placeholdersSelector);
+ const [opening, closing] = $$(placeholdersSelector);
closing.remove();
// Move the wrapped text into the existing link
diff --git a/source/features/same-branch-author-commits.tsx b/source/features/same-branch-author-commits.tsx
index 84afda1c..b0230752 100644
--- a/source/features/same-branch-author-commits.tsx
+++ b/source/features/same-branch-author-commits.tsx
@@ -1,10 +1,10 @@
-import select from 'select-dom';
+import {$$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
function init(): void {
- for (const author of select.all('.js-navigation-container a.commit-author')) {
+ for (const author of $$('.js-navigation-container a.commit-author')) {
author.pathname = location.pathname;
}
}
diff --git a/source/features/select-all-notifications-shortcut.tsx b/source/features/select-all-notifications-shortcut.tsx
index 396df608..9fc46687 100644
--- a/source/features/select-all-notifications-shortcut.tsx
+++ b/source/features/select-all-notifications-shortcut.tsx
@@ -1,11 +1,11 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
import {registerHotkey} from '../github-helpers/hotkey.js';
function selectAllNotifications(): void {
- select('.js-notifications-mark-all-prompt')!.click();
+ $('.js-notifications-mark-all-prompt')!.click();
}
function init(signal: AbortSignal): void {
diff --git a/source/features/select-notifications.tsx b/source/features/select-notifications.tsx
index 992ca994..904f86bf 100644
--- a/source/features/select-notifications.tsx
+++ b/source/features/select-notifications.tsx
@@ -1,6 +1,6 @@
import './select-notifications.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import onetime from 'onetime';
import delegate from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -34,8 +34,8 @@ type Filter = keyof typeof filters;
type Category = 'Type' | 'Status' | 'Read';
function resetFilters({target}: React.SyntheticEvent): void {
- select('form#rgh-select-notifications-form')!.reset();
- for (const label of select.all('label', target as Element)) {
+ $('form#rgh-select-notifications-form')!.reset();
+ for (const label of $$('label', target as Element)) {
label.setAttribute('aria-checked', 'false');
}
}
@@ -45,37 +45,37 @@ function getFiltersSelector(formData: FormData, category: Category): string {
}
function handleSelection({target}: Event): void {
- const selectAllCheckbox = select('input[type="checkbox"].js-notifications-mark-all-prompt')!;
+ const selectAllCheckbox = $('input[type="checkbox"].js-notifications-mark-all-prompt')!;
// Reset the "Select all" checkbox
if (selectAllCheckbox.checked) {
selectAllCheckbox.click();
}
- if (select.exists(':checked', target as Element)) {
- const formData = new FormData(select('form#rgh-select-notifications-form'));
+ if (elementExists(':checked', target as Element)) {
+ const formData = new FormData($('form#rgh-select-notifications-form'));
const types = getFiltersSelector(formData, 'Type');
const statuses = getFiltersSelector(formData, 'Status');
const readStatus = getFiltersSelector(formData, 'Read');
- for (const notification of select.all('.notifications-list-item')) {
+ for (const notification of $$('.notifications-list-item')) {
if (
- (types && !select.exists(types, notification))
- || (statuses && !select.exists(statuses, notification))
+ (types && !elementExists(types, notification))
+ || (statuses && !elementExists(statuses, notification))
|| (readStatus && !notification.matches(readStatus))
) {
// Make excluded notifications unselectable
- select('.js-notification-bulk-action-check-item', notification)!.removeAttribute('data-check-all-item');
+ $('.js-notification-bulk-action-check-item', notification)!.removeAttribute('data-check-all-item');
}
}
// If at least one notification is selectable, trigger the "Select all" checkbox
- if (select.exists('.js-notification-bulk-action-check-item[data-check-all-item]')) {
+ if (elementExists('.js-notification-bulk-action-check-item[data-check-all-item]')) {
selectAllCheckbox.click();
}
}
// Make all notifications selectable again
- for (const disabledNotificationCheckbox of select.all('.js-notification-bulk-action-check-item:not([data-check-all-item])')) {
+ for (const disabledNotificationCheckbox of $$('.js-notification-bulk-action-check-item:not([data-check-all-item])')) {
disabledNotificationCheckbox.setAttribute('data-check-all-item', '');
}
}
@@ -152,7 +152,7 @@ const createDropdown = onetime(() => (
));
function closeDropdown(): void {
- select('.rgh-select-notifications')?.removeAttribute('open');
+ $('.rgh-select-notifications')?.removeAttribute('open');
}
function addDropdown(markAllPrompt: Element): void {
diff --git a/source/features/selection-in-new-tab.tsx b/source/features/selection-in-new-tab.tsx
index ae4285d2..a33b4d05 100644
--- a/source/features/selection-in-new-tab.tsx
+++ b/source/features/selection-in-new-tab.tsx
@@ -1,11 +1,11 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import onetime from 'onetime';
import features from '../feature-manager.js';
import {registerHotkey} from '../github-helpers/hotkey.js';
function openInNewTab(): void {
- const selected = select('.navigation-focus a.js-navigation-open[href]');
+ const selected = $('.navigation-focus a.js-navigation-open[href]');
if (!selected) {
return;
}
diff --git a/source/features/show-open-prs-of-forks.tsx b/source/features/show-open-prs-of-forks.tsx
index 6f7091b0..82fd909d 100644
--- a/source/features/show-open-prs-of-forks.tsx
+++ b/source/features/show-open-prs-of-forks.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -62,7 +62,7 @@ async function initHeadHint(): Promise<void | false> {
return false;
}
- select(`[data-hovercard-type="repository"][href="/${getForkedRepo()!}"]`)!.after(
+ $(`[data-hovercard-type="repository"][href="/${getForkedRepo()!}"]`)!.after(
// The class is used by `quick-fork-deletion`
<> with <a href={url} className="rgh-open-prs-of-forks">{getLinkCopy(count)}</a></>,
);
@@ -74,7 +74,7 @@ async function initDeleteHint(): Promise<void | false> {
return false;
}
- select('details-dialog[aria-label*="Delete"] .Box-body p:first-child')!.after(
+ $('details-dialog[aria-label*="Delete"] .Box-body p:first-child')!.after(
<p className="flash flash-warn">
It will also abandon <a href={url}>your {getLinkCopy(count)}</a> in <strong>{getForkedRepo()!}</strong> and you’ll no longer be able to edit {count === 1 ? 'it' : 'them'}.
</p>,
diff --git a/source/features/sort-conversations-by-update-time.tsx b/source/features/sort-conversations-by-update-time.tsx
index a63292f6..fb2f6862 100644
--- a/source/features/sort-conversations-by-update-time.tsx
+++ b/source/features/sort-conversations-by-update-time.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import elementReady from 'element-ready';
@@ -16,9 +16,9 @@ export function saveOriginalHref(link: HTMLAnchorElement): void {
async function selectCurrentConversationFilter(): Promise<void> {
const currentSearchURL = location.href.replace('/pulls?', '/issues?'); // Replacement needed to make up for the redirection of "Your pull requests" link
const menu = await elementReady('#filters-select-menu');
- const currentFilter = select(`a.SelectMenu-item[href="${currentSearchURL}"]`, menu);
+ const currentFilter = $(`a.SelectMenu-item[href="${currentSearchURL}"]`, menu);
if (currentFilter) {
- select('[aria-checked="true"]', menu)?.setAttribute('aria-checked', 'false');
+ $('[aria-checked="true"]', menu)?.setAttribute('aria-checked', 'false');
currentFilter.setAttribute('aria-checked', 'true');
}
}
diff --git a/source/features/submission-via-ctrl-enter-everywhere.tsx b/source/features/submission-via-ctrl-enter-everywhere.tsx
index 1472b9ea..773e0d89 100644
--- a/source/features/submission-via-ctrl-enter-everywhere.tsx
+++ b/source/features/submission-via-ctrl-enter-everywhere.tsx
@@ -1,10 +1,10 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
function addQuickSubmit(): void {
- select([
+ $([
'input#commit-summary-input',
'textarea[aria-label="Describe this release"]',
])!.classList.add('js-quick-submit');
diff --git a/source/features/swap-branches-on-compare.tsx b/source/features/swap-branches-on-compare.tsx
index 7d52bf32..559f3653 100644
--- a/source/features/swap-branches-on-compare.tsx
+++ b/source/features/swap-branches-on-compare.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -16,10 +16,10 @@ function init(): void {
// Compares against the "base" branch if the URL only has one reference
if (references.length === 1) {
- references.unshift(select('.branch span')!.textContent);
+ references.unshift($('.branch span')!.textContent);
}
- const referencePicker = select('.range-editor .d-inline-block + .range-cross-repo-pair')!;
+ const referencePicker = $('.range-editor .d-inline-block + .range-cross-repo-pair')!;
referencePicker.after(
<a className="btn btn-sm mx-2" href={buildRepoURL('compare/' + references.join('...'))}>
Swap
diff --git a/source/features/sync-pr-commit-title.tsx b/source/features/sync-pr-commit-title.tsx
index 114ec2ad..22362ee7 100644
--- a/source/features/sync-pr-commit-title.tsx
+++ b/source/features/sync-pr-commit-title.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import delegate from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -14,7 +14,7 @@ const prTitleFieldSelector = 'input#issue_title';
const commitTitleFieldSelector = '.is-squashing form:not([hidden]) input#merge_title_field';
function getCurrentCommitTitleField(): HTMLInputElement | undefined {
- return select(commitTitleFieldSelector);
+ return $(commitTitleFieldSelector);
}
function getCurrentCommitTitle(): string | undefined {
@@ -22,7 +22,7 @@ function getCurrentCommitTitle(): string | undefined {
}
function createCommitTitle(): string {
- const prTitle = select(prTitleFieldSelector)!.value.trim();
+ const prTitle = $(prTitleFieldSelector)!.value.trim();
return `${prTitle} (#${getConversationNumber()!})`;
}
@@ -33,7 +33,7 @@ function needsSubmission(): boolean {
function getUI(): HTMLElement {
const cancelButton = <button type="button" className="btn-link Link--muted text-underline rgh-sync-pr-commit-title">Cancel</button>;
- return select('.rgh-sync-pr-commit-title-note') ?? (
+ return $('.rgh-sync-pr-commit-title-note') ?? (
<p className="note rgh-sync-pr-commit-title-note">
The title of this PR will be updated to match this title. {cancelButton}
</p>
diff --git a/source/features/tag-changes-link.tsx b/source/features/tag-changes-link.tsx
index de60aedf..70b7f58a 100644
--- a/source/features/tag-changes-link.tsx
+++ b/source/features/tag-changes-link.tsx
@@ -1,6 +1,6 @@
import './tag-changes-link.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import domLoaded from 'dom-loaded';
import {DiffIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -19,7 +19,7 @@ type TagDetails = {
};
async function getNextPage(): Promise<DocumentFragment> {
- const nextPageLink = select('.pagination a:last-child');
+ const nextPageLink = $('.pagination a:last-child');
if (nextPageLink) {
return fetchDom(nextPageLink.href);
}
@@ -34,13 +34,13 @@ async function getNextPage(): Promise<DocumentFragment> {
function parseTags(element: HTMLElement): TagDetails {
// Safari doesn't correctly parse links if they're loaded via AJAX #3899
- const {pathname: tagUrl} = new URL(select(['a[href*="/tree/"]', 'a[href*="/tag/"]'], element)!.href);
+ const {pathname: tagUrl} = new URL($(['a[href*="/tree/"]', 'a[href*="/tag/"]'], element)!.href);
const tag = /\/(?:releases\/tag|tree)\/(.*)/.exec(tagUrl)![1];
return {
element,
tag,
- commit: select('[href*="/commit/"]', element)!.textContent.trim(),
+ commit: $('[href*="/commit/"]', element)!.textContent.trim(),
...parseTag(decodeURIComponent(tag)), // `version`, `namespace`
};
}
@@ -89,7 +89,7 @@ async function init(): Promise<void> {
// Look for tags in the current page and the next page
const pages = [document, await getNextPage()];
await domLoaded;
- const allTags = select.all(tagsSelector, pages).map(tag => parseTags(tag));
+ const allTags = $$(tagsSelector, pages).map(tag => parseTags(tag));
for (const [index, container] of allTags.entries()) {
const previousTag = getPreviousTag(index, allTags);
@@ -97,7 +97,7 @@ async function init(): Promise<void> {
continue;
}
- const lastLinks = select.all([
+ const lastLinks = $$([
'.Link--muted[data-hovercard-type="commit"]', // Link to commit in release sidebar
'.list-style-none > .d-inline-block:last-child', // Link to source tarball under release tag
], container.element);
@@ -114,7 +114,7 @@ async function init(): Promise<void> {
);
// The page of a tag without a release still uses the old layout #5037
- if (pageDetect.isEnterprise() || pageDetect.isTags() || (pageDetect.isSingleReleaseOrTag() && select.exists('.release'))) {
+ if (pageDetect.isEnterprise() || pageDetect.isTags() || (pageDetect.isSingleReleaseOrTag() && elementExists('.release'))) {
lastLink.after(
<li className={lastLink.className + ' rgh-changelog-link'}>
{compareLink}
diff --git a/source/features/tags-on-commits-list.tsx b/source/features/tags-on-commits-list.tsx
index 1d21e56f..36f127bc 100644
--- a/source/features/tags-on-commits-list.tsx
+++ b/source/features/tags-on-commits-list.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import cache from 'webext-storage-cache/legacy.js';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import {TagIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -88,7 +88,7 @@ async function getTags(lastCommit: string, after?: string): Promise<CommitTags>
async function init(): Promise<void | false> {
const cacheKey = `tags:${getRepo()!.nameWithOwner}`;
- const commitsOnPage = select.all('.js-commits-list-item');
+ const commitsOnPage = $$('.js-commits-list-item');
const lastCommitOnPage = getCommitHash(commitsOnPage.at(-1)!);
let cached = await cache.get<Record<string, string[]>>(cacheKey) ?? {};
const commitsWithNoTags = [];
@@ -105,7 +105,7 @@ async function init(): Promise<void | false> {
// There was no tags for this commit, save that info to the cache
commitsWithNoTags.push(targetCommit);
} else if (targetTags.length > 0) {
- const commitMeta = select('.flex-auto .d-flex.mt-1', commit)!;
+ const commitMeta = $('.flex-auto .d-flex.mt-1', commit)!;
commitMeta.classList.add('flex-wrap');
commitMeta.append(
<span>
diff --git a/source/features/toggle-files-button.tsx b/source/features/toggle-files-button.tsx
index 40c8ee39..7f6ffd9c 100644
--- a/source/features/toggle-files-button.tsx
+++ b/source/features/toggle-files-button.tsx
@@ -1,5 +1,5 @@
import './toggle-files-button.css';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {CachedValue} from 'webext-storage-cache';
import React from 'dom-chef';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -14,7 +14,7 @@ const wereFilesHidden = new CachedValue<boolean>('files-hidden');
const toggleButtonClass = 'rgh-toggle-files';
function addButton(filesBox: HTMLElement): void {
- select('ul:has(.octicon-history)', filesBox)?.append(
+ $('ul:has(.octicon-history)', filesBox)?.append(
<button
type="button"
className={`btn-octicon ${toggleButtonClass}`}
@@ -31,7 +31,7 @@ type Targets = {
};
function getTargets(): Targets {
- const fileList = select('[aria-labelledby="files"]')!;
+ const fileList = $('[aria-labelledby="files"]')!;
const buttonWrapper = fileList.nextElementSibling!;
return {fileList, buttonWrapper};
}
diff --git a/source/features/unfinished-comments.tsx b/source/features/unfinished-comments.tsx
index 2e824ec1..b0b14177 100644
--- a/source/features/unfinished-comments.tsx
+++ b/source/features/unfinished-comments.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$$} from 'select-dom';
import delegate from 'delegate-it';
import * as pageDetect from 'github-url-detection';
@@ -10,7 +10,7 @@ let submitting: number | undefined;
function hasDraftComments(): boolean {
// `[disabled]` excludes the PR description field that `wait-for-checks` disables while it waits
// `[id^="convert-to-issue-body"]` excludes the hidden pre-filled textareas created when opening the dropdown menu of review comments
- return select.all('textarea:not([disabled], [id^="convert-to-issue-body"])').some(textarea =>
+ return $$('textarea:not([disabled], [id^="convert-to-issue-body"])').some(textarea =>
textarea.value !== textarea.textContent, // Exclude comments being edited but not yet changed (and empty comment fields)
);
}
diff --git a/source/features/unwrap-unnecessary-dropdowns.tsx b/source/features/unwrap-unnecessary-dropdowns.tsx
index 690f5c4b..26d445a8 100644
--- a/source/features/unwrap-unnecessary-dropdowns.tsx
+++ b/source/features/unwrap-unnecessary-dropdowns.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -13,7 +13,7 @@ function replaceDropdownInPlace(dropdown: Element, form: Element): void {
async function unwrapNotifications(): Promise<void | false> {
await elementReady('.js-check-all-container > :first-child'); // Ensure the entire dropdown has loaded
- const forms = select.all('[action="/notifications/beta/update_view_preference"]');
+ const forms = $$('[action="/notifications/beta/update_view_preference"]');
if (forms.length === 0) {
return false;
}
@@ -23,14 +23,14 @@ async function unwrapNotifications(): Promise<void | false> {
}
const dropdown = forms[0].closest('details')!;
- const currentView = select('summary i', dropdown)!.nextSibling!.textContent.trim();
+ const currentView = $('summary i', dropdown)!.nextSibling!.textContent.trim();
const desiredForm = currentView === 'Date' ? forms[0] : forms[1];
// Replace dropdown
replaceDropdownInPlace(dropdown, desiredForm);
// Fix button’s style
- const button = select('[type="submit"]', desiredForm)!;
+ const button = $('[type="submit"]', desiredForm)!;
button.className = 'btn';
button.textContent = `Group by ${button.textContent.toLowerCase()}`;
}
diff --git a/source/features/update-pr-from-base-branch.tsx b/source/features/update-pr-from-base-branch.tsx
index e6f1eca5..388861c7 100644
--- a/source/features/update-pr-from-base-branch.tsx
+++ b/source/features/update-pr-from-base-branch.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -56,7 +56,7 @@ function createButton(): JSX.Element {
}
async function addButton(mergeBar: Element): Promise<void> {
- if (!select.exists(canMerge) || select.exists(canNativelyUpdate)) {
+ if (!elementExists(canMerge) || elementExists(canNativelyUpdate)) {
return;
}
@@ -104,7 +104,7 @@ void features.add(import.meta.url, {
],
exclude: [
pageDetect.isClosedPR,
- () => select('.head-ref')!.title === 'This repository has been deleted',
+ () => $('.head-ref')!.title === 'This repository has been deleted',
],
awaitDomReady: true, // DOM-based exclusions
init,
diff --git a/source/features/use-first-commit-message-for-new-prs.tsx b/source/features/use-first-commit-message-for-new-prs.tsx
index 7f263979..6dff0a3f 100644
--- a/source/features/use-first-commit-message-for-new-prs.tsx
+++ b/source/features/use-first-commit-message-for-new-prs.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
import * as textFieldEdit from 'text-field-edit';
@@ -24,8 +24,8 @@ function interpretNode(node: ChildNode): string | void {
}
function getFirstCommit(): {title: string; body: string | undefined} {
- const titleParts = select('.js-commits-list-item:first-child p')!.childNodes;
- const body = select('.js-commits-list-item:first-child .Details-content--hidden pre')
+ const titleParts = $('.js-commits-list-item:first-child p')!.childNodes;
+ const body = $('.js-commits-list-item:first-child .Details-content--hidden pre')
?.textContent.trim() ?? undefined;
const title = [...titleParts]
@@ -40,21 +40,21 @@ async function init(): Promise<void | false> {
const requestedContent = new URL(location.href).searchParams;
const commitCountIcon = await elementReady('div.Box.mb-3 .octicon-git-commit');
const commitCount = commitCountIcon?.nextElementSibling;
- if (!commitCount || looseParseInt(commitCount) < 2 || !select.exists('#new_pull_request')) {
+ if (!commitCount || looseParseInt(commitCount) < 2 || !elementExists('#new_pull_request')) {
return false;
}
const firstCommit = getFirstCommit();
if (!requestedContent.has('pull_request[title]')) {
textFieldEdit.set(
- select('.discussion-topic-header input')!,
+ $('.discussion-topic-header input')!,
firstCommit.title,
);
}
if (firstCommit.body && !requestedContent.has('pull_request[body]')) {
textFieldEdit.insert(
- select('#new_pull_request textarea[aria-label="Comment body"]')!,
+ $('#new_pull_request textarea[aria-label="Comment body"]')!,
firstCommit.body,
);
}
diff --git a/source/features/useful-not-found-page.tsx b/source/features/useful-not-found-page.tsx
index 122450cd..4cfa35fd 100644
--- a/source/features/useful-not-found-page.tsx
+++ b/source/features/useful-not-found-page.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import onetime from 'onetime';
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
@@ -114,7 +114,7 @@ async function showMissingPart(): Promise<void> {
.reverse() // Restore order
.flatMap((link, i) => [i > 0 && ' / ', link]); // Add separators
- select('main > :first-child, #parallax_illustration')!.after(
+ $('main > :first-child, #parallax_illustration')!.after(
<h2 className="container mt-4 text-center">{breadcrumbs}</h2>,
);
}
@@ -125,7 +125,7 @@ async function showDefaultBranchLink(): Promise<void> {
return;
}
- select('main > .container-lg')!.before(
+ $('main > .container-lg')!.before(
<p className="container mt-4 text-center">
<a href={urlToFileOnDefaultBranch}>This {getType()}</a> exists on the default branch.
</p>,
@@ -172,7 +172,7 @@ async function getGitObjectHistoryLink(): Promise<HTMLElement | undefined> {
async function showGitObjectHistory(): Promise<void> {
const link = await getGitObjectHistoryLink();
if (link) {
- select('main > .container-lg')!.before(link);
+ $('main > .container-lg')!.before(link);
}
}
diff --git a/source/features/user-local-time.tsx b/source/features/user-local-time.tsx
index 070e1cc6..3b64e0b3 100644
--- a/source/features/user-local-time.tsx
+++ b/source/features/user-local-time.tsx
@@ -4,7 +4,7 @@ import './user-local-time.css';
import React from 'dom-chef';
import {CachedFunction} from 'webext-storage-cache';
import delay from 'delay';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import {ClockIcon} from '@primer/octicons-react';
import features from '../feature-manager.js';
@@ -108,17 +108,17 @@ async function display({
async function insertUserLocalTime(hovercardContainer: Element): Promise<void> {
const hovercard = hovercardContainer.closest('div.Popover-message')!;
- if (!select.exists('[data-hydro-view*="user-hovercard-hover"]', hovercard)) {
+ if (!elementExists('[data-hydro-view*="user-hovercard-hover"]', hovercard)) {
// It's not the hovercard type we expect
return;
}
- if (select.exists('profile-timezone', hovercard)) {
+ if (elementExists('profile-timezone', hovercard)) {
// Native time already present
return;
}
- const login = select('a.Link--primary', hovercard)?.pathname.slice(1);
+ const login = $('a.Link--primary', hovercard)?.pathname.slice(1);
if (!login || login === getUsername()) {
return;
}
diff --git a/source/features/vertical-front-matter.tsx b/source/features/vertical-front-matter.tsx
index f26ab3a0..e2427ac3 100644
--- a/source/features/vertical-front-matter.tsx
+++ b/source/features/vertical-front-matter.tsx
@@ -1,6 +1,6 @@
import './vertical-front-matter.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import elementReady from 'element-ready';
@@ -15,12 +15,12 @@ async function init(): Promise<false | void> {
return false;
}
- const headers = select.all(':scope > thead th', table);
+ const headers = $$(':scope > thead th', table);
if (headers.length <= 4) {
return false;
}
- const rows = select.all(':scope > tbody > tr', table);
+ const rows = $$(':scope > tbody > tr', table);
if (rows.length !== 1 || headers.length !== rows[0].childElementCount) {
return false;
}
diff --git a/source/features/view-last-pr-deployment.tsx b/source/features/view-last-pr-deployment.tsx
index c70b3991..17f3ff91 100644
--- a/source/features/view-last-pr-deployment.tsx
+++ b/source/features/view-last-pr-deployment.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {lastElement} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {RocketIcon} from '@primer/octicons-react';
@@ -7,7 +7,7 @@ import features from '../feature-manager.js';
import observe from '../helpers/selector-observer.js';
function addLink(header: HTMLElement): void {
- const lastDeployment = select.last('.js-timeline-item a[title="Deployment has completed"]');
+ const lastDeployment = lastElement('.js-timeline-item a[title="Deployment has completed"]');
if (!lastDeployment) {
return;
}
diff --git a/source/features/wait-for-attachments.tsx b/source/features/wait-for-attachments.tsx
index 49d1e403..5a78c98a 100644
--- a/source/features/wait-for-attachments.tsx
+++ b/source/features/wait-for-attachments.tsx
@@ -2,7 +2,7 @@
// `textarea[data-required-trimmed]` conflicts with this behavior by overriding the validity states in the meantime.
// `button[data-disable-invalid]` are automatically disabled while the form is invalid, but some buttons don't have it.
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -13,13 +13,13 @@ const attributeBackup = 'data-rgh-required-trimmed';
function toggleSubmitButtons({target, type}: Event): void {
const fileAttachment = target as HTMLElement;
- for (const button of select.all('.btn-primary[type="submit"]:not([data-disable-invalid])', fileAttachment.closest('form')!)) {
+ for (const button of $$('.btn-primary[type="submit"]:not([data-disable-invalid])', fileAttachment.closest('form')!)) {
button.dataset.disableInvalid = '';
}
// Temporarily disable `data-required-trimmed` so that it doesn't conflict with the desired behavior.
// The complex selector ensures that we don't add the attribute to fields that never had it in the first place.
- const textarea = select(`[${attribute}], [${attributeBackup}]`, fileAttachment)!;
+ const textarea = $(`[${attribute}], [${attributeBackup}]`, fileAttachment)!;
if (textarea) {
if (type === 'upload:setup') {
textarea.setAttribute(attributeBackup, textarea.getAttribute(attribute)!);
diff --git a/source/features/wait-for-checks.tsx b/source/features/wait-for-checks.tsx
index 0e067063..1a28b54d 100644
--- a/source/features/wait-for-checks.tsx
+++ b/source/features/wait-for-checks.tsx
@@ -1,6 +1,6 @@
import './wait-for-checks.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import onetime from 'onetime';
import {InfoIcon} from '@primer/octicons-react';
import * as pageDetect from 'github-url-detection';
@@ -36,7 +36,7 @@ const generateCheckbox = onetime(() => (
));
function getCheckbox(): HTMLInputElement | undefined {
- return select('input[name="rgh-pr-check-waiter"]');
+ return $('input[name="rgh-pr-check-waiter"]');
}
// Only show the checkbox if the last commit doesn't have a green or red CI icon
@@ -46,10 +46,10 @@ function showCheckboxIfNecessary(): void {
const isNecessary = lastCommitStatus === prCiStatus.PENDING
// If the latest commit is missing an icon, add the checkbox as long as there's at least one CI icon on the page (including `ci-link`)
- || (lastCommitStatus === false && select.exists(prCommitStatusIcon));
+ || (lastCommitStatus === false && elementExists(prCommitStatusIcon));
if (!checkbox && isNecessary) {
- select('.js-merge-form .select-menu')?.append(generateCheckbox());
+ $('.js-merge-form .select-menu')?.append(generateCheckbox());
} else if (checkbox && !isNecessary) {
checkbox.parentElement!.remove();
}
@@ -58,7 +58,7 @@ function showCheckboxIfNecessary(): void {
let waiting: symbol | undefined;
function disableForm(disabled = true): void {
- for (const field of select.all(`
+ for (const field of $$(`
textarea[name="commit_message"],
input[name="commit_title"],
input[name="rgh-pr-check-waiter"],
@@ -196,7 +196,7 @@ void features.add(import.meta.url, {
userCanLikelyMergePR,
pageDetect.isOpenPR,
// The repo has enabled Actions
- () => select.exists(actionsTab),
+ () => elementExists(actionsTab),
],
include: [
pageDetect.isPRConversation,
diff --git a/source/features/warn-pr-from-master.tsx b/source/features/warn-pr-from-master.tsx
index c47108c4..0b15080d 100644
--- a/source/features/warn-pr-from-master.tsx
+++ b/source/features/warn-pr-from-master.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import * as pageDetect from 'github-url-detection';
import features from '../feature-manager.js';
@@ -8,8 +8,8 @@ import {getRepo} from '../github-helpers/index.js';
async function init(): Promise<false | void> {
let defaultBranch;
- if (select.exists('.is-cross-repo')) {
- const forkedRepository = getRepo(select('[title^="head: "]')!.textContent)!;
+ if (elementExists('.is-cross-repo')) {
+ const forkedRepository = getRepo($('[title^="head: "]')!.textContent)!;
defaultBranch = await defaultBranchOfRepo.get(forkedRepository);
} else {
defaultBranch = await getDefaultBranch();
@@ -20,7 +20,7 @@ async function init(): Promise<false | void> {
return false;
}
- select('.js-compare-pr')!.before(
+ $('.js-compare-pr')!.before(
<div className="flash flash-error my-3">
<strong>Note:</strong> Creating a PR from the default branch is an <a href="https://blog.jasonmeridth.com/posts/do-not-issue-pull-requests-from-your-master-branch/" target="_blank" rel="noopener noreferrer">anti-pattern</a>.
</div>,
diff --git a/source/features/warning-for-disallow-edits.tsx b/source/features/warning-for-disallow-edits.tsx
index 6aba8e1b..5d598af5 100644
--- a/source/features/warning-for-disallow-edits.tsx
+++ b/source/features/warning-for-disallow-edits.tsx
@@ -1,6 +1,6 @@
import './warning-for-disallow-edits.css';
import React from 'dom-chef';
-import select from 'select-dom';
+import {$} from 'select-dom';
import onetime from 'onetime';
import * as pageDetect from 'github-url-detection';
import delegate, {DelegateEvent} from 'delegate-it';
@@ -33,7 +33,7 @@ function toggleHandler(event: DelegateEvent<Event, HTMLInputElement>): void {
}
function init(signal: AbortSignal): void | false {
- const checkbox = select('input[name="collab_privs"]');
+ const checkbox = $('input[name="collab_privs"]');
if (!checkbox) {
return false;
}
diff --git a/source/github-events/on-field-keydown.tsx b/source/github-events/on-field-keydown.tsx
index ae21b164..fc8e491e 100644
--- a/source/github-events/on-field-keydown.tsx
+++ b/source/github-events/on-field-keydown.tsx
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {elementExists} from 'select-dom';
import delegate, {DelegateEventHandler} from 'delegate-it';
type DelegateFieldEvent = DelegateEventHandler<KeyboardEvent, HTMLTextAreaElement>;
@@ -8,7 +8,7 @@ function onFieldKeydown(selector: string, callback: DelegateFieldEvent, signal:
const field = event.delegateTarget;
// The suggester is GitHub’s autocomplete dropdown
- if (select.exists('.suggester', field.form!) || event.isComposing) {
+ if (elementExists('.suggester', field.form!) || event.isComposing) {
return;
}
diff --git a/source/github-helpers/dom-formatters.tsx b/source/github-helpers/dom-formatters.tsx
index d764498b..ca19d5f7 100644
--- a/source/github-helpers/dom-formatters.tsx
+++ b/source/github-helpers/dom-formatters.tsx
@@ -1,5 +1,5 @@
import React from 'dom-chef';
-import select from 'select-dom';
+import {$$, elementExists} from 'select-dom';
import zipTextNodes from 'zip-text-nodes';
import {applyToLink} from 'shorten-repo-url';
import linkifyURLsCore from 'linkify-urls';
@@ -68,8 +68,8 @@ export function linkifyURLs(element: Element): Element[] | void {
return;
}
- if (select.exists(linkifiedURLSelector, element)) {
- return select.all(linkifiedURLSelector, element);
+ if (elementExists(linkifiedURLSelector, element)) {
+ return $$(linkifiedURLSelector, element);
}
const linkified = linkifyURLsCore(element.textContent, {
diff --git a/source/github-helpers/get-current-git-ref.ts b/source/github-helpers/get-current-git-ref.ts
index b2d1d1c9..65b9feff 100644
--- a/source/github-helpers/get-current-git-ref.ts
+++ b/source/github-helpers/get-current-git-ref.ts
@@ -1,5 +1,5 @@
import {isRepoCommitList} from 'github-url-detection';
-import select from 'select-dom';
+import {$} from 'select-dom';
import {extractCurrentBranchFromBranchPicker} from './index.js';
import {branchSelector} from './selectors.js';
@@ -11,7 +11,7 @@ const titleWithGitRef = / at (?<branch>[.\w-/]+)( · [\w-]+\/[\w-]+)?$/i;
export default function getCurrentGitRef(): string | undefined {
// Note: This is not in the <head> so it's only available on AJAXed loads.
// It appears on every Code page except `commits` on folders/files
- const picker = select(branchSelector);
+ const picker = $(branchSelector);
const refViaPicker = picker && extractCurrentBranchFromBranchPicker(picker);
if (refViaPicker) {
return refViaPicker;
@@ -49,7 +49,7 @@ export function getGitRef(pathname: string, title: string): string | undefined {
// In <head>, but not reliable https://github.com/refined-github/refined-github/assets/1402241/50357d94-505f-48dc-bd54-74e86b19d642
function getCurrentBranchFromFeed(): string | undefined {
- const feedLink = isRepoCommitList() && select('link[type="application/atom+xml"]');
+ const feedLink = isRepoCommitList() && $('link[type="application/atom+xml"]');
if (!feedLink) {
// Do not throw errors, the element may be missing after AJAX navigation even if on the right page
return;
diff --git a/source/github-helpers/get-tab-count.ts b/source/github-helpers/get-tab-count.ts
index c7658395..af7a18a4 100644
--- a/source/github-helpers/get-tab-count.ts
+++ b/source/github-helpers/get-tab-count.ts
@@ -1,8 +1,8 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import oneMutation from 'one-mutation';
export default async function getTabCount(tab: Element): Promise<number> {
- const counter = select('.Counter, .num', tab);
+ const counter = $('.Counter, .num', tab);
if (!counter) {
// GitHub might have already dropped the counter, which means it's 0
return 0;
diff --git a/source/github-helpers/get-user-avatar.ts b/source/github-helpers/get-user-avatar.ts
index 510066e2..e61b2e81 100644
--- a/source/github-helpers/get-user-avatar.ts
+++ b/source/github-helpers/get-user-avatar.ts
@@ -1,11 +1,11 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import * as pageDetect from 'github-url-detection';
export default function getUserAvatar(username: string, size: number): string | void {
const cleanName = username.replace('[bot]', '');
// Find image on page. Saves a request and a redirect + add support for bots
- const existingAvatar = select(`img[alt="@${cleanName}"]`);
+ const existingAvatar = $(`img[alt="@${cleanName}"]`);
if (existingAvatar) {
return existingAvatar.src;
}
diff --git a/source/github-helpers/index.ts b/source/github-helpers/index.ts
index b9e4e673..051d4b02 100644
--- a/source/github-helpers/index.ts
+++ b/source/github-helpers/index.ts
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$, elementExists} from 'select-dom';
import onetime from 'onetime';
import elementReady from 'element-ready';
import compareVersions from 'tiny-version-compare';
@@ -37,7 +37,7 @@ export function buildRepoURL<S extends string>(...pathParts: RequireAtLeastOne<A
}
export function getForkedRepo(): string | undefined {
- return select('meta[name="octolytics-dimension-repository_parent_nwo"]')?.content;
+ return $('meta[name="octolytics-dimension-repository_parent_nwo"]')?.content;
}
export function parseTag(tag: string): {version: string; namespace: string} {
@@ -92,7 +92,7 @@ export const isPermalink = mem(async () => {
}
// Awaiting only the branch selector means it resolves early even if the icon tag doesn't exist, whereas awaiting the icon tag would wait for the DOM ready event before resolving.
- return select.exists(
+ return elementExists(
'.octicon-tag', // Tags have an icon
await elementReady(branchSelector),
);
@@ -118,7 +118,7 @@ export async function isArchivedRepoAsync(): Promise<boolean> {
return pageDetect.isArchivedRepo();
}
-export const userCanLikelyMergePR = (): boolean => select.exists('.discussion-sidebar-item .octicon-lock');
+export const userCanLikelyMergePR = (): boolean => elementExists('.discussion-sidebar-item .octicon-lock');
export const cacheByRepo = (): string => getRepo()!.nameWithOwner;
diff --git a/source/github-helpers/load-details-menu.ts b/source/github-helpers/load-details-menu.ts
index f3db3d42..13158676 100644
--- a/source/github-helpers/load-details-menu.ts
+++ b/source/github-helpers/load-details-menu.ts
@@ -1,8 +1,8 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import oneEvent from 'one-event';
export default async function loadDetailsMenu(detailsMenu: HTMLElement): Promise<void> {
- const fragment = select('.js-comment-header-actions-deferred-include-fragment', detailsMenu);
+ const fragment = $('.js-comment-header-actions-deferred-include-fragment', detailsMenu);
if (!fragment) {
return;
}
diff --git a/source/github-helpers/pr-branches.ts b/source/github-helpers/pr-branches.ts
index a2105bc8..38747679 100644
--- a/source/github-helpers/pr-branches.ts
+++ b/source/github-helpers/pr-branches.ts
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
export type PrReference = {
/** @example fregante/mem:main */
@@ -59,10 +59,10 @@ function parseReference(referenceElement: HTMLElement): PrReference {
export function getBranches(): {base: PrReference; head: PrReference} {
return {
get base() {
- return parseReference(select('.base-ref')!);
+ return parseReference($('.base-ref')!);
},
get head() {
- return parseReference(select('.head-ref')!);
+ return parseReference($('.head-ref')!);
},
};
}
diff --git a/source/github-helpers/pr-ci-status.ts b/source/github-helpers/pr-ci-status.ts
index d1c4a970..31e074fc 100644
--- a/source/github-helpers/pr-ci-status.ts
+++ b/source/github-helpers/pr-ci-status.ts
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$, lastElement} from 'select-dom';
import api from './api.js';
import {prCommit, prCommitStatusIcon} from './selectors.js';
@@ -9,13 +9,13 @@ export const PENDING = Symbol('Pending');
export type CommitStatus = false | typeof SUCCESS | typeof FAILURE | typeof PENDING;
export function getLastCommitReference(): string {
- return select.last(`${prCommit} code`)!.textContent;
+ return lastElement(`${prCommit} code`)!.textContent;
}
export function getLastCommitStatus(): CommitStatus {
// Select the last commit first, THEN pick the icon, otherwise it might pick non-last commit while the CI is starting up
- const lastCommit = select.last(prCommit)!;
- const lastCommitStatusIcon = select(prCommitStatusIcon, lastCommit);
+ const lastCommit = lastElement(prCommit)!;
+ const lastCommitStatusIcon = $(prCommitStatusIcon, lastCommit);
// Some commits don't have a CI status icon at all
if (lastCommitStatusIcon) {
diff --git a/source/helpers/attach-element.ts b/source/helpers/attach-element.ts
index 031925cf..0703febc 100644
--- a/source/helpers/attach-element.ts
+++ b/source/helpers/attach-element.ts
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$, $$, elementExists} from 'select-dom';
import {RequireAtLeastOne} from 'type-fest';
import {isDefined} from 'ts-extras';
@@ -29,7 +29,7 @@ export default function attachElement<NewElement extends Element>(
forEach,
allowMissingAnchor = false,
}: Attachment<NewElement>): NewElement[] {
- const anchorElement = typeof anchor === 'string' ? select(anchor) : anchor;
+ const anchorElement = typeof anchor === 'string' ? $(anchor) : anchor;
if (!anchorElement) {
if (allowMissingAnchor) {
return [];
@@ -38,7 +38,7 @@ export default function attachElement<NewElement extends Element>(
throw new Error('Element not found');
}
- if (select.exists('.' + className, anchorElement.parentElement ?? anchorElement)) {
+ if (elementExists('.' + className, anchorElement.parentElement ?? anchorElement)) {
return [];
}
@@ -68,6 +68,6 @@ export function attachElements<NewElement extends Element>(anchors: string | str
className = 'rgh-' + getCallerID(),
...options
}: Attachment<NewElement>): NewElement[] {
- return select.all(`:is(${String(anchors)}):not(.${className})`)
+ return $$(`:is(${String(anchors)}):not(.${className})`)
.flatMap(anchor => attachElement(anchor, {...options, className}));
}
diff --git a/source/helpers/bisect.tsx b/source/helpers/bisect.tsx
index e9bc47aa..902c4a2b 100644
--- a/source/helpers/bisect.tsx
+++ b/source/helpers/bisect.tsx
@@ -1,6 +1,6 @@
import React from 'dom-chef';
import {CachedValue} from 'webext-storage-cache';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import elementReady from 'element-ready';
import pluralize from './pluralize.js';
@@ -58,7 +58,7 @@ async function onEndButtonClick(): Promise<void> {
}
function createMessageBox(message: Element | string, extraButtons?: Element): void {
- select('#rgh-bisect-dialog')?.remove();
+ $('#rgh-bisect-dialog')?.remove();
document.body.append(
<div id="rgh-bisect-dialog" className="Box p-3">
<p>{message}</p>
@@ -97,7 +97,7 @@ export default async function bisectFeatures(): Promise<Record<string, boolean>
// Enable "Yes"/"No" buttons once the page is done loading
window.addEventListener('load', () => {
- for (const button of select.all('#rgh-bisect-dialog [aria-disabled]')) {
+ for (const button of $$('#rgh-bisect-dialog [aria-disabled]')) {
button.removeAttribute('aria-disabled');
}
});
diff --git a/source/helpers/click-all.ts b/source/helpers/click-all.ts
index 9d38adff..a9fb4f64 100644
--- a/source/helpers/click-all.ts
+++ b/source/helpers/click-all.ts
@@ -1,5 +1,5 @@
import mem from 'mem';
-import select from 'select-dom';
+import {$$} from 'select-dom';
import {DelegateEvent} from 'delegate-it';
import preserveScroll from './preserve-scroll.js';
@@ -17,7 +17,7 @@ export default mem((selector: string | ((clickedItem: HTMLElement) => string)):
});
function clickAllExcept(elementsToClick: string, except: HTMLElement): void {
- for (const item of select.all(elementsToClick)) {
+ for (const item of $$(elementsToClick)) {
if (item !== except) {
item.click();
}
diff --git a/source/helpers/dom-utils.ts b/source/helpers/dom-utils.ts
index ce301d5b..415436ac 100644
--- a/source/helpers/dom-utils.ts
+++ b/source/helpers/dom-utils.ts
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import {setFetch} from 'push-form';
// Nodes may be exactly `null`
import {type Nullable} from 'vitest';
@@ -35,11 +35,11 @@ if (window.content?.fetch) {
*/
export const appendBefore = (parent: string | Element, before: string, child: Element): void => {
if (typeof parent === 'string') {
- parent = select(parent)!;
+ parent = $(parent)!;
}
// Select direct children only
- const beforeElement = select(`:scope > :is(${before})`, parent);
+ const beforeElement = $(`:scope > :is(${before})`, parent);
if (beforeElement) {
beforeElement.before(child);
} else {
diff --git a/source/helpers/on-element-replacement.ts b/source/helpers/on-element-replacement.ts
index 27c555e4..f5110205 100644
--- a/source/helpers/on-element-replacement.ts
+++ b/source/helpers/on-element-replacement.ts
@@ -1,4 +1,4 @@
-import select from 'select-dom';
+import {$} from 'select-dom';
import onElementRemoval from './on-element-removal.js';
@@ -18,7 +18,7 @@ export default async function onElementReplacement(
return;
}
- let trackedElement = select(selector);
+ let trackedElement = $(selector);
if (!trackedElement) {
throw new Error('The element can’t be found');
}
@@ -34,7 +34,7 @@ export default async function onElementReplacement(
return;
}
- trackedElement = select(selector);
+ trackedElement = $(selector);
if (trackedElement) {
callback(trackedElement);
}
diff --git a/source/options.tsx b/source/options.tsx
index 3c5e842f..5c47aba4 100644
--- a/source/options.tsx
+++ b/source/options.tsx
@@ -2,7 +2,7 @@ import 'webext-base-css/webext-base.css';
import './options.css';
import React from 'dom-chef';
import domify from 'doma';
-import select from 'select-dom';
+import {$, $$} from 'select-dom';
import fitTextarea from 'fit-textarea';
import prettyBytes from 'pretty-bytes';
import {assertError} from 'ts-extras';
@@ -34,7 +34,7 @@ type Status = {
const {version} = browser.runtime.getManifest();
function reportStatus({tokenType, error, text, scopes}: Status): void {
- const tokenStatus = select('#validation')!;
+ const tokenStatus = $('#validation')!;
tokenStatus.textContent = text ?? '';
if (error) {
tokenStatus.dataset.validation = 'invalid';
@@ -43,11 +43,11 @@ function reportStatus({tokenType, error, text, scopes}: Status): void {
}
// Toggle the ulists by token type (default to classic)
- for (const ulist of select.all('[data-token-type]')) {
+ for (const ulist of $$('[data-token-type]')) {
ulist.style.display = ulist.dataset.tokenType === tokenType ? '' : 'none';
}
- for (const scope of select.all('[data-scope]')) {
+ for (const scope of $$('[data-scope]')) {
if (scopes) {
scope.dataset.validation = scopes.includes(scope.dataset.scope!) ? 'valid' : 'invalid';
} else {
@@ -57,7 +57,7 @@ function reportStatus({tokenType, error, text, scopes}: Status): void {
}
async function getTokenScopes(personalToken: string): Promise<string[]> {
- const tokenLink = select('a#personal-token-link')!;
+ const tokenLink = $('a#personal-token-link')!;
const url = tokenLink.host === 'github.com'
? 'https://api.github.com/'
: `${tokenLink.origin}/api/v3/`;
@@ -91,14 +91,14 @@ async function getTokenScopes(personalToken: string): Promise<string[]> {
}
function expandTokenSection(): void {
- select('details#token')!.open = true;
+ $('details#token')!.open = true;
}
async function updateStorageUsage(area: 'sync' | 'local'): Promise<void> {
const storage = browser.storage[area];
const used = await getStorageBytesInUse(area);
const available = storage.QUOTA_BYTES - used;
- for (const output of select.all(`.storage-${area}`)) {
+ for (const output of $$(`.storage-${area}`)) {
output.textContent = available < 1000
? 'FULL!'
: (available < 100_000
@@ -108,7 +108,7 @@ async function updateStorageUsage(area: 'sync' | 'local'): Promise<void> {
}
async function validateToken(): Promise<void> {
- const tokenField = select('input[name="personalToken"]')!;
+ const tokenField = $('input[name="personalToken"]')!;
const tokenType = tokenField.value.startsWith('github_pat_') ? 'fine_grained' : 'classic';
reportStatus({tokenType});
@@ -135,9 +135,9 @@ async function validateToken(): Promise<void> {
}
function moveDisabledFeaturesToTop(): void {
- const container = select('.js-features')!;
+ const container = $('.js-features')!;
- for (const unchecked of select.all('.feature-checkbox:not(:checked)', container).reverse()) {
+ for (const unchecked of $$('.feature-checkbox:not(:checked)', container).reverse()) {
// .reverse() needed to preserve alphabetical order while prepending
container.prepend(unchecked.closest('.feature')!);
}
@@ -180,7 +180,7 @@ async function findFeatureHandler(event: Event): Promise<void> {
button.disabled = false;
}, 10_000);
- select('#find-feature-message')!.hidden = false;
+ $('#find-feature-message')!.hidden = false;
}
function summaryHandler(event: DelegateEvent<MouseEvent>): void {
@@ -190,7 +190,7 @@ function summaryHandler(event: DelegateEvent<MouseEvent>): void {
event.preventDefault();
if (event.altKey) {
- for (const screenshotLink of select.all('.screenshot-link')) {
+ for (const screenshotLink of $$('.screenshot-link')) {
toggleScreenshot(screenshotLink.parentElement!);
}
} else {
@@ -213,7 +213,7 @@ function featuresFilterHandler(event: Event): void {
.replaceAll(/\W/g, ' ')
.split(/\s+/)
.filter(Boolean); // Ignore empty strings
- for (const feature of select.all('.feature')) {
+ for (const feature of $$('.feature')) {
feature.hidden = !keywords.every(word => feature.dataset.text!.includes(word));
}
}
@@ -222,7 +222,7 @@ function focusFirstField({delegateTarget: section}: DelegateEvent<Event, HTMLDet
// @ts-expect-error No Firefox support https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded
(section.scrollIntoViewIfNeeded ?? section.scrollIntoView).call(section);
if (section.open) {
- const field = select('input, textarea', section);
+ const field = $('input, textarea', section);
if (field) {
field.focus();
if (field instanceof HTMLTextAreaElement) {
@@ -236,10 +236,10 @@ function focusFirstField({delegateTarget: section}: DelegateEvent<Event, HTMLDet
async function markLocalHotfixes(): Promise<void> {
for (const [feature, relatedIssue] of await getLocalHotfixes()) {
if (importedFeatures.includes(feature)) {
- const input = select<HTMLInputElement>('#' + feature)!;
+ const input = $<HTMLInputElement>('#' + feature)!;
input.disabled = true;
input.removeAttribute('name');
- select(`.feature-name[for="${feature}"]`)!.after(
+ $(`.feature-name[for="${feature}"]`)!.after(
<span className="hotfix-notice"> (Disabled due to {createRghIssueLink(relatedIssue)})</span>,
);
}
@@ -251,12 +251,12 @@ function updateRateLink(): void {
return;
}
- select('a#rate-link')!.href = isFirefox() ? 'https://addons.mozilla.org/en-US/firefox/addon/refined-github-' : 'https://apps.apple.com/app/id1519867270?action=write-review';
+ $('a#rate-link')!.href = isFirefox() ? 'https://addons.mozilla.org/en-US/firefox/addon/refined-github-' : 'https://apps.apple.com/app/id1519867270?action=write-review';
}
async function showStoredCssHotfixes(): Promise<void> {
const cachedCSS = await styleHotfixes.getCached(version);
- select('#hotfixes-field')!.textContent
+ $('#hotfixes-field')!.textContent
= isDevelopmentVersion()
? 'Hotfixes are not applied in the development version.'
: isEnterprise()
@@ -266,30 +266,30 @@ async function showStoredCssHotfixes(): Promise<void> {
function enableToggleAll({currentTarget: button}: Event): void {
(button as HTMLButtonElement).parentElement!.remove();
- for (const ui of select.all('.toggle-all-features')) {
+ for (const ui of $$('.toggle-all-features')) {
ui.hidden = false;
}
}
function disableAllFeatures(): void {
- for (const enabledFeature of select.all('.feature-checkbox:checked')) {
+ for (const enabledFeature of $$('.feature-checkbox:checked')) {
enabledFeature.click();
}
- select('details#features')!.open = true;
+ $('details#features')!.open = true;
}
function enableAllFeatures(): void {
- for (const disabledFeature of select.all('.feature-checkbox:not(:checked)')) {
+ for (const disabledFeature of $$('.feature-checkbox:not(:checked)')) {
disabledFeature.click();
}
- select('details#features')!.open = true;
+ $('details#features')!.open = true;
}
async function generateDom(): Promise<void> {
// Generate list
- select('.js-features')!.append(...featuresMeta
+ $('.js-features')!.append(...featuresMeta
.filter(feature => importedFeatures.includes(feature.id))
.map(feature => buildFeatureCheckbox(feature)),
);
@@ -301,7 +301,7 @@ async function generateDom(): Promise<void> {
await perDomainOptions.syncForm('form');
// Only now the form is ready, we can show it
- select('#js-failed')!.remove();
+ $('#js-failed')!.remove();
// Decorate list
moveDisabledFeaturesToTop();
@@ -310,7 +310,7 @@ async function generateDom(): Promise<void> {
void validateToken();
// Add feature count. CSS-only features are added approximately
- select('.features-header')!.append(` (${featuresMeta.length + 25})`);
+ $('.features-header')!.append(` (${featuresMeta.length + 25})`);
// Update rate link if necessary
updateRateLink();
@@ -321,7 +321,7 @@ async function generateDom(): Promise<void> {
// Hide non-applicable "Button link" section
if (doesBrowserActionOpenOptions) {
- select('#action')!.hidden = true;
+ $('#action')!.hidden = true;
}
// Show stored CSS hotfixes
@@ -330,9 +330,9 @@ async function generateDom(): Promise<void> {
function addEventListeners(): void {
// Update domain-dependent page content when the domain is changed
- select('.OptionsSyncPerDomain-picker select')?.addEventListener('change', ({currentTarget: dropdown}) => {
+ $('.OptionsSyncPerDomain-picker select')?.addEventListener('change', ({currentTarget: dropdown}) => {
const host = (dropdown as HTMLSelectElement).value;
- select('a#personal-token-link')!.host = host === 'default' ? 'github.com' : host;
+ $('a#personal-token-link')!.host = host === 'default' ? 'github.com' : host;
// Delay validating to let options load first
setTimeout(validateToken, 100);
});
@@ -361,21 +361,21 @@ function addEventListeners(): void {
delegate('details', 'toggle', focusFirstField, {capture: true});
// Filter feature list
- select('#filter-features')!.addEventListener('input', featuresFilterHandler);
+ $('#filter-features')!.addEventListener('input', featuresFilterHandler);
// Add cache clearer
- select('#clear-cache')!.addEventListener('click', clearCacheHandler);
+ $('#clear-cache')!.addEventListener('click', clearCacheHandler);
// Add bisect tool
- select('#find-feature')!.addEventListener('click', findFeatureHandler);
+ $('#find-feature')!.addEventListener('click', findFeatureHandler);
// Handle "Toggle all" buttons
- select('#toggle-all-features')!.addEventListener('click', enableToggleAll);
- select('#disable-all-features')!.addEventListener('click', disableAllFeatures);
- select('#enable-all-features')!.addEventListener('click', enableAllFeatures);
+ $('#toggle-all-features')!.addEventListener('click', enableToggleAll);
+ $('#disable-all-features')!.addEventListener('click', disableAllFeatures);
+ $('#enable-all-features')!.addEventListener('click', enableAllFeatures);
// Add token validation
- select('[name="personalToken"]')!.addEventListener('input', validateToken);
+ $('[name="personalToken"]')!.addEventListener('input', validateToken);
}
async function init(): Promise<void> {