Skip to content

Commit baa7853

Browse files
Changes from PR-220, ISSUE-200.
1 parent ef90fb1 commit baa7853

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

lib/bundle.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ function crawl (parent, key, path, pathFromRoot, indirections, inventory, $refs,
9595
*/
9696
function inventory$Ref ($refParent, $refKey, path, pathFromRoot, indirections, inventory, $refs, options) {
9797
let $ref = $refKey === null ? $refParent : $refParent[$refKey];
98-
let $refPath = url.resolve(path, $ref.$ref);
98+
let $refPath = url.resolve(pathFromRoot, $ref.$ref);
9999
let pointer = $refs._resolve($refPath, pathFromRoot, options);
100100
if (pointer === null) {
101101
return;

lib/resolve-external.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,34 +44,34 @@ function resolveExternal (parser, options) {
4444
* @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash
4545
* @param {$Refs} $refs
4646
* @param {$RefParserOptions} options
47-
* @param {Set} seen - Internal.
47+
* @param {boolean} external - Whether `obj` was found in an external document.
4848
*
4949
* @returns {Promise[]}
5050
* Returns an array of promises. There will be one promise for each JSON reference in `obj`.
5151
* If `obj` does not contain any JSON references, then the array will be empty.
5252
* If any of the JSON references point to files that contain additional JSON references,
5353
* then the corresponding promise will internally reference an array of promises.
5454
*/
55-
function crawl (obj, path, $refs, options, seen) {
55+
function crawl (obj, path, $refs, options, seen, external) {
5656
seen = seen || new Set();
5757
let promises = [];
5858

59-
if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj) && !seen.has(obj)) {
60-
seen.add(obj); // Track previously seen objects to avoid infinite recursion
59+
if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj)) {
6160
if ($Ref.isExternal$Ref(obj)) {
6261
promises.push(resolve$Ref(obj, path, $refs, options));
6362
}
6463
else {
64+
if (external && $Ref.is$Ref(obj)) {
65+
/* Correct the reference in the external document so we can resolve it */
66+
const withoutHash = url.stripHash(path);
67+
obj.$ref = withoutHash + obj.$ref;
68+
}
69+
6570
for (let key of Object.keys(obj)) {
6671
let keyPath = Pointer.join(path, key);
6772
let value = obj[key];
6873

69-
if ($Ref.isExternal$Ref(value)) {
70-
promises.push(resolve$Ref(value, keyPath, $refs, options));
71-
}
72-
else {
73-
promises = promises.concat(crawl(value, keyPath, $refs, options, seen));
74-
}
74+
promises = promises.concat(crawl(value, keyPath, $refs, options, seen, external));
7575
}
7676
}
7777
}
@@ -97,6 +97,12 @@ async function resolve$Ref ($ref, path, $refs, options) {
9797
let resolvedPath = url.resolve(path, $ref.$ref);
9898
let withoutHash = url.stripHash(resolvedPath);
9999

100+
/* Correct the $ref to use a path relative to the root, so that $Refs._resolve can resolve it,
101+
otherwise transitive relative external references will be incorrect if the second external
102+
relative ref doesn't work relative to the root document.
103+
*/
104+
$ref.$ref = url.relative($refs._root$Ref.path, resolvedPath);
105+
100106
// Do we already have this $ref?
101107
$ref = $refs._$refs[withoutHash];
102108
if ($ref) {
@@ -110,7 +116,7 @@ async function resolve$Ref ($ref, path, $refs, options) {
110116

111117
// Crawl the parsed value
112118
// console.log('Resolving $ref pointers in %s', withoutHash);
113-
let promises = crawl(result, withoutHash + "#", $refs, options);
119+
let promises = crawl(result, withoutHash + "#", $refs, options, null, true);
114120

115121
return Promise.all(promises);
116122
}

lib/util/url.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use strict";
22

33
const nodePath = require("path");
4-
const projectDir = nodePath.resolve(__dirname, "..", "..");
54

65
let isWindows = /^win/.test(globalThis.process?.platform),
76
forwardSlashPattern = /\//g,
@@ -193,14 +192,7 @@ exports.fromFileSystemPath = function fromFileSystemPath (path) {
193192
// Step 1: On Windows, replace backslashes with forward slashes,
194193
// rather than encoding them as "%5C"
195194
if (isWindows) {
196-
const hasProjectDir = path.toUpperCase().includes(projectDir.replace(/\\/g, "\\").toUpperCase());
197-
const hasProjectUri = path.toUpperCase().includes(projectDir.replace(/\\/g, "/").toUpperCase());
198-
if (hasProjectDir || hasProjectUri) {
199-
path = path.replace(/\\/g, "/");
200-
}
201-
else {
202-
path = `${projectDir}/${path}`.replace(/\\/g, "/");
203-
}
195+
path = path.replace(/\\/g, "/");
204196
}
205197

206198
// Step 2: `encodeURI` will take care of MOST characters
@@ -293,3 +285,22 @@ exports.safePointerToPath = function safePointerToPath (pointer) {
293285
.replace(jsonPointerTilde, "~");
294286
});
295287
};
288+
289+
/**
290+
* Like path.relative(from, to) but for URLs. It will return a relative
291+
* URL if it can, otherwise an absolute URL is returned.
292+
* @param {string} from
293+
* @param {string} to
294+
* @returns {string}
295+
*/
296+
exports.relative = function relative (from, to) {
297+
if (!exports.isFileSystemPath(from) || !exports.isFileSystemPath(to)) {
298+
return exports.resolve(from, to);
299+
}
300+
301+
const fromDir = nodePath.dirname(exports.stripHash(from));
302+
const toPath = exports.stripHash(to);
303+
304+
const result = nodePath.relative(fromDir, toPath);
305+
return result + exports.getHash(to);
306+
};

0 commit comments

Comments
 (0)