Socket
Socket
Sign inDemoInstall

tldts

Package Overview
Dependencies
Maintainers
1
Versions
733
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tldts - npm Package Compare versions

Comparing version 3.1.2 to 4.0.0

dist/lib/extract-hostname.d.ts

30

CHANGELOG.md

@@ -5,2 +5,32 @@ ## Change Log

### 4.0.0
*2019-01-07*
This Release introduces some more optimizations both in size of bundles,
memory usage and speed of parsing. Because it introduces some breaking
changes in the API results (`host` renamed into `hostname` and deletion
of the `isValid` attribute), as well as introducing a new experimental
backend (`tldts-experimental` bundle), this is a major version bump.
- [#16](https://github.com/remusao/tldts/pull/16) Optimizations + comparison with other libraries (#16)
* Optimize Trie into a DAWG (size reduction)
* Implement comparison with other libraries
* Implement fast path for valid hostnames as arguments
* Allow to disable hostname parsing and validation using option
* Add tests for corner-cases URLs parsing
* Update README
- [#13](https://github.com/remusao/tldts/pull/13) Implement experimental probabilistic packed suffix structure (#13)
* Implement packed hash probabilistic structure for more compact
representation and faster lookups. See ./bin/builders/hashes.js for more
details about how it works.
* Create second bundle (tldts-experimental) making use of this new implementation
* Simplify hostname validation and remove strict IDNA checks
* Move lookup implementations into 'lookup' sub-folder
* Move compiled data into 'lookup/data' sub-folder
* Refactor suffix list parsing out of builders
* Handle IDNA hostnames at build-time instead of runtime (by indexing
some suffixes multiple times: once puny-coded and once in unicode form)
### 3.1.1

@@ -7,0 +37,0 @@

2

dist/lib/domain.d.ts
import { IOptions } from './options';
export default function getDomain(suffix: string | null, hostname: string, options: IOptions): string | null;
export default function getDomain(suffix: string, hostname: string, options: IOptions): string | null;

@@ -1,2 +0,1 @@

import { IOptions } from './options';
export default function isValid(hostname: string, options: IOptions): boolean;
export default function (hostname: string): boolean;
export interface IOptions {
allowIcannDomains: boolean;
allowPrivateDomains: boolean;
extractHostname: (url: string) => string | null;
strictHostnameValidation: boolean;
validHosts: string[];
extractHostname: boolean;
validHosts: string[] | null;
}
export declare function setDefaults({ allowIcannDomains, allowPrivateDomains, extractHostname, strictHostnameValidation, validHosts, }?: Partial<IOptions>): IOptions;
export declare function setDefaults({ allowIcannDomains, allowPrivateDomains, extractHostname, validHosts, }?: Partial<IOptions>): IOptions;

@@ -0,3 +1,3 @@

import { IPublicSuffix, ISuffixLookupOptions } from './lookup/interface';
import { IOptions } from './options';
import { IPublicSuffix } from './suffix-trie';
export default function getPublicSuffix(hostname: string, options: IOptions): IPublicSuffix;
export default function getPublicSuffix(hostname: string, options: IOptions, suffixLookup: (_1: string, _2: ISuffixLookupOptions) => IPublicSuffix | null): IPublicSuffix;

@@ -1,1 +0,1 @@

export default function getSubdomain(hostname: string, domain: string | null): string | null;
export default function getSubdomain(hostname: string, domain: string): string;

@@ -0,23 +1,4 @@

import { IResult } from './lib/factory';
import { IOptions } from './lib/options';
interface IResult {
host: string | null;
isValid: boolean | null;
isIp: boolean;
subdomain: string | null;
domain: string | null;
publicSuffix: string | null;
isIcann: boolean | null;
isPrivate: boolean | null;
}
declare const enum FLAG {
HOST = 0,
IS_VALID = 1,
IS_IP = 2,
PUBLIC_SUFFIX = 3,
DOMAIN = 4,
SUB_DOMAIN = 5,
ALL = 6
}
export declare function parse(url: string, partialOptions?: Partial<IOptions>, step?: FLAG): IResult;
export declare function isValidHostname(url: string, options?: Partial<IOptions>): boolean;
export declare function parse(url: string, options?: Partial<IOptions>): IResult;
export declare function getPublicSuffix(url: string, options?: Partial<IOptions>): string | null;

@@ -27,2 +8,1 @@ export declare function getDomain(url: string, options?: Partial<IOptions>): string | null;

export declare function getHostname(url: string, options?: Partial<IOptions>): string | null;
export {};
import { IOptions } from './options';
/**
* Polyfill for `endsWith`
*/
function endsWith(str: string, pattern: string): boolean {
return str.lastIndexOf(pattern) === str.length - pattern.length;
}
/**
* Check if `vhost` is a valid suffix of `hostname` (top-domain)

@@ -22,3 +15,3 @@ *

function shareSameDomainSuffix(hostname: string, vhost: string): boolean {
if (endsWith(hostname, vhost)) {
if (hostname.endsWith(vhost)) {
return (

@@ -63,3 +56,3 @@ hostname.length === vhost.length ||

// Extract the part between the last '.'
return hostname.substr(lastDotBeforeSuffixIndex + 1);
return hostname.slice(lastDotBeforeSuffixIndex + 1);
}

@@ -71,20 +64,17 @@

export default function getDomain(
suffix: string | null,
suffix: string,
hostname: string,
options: IOptions,
): string | null {
const validHosts = options.validHosts;
// Check if `hostname` ends with a member of `validHosts`.
for (let i = 0; i < validHosts.length; i += 1) {
const vhost = validHosts[i];
if (shareSameDomainSuffix(hostname, vhost)) {
return vhost;
if (options.validHosts !== null) {
const validHosts = options.validHosts;
for (let i = 0; i < validHosts.length; i += 1) {
const vhost = validHosts[i];
if (shareSameDomainSuffix(hostname, vhost)) {
return vhost;
}
}
}
// If there is no suffix, there is no hostname
if (suffix === null) {
return null;
}
// If `hostname` is a valid public suffix, then there is no domain to return.

@@ -91,0 +81,0 @@ // Since we already know that `getPublicSuffix` returns a suffix of `hostname`

@@ -41,6 +41,4 @@ /**

} else if (
!(
(code >= 48 && code <= 57) || // 0-9
(code >= 97 && code <= 102)
) // a-f
((code >= 48 && code <= 57) || // 0-9
(code >= 97 && code <= 102)) === false // a-f
) {

@@ -47,0 +45,0 @@ return false;

@@ -1,9 +0,23 @@

import isValidIDNA from './idna';
import { IOptions } from './options';
/**
* Implements fast shallow verification of hostnames. This does not perform a
* struct check on the content of labels (classes of Unicode characters, etc.)
* but instead check that the structure is valid (number of labels, length of
* labels, etc.).
*
* If you need stricter validation, consider using an external library.
*/
function containsUnderscore(hostname: string): boolean {
return hostname.indexOf('_') !== -1;
function isValidAscii(code: number): boolean {
return (
(code >= 97 && code <= 122) || (code >= 48 && code <= 57) || code > 127
);
}
function isValidHostname(hostname: string): boolean {
/**
* Check if a hostname string is valid. It's usually a preliminary check before
* trying to use getDomain or anything else.
*
* Beware: it does not check if the TLD exists.
*/
export default function(hostname: string): boolean {
if (hostname.length > 255) {

@@ -17,12 +31,7 @@ return false;

// Check first character
const firstCharCode: number | undefined = hostname.codePointAt(0);
if (firstCharCode === undefined) {
// @ts-ignore
if (!isValidAscii(hostname.codePointAt(0))) {
return false;
}
if (!isValidIDNA(firstCharCode)) {
return false;
}
// Validate hostname according to RFC

@@ -35,5 +44,3 @@ let lastDotIndex = -1;

const code = hostname.codePointAt(i);
if (code === undefined) {
return false;
} else if (code === 46) {
if (code === 46) {
// '.'

@@ -45,5 +52,5 @@ if (

lastCharCode === 46 ||
// Check that the previous label does not end with a '-'
// Check that the previous label does not end with a '-' (dash)
lastCharCode === 45 ||
// Check that the previous label does not end with a '_'
// Check that the previous label does not end with a '_' (underscore)
lastCharCode === 95

@@ -55,3 +62,4 @@ ) {

lastDotIndex = i;
} else if (!(isValidIDNA(code) || code === 45 || code === 95)) {
// @ts-ignore
} else if (!(isValidAscii(code) || code === 45 || code === 95)) {
// Check if there is a forbidden character in the label

@@ -73,15 +81,1 @@ return false;

}
/**
* Check if a hostname string is valid (according to RFC). It's usually a
* preliminary check before trying to use getDomain or anything else.
*
* Beware: it does not check if the TLD exists.
*/
export default function isValid(hostname: string, options: IOptions): boolean {
return (
isValidHostname(hostname) &&
(options.strictHostnameValidation === false ||
!containsUnderscore(hostname))
);
}

@@ -1,9 +0,6 @@

import extractHostnameDefault from './clean-host';
export interface IOptions {
allowIcannDomains: boolean;
allowPrivateDomains: boolean;
extractHostname: (url: string) => string | null;
strictHostnameValidation: boolean;
validHosts: string[];
extractHostname: boolean;
validHosts: string[] | null;
}

@@ -14,5 +11,4 @@

allowPrivateDomains = false,
extractHostname = extractHostnameDefault,
strictHostnameValidation = false,
validHosts = [],
extractHostname = true,
validHosts = null,
}: Partial<IOptions> = {}): IOptions {

@@ -23,5 +19,4 @@ return {

extractHostname,
strictHostnameValidation,
validHosts,
};
}

@@ -1,6 +0,18 @@

import extractTldFromHost from './from-host';
import { IPublicSuffix, ISuffixLookupOptions } from './lookup/interface';
import { IOptions } from './options';
import { hasTld, IPublicSuffix, suffixLookup } from './suffix-trie';
/**
* Utility to extract the TLD from a hostname string
*/
function extractTldFromHost(hostname: string): string | null {
const lastDotIndex = hostname.lastIndexOf('.');
if (lastDotIndex === -1) {
// Single label is considered a tld
return hostname;
}
return hostname.slice(lastDotIndex + 1);
}
/**
* Returns the public suffix (including exact matches)

@@ -11,12 +23,4 @@ */

options: IOptions,
suffixLookup: (_1: string, _2: ISuffixLookupOptions) => IPublicSuffix | null,
): IPublicSuffix {
// First check if `hostname` is already a valid top-level Domain.
if (hasTld(hostname)) {
return {
isIcann: false,
isPrivate: false,
publicSuffix: hostname,
};
}
const candidate = suffixLookup(hostname, options);

@@ -23,0 +27,0 @@ if (candidate === null) {

/**
* Returns the subdomain of a hostname string
*/
export default function getSubdomain(
hostname: string,
domain: string | null,
): string | null {
// No domain found? Just abort, abort!
if (domain === null) {
return null;
}
return hostname.substr(0, hostname.length - domain.length - 1);
export default function getSubdomain(hostname: string, domain: string): string {
return hostname.slice(0, -domain.length - 1);
}
{
"name": "tldts",
"description": "Library to work against complex domain names, subdomains and URIs.",
"version": "3.1.2",
"version": "4.0.0",
"homepage": "https://github.com/remusao/tldts",

@@ -27,3 +27,4 @@ "author": "Rémi Berson",

"lib",
"tldts.ts"
"tldts.ts",
"tldts-experimental.ts"
],

@@ -39,3 +40,5 @@ "license": "MIT",

"prebundle": "npm run build",
"minify": "google-closure-compiler --js=./dist/tldts.umd.js --js_output_file=./dist/tldts.umd.min.js",
"minify-tldts": "google-closure-compiler --js=./dist/tldts.umd.js --js_output_file=./dist/tldts.umd.min.js",
"minify-tldts-experimental": "google-closure-compiler --js=./dist/tldts-experimental.umd.js --js_output_file=./dist/tldts-experimental.umd.min.js",
"minify": "npm run minify-tldts && npm run minify-tldts-experimental",
"preminify": "npm run bundle",

@@ -47,23 +50,18 @@ "prepack": "npm run minify",

},
"dependencies": {
"punycode": "^2.1.1"
},
"dependencies": {},
"devDependencies": {
"@types/jest": "^23.3.10",
"@types/node": "^10.12.12",
"@types/jest": "^23.3.11",
"@types/node": "^10.12.18",
"benchmark": "^2.1.4",
"concurrently": "^4.1.0",
"eslint": "^5.10.0",
"coveralls": "^3.0.2",
"eslint": "^5.11.1",
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
"eslint-plugin-react": "^7.11.1",
"google-closure-compiler": "^20181125.1.0",
"eslint-plugin-react": "^7.12.2",
"google-closure-compiler": "^20181210.0.0",
"jest": "^23.6.0",
"prettier": "^1.15.3",
"rollup": "^0.67.4",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-node-resolve": "^4.0.0",
"rollup": "^1.0.2",
"ts-jest": "^23.10.5",
"tslint": "^5.11.0",
"tslint": "^5.12.0",
"typescript": "^3.2.2"

@@ -75,2 +73,5 @@ },

"domain",
"subdomain",
"subdomain",
"hostname",
"browser",

@@ -80,5 +81,5 @@ "uri",

"domain name",
"subdomain",
"public suffix"
"public suffix",
"typescript"
]
}

@@ -1,88 +0,138 @@

# tldts [![Build Status][badge-ci]](http://travis-ci.org/remusao/tldts) ![][badge-downloads]
# tldts - Hostname and Domain Parsing using Public Suffix Lists
> `tldts` is a Typescript library to work against complex domain names, subdomains and well-known TLDs. It is a fork of the very good [tld.js](https://github.com/oncletom/tld.js) JavaScript library.
[![NPM](https://nodei.co/npm/tldts.png?downloads=true&downloadRank=true)](https://nodei.co/npm/tldts/)
It answers with accuracy to questions like _what is `mail.google.com`'s domain?_, _what is `a.b.ide.kyoto.jp`'s subdomain?_ and _is `https://big.data`'s TLD a well-known one?_.
[![Build Status][badge-ci]](http://travis-ci.org/remusao/tldts) ![][badge-downloads]
![Coverage Status](https://coveralls.io/repos/github/remusao/tldts/badge.svg?branch=master)
[![Known Vulnerabilities](https://snyk.io/test/github/remusao/tldts/badge.svg?targetFile=package.json)](https://snyk.io/test/github/remusao/tldts?targetFile=package.json)
`tldts` [runs fast](#performances) (even faster than the original tld.js library thanks to additional optimizations), is fully tested and is safe to use in the browser (UMD bundles are provided as well as an ES6 module version and Typescripts type declarations). Because it relies on Mozilla's [public suffix list][], now is a good time to say _thank you_ Mozilla!
> `tldts` is a Typescript library to parse hostnames, domains, public suffixes, top-level domains and subdomains from URLs.
**Features**:
1. **Fastest library** around (up to 2M operations per second, that's 3 orders of
magnitude faster than the most popular library out there)
2. Written in **TypeScript**, ships with `umd`, `esm`, `cjs` bundles and *type definitions*
3. Full Unicode/IDNA support
4. Support both ICANN and Private suffixes
5. Ships with continuously updated version of the list: it works *out of the box*!
6. Support parsing full URLs or hostnames
7. Small bundles and small memory footprint
# Install
```bash
# Regular install
npm install --save tldts
```
It ships by default with the latest version of the public suffix lists, but you
can provide your own version (more up-to-date or modified) using the `update`
method.
# Usage
# Using It
```js
const { parse } = require('tldts');
const tldts = require('tldts');
// Retrieving hostname related informations of a given URL
parse('http://www.writethedocs.org/conf/eu/2017/');
// { domain: 'writethedocs.org',
// hostname: 'www.writethedocs.org',
// isIcann: true,
// isIp: false,
// isPrivate: false,
// publicSuffix: 'org',
// subdomain: 'www' }
```
⬇️ Read the documentation _below_ to find out the available _functions_.
# API
## `tldts.parse()`
* `tldts.parse(url | hostname, options)`
* `tldts.getHostname(url | hostname, options)`
* `tldts.getDomain(url | hostname, options)`
* `tldts.getPublicSuffix(url | hostname, options)`
* `tldts.getSubdomain(url, | hostname, options)`
This methods returns handy **properties about a URL or a hostname**.
The behavior of `tldts` can be customized using an `options` argument for all
the functions exposed as part of the public API.
```js
{
// Use suffixes from ICANN section (default: true)
allowIcannDomains: boolean;
// Use suffixes from Private section (default: false)
allowPrivateDomains: boolean;
// Extract and validate hostname (default: true)
extractHostname: boolean;
// Specifies extra valid suffixes (default: null)
validHosts: string[] | null;
}
```
The `parse` method returns handy **properties about a URL or a hostname**.
```js
const tldts = require('tldts');
tldts.parse('https://spark-public.s3.amazonaws.com/dataanalysis/loansData.csv');
// { host: 'spark-public.s3.amazonaws.com',
// isValid: true,
// { domain: 'amazonaws.com',
// hostname: 'spark-public.s3.amazonaws.com',
// isIcann: true,
// isIp: false,
// isPrivate: false,
// publicSuffix: 'com',
// isIcann: true,
// isPrivate: false,
// domain: 'amazonaws.com',
// subdomain: 'spark-public.s3' }
tldts.parse('https://spark-public.s3.amazonaws.com/dataanalysis/loansData.csv', { allowPrivateDomains: true })
// { host: 'spark-public.s3.amazonaws.com',
// isValid: true,
// { domain: 'spark-public.s3.amazonaws.com',
// hostname: 'spark-public.s3.amazonaws.com',
// isIcann: false,
// isIp: false,
// isPrivate: true,
// publicSuffix: 's3.amazonaws.com',
// isIcann: false,
// isPrivate: true,
// domain: 'spark-public.s3.amazonaws.com',
// subdomain: '' }
tldts.parse('gopher://domain.unknown/');
// { host: 'domain.unknown',
// isValid: true,
// { domain: 'domain.unknown',
// hostname: 'domain.unknown',
// isIcann: false,
// isIp: false,
// isPrivate: true,
// publicSuffix: 'unknown',
// isIcann: false,
// isPrivate: false,
// domain: 'domain.unknown',
// subdomain: '' }
tldts.parse('https://192.168.0.0')
// { host: '192.168.0.0',
// isValid: true,
tldts.parse('https://192.168.0.0') // IPv4
// { domain: null,
// hostname: '192.168.0.0',
// isIcann: null,
// isIp: true,
// isPrivate: null,
// publicSuffix: null,
// subdomain: null }
tldts.parse('https://[::1]') // IPv6
// { domain: null,
// hostname: '::1',
// isIcann: null,
// isIp: true,
// isPrivate: null,
// domain: null,
// publicSuffix: null,
// subdomain: null }
tldts.parse('tldts@emailprovider.co.uk') // email
// { domain: 'emailprovider.co.uk',
// hostname: 'emailprovider.co.uk',
// isIcann: true,
// isIp: false,
// isPrivate: false,
// publicSuffix: 'co.uk',
// subdomain: '' }
```
| Property Name | Type | |
| --- | --- | --- |
| `host` | `String` | `host` part of the input extracted automatically |
| `isValid` | `Boolean` | Is the hostname valid according to the RFC? |
| `publicSuffix` | `String` | |
| `isIcann` | `Boolean` | Does TLD come from public part of the list |
| `isPrivate` | `Boolean` | Does TLD come from private part of the list |
| `domain` | `String` | |
| `subdomain` | `String` | |
| Property Name | Type | Description |
|:-------------- |:------ |:------------------------------------------- |
| `hostname` | `str` | `hostname` of the input extracted automatically |
| `domain` | `str` | Domain (tld + sld) |
| `subdomain` | `str` | Sub domain (what comes after `domain`) |
| `publicSuffix` | `str` | Public Suffix (tld) of `hostname` |
| `isIcann` | `bool` | Does TLD come from ICANN part of the list |
| `isPrivate` | `bool` | Does TLD come from Private part of the list |
| `isIP` | `bool` | Is `hostname` an IP address? |

@@ -95,3 +145,3 @@

### getDomain()
### getDomain(url | hostname, options?)

@@ -101,3 +151,3 @@ Returns the fully qualified domain from a given string.

```javascript
const { getDomain } = tldts;
const { getDomain } = require('tldts');

@@ -113,3 +163,3 @@ getDomain('google.com'); // returns `google.com`

### getSubdomain()
### getSubdomain(url | hostname, options?)

@@ -119,3 +169,3 @@ Returns the complete subdomain for a given string.

```javascript
const { getSubdomain } = tldts;
const { getSubdomain } = require('tldts');

@@ -132,3 +182,3 @@ getSubdomain('google.com'); // returns ``

### getPublicSuffix()
### getPublicSuffix(url | hostname, options?)

@@ -138,3 +188,3 @@ Returns the [public suffix][] for a given string.

```javascript
const { getPublicSuffix } = tldts;
const { getPublicSuffix } = require('tldts');

@@ -149,18 +199,2 @@ getPublicSuffix('google.com'); // returns `com`

### isValidHostname()
Checks if the given string is a valid hostname according to [RFC 1035](https://tools.ietf.org/html/rfc1035).
It does not check if the TLD is _well-known_.
```javascript
const { isValidHostname } = tldts;
isValidHostname('google.com'); // returns `true`
isValidHostname('.google.com'); // returns `false`
isValidHostname('my.fake.domain'); // returns `true`
isValidHostname('localhost'); // returns `true`
isValidHostname('https://user:password@example.co.uk:8080/some/path?and&query#hash'); // returns `false`
isValidHostname('192.168.0.0') // returns `true`
```
# Troubleshooting

@@ -187,71 +221,43 @@

Many libraries offer a list of TLDs. But, are they up-to-date? And how to update them?
`tldts` made the opinionated choice of shipping with a list of suffixes directly
in its bundle. There is currently no mechanism to update the lists yourself, but
we make sure that the version shipped is always up-to-date.
`tldts` bundles a list of known TLDs but this list can become outdated.
This is especially true if the package have not been updated on npm for a while.
If you keep `tldts` updated, the lists should be up-to-date as well!
Thankfully for you, you can pass your own version of the list to the `update`
method of `tldts`. It can be fetched from `https://publicsuffix.org/list/public_suffix_list.dat`:
# Performance
```js
const { update } = require('tldts');
`tldts` is the *fastest JavaScript library* available for parsing
hostnames. It is able to parse up to **2M hostnames per second** on a
modern i7-8550U CPU with Node.js version 11.6.0.
// `tldts` will not fetch the lists for you at the moment, so depending on your
// platform your might use either `fetch` or something else.
update(lists_as_a_string);
```
Please see [this detailed comparison](./comparison/comparison.md) with other available libraries.
Open an issue to request an update of the bundled TLDs.
## Experimental Bundle
# Contributing
`tldts` ships with two bundles, the default one is what you should use and what
is imported out of the box. It makes use of an optimized DAWG (direct acyclic
word graph) data-structure and delivers very good performances. If that is not
enough, you can try the `tldts-experimental` bundle which implements a
*probabilistic data-structure*. It is:
Provide a pull request (with tested code) to include your work in this main project.
Issues may be awaiting for help so feel free to give a hand, with code or ideas.
* Must smaller (in terms of bundle size and memory footprint)
* Loads instantly (no data loading or parsing required)
* Much faster (lookups are up to 1.5-2x faster)
# Performances
The drawback is that there might be some *unlikely* false positive (think bloom filters).
`tldts` is fast, but keep in mind that it might vary depending on your
own use-case. Because the library tried to be smart, the speed can be
drastically different depending on the input (it will be faster if you
provide an already cleaned hostname, compared to a random URL).
For more details, check the documentation from the following files:
* [building](./bin/builders/hashes.js)
* [lookups](./lib/lookup/packed_hashes.ts)
On an Intel i7-6600U (2,60-3,40 GHz) using Node.js `v10.9.0`:
## For already cleaned hostnames
| Methods | ops/sec |
| --- | --- |
| `isValidHostname` | ~`7,500,000` |
| `getHostname` | ~`3,200,000` |
| `getPublicSuffix` | ~`1,100,000` |
| `getDomain` | ~`1,100,000` |
| `getSubdomain` | ~`1,100,000` |
| `parse` | ~`1,000,000` |
## For random URLs
| Methods | ops/sec |
| --- | --- |
| `isValidHostname` | ~`12,000,000` |
| `getHostname` | ~`2,640,000` |
| `getPublicSuffix` | ~`800,000` |
| `getDomain` | ~`760,000` |
| `getSubdomain` | ~`760,000` |
| `parse` | ~`750,000` |
You can measure the performance of `tldts` on your hardware by running the following command:
```bash
npm run benchmark
```
_Notice_: if this is not fast enough for your use-case, please get in touch via an issue so that we can analyze that this is so.
## Contributors
This project exists thanks to all the people who contributed to `tld.js` as well as `tldts`. [[Contribute]](CONTRIBUTING.md).
`tldts` is based upon the excellent `tld.js` library and would not exist without
the many contributors who worked on the project:
<a href="graphs/contributors"><img src="https://opencollective.com/tldjs/contributors.svg?width=890" /></a>
This project would not be possible without the amazing Mozilla's
[public suffix list][]. Thank you for your hard work!
# License

@@ -258,0 +264,0 @@

@@ -1,118 +0,9 @@

import getDomainImpl from './lib/domain';
import isIpImpl from './lib/is-ip';
import isValidHostnameImpl from './lib/is-valid';
import { IOptions, setDefaults } from './lib/options';
import getPublicSuffixImpl from './lib/public-suffix';
import getSubdomainImpl from './lib/subdomain';
import parseImpl, { FLAG, IResult } from './lib/factory';
import suffixLookup from './lib/lookup/suffix-trie';
import { IOptions } from './lib/options';
interface IResult {
// `host` is either a registered name (including but not limited to a
// hostname), or an IP address. IPv4 addresses must be in dot-decimal
// notation, and IPv6 addresses must be enclosed in brackets ([]). This is
// directly extracted from the input URL.
host: string | null;
// Is `host` a valid hostname?
isValid: boolean | null;
// Is `host` an IP? (IPv4 or IPv6)
isIp: boolean;
// `host` split between subdomain, domain and its public suffix (if any)
subdomain: string | null;
domain: string | null;
publicSuffix: string | null;
// Specifies if `publicSuffix` comes from the ICANN or PRIVATE section of the list
isIcann: boolean | null;
isPrivate: boolean | null;
export function parse(url: string, options?: Partial<IOptions>): IResult {
return parseImpl(url, FLAG.ALL, suffixLookup, options);
}
// Flags representing steps in the `parse` function. They are used to implement
// an early stop mechanism (simulating some form of laziness) to avoid doing
// more work than necessary to perform a given action (e.g.: we don't need to
// extract the domain and subdomain if we are only interested in public suffix).
const enum FLAG {
HOST,
IS_VALID,
IS_IP,
PUBLIC_SUFFIX,
DOMAIN,
SUB_DOMAIN,
ALL,
}
export function parse(
url: string,
partialOptions?: Partial<IOptions>,
step: FLAG = FLAG.ALL,
): IResult {
const options: IOptions = setDefaults(partialOptions);
const result: IResult = {
domain: null,
host: null,
isIcann: null,
isIp: false,
isPrivate: null,
isValid: null,
publicSuffix: null,
subdomain: null,
};
// Extract hostname from `url`
const host = options.extractHostname(url);
if (host === null) {
result.isIp = false;
result.isValid = false;
return result;
}
result.host = host.toLowerCase();
if (step === FLAG.HOST) {
return result;
}
// Check if `host` is a valid ip address
result.isIp = isIpImpl(result.host);
if (result.isIp) {
result.isValid = true;
return result;
}
if (step === FLAG.IS_IP) {
return result;
}
// Check if `host` is valid
result.isValid = isValidHostnameImpl(result.host, options);
if (result.isValid === false || step === FLAG.IS_VALID) {
return result;
}
// Extract public suffix
const publicSuffixResult = getPublicSuffixImpl(result.host, options);
result.publicSuffix = publicSuffixResult.publicSuffix;
result.isIcann = publicSuffixResult.isIcann;
result.isPrivate = publicSuffixResult.isIcann === false;
if (step === FLAG.PUBLIC_SUFFIX) {
return result;
}
// Extract domain
result.domain = getDomainImpl(result.publicSuffix, result.host, options);
if (step === FLAG.DOMAIN) {
return result;
}
// Extract subdomain
result.subdomain = getSubdomainImpl(result.host, result.domain);
return result;
}
export function isValidHostname(
url: string,
options?: Partial<IOptions>,
): boolean {
return isValidHostnameImpl(url, setDefaults(options));
}
export function getPublicSuffix(

@@ -122,3 +13,3 @@ url: string,

): string | null {
return parse(url, options, FLAG.PUBLIC_SUFFIX).publicSuffix;
return parseImpl(url, FLAG.PUBLIC_SUFFIX, suffixLookup, options).publicSuffix;
}

@@ -130,3 +21,3 @@

): string | null {
return parse(url, options, FLAG.DOMAIN).domain;
return parseImpl(url, FLAG.DOMAIN, suffixLookup, options).domain;
}

@@ -138,3 +29,3 @@

): string | null {
return parse(url, options, FLAG.SUB_DOMAIN).subdomain;
return parseImpl(url, FLAG.SUB_DOMAIN, suffixLookup, options).subdomain;
}

@@ -146,3 +37,3 @@

): string | null {
return parse(url, options, FLAG.HOST).host;
return parseImpl(url, FLAG.HOSTNAME, suffixLookup, options).hostname;
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc