Skip to content

Commit

Permalink
Merge pull request #14 from oncletom/feature-14
Browse files Browse the repository at this point in the history
add domainExists()
  • Loading branch information
Oncle Tom committed Jan 8, 2013
2 parents c4e459a + 53c1a32 commit 0d132ff
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 36 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,26 @@ Returns the fully qualified domain from a host string.
```javascript
tld.getDomain('google.com'); // returns `google.com`
tld.getDomain('fr.google.com'); // returns `google.com`
tld.getDomain('google.co.uk'); // returns `google.co.uk`
tld.getDomain('fr.google.google'); // returns `google.google`
tld.getDomain('foo.google.co.uk'); // returns `google.co.uk`
tld.getDomain('t.co'); // returns `t.co`
tld.getDomain('fr.t.co'); // returns `t.co`
```

### tldExists()

Checks if the TLD is valid for a given host.

```javascript
tld.tldExists('google.com'); // returns `true`
tld.tldExists('google.google'); // returns `false` (not an explicit registered TLD)
tld.tldexists('com'); // returns `true`
tld.tldexists('uk'); // returns `true`
tld.tldexists('co.uk'); // returns `true` (because `uk` is a valid TLD)
tld.tldexists('amazon.fancy.uk'); // returns `true` (still because `uk` is a valid TLD)
tld.tldexists('amazon.co.uk'); // returns `true` (still because `uk` is a valid TLD)
```

### isValid()

