hosts.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* eslint-disable max-len */
  2. 'use strict'
  3. const maybeJoin = (...args) => args.every(arg => arg) ? args.join('') : ''
  4. const maybeEncode = (arg) => arg ? encodeURIComponent(arg) : ''
  5. const formatHashFragment = (f) => f.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-')
  6. const defaults = {
  7. sshtemplate: ({ domain, user, project, committish }) =>
  8. `git@${domain}:${user}/${project}.git${maybeJoin('#', committish)}`,
  9. sshurltemplate: ({ domain, user, project, committish }) =>
  10. `git+ssh://git@${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
  11. edittemplate: ({ domain, user, project, committish, editpath, path }) =>
  12. `https://${domain}/${user}/${project}${maybeJoin('/', editpath, '/', maybeEncode(committish || 'HEAD'), '/', path)}`,
  13. browsetemplate: ({ domain, user, project, committish, treepath }) =>
  14. `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}`,
  15. browsetreetemplate: ({ domain, user, project, committish, treepath, path, fragment, hashformat }) =>
  16. `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || 'HEAD')}/${path}${maybeJoin('#', hashformat(fragment || ''))}`,
  17. browseblobtemplate: ({ domain, user, project, committish, blobpath, path, fragment, hashformat }) =>
  18. `https://${domain}/${user}/${project}/${blobpath}/${maybeEncode(committish || 'HEAD')}/${path}${maybeJoin('#', hashformat(fragment || ''))}`,
  19. docstemplate: ({ domain, user, project, treepath, committish }) =>
  20. `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}#readme`,
  21. httpstemplate: ({ auth, domain, user, project, committish }) =>
  22. `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
  23. filetemplate: ({ domain, user, project, committish, path }) =>
  24. `https://${domain}/${user}/${project}/raw/${maybeEncode(committish || 'HEAD')}/${path}`,
  25. shortcuttemplate: ({ type, user, project, committish }) =>
  26. `${type}:${user}/${project}${maybeJoin('#', committish)}`,
  27. pathtemplate: ({ user, project, committish }) =>
  28. `${user}/${project}${maybeJoin('#', committish)}`,
  29. bugstemplate: ({ domain, user, project }) =>
  30. `https://${domain}/${user}/${project}/issues`,
  31. hashformat: formatHashFragment,
  32. }
  33. const hosts = {}
  34. hosts.github = {
  35. // First two are insecure and generally shouldn't be used any more, but
  36. // they are still supported.
  37. protocols: ['git:', 'http:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'],
  38. domain: 'github.com',
  39. treepath: 'tree',
  40. blobpath: 'blob',
  41. editpath: 'edit',
  42. filetemplate: ({ auth, user, project, committish, path }) =>
  43. `https://${maybeJoin(auth, '@')}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish || 'HEAD')}/${path}`,
  44. gittemplate: ({ auth, domain, user, project, committish }) =>
  45. `git://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
  46. tarballtemplate: ({ domain, user, project, committish }) =>
  47. `https://codeload.${domain}/${user}/${project}/tar.gz/${maybeEncode(committish || 'HEAD')}`,
  48. extract: (url) => {
  49. let [, user, project, type, committish] = url.pathname.split('/', 5)
  50. if (type && type !== 'tree') {
  51. return
  52. }
  53. if (!type) {
  54. committish = url.hash.slice(1)
  55. }
  56. if (project && project.endsWith('.git')) {
  57. project = project.slice(0, -4)
  58. }
  59. if (!user || !project) {
  60. return
  61. }
  62. return { user, project, committish }
  63. },
  64. }
  65. hosts.bitbucket = {
  66. protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'],
  67. domain: 'bitbucket.org',
  68. treepath: 'src',
  69. blobpath: 'src',
  70. editpath: '?mode=edit',
  71. edittemplate: ({ domain, user, project, committish, treepath, path, editpath }) =>
  72. `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish || 'HEAD'), '/', path, editpath)}`,
  73. tarballtemplate: ({ domain, user, project, committish }) =>
  74. `https://${domain}/${user}/${project}/get/${maybeEncode(committish || 'HEAD')}.tar.gz`,
  75. extract: (url) => {
  76. let [, user, project, aux] = url.pathname.split('/', 4)
  77. if (['get'].includes(aux)) {
  78. return
  79. }
  80. if (project && project.endsWith('.git')) {
  81. project = project.slice(0, -4)
  82. }
  83. if (!user || !project) {
  84. return
  85. }
  86. return { user, project, committish: url.hash.slice(1) }
  87. },
  88. }
  89. hosts.gitlab = {
  90. protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'],
  91. domain: 'gitlab.com',
  92. treepath: 'tree',
  93. blobpath: 'tree',
  94. editpath: '-/edit',
  95. httpstemplate: ({ auth, domain, user, project, committish }) =>
  96. `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
  97. tarballtemplate: ({ domain, user, project, committish }) =>
  98. `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish || 'HEAD')}`,
  99. extract: (url) => {
  100. const path = url.pathname.slice(1)
  101. if (path.includes('/-/') || path.includes('/archive.tar.gz')) {
  102. return
  103. }
  104. const segments = path.split('/')
  105. let project = segments.pop()
  106. if (project.endsWith('.git')) {
  107. project = project.slice(0, -4)
  108. }
  109. const user = segments.join('/')
  110. if (!user || !project) {
  111. return
  112. }
  113. return { user, project, committish: url.hash.slice(1) }
  114. },
  115. }
  116. hosts.gist = {
  117. protocols: ['git:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'],
  118. domain: 'gist.github.com',
  119. editpath: 'edit',
  120. sshtemplate: ({ domain, project, committish }) =>
  121. `git@${domain}:${project}.git${maybeJoin('#', committish)}`,
  122. sshurltemplate: ({ domain, project, committish }) =>
  123. `git+ssh://git@${domain}/${project}.git${maybeJoin('#', committish)}`,
  124. edittemplate: ({ domain, user, project, committish, editpath }) =>
  125. `https://${domain}/${user}/${project}${maybeJoin('/', maybeEncode(committish))}/${editpath}`,
  126. browsetemplate: ({ domain, project, committish }) =>
  127. `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`,
  128. browsetreetemplate: ({ domain, project, committish, path, hashformat }) =>
  129. `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}${maybeJoin('#', hashformat(path))}`,
  130. browseblobtemplate: ({ domain, project, committish, path, hashformat }) =>
  131. `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}${maybeJoin('#', hashformat(path))}`,
  132. docstemplate: ({ domain, project, committish }) =>
  133. `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`,
  134. httpstemplate: ({ domain, project, committish }) =>
  135. `git+https://${domain}/${project}.git${maybeJoin('#', committish)}`,
  136. filetemplate: ({ user, project, committish, path }) =>
  137. `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin('/', maybeEncode(committish))}/${path}`,
  138. shortcuttemplate: ({ type, project, committish }) =>
  139. `${type}:${project}${maybeJoin('#', committish)}`,
  140. pathtemplate: ({ project, committish }) =>
  141. `${project}${maybeJoin('#', committish)}`,
  142. bugstemplate: ({ domain, project }) =>
  143. `https://${domain}/${project}`,
  144. gittemplate: ({ domain, project, committish }) =>
  145. `git://${domain}/${project}.git${maybeJoin('#', committish)}`,
  146. tarballtemplate: ({ project, committish }) =>
  147. `https://codeload.github.com/gist/${project}/tar.gz/${maybeEncode(committish || 'HEAD')}`,
  148. extract: (url) => {
  149. let [, user, project, aux] = url.pathname.split('/', 4)
  150. if (aux === 'raw') {
  151. return
  152. }
  153. if (!project) {
  154. if (!user) {
  155. return
  156. }
  157. project = user
  158. user = null
  159. }
  160. if (project.endsWith('.git')) {
  161. project = project.slice(0, -4)
  162. }
  163. return { user, project, committish: url.hash.slice(1) }
  164. },
  165. hashformat: function (fragment) {
  166. return fragment && 'file-' + formatHashFragment(fragment)
  167. },
  168. }
  169. hosts.sourcehut = {
  170. protocols: ['git+ssh:', 'https:'],
  171. domain: 'git.sr.ht',
  172. treepath: 'tree',
  173. blobpath: 'tree',
  174. filetemplate: ({ domain, user, project, committish, path }) =>
  175. `https://${domain}/${user}/${project}/blob/${maybeEncode(committish) || 'HEAD'}/${path}`,
  176. httpstemplate: ({ domain, user, project, committish }) =>
  177. `https://${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
  178. tarballtemplate: ({ domain, user, project, committish }) =>
  179. `https://${domain}/${user}/${project}/archive/${maybeEncode(committish) || 'HEAD'}.tar.gz`,
  180. bugstemplate: ({ user, project }) =>
  181. `https://todo.sr.ht/${user}/${project}`,
  182. extract: (url) => {
  183. let [, user, project, aux] = url.pathname.split('/', 4)
  184. // tarball url
  185. if (['archive'].includes(aux)) {
  186. return
  187. }
  188. if (project && project.endsWith('.git')) {
  189. project = project.slice(0, -4)
  190. }
  191. if (!user || !project) {
  192. return
  193. }
  194. return { user, project, committish: url.hash.slice(1) }
  195. },
  196. }
  197. for (const [name, host] of Object.entries(hosts)) {
  198. hosts[name] = Object.assign({}, defaults, host)
  199. }
  200. module.exports = hosts