Skip to content

Commit

Permalink
feat(browse): fragment support for browse() (#28)
Browse files Browse the repository at this point in the history
* extended browse method to support optional file path

This could be extremely useful for those wanting to generate links to
formatted docs and/or syntax highlighted source files

* updated REAMDE.md to document new browse method signature

* fixed gist browsefile URLs by transforming path to lower case and added ability to also append hash fragment

* minor improvement to README to use real live URL example for hash fragment
  • Loading branch information
neocotic authored and zkat committed Mar 7, 2018
1 parent 627ab55 commit cd5e5bb
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 10 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,11 @@ would return `https://raw.githubusercontent.com/npm/hosted-git-info/v1.0.0/packa

eg, `github:npm/hosted-git-info`

* info.browse(opts)
* info.browse(path, fragment, opts)

eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0`
eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0`,
`https://github.com/npm/hosted-git-info/tree/v1.2.0/package.json`,
`https://github.com/npm/hosted-git-info/tree/v1.2.0/REAMDE.md#supported-hosts`

* info.bugs(opts)

Expand Down Expand Up @@ -129,4 +131,3 @@ SSH connect strings will be normalized into `git+ssh` URLs.

Currently this supports Github, Bitbucket and Gitlab. Pull requests for
additional hosts welcome.

14 changes: 12 additions & 2 deletions git-host-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,30 @@ var gitHosts = module.exports = {
'sshtemplate': 'git@{domain}:/{project}.git{#committish}',
'sshurltemplate': 'git+ssh://git@{domain}/{project}.git{#committish}',
'browsetemplate': 'https://{domain}/{project}{/committish}',
'browsefiletemplate': 'https://{domain}/{project}{/committish}{#path}',
'docstemplate': 'https://{domain}/{project}{/committish}',
'httpstemplate': 'git+https://{domain}/{project}.git{#committish}',
'shortcuttemplate': '{type}:{project}{#committish}',
'pathtemplate': '{project}{#committish}',
'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz'
'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz',
'hashformat': function (fragment) {
return 'file-' + formatHashFragment(fragment)
}
}
}

var gitHostDefaults = {
'sshtemplate': 'git@{domain}:{user}/{project}.git{#committish}',
'sshurltemplate': 'git+ssh://git@{domain}/{user}/{project}.git{#committish}',
'browsetemplate': 'https://{domain}/{user}/{project}{/tree/committish}',
'browsefiletemplate': 'https://{domain}/{user}/{project}/{treepath}/{committish}/{path}{#fragment}',
'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#readme',
'httpstemplate': 'git+https://{auth@}{domain}/{user}/{project}.git{#committish}',
'filetemplate': 'https://{domain}/{user}/{project}/raw/{committish}/{path}',
'shortcuttemplate': '{type}:{user}/{project}{#committish}',
'pathtemplate': '{user}/{project}{#committish}',
'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/
'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/,
'hashformat': formatHashFragment
}

Object.keys(gitHosts).forEach(function (name) {
Expand All @@ -66,3 +72,7 @@ Object.keys(gitHosts).forEach(function (name) {
return protocol.replace(/([\\+*{}()[\]$^|])/g, '\\$1')
}).join('|') + '):$')
})

