Skip to content

Commit

Permalink
[fix] Ignore the slashes after the protocol for special URLs
Browse files Browse the repository at this point in the history
Fixes #205
Fixes #206
  • Loading branch information
lpinca committed Jul 23, 2021
1 parent ee22050 commit 04db85c
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 9 deletions.
51 changes: 44 additions & 7 deletions index.js
Expand Up @@ -98,6 +98,24 @@ function lolcation(loc) {
return finaldestination;
}

/**
* Check whether a protocol scheme is special.
*
* @param {String} The protocol scheme of the URL
* @return {Boolean} `true` if the protocol scheme is special, else `false`
* @private
*/
function isSpecial(scheme) {
return (
scheme === 'ftp:' ||
scheme === 'file:' ||
scheme === 'http:' ||
scheme === 'https:' ||
scheme === 'ws:' ||
scheme === 'wss:'
);
}

/**
* @typedef ProtocolExtract
* @type Object
Expand All @@ -110,16 +128,32 @@ function lolcation(loc) {
* Extract protocol information from a URL with/without double slash ("//").
*
* @param {String} address URL we want to extract from.
* @param {Object} location
* @return {ProtocolExtract} Extracted information.
* @private
*/
function extractProtocol(address) {
function extractProtocol(address, location) {
address = trimLeft(address);
location = location || {};

var match = protocolre.exec(address)
, protocol = match[1] ? match[1].toLowerCase() : ''
, slashes = !!(match[2] && match[2].length >= 2)
, rest = match[2] && match[2].length === 1 ? '/' + match[3] : match[3];
var match = protocolre.exec(address);
var protocol = match[1] ? match[1].toLowerCase() : '';
var rest = match[2] ? match[2] + match[3] : match[3];
var slashes = !!(match[2] && match[2].length >= 2);

if (protocol === 'file:') {
if (slashes) {
rest = rest.slice(2);
}
} else if (isSpecial(protocol)) {
rest = match[3];
} else if (protocol) {
if (rest.indexOf('//') === 0) {
rest = rest.slice(2);
}
} else if (slashes && location.hostname) {
rest = match[3];
}

return {
protocol: protocol,
Expand Down Expand Up @@ -214,7 +248,7 @@ function Url(address, location, parser) {
//
// Extract protocol information before running the instructions.
//
extracted = extractProtocol(address || '');
extracted = extractProtocol(address || '', location);
relative = !extracted.protocol && !extracted.slashes;
url.slashes = extracted.slashes || relative && location.slashes;
url.protocol = extracted.protocol || location.protocol || '';
Expand All @@ -224,7 +258,10 @@ function Url(address, location, parser) {
// When the authority component is absent the URL starts with a path
// component.
//
if (!extracted.slashes || url.protocol === 'file:') {
if (
url.protocol === 'file:' ||
(!extracted.slashes && !isSpecial(extracted.protocol))
) {
instructions[3] = [/(.*)/, 'pathname'];
}

Expand Down
16 changes: 14 additions & 2 deletions test/test.js
Expand Up @@ -93,7 +93,7 @@ describe('url-parse', function () {
assume(parse.extractProtocol('//foo/bar')).eql({
slashes: true,
protocol: '',
rest: 'foo/bar'
rest: '//foo/bar'
});
});

Expand Down Expand Up @@ -440,7 +440,7 @@ describe('url-parse', function () {
});

it('handles the file: protocol', function () {
var slashes = ['', '/', '//', '///', '////', '/////'];
var slashes = ['', '/', '//', '///'];
var data;
var url;

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

url = 'file:////';
data = parse(url);
assume(data.protocol).equals('file:');
assume(data.pathname).equals('//');
assume(data.href).equals(url);

url = 'file://///';
data = parse(url);
assume(data.protocol).equals('file:');
assume(data.pathname).equals('///');
assume(data.href).equals(url);

url = 'file:///Users/foo/BAR/baz.pdf';
data = parse(url);
assume(data.protocol).equals('file:');
Expand Down

0 comments on commit 04db85c

Please sign in to comment.