Checks if the host string is valid.
Expand Down
67 changes: 45 additions & 22 deletions lib/tld.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ var Rule = require(__dirname + '/rule.js');
* Useable methods are those documented with an @api in JSDoc
* See README.md for more explainations on how to use this stuff.
*/
function tld (){
function tld () {
/*jshint validthis: true */
this.rules = [];
}

tld.init = function init() {
tld.init = function init () {
return new tld();
};

Expand All @@ -27,15 +27,15 @@ tld.init = function init() {
* @param rules {Array} List of rules used to work on
* @return {Object} Candidate object, with a normal and exception state
*/
tld.getCandidateRule = function getCandidateRule(host, rules) {
tld.getCandidateRule = function getCandidateRule (host, rules) {
var rule = {'normal': null, 'exception': null};

rules.some(function(r){
rules.some(function (r) {
var pattern;

//sld matching? escape the loop immediately (except if it's an exception)
if ('.'+host === r.getNormalXld()){
if (r.exception === true){
if ('.' + host === r.getNormalXld()) {
if (r.exception === true) {
rule.normal = r;
}

Expand All @@ -46,7 +46,7 @@ tld.getCandidateRule = function getCandidateRule(host, rules) {
//if it's an exception, we want to loop a bit more to a normal rule
pattern = '.+' + r.getNormalPattern() + '$';

if ((new RegExp(pattern)).test(host)){
if ((new RegExp(pattern)).test(host)) {
rule[r.exception ? 'exception' : 'normal'] = r;
return !r.exception;
}
Expand All @@ -68,44 +68,44 @@ tld.getCandidateRule = function getCandidateRule(host, rules) {
* @param tld {String} Top-Level-Domain string
* @return {Array} Rules subset
*/
tld.prototype.getRulesForTld = function getRulesForTld(tld, default_rule){
tld.prototype.getRulesForTld = function getRulesForTld (tld, default_rule) {
var exception = '!';
var wildcard = '*';
var append_tld_rule = true;
var rules = this.rules[tld];

// Already parsed
if (Array.isArray(rules)){
if (Array.isArray(rules)) {
return rules;
}

// Nothing found, apply some default value
if (!rules){
if (!rules) {
return default_rule ? [ default_rule ] : [];
}

// Parsing needed
rules = rules.split('|').map(function transformAsRule(sld){
rules = rules.split('|').map(function transformAsRule (sld) {
var first_bit = sld[0];

if (first_bit === exception || first_bit === wildcard){
if (first_bit === exception || first_bit === wildcard) {
sld = sld.slice(1);

if (!sld){
if (!sld) {
append_tld_rule = false;
}
}

return new Rule({
"firstLevel": tld,
"firstLevel": tld,
"secondLevel": sld,
"exception": first_bit === exception,
"wildcard": first_bit === wildcard
"exception": first_bit === exception,
"wildcard": first_bit === wildcard
});
});

// Always prepend to make it the latest rule to be applied
if (append_tld_rule){
if (append_tld_rule) {
rules.unshift(new Rule({
"firstLevel": tld
}));
Expand All @@ -116,17 +116,40 @@ tld.prototype.getRulesForTld = function getRulesForTld(tld, default_rule){
return rules;
};

/**
* Checks if the TLD exists for a given host
*
* @api
* @param {string} host
* @return {boolean}
*/
tld.prototype.tldExists = function tldExists(host){
var hostTld;

host = (host+'').trim().toLocaleLowerCase();

// Easy case, it's a TLD
if (this.rules[host]){
return true;
}

// Popping only the TLD of the hostname
hostTld = host.split('.').pop();

return this.rules[hostTld] !== undefined;
};

/**
* Detects the domain based on rules and upon and a host string
*
* @api
* @param {string} host
* @return {String}
*/
tld.prototype.getDomain = function getDomain(host) {
tld.prototype.getDomain = function getDomain (host) {
var domain = null, hostTld, rules, rule;

if (this.isValid(host) === false){
if (this.isValid(host) === false) {
return null;
}

Expand All @@ -135,11 +158,11 @@ tld.prototype.getDomain = function getDomain(host) {
rules = this.getRulesForTld(hostTld, new Rule({"firstLevel": hostTld}));
rule = tld.getCandidateRule(host, rules);

if (rule === null){
if (rule === null) {
return null;
}

host.replace(new RegExp(rule.getPattern()), function(m, d){
host.replace(new RegExp(rule.getPattern()), function (m, d) {
domain = d;
});

Expand All @@ -157,7 +180,7 @@ tld.prototype.getDomain = function getDomain(host) {
* @param host {String}
* @return {Boolean}
*/
tld.prototype.isValid = function isValid(host){
tld.prototype.isValid = function isValid (host) {
return !(typeof host !== 'string' || host.indexOf('.') === -1 || host[0] === '.');
};

Expand Down
49 changes: 36 additions & 13 deletions test/tld.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,78 @@
var tld = require('../index.js');
var expect = require('expect.js');

suite('tld.js', function(){
suite('Basics', function(){
test('Rules are already loaded', function(){
suite('tld.js', function () {
suite('Basics', function () {
test('Rules are already loaded', function () {
expect(tld.rules).to.be.an(Object);
expect(Object.keys(tld.rules).length).to.be.above(0);
});
});

suite('#isValid()', function(){
test('Good one', function(){
suite('#isValid()', function () {
test('Good ones', function () {
expect(tld.isValid('')).to.be(false);
expect(tld.isValid('google.com')).to.be(true);
expect(tld.isValid('miam.google.com')).to.be(true);
expect(tld.isValid('miam.miam.google.com')).to.be(true);
});
test('Invalid type', function(){
test('Invalid types', function () {
expect(tld.isValid(null)).to.be(false);
expect(tld.isValid(undefined)).to.be(false);
expect(tld.isValid(0)).to.be(false);
expect(tld.isValid([])).to.be(false);
expect(tld.isValid({})).to.be(false);
expect(tld.isValid(function(){})).to.be(false);
expect(tld.isValid(function () {
})).to.be(false);
});

test('Invalid notation', function(){
test('Invalid notation', function () {
expect(tld.isValid('.google.com')).to.be(false);
expect(tld.isValid('.com')).to.be(false);
});

test('Dot-less hostname', function(){
test('Dot-less hostname', function () {
expect(tld.isValid('localhost')).to.be(false);
expect(tld.isValid('google')).to.be(false);
});
});

suite('#getDomain()', function(){
test('basic domains', function(){
suite('#getDomain()', function () {
test('basic domains', function () {
expect(tld.getDomain('google.com')).to.be('google.com');
expect(tld.getDomain('t.co')).to.be('t.co');
});

test('composed ', function() {
test('composed ', function () {
expect(tld.getDomain('google.co.uk')).to.be('google.co.uk');
});

test('subdomains', function() {
test('subdomains', function () {
expect(tld.getDomain('fr.google.com')).to.be('google.com');
expect(tld.getDomain('foo.google.co.uk')).to.be('google.co.uk');
expect(tld.getDomain('fr.t.co')).to.be('t.co');
});
});

suite('#tldExists', function () {
test('existing TLD', function () {
expect(tld.tldExists('com')).to.be(true);
expect(tld.tldExists('example.com')).to.be(true);
expect(tld.tldExists('co.uk')).to.be(true);
expect(tld.tldExists('amazon.co.uk')).to.be(true);
expect(tld.tldExists('台灣')).to.be(true);
expect(tld.tldExists('台灣.台灣')).to.be(true);
});

test('unexisting TLD', function () {
expect(tld.tldExists('con')).to.be(false);
expect(tld.tldExists('example.con')).to.be(false);
expect(tld.tldExists('go')).to.be(false);
expect(tld.tldExists('チーズ')).to.be(false);
});

test('they cannot be verified', function(){
expect(tld.tldExists('uk.com')).to.be(true);
});
});
});

0 comments on commit 0d132ff

Please sign in to comment.