Skip to content

Commit 04db85c

Browse files
committed
[fix] Ignore the slashes after the protocol for special URLs
Fixes #205 Fixes #206
1 parent ee22050 commit 04db85c

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

Diff for: index.js

+44-7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,24 @@ function lolcation(loc) {
9898
return finaldestination;
9999
}
100100

101+
/**
102+
* Check whether a protocol scheme is special.
103+
*
104+
* @param {String} The protocol scheme of the URL
105+
* @return {Boolean} `true` if the protocol scheme is special, else `false`
106+
* @private
107+
*/
108+
function isSpecial(scheme) {
109+
return (
110+
scheme === 'ftp:' ||
111+
scheme === 'file:' ||
112+
scheme === 'http:' ||
113+
scheme === 'https:' ||
114+
scheme === 'ws:' ||
115+
scheme === 'wss:'
116+
);
117+
}
118+
101119
/**
102120
* @typedef ProtocolExtract
103121
* @type Object
@@ -110,16 +128,32 @@ function lolcation(loc) {
110128
* Extract protocol information from a URL with/without double slash ("//").
111129
*
112130
* @param {String} address URL we want to extract from.
131+
* @param {Object} location
113132
* @return {ProtocolExtract} Extracted information.
114133
* @private
115134
*/
116-
function extractProtocol(address) {
135+
function extractProtocol(address, location) {
117136
address = trimLeft(address);
137+
location = location || {};
118138

119-
var match = protocolre.exec(address)
120-
, protocol = match[1] ? match[1].toLowerCase() : ''
121-
, slashes = !!(match[2] && match[2].length >= 2)
122-
, rest = match[2] && match[2].length === 1 ? '/' + match[3] : match[3];
139+
var match = protocolre.exec(address);
140+
var protocol = match[1] ? match[1].toLowerCase() : '';
141+
var rest = match[2] ? match[2] + match[3] : match[3];
142+
var slashes = !!(match[2] && match[2].length >= 2);
143+
144+
if (protocol === 'file:') {
145+
if (slashes) {
146+
rest = rest.slice(2);
147+
}
148+
} else if (isSpecial(protocol)) {
149+
rest = match[3];
150+
} else if (protocol) {
151+
if (rest.indexOf('//') === 0) {
152+
rest = rest.slice(2);
153+
}
154+
} else if (slashes && location.hostname) {
155+
rest = match[3];
156+
}
123157

124158
return {
125159
protocol: protocol,
@@ -214,7 +248,7 @@ function Url(address, location, parser) {
214248
//
215249
// Extract protocol information before running the instructions.
216250
//
217-
extracted = extractProtocol(address || '');
251+
extracted = extractProtocol(address || '', location);
218252
relative = !extracted.protocol && !extracted.slashes;
219253
url.slashes = extracted.slashes || relative && location.slashes;
220254
url.protocol = extracted.protocol || location.protocol || '';
@@ -224,7 +258,10 @@ function Url(address, location, parser) {
224258
// When the authority component is absent the URL starts with a path
225259
// component.
226260
//
227-
if (!extracted.slashes || url.protocol === 'file:') {
261+
if (
262+
url.protocol === 'file:' ||
263+
(!extracted.slashes && !isSpecial(extracted.protocol))
264+
) {
228265
instructions[3] = [/(.*)/, 'pathname'];
229266
}
230267

Diff for: test/test.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe('url-parse', function () {
9393
assume(parse.extractProtocol('//foo/bar')).eql({
9494
slashes: true,
9595
protocol: '',
96-
rest: 'foo/bar'
96+
rest: '//foo/bar'
9797
});
9898
});
9999

@@ -440,7 +440,7 @@ describe('url-parse', function () {
440440
});
441441

442442
it('handles the file: protocol', function () {
443-
var slashes = ['', '/', '//', '///', '////', '/////'];
443+
var slashes = ['', '/', '//', '///'];
444444
var data;
445445
var url;
446446

@@ -451,6 +451,18 @@ describe('url-parse', function () {
451451
assume(data.href).equals('file:///');
452452
}
453453

454+
url = 'file:////';
455+
data = parse(url);
456+
assume(data.protocol).equals('file:');
457+
assume(data.pathname).equals('//');
458+
assume(data.href).equals(url);
459+
460+
url = 'file://///';
461+
data = parse(url);
462+
assume(data.protocol).equals('file:');
463+
assume(data.pathname).equals('///');
464+
assume(data.href).equals(url);
465+
454466
url = 'file:///Users/foo/BAR/baz.pdf';
455467
data = parse(url);
456468
assume(data.protocol).equals('file:');

0 commit comments

Comments
 (0)