11/**
22 * @typedef {import('mdast').Root } Root
33 *
4+ * @callback DefaultBuildUrl
5+ * @param {BuildUrlValues } values
6+ * @returns {string }
7+ *
8+ * @callback BuildUrl
9+ * @param {BuildUrlValues } values
10+ * @param {DefaultBuildUrl } defaultBuildUrl
11+ * @returns {string }
12+ *
13+ * @typedef {BuildUrlCommitValues|BuildUrlCompareValues|BuildUrlIssueValues|BuildUrlMentionValues } BuildUrlValues
14+ *
15+ * @typedef BuildUrlCommitValues
16+ * Arguments for buildUrl functions for commit hash
17+ * @property {'commit' } type The type of special object
18+ * @property {string } hash The commit hash value
19+ * @property {string } project The project of the repo
20+ * @property {string } user The owner of the repo
21+ *
22+ * @typedef BuildUrlCompareValues
23+ * Arguments for buildUrl functions for commit hash ranges
24+ * @property {'compare' } type The type of special object
25+ * @property {string } base The SHA of the range start
26+ * @property {string } compare The SHA of the range end
27+ * @property {string } project The project of the repo
28+ * @property {string } user The owner of the repo
29+ *
30+ * @typedef BuildUrlIssueValues
31+ * Arguments for buildUrl functions for issues
32+ * @property {'issue' } type The type of special object
33+ * @property {string } no The parsed issue number
34+ * @property {string } project The project of the repo
35+ * @property {string } user The owner of the repo
36+ *
37+ * @typedef BuildUrlMentionValues
38+ * Arguments for buildUrl functions for mentions
39+ * @property {'mention' } type The type of special object
40+ * @property {string } user The parsed user name
41+ *
42+ * @typedef RepositoryInfo
43+ * The owner and project of the repo
44+ * @property {string } project The project/repo name
45+ * @property {string } user The user/organization name
46+ *
447 * @typedef Options
548 * Configuration.
49+ * @property {BuildUrl } [buildUrl]
650 * @property {boolean } [mentionStrong=true]
751 * Wrap mentions in `<strong>`, true by default.
852 * This makes them render more like how GitHub styles them.
@@ -118,13 +162,23 @@ export default function remarkGithub(options = {}) {
118162 : ''
119163 }
120164
165+ /**
166+ * @param {BuildUrlValues } values
167+ * @returns {string }
168+ */
169+ function buildUrl ( values ) {
170+ if ( options . buildUrl ) return options . buildUrl ( values , defaultBuildUrl )
171+ return defaultBuildUrl ( values )
172+ }
173+
121174 // Parse the URL: See the tests for all possible kinds.
122175 const repositoryMatch = repoRegex . exec ( repository || '' )
123176
124177 if ( ! repositoryMatch ) {
125178 throw new Error ( 'Missing `repository` field in `options`' )
126179 }
127180
181+ /** @type {RepositoryInfo } */
128182 const repositoryInfo = { user : repositoryMatch [ 1 ] , project : repositoryMatch [ 2 ] }
129183
130184 return ( tree ) => {
@@ -213,7 +267,7 @@ export default function remarkGithub(options = {}) {
213267 return {
214268 type : 'link' ,
215269 title : null ,
216- url : 'https://github.com/' + username ,
270+ url : buildUrl ( { type : 'mention' , user : username } ) ,
217271 children : [ node ]
218272 }
219273 }
@@ -235,13 +289,12 @@ export default function remarkGithub(options = {}) {
235289 return {
236290 type : 'link' ,
237291 title : null ,
238- url :
239- 'https://github.com/' +
240- repositoryInfo . user +
241- '/' +
242- repositoryInfo . project +
243- '/issues/' +
292+ url : buildUrl ( {
293+ type : 'issue' ,
244294 no,
295+ project : repositoryInfo . project ,
296+ user : repositoryInfo . user
297+ } ) ,
245298 children : [ { type : 'text' , value} ]
246299 }
247300 }
@@ -265,13 +318,13 @@ export default function remarkGithub(options = {}) {
265318 return {
266319 type : 'link' ,
267320 title : null ,
268- url :
269- 'https://github.com/' +
270- repositoryInfo . user +
271- '/' +
272- repositoryInfo . project +
273- '/compare/' +
274- value ,
321+ url : buildUrl ( {
322+ type : 'compare' ,
323+ base : a ,
324+ compare : b ,
325+ project : repositoryInfo . project ,
326+ user : repositoryInfo . user
327+ } ) ,
275328 children : [ { type : 'inlineCode' , value : abbr ( a ) + '...' + abbr ( b ) } ]
276329 }
277330 }
@@ -296,13 +349,12 @@ export default function remarkGithub(options = {}) {
296349 return {
297350 type : 'link' ,
298351 title : null ,
299- url :
300- 'https://github.com/' +
301- repositoryInfo . user +
302- '/' +
303- repositoryInfo . project +
304- '/commit/' +
305- value ,
352+ url : buildUrl ( {
353+ type : 'commit' ,
354+ project : repositoryInfo . project ,
355+ user : repositoryInfo . user ,
356+ hash : value
357+ } ) ,
306358 children : [ { type : 'inlineCode' , value : abbr ( value ) } ]
307359 }
308360 }
@@ -350,15 +402,19 @@ export default function remarkGithub(options = {}) {
350402 return {
351403 type : 'link' ,
352404 title : null ,
353- url :
354- 'https://github.com/' +
355- user +
356- '/' +
357- ( project || repositoryInfo . project ) +
358- '/' +
359- ( no ? 'issues' : 'commit' ) +
360- '/' +
361- ( no || sha ) ,
405+ url : no
406+ ? buildUrl ( {
407+ type : 'issue' ,
408+ no,
409+ project : project || repositoryInfo . project ,
410+ user
411+ } )
412+ : buildUrl ( {
413+ type : 'commit' ,
414+ hash : sha ,
415+ project : project || repositoryInfo . project ,
416+ user
417+ } ) ,
362418 children : nodes
363419 }
364420 }
@@ -374,6 +430,34 @@ function abbr(sha) {
374430 return sha . slice ( 0 , minShaLength )
375431}
376432
433+ /**
434+ * Given a set of values based on the values type, returns link URL.
435+ *
436+ * @type {DefaultBuildUrl }
437+ */
438+ function defaultBuildUrl ( values ) {
439+ const base = 'https://github.com'
440+
441+ if ( values . type === 'mention' ) return [ base , values . user ] . join ( '/' )
442+
443+ const { project, user} = values
444+
445+ if ( values . type === 'commit' )
446+ return [ base , user , project , 'commit' , values . hash ] . join ( '/' )
447+
448+ if ( values . type === 'issue' )
449+ return [ base , user , project , 'issues' , values . no ] . join ( '/' )
450+
451+ // This should only run if values.type is 'compare'
452+ return [
453+ base ,
454+ user ,
455+ project ,
456+ 'compare' ,
457+ values . base + '...' + values . compare
458+ ] . join ( '/' )
459+ }
460+
377461/**
378462 * Parse a link and determine whether it links to GitHub.
379463 *
0 commit comments