Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated so the query parameter value of zero is valid. #36

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 122 additions & 120 deletions lib/generator.js
Original file line number Diff line number Diff line change
@@ -1,155 +1,157 @@
var _ = require('lodash');
var url = require('url');
var querystring = require('querystring');
var BasePlugin = require('mixdown-app').Plugin;

if (typeof (global) === 'undefined') {
var global = typeof (window) === 'undefined' ? {} : window;
if (typeof(global) === 'undefined') {
var global = typeof(window) === 'undefined' ? {} : window;
}

module.exports = BasePlugin.extend({
_namespace_default: 'route_generator',
var Generator = function() {};

init: function (options) {
this._super(options);
/**
* Attaches a router plugin to an application.
*
**/
Generator.prototype.attach = function(options) {
var app = options.app;

this._options.cache_buster = this._options.cache_buster || Math.ceil(Math.random() * 10000);
},
/**
* Initializes the routes for this application
*
**/
var router = this.router || {};

// this allow the manifest to be set if the plugin is used outside of mixdown router.
// mixdown-router extends this class and overrides this method.
manifest: function (route_table) {
if (route_table) {
this.__route_table__ = route_table;
_.extend(router, {

_.each(this.__route_table__, function (routeObject) {
_.each(routeObject.params, function (param) {
if (_.isEmpty(param.regex)) {
param.regex = /(.*)/;
} else if (!(param.regex instanceof RegExp)) {
param.regex = new RegExp(param.regex);
}
});
});
}
return this.__route_table__ || {};
},
/**
* Gets a url object for the given route and parameters. This is where you put your custom route generation.
* http://nodejs.org/api/url.html#url_url
**/
url: function(route, params, host) {
params = params || {};

/**
* Gets a url object for the given route and parameters. This is where you put your custom route generation.
* http://nodejs.org/api/url.html#url_url
**/
url: function (route, params) {
params = params || {};

var uri = url.parse('');
var routeObject = this.manifest()[route];

if (!routeObject) {
return 'Route Not Found - ' + route;
}

// if these are set on the route, then attach them. This will allow injection of FQ urls.
// this will allow polyfill of window object when in a browser.
var location = global.location || {};
uri.protocol = routeObject.protocol || location.protocol;
uri.hostname = routeObject.hostname || location.hostname;
uri.port = routeObject.hasOwnProperty('port') ? routeObject.port : location.port;
uri.method = routeObject.method || null;
uri.auth = routeObject.auth || null;

// map the param fields to querystring as defined in route.
var queryParams = {};
var restParams = {};

// split params into rest/query
_.each(routeObject.params, function (param, key) {
if (param.kind === 'rest') {
restParams[key] = param;
} else if (param.kind === 'query') {
queryParams[key] = param;
}
});
var uri = url.parse('');
debugger;
var routeObject = this.routes[route];

uri.query = uri.query || {};
if (!_.isEmpty(queryParams)) {
if (!routeObject) {
return 'Route Not Found - ' + route;
}

_.each(queryParams, function (param, key) {
// if these are set on the route, then attach them. This will allow injection of FQ urls.
// this will allow polyfill of window object when in a browser.
// allow for host to be past directly when windowless
var _host = host || null;
var _port = null;

if (params.hasOwnProperty(key) || param['default']) {
if (_host != null) {
var host_split = _host.split(":");

// replace capturing group with value
var qval = (params.hasOwnProperty(key) && params[key] !== null) ? params[key] : param['default'];
if (qval) {
uri.query[key] = param.regex.source.replace(/\(.*\)/, qval);
}
if (host_split.length > 1) {
_port = host_split[1];
_host = host_split[0];
}
}

var location = global.location || {};
uri.protocol = routeObject.protocol || location.protocol;
uri.hostname = routeObject.hostname || location.hostname || _host;
uri.port = routeObject.hasOwnProperty('port') ? routeObject.port : (location.port || _port);
uri.method = routeObject.method || null;
uri.auth = routeObject.auth || null;

// map the param fields to querystring as defined in route.
var queryParams = {};
var restParams = {};

// split params into rest/query
_.each(routeObject.params, function(param, key) {
if (param.kind === 'rest') {
restParams[key] = param;
} else if (param.kind === 'query') {
queryParams[key] = param;
}
});
}

// build the pathname.
uri.pathname = '';
if (!_.isEmpty(queryParams)) {

_.each(queryParams, function(param, key) {

// get url segments
// drop first element in array, since a leading slash creates an empty segment
var urlSegments = routeObject.path.split('/');
urlSegments = urlSegments.length > 0 ? urlSegments.slice(1) : urlSegments;
if (params.hasOwnProperty(key) || param['default']) {
uri.query = uri.query || {};

// replace named params with corresponding values and generate uri
_.each(urlSegments, function (segment, i) {
// replace capturing group with value
var qval = (params.hasOwnProperty(key) && params[key] !== null) ? params[key] : param['default'];
if (qval && param.regex) {
debugger;
uri.query[key] = param.regex.replace(/\(.*\)/, qval);
}
}

});
}

// build the pathname.
uri.pathname = '';

// get url segments
// drop first element in array, since a leading slash creates an empty segment
var urlSegments = routeObject.path.split('/');
urlSegments = urlSegments.length > 0 ? urlSegments.slice(1) : urlSegments;

// replace named params with corresponding values and generate uri
_.each(urlSegments, function(segment, i) {

// is this a REST segment?
if (/^\??:/.test(segment)) {
// is this a REST segment?
if (/^\??:/.test(segment)) {

// replace with param value if available.
var pName = segment.replace(/^\??:/, '');
var pConfig = restParams[pName];
// replace with param value if available.
var pName = segment.replace(/^\??:/, '');
var pConfig = restParams[pName];

if (pConfig && pConfig.kind === 'rest') {
if (pConfig && pConfig.kind === 'rest') {

// this is a rest param. replace the capturing group with our value.
var pval = params[pName] ? params[pName] : pConfig['default'];
if (pval) {
var rx = (pConfig.regex instanceof RegExp) ? pConfig.regex.source : pConfig.regex;
uri.pathname += '/' + encodeURIComponent(rx.replace(/\(.*\)/, pval)).replace(/(%2f)/gi, '/');
} else if (segment[0] === '?') {
uri.pathname += '/';
// this is a rest param. replace the capturing group with our value.
var pval = params[pName] ? params[pName] : pConfig['default'];
if (pval) {
uri.pathname += '/' + encodeURIComponent(pConfig.regex.replace(/\(.*\)/, pval)).replace(/(%2f)/gi, '/');
} else if (segment[0] === '?') {
uri.pathname += '/';
}
}
} else {

// just append
uri.pathname += '/' + segment;
}
} else {
});

// just append
uri.pathname += '/' + segment;
}
});
uri.search = uri.query ? '?' + querystring.stringify(uri.query) : null;
uri.path = uri.pathname + (uri.search || '');
uri.host = uri.hostname ? (uri.hostname + (uri.port && uri.port != 80 ? ':' + uri.port : '')) : null;

// do we need to add a cache buster to this?
if (routeObject.cache_buster) {
var cb_key = typeof (routeObject.cache_buster) == 'string' ? routeObject.cache_buster : 'v';
uri.query[cb_key] = this._options.cache_buster;
}
return uri;
},

uri.search = _.keys(uri.query).length ? '?' + querystring.stringify(uri.query) : null;
uri.path = uri.pathname + (uri.search || '');
uri.host = uri.hostname ? (uri.hostname + (uri.port && uri.port != 80 ? ':' + uri.port : '')) : null;
/**
* Gets a url as a string for the given route and parameters. This calls url() and stringifies the route.
*
**/
format: function(route, params) {
var u = router.url(route, params);
var routeObject = router.routes[route];

return uri;
},
if (routeObject.browser === true || routeObject.browser === 'true') {
return u.path;
}

/**
* Gets a url as a string for the given route and parameters. This calls url() and stringifies the route.
*
**/
format: function (route, params) {
var u = this.url(route, params);
var routeObject = this.manifest()[route];
return url.format(u);
},
routes: options.routes,
params: options.params

if (routeObject && (routeObject.browser === true || routeObject.browser === 'true')) {
return u.path;
}
});

return url.format(u);
}
};

});
module.exports = Generator;