3
3
* Happy about anyone who's able to make this work with imports (i.e. run the tests in this project), but I couldn't figure it out and gave up.
4
4
*/
5
5
6
- export type SupportedApplication = "github" | "gitlab" | "bitbucket-server" | "bitbucket" ;
6
+ export type SupportedApplication = "github" | "gitlab" | "bitbucket-server" | "bitbucket" | "azure-devops" ;
7
7
8
8
const resolveMetaAppName = ( head : HTMLHeadElement ) : string | undefined => {
9
9
const metaApplication = head . querySelector ( "meta[name=application-name]" ) ;
@@ -18,16 +18,24 @@ const resolveMetaAppName = (head: HTMLHeadElement): string | undefined => {
18
18
return undefined ;
19
19
} ;
20
20
21
+ export const DEFAULT_HOSTS = [ "github.com" , "gitlab.com" , "bitbucket.org" , "dev.azure.com" ] ;
22
+
21
23
/**
22
24
* Provides a fast check to see if the current URL is on a supported site.
23
25
*/
24
26
export const isSiteSuitable = ( ) : boolean => {
27
+ const isWhitelistedHost = DEFAULT_HOSTS . some ( ( host ) => location . host === host ) ;
28
+ if ( isWhitelistedHost ) {
29
+ return true ;
30
+ }
31
+
25
32
const appName = resolveMetaAppName ( document . head ) ;
26
33
if ( ! appName ) {
27
34
return false ;
28
35
}
29
36
const allowedApps = [ "GitHub" , "GitLab" , "Bitbucket" ] ;
30
- return allowedApps . includes ( appName ) ;
37
+
38
+ return allowedApps . some ( ( allowedApp ) => appName . includes ( allowedApp ) ) ;
31
39
} ;
32
40
33
41
export interface ButtonContributionParams {
@@ -51,7 +59,7 @@ export interface ButtonContributionParams {
51
59
/**
52
60
* The element in which the button should be inserted.
53
61
*
54
- * This element will be inserted into teh main document and allows for styling within the original page.
62
+ * This element will be inserted into the main document and allows for styling within the original page.
55
63
*
56
64
* The structure looks like this:
57
65
*
@@ -98,6 +106,12 @@ export interface ButtonContributionParams {
98
106
* the classnames to remove and add.
99
107
*/
100
108
manipulations ?: { element : string ; remove ?: string ; add ?: string ; style ?: Partial < CSSStyleDeclaration > } [ ] ;
109
+
110
+ /**
111
+ * A function that can be used to transform the URL that should be opened when the Gitpod button is clicked.
112
+ * @returns The transformed URL.
113
+ */
114
+ urlTransformer ?: ( originalURL : string ) => string ;
101
115
}
102
116
103
117
function createElement (
@@ -113,6 +127,61 @@ function createElement(
113
127
}
114
128
115
129
export const buttonContributions : ButtonContributionParams [ ] = [
130
+ // Azure DevOps
131
+ {
132
+ id : "ado-repo" ,
133
+ exampleUrls : [
134
+ // "https://dev.azure.com/services-azure/_git/project2"
135
+ ] ,
136
+ selector : "div.repos-files-header-commandbar:nth-child(1)" ,
137
+ containerElement : createElement ( "div" , { } ) ,
138
+ application : "azure-devops" ,
139
+ insertBefore : `div.bolt-header-command-item-button:has(button[id^="__bolt-header-command-bar-menu-button"])` ,
140
+ manipulations : [
141
+ {
142
+ element : "div.repos-files-header-commandbar.scroll-hidden" ,
143
+ remove : "scroll-hidden" ,
144
+ } ,
145
+ ] ,
146
+ urlTransformer ( originalUrl ) {
147
+ const url = new URL ( originalUrl ) ;
148
+ if ( url . pathname . includes ( "version=GB" ) ) {
149
+ return originalUrl ;
150
+ }
151
+ // version=GBdevelop
152
+ const branchElement = document . evaluate (
153
+ "//div[contains(@class, 'version-dropdown')]//span[contains(@class, 'text-ellipsis')]" ,
154
+ document ,
155
+ null ,
156
+ XPathResult . FIRST_ORDERED_NODE_TYPE ,
157
+ null ,
158
+ ) . singleNodeValue ;
159
+ if ( branchElement ) {
160
+ const branch = branchElement . textContent ?. trim ( ) ;
161
+ url . searchParams . set ( "version" , `GB${ branch } ` ) ;
162
+ }
163
+
164
+ return url . toString ( ) ;
165
+ } ,
166
+ } ,
167
+ {
168
+ id : "ado-pr" ,
169
+ exampleUrls : [
170
+ // "https://dev.azure.com/services-azure/test-project/_git/repo2/pullrequest/1"
171
+ ] ,
172
+ selector : ".repos-pr-header > div:nth-child(2) > div:nth-child(1)" ,
173
+ containerElement : createElement ( "div" , { } ) ,
174
+ application : "azure-devops" ,
175
+ insertBefore : `div.bolt-header-command-item-button:has(button[id^="__bolt-menu-button-"])` ,
176
+ } ,
177
+ {
178
+ id : "ado-repo-empty" ,
179
+ exampleUrls : [ ] ,
180
+ selector : "div.clone-with-application" ,
181
+ application : "azure-devops" ,
182
+ containerElement : createElement ( "div" , { marginLeft : "4px" , marginRight : "4px" } ) ,
183
+ } ,
184
+
116
185
// GitLab
117
186
{
118
187
id : "gl-repo" , // also taking care of branches
0 commit comments