Skip to content

Commit cd5e5bb

Browse files
neocoticzkat
authored andcommitted
feat(browse): fragment support for browse() (#28)
* 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
1 parent 627ab55 commit cd5e5bb

8 files changed

+47
-10
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ would return `https://raw.githubusercontent.com/npm/hosted-git-info/v1.0.0/packa
7777

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

80-
* info.browse(opts)
80+
* info.browse(path, fragment, opts)
8181

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

8486
* info.bugs(opts)
8587

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

130132
Currently this supports Github, Bitbucket and Gitlab. Pull requests for
131133
additional hosts welcome.
132-

git-host-info.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,30 @@ var gitHosts = module.exports = {
3636
'sshtemplate': 'git@{domain}:/{project}.git{#committish}',
3737
'sshurltemplate': 'git+ssh://git@{domain}/{project}.git{#committish}',
3838
'browsetemplate': 'https://{domain}/{project}{/committish}',
39+
'browsefiletemplate': 'https://{domain}/{project}{/committish}{#path}',
3940
'docstemplate': 'https://{domain}/{project}{/committish}',
4041
'httpstemplate': 'git+https://{domain}/{project}.git{#committish}',
4142
'shortcuttemplate': '{type}:{project}{#committish}',
4243
'pathtemplate': '{project}{#committish}',
43-
'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz'
44+
'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz',
45+
'hashformat': function (fragment) {
46+
return 'file-' + formatHashFragment(fragment)
47+
}
4448
}
4549
}
4650

4751
var gitHostDefaults = {
4852
'sshtemplate': 'git@{domain}:{user}/{project}.git{#committish}',
4953
'sshurltemplate': 'git+ssh://git@{domain}/{user}/{project}.git{#committish}',
5054
'browsetemplate': 'https://{domain}/{user}/{project}{/tree/committish}',
55+
'browsefiletemplate': 'https://{domain}/{user}/{project}/{treepath}/{committish}/{path}{#fragment}',
5156
'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#readme',
5257
'httpstemplate': 'git+https://{auth@}{domain}/{user}/{project}.git{#committish}',
5358
'filetemplate': 'https://{domain}/{user}/{project}/raw/{committish}/{path}',
5459
'shortcuttemplate': '{type}:{user}/{project}{#committish}',
5560
'pathtemplate': '{user}/{project}{#committish}',
56-
'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/
61+
'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/,
62+
'hashformat': formatHashFragment
5763
}
5864

5965
Object.keys(gitHosts).forEach(function (name) {
@@ -66,3 +72,7 @@ Object.keys(gitHosts).forEach(function (name) {
6672
return protocol.replace(/([\\+*{}()[\]$^|])/g, '\\$1')
6773
}).join('|') + '):$')
6874
})
75+
76+
function formatHashFragment (fragment) {
77+
return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-')
78+
}

git-host.js

+21-5
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,24 @@ GitHost.prototype.hash = function () {
2323
GitHost.prototype._fill = function (template, opts) {
2424
if (!template) return
2525
var vars = Object.assign({}, opts)
26+
vars.path = vars.path ? vars.path.replace(/^[/]+/g, '') : ''
2627
opts = Object.assign({}, this.opts, opts)
2728
var self = this
2829
Object.keys(this).forEach(function (key) {
2930
if (self[key] != null && vars[key] == null) vars[key] = self[key]
3031
})
3132
var rawAuth = vars.auth
3233
var rawComittish = vars.committish
34+
var rawFragment = vars.fragment
35+
var rawPath = vars.path
3336
Object.keys(vars).forEach(function (key) {
3437
vars[key] = encodeURIComponent(vars[key])
3538
})
3639
vars['auth@'] = rawAuth ? rawAuth + '@' : ''
40+
vars['#fragment'] = rawFragment ? '#' + this.hashformat(rawFragment) : ''
41+
vars.fragment = vars.fragment ? vars.fragment : ''
42+
vars['#path'] = rawPath ? '#' + this.hashformat(rawPath) : ''
43+
vars['/path'] = vars.path ? '/' + vars.path : ''
3744
if (opts.noCommittish) {
3845
vars['#committish'] = ''
3946
vars['/tree/committish'] = ''
@@ -66,8 +73,19 @@ GitHost.prototype.sshurl = function (opts) {
6673
return this._fill(this.sshurltemplate, opts)
6774
}
6875

69-
GitHost.prototype.browse = function (opts) {
70-
return this._fill(this.browsetemplate, opts)
76+
GitHost.prototype.browse = function (P, F, opts) {
77+
if (typeof P === 'string') {
78+
if (typeof F !== 'string') {
79+
opts = F
80+
F = null
81+
}
82+
return this._fill(this.browsefiletemplate, extend({
83+
fragment: F,
84+
path: P
85+
}, opts))
86+
} else {
87+
return this._fill(this.browsetemplate, P)
88+
}
7189
}
7290

7391
GitHost.prototype.docs = function (opts) {
@@ -99,9 +117,7 @@ GitHost.prototype.tarball = function (opts) {
99117
}
100118

101119
GitHost.prototype.file = function (P, opts) {
102-
return this._fill(this.filetemplate, Object.assign({
103-
path: P.replace(/^[/]+/g, '')
104-
}, opts))
120+
return this._fill(this.filetemplate, Object.assign({ path: P }, opts))
105121
}
106122

107123
GitHost.prototype.getDefaultRepresentation = function () {

test/bitbucket.js

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ test('fromUrl(bitbucket url)', function (t) {
1010
if (!hostinfo) return
1111
t.is(hostinfo.https(), 'git+https://bitbucket.org/111/222.git' + hash, label + ' -> https')
1212
t.is(hostinfo.browse(), 'https://bitbucket.org/111/222' + (branch ? '/src/' + branch : ''), label + ' -> browse')
13+
t.is(hostinfo.browse('C'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C', label + ' -> browse(path)')
14+
t.is(hostinfo.browse('C', 'A'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
1315
t.is(hostinfo.docs(), 'https://bitbucket.org/111/222' + (branch ? '/src/' + branch : '') + '#readme', label + ' -> docs')
1416
t.is(hostinfo.ssh(), '[email protected]:111/222.git' + hash, label + ' -> ssh')
1517
t.is(hostinfo.sshurl(), 'git+ssh://[email protected]/111/222.git' + hash, label + ' -> sshurl')

test/gist.js

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ test('fromUrl(gist url)', function (t) {
1111
t.is(hostinfo.https(), 'git+https://gist.github.com/222.git' + hash, label + ' -> https')
1212
t.is(hostinfo.git(), 'git://gist.github.com/222.git' + hash, label + ' -> git')
1313
t.is(hostinfo.browse(), 'https://gist.github.com/222' + (branch ? '/' + branch : ''), label + ' -> browse')
14+
t.is(hostinfo.browse('C'), 'https://gist.github.com/222' + (branch ? '/' + branch : '') + '#file-c', label + ' -> browse(path)')
15+
t.is(hostinfo.browse('C', 'A'), 'https://gist.github.com/222' + (branch ? '/' + branch : '') + '#file-c', label + ' -> browse(path, fragment)')
1416
t.is(hostinfo.bugs(), 'https://gist.github.com/222', label + ' -> bugs')
1517
t.is(hostinfo.docs(), 'https://gist.github.com/222' + (branch ? '/' + branch : ''), label + ' -> docs')
1618
t.is(hostinfo.ssh(), '[email protected]:/222.git' + hash, label + ' -> ssh')

test/github.js

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ test('fromUrl(github url)', function (t) {
1111
t.is(hostinfo.https(), 'git+https://github.com/111/222.git' + hash, label + ' -> https')
1212
t.is(hostinfo.git(), 'git://github.com/111/222.git' + hash, label + ' -> git')
1313
t.is(hostinfo.browse(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : ''), label + ' -> browse')
14+
t.is(hostinfo.browse('C'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C', label + ' -> browse(path)')
15+
t.is(hostinfo.browse('C', 'A'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
1416
t.is(hostinfo.bugs(), 'https://github.com/111/222/issues', label + ' -> bugs')
1517
t.is(hostinfo.docs(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : '') + '#readme', label + ' -> docs')
1618
t.is(hostinfo.ssh(), '[email protected]:111/222.git' + hash, label + ' -> ssh')

test/gitlab.js

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ test('fromUrl(gitlab url)', function (t) {
1010
if (!hostinfo) return
1111
t.is(hostinfo.https(), 'git+https://gitlab.com/111/222.git' + hash, label + ' -> https')
1212
t.is(hostinfo.browse(), 'https://gitlab.com/111/222' + (branch ? '/tree/' + branch : ''), label + ' -> browse')
13+
t.is(hostinfo.browse('C'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C', label + ' -> browse(path)')
14+
t.is(hostinfo.browse('C', 'A'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
1315
t.is(hostinfo.docs(), 'https://gitlab.com/111/222' + (branch ? '/tree/' + branch : '') + '#README', label + ' -> docs')
1416
t.is(hostinfo.ssh(), '[email protected]:111/222.git' + hash, label + ' -> ssh')
1517
t.is(hostinfo.sshurl(), 'git+ssh://[email protected]/111/222.git' + hash, label + ' -> sshurl')

test/https-with-inline-auth.js

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ test('HTTPS GitHub URL with embedded auth -- generally not a good idea', functio
1111
t.is(hostinfo.https(), 'git+https://user:[email protected]/111/222.git' + hash, label + ' -> https')
1212
t.is(hostinfo.git(), 'git://user:[email protected]/111/222.git' + hash, label + ' -> git')
1313
t.is(hostinfo.browse(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : ''), label + ' -> browse')
14+
t.is(hostinfo.browse('C'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C', label + ' -> browse(path)')
15+
t.is(hostinfo.browse('C', 'A'), 'https://github.com/111/222/tree/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
1416
t.is(hostinfo.bugs(), 'https://github.com/111/222/issues', label + ' -> bugs')
1517
t.is(hostinfo.docs(), 'https://github.com/111/222' + (branch ? '/tree/' + branch : '') + '#readme', label + ' -> docs')
1618
t.is(hostinfo.ssh(), '[email protected]:111/222.git' + hash, label + ' -> ssh')

0 commit comments

Comments
 (0)