Skip to content

Commit

Permalink
v1.0.0-alpha12
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenvachon committed Jul 12, 2019
1 parent 2d31377 commit faac8fb
Show file tree
Hide file tree
Showing 13 changed files with 12,103 additions and 11,057 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
coverage/
lib-es5/
node_modules/
.nyc_output/
package-lock.json
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: node_js
node_js:
- 6
- 8
- 10
- 12
- node
script: npm run ci
160 changes: 110 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,92 @@
# url-relation [![NPM Version][npm-image]][npm-url] ![File Size][filesize-image] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Dependency Monitor][greenkeeper-image]][greenkeeper-url]

> Determine the relation between two URLs.
> Determine the relation between two [`URL`](https://developer.mozilla.org/en/docs/Web/API/URL)s.

## Installation

[Node.js](http://nodejs.org/) `>= 6` is required. To install, type this at the command line:
[Node.js](http://nodejs.org) `>= 8` is required. To install, type this at the command line:
```shell
npm install url-relation
```


## Usage
## Constructor
```js
new URLRelation(url1, url2[, options]);
```


## Methods & Functions

### `URLRelation.match(url1, url2[, options])`
```js
const URLRelation = require('url-relation');

const url1 = new URL('http://domain.com/');
const url2 = new URL('http://domain.com/#hash');

const options = {
components: [URLRelation.HASH],
ignoreComponents: true
};

if (URLRelation.match(url1, url2, options)) {
// considered the same
}
```

### `URLRelation::upTo(component[, ignoredComponents])`
`component` is the same as [`targetComponent`](#targetcomponent).

* Inputs *must* be [`URL`](https://developer.mozilla.org/en/docs/Web/API/URL) instances.
* The result will be a number that correponds to a [relation constant](#relation-constants).
`ignoredComponents` is the same as [`components`](#components). However, if it's value is a non-empty array, it will also set [`ignoreComponents`](#ignorecomponents) to `true`.

```js
const urlRelation = require('url-relation');
const URLRelation = require('url-relation');

const url1 = new URL('http://domain.com/');
const url2 = new URL('http://domain.com/#hash');

const relation = urlRelation(url1, url2, options);
//-> 14
const relation = new URLRelation(url1, url2, options);

if (relation >= urlRelation.HOST) {
// same host
if (relation.upTo(URLRelation.HASH, [URLRelation.HASH])) {
// considered the same
}

if (relation.upTo(URLRelation.PATH)) {
// considered the same
}
```


## Options

It is simplest to use an [option profile](#option-profiles), but custom configurations are still possible.

### `components`
Type: `Array<Symbol>`
Default value: `[]`
A list of URL components for [`ignoreComponents`](#ignorecomponents). See [URL Components](#urlcomponents) for possible values.

### `defaultPorts`
Type: `Object`
Default value: `{}`
A map of protocol default ports for [`ignoreDefaultPort`](#ignoredefaultport). Be sure to include the suffixed ":" in the key. [Common protocols](https://url.spec.whatwg.org/#special-scheme) already have their ports removed.

### `directoryIndexes`
Type: `Array<RegExp|string>`
Default value: `['index.html']`
A list of file names for [`ignoreDirectoryIndex`](#ignoredirectoryindex).
### `ignoreComponents`
Type: `Boolean` or `Function`
Default value: `true`
When set to `true` or a function that returns `true`, a URL's components specified in [`components`](#components) will be ignored during comparison.

### `ignoreDefaultPort`
Type: `Boolean` or `Function`
Default value: `true`
When set to `true` or a function that returns `true`, a URL's port that matches any found in [`defaultPorts`](#defaultports) will be ignored during comparison.

### `ignoreDirectoryIndex`
### `ignoreIndexFilename`
Type: `Boolean` or `Function`
Default value: [`Function`](https://github.com/stevenvachon/url-relation/blob/master/index.js#L34)
When set to `true` or a function that returns `true`, a URL's file name that matches any found in [`directoryIndexes`](#directoryindexes) will be ignored during comparison.

### `ignoreEmptyDirectoryNames`
Type: `Boolean` or `Function`
Default value: `false`
When set to `true` or a function that returns `true`, empty directory names within a URL's path (such as the "//" in "/path//to/") will be ignored during comparison.
When set to `true` or a function that returns `true`, a URL's file name that matches any found in [`indexFilenames`](#indexFilenames) will be ignored during comparison.

### `ignoreEmptyQueries`
Type: `Boolean` or `Function`
Expand All @@ -74,24 +103,39 @@ Type: `Boolean` or `Function`
Default value: [`Function`](https://github.com/stevenvachon/url-relation/blob/master/index.js#L40-46)
When set to `true` or a function that returns `true`, the order of *unique* query parameters will not distinguish one URL from another. **This option will be silently skipped** if the input `URL`s do not support `URLSearchParams`.

### `ignoreEmptySegmentNames`
Type: `Boolean` or `Function`
Default value: `false`
When set to `true` or a function that returns `true`, empty segment names within a URL's path (such as the "//" in "/path//to/") will be ignored during comparison.

### `ignoreWWW`
Type: `Boolean` or `Function`
Default value: [`Function`](https://github.com/stevenvachon/url-relation/blob/master/index.js#L34)
When set to `true` or a function that returns `true`, a URL's "www" subdomain will be ignored during comparison.

### `indexFilenames`
Type: `Array<RegExp|string>`
Default value: `['index.html']`
A list of file names for [`ignoreIndexFilename`](#ignoreindexfilename).

### `queryNames`
Type: `Array<RegExp|string>`
Default value: `[]`
A list of query parameters for [`ignoreQueryNames`](#ignorequerynames).

### `targetComponent`
Type: `Symbol`
Default value: `URLRelation.HASH`
The URL component at which to limit—and include in—the relation from left to right. See [URL Components](#urlcomponents) for more info and for possible values.


### Function as an Option

When an option is defined as a `Function`, it must return `true` to be included in the custom filter:
```js
const options = {
ignoreDirectoryIndex: (url1, url2) => {
// Only URLs with these protocols will have their directory indexes ignored
ignoreIndexFilename: (url1, url2) => {
// Only URLs with these protocols will have their index filename ignored
return url1.protocol === 'http:' && url1.protocol === 'https:';
}
};
Expand All @@ -106,44 +150,43 @@ const options = {

An example of checking for a trusted hostname:
```js
const dynamicProfile = (url1, url2) => {
const trustedHosts = ['domain.com'];

const isTrusted = trustedHosts
.reduce((results, trustedHost) => {
results[0] = results[0] || url1.hostname.endsWith(trustedHost);
results[1] = results[1] || url2.hostname.endsWith(trustedHost);
return results;
}, [false,false])
.every(result => result);

return URLRelation[`${isTrusted ? 'COMMON' : 'CAREFUL'}_PROFILE`];
};

const url1 = new URL('http://domain.com/');
const url2 = new URL('http://domain.com/#hash');

const trustedHosts = ['domain.com'];

const isTrusted = trustedHosts
.reduce((results, trustedHost) => {
results[0] = results[0] || url1.hostname.endsWith(trustedHost);
results[1] = results[1] || url2.hostname.endsWith(trustedHost);
return results;
}, [false,false])
.every(result => result);

const options = urlRelation[`${isTrusted ? 'COMMON' : 'CAREFUL'}_PROFILE`];

urlRelation(url1, url2, options);
const profile = dynamicProfile(url1, url2);
```


#### Customizing Profiles

```js
const custom = {
...urlRelation.CAREFUL_PROFILE,
ignoreTrailingSlash: true
...URLRelation.COMMON_PROFILE,
indexFilenames: ['index.html', 'index.php']
};
```
Or:
```js
const extend = require('extend');

const custom = extend(true, {}, urlRelation.COMMON_PROFILE, { directoryIndexes:['index.php'] });
const custom = extend(true, {}, URLRelation.COMMON_PROFILE, { indexFilenames:['index.php'] });
```


## Relation Constants

In sequential order, returned values can be compared with: `NONE`, `PROTOCOL`, `TLD`, `DOMAIN`, `SUBDOMAIN`, `HOSTNAME`, `PORT`, `HOST`, `USERNAME`, `PASSWORD`, `AUTH`, `DIRECTORY`, `FILENAME`, `PATHNAME`, `SEARCH`, `PATH`, `HASH`, `ALL`.
## URL Components

```
AUTH HOST PATH
Expand All @@ -155,26 +198,43 @@ In sequential order, returned values can be compared with: `NONE`, `PROTOCOL`, `
foo://username:password@www.example.com:123/hello/world/there.html?var=value#foo
\_/ \_/ \_____/ \_/ \_________/ \________/
| | | | | |
PROTOCOL SUBDOMAIN | TLD DIRECTORY FILENAME
PROTOCOL SUBDOMAIN | TLD SEGMENTS FILENAME
|
DOMAIN
```

**Note:** there are a few breaks in the linearity of these values:

* `AUTH` is prioritized *after* `HOST` because matching authentication on a different host is pointless.
* `TLD` is prioritized *before* `DOMAIN` because matching a domain on a different top-level domain is pointless.
The components of URLs are compared in the following order:
* `PROTOCOL`
* `USERNAME`
* `PASSWORD`
* `AUTH`
* `TLD`
* `DOMAIN`
* `SUBDOMAIN`
* `HOSTNAME`
* `PORT`
* `HOST`
* `SEGMENTS`
* `FILENAME`
* `PATHNAME`
* `SEARCH`
* `PATH`
* `HASH`

As you may have noticed, there are a few breaks in linearity:

* `TLD` is prioritized *before* `DOMAIN` because matching a domain on a different top-level domain is very uncommon (but still possible via [`ignoreComponents`](#ignorecomponents)).
* `SUBDOMAIN` is prioritized *after* `DOMAIN`.


## Browserify/etc

Due to extreme file size in correctly parsing domains, browser builds will not include such functionality by default. As a result, output of this library within a web browser will never exactly equal `TLD`, `DOMAIN` nor `SUBDOMAIN`.
Due to extreme file size in correctly parsing domains, browser builds will not include such functionality by default. While not always accurate, relations of `TLD`, `DOMAIN` and `SUBDOMAIN` will simply reflect that of `HOSTNAME`.


[npm-image]: https://img.shields.io/npm/v/url-relation.svg
[npm-url]: https://npmjs.org/package/url-relation
[filesize-image]: https://img.shields.io/badge/size-2.4kB%20gzipped-blue.svg
[filesize-image]: https://img.shields.io/badge/size-12.5kB%20gzipped-blue.svg
[travis-image]: https://img.shields.io/travis/stevenvachon/url-relation.svg
[travis-url]: https://travis-ci.org/stevenvachon/url-relation
[coveralls-image]: https://img.shields.io/coveralls/stevenvachon/url-relation.svg
Expand Down

0 comments on commit faac8fb

Please sign in to comment.