1 | # psl (Public Suffix List)
|
2 |
|
3 | [![Node.js CI](https://github.com/lupomontero/psl/actions/workflows/node.js.yml/badge.svg)](https://github.com/lupomontero/psl/actions/workflows/node.js.yml)
|
4 |
|
5 | `psl` is a `JavaScript` domain name parser based on the
|
6 | [Public Suffix List](https://publicsuffix.org/).
|
7 |
|
8 | This implementation is tested against the
|
9 | [test data hosted by Mozilla](http://mxr.mozilla.org/mozilla-central/source/netwerk/test/unit/data/test_psl.txt?raw=1)
|
10 | and kindly provided by [Comodo](https://www.comodo.com/).
|
11 |
|
12 | Cross browser testing provided by
|
13 | [<img alt="BrowserStack" width="160" src="./browserstack-logo.svg" />](https://www.browserstack.com/)
|
14 |
|
15 | ## What is the Public Suffix List?
|
16 |
|
17 | The Public Suffix List is a cross-vendor initiative to provide an accurate list
|
18 | of domain name suffixes.
|
19 |
|
20 | The Public Suffix List is an initiative of the Mozilla Project, but is
|
21 | maintained as a community resource. It is available for use in any software,
|
22 | but was originally created to meet the needs of browser manufacturers.
|
23 |
|
24 | A "public suffix" is one under which Internet users can directly register names.
|
25 | Some examples of public suffixes are ".com", ".co.uk" and "pvt.k12.wy.us". The
|
26 | Public Suffix List is a list of all known public suffixes.
|
27 |
|
28 | Source: http://publicsuffix.org
|
29 |
|
30 |
|
31 | ## Installation
|
32 |
|
33 | ### Node.js
|
34 |
|
35 | ```sh
|
36 | npm install --save psl
|
37 | ```
|
38 |
|
39 | ### Browser
|
40 |
|
41 | Download [psl.min.js](https://raw.githubusercontent.com/lupomontero/psl/master/dist/psl.min.js)
|
42 | and include it in a script tag.
|
43 |
|
44 | ```html
|
45 | <script src="psl.min.js"></script>
|
46 | ```
|
47 |
|
48 | This script is browserified and wrapped in a [umd](https://github.com/umdjs/umd)
|
49 | wrapper so you should be able to use it standalone or together with a module
|
50 | loader.
|
51 |
|
52 | ## API
|
53 |
|
54 | ### `psl.parse(domain)`
|
55 |
|
56 | Parse domain based on Public Suffix List. Returns an `Object` with the following
|
57 | properties:
|
58 |
|
59 | * `tld`: Top level domain (this is the _public suffix_).
|
60 | * `sld`: Second level domain (the first private part of the domain name).
|
61 | * `domain`: The domain name is the `sld` + `tld`.
|
62 | * `subdomain`: Optional parts left of the domain.
|
63 |
|
64 | #### Example:
|
65 |
|
66 | ```js
|
67 | var psl = require('psl');
|
68 |
|
69 | // Parse domain without subdomain
|
70 | var parsed = psl.parse('google.com');
|
71 | console.log(parsed.tld); // 'com'
|
72 | console.log(parsed.sld); // 'google'
|
73 | console.log(parsed.domain); // 'google.com'
|
74 | console.log(parsed.subdomain); // null
|
75 |
|
76 | // Parse domain with subdomain
|
77 | var parsed = psl.parse('www.google.com');
|
78 | console.log(parsed.tld); // 'com'
|
79 | console.log(parsed.sld); // 'google'
|
80 | console.log(parsed.domain); // 'google.com'
|
81 | console.log(parsed.subdomain); // 'www'
|
82 |
|
83 | // Parse domain with nested subdomains
|
84 | var parsed = psl.parse('a.b.c.d.foo.com');
|
85 | console.log(parsed.tld); // 'com'
|
86 | console.log(parsed.sld); // 'foo'
|
87 | console.log(parsed.domain); // 'foo.com'
|
88 | console.log(parsed.subdomain); // 'a.b.c.d'
|
89 | ```
|
90 |
|
91 | ### `psl.get(domain)`
|
92 |
|
93 | Get domain name, `sld` + `tld`. Returns `null` if not valid.
|
94 |
|
95 | #### Example:
|
96 |
|
97 | ```js
|
98 | var psl = require('psl');
|
99 |
|
100 | // null input.
|
101 | psl.get(null); // null
|
102 |
|
103 | // Mixed case.
|
104 | psl.get('COM'); // null
|
105 | psl.get('example.COM'); // 'example.com'
|
106 | psl.get('WwW.example.COM'); // 'example.com'
|
107 |
|
108 | // Unlisted TLD.
|
109 | psl.get('example'); // null
|
110 | psl.get('example.example'); // 'example.example'
|
111 | psl.get('b.example.example'); // 'example.example'
|
112 | psl.get('a.b.example.example'); // 'example.example'
|
113 |
|
114 | // TLD with only 1 rule.
|
115 | psl.get('biz'); // null
|
116 | psl.get('domain.biz'); // 'domain.biz'
|
117 | psl.get('b.domain.biz'); // 'domain.biz'
|
118 | psl.get('a.b.domain.biz'); // 'domain.biz'
|
119 |
|
120 | // TLD with some 2-level rules.
|
121 | psl.get('uk.com'); // null);
|
122 | psl.get('example.uk.com'); // 'example.uk.com');
|
123 | psl.get('b.example.uk.com'); // 'example.uk.com');
|
124 |
|
125 | // More complex TLD.
|
126 | psl.get('c.kobe.jp'); // null
|
127 | psl.get('b.c.kobe.jp'); // 'b.c.kobe.jp'
|
128 | psl.get('a.b.c.kobe.jp'); // 'b.c.kobe.jp'
|
129 | psl.get('city.kobe.jp'); // 'city.kobe.jp'
|
130 | psl.get('www.city.kobe.jp'); // 'city.kobe.jp'
|
131 |
|
132 | // IDN labels.
|
133 | psl.get('食狮.com.cn'); // '食狮.com.cn'
|
134 | psl.get('食狮.公司.cn'); // '食狮.公司.cn'
|
135 | psl.get('www.食狮.公司.cn'); // '食狮.公司.cn'
|
136 |
|
137 | // Same as above, but punycoded.
|
138 | psl.get('xn--85x722f.com.cn'); // 'xn--85x722f.com.cn'
|
139 | psl.get('xn--85x722f.xn--55qx5d.cn'); // 'xn--85x722f.xn--55qx5d.cn'
|
140 | psl.get('www.xn--85x722f.xn--55qx5d.cn'); // 'xn--85x722f.xn--55qx5d.cn'
|
141 | ```
|
142 |
|
143 | ### `psl.isValid(domain)`
|
144 |
|
145 | Check whether a domain has a valid Public Suffix. Returns a `Boolean` indicating
|
146 | whether the domain has a valid Public Suffix.
|
147 |
|
148 | #### Example
|
149 |
|
150 | ```js
|
151 | var psl = require('psl');
|
152 |
|
153 | psl.isValid('google.com'); // true
|
154 | psl.isValid('www.google.com'); // true
|
155 | psl.isValid('x.yz'); // false
|
156 | ```
|
157 |
|
158 |
|
159 | ## Testing and Building
|
160 |
|
161 | Test are written using [`mocha`](https://mochajs.org/) and can be
|
162 | run in two different environments: `node` and `phantomjs`.
|
163 |
|
164 | ```sh
|
165 | # This will run `eslint`, `mocha` and `karma`.
|
166 | npm test
|
167 |
|
168 | # Individual test environments
|
169 | # Run tests in node only.
|
170 | ./node_modules/.bin/mocha test
|
171 | # Run tests in phantomjs only.
|
172 | ./node_modules/.bin/karma start ./karma.conf.js --single-run
|
173 |
|
174 | # Build data (parse raw list) and create dist files
|
175 | npm run build
|
176 | ```
|
177 |
|
178 | Feel free to fork if you see possible improvements!
|
179 |
|
180 |
|
181 | ## Acknowledgements
|
182 |
|
183 | * Mozilla Foundation's [Public Suffix List](https://publicsuffix.org/)
|
184 | * Thanks to Rob Stradling of [Comodo](https://www.comodo.com/) for providing
|
185 | test data.
|
186 | * Inspired by [weppos/publicsuffix-ruby](https://github.com/weppos/publicsuffix-ruby)
|
187 |
|
188 |
|
189 | ## License
|
190 |
|
191 | The MIT License (MIT)
|
192 |
|
193 | Copyright (c) 2017 Lupo Montero <lupomontero@gmail.com>
|
194 |
|
195 | Permission is hereby granted, free of charge, to any person obtaining a copy
|
196 | of this software and associated documentation files (the "Software"), to deal
|
197 | in the Software without restriction, including without limitation the rights
|
198 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
199 | copies of the Software, and to permit persons to whom the Software is
|
200 | furnished to do so, subject to the following conditions:
|
201 |
|
202 | The above copyright notice and this permission notice shall be included in
|
203 | all copies or substantial portions of the Software.
|
204 |
|
205 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
206 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
207 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
208 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
209 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
210 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
211 | THE SOFTWARE.
|