function formatHashFragment (fragment) {
return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-')
}
26 changes: 21 additions & 5 deletions git-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,24 @@ GitHost.prototype.hash = function () {
GitHost.prototype._fill = function (template, opts) {
if (!template) return
var vars = Object.assign({}, opts)
vars.path = vars.path ? vars.path.replace(/^[/]+/g, '') : ''
opts = Object.assign({}, this.opts, opts)
var self = this
Object.keys(this).forEach(function (key) {
if (self[key] != null && vars[key] == null) vars[key] = self[key]
})
var rawAuth = vars.auth
var rawComittish = vars.committish
var rawFragment = vars.fragment
var rawPath = vars.path
Object.keys(vars).forEach(function (key) {
vars[key] = encodeURIComponent(vars[key])
})
vars['auth@'] = rawAuth ? rawAuth + '@' : ''
vars['#fragment'] = rawFragment ? '#' + this.hashformat(rawFragment) : ''
vars.fragment = vars.fragment ? vars.fragment : ''
vars['#path'] = rawPath ? '#' + this.hashformat(rawPath) : ''
vars['/path'] = vars.path ? '/' + vars.path : ''
if (opts.noCommittish) {
vars['#committish'] = ''
vars['/tree/committish'] = ''
Expand Down Expand Up @@ -66,8 +73,19 @@ GitHost.prototype.sshurl = function (opts) {
return this._fill(this.sshurltemplate, opts)
}

GitHost.prototype.browse = function (opts) {
return this._fill(this.browsetemplate, opts)
GitHost.prototype.browse = function (P, F, opts) {
if (typeof P === 'string') {
if (typeof F !== 'string') {
opts = F
F = null
}
return this._fill(this.browsefiletemplate, extend({
fragment: F,
path: P
}, opts))
} else {
return this._fill(this.browsetemplate, P)
}
}

GitHost.prototype.docs = function (opts) {
Expand Down Expand Up @@ -99,9 +117,7 @@ GitHost.prototype.tarball = function (opts) {
}

GitHost.prototype.file = function (P, opts) {
return this._fill(this.filetemplate, Object.assign({
path: P.replace(/^[/]+/g, '')
}, opts))
return this._fill(this.filetemplate, Object.assign({ path: P }, opts))
}

GitHost.prototype.getDefaultRepresentation = function () {
Expand Down
2 changes: 2 additions & 0 deletions test/bitbucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ test('fromUrl(bitbucket url)', function (t) {
if (!hostinfo) return
t.is(hostinfo.https(), 'git+https://bitbucket.org/111/222.git' + hash, label + ' -> https')
t.is(hostinfo.browse(), 'https://bitbucket.org/111/222' + (branch ? '/src/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse('C'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.docs(), 'https://bitbucket.org/111/222' + (branch ? '/src/' + branch : '') + '#readme', label + ' -> docs')
t.is(hostinfo.ssh(), 'git@bitbucket.org:111/222.git' + hash, label + ' -> ssh')
t.is(hostinfo.sshurl(), 'git+ssh://git@bitbucket.org/111/222.git' + hash, label + ' -> sshurl')
Expand Down
2 changes: 2 additions & 0 deletions test/gist.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ test('fromUrl(gist url)', function (t) {
t.is(hostinfo.https(), 'git+https://gist.github.com/222.git' + hash, label + ' -> https')
t.is(hostinfo.git(), 'git://gist.github.com/222.git' + hash, label + ' -> git')
t.is(hostinfo.browse(), 'https://gist.github.com/222' + (branch ? '/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse('C'), 'https://gist.github.com/222' + (branch ? '/' + branch : '') + '#file-c', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://gist.github.com/222' + (branch ? '/' + branch : '') + '#file-c', label + ' -> browse(path, fragment)')
t.is(hostinfo.bugs(), 'https://gist.github.com/222', label + ' -> bugs')
t.is(hostinfo.docs(), 'https://gist.github.com/222' + (branch ? '/' + branch : ''), label + ' -> docs')
t.is(hostinfo.ssh(), 'git@gist.github.com:/222.git' + hash, label + ' -> ssh')
Expand Down
2 changes: 2 additions & 0 deletions test/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ test('fromUrl(github url)', function (t) {
t.is(hostinfo.https(), 'git+https://github.com/111/222.git' + hash, label + ' -> https')
t.is(hostinfo.git(), 'git://github.com/111/222.git' + hash, label + ' -> git')
t.is(hostinfo.browse(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse('C'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.bugs(), 'https://github.com/111/222/issues', label + ' -> bugs')
t.is(hostinfo.docs(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : '') + '#readme', label + ' -> docs')
t.is(hostinfo.ssh(), 'git@github.com:111/222.git' + hash, label + ' -> ssh')
Expand Down
2 changes: 2 additions & 0 deletions test/gitlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ test('fromUrl(gitlab url)', function (t) {
if (!hostinfo) return
t.is(hostinfo.https(), 'git+https://gitlab.com/111/222.git' + hash, label + ' -> https')
t.is(hostinfo.browse(), 'https://gitlab.com/111/222' + (branch ? '/tree/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse('C'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.docs(), 'https://gitlab.com/111/222' + (branch ? '/tree/' + branch : '') + '#README', label + ' -> docs')
t.is(hostinfo.ssh(), 'git@gitlab.com:111/222.git' + hash, label + ' -> ssh')
t.is(hostinfo.sshurl(), 'git+ssh://git@gitlab.com/111/222.git' + hash, label + ' -> sshurl')
Expand Down
2 changes: 2 additions & 0 deletions test/https-with-inline-auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ test('HTTPS GitHub URL with embedded auth -- generally not a good idea', functio
t.is(hostinfo.https(), 'git+https://user:pass@github.com/111/222.git' + hash, label + ' -> https')
t.is(hostinfo.git(), 'git://user:pass@github.com/111/222.git' + hash, label + ' -> git')
t.is(hostinfo.browse(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse('C'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.bugs(), 'https://github.com/111/222/issues', label + ' -> bugs')
t.is(hostinfo.docs(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : '') + '#readme', label + ' -> docs')
t.is(hostinfo.ssh(), 'git@github.com:111/222.git' + hash, label + ' -> ssh')
Expand Down

0 comments on commit cd5e5bb

Please sign in to comment.