cherrytree
Advanced tools
Comparing version 2.0.0-alpha.1 to 2.0.0-alpha.2
@@ -0,11 +1,13 @@ | ||
"use strict"; | ||
module.exports = { | ||
map: require('lodash/collection/map'), | ||
each: require('lodash/collection/each'), | ||
reduce: require('lodash/collection/reduce'), | ||
pluck: require('lodash/collection/pluck'), | ||
extend: require('lodash/object/assign'), | ||
pick: require('lodash/object/pick'), | ||
toArray: require('lodash/lang/toArray'), | ||
clone: require('lodash/lang/clone'), | ||
isEqual: require('lodash/lang/isEqual') | ||
} | ||
map: require("lodash/collection/map"), | ||
each: require("lodash/collection/each"), | ||
reduce: require("lodash/collection/reduce"), | ||
pluck: require("lodash/collection/pluck"), | ||
extend: require("lodash/object/assign"), | ||
pick: require("lodash/object/pick"), | ||
toArray: require("lodash/lang/toArray"), | ||
clone: require("lodash/lang/clone"), | ||
isEqual: require("lodash/lang/isEqual") | ||
}; |
@@ -1,30 +0,32 @@ | ||
let _ = require('./dash') | ||
let invariant = require('./invariant') | ||
"use strict"; | ||
module.exports = function dsl (callback) { | ||
let ancestors = [] | ||
let matches = {} | ||
let names = {} | ||
var _ = require("./dash"); | ||
var invariant = require("./invariant"); | ||
callback(function route (name, options, callback) { | ||
let routes | ||
module.exports = function dsl(callback) { | ||
var ancestors = []; | ||
var matches = {}; | ||
var names = {}; | ||
invariant(!names[name], 'Route names must be unique, but route "%s" is declared multiple times', name) | ||
callback(function route(name, options, callback) { | ||
var routes = undefined; | ||
names[name] = true | ||
invariant(!names[name], "Route names must be unique, but route \"%s\" is declared multiple times", name); | ||
names[name] = true; | ||
if (arguments.length === 1) { | ||
options = {} | ||
options = {}; | ||
} | ||
if (arguments.length === 2 && typeof options === 'function') { | ||
callback = options | ||
options = {} | ||
if (arguments.length === 2 && typeof options === "function") { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (typeof options.path !== 'string') { | ||
let parts = name.split('.') | ||
options.path = parts[parts.length - 1] | ||
if (options.path === 'index') { | ||
options.path = '' | ||
if (typeof options.path !== "string") { | ||
var parts = name.split("."); | ||
options.path = parts[parts.length - 1]; | ||
if (options.path === "index") { | ||
options.path = ""; | ||
} | ||
@@ -35,6 +37,6 @@ } | ||
if (callback) { | ||
ancestors = ancestors.concat(name) | ||
callback() | ||
routes = pop() | ||
ancestors.splice(-1) | ||
ancestors = ancestors.concat(name); | ||
callback(); | ||
routes = pop(); | ||
ancestors.splice(-1); | ||
} | ||
@@ -49,19 +51,19 @@ | ||
ancestors: _.clone(ancestors) | ||
}) | ||
}) | ||
}); | ||
}); | ||
function pop () { | ||
return matches[currentLevel()] || [] | ||
function pop() { | ||
return matches[currentLevel()] || []; | ||
} | ||
function push (route) { | ||
matches[currentLevel()] = matches[currentLevel()] || [] | ||
matches[currentLevel()].push(route) | ||
function push(route) { | ||
matches[currentLevel()] = matches[currentLevel()] || []; | ||
matches[currentLevel()].push(route); | ||
} | ||
function currentLevel () { | ||
return ancestors.join('.') | ||
function currentLevel() { | ||
return ancestors.join("."); | ||
} | ||
return pop() | ||
} | ||
return pop(); | ||
}; |
@@ -1,23 +0,21 @@ | ||
var invariant = function (condition, format, a, b, c, d, e, f) { | ||
"use strict"; | ||
var invariant = function invariant(condition, format, a, b, c, d, e, f) { | ||
if (!condition) { | ||
var error | ||
var error; | ||
if (format === undefined) { | ||
error = new Error( | ||
'Minified exception occurred; use the non-minified dev environment ' + | ||
'for the full error message and additional helpful warnings.' | ||
) | ||
error = new Error("Minified exception occurred; use the non-minified dev environment " + "for the full error message and additional helpful warnings."); | ||
} else { | ||
var args = [a, b, c, d, e, f] | ||
var argIndex = 0 | ||
error = new Error( | ||
'Invariant Violation: ' + | ||
format.replace(/%s/g, function () { return args[argIndex++] }) | ||
) | ||
var args = [a, b, c, d, e, f]; | ||
var argIndex = 0; | ||
error = new Error("Invariant Violation: " + format.replace(/%s/g, function () { | ||
return args[argIndex++]; | ||
})); | ||
} | ||
error.framesToPop = 1 // we don't care about invariant's own frame | ||
throw error | ||
error.framesToPop = 1; // we don't care about invariant's own frame | ||
throw error; | ||
} | ||
} | ||
}; | ||
module.exports = invariant | ||
module.exports = invariant; |
@@ -1,5 +0,7 @@ | ||
var _ = require('../dash') | ||
var links = require('./history/link_delegate') | ||
var LocationBar = require('location-bar') | ||
"use strict"; | ||
var _ = require("../dash"); | ||
var links = require("./history/link_delegate"); | ||
var LocationBar = require("location-bar"); | ||
/** | ||
@@ -9,4 +11,4 @@ * Constructor | ||
var HistoryLocation = function (options) { | ||
this.path = '' | ||
var HistoryLocation = function HistoryLocation(options) { | ||
this.path = ""; | ||
@@ -16,13 +18,13 @@ this.options = _.extend({ | ||
interceptLinks: true, | ||
root: '/' | ||
}, options) | ||
root: "/" | ||
}, options); | ||
// we're using the location-bar module for actual | ||
// URL management | ||
var self = this | ||
this.locationBar = new LocationBar() | ||
var self = this; | ||
this.locationBar = new LocationBar(); | ||
this.locationBar.onChange(function (path) { | ||
self.handleURL('/' + (path || '')) | ||
}) | ||
this.locationBar.start(_.extend({}, options)) | ||
self.handleURL("/" + (path || "")); | ||
}); | ||
this.locationBar.start(_.extend({}, options)); | ||
@@ -33,5 +35,5 @@ // we want to intercept all link clicks in case we're using push state, | ||
if (this.usesPushState() && this.options.interceptLinks) { | ||
this.interceptLinks() | ||
this.interceptLinks(); | ||
} | ||
} | ||
}; | ||
@@ -46,4 +48,4 @@ /** | ||
HistoryLocation.prototype.usesPushState = function () { | ||
return this.options.pushState && this.locationBar.hasPushState() | ||
} | ||
return this.options.pushState && this.locationBar.hasPushState(); | ||
}; | ||
@@ -55,4 +57,4 @@ /** | ||
HistoryLocation.prototype.getURL = function () { | ||
return this.path | ||
} | ||
return this.path; | ||
}; | ||
@@ -66,6 +68,6 @@ /** | ||
if (this.path !== path) { | ||
this.path = path | ||
this.locationBar.update(path, _.extend({trigger: true}, options)) | ||
this.path = path; | ||
this.locationBar.update(path, _.extend({ trigger: true }, options)); | ||
} | ||
} | ||
}; | ||
@@ -79,6 +81,6 @@ /** | ||
if (this.path !== path) { | ||
this.path = path | ||
this.locationBar.update(path, _.extend({trigger: true, replace: true}, options)) | ||
this.path = path; | ||
this.locationBar.update(path, _.extend({ trigger: true, replace: true }, options)); | ||
} | ||
} | ||
}; | ||
@@ -90,4 +92,4 @@ /** | ||
HistoryLocation.prototype.onChange = function (callback) { | ||
this.changeCallback = callback | ||
} | ||
this.changeCallback = callback; | ||
}; | ||
@@ -100,16 +102,16 @@ /** | ||
if (this.locationBar.hasPushState()) { | ||
var rootURL = this.options.root | ||
var rootURL = this.options.root; | ||
if (path !== '') { | ||
rootURL = rootURL.replace(/\/$/, '') | ||
if (path !== "") { | ||
rootURL = rootURL.replace(/\/$/, ""); | ||
} | ||
return rootURL + path | ||
return rootURL + path; | ||
} else { | ||
if (path[0] === '/') { | ||
path = path.substr(1) | ||
if (path[0] === "/") { | ||
path = path.substr(1); | ||
} | ||
return '#' + path | ||
return "#" + path; | ||
} | ||
} | ||
}; | ||
@@ -120,7 +122,7 @@ /** | ||
HistoryLocation.prototype.destroy = function () { | ||
this.locationBar.stop() | ||
this.locationBar.stop(); | ||
if (this.linkHandler) { | ||
links.undelegate(this.linkHandler) | ||
links.undelegate(this.linkHandler); | ||
} | ||
} | ||
}; | ||
@@ -132,12 +134,12 @@ /** | ||
HistoryLocation.prototype.interceptLinks = function () { | ||
var self = this | ||
var self = this; | ||
this.linkHandler = function (e, link) { | ||
e.preventDefault() | ||
e.preventDefault(); | ||
// TODO use router.transitionTo instead, because | ||
// that way we're handling errors and what not? and don't | ||
// update url on failed requests or smth? | ||
self.navigate(link.getAttribute('href')) | ||
} | ||
links.delegate(this.linkHandler) | ||
} | ||
self.navigate(link.getAttribute("href")); | ||
}; | ||
links.delegate(this.linkHandler); | ||
}; | ||
@@ -152,4 +154,4 @@ /** | ||
HistoryLocation.prototype.navigate = function (url) { | ||
this.locationBar.update(url, {trigger: true}) | ||
} | ||
this.locationBar.update(url, { trigger: true }); | ||
}; | ||
@@ -166,8 +168,8 @@ /** | ||
HistoryLocation.prototype.handleURL = function (url) { | ||
this.path = url | ||
this.path = url; | ||
if (this.changeCallback) { | ||
this.changeCallback(url) | ||
this.changeCallback(url); | ||
} | ||
} | ||
}; | ||
module.exports = HistoryLocation | ||
module.exports = HistoryLocation; |
@@ -1,3 +0,5 @@ | ||
var exp = {} | ||
"use strict"; | ||
var exp = {}; | ||
/** | ||
@@ -7,5 +9,5 @@ * DOM Event bind/unbind | ||
var bind = window.addEventListener ? 'addEventListener' : 'attachEvent' | ||
var unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent' | ||
var prefix = bind !== 'addEventListener' ? 'on' : '' | ||
var bind = window.addEventListener ? "addEventListener" : "attachEvent"; | ||
var unbind = window.removeEventListener ? "removeEventListener" : "detachEvent"; | ||
var prefix = bind !== "addEventListener" ? "on" : ""; | ||
@@ -24,5 +26,5 @@ /** | ||
exp.bind = function (el, type, fn, capture) { | ||
el[bind](prefix + type, fn, capture || false) | ||
return fn | ||
} | ||
el[bind](prefix + type, fn, capture || false); | ||
return fn; | ||
}; | ||
@@ -41,6 +43,6 @@ /** | ||
exp.unbind = function (el, type, fn, capture) { | ||
el[unbind](prefix + type, fn, capture || false) | ||
return fn | ||
} | ||
el[unbind](prefix + type, fn, capture || false); | ||
return fn; | ||
}; | ||
module.exports = exp | ||
module.exports = exp; |
@@ -1,13 +0,15 @@ | ||
var events = require('./events') | ||
"use strict"; | ||
var link = function (element) { | ||
element = {parentNode: element} | ||
var events = require("./events"); | ||
var root = document | ||
var link = function link(element) { | ||
element = { parentNode: element }; | ||
var root = document; | ||
// Make sure `element !== document` and `element != null` | ||
// otherwise we get an illegal invocation | ||
while ((element = element.parentNode) && element !== document) { | ||
if (element.tagName.toLowerCase() === 'a') { | ||
return element | ||
if (element.tagName.toLowerCase() === "a") { | ||
return element; | ||
} | ||
@@ -18,6 +20,6 @@ // After `matches` on the edge case that | ||
if (element === root) { | ||
return | ||
return; | ||
} | ||
} | ||
} | ||
}; | ||
@@ -38,11 +40,11 @@ /** | ||
var delegate = function (el, type, fn) { | ||
var delegate = function delegate(el, type, fn) { | ||
return events.bind(el, type, function (e) { | ||
var target = e.target || e.srcElement | ||
var el = link(target) | ||
var target = e.target || e.srcElement; | ||
var el = link(target); | ||
if (el) { | ||
fn(e, el) | ||
fn(e, el); | ||
} | ||
}) | ||
} | ||
}); | ||
}; | ||
@@ -59,7 +61,7 @@ /** | ||
var undelegate = function (el, type, fn) { | ||
var undelegate = function undelegate(el, type, fn) { | ||
// TODO 2014-03-25 fix unbinding - this fn we're trying | ||
// to ubind has never been bound, we bound an anonymous function | ||
events.unbind(el, type, fn) | ||
} | ||
events.unbind(el, type, fn); | ||
}; | ||
@@ -77,22 +79,22 @@ /** | ||
// default to document | ||
if (typeof el === 'function') { | ||
fn = el | ||
el = document | ||
if (typeof el === "function") { | ||
fn = el; | ||
el = document; | ||
} | ||
delegate(el, 'click', function (e, el) { | ||
if (clickable(e, el)) fn(e, el) | ||
}) | ||
} | ||
delegate(el, "click", function (e, el) { | ||
if (clickable(e, el)) fn(e, el); | ||
}); | ||
}; | ||
module.exports.undelegate = function (el, fn) { | ||
// default to document | ||
if (typeof el === 'function') { | ||
fn = el | ||
el = document | ||
if (typeof el === "function") { | ||
fn = el; | ||
el = document; | ||
} | ||
// TODO 2014-03-25 fix undelegation here too | ||
undelegate(el, 'click', fn) | ||
} | ||
undelegate(el, "click", fn); | ||
}; | ||
@@ -103,26 +105,32 @@ /** | ||
function clickable (e, el) { | ||
if (which(e) !== 1) return | ||
if (e.metaKey || e.ctrlKey || e.shiftKey) return | ||
if (e.defaultPrevented) return | ||
// check target | ||
if (el.target) return | ||
// check for data-bypass attribute | ||
if (el.getAttribute('data-bypass') !== null) return | ||
// inspect the href | ||
var href = el.getAttribute('href') | ||
if (!href || href.length === 0) return | ||
// don't handle hash links | ||
if (href[0] === '#') return | ||
// external/absolute links | ||
if (href.indexOf('http://') === 0 || href.indexOf('https://') === 0) return | ||
// don't intercept javascript links | ||
function clickable(e, el) { | ||
if (which(e) !== 1) { | ||
return; | ||
}if (e.metaKey || e.ctrlKey || e.shiftKey) { | ||
return; | ||
}if (e.defaultPrevented) { | ||
return; | ||
} // check target | ||
if (el.target) { | ||
return; | ||
} // check for data-bypass attribute | ||
if (el.getAttribute("data-bypass") !== null) { | ||
return; | ||
} // inspect the href | ||
var href = el.getAttribute("href"); | ||
if (!href || href.length === 0) { | ||
return; | ||
} // don't handle hash links | ||
if (href[0] === "#") { | ||
return; | ||
} // external/absolute links | ||
if (href.indexOf("http://") === 0 || href.indexOf("https://") === 0) { | ||
return; | ||
} // don't intercept javascript links | ||
/*eslint-disable no-script-url*/ | ||
if (href.indexOf('javascript:') === 0) return | ||
/*eslint-enable no-script-url*/ | ||
if (href.indexOf("javascript:") === 0) { | ||
return; | ||
} /*eslint-enable no-script-url*/ | ||
return true | ||
return true; | ||
} | ||
@@ -134,5 +142,5 @@ | ||
function which (e) { | ||
e = e || window.event | ||
return e.which === null ? e.button : e.which | ||
} | ||
function which(e) { | ||
e = e || window.event; | ||
return e.which === null ? e.button : e.which; | ||
} |
@@ -0,33 +1,35 @@ | ||
"use strict"; | ||
module.exports = function () { | ||
return { | ||
path: '', | ||
path: "", | ||
getURL: function () { | ||
return this.path | ||
getURL: function getURL() { | ||
return this.path; | ||
}, | ||
setURL: function (path) { | ||
this.path = path | ||
this.handleURL(this.getURL()) | ||
setURL: function setURL(path) { | ||
this.path = path; | ||
this.handleURL(this.getURL()); | ||
}, | ||
replaceURL: function (path) { | ||
this.setURL(path) | ||
replaceURL: function replaceURL(path) { | ||
this.setURL(path); | ||
}, | ||
onChange: function (callback) { | ||
this.changeCallback = callback | ||
onChange: function onChange(callback) { | ||
this.changeCallback = callback; | ||
}, | ||
handleURL: function (url) { | ||
this.path = url | ||
handleURL: function handleURL(url) { | ||
this.path = url; | ||
if (this.changeCallback) { | ||
this.changeCallback(url) | ||
this.changeCallback(url); | ||
} | ||
}, | ||
formatURL: function (url) { | ||
return url | ||
formatURL: function formatURL(url) { | ||
return url; | ||
} | ||
} | ||
} | ||
}; | ||
}; |
110
lib/path.js
@@ -1,25 +0,27 @@ | ||
var _ = require('./dash') | ||
var invariant = require('./invariant') | ||
var merge = require('qs/lib/utils').merge | ||
var qs = require('qs') | ||
var pathToRegexp = require('path-to-regexp') | ||
"use strict"; | ||
var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?+*]?)/g | ||
var specialParamChars = /[+*?]$/g | ||
var queryMatcher = /\?(.+)/ | ||
var _ = require("./dash"); | ||
var invariant = require("./invariant"); | ||
var merge = require("qs/lib/utils").merge; | ||
var qs = require("qs"); | ||
var pathToRegexp = require("path-to-regexp"); | ||
var _compiledPatterns = {} | ||
var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?+*]?)/g; | ||
var specialParamChars = /[+*?]$/g; | ||
var queryMatcher = /\?(.+)/; | ||
function compilePattern (pattern) { | ||
var _compiledPatterns = {}; | ||
function compilePattern(pattern) { | ||
if (!(pattern in _compiledPatterns)) { | ||
var paramNames = [] | ||
var re = pathToRegexp(pattern, paramNames) | ||
var paramNames = []; | ||
var re = pathToRegexp(pattern, paramNames); | ||
_compiledPatterns[pattern] = { | ||
matcher: re, | ||
paramNames: _.pluck(paramNames, 'name') | ||
} | ||
paramNames: _.pluck(paramNames, "name") | ||
}; | ||
} | ||
return _compiledPatterns[pattern] | ||
return _compiledPatterns[pattern]; | ||
} | ||
@@ -32,4 +34,4 @@ | ||
*/ | ||
isAbsolute: function (path) { | ||
return path.charAt(0) === '/' | ||
isAbsolute: function isAbsolute(path) { | ||
return path.charAt(0) === "/"; | ||
}, | ||
@@ -40,4 +42,4 @@ | ||
*/ | ||
join: function (a, b) { | ||
return a.replace(/\/*$/, '/') + b | ||
join: function join(a, b) { | ||
return a.replace(/\/*$/, "/") + b; | ||
}, | ||
@@ -48,4 +50,4 @@ | ||
*/ | ||
extractParamNames: function (pattern) { | ||
return compilePattern(pattern).paramNames | ||
extractParamNames: function extractParamNames(pattern) { | ||
return compilePattern(pattern).paramNames; | ||
}, | ||
@@ -58,19 +60,19 @@ | ||
*/ | ||
extractParams: function (pattern, path) { | ||
var cp = compilePattern(pattern) | ||
var matcher = cp.matcher | ||
var paramNames = cp.paramNames | ||
var match = path.match(matcher) | ||
extractParams: function extractParams(pattern, path) { | ||
var cp = compilePattern(pattern); | ||
var matcher = cp.matcher; | ||
var paramNames = cp.paramNames; | ||
var match = path.match(matcher); | ||
if (!match) { | ||
return null | ||
return null; | ||
} | ||
var params = {} | ||
var params = {}; | ||
paramNames.forEach(function (paramName, index) { | ||
params[paramName] = match[index + 1] | ||
}) | ||
params[paramName] = match[index + 1]; | ||
}); | ||
return params | ||
return params; | ||
}, | ||
@@ -82,23 +84,19 @@ | ||
*/ | ||
injectParams: function (pattern, params) { | ||
params = params || {} | ||
injectParams: function injectParams(pattern, params) { | ||
params = params || {}; | ||
return pattern.replace(paramInjectMatcher, function (match, param) { | ||
let paramName = param.replace(specialParamChars, '') | ||
var paramName = param.replace(specialParamChars, ""); | ||
// If param is optional don't check for existence | ||
if (param.slice(-1) === '?' || param.slice(-1) === '*') { | ||
if (param.slice(-1) === "?" || param.slice(-1) === "*") { | ||
if (params[paramName] == null) { | ||
return '' | ||
return ""; | ||
} | ||
} else { | ||
invariant( | ||
params[paramName] != null, | ||
"Missing '%s' parameter for path '%s'", | ||
paramName, pattern | ||
) | ||
invariant(params[paramName] != null, "Missing '%s' parameter for path '%s'", paramName, pattern); | ||
} | ||
return params[paramName] | ||
}) | ||
return params[paramName]; | ||
}); | ||
}, | ||
@@ -110,5 +108,5 @@ | ||
*/ | ||
extractQuery: function (path) { | ||
var match = path.match(queryMatcher) | ||
return match && qs.parse(match[1]) | ||
extractQuery: function extractQuery(path) { | ||
var match = path.match(queryMatcher); | ||
return match && qs.parse(match[1]); | ||
}, | ||
@@ -119,4 +117,4 @@ | ||
*/ | ||
withoutQuery: function (path) { | ||
return path.replace(queryMatcher, '') | ||
withoutQuery: function withoutQuery(path) { | ||
return path.replace(queryMatcher, ""); | ||
}, | ||
@@ -128,20 +126,20 @@ | ||
*/ | ||
withQuery: function (path, query) { | ||
var existingQuery = Path.extractQuery(path) | ||
withQuery: function withQuery(path, query) { | ||
var existingQuery = Path.extractQuery(path); | ||
if (existingQuery) { | ||
query = query ? merge(existingQuery, query) : existingQuery | ||
query = query ? merge(existingQuery, query) : existingQuery; | ||
} | ||
var queryString = qs.stringify(query, { indices: false }) | ||
var queryString = qs.stringify(query, { indices: false }); | ||
if (queryString) { | ||
return Path.withoutQuery(path) + '?' + queryString | ||
return Path.withoutQuery(path) + "?" + queryString; | ||
} | ||
return path | ||
return path; | ||
} | ||
} | ||
}; | ||
module.exports = Path | ||
module.exports = Path; |
@@ -1,19 +0,23 @@ | ||
var _ = require('./dash') | ||
var dsl = require('./dsl') | ||
var Path = require('./path') | ||
var invariant = require('./invariant') | ||
var HistoryLocation = require('./locations/history') | ||
var MemoryLocation = require('./locations/memory') | ||
var transition = require('./transition') | ||
"use strict"; | ||
function createLogger (log, error) { | ||
var _ = require("./dash"); | ||
var dsl = require("./dsl"); | ||
var Path = require("./path"); | ||
var invariant = require("./invariant"); | ||
var HistoryLocation = require("./locations/history"); | ||
var MemoryLocation = require("./locations/memory"); | ||
var transition = require("./transition"); | ||
function createLogger(log, error) { | ||
// falsy means no logging | ||
if (!log) return () => {} | ||
// custom logging function | ||
if (log !== true) return log | ||
// true means use the default logger - console | ||
let fn = error ? console.error : console.info | ||
if (!log) { | ||
return function () {}; | ||
} // custom logging function | ||
if (log !== true) { | ||
return log; | ||
} // true means use the default logger - console | ||
var fn = error ? console.error : console.info; | ||
return function () { | ||
fn.apply(console, arguments) | ||
} | ||
fn.apply(console, arguments); | ||
}; | ||
} | ||
@@ -24,5 +28,5 @@ | ||
*/ | ||
var Cherrytree = function () { | ||
this.initialize.apply(this, arguments) | ||
} | ||
var Cherrytree = function Cherrytree() { | ||
this.initialize.apply(this, arguments); | ||
}; | ||
@@ -34,9 +38,9 @@ /** | ||
Cherrytree.prototype.initialize = function (options) { | ||
this.nextId = 1 | ||
this.state = {} | ||
this.middleware = [] | ||
this.options = _.extend({}, options) | ||
this.log = createLogger(this.options.log) | ||
this.logError = createLogger(this.options.logError === false ? false : true, true) | ||
} | ||
this.nextId = 1; | ||
this.state = {}; | ||
this.middleware = []; | ||
this.options = _.extend({}, options); | ||
this.log = createLogger(this.options.log); | ||
this.logError = createLogger(this.options.logError === false ? false : true, true); | ||
}; | ||
@@ -50,5 +54,5 @@ /** | ||
Cherrytree.prototype.use = function (middleware) { | ||
this.middleware.push(middleware) | ||
return this | ||
} | ||
this.middleware.push(middleware); | ||
return this; | ||
}; | ||
@@ -63,9 +67,9 @@ /** | ||
// create the route tree | ||
this.routes = dsl(routes) | ||
this.routes = dsl(routes); | ||
// create the matcher list, which is like a flattened | ||
// list of routes = a list of all branches of the route tree | ||
var matchers = this.matchers = [] | ||
var matchers = this.matchers = []; | ||
eachBranch({routes: this.routes}, [], function (routes) { | ||
eachBranch({ routes: this.routes }, [], function (routes) { | ||
// concatenate the paths of the list of routes | ||
@@ -75,7 +79,7 @@ var path = _.reduce(routes, function (memo, r) { | ||
// and keep resetting the trailing slash | ||
return (r.path[0] === '/' ? r.path : memo + '/' + r.path).replace(/\/$/, '') | ||
}, '') | ||
return (r.path[0] === "/" ? r.path : memo + "/" + r.path).replace(/\/$/, ""); | ||
}, ""); | ||
// ensure we have a leading slash | ||
if (path === '') { | ||
path = '/' | ||
if (path === "") { | ||
path = "/"; | ||
} | ||
@@ -88,17 +92,17 @@ // register routes | ||
paramNames: Path.extractParamNames(routes[routes.length - 1].path) | ||
}) | ||
}) | ||
}); | ||
}); | ||
function eachBranch (node, memo, fn) { | ||
function eachBranch(node, memo, fn) { | ||
_.each(node.routes, function (route) { | ||
if (!route.routes || route.routes.length === 0) { | ||
fn.call(null, memo.concat(route)) | ||
fn.call(null, memo.concat(route)); | ||
} else { | ||
eachBranch(route, memo.concat(route), fn) | ||
eachBranch(route, memo.concat(route), fn); | ||
} | ||
}) | ||
}); | ||
} | ||
return this | ||
} | ||
return this; | ||
}; | ||
@@ -113,8 +117,12 @@ /** | ||
Cherrytree.prototype.listen = function (location) { | ||
location = this.location = location || this.createDefaultLocation() | ||
var _this = this; | ||
location = this.location = location || this.createDefaultLocation(); | ||
// setup the location onChange handler | ||
location.onChange((url) => this.dispatch(url)) | ||
location.onChange(function (url) { | ||
return _this.dispatch(url); | ||
}); | ||
// and also kick off the initial transition | ||
return this.dispatch(location.getURL()) | ||
} | ||
return this.dispatch(location.getURL()); | ||
}; | ||
@@ -132,6 +140,6 @@ /** | ||
if (this.state.activeTransition) { | ||
return this.replaceWith.apply(this, arguments) | ||
return this.replaceWith.apply(this, arguments); | ||
} | ||
return this.doTransition('setURL', _.toArray(arguments)) | ||
} | ||
return this.doTransition("setURL", _.toArray(arguments)); | ||
}; | ||
@@ -149,4 +157,4 @@ /** | ||
Cherrytree.prototype.replaceWith = function () { | ||
return this.doTransition('replaceURL', _.toArray(arguments)) | ||
} | ||
return this.doTransition("replaceURL", _.toArray(arguments)); | ||
}; | ||
@@ -163,16 +171,16 @@ /** | ||
Cherrytree.prototype.generate = function (name, params, query) { | ||
invariant(this.location, 'call .listen() before using .generate()') | ||
var matcher | ||
invariant(this.location, "call .listen() before using .generate()"); | ||
var matcher; | ||
params = params || {} | ||
query = query || {} | ||
params = params || {}; | ||
query = query || {}; | ||
_.each(this.matchers, function (m) { | ||
if (m.name === name) { | ||
matcher = m | ||
matcher = m; | ||
} | ||
}) | ||
}); | ||
if (!matcher) { | ||
throw new Error('No route is named ' + name) | ||
throw new Error("No route is named " + name); | ||
} | ||
@@ -185,11 +193,11 @@ | ||
// reaching out to the router.state if that's what they want. | ||
var currentParams = _.clone(this.state.params || {}) | ||
var currentParams = _.clone(this.state.params || {}); | ||
if (this.state.activeTransition) { | ||
currentParams = _.clone(this.state.activeTransition.params || {}) | ||
currentParams = _.clone(this.state.activeTransition.params || {}); | ||
} | ||
params = _.extend(currentParams, params) | ||
params = _.extend(currentParams, params); | ||
var url = Path.withQuery(Path.injectParams(matcher.path, params), query) | ||
return this.location.formatURL(url) | ||
} | ||
var url = Path.withQuery(Path.injectParams(matcher.path, params), query); | ||
return this.location.formatURL(url); | ||
}; | ||
@@ -202,9 +210,9 @@ /** | ||
if (this.location && this.location.destroy && this.location.destroy) { | ||
this.location.destroy() | ||
this.location.destroy(); | ||
} | ||
if (this.state.activeTransition) { | ||
this.state.activeTransition.cancel() | ||
this.state.activeTransition.cancel(); | ||
} | ||
this.state = {} | ||
} | ||
this.state = {}; | ||
}; | ||
@@ -217,3 +225,3 @@ /** | ||
*/ | ||
Cherrytree.prototype.reset = function () {} | ||
Cherrytree.prototype.reset = function () {}; | ||
@@ -224,24 +232,26 @@ /** | ||
Cherrytree.prototype.doTransition = function (method, params) { | ||
let previousUrl = this.location.getURL() | ||
var _this = this; | ||
let url = params[0] | ||
if (url[0] !== '/') { | ||
url = this.generate.apply(this, params) | ||
url = url.replace(/^#/, '/') | ||
var previousUrl = this.location.getURL(); | ||
var url = params[0]; | ||
if (url[0] !== "/") { | ||
url = this.generate.apply(this, params); | ||
url = url.replace(/^#/, "/"); | ||
} | ||
let transition = this.dispatch(url) | ||
var transition = this.dispatch(url); | ||
transition.catch((err) => { | ||
if (err && err.type === 'TransitionCancelled') { | ||
transition["catch"](function (err) { | ||
if (err && err.type === "TransitionCancelled") { | ||
// reset the URL in case the transition has been cancelled | ||
this.location.replaceURL(previousUrl, {trigger: false}) | ||
_this.location.replaceURL(previousUrl, { trigger: false }); | ||
} | ||
return err | ||
}) | ||
return err; | ||
}); | ||
this.location[method](url, {trigger: false}) | ||
this.location[method](url, { trigger: false }); | ||
return transition | ||
} | ||
return transition; | ||
}; | ||
@@ -256,18 +266,18 @@ /** | ||
Cherrytree.prototype.match = function (path) { | ||
path = (path || '').replace(/\/$/, '') || '/' | ||
var found = false | ||
var params | ||
var query | ||
var routes = [] | ||
var pathWithoutQuery = Path.withoutQuery(path) | ||
path = (path || "").replace(/\/$/, "") || "/"; | ||
var found = false; | ||
var params; | ||
var query; | ||
var routes = []; | ||
var pathWithoutQuery = Path.withoutQuery(path); | ||
_.each(this.matchers, function (matcher) { | ||
if (!found) { | ||
params = Path.extractParams(matcher.path, pathWithoutQuery) | ||
params = Path.extractParams(matcher.path, pathWithoutQuery); | ||
if (params) { | ||
found = true | ||
routes = matcher.routes | ||
query = Path.extractQuery(path) || {} | ||
found = true; | ||
routes = matcher.routes; | ||
query = Path.extractQuery(path) || {}; | ||
} | ||
} | ||
}) | ||
}); | ||
return { | ||
@@ -277,3 +287,3 @@ routes: _.map(routes, descriptor), | ||
query: query || {} | ||
} | ||
}; | ||
@@ -286,3 +296,3 @@ // clone the data (only a shallow clone of options) | ||
// will get to use pristine data. | ||
function descriptor (route) { | ||
function descriptor(route) { | ||
return { | ||
@@ -294,19 +304,17 @@ name: route.name, | ||
ancestors: _.clone(route.ancestors) | ||
} | ||
}; | ||
} | ||
} | ||
}; | ||
Cherrytree.prototype.dispatch = function (path) { | ||
let match = this.match(path) | ||
let query = match.query | ||
let pathname = Path.withoutQuery(path) | ||
var match = this.match(path); | ||
var query = match.query; | ||
var pathname = Path.withoutQuery(path); | ||
let activeTransition = this.state.activeTransition | ||
var activeTransition = this.state.activeTransition; | ||
// if we already have an active transition with all the same | ||
// params - return that and don't do anything else | ||
if (activeTransition && | ||
activeTransition.pathname === pathname && | ||
_.isEqual(activeTransition.query, query)) { | ||
return activeTransition | ||
if (activeTransition && activeTransition.pathname === pathname && _.isEqual(activeTransition.query, query)) { | ||
return activeTransition; | ||
} | ||
@@ -317,5 +325,5 @@ | ||
if (activeTransition) { | ||
let err = new Error('TransitionRedirected') | ||
err.type = 'TransitionRedirected' | ||
activeTransition.cancel(err) | ||
var err = new Error("TransitionRedirected"); | ||
err.type = "TransitionRedirected"; | ||
activeTransition.cancel(err); | ||
} | ||
@@ -328,4 +336,3 @@ | ||
if (!activeTransition) { | ||
if (this.state.pathname === pathname && | ||
_.isEqual(this.state.query, query)) { | ||
if (this.state.pathname === pathname && _.isEqual(this.state.query, query)) { | ||
return transition({ | ||
@@ -337,7 +344,7 @@ id: this.nextId++, | ||
router: this | ||
}) | ||
}); | ||
} | ||
} | ||
let t = transition({ | ||
var t = transition({ | ||
id: this.nextId++, | ||
@@ -347,8 +354,8 @@ path: path, | ||
router: this | ||
}) | ||
}); | ||
this.state.activeTransition = t | ||
this.state.activeTransition = t; | ||
return t | ||
} | ||
return t; | ||
}; | ||
@@ -364,9 +371,9 @@ /** | ||
Cherrytree.prototype.createDefaultLocation = function () { | ||
let locationOptions = _.pick(this.options, ['pushState', 'root', 'interceptLinks']) | ||
return new HistoryLocation(locationOptions) | ||
} | ||
var locationOptions = _.pick(this.options, ["pushState", "root", "interceptLinks"]); | ||
return new HistoryLocation(locationOptions); | ||
}; | ||
module.exports = function cherrytree (options) { | ||
return new Cherrytree(options) | ||
} | ||
module.exports = function cherrytree(options) { | ||
return new Cherrytree(options); | ||
}; | ||
@@ -377,3 +384,3 @@ /** | ||
module.exports.HistoryLocation = HistoryLocation | ||
module.exports.MemoryLocation = MemoryLocation | ||
module.exports.HistoryLocation = HistoryLocation; | ||
module.exports.MemoryLocation = MemoryLocation; |
@@ -1,33 +0,35 @@ | ||
var _ = require('./dash') | ||
var Promise = require('es6-promise').Promise | ||
var invariant = require('./invariant') | ||
var Path = require('./path') | ||
"use strict"; | ||
module.exports = function transition (options) { | ||
options = options || {} | ||
var _ = require("./dash"); | ||
var Promise = require("es6-promise").Promise; | ||
var invariant = require("./invariant"); | ||
var Path = require("./path"); | ||
let router = options.router | ||
let log = router.log | ||
let logError = router.logError | ||
module.exports = function transition(options) { | ||
options = options || {}; | ||
let path = options.path | ||
let match = options.match | ||
let routes = match.routes | ||
let params = match.params | ||
let query = match.query | ||
var router = options.router; | ||
var log = router.log; | ||
var logError = router.logError; | ||
let id = options.id | ||
let startTime = Date.now() | ||
log('---') | ||
log('Transition #' + id, 'to', path) | ||
log('Transition #' + id, 'routes:', _.pluck(routes, 'name')) | ||
log('Transition #' + id, 'params:', params) | ||
log('Transition #' + id, 'query:', query) | ||
var path = options.path; | ||
var match = options.match; | ||
var routes = match.routes; | ||
var params = match.params; | ||
var query = match.query; | ||
var id = options.id; | ||
var startTime = Date.now(); | ||
log("---"); | ||
log("Transition #" + id, "to", path); | ||
log("Transition #" + id, "routes:", _.pluck(routes, "name")); | ||
log("Transition #" + id, "params:", params); | ||
log("Transition #" + id, "query:", query); | ||
// create the transition promise | ||
var resolve, reject | ||
var resolve, reject; | ||
var promise = new Promise(function (res, rej) { | ||
resolve = res | ||
reject = rej | ||
}) | ||
resolve = res; | ||
reject = rej; | ||
}); | ||
@@ -39,11 +41,11 @@ // 1. make transition errors loud | ||
promise.then(function () { | ||
log('Transition #' + id, 'completed in', (Date.now() - startTime) + 'ms') | ||
}).catch(function (err) { | ||
if (err.type !== 'TransitionRedirected' && err.type !== 'TransitionCancelled') { | ||
log('Transition #' + id, 'FAILED') | ||
logError(err.stack) | ||
log("Transition #" + id, "completed in", Date.now() - startTime + "ms"); | ||
})["catch"](function (err) { | ||
if (err.type !== "TransitionRedirected" && err.type !== "TransitionCancelled") { | ||
log("Transition #" + id, "FAILED"); | ||
logError(err.stack); | ||
} | ||
}) | ||
}); | ||
var cancelled = false | ||
var cancelled = false; | ||
@@ -54,4 +56,4 @@ var transition = { | ||
routes: router.state.routes || [], | ||
path: router.state.path || '', | ||
pathname: router.state.pathname || '', | ||
path: router.state.path || "", | ||
pathname: router.state.pathname || "", | ||
params: router.state.params || {}, | ||
@@ -65,72 +67,70 @@ query: router.state.query || {} | ||
query: query, | ||
retry: function () { | ||
return router.transitionTo(path) | ||
retry: function retry() { | ||
return router.transitionTo(path); | ||
}, | ||
cancel: function (err) { | ||
cancel: function cancel(err) { | ||
if (router.state.activeTransition !== transition) { | ||
return | ||
return; | ||
} | ||
if (transition.isCancelled) { | ||
return | ||
return; | ||
} | ||
router.state.activeTransition = null | ||
transition.isCancelled = true | ||
cancelled = true | ||
router.state.activeTransition = null; | ||
transition.isCancelled = true; | ||
cancelled = true; | ||
if (!err) { | ||
err = new Error('TransitionCancelled') | ||
err.type = 'TransitionCancelled' | ||
err = new Error("TransitionCancelled"); | ||
err.type = "TransitionCancelled"; | ||
} | ||
if (err.type === 'TransitionCancelled') { | ||
log('Transition #' + id, 'cancelled') | ||
if (err.type === "TransitionCancelled") { | ||
log("Transition #" + id, "cancelled"); | ||
} | ||
if (err.type === 'TransitionRedirected') { | ||
log('Transition #' + id, 'redirected') | ||
if (err.type === "TransitionRedirected") { | ||
log("Transition #" + id, "redirected"); | ||
} | ||
reject(err) | ||
reject(err); | ||
}, | ||
redirectTo: function () { | ||
return router.transitionTo.apply(router, arguments) | ||
redirectTo: function redirectTo() { | ||
return router.transitionTo.apply(router, arguments); | ||
}, | ||
followRedirects: function () { | ||
return promise['catch'](function (reason) { | ||
followRedirects: function followRedirects() { | ||
return promise["catch"](function (reason) { | ||
if (router.state.activeTransition) { | ||
return router.state.activeTransition.followRedirects() | ||
return router.state.activeTransition.followRedirects(); | ||
} | ||
return Promise.reject(reason) | ||
}) | ||
return Promise.reject(reason); | ||
}); | ||
}, | ||
then: promise.then.bind(promise), | ||
catch: promise.catch.bind(promise) | ||
} | ||
"catch": promise["catch"].bind(promise) | ||
}; | ||
// here we handle calls to all of the middlewares | ||
function callNext (i, prevResult) { | ||
var middlewareName | ||
function callNext(i, prevResult) { | ||
var middlewareName; | ||
// if transition has been cancelled - nothing left to do | ||
if (cancelled) { | ||
return | ||
return; | ||
} | ||
// done | ||
if (i < router.middleware.length) { | ||
middlewareName = router.middleware[i].name || 'anonymous' | ||
log('Transition #' + id, 'resolving middleware:', middlewareName) | ||
let middlewarePromise | ||
middlewareName = router.middleware[i].name || "anonymous"; | ||
log("Transition #" + id, "resolving middleware:", middlewareName); | ||
var middlewarePromise = undefined; | ||
try { | ||
middlewarePromise = router.middleware[i](transition, prevResult) | ||
invariant(transition !== middlewarePromise, 'Middleware %s returned a transition which resulted in a deadlock', middlewareName) | ||
middlewarePromise = router.middleware[i](transition, prevResult); | ||
invariant(transition !== middlewarePromise, "Middleware %s returned a transition which resulted in a deadlock", middlewareName); | ||
} catch (err) { | ||
return reject(err) | ||
return reject(err); | ||
} | ||
Promise.resolve(middlewarePromise) | ||
.then(function (result) { | ||
callNext(i + 1, result) | ||
}) | ||
.catch(function (err) { | ||
log('Transition #' + id, 'resolving middleware:', middlewareName, 'FAILED') | ||
reject(err) | ||
}) | ||
Promise.resolve(middlewarePromise).then(function (result) { | ||
callNext(i + 1, result); | ||
})["catch"](function (err) { | ||
log("Transition #" + id, "resolving middleware:", middlewareName, "FAILED"); | ||
reject(err); | ||
}); | ||
} else { | ||
@@ -144,4 +144,4 @@ router.state = { | ||
query: query | ||
} | ||
resolve() | ||
}; | ||
resolve(); | ||
} | ||
@@ -151,12 +151,14 @@ } | ||
if (!options.noop) { | ||
Promise.resolve().then(() => callNext(0)) | ||
Promise.resolve().then(function () { | ||
return callNext(0); | ||
}); | ||
} else { | ||
resolve() | ||
resolve(); | ||
} | ||
if (options.noop) { | ||
transition.noop = true | ||
transition.noop = true; | ||
} | ||
return transition | ||
} | ||
return transition; | ||
}; |
{ | ||
"name": "cherrytree", | ||
"version": "2.0.0-alpha.1", | ||
"version": "2.0.0-alpha.2", | ||
"description": "Cherrytree - a flexible hierarchical client side router", | ||
@@ -5,0 +5,0 @@ "main": "index", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
0
6066
0
209226
15