Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@
"yalc.watch": "nodemon --watch 'src/**/*' --exec 'yarn yalc'"
},
"peerDependencies": {},
"dependencies": {},
"dependencies": {
"urijs": "^1.19.1",
"path-browserify": "^1.0.0",
"vscode-uri": "^2.0.2"
},
"devDependencies": {
"@stoplight/scripts": "7.0.0",
"@types/jest": "24.x.x",
"@types/urijs": "^1.19.1",
"jest": "24.x.x",
"nodemon": "1.x.x",
"prettier": "1.x.x",
Expand Down
24 changes: 24 additions & 0 deletions src/__tests__/isAbsolute.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { isAbsolute } from '../';

describe('isAbsolute', () => {
it.each([
'\\foo\\bar.json',
'c:\\foo\\bar.json',
'c:\\',
'c:/',
'c:/foo/bar.json',
'/home/test',
'/',
'/var/lib/test/',
'/var/bin.d',
'https://foo.com/bar',
'http://localhost',
'http://boo.com',
])('treats %s path as absolute', filepath => {
expect(isAbsolute(filepath)).toBe(true);
});

it.each(['foo/bar', 'test', '', 'www.foo.com', './foo/bar'])('treats %s path as non-absolute', filepath => {
expect(isAbsolute(filepath)).toBe(false);
});
});
17 changes: 17 additions & 0 deletions src/__tests__/join.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { join } from '../';

describe('join', () => {
it('does some basic resolving', () => {
expect(join('/foo/bar', '..', 'baz')).toEqual('/foo/baz');
expect(join('c:/foo/bar', '..', 'baz')).toEqual('c:/foo/baz');
});

it('handles mixed slashes', () => {
expect(join('/test\\baz', 'foo/d')).toEqual('/test/baz/foo/d');
});

it('handles URLs', () => {
expect(join('https://foo.test', 'com', 'baz')).toEqual('https://foo.test/com/baz');
expect(join('https://foo.com/pets', '..', 'users', '123')).toEqual('https://foo.com/users/123');
});
});
23 changes: 23 additions & 0 deletions src/__tests__/normalize.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { normalize } from '../';

describe('normalize', () => {
it('replaces Windows-like slashes with POSIX-compatible ones', () => {
expect(normalize('c:\\foo\\bar')).toEqual('c:/foo/bar');
});

it('ignores POSIX slashes', () => {
expect(normalize('/d/foo')).toEqual('/d/foo');
});

it('does some basic resolving', () => {
expect(normalize('/foo/bar/boom/../../baz/.././a')).toEqual('/foo/a');
expect(normalize('/foo/bar/boom/../a')).toEqual('/foo/bar/a');
expect(normalize('/foo/bar/boom/..')).toEqual('/foo/bar');
});

it('handles URLs', () => {
expect(normalize('https://foo.com/baz/bar')).toEqual('https://foo.com/baz/bar');
expect(normalize('htTps://foo.com/baz/bar')).toEqual('https://foo.com/baz/bar');
expect(normalize('htTps://foo.com/baz/bar/../foo')).toEqual('https://foo.com/baz/foo');
});
});
28 changes: 28 additions & 0 deletions src/__tests__/relative.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { relative } from '../';

describe('relative', () => {
it('handles POSIX URIs', () => {
expect(relative('/test/bar/a', '/test/foo/c')).toEqual('../../foo/c');
expect(relative('~/test/bar', '~/test/foo')).toEqual('../foo');
});

it('handles Windows URIs', () => {
expect(relative('c:\\test\\baz', 'C:\\test\\foo')).toEqual('../../../C:/test/foo');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marbemac weird things happening here.

});

it('handles mixed slashes', () => {
expect(relative('/test\\baz', '/test\\foo')).toEqual('../foo');
});

it('handles URLs', () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also add some tests to make sure it handles the various file path cases (posix, windows, forward slash, mixed slash, etc).

expect(relative('http://stoplight.io/bar/foo', 'http://stoplight.io/')).toEqual('bar/foo');
expect(relative('http://stoplight.io/bar/foo/baz', 'http://stoplight.io/bar/z/x')).toEqual('../foo/baz');
});

it('handles different origins', () => {
expect(relative('/a/bar/c', '/x/foo/c')).toEqual('../../../x/foo/c');
expect(relative('http://stoplight.io/bar/foo/baz', 'https://stop.bar/bar/z/x')).toEqual(
'http://stoplight.io/bar/foo/baz',
);
});
});
17 changes: 17 additions & 0 deletions src/__tests__/startsWithWindowsDrive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { startsWithWindowsDrive } from '../';

