Skip to content

Commit 3ebbdc1

Browse files
committed
resolve uri-ref relative to document
1 parent 0cf0434 commit 3ebbdc1

2 files changed

Lines changed: 43 additions & 16 deletions

File tree

src/services/jsonLinks.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { JSONDocument } from '../parser/jsonParser';
99
import { IJSONSchemaService } from './jsonSchemaService';
1010
import { URI } from 'vscode-uri';
1111
import { existsSync as fileExistsSync } from 'fs';
12-
import { resolve as resolvePath } from 'path';
12+
import * as path from 'path';
1313

1414
export class JSONLinks {
1515
private schemaService: IJSONSchemaService;
@@ -48,13 +48,14 @@ export function findLinks(document: TextDocument, doc: JSONDocument, schemaServi
4848
matchingSchemas.forEach((s) => {
4949
if (s.node === pathNode && !s.inverted && s.schema) {
5050
if (s.schema.format === 'uri-reference') {
51-
const path = resolvePath(pathNode.value);
52-
const uri = URI.file(path);
53-
if (fileExistsSync(path)) {
54-
pathLinks.push({
55-
target: uri.toString(),
56-
range: createRange(document, pathNode)
57-
});
51+
const pathURI = resolveURIRef(pathNode.value, document);
52+
if (pathURI) {
53+
if (fileExistsSync(pathURI.fsPath)) {
54+
pathLinks.push({
55+
target: pathURI.toString(),
56+
range: createRange(document, pathNode)
57+
});
58+
}
5859
}
5960
}
6061
}
@@ -128,3 +129,25 @@ function parseJSONPointer(path: string): string[] | null {
128129
function unescape(str: string): string {
129130
return str.replace(/~1/g, '/').replace(/~0/g, '~');
130131
}
132+
133+
function resolveURIRef(ref: string, document: TextDocument): URI | null {
134+
if (ref.indexOf('://') > 0) {
135+
// Already a fully qualified URI.
136+
// The language service should already create a document link
137+
// for these, so no need to created a duplicate.
138+
return null;
139+
}
140+
141+
if (ref.startsWith('/')) {
142+
// Already an absolute path, no need to resolve.
143+
return URI.file(ref);
144+
}
145+
146+
// Resolve ref relative to the document.
147+
const docURI = URI.parse(document.uri);
148+
const docDir = path.dirname(docURI.path);
149+
const refPath = path.join(docDir, ref);
150+
return docURI.with({
151+
path: refPath
152+
});
153+
}

src/test/links.test.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
Range,
1414
TextDocument,
1515
} from '../jsonLanguageService';
16-
import { resolve as resolvePath } from 'path';
16+
import * as path from 'path';
17+
import { URI } from 'vscode-uri';
1718

1819
suite('JSON Find Links', () => {
1920
const testFindLinksFor = function (value: string, expected: {offset: number, length: number, target: number} | null): PromiseLike<void> {
@@ -72,9 +73,13 @@ suite('JSON Find Links', () => {
7273
});
7374

7475
test('URI reference link', async function () {
75-
const relativePath = './src/test/fixtures/uri-reference.txt';
76-
const content = `{"stringProp": "string-value", "uriProp": "${relativePath}", "uriPropNotFound": "./does/not/exist.txt"}`;
77-
const document = TextDocument.create('test://test.json', 'json', 0, content);
76+
// This test file runs in `./lib/umd/test`, but the fixtures are in `./src`.
77+
const refRelPath = '../../../src/test/fixtures/uri-reference.txt';
78+
const refAbsPath = path.join(__dirname, refRelPath);
79+
const docAbsPath = path.join(__dirname, 'test.json');
80+
81+
const content = `{"stringProp": "string-value", "uriProp": "${refRelPath}", "uriPropNotFound": "./does/not/exist.txt"}`;
82+
const document = TextDocument.create(URI.file(docAbsPath).toString(), 'json', 0, content);
7883
const schema: JSONSchema = {
7984
type: 'object',
8085
properties: {
@@ -94,11 +99,10 @@ suite('JSON Find Links', () => {
9499
await testFindLinksWithSchema(document, schema).then((links) => {
95100
assert.notDeepEqual(links, []);
96101

97-
const absPath = resolvePath(relativePath);
98-
assert.equal(links[0].target, `file://${absPath}`);
102+
assert.equal(links[0].target, URI.file(refAbsPath).toString());
99103

100-
const startOffset = content.indexOf(relativePath);
101-
const endOffset = startOffset + relativePath.length;
104+
const startOffset = content.indexOf(refRelPath);
105+
const endOffset = startOffset + refRelPath.length;
102106
const range = Range.create(document.positionAt(startOffset), document.positionAt(endOffset));
103107
assert.deepEqual(links[0].range, range);
104108
});

0 commit comments

Comments
 (0)