@@ -81,9 +81,7 @@ TEST: addTests('isCompare', [
8181 'https://github.com/sindresorhus/refined-github/compare' ,
8282 'https://github.com/sindresorhus/refined-github/compare/' ,
8383 'https://github.com/sindresorhus/refined-github/compare/master...branch-name' ,
84- 'https://github.com/sindresorhus/refined-github/compare/master...branch-name?quick_pull=1' ,
85- 'https://github.com/sindresorhus/refined-github/compare/branch-1...branch-2?quick_pull=1' ,
86- 'https://github.com/sindresorhus/refined-github/compare/test-branch?quick_pull=1' ,
84+ 'isQuickPR' ,
8785] ) ;
8886
8987export const isCompareWikiPage = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => isRepoWiki ( url ) && getCleanPathname ( url ) . split ( '/' ) . slice ( 3 , 5 ) . includes ( '_compare' ) ;
@@ -92,17 +90,19 @@ TEST: addTests('isCompareWikiPage', [
9290 'https://github.com/brookhong/Surfingkeys/wiki/Color-Themes/_compare/8ebb46b1a12d16fc1af442b7df0ca13ca3bb34dc...80e51eeabe69b15a3f23880ecc36f800b71e6c6d' ,
9391] ) ;
9492
93+ /**
94+ * @deprecated Use `isHome` and/or `isFeed` instead
95+ */
9596export const isDashboard = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => ! isGist ( url ) && / ^ $ | ^ ( o r g s \/ [ ^ / ] + \/ ) ? d a s h b o a r d ( - f e e d ) ? ( \/ | $ ) / . test ( getCleanPathname ( url ) ) ;
9697TEST: addTests ( 'isDashboard' , [
9798 'https://github.com///' ,
9899 'https://github.com//' ,
99100 'https://github.com/' ,
100101 'https://github.com' ,
101- 'https://github.com/orgs/test /dashboard' ,
102+ 'https://github.com/orgs/refined-github /dashboard' ,
102103 'https://github.com/dashboard/index/2' ,
103104 'https://github.com//dashboard' ,
104105 'https://github.com/dashboard' ,
105- 'https://github.com/orgs/edit/dashboard' ,
106106 'https://github.big-corp.com/' ,
107107 'https://not-github.com/' ,
108108 'https://my-little-hub.com/' ,
@@ -115,6 +115,31 @@ TEST: addTests('isDashboard', [
115115 'https://github.com/dashboard-feed' ,
116116] ) ;
117117
118+ export const isHome = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => ! isGist ( url ) && / ^ $ | ^ d a s h b o a r d \/ ? $ / . test ( getCleanPathname ( url ) ) ;
119+ TEST: addTests ( 'isHome' , [
120+ 'https://github.com' ,
121+ 'https://github.com//dashboard' ,
122+ 'https://github.com///' ,
123+ 'https://github.com//' ,
124+ 'https://github.com/' ,
125+ 'https://github.com/dashboard' ,
126+ 'https://github.big-corp.com/' ,
127+ 'https://not-github.com/' ,
128+ 'https://my-little-hub.com/' ,
129+ 'https://github.com/?tab=repositories' , // Gotcha for `isUserProfileRepoTab`
130+ 'https://github.com/?tab=stars' , // Gotcha for `isUserProfileStarsTab`
131+ 'https://github.com/?tab=followers' , // Gotcha for `isUserProfileFollowersTab`
132+ 'https://github.com/?tab=following' , // Gotcha for `isUserProfileFollowingTab`
133+ 'https://github.com/?tab=overview' , // Gotcha for `isUserProfileMainTab`
134+ 'https://github.com?search=1' , // Gotcha for `isRepoTree`
135+ ] ) ;
136+
137+ export const isFeed = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => ! isGist ( url ) && / ^ ( f e e d | o r g s \/ [ ^ / ] + \/ d a s h b o a r d ) \/ ? $ / . test ( getCleanPathname ( url ) ) ;
138+ TEST: addTests ( 'isFeed' , [
139+ 'https://github.com/feed' ,
140+ 'https://github.com/orgs/refined-github/dashboard' ,
141+ ] ) ;
142+
118143export const isEnterprise = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => url . hostname !== 'github.com' && url . hostname !== 'gist.github.com' ;
119144TEST: addTests ( 'isEnterprise' , [
120145 'https://github.big-corp.com/' ,
@@ -217,7 +242,11 @@ TEST: addTests('isNotifications', [
217242
218243export const isOrganizationProfile = ( ) : boolean => exists ( 'meta[name="hovercard-subject-tag"][content^="organization"]' ) ;
219244
220- export const isOrganizationRepo = ( ) : boolean => exists ( '.AppHeader-context-full [data-hovercard-type="organization"]' ) ;
245+ export const isOrganizationRepo = ( ) : boolean => exists ( [
246+ 'qbsearch-input[data-current-repository][data-current-org]:not([data-current-repository=""], [data-current-org=""])' ,
247+ // TODO: Remove after June 2026
248+ '.AppHeader-context-full [data-hovercard-type="organization"]' ,
249+ ] . join ( ',' ) ) ;
221250
222251export const isTeamDiscussion = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => Boolean ( getOrg ( url ) ?. path . startsWith ( 'teams' ) ) ;
223252TEST: addTests ( 'isTeamDiscussion' , [
@@ -317,18 +346,20 @@ TEST: addTests('isPRFiles', [
317346 'https://github.com/refined-github/refined-github/pull/148/changes/1e27d7998afdd3608d9fc3bf95ccf27fa5010641..e1aba6febb3fe38aafd1137cff28b536eeeabe7e' ,
318347] ) ;
319348
320- export const isQuickPR = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => isCompare ( url ) && / [ ? & ] q u i c k _ p u l l = 1 ( & | $ ) / . test ( url . search ) ;
349+ export const isQuickPR = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => isCompare ( url ) && / [ ? & ] ( q u i c k _ p u l l | e x p a n d ) = 1 ( & | $ ) / . test ( url . search ) ;
321350TEST: addTests ( 'isQuickPR' , [
322351 'https://github.com/sindresorhus/refined-github/compare/master...branch-name?quick_pull=1' ,
323352 'https://github.com/sindresorhus/refined-github/compare/branch-1...branch-2?quick_pull=1' ,
324353 'https://github.com/sindresorhus/refined-github/compare/test-branch?quick_pull=1' ,
354+ 'https://github.com/refined-github/sandbox/compare/fregante-patch-2?expand=1' ,
355+ 'https://github.com/refined-github/sandbox/compare/default-a...fregante-patch-2?expand=1' ,
325356] ) ;
326357
327358const getStateLabel = ( ) : string | undefined => $ ( [
328359 '.State' , // Old view
329360 // React versions
330- '[class^="StateLabel"]' ,
331- '[data-testid="header-state "]' ,
361+ '[class^="StateLabel"]' , // TODO: Remove after July 2026
362+ '[class^="prc-StateLabel-StateLabel "]' ,
332363] . join ( ',' ) ) ?. textContent ?. trim ( ) ;
333364
334365export const isMergedPR = ( ) : boolean => getStateLabel ( ) === 'Merged' ;
@@ -422,9 +453,16 @@ TEST: addTests('isRepo', [
422453export const hasRepoHeader = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => isRepo ( url ) && ! isRepoSearch ( url ) ;
423454TEST: addTests ( 'hasRepoHeader' , combinedTestOnly ) ;
424455
425- // On empty repos, there's only isRepoHome; this element is found in `<head>`
426- export const isEmptyRepoRoot = ( ) : boolean => isRepoHome ( ) && ! exists ( 'link[rel="canonical"]' ) ;
456+ export const isEmptyRepoRoot = ( ) : boolean => isRepoHome ( ) && exists ( [
457+ // If you don't have write access
458+ '.blankslate-icon' ,
459+ // If you have write access
460+ '#empty-setup-clone-url' ,
461+ ] . join ( ',' ) ) ;
427462
463+ /**
464+ * @deprecated Doesn't work anymore. Use `isEmptyRepoRoot` or API instead.
465+ */
428466export const isEmptyRepo = ( ) : boolean => exists ( '[aria-label="Cannot fork because repository is empty."]' ) ;
429467
430468export const isPublicRepo = ( ) : boolean => exists ( 'meta[name="octolytics-dimension-repository_public"][content="true"]' ) ;
@@ -751,7 +789,7 @@ TEST: addTests('isGistProfile', [
751789
752790export const isUserProfile = ( ) : boolean => isProfile ( ) && ! isOrganizationProfile ( ) ;
753791
754- export const isPrivateUserProfile = ( ) : boolean => isUserProfile ( ) && ! exists ( '.UnderlineNav-item[href$="tab=stars"] ' ) ;
792+ export const isPrivateUserProfile = ( ) : boolean => isUserProfile ( ) && exists ( '#user-private-profile-frame ' ) ;
755793
756794export const isUserProfileMainTab = ( ) : boolean =>
757795 isUserProfile ( )
@@ -883,7 +921,20 @@ TEST: addTests('isRepositoryActions', [
883921
884922export const isUserTheOrganizationOwner = ( ) : boolean => isOrganizationProfile ( ) && exists ( '[aria-label="Organization"] [data-tab-item="org-header-settings-tab"]' ) ;
885923
886- export const canUserAdminRepo = ( ) : boolean => isRepo ( ) && exists ( '.reponav-item[href$="/settings"], [data-tab-item$="settings-tab"]' ) ;
924+ /**
925+ * @deprecated Use canUserAccessRepoSettings or API instead.
926+ */
927+ export const canUserAdminRepo = ( ) : boolean => {
928+ const repo = getRepo ( ) ;
929+ return Boolean ( repo && exists ( `:is(${ [
930+ '.GlobalNav' ,
931+ // Remove after June 2026
932+ '.js-repo-nav' ,
933+ ] . join ( ',' ) } ) a[href="/${ repo . nameWithOwner } /settings"]`) ) ;
934+ } ;
935+
936+ // eslint-disable-next-line @typescript-eslint/no-deprecated
937+ export const canUserAccessRepoSettings = canUserAdminRepo ;
887938
888939export const isNewRepo = ( url : URL | HTMLAnchorElement | Location = location ) : boolean => ! isGist ( url ) && ( url . pathname === '/new' || / ^ o r g a n i z a t i o n s \/ [ ^ / ] + \/ r e p o s i t o r i e s \/ n e w $ / . test ( getCleanPathname ( url ) ) ) ;
889940TEST: addTests ( 'isNewRepo' , [
0 commit comments