Skip to content

Commit

Permalink
es6. Closes #17
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Nov 1, 2015
1 parent 571cf0d commit 260bb6c
Show file tree
Hide file tree
Showing 7 changed files with 358 additions and 358 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
language: node_js

node_js:
- 0.10
- 4.0
- 4
- 5

sudo: false

128 changes: 61 additions & 67 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
'use strict';

// Load modules

var Hoek = require('hoek');
var Boom = require('boom');
var Regex = require('./regex');
var Segment = require('./segment');
const Hoek = require('hoek');
const Boom = require('boom');
const Regex = require('./regex');
const Segment = require('./segment');


// Declare internals

var internals = {
const internals = {
pathRegex: Regex.generate(),
defaults: {
isCaseSensitive: true
Expand All @@ -34,21 +36,19 @@ exports.Router = internals.Router = function (options) {

internals.Router.prototype.add = function (config, route) {

var self = this;

var method = config.method.toLowerCase();
const method = config.method.toLowerCase();

var vhost = config.vhost || '*';
const vhost = config.vhost || '*';
if (vhost !== '*') {
self.vhosts = self.vhosts || {};
self.vhosts[vhost] = self.vhosts[vhost] || {};
this.vhosts = this.vhosts || {};
this.vhosts[vhost] = this.vhosts[vhost] || {};
}

var table = (vhost === '*' ? self.routes : self.vhosts[vhost]);
const table = (vhost === '*' ? this.routes : this.vhosts[vhost]);
table[method] = table[method] || { routes: [], router: new Segment() };

var analysis = config.analysis || this.analyze(config.path);
var record = {
const analysis = config.analysis || this.analyze(config.path);
const record = {
path: config.path,
route: route || config.path,
segments: analysis.segments,
Expand All @@ -63,7 +63,7 @@ internals.Router.prototype.add = function (config, route) {
table[method].routes.push(record);
table[method].routes.sort(internals.sort);

var last = record.segments[record.segments.length - 1];
const last = record.segments[record.segments.length - 1];
if (last.empty) {
table[method].router.add(analysis.segments.slice(0, -1), record);
}
Expand All @@ -87,10 +87,10 @@ internals.Router.prototype.special = function (type, route) {

internals.Router.prototype.route = function (method, path, hostname) {

var segments = path.split('/').slice(1);
const segments = path.split('/').slice(1);

var vhost = (this.vhosts && hostname && this.vhosts[hostname]);
var route = (vhost && this._lookup(path, segments, vhost, method)) ||
const vhost = (this.vhosts && hostname && this.vhosts[hostname]);
const route = (vhost && this._lookup(path, segments, vhost, method)) ||
this._lookup(path, segments, this.routes, method) ||
(method === 'head' && vhost && this._lookup(path, segments, vhost, 'get')) ||
(method === 'head' && this._lookup(path, segments, this.routes, 'get')) ||
Expand All @@ -105,35 +105,35 @@ internals.Router.prototype.route = function (method, path, hostname) {

internals.Router.prototype._lookup = function (path, segments, table, method) {

var set = table[method];
const set = table[method];
if (!set) {
return null;
}

var match = set.router.lookup(path, segments, this.settings);
const match = set.router.lookup(path, segments, this.settings);
if (!match) {
return null;
}

var assignments = {};
var array = [];
for (var i = 0, il = match.array.length; i < il; ++i) {
var name = match.record.params[i];
var value = match.array[i];
const assignments = {};
const array = [];
for (let i = 0; i < match.array.length; ++i) {
const name = match.record.params[i];
let value = match.array[i];
if (value) {
value = internals.decode(value);
if (value.isBoom) {
return this.specials.badRequest || value;
}

if (assignments[name] !== undefined) {
assignments[name] += '/' + value;
assignments[name] = assignments[name] + '/' + value;
}
else {
assignments[name] = value;
}

if (i + 1 === il ||
if (i + 1 === match.array.length ||
name !== match.record.params[i + 1]) {

array.push(assignments[name]);
Expand Down Expand Up @@ -163,20 +163,14 @@ internals.Router.prototype.normalize = function (path) {

// Uppercase %encoded values

var uppercase = path.replace(/%[0-9a-fA-F][0-9a-fA-F]/g, function (encoded) {

return encoded.toUpperCase();
});
const uppercase = path.replace(/%[0-9a-fA-F][0-9a-fA-F]/g, (encoded) => encoded.toUpperCase());

// Decode non-reserved path characters: a-z A-Z 0-9 _!$&'()*+,;=:@-.~
// ! (%21) $ (%24) & (%26) ' (%27) ( (%28) ) (%29) * (%2A) + (%2B) , (%2C) - (%2D) . (%2E)
// 0-9 (%30-39) : (%3A) ; (%3B) = (%3D)
// @ (%40) A-Z (%41-5A) _ (%5F) a-z (%61-7A) ~ (%7E)

var decoded = uppercase.replace(/%(?:2[146-9A-E]|3[\dABD]|4[\dA-F]|5[\dAF]|6[1-9A-F]|7[\dAE])/g, function (encoded) {

return String.fromCharCode(parseInt(encoded.substring(1), 16));
});
const decoded = uppercase.replace(/%(?:2[146-9A-E]|3[\dABD]|4[\dA-F]|5[\dAF]|6[1-9A-F]|7[\dAE])/g, (encoded) => String.fromCharCode(parseInt(encoded.substring(1), 16)));

path = decoded;
}
Expand All @@ -190,13 +184,13 @@ internals.Router.prototype.analyze = function (path) {
Hoek.assert(internals.pathRegex.validatePath.test(path), 'Invalid path:', path);
Hoek.assert(!internals.pathRegex.validatePathEncoded.test(path), 'Path cannot contain encoded non-reserved path characters:', path);

var pathParts = path.split('/');
var segments = [];
var params = [];
var fingers = [];
const pathParts = path.split('/');
const segments = [];
const params = [];
const fingers = [];

for (var i = 1, il = pathParts.length; i < il; ++i) { // Skip first empty segment
var segment = pathParts[i];
for (let i = 1; i < pathParts.length; ++i) { // Skip first empty segment
let segment = pathParts[i];

// Literal

Expand All @@ -209,21 +203,21 @@ internals.Router.prototype.analyze = function (path) {

// Parameter

var parts = internals.parseParams(segment);
const parts = internals.parseParams(segment);
if (parts.length === 1) {

// Simple parameter

var item = parts[0];
const item = parts[0];
Hoek.assert(params.indexOf(item.name) === -1, 'Cannot repeat the same parameter name:', item.name, 'in:', path);
params.push(item.name);

if (item.wilcard) {
if (item.count) {
for (var m = 0; m < item.count; ++m) {
for (let j = 0; j < item.count; ++j) {
fingers.push('?');
segments.push({});
if (m) {
if (j) {
params.push(item.name);
}
}
Expand All @@ -242,27 +236,27 @@ internals.Router.prototype.analyze = function (path) {

// Mixed parameter

var seg = {
const seg = {
length: parts.length,
first: typeof parts[0] !== 'string',
segments: []
};

var finger = '';
var regex = '^';
for (var p = 0, pl = parts.length; p < pl; ++p) {
var part = parts[p];
let finger = '';
let regex = '^';
for (let j = 0; j < parts.length; ++j) {
const part = parts[j];
if (typeof part === 'string') {
finger += part;
regex += Hoek.escapeRegex(part);
finger = finger + part;
regex = regex + Hoek.escapeRegex(part);
seg.segments.push(part);
}
else {
Hoek.assert(params.indexOf(part.name) === -1, 'Cannot repeat the same parameter name:', part.name, 'in:', path);
params.push(part.name);

finger += '?';
regex += '(.' + (part.empty ? '*' : '+') + ')';
finger = finger + '?';
regex = regex + '(.' + (part.empty ? '*' : '+') + ')';
}
}

Expand All @@ -282,8 +276,8 @@ internals.Router.prototype.analyze = function (path) {

internals.parseParams = function (segment) {

var parts = [];
segment.replace(internals.pathRegex.parseParam, function (match, literal, name, wilcard, count, empty) {
const parts = [];
segment.replace(internals.pathRegex.parseParam, (match, literal, name, wilcard, count, empty) => {

if (literal) {
parts.push(literal);
Expand All @@ -306,25 +300,25 @@ internals.parseParams = function (segment) {

internals.Router.prototype.table = function (host) {

var result = [];
var collect = function (table) {
const result = [];
const collect = (table) => {

if (!table) {
return;
}

Object.keys(table).forEach(function (method) {
Object.keys(table).forEach((method) => {

table[method].routes.forEach(function (record) {
table[method].routes.forEach((record) => {

result.push(record.route);
});
});
};

if (this.vhosts) {
var vhosts = host ? [].concat(host) : Object.keys(this.vhosts);
for (var i = 0, il = vhosts.length; i < il; ++i) {
const vhosts = host ? [].concat(host) : Object.keys(this.vhosts);
for (let i = 0; i < vhosts.length; ++i) {
collect(this.vhosts[vhosts[i]]);
}
}
Expand All @@ -337,17 +331,17 @@ internals.Router.prototype.table = function (host) {

internals.sort = function (a, b) {

var aFirst = -1;
var bFirst = 1;
const aFirst = -1;
const bFirst = 1;

var as = a.segments;
var bs = b.segments;
const as = a.segments;
const bs = b.segments;

if (as.length !== bs.length) {
return (as.length > bs.length ? bFirst : aFirst);
}

for (var i = 0, il = as.length; ; ++i) {
for (let i = 0; ; ++i) {
if (as[i].literal) {
if (bs[i].literal) {
if (as[i].literal === bs[i].literal) {
Expand Down
36 changes: 19 additions & 17 deletions lib/regex.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use strict';

// Load modules


// Declare internals

var internals = {};
const internals = {};


exports.generate = function () {
Expand All @@ -16,31 +18,31 @@ exports.generate = function () {
/{param*}
*/

var empty = '(?:^\\/$)';
const empty = '(?:^\\/$)';

var legalChars = '[\\w\\!\\$&\'\\(\\)\\*\\+\\,;\\=\\:@\\-\\.~]';
var encoded = '%[A-F0-9]{2}';
const legalChars = '[\\w\\!\\$&\'\\(\\)\\*\\+\\,;\\=\\:@\\-\\.~]';
const encoded = '%[A-F0-9]{2}';

var literalChar = '(?:' + legalChars + '|' + encoded + ')';
var literal = literalChar + '+';
var literalOptional = literalChar + '*';
const literalChar = '(?:' + legalChars + '|' + encoded + ')';
const literal = literalChar + '+';
const literalOptional = literalChar + '*';

var midParam = '(?:\\{\\w+(?:\\*[1-9]\\d*)?\\})'; // {p}, {p*2}
var endParam = '(?:\\/(?:\\{\\w+(?:(?:\\*(?:[1-9]\\d*)?)|(?:\\?))?\\})?)?'; // {p}, {p*2}, {p*}, {p?}
const midParam = '(?:\\{\\w+(?:\\*[1-9]\\d*)?\\})'; // {p}, {p*2}
const endParam = '(?:\\/(?:\\{\\w+(?:(?:\\*(?:[1-9]\\d*)?)|(?:\\?))?\\})?)?'; // {p}, {p*2}, {p*}, {p?}

var partialParam = '(?:\\{\\w+\\??\\})'; // {p}, {p?}
var mixedParam = '(?:(?:' + literal + partialParam + ')+' + literalOptional + ')|(?:' + partialParam + '(?:' + literal + partialParam + ')+' + literalOptional + ')|(?:' + partialParam + literal + ')';
const partialParam = '(?:\\{\\w+\\??\\})'; // {p}, {p?}
const mixedParam = '(?:(?:' + literal + partialParam + ')+' + literalOptional + ')|(?:' + partialParam + '(?:' + literal + partialParam + ')+' + literalOptional + ')|(?:' + partialParam + literal + ')';

var segmentContent = '(?:' + literal + '|' + midParam + '|' + mixedParam + ')';
var segment = '\\/' + segmentContent;
var segments = '(?:' + segment + ')*';
const segmentContent = '(?:' + literal + '|' + midParam + '|' + mixedParam + ')';
const segment = '\\/' + segmentContent;
const segments = '(?:' + segment + ')*';

var path = '(?:^' + segments + endParam + '$)';
const path = '(?:^' + segments + endParam + '$)';

// 1:literal 2:name 3:* 4:count 5:?
var parseParam = '(' + literal + ')|(?:\\{(\\w+)(?:(\\*)(\\d+)?)?(\\?)?\\})';
const parseParam = '(' + literal + ')|(?:\\{(\\w+)(?:(\\*)(\\d+)?)?(\\?)?\\})';

var expressions = {
const expressions = {
parseParam: new RegExp(parseParam, 'g'),
validatePath: new RegExp(empty + '|' + path),
validatePathEncoded: /%(?:2[146-9A-E]|3[\dABD]|4[\dA-F]|5[\dAF]|6[1-9A-F]|7[\dAE])/g
Expand Down
Loading

0 comments on commit 260bb6c

Please sign in to comment.