Skip to content

Commit f2a9501

Browse files
Fixed bugs in "file://" url handling on Windows and on old versions of Node
1 parent 6e37b53 commit f2a9501

File tree

9 files changed

+75
-19
lines changed

9 files changed

+75
-19
lines changed

dist/ref-parser.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,20 +1870,45 @@ exports.path.localPathToUrl = function localPathToUrl(path) {
18701870
* @returns {string}
18711871
*/
18721872
exports.path.urlToLocalPath = function urlToLocalPath(url, keepFileProtocol) {
1873+
// Decode URL-encoded characters
18731874
url = decodeURI(url);
1875+
18741876
// Manually decode characters that are not decoded by `decodeURI`
18751877
for (var i = 0; i < urlDecodePatterns.length; i += 2) {
18761878
url = url.replace(urlDecodePatterns[i], urlDecodePatterns[i + 1]);
18771879
}
1878-
if (!keepFileProtocol && url.substr(0, 7).toLowerCase() === 'file://') {
1879-
url = url.substr(7);
1880+
1881+
// Handle "file://" URLs
1882+
var isFileUrl = url.substr(0, 7).toLowerCase() === 'file://';
1883+
if (isFileUrl) {
1884+
var protocol = 'file:///';
1885+
1886+
// Remove the third "/" if there is one
1887+
var path = url[7] === '/' ? url.substr(8) : url.substr(7);
1888+
1889+
if (isWindows && path[1] === '/') {
1890+
// insert a colon (":") after the drive letter on Windows
1891+
path = path[0] + ':' + path.substr(1);
1892+
}
1893+
1894+
if (keepFileProtocol) {
1895+
url = protocol + path;
1896+
}
1897+
else {
1898+
isFileUrl = false;
1899+
url = isWindows ? path : '/' + path;
1900+
}
18801901
}
1881-
if (isWindows) {
1902+
1903+
// Format path separators on Windows
1904+
if (isWindows && !isFileUrl) {
18821905
url = url.replace(forwardSlashPattern, '\\');
18831906
}
1907+
18841908
return url;
18851909
};
18861910

1911+
18871912
/**
18881913
* Returns the hash (URL fragment), if any, of the given path.
18891914
*

dist/ref-parser.js.map

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ref-parser.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ref-parser.min.js.map

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/util.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,45 @@ exports.path.localPathToUrl = function localPathToUrl(path) {
8282
* @returns {string}
8383
*/
8484
exports.path.urlToLocalPath = function urlToLocalPath(url, keepFileProtocol) {
85+
// Decode URL-encoded characters
8586
url = decodeURI(url);
87+
8688
// Manually decode characters that are not decoded by `decodeURI`
8789
for (var i = 0; i < urlDecodePatterns.length; i += 2) {
8890
url = url.replace(urlDecodePatterns[i], urlDecodePatterns[i + 1]);
8991
}
90-
if (!keepFileProtocol && url.substr(0, 7).toLowerCase() === 'file://') {
91-
url = url.substr(7);
92+
93+
// Handle "file://" URLs
94+
var isFileUrl = url.substr(0, 7).toLowerCase() === 'file://';
95+
if (isFileUrl) {
96+
var protocol = 'file:///';
97+
98+
// Remove the third "/" if there is one
99+
var path = url[7] === '/' ? url.substr(8) : url.substr(7);
100+
101+
if (isWindows && path[1] === '/') {
102+
// insert a colon (":") after the drive letter on Windows
103+
path = path[0] + ':' + path.substr(1);
104+
}
105+
106+
if (keepFileProtocol) {
107+
url = protocol + path;
108+
}
109+
else {
110+
isFileUrl = false;
111+
url = isWindows ? path : '/' + path;
112+
}
92113
}
93-
if (isWindows) {
114+
115+
// Format path separators on Windows
116+
if (isWindows && !isFileUrl) {
94117
url = url.replace(forwardSlashPattern, '\\');
95118
}
119+
96120
return url;
97121
};
98122

123+
99124
/**
100125
* Returns the hash (URL fragment), if any, of the given path.
101126
*

tests/fixtures/globals.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
global.userAgent = {
3030
isNode: true,
31+
isOldNode: /^v0\./.test(process.version),
3132
isBrowser: false,
3233
isTravisCI: !!process.env.TRAVIS
3334
};

tests/fixtures/helper.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
helper.testResolve = function testResolve(filePath, params) {
5050
var parsedSchema = arguments[2];
5151
var expectedFiles = [], expectedValues = [], actualFiles;
52+
5253
for (var i = 1; i < arguments.length; i += 2) {
5354
expectedFiles.push(arguments[i]);
5455
expectedValues.push(arguments[i + 1]);

tests/fixtures/path.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
path.rel = function(file) {
2020
if (userAgent.isNode) {
2121
// Return the relative path from the project root
22-
return file;
22+
return _path.normalize(file);
2323
}
2424

2525
// Encode special characters in paths when running in a browser
@@ -71,6 +71,7 @@
7171
slashes: true,
7272
pathname: pathname
7373
});
74+
7475
return url;
7576
};
7677

tests/specs/external/external.spec.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,16 @@ describe('Schema with external $refs', function() {
5050
path.abs('specs/external/definitions/required-string.yaml'), helper.parsed.external.requiredString
5151
));
5252

53-
it('should resolve successfully from a url', helper.testResolve(
54-
path.url('specs/external/external.yaml'),
55-
path.url('specs/external/external.yaml'), helper.parsed.external.schema,
56-
path.url('specs/external/definitions/definitions.json'), helper.parsed.external.definitions,
57-
path.url('specs/external/definitions/name.yaml'), helper.parsed.external.name,
58-
path.url('specs/external/definitions/required-string.yaml'), helper.parsed.external.requiredString
59-
));
53+
// Skip this test on Node v0.x, due to bugs in `url.resolve()`
54+
if (!userAgent.isOldNode) {
55+
it('should resolve successfully from a url', helper.testResolve(
56+
path.url('specs/external/external.yaml'),
57+
path.url('specs/external/external.yaml'), helper.parsed.external.schema,
58+
path.url('specs/external/definitions/definitions.json'), helper.parsed.external.definitions,
59+
path.url('specs/external/definitions/name.yaml'), helper.parsed.external.name,
60+
path.url('specs/external/definitions/required-string.yaml'), helper.parsed.external.requiredString
61+
));
62+
}
6063

6164
it('should dereference successfully', function() {
6265
var parser = new $RefParser();

0 commit comments

Comments
 (0)