describe('startsWithWindowsDrive', () => {
it.each(['c:\\foo\\bar.json', 'c:\\', 'c:/', 'c:/foo/bar.json', 'c:\\', 'Z:\\', 'A:/'])(
'recognizes driver letter in %s',
filepath => {
expect(startsWithWindowsDrive(filepath)).toBe(true);
},
);

it.each(['0:\\foo\\bar.json', ' :\\', 'c:a', 'z\\\\', '', 'c:', 'c'])(
'does not detect driver letter in %s',
filepath => {
expect(startsWithWindowsDrive(filepath)).toBe(false);
},
);
});
78 changes: 78 additions & 0 deletions src/__tests__/urlify.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { urlify } from '../urlify';

describe('urlify', () => {
it('wraps all obj methods', () => {
const obj = {
test() {
return false;
},

baz: (d: unknown) => true,
};

const result = urlify(obj, obj);
expect(result).not.toStrictEqual(obj);
expect(result).toMatchObject({
test: expect.any(Function),
baz: expect.any(Function),
});
});

it('wrapped method returning string normalizes the return', () => {
const obj = {
test: () => 'c:\\foo\\baz',
};

const result = urlify(obj, obj);
expect(result.test()).toEqual('c:/foo/baz');
});

it('wrapped method returning non-string value is supported', () => {
const obj = {
test: () => false,
};

const result = urlify(obj, obj);
expect(result.test()).toEqual(false);
});

it('copies properties whose values are not functions', () => {
const obj = {
foo: 'bar',
bar: {},
c: null,
};

expect(urlify({ ...obj }, { ...obj })).toStrictEqual(obj);
});

it('includes non-enumerable properties', () => {
const obj = Object.defineProperty({}, 'a', {
enumerable: false,
value: 2,
});

expect(urlify(obj, obj)).toHaveProperty('a', 2);
});

it('makes use of alternative method if url is detected', () => {
const obj = {
test: (a: string) => 'http://baz.com',
};
const altObj = {
test: () => 'foo.com',
};

const result = urlify(obj, altObj);
expect(result.test('http://baz.com')).toEqual('foo.com');
});

it('throws if alternative method is not implemented', () => {
const obj = {
test: (a: string) => 'http://baz.com',
};

const result = urlify(obj, {});
expect(() => result.test('http://baz.com')).toThrow();
});
});
11 changes: 11 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as path from 'path-browserify';
import * as pathURL from './path-url';
import { urlify } from './urlify';

const { dirname, extname, join, relative, sep, resolve, parse } = urlify(path, pathURL);
export { dirname, extname, join, relative, sep, resolve, parse };

export * from './normalize';
export * from './startsWithWindowsDrive';
export * from './toFSPath';
export * from './isAbsolute';
20 changes: 20 additions & 0 deletions src/isAbsolute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as URI from 'urijs';
import { isURL } from './isURL';
import { startsWithWindowsDrive } from './startsWithWindowsDrive';

const PATH_SEPARATOR_REGEXP = /^[/\\]/;

// based on https://github.com/nodejs/node/blob/9946c597077070941309e5b2986a810e52978a97/lib/path.js#L349
export function isAbsolute(uri: string) {
if (uri.length === 0) return false;

if (isURL(uri)) {
try {
return URI(uri).is('absolute');
} catch {
return false;
}
}

return PATH_SEPARATOR_REGEXP.test(uri) || startsWithWindowsDrive(uri);
}
3 changes: 3 additions & 0 deletions src/isURL.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const PROTOCOL = /^[A-Za-z]{2,}:\/\//;

export const isURL = (uri: string) => PROTOCOL.test(uri);
16 changes: 16 additions & 0 deletions src/normalize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// https://github.com/isomorphic-git/isomorphic-git/blob/master/src/utils/normalizePath.js

import * as path from 'path-browserify';
import * as URI from 'urijs';
import { isURL } from './isURL';

export function normalize(uri: string) {
if (isURL(uri)) {
return new URI(uri).normalize().href();
}

return path
.normalize(uri)
.replace(/\\/g, '/') // Replace '\' with '/'
.replace(/(.+)\/$/, '$1'); // Remove trailing '/'
}
Loading