Skip to content

Commit

Permalink
fix: align pathname, host and port in IE with other environments (#2)
Browse files Browse the repository at this point in the history
- A pathname should always start with a slash.
- The implicit ports 80 (http) and 443 (https) are omitted by all other
  environments besides Internet Explorer.
- Always set an empty string as fallback.

BREAKING CHANGE: Setting an empty string as fallback value deviates
from the Node.js implementation of `url.parse`.
  • Loading branch information
unstubbable authored Jan 13, 2017
1 parent e33e14c commit 7ea9c91
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 19 deletions.
47 changes: 46 additions & 1 deletion src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { assert } from 'chai';
import { parseURL } from './';

describe('parseURL', () => {
it('returns an URL object for the given URL', () => {
it('returns an URL object for http://www.example.com:1234/foo?bar=1#baz', () => {
const urlString = 'http://www.example.com:1234/foo?bar=1#baz';
const expectedResult = {
hash: '#baz',
Expand All @@ -16,4 +16,49 @@ describe('parseURL', () => {
};
assert.deepEqual(parseURL(urlString), expectedResult);
});

it('returns an URL object for https://www.example.com', () => {
const urlString = 'https://www.example.com';
const expectedResult = {
hash: '',
host: 'www.example.com',
hostname: 'www.example.com',
href: 'https://www.example.com/',
pathname: '/',
port: '',
protocol: 'https:',
search: ''
};
assert.deepEqual(parseURL(urlString), expectedResult);
});

it('returns an URL object for http://www.example.com', () => {
const urlString = 'http://www.example.com';
const expectedResult = {
hash: '',
host: 'www.example.com',
hostname: 'www.example.com',
href: 'http://www.example.com/',
pathname: '/',
port: '',
protocol: 'http:',
search: ''
};
assert.deepEqual(parseURL(urlString), expectedResult);
});

it('returns an URL object for http://www.example.com:1234?bar=1&baz=2', () => {
const urlString = 'http://www.example.com:1234?bar=1&baz=2';
const expectedResult = {
hash: '',
host: 'www.example.com:1234',
hostname: 'www.example.com',
href: 'http://www.example.com:1234/?bar=1&baz=2',
pathname: '/',
port: '1234',
protocol: 'http:',
search: '?bar=1&baz=2'
};
assert.deepEqual(parseURL(urlString), expectedResult);
});
});
51 changes: 33 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Url as NodeURL } from 'url';

export interface URL {
hash: string | undefined;
host: string | undefined;
hostname: string | undefined;
href: string | undefined;
pathname: string | undefined;
port: string | undefined;
protocol: string | undefined;
search: string | undefined;
hash: string;
host: string;
hostname: string;
href: string;
pathname: string;
port: string;
protocol: string;
search: string;
}

let a: HTMLAnchorElement;
Expand All @@ -19,6 +19,21 @@ if (typeof document !== 'undefined') {
parse = require('url').parse;
}

// Removes port 80/443 from `port` and `host` if it does not exist on `href`.
// Internet Explorer is the only browser that adds these ports.
function removeImplicitPort(url: URL): URL {
const { host, href, pathname, port, protocol } = url;
if (href.indexOf(`${protocol}//${host}${pathname}`) < 0) {
url.port = '';
url.host = host.slice(0, host.length - port.length - 1);
}
return url;
}

function prependSlash(path: string): string {
return path.indexOf('/') === 0 ? path : `/${path}`;
}

export function parseURL(urlString: string): URL {
let parsed: HTMLAnchorElement | NodeURL;

Expand All @@ -29,14 +44,14 @@ export function parseURL(urlString: string): URL {
parsed = parse(urlString) as NodeURL;
}

return {
hash: parsed.hash,
host: parsed.host,
hostname: parsed.hostname,
href: parsed.href,
pathname: parsed.pathname,
port: parsed.port,
protocol: parsed.protocol,
search: parsed.search
};
return removeImplicitPort({
hash: parsed.hash || '',
host: parsed.host || '',
hostname: parsed.hostname || '',
href: parsed.href || '',
pathname: prependSlash(parsed.pathname || ''),
port: parsed.port || '',
protocol: parsed.protocol || '',
search: parsed.search || ''
});
}

0 comments on commit 7ea9c91

Please sign in to comment.