Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6549800
commit 65f1038
Showing
33 changed files
with
139,575 additions
and
5,925 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
coverage/ | ||
index-es5.js | ||
index-es5.js.map | ||
node_modules/ | ||
relateurl-browser.js | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,5 @@ | ||
language: node_js | ||
node_js: | ||
- "0.10" | ||
- "0.12" | ||
- "4" | ||
- "5" | ||
- "6" | ||
script: npm test | ||
- 14 | ||
- node | ||
script: npm run ci |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,159 +1,85 @@ | ||
# relateurl [![NPM Version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][david-image]][david-url] | ||
# relateurl [![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] | ||
|
||
> Minify URLs by converting them from absolute to relative. | ||
> Create a relative URL with options to minify. | ||
If you were to use this library on a website like `http://example.com/dir1/dir1-1/`, you would get results such as: | ||
|
||
| Before | After | | ||
| :------------------------------------------ | :----------------------------------- | | ||
| `http://example.com/dir1/dir1-2/index.html` | `../dir1-2/` | | ||
| `http://example.com/dir2/dir2-1/` | `/dir2/dir2-1/` | | ||
| `http://example.com/dir1/dir1-1/` | ` ` | | ||
| `https://example.com/dir1/dir1-1/` | `https://example.com/dir1/dir1-1/` | | ||
| `http://google.com:80/dir/` | `//google.com/dir/` | | ||
| `../../../../../../../../#anchor` | `/#anchor` | | ||
With `http://domain.com/seg1/seg1-1/` as a base URL, you can produce: | ||
|
||
**All string parsing.** *No* directory browsing. It is thoroughly tested, very fast and lightweight with zero external dependencies. | ||
| Before | After | | ||
| :----------------------------------------- | :-------------------------------- | | ||
| `http://domain.com/seg1/seg1-2/index.html` | `../seg1-2/` | | ||
| `http://domain.com/seg2/seg2-1/` | `/seg2/seg2-1/` | | ||
| `http://domain.com/seg1/seg1-1/` | ` ` | | ||
| `httpS://domain.com/seg1/seg1-1/` | `https://domain.com/seg1/seg1-1/` | | ||
| `../../../../../../../../#anchor` | `/#anchor` | | ||
|
||
## Getting Started | ||
|
||
This utility requires [Node.js](http://nodejs.org/) `>= 0.10`. To install, type this at the command line: | ||
``` | ||
npm install relateurl --save-dev | ||
``` | ||
|
||
### Options | ||
|
||
#### options.defaultPorts | ||
Type: `Object` | ||
Default value: `{ftp:21, http:80, https:443}` | ||
|
||
Extend the list with any ports you need. Any URLs containing these default ports will have them removed. Example: `http://example.com:80/` will become `http://example.com/`. | ||
|
||
#### options.directoryIndexes | ||
Type: `Array` | ||
Default value: `["index.html"]` | ||
|
||
Extend the list with any resources you need. Works with [`options.removeDirectoryIndexes`](#options.removeDirectoryIndexes). | ||
|
||
#### options.ignore_www | ||
Type: `Boolean` | ||
Default value: `false` | ||
|
||
This will, for example, consider any domains containing `http://www.example.com/` to be related to any that contain `http://example.com/`. | ||
|
||
#### options.output | ||
Type: constant or `String` | ||
Choices: `RelateUrl.ABSOLUTE`,`RelateUrl.PATH_RELATIVE`,`RelateUrl.ROOT_RELATIVE`,`RelateUrl.SHORTEST` | ||
Choices: `"absolute"`,`"pathRelative"`,`"rootRelative"`,`"shortest"` | ||
Default value: `RelateUrl.SHORTEST` | ||
|
||
`RelateUrl.ABSOLUTE` will produce an absolute URL. Overrides [`options.schemeRelative`](#options.schemeRelative) with a value of `false`. | ||
`RelateUrl.PATH_RELATIVE` will produce something like `../child-of-parent/etc/`. | ||
`RelateUrl.ROOT_RELATIVE` will produce something like `/child-of-root/etc/`. | ||
`RelateUrl.SHORTEST` will choose whichever is shortest between root- and path-relative. | ||
|
||
#### options.rejectedSchemes | ||
Type: `Array` | ||
Default value: `["data","javascript","mailto"]` | ||
|
||
Extend the list with any additional schemes. Example: `javascript:something` will not be modified. | ||
## Installation | ||
|
||
#### options.removeAuth | ||
Type: `Boolean` | ||
Default value: `false` | ||
|
||
Remove user authentication information from the output URL. | ||
[Node.js](https://nodejs.org) `>= 14` is required. To install, type this at the command line: | ||
```shell | ||
npm install relateurl | ||
``` | ||
|
||
#### options.removeDirectoryIndexes | ||
Type: `Boolean` | ||
Default value: `true` | ||
|
||
Remove any resources that match any found in [`options.directoryIndexes`](#options.directoryIndexes). | ||
## Usage | ||
|
||
#### options.removeEmptyQueries | ||
Type: `Boolean` | ||
Default value: `false` | ||
Inputs *must* be [`URL`](https://mdn.io/URL) instances. | ||
|
||
Remove empty query variables. Example: `http://domain.com/?var1&var2=&var3=asdf` will become `http://domain.com/?var3=adsf`. This does not apply to unrelated URLs (with other protocols, auths, hosts and/or ports). | ||
```js | ||
const relateURL = require('relateurl'); | ||
|
||
#### options.removeRootTrailingSlash | ||
Type: `Boolean` | ||
Default value: `true` | ||
const base = new URL('http://domain.com/seg1/seg1-1/'); | ||
const url = new URL('//domain.com/seg1/seg1-2/index.html', base); | ||
|
||
Remove trailing slashes from root paths. Example: `http://domain.com/?var` will become `http://domain.com?var` while `http://domain.com/dir/?var` will not be modified. | ||
relateURL(url, base, options); | ||
//-> ../seg1-2/ | ||
``` | ||
|
||
#### options.schemeRelative | ||
Type: `Boolean` | ||
Default value: `true` | ||
|
||
Output URLs relative to the scheme. Example: `http://example.com/` will become `//example.com/`. | ||
## Options | ||
|
||
#### options.site | ||
Type: `String` | ||
Default value: `undefined` | ||
It is simplest to use an [option profile](#option-profiles), but custom configurations are still possible. | ||
|
||
An options-based version of the [`from`](#examples) argument. If both are specified, `from` takes priority. | ||
### `output` | ||
Type: `Symbol` | ||
Default value: `relateURL.SHORTEST` | ||
The limit of how far the resulting URL should be related. Possible values: | ||
|
||
#### options.slashesDenoteHost | ||
Type: `Boolean` | ||
Default value: `true` | ||
* `PROTOCOL_RELATIVE`: will try to produce something like `//domain.com/path/to/file.html`. | ||
* `ROOT_PATH_RELATIVE`: will try to produce something like `/child-of-root/etc/`. | ||
* `PATH_RELATIVE`: will try to produce something like `../child-of-parent/etc/`. | ||
* `SHORTEST`: will try to choose whichever is shortest between `PATH_RELATIVE` and `ROOT_PATH_RELATIVE`. | ||
|
||
Passed to Node's [`url.parse`](http://nodejs.org/api/url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost). | ||
|
||
### Examples | ||
This library can be used as a [function for single-use](#single-instance) or as a [class for multiple conversions](#reusable-instances). | ||
### Minify Options | ||
|
||
Upon successful conversion, a `String` will be returned. If an issue is encountered while parsing `from`, an error will be thrown. | ||
Any other defined option will be passed to [minurl](https://npmjs.com/minurl). Avoid setting `stringify` to `false`, as it will prevent any operations performed by this library from being outputted. | ||
|
||
#### Single Instance | ||
#### Ignoring Basic Authentication | ||
Ignoring a URL's username and password attributes will need the not-so-obvious `removeAuth` option (from `minurl`): | ||
```js | ||
var RelateUrl = require("relateurl"); | ||
|
||
var result = RelateUrl.relate(from, to, options); | ||
``` | ||
|
||
#### Reusable Instances | ||
```js | ||
var RelateUrl = require("relateurl"); | ||
|
||
var instance = new RelateUrl(from, options); | ||
|
||
var result1 = instance.relate(to1); | ||
var result2 = instance.relate(to2, customOptions); | ||
var result3 = instance.relate(to3); | ||
``` | ||
|
||
## FAQ | ||
1. **Why bother writing/using this?** | ||
To aid in further minifying HTML, mainly for the purpose of faster page loads and SEO. It's been integrated into [HTMLMinifier](https://github.com/kangax/html-minifier). | ||
|
||
2. **Why not just use Node's `url.parse`, `url.resolve` and `path.relative`?** | ||
`url.parse` *is* used, but `url.resolve` and `path.relative` are both slower and less powerful than this library. | ||
const base = new URL('http://user:pass@domain.com/seg1/seg1-1/'); | ||
const url = new URL('http://domain.com/seg1/seg1-2/'); | ||
|
||
relateURL(url, base, { | ||
removeAuth: true | ||
}); | ||
//-> ../seg1-2/ | ||
```` | ||
|
||
## Release History | ||
* 0.2.7 Node v6 support | ||
* 0.2.6 minor enhancements | ||
* 0.2.5 added `options.removeRootTrailingSlash` | ||
* 0.2.4 added `options.site` | ||
* 0.2.3 added browserify npm-script | ||
* 0.2.2 removed task runner | ||
* 0.2.1 shorten resource- and query-relative URLs, test variations list with other site URLs | ||
* 0.2.0 code cleanup, `options.removeEmptyQueries=true` only applied to unrelated URLs | ||
* 0.1.0 initial release | ||
|
||
### Option Profiles | ||
|
||
## Roadmap | ||
* 0.2.8 check if queries are the same, regardless of param order | ||
* 0.2.8 possible [scheme exclusions](http://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml) such as `tel:` | ||
* 0.2.8 decipher and return invalid input (special cases) to complete test suite | ||
* 0.3.0 test `options.slashesDenoteHost=false`, add something like `options.externalDirectoryIndexes=[]` for external sites | ||
There're two profiles: [`CAREFUL_PROFILE` and `COMMON_PROFILE`](https://npmjs.com/minurl#option-profiles). | ||
[npm-image]: https://img.shields.io/npm/v/relateurl.svg | ||
[npm-url]: https://npmjs.org/package/relateurl | ||
[filesize-image]: https://img.shields.io/badge/bundle-56kB%20gzipped-blue.svg | ||
[travis-image]: https://img.shields.io/travis/stevenvachon/relateurl.svg | ||
[travis-url]: https://travis-ci.org/stevenvachon/relateurl | ||
[david-image]: https://img.shields.io/david/stevenvachon/relateurl.svg | ||
[david-url]: https://david-dm.org/stevenvachon/relateurl | ||
[coveralls-image]: https://img.shields.io/coveralls/stevenvachon/relateurl.svg | ||
[coveralls-url]: https://coveralls.io/github/stevenvachon/relateurl | ||
[greenkeeper-image]: https://badges.greenkeeper.io/stevenvachon/relateurl.svg | ||
[greenkeeper-url]: https://greenkeeper.io/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
"use strict"; | ||
const {writeFileSync} = require("fs"); | ||
|
||
const urls = | ||
[ | ||
// Parts removing from right to left | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1=", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/", | ||
"http://user:pass@www.domain.com:80/test//", | ||
"http://user:pass@www.domain.com:80/test/", | ||
"http://user:pass@www.domain.com:80/", | ||
"http://user:pass@www.domain.com:80", | ||
"http://user:pass@www.domain.com/", | ||
"http://user:pass@www.domain.com", | ||
"http://user:pass@www.domain./", | ||
"http://user:pass@www.domain.", | ||
"http://user:pass@www.domain/", | ||
"http://user:pass@www.domain", | ||
"http://user:pass@www./", | ||
"http://user:pass@www.", | ||
"http://user:pass@www/", | ||
"http://user:pass@www", | ||
|
||
// Parts changing from left to right | ||
"https://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user2:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass2@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user2:pass2@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://:@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www2.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain2.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com2:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:81/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test2//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test/tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter2/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index2.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va+r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r12= +dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1=++dir&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir2&var2=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var22=text&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text2&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var32#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor2", | ||
|
||
// Edge cases | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3&=#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var2=text2&var3#anchor", | ||
"http://user:pass@www.domain.com:80/test//tes.ter/./../index.html?var2=text&va r1= +dir&var3&var2=text2#anchor", | ||
"http://user:pass@www.domain.com:80//", | ||
"http://user:pass@www.domain.com:80///test/", | ||
"http://user:pass@com:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@localhost:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"http://user:pass@127.0.0.1:80/test//tes.ter/./../index.html?va r1= +dir&var2=text&var3#anchor", | ||
"other://domain/" | ||
]; | ||
|
||
|
||
|
||
const generate = () => saveFile(`${__dirname}/tests.json`); | ||
|
||
|
||
|
||
const generateData = () => | ||
{ | ||
const output = []; | ||
|
||
for (let i=0; i<urls.length; i++) | ||
{ | ||
for (let j=0; j<urls.length; j++) | ||
{ | ||
output.push( | ||
{ | ||
url: urls[i], | ||
base: urls[j], | ||
related: | ||
{ | ||
careful: | ||
{ | ||
// Placeholder values for manual editing | ||
PROTOCOL_RELATIVE: null, | ||
ROOT_PATH_RELATIVE: null, | ||
PATH_RELATIVE: null, | ||
SHORTEST: null | ||
}, | ||
common_deep: | ||
{ | ||
// Placeholder values for manual editing | ||
PROTOCOL_RELATIVE: null, | ||
ROOT_PATH_RELATIVE: null, | ||
PATH_RELATIVE: null, | ||
SHORTEST: null | ||
}, | ||
common_shallow: | ||
{ | ||
// Placeholder values for manual editing | ||
PROTOCOL_RELATIVE: null, | ||
ROOT_PATH_RELATIVE: null, | ||
PATH_RELATIVE: null, | ||
SHORTEST: null | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
|
||
return output; | ||
}; | ||
|
||
|
||
|
||
// Extra line break for unix/git | ||
const generateString = () => JSON.stringify(generateData(), null, "\t") + "\n"; | ||
|
||
|
||
|
||
const saveFile = location => | ||
{ | ||
writeFileSync(location, generateString()); | ||
|
||
console.log(`Written to: ${location}`); | ||
}; | ||
|
||
|
||
|
||
generate(); |
Oops, something went wrong.