Skip to content

Commit 19ce0e7

Browse files
Added support for local file paths that contain characters which should be URL-encoded
1 parent 244d639 commit 19ce0e7

15 files changed

Lines changed: 264 additions & 52 deletions

dist/ref-parser.js

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ $RefParser.prototype.parse = function(schema, options, callback) {
293293
var me = this;
294294

295295
// Resolve the absolute path of the schema
296+
args.schema = util.path.localPathToUrl(args.schema);
296297
args.schema = url.resolve(util.path.cwd(), args.schema);
297298
this._basePath = util.path.stripHash(args.schema);
298299

@@ -984,7 +985,7 @@ function read$RefFile($ref, options) {
984985
return new Promise(function(resolve, reject) {
985986
var file;
986987
try {
987-
file = decodeURI($ref.path);
988+
file = util.path.urlToLocalPath($ref.path);
988989
}
989990
catch (err) {
990991
reject(ono.uri(err, 'Malformed URI: %s', $ref.path));
@@ -1332,19 +1333,9 @@ function $Refs() {
13321333
* @returns {string[]}
13331334
*/
13341335
$Refs.prototype.paths = function(types) {
1335-
var $refs = this._$refs;
1336-
var keys = Object.keys($refs);
1337-
types = Array.isArray(types) ? types : Array.prototype.slice.call(arguments);
1338-
1339-
if (types.length > 0 && types[0]) {
1340-
keys = keys.filter(function(key) {
1341-
return types.indexOf($refs[key].pathType) !== -1;
1342-
});
1343-
}
1344-
1345-
return keys.map(function(key) {
1346-
// Decode URL-encoded characters for local file paths
1347-
return $refs[key].type === 'fs' ? decodeURI(key) : key;
1336+
var paths = getPaths(this._$refs, arguments);
1337+
return paths.map(function(path) {
1338+
return path.decoded;
13481339
});
13491340
};
13501341

@@ -1356,10 +1347,9 @@ $Refs.prototype.paths = function(types) {
13561347
*/
13571348
$Refs.prototype.values = function(types) {
13581349
var $refs = this._$refs;
1359-
var keys = this.paths(types);
1360-
1361-
return keys.reduce(function(obj, key) {
1362-
obj[key] = $refs[key].value;
1350+
var paths = getPaths($refs, arguments);
1351+
return paths.reduce(function(obj, path) {
1352+
obj[path.decoded] = $refs[path.encoded].value;
13631353
return obj;
13641354
}, {});
13651355
};
@@ -1475,6 +1465,33 @@ $Refs.prototype._get$Ref = function(path) {
14751465
return this._$refs[withoutHash];
14761466
};
14771467

1468+
/**
1469+
* Returns the encoded and decoded paths keys of the given object.
1470+
*
1471+
* @param {object} $refs - The object whose keys are URL-encoded paths
1472+
* @param {...string|string[]} [types] - Only return paths of the given types ("fs", "http", "https")
1473+
* @returns {object[]}
1474+
*/
1475+
function getPaths($refs, types) {
1476+
var paths = Object.keys($refs);
1477+
1478+
// Filter the paths by type
1479+
types = Array.isArray(types[0]) ? types[0] : Array.prototype.slice.call(types);
1480+
if (types.length > 0 && types[0]) {
1481+
paths = paths.filter(function(key) {
1482+
return types.indexOf($refs[key].pathType) !== -1;
1483+
});
1484+
}
1485+
1486+
// Decode local filesystem paths
1487+
return paths.map(function(path) {
1488+
return {
1489+
encoded: path,
1490+
decoded: $refs[path].pathType === 'fs' ? util.path.urlToLocalPath(path) : path
1491+
};
1492+
});
1493+
}
1494+
14781495
},{"./options":4,"./util":12,"ono":50}],11:[function(require,module,exports){
14791496
'use strict';
14801497

@@ -1649,6 +1666,22 @@ exports.doCallback = function doCallback(callback, err, params) {
16491666

16501667
var protocolPattern = /^[a-z0-9.+-]+:\/\//i;
16511668

1669+
// RegExp patterns to URL-encode special characters in local filesystem paths
1670+
var urlEncodePatterns = [
1671+
/\?/g, '%3F',
1672+
/\#/g, '%23',
1673+
/^win/.test(process.platform) ? /\\/g : /\//, '/'
1674+
];
1675+
1676+
// RegExp patterns to URL-decode special characters for local filesystem paths
1677+
var urlDecodePatterns = [
1678+
/\%23/g, '#',
1679+
/\%24/g, '$',
1680+
/\%26/g, '&',
1681+
/\%2C/g, ',',
1682+
/\%40/g, '@'
1683+
];
1684+
16521685
/**
16531686
* Returns the current working directory (in Node) or the current page URL (in browsers).
16541687
*
@@ -1668,6 +1701,38 @@ exports.isUrl = function isUrl(path) {
16681701
return protocolPattern.test(path);
16691702
};
16701703

1704+
/**
1705+
* If the given path is a local filesystem path, it is converted to a URL.
1706+
*
1707+
* @param {string} path
1708+
* @returns {string}
1709+
*/
1710+
exports.localPathToUrl = function localPathToUrl(path) {
1711+
if (!process.browser && !exports.isUrl(path)) {
1712+
// Manually encode characters that are not encoded by `encodeURI`
1713+
for (var i = 0; i < urlEncodePatterns.length; i += 2) {
1714+
path = path.replace(urlEncodePatterns[i], urlEncodePatterns[i + 1]);
1715+
}
1716+
path = encodeURI(path);
1717+
}
1718+
return path;
1719+
};
1720+
1721+
/**
1722+
* Converts a URL to a local filesystem path
1723+
*
1724+
* @param {string} url
1725+
* @returns {string}
1726+
*/
1727+
exports.urlToLocalPath = function urlToLocalPath(url) {
1728+
url = decodeURI(url);
1729+
// Manually decode characters that are not decoded by `decodeURI`
1730+
for (var i = 0; i < urlDecodePatterns.length; i += 2) {
1731+
url = url.replace(urlDecodePatterns[i], urlDecodePatterns[i + 1]);
1732+
}
1733+
return url;
1734+
};
1735+
16711736
/**
16721737
* Adds a hash to the given path, if it doesn't already have one.
16731738
*

dist/ref-parser.js.map

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

0 commit comments

Comments
 (0)