one.com-page
Advanced tools
Comparing version 1.6.3 to 1.6.4-patch1
@@ -0,1 +1,8 @@ | ||
1.6.3 / 2015-04-19 | ||
================== | ||
* fix including page.js on server side | ||
* fix including page.js if the document is already loaded | ||
* fix bug with click-event in Firefox | ||
1.6.2 / 2015-03-06 | ||
@@ -6,3 +13,2 @@ ================== | ||
* fix nw.js support #238 | ||
* fix bug with click-event in Firefox #244 | ||
* fix popstate issue in Safari #213 | ||
@@ -9,0 +15,0 @@ |
33
index.js
@@ -20,3 +20,3 @@ /* globals require, module */ | ||
*/ | ||
var clickEvent = document.ontouchstart ? 'touchstart' : 'click'; | ||
var clickEvent = ('undefined' !== typeof document) && document.ontouchstart ? 'touchstart' : 'click'; | ||
@@ -205,3 +205,3 @@ /** | ||
if (false !== dispatch) { | ||
page.dispatchExit(ctx, dispatchNext); | ||
page.dispatchExit(dispatchNext); | ||
} else { | ||
@@ -287,5 +287,4 @@ dispatchNext(); | ||
/** | ||
* Dispatch the exit routes for current `ctx`. | ||
* Dispatch the exit routes for prevContext. | ||
* | ||
* @param {Object} ctx | ||
* @param {Function} cb | ||
@@ -295,6 +294,5 @@ * @api private | ||
page.dispatchExit = function (ctx, cb) { | ||
page.dispatchExit = function (cb) { | ||
var prev = prevContext, | ||
i = 0; | ||
prevContext = ctx; | ||
@@ -323,2 +321,3 @@ function nextExit() { | ||
var i = 0; | ||
prevContext = ctx; | ||
@@ -347,3 +346,3 @@ function nextEnter() { | ||
page.dispatch = function(ctx) { | ||
page.dispatchExit(ctx, function () { | ||
page.dispatchExit(function () { | ||
page.dispatchEnter(ctx); | ||
@@ -530,3 +529,3 @@ }); | ||
pathname = ~qsIndex ? path.slice(0, qsIndex) : path, | ||
m = this.regexp.exec(decodeURIComponent(pathname)); | ||
m = this.regexp.exec(pathname); | ||
@@ -552,9 +551,15 @@ if (!m) return false; | ||
var onpopstate = (function () { | ||
// this hack resolves https://github.com/visionmedia/page.js/issues/213 | ||
var loaded = false; | ||
window.addEventListener('load', function() { | ||
setTimeout(function() { | ||
loaded = true; | ||
}, 0); | ||
}); | ||
if ('undefined' === typeof window) { | ||
return; | ||
} | ||
if (document.readyState === 'complete') { | ||
loaded = true; | ||
} else { | ||
window.addEventListener('load', function() { | ||
setTimeout(function() { | ||
loaded = true; | ||
}, 0); | ||
}); | ||
} | ||
return function onpopstate(e) { | ||
@@ -561,0 +566,0 @@ if (!loaded) return; |
{ | ||
"name": "one.com-page", | ||
"description": "Tiny client-side router", | ||
"version": "1.6.3", | ||
"version": "1.6.4-patch1", | ||
"license": "MIT", | ||
"repository": { | ||
@@ -22,3 +23,3 @@ "type": "git", | ||
"dependencies": { | ||
"path-to-regexp": "~1.0.1" | ||
"path-to-regexp": "~1.2.1" | ||
}, | ||
@@ -25,0 +26,0 @@ "devDependencies": { |
381
page.js
@@ -22,3 +22,3 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.page=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
*/ | ||
var clickEvent = document.ontouchstart ? 'touchstart' : 'click'; | ||
var clickEvent = ('undefined' !== typeof document) && document.ontouchstart ? 'touchstart' : 'click'; | ||
@@ -207,3 +207,3 @@ /** | ||
if (false !== dispatch) { | ||
page.dispatchExit(ctx, dispatchNext); | ||
page.dispatchExit(dispatchNext); | ||
} else { | ||
@@ -289,5 +289,4 @@ dispatchNext(); | ||
/** | ||
* Dispatch the exit routes for current `ctx`. | ||
* Dispatch the exit routes for prevContext. | ||
* | ||
* @param {Object} ctx | ||
* @param {Function} cb | ||
@@ -297,6 +296,5 @@ * @api private | ||
page.dispatchExit = function (ctx, cb) { | ||
page.dispatchExit = function (cb) { | ||
var prev = prevContext, | ||
i = 0; | ||
prevContext = ctx; | ||
@@ -325,2 +323,3 @@ function nextExit() { | ||
var i = 0; | ||
prevContext = ctx; | ||
@@ -349,3 +348,3 @@ function nextEnter() { | ||
page.dispatch = function(ctx) { | ||
page.dispatchExit(ctx, function () { | ||
page.dispatchExit(function () { | ||
page.dispatchEnter(ctx); | ||
@@ -532,3 +531,3 @@ }); | ||
pathname = ~qsIndex ? path.slice(0, qsIndex) : path, | ||
m = this.regexp.exec(decodeURIComponent(pathname)); | ||
m = this.regexp.exec(pathname); | ||
@@ -554,9 +553,15 @@ if (!m) return false; | ||
var onpopstate = (function () { | ||
// this hack resolves https://github.com/visionmedia/page.js/issues/213 | ||
var loaded = false; | ||
window.addEventListener('load', function() { | ||
setTimeout(function() { | ||
loaded = true; | ||
}, 0); | ||
}); | ||
if ('undefined' === typeof window) { | ||
return; | ||
} | ||
if (document.readyState === 'complete') { | ||
loaded = true; | ||
} else { | ||
window.addEventListener('load', function() { | ||
setTimeout(function() { | ||
loaded = true; | ||
}, 0); | ||
}); | ||
} | ||
return function onpopstate(e) { | ||
@@ -748,3 +753,3 @@ if (!loaded) return; | ||
},{}],3:[function(require,module,exports){ | ||
var isArray = require('isarray'); | ||
var isarray = require('isarray') | ||
@@ -754,3 +759,7 @@ /** | ||
*/ | ||
module.exports = pathToRegexp; | ||
module.exports = pathToRegexp | ||
module.exports.parse = parse | ||
module.exports.compile = compile | ||
module.exports.tokensToFunction = tokensToFunction | ||
module.exports.tokensToRegExp = tokensToRegExp | ||
@@ -769,10 +778,173 @@ /** | ||
// | ||
// "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?"] | ||
// "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined] | ||
'([\\/.])?(?:\\:(\\w+)(?:\\(((?:\\\\.|[^)])*)\\))?|\\(((?:\\\\.|[^)])*)\\))([+*?])?', | ||
// Match regexp special characters that are always escaped. | ||
'([.+*?=^!:${}()[\\]|\\/])' | ||
].join('|'), 'g'); | ||
// "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] | ||
// "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] | ||
// "/*" => ["/", undefined, undefined, undefined, undefined, "*"] | ||
'([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^()])+)\\))?|\\(((?:\\\\.|[^()])+)\\))([+*?])?|(\\*))' | ||
].join('|'), 'g') | ||
/** | ||
* Parse a string for the raw tokens. | ||
* | ||
* @param {String} str | ||
* @return {Array} | ||
*/ | ||
function parse (str) { | ||
var tokens = [] | ||
var key = 0 | ||
var index = 0 | ||
var path = '' | ||
var res | ||
while ((res = PATH_REGEXP.exec(str)) != null) { | ||
var m = res[0] | ||
var escaped = res[1] | ||
var offset = res.index | ||
path += str.slice(index, offset) | ||
index = offset + m.length | ||
// Ignore already escaped sequences. | ||
if (escaped) { | ||
path += escaped[1] | ||
continue | ||
} | ||
// Push the current path onto the tokens. | ||
if (path) { | ||
tokens.push(path) | ||
path = '' | ||
} | ||
var prefix = res[2] | ||
var name = res[3] | ||
var capture = res[4] | ||
var group = res[5] | ||
var suffix = res[6] | ||
var asterisk = res[7] | ||
var repeat = suffix === '+' || suffix === '*' | ||
var optional = suffix === '?' || suffix === '*' | ||
var delimiter = prefix || '/' | ||
var pattern = capture || group || (asterisk ? '.*' : '[^' + delimiter + ']+?') | ||
tokens.push({ | ||
name: name || key++, | ||
prefix: prefix || '', | ||
delimiter: delimiter, | ||
optional: optional, | ||
repeat: repeat, | ||
pattern: escapeGroup(pattern) | ||
}) | ||
} | ||
// Match any characters still remaining. | ||
if (index < str.length) { | ||
path += str.substr(index) | ||
} | ||
// If the path exists, push it onto the end. | ||
if (path) { | ||
tokens.push(path) | ||
} | ||
return tokens | ||
} | ||
/** | ||
* Compile a string to a template function for the path. | ||
* | ||
* @param {String} str | ||
* @return {Function} | ||
*/ | ||
function compile (str) { | ||
return tokensToFunction(parse(str)) | ||
} | ||
/** | ||
* Expose a method for transforming tokens into the path function. | ||
*/ | ||
function tokensToFunction (tokens) { | ||
// Compile all the tokens into regexps. | ||
var matches = new Array(tokens.length) | ||
// Compile all the patterns before compilation. | ||
for (var i = 0; i < tokens.length; i++) { | ||
if (typeof tokens[i] === 'object') { | ||
matches[i] = new RegExp('^' + tokens[i].pattern + '$') | ||
} | ||
} | ||
return function (obj) { | ||
var path = '' | ||
var data = obj || {} | ||
for (var i = 0; i < tokens.length; i++) { | ||
var token = tokens[i] | ||
if (typeof token === 'string') { | ||
path += token | ||
continue | ||
} | ||
var value = data[token.name] | ||
var segment | ||
if (value == null) { | ||
if (token.optional) { | ||
continue | ||
} else { | ||
throw new TypeError('Expected "' + token.name + '" to be defined') | ||
} | ||
} | ||
if (isarray(value)) { | ||
if (!token.repeat) { | ||
throw new TypeError('Expected "' + token.name + '" to not repeat, but received "' + value + '"') | ||
} | ||
if (value.length === 0) { | ||
if (token.optional) { | ||
continue | ||
} else { | ||
throw new TypeError('Expected "' + token.name + '" to not be empty') | ||
} | ||
} | ||
for (var j = 0; j < value.length; j++) { | ||
segment = encodeURIComponent(value[j]) | ||
if (!matches[i].test(segment)) { | ||
throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') | ||
} | ||
path += (j === 0 ? token.prefix : token.delimiter) + segment | ||
} | ||
continue | ||
} | ||
segment = encodeURIComponent(value) | ||
if (!matches[i].test(segment)) { | ||
throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') | ||
} | ||
path += token.prefix + segment | ||
} | ||
return path | ||
} | ||
} | ||
/** | ||
* Escape a regular expression string. | ||
* | ||
* @param {String} str | ||
* @return {String} | ||
*/ | ||
function escapeString (str) { | ||
return str.replace(/([.+*?=^!:${}()[\]|\/])/g, '\\$1') | ||
} | ||
/** | ||
* Escape the capturing group by escaping special characters and meaning. | ||
@@ -784,3 +956,3 @@ * | ||
function escapeGroup (group) { | ||
return group.replace(/([=!:$\/()])/g, '\\$1'); | ||
return group.replace(/([=!:$\/()])/g, '\\$1') | ||
} | ||
@@ -796,4 +968,4 @@ | ||
function attachKeys (re, keys) { | ||
re.keys = keys; | ||
return re; | ||
re.keys = keys | ||
return re | ||
} | ||
@@ -808,3 +980,3 @@ | ||
function flags (options) { | ||
return options.sensitive ? '' : 'i'; | ||
return options.sensitive ? '' : 'i' | ||
} | ||
@@ -821,3 +993,3 @@ | ||
// Use a negative lookahead to match only capturing groups. | ||
var groups = path.source.match(/\((?!\?)/g); | ||
var groups = path.source.match(/\((?!\?)/g) | ||
@@ -827,11 +999,13 @@ if (groups) { | ||
keys.push({ | ||
name: i, | ||
name: i, | ||
prefix: null, | ||
delimiter: null, | ||
optional: false, | ||
repeat: false | ||
}); | ||
optional: false, | ||
repeat: false, | ||
pattern: null | ||
}) | ||
} | ||
} | ||
return attachKeys(path, keys); | ||
return attachKeys(path, keys) | ||
} | ||
@@ -848,57 +1022,97 @@ | ||
function arrayToRegexp (path, keys, options) { | ||
var parts = []; | ||
var parts = [] | ||
for (var i = 0; i < path.length; i++) { | ||
parts.push(pathToRegexp(path[i], keys, options).source); | ||
parts.push(pathToRegexp(path[i], keys, options).source) | ||
} | ||
var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)); | ||
return attachKeys(regexp, keys); | ||
var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)) | ||
return attachKeys(regexp, keys) | ||
} | ||
/** | ||
* Replace the specific tags with regexp strings. | ||
* Create a path regexp from string input. | ||
* | ||
* @param {String} path | ||
* @param {Array} keys | ||
* @return {String} | ||
* @param {Object} options | ||
* @return {RegExp} | ||
*/ | ||
function replacePath (path, keys) { | ||
var index = 0; | ||
function stringToRegexp (path, keys, options) { | ||
var tokens = parse(path) | ||
var re = tokensToRegExp(tokens, options) | ||
function replace (_, escaped, prefix, key, capture, group, suffix, escape) { | ||
if (escaped) { | ||
return escaped; | ||
// Attach keys back to the regexp. | ||
for (var i = 0; i < tokens.length; i++) { | ||
if (typeof tokens[i] !== 'string') { | ||
keys.push(tokens[i]) | ||
} | ||
} | ||
if (escape) { | ||
return '\\' + escape; | ||
} | ||
return attachKeys(re, keys) | ||
} | ||
var repeat = suffix === '+' || suffix === '*'; | ||
var optional = suffix === '?' || suffix === '*'; | ||
/** | ||
* Expose a function for taking tokens and returning a RegExp. | ||
* | ||
* @param {Array} tokens | ||
* @param {Array} keys | ||
* @param {Object} options | ||
* @return {RegExp} | ||
*/ | ||
function tokensToRegExp (tokens, options) { | ||
options = options || {} | ||
keys.push({ | ||
name: key || index++, | ||
delimiter: prefix || '/', | ||
optional: optional, | ||
repeat: repeat | ||
}); | ||
var strict = options.strict | ||
var end = options.end !== false | ||
var route = '' | ||
var lastToken = tokens[tokens.length - 1] | ||
var endsWithSlash = typeof lastToken === 'string' && /\/$/.test(lastToken) | ||
prefix = prefix ? ('\\' + prefix) : ''; | ||
capture = escapeGroup(capture || group || '[^' + (prefix || '\\/') + ']+?'); | ||
// Iterate over the tokens and create our regexp string. | ||
for (var i = 0; i < tokens.length; i++) { | ||
var token = tokens[i] | ||
if (repeat) { | ||
capture = capture + '(?:' + prefix + capture + ')*'; | ||
} | ||
if (typeof token === 'string') { | ||
route += escapeString(token) | ||
} else { | ||
var prefix = escapeString(token.prefix) | ||
var capture = token.pattern | ||
if (optional) { | ||
return '(?:' + prefix + '(' + capture + '))?'; | ||
if (token.repeat) { | ||
capture += '(?:' + prefix + capture + ')*' | ||
} | ||
if (token.optional) { | ||
if (prefix) { | ||
capture = '(?:' + prefix + '(' + capture + '))?' | ||
} else { | ||
capture = '(' + capture + ')?' | ||
} | ||
} else { | ||
capture = prefix + '(' + capture + ')' | ||
} | ||
route += capture | ||
} | ||
} | ||
// Basic parameter support. | ||
return prefix + '(' + capture + ')'; | ||
// In non-strict mode we allow a slash at the end of match. If the path to | ||
// match already ends with a slash, we remove it for consistency. The slash | ||
// is valid at the end of a path match, not in the middle. This is important | ||
// in non-ending mode, where "/test/" shouldn't match "/test//route". | ||
if (!strict) { | ||
route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?' | ||
} | ||
return path.replace(PATH_REGEXP, replace); | ||
if (end) { | ||
route += '$' | ||
} else { | ||
// In non-ending mode, we need the capturing groups to match as much as | ||
// possible by using a positive lookahead to the end or next path segment. | ||
route += strict && endsWithSlash ? '' : '(?=\\/|$)' | ||
} | ||
return new RegExp('^' + route, flags(options)) | ||
} | ||
@@ -919,41 +1133,20 @@ | ||
function pathToRegexp (path, keys, options) { | ||
keys = keys || []; | ||
keys = keys || [] | ||
if (!isArray(keys)) { | ||
options = keys; | ||
keys = []; | ||
if (!isarray(keys)) { | ||
options = keys | ||
keys = [] | ||
} else if (!options) { | ||
options = {}; | ||
options = {} | ||
} | ||
if (path instanceof RegExp) { | ||
return regexpToRegexp(path, keys, options); | ||
return regexpToRegexp(path, keys, options) | ||
} | ||
if (isArray(path)) { | ||
return arrayToRegexp(path, keys, options); | ||
if (isarray(path)) { | ||
return arrayToRegexp(path, keys, options) | ||
} | ||
var strict = options.strict; | ||
var end = options.end !== false; | ||
var route = replacePath(path, keys); | ||
var endsWithSlash = path.charAt(path.length - 1) === '/'; | ||
// In non-strict mode we allow a slash at the end of match. If the path to | ||
// match already ends with a slash, we remove it for consistency. The slash | ||
// is valid at the end of a path match, not in the middle. This is important | ||
// in non-ending mode, where "/test/" shouldn't match "/test//route". | ||
if (!strict) { | ||
route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?'; | ||
} | ||
if (end) { | ||
route += '$'; | ||
} else { | ||
// In non-ending mode, we need the capturing groups to match as much as | ||
// possible by using a positive lookahead to the end or next path segment. | ||
route += strict && endsWithSlash ? '' : '(?=\\/|$)'; | ||
} | ||
return attachKeys(new RegExp('^' + route, flags(options)), keys); | ||
return stringToRegexp(path, keys, options) | ||
} | ||
@@ -960,0 +1153,0 @@ |
@@ -30,8 +30,2 @@  | ||
Via CDN and script tag: | ||
```html | ||
<script src="https://cdn.rawgit.com/visionmedia/page.js/master/page.js"></script> | ||
``` | ||
## Running examples | ||
@@ -270,2 +264,13 @@ | ||
### Non-URL symbols in paths | ||
When writing a path for routing, be aware that any symbols | ||
that normally require URL-encoding to appear in a URL will | ||
need to be URL-encoded in the registered path. | ||
```js | ||
page('/this won't work'); | ||
page('this%20will'); | ||
``` | ||
### Default 404 behaviour | ||
@@ -272,0 +277,0 @@ |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
61753
0
1482
543
2
+ Addedpath-to-regexp@1.2.1(transitive)
- Removedpath-to-regexp@1.0.3(transitive)
Updatedpath-to-regexp@~1.2.1