diff --git a/examples/index.html b/examples/index.html index ef4755f..9a547c9 100644 --- a/examples/index.html +++ b/examples/index.html @@ -251,6 +251,7 @@

JSV: JSON Schema Validator

+ diff --git a/lib/uri/schemes/urn.js b/lib/uri/schemes/urn.js new file mode 100644 index 0000000..82f48de --- /dev/null +++ b/lib/uri/schemes/urn.js @@ -0,0 +1,86 @@ +(function () { + var URI_NS = require("../uri"), + URI = URI_NS.URI, + pctEncChar = URI_NS.pctEncChar, + NID$ = "(?:[0-9A-Za-z][0-9A-Za-z\\-]{1,31})", + PCT_ENCODED$ = "(?:\\%[0-9A-Fa-f]{2})", + TRANS$$ = "[0-9A-Za-z\\(\\)\\+\\,\\-\\.\\:\\=\\@\\;\\$\\_\\!\\*\\'\\/\\?\\#]", + NSS$ = "(?:(?:" + PCT_ENCODED$ + "|" + TRANS$$ + ")+)", + URN_SCHEME = new RegExp("^urn\\:(" + NID$ + ")$"), + URN_PATH = new RegExp("^(" + NID$ + ")\\:(" + NSS$ + ")$"), + URN_PARSE = /^([^\:]+)\:(.*)/, + URN_EXCLUDED = /[\x00-\x20\\\"\&\<\>\[\]\^\`\{\|\}\~\x7F-\xFF]/g, + UUID = /^[0-9A-Fa-f]{8}(?:\-[0-9A-Fa-f]{4}){3}\-[0-9A-Fa-f]{12}$/; + + //RFC 2141 + URI.SCHEMES["urn"] = { + parse : function (components, options) { + var matches = components.path.match(URN_PATH), + scheme, schemeHandler; + + if (!matches) { + if (!options.tolerant) { + components.errors.push("URN is not strictly valid."); + } + + matches = components.path.match(URN_PARSE); + } + + if (matches) { + scheme = "urn:" + matches[1].toLowerCase(); + schemeHandler = URI.SCHEMES[scheme]; + + //in order to serialize properly, + //every URN must have a serializer that calls the URN serializer + if (!schemeHandler) { + schemeHandler = URI.SCHEMES[scheme] = {}; + } + if (!schemeHandler.serialize) { + schemeHandler.serialize = URI.SCHEMES["urn"].serialize; + } + + components.scheme = scheme; + components.path = matches[2]; + + if (schemeHandler.parse) { + schemeHandler.parse(components, options); + } + } else { + components.errors.push("URN can not be parsed."); + } + + return components; + }, + + serialize : function (components, options) { + var scheme = components.scheme || options.scheme, + matches; + + if (scheme && scheme !== "urn") { + var matches = scheme.match(URN_SCHEME); + + if (!matches) { + matches = ["urn:" + scheme, scheme]; + } + + components.scheme = "urn"; + components.path = matches[1] + ":" + (components.path ? components.path.replace(URN_EXCLUDED, pctEncChar) : ""); + } + + return components; + } + }; + + //RFC 4122 + URI.SCHEMES["urn:uuid"] = { + serialize : function (components, options) { + //ensure UUID is valid + if (!options.tolerant && (!components.path || !components.path.match(UUID))) { + //invalid UUIDs can not have this scheme + components.scheme = undefined; + } + + return URI.SCHEMES["urn"].serialize(components, options); + } + }; +}()); \ No newline at end of file diff --git a/lib/uri/tests/index.html b/lib/uri/tests/index.html deleted file mode 100644 index 1f76ce3..0000000 --- a/lib/uri/tests/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - -

URI.js Test Suite

-

-
-

-
    - - \ No newline at end of file diff --git a/lib/uri/tests/qunit.css b/lib/uri/tests/qunit.css deleted file mode 100644 index 861c40d..0000000 --- a/lib/uri/tests/qunit.css +++ /dev/null @@ -1,118 +0,0 @@ -ol#qunit-tests { - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - margin:0; - padding:0; - list-style-position:inside; - - font-size: smaller; -} -ol#qunit-tests li{ - padding:0.4em 0.5em 0.4em 2.5em; - border-bottom:1px solid #fff; - font-size:small; - list-style-position:inside; -} -ol#qunit-tests li ol{ - box-shadow: inset 0px 2px 13px #999; - -moz-box-shadow: inset 0px 2px 13px #999; - -webkit-box-shadow: inset 0px 2px 13px #999; - margin-top:0.5em; - margin-left:0; - padding:0.5em; - background-color:#fff; - border-radius:15px; - -moz-border-radius: 15px; - -webkit-border-radius: 15px; -} -ol#qunit-tests li li{ - border-bottom:none; - margin:0.5em; - background-color:#fff; - list-style-position: inside; - padding:0.4em 0.5em 0.4em 0.5em; -} - -ol#qunit-tests li li.pass{ - border-left:26px solid #C6E746; - background-color:#fff; - color:#5E740B; - } -ol#qunit-tests li li.fail{ - border-left:26px solid #EE5757; - background-color:#fff; - color:#710909; -} -ol#qunit-tests li.pass{ - background-color:#D2E0E6; - color:#528CE0; -} -ol#qunit-tests li.fail{ - background-color:#EE5757; - color:#000; -} -ol#qunit-tests li strong { - cursor:pointer; -} -h1#qunit-header{ - background-color:#0d3349; - margin:0; - padding:0.5em 0 0.5em 1em; - color:#fff; - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - border-top-right-radius:15px; - border-top-left-radius:15px; - -moz-border-radius-topright:15px; - -moz-border-radius-topleft:15px; - -webkit-border-top-right-radius:15px; - -webkit-border-top-left-radius:15px; - text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px; -} -h2#qunit-banner{ - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - height:5px; - margin:0; - padding:0; -} -h2#qunit-banner.qunit-pass{ - background-color:#C6E746; -} -h2#qunit-banner.qunit-fail, #qunit-testrunner-toolbar { - background-color:#EE5757; -} -#qunit-testrunner-toolbar { - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - padding:0; - /*width:80%;*/ - padding:0em 0 0.5em 2em; - font-size: small; -} -h2#qunit-userAgent { - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - background-color:#2b81af; - margin:0; - padding:0; - color:#fff; - font-size: small; - padding:0.5em 0 0.5em 2.5em; - text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; -} -p#qunit-testresult{ - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - margin:0; - font-size: small; - color:#2b81af; - border-bottom-right-radius:15px; - border-bottom-left-radius:15px; - -moz-border-radius-bottomright:15px; - -moz-border-radius-bottomleft:15px; - -webkit-border-bottom-right-radius:15px; - -webkit-border-bottom-left-radius:15px; - background-color:#D2E0E6; - padding:0.5em 0.5em 0.5em 2.5em; -} -strong b.fail{ - color:#710909; - } -strong b.pass{ - color:#5E740B; - } \ No newline at end of file diff --git a/lib/uri/tests/qunit.js b/lib/uri/tests/qunit.js deleted file mode 100644 index f050a08..0000000 --- a/lib/uri/tests/qunit.js +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * QUnit - A JavaScript Unit Testing Framework - * - * http://docs.jquery.com/QUnit - * - * Copyright (c) 2009 John Resig, Jörn Zaefferer - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - */ - -(function(window) { - -var QUnit = { - - // Initialize the configuration options - init: function() { - config = { - stats: { all: 0, bad: 0 }, - moduleStats: { all: 0, bad: 0 }, - started: +new Date, - blocking: false, - autorun: false, - assertions: [], - filters: [], - queue: [] - }; - - var tests = id("qunit-tests"), - banner = id("qunit-banner"), - result = id("qunit-testresult"); - - if ( tests ) { - tests.innerHTML = ""; - } - - if ( banner ) { - banner.className = ""; - } - - if ( result ) { - result.parentNode.removeChild( result ); - } - }, - - // call on start of module test to prepend name to all tests - module: function(name, testEnvironment) { - config.currentModule = name; - - synchronize(function() { - if ( config.currentModule ) { - QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all ); - } - - config.currentModule = name; - config.moduleTestEnvironment = testEnvironment; - config.moduleStats = { all: 0, bad: 0 }; - - QUnit.moduleStart( name, testEnvironment ); - }); - }, - - asyncTest: function(testName, expected, callback) { - if ( arguments.length === 2 ) { - callback = expected; - expected = 0; - } - - QUnit.test(testName, expected, callback, true); - }, - - test: function(testName, expected, callback, async) { - var name = testName, testEnvironment, testEnvironmentArg; - - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - // is 2nd argument a testEnvironment? - if ( expected && typeof expected === 'object') { - testEnvironmentArg = expected; - expected = null; - } - - if ( config.currentModule ) { - name = config.currentModule + " module: " + name; - } - - if ( !validTest(name) ) { - return; - } - - synchronize(function() { - QUnit.testStart( testName ); - - testEnvironment = extend({ - setup: function() {}, - teardown: function() {} - }, config.moduleTestEnvironment); - if (testEnvironmentArg) { - extend(testEnvironment,testEnvironmentArg); - } - - // allow utility functions to access the current test environment - QUnit.current_testEnvironment = testEnvironment; - - config.assertions = []; - config.expected = expected; - - try { - if ( !config.pollution ) { - saveGlobal(); - } - - testEnvironment.setup.call(testEnvironment); - } catch(e) { - QUnit.ok( false, "Setup failed on " + name + ": " + e.message ); - } - - if ( async ) { - QUnit.stop(); - } - - try { - callback.call(testEnvironment); - } catch(e) { - fail("Test " + name + " died, exception and test follows", e, callback); - QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message ); - // else next test will carry the responsibility - saveGlobal(); - - // Restart the tests if they're blocking - if ( config.blocking ) { - start(); - } - } - }); - - synchronize(function() { - try { - checkPollution(); - testEnvironment.teardown.call(testEnvironment); - } catch(e) { - QUnit.ok( false, "Teardown failed on " + name + ": " + e.message ); - } - - try { - QUnit.reset(); - } catch(e) { - fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset); - } - - if ( config.expected && config.expected != config.assertions.length ) { - QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" ); - } - - var good = 0, bad = 0, - tests = id("qunit-tests"); - - config.stats.all += config.assertions.length; - config.moduleStats.all += config.assertions.length; - - if ( tests ) { - var ol = document.createElement("ol"); - ol.style.display = "none"; - - for ( var i = 0; i < config.assertions.length; i++ ) { - var assertion = config.assertions[i]; - - var li = document.createElement("li"); - li.className = assertion.result ? "pass" : "fail"; - li.appendChild(document.createTextNode(assertion.message || "(no message)")); - ol.appendChild( li ); - - if ( assertion.result ) { - good++; - } else { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - - var b = document.createElement("strong"); - b.innerHTML = name + " (" + bad + ", " + good + ", " + config.assertions.length + ")"; - - addEvent(b, "click", function() { - var next = b.nextSibling, display = next.style.display; - next.style.display = display === "none" ? "block" : "none"; - }); - - addEvent(b, "dblclick", function(e) { - var target = e && e.target ? e.target : window.event.srcElement; - if ( target.nodeName.toLowerCase() === "strong" ) { - var text = "", node = target.firstChild; - - while ( node.nodeType === 3 ) { - text += node.nodeValue; - node = node.nextSibling; - } - - text = text.replace(/(^\s*|\s*$)/g, ""); - - if ( window.location ) { - window.location.href = window.location.href.match(/^(.+?)(\?.*)?$/)[1] + "?" + encodeURIComponent(text); - } - } - }); - - var li = document.createElement("li"); - li.className = bad ? "fail" : "pass"; - li.appendChild( b ); - li.appendChild( ol ); - tests.appendChild( li ); - - if ( bad ) { - var toolbar = id("qunit-testrunner-toolbar"); - if ( toolbar ) { - toolbar.style.display = "block"; - id("qunit-filter-pass").disabled = null; - id("qunit-filter-missing").disabled = null; - } - } - - } else { - for ( var i = 0; i < config.assertions.length; i++ ) { - if ( !config.assertions[i].result ) { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - } - - QUnit.testDone( testName, bad, config.assertions.length ); - - if ( !window.setTimeout && !config.queue.length ) { - done(); - } - }); - - if ( window.setTimeout && !config.doneTimer ) { - config.doneTimer = window.setTimeout(function(){ - if ( !config.queue.length ) { - done(); - } else { - synchronize( done ); - } - }, 13); - } - }, - - /** - * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. - */ - expect: function(asserts) { - config.expected = asserts; - }, - - /** - * Asserts true. - * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); - */ - ok: function(a, msg) { - QUnit.log(a, msg); - - config.assertions.push({ - result: !!a, - message: msg - }); - }, - - /** - * Checks that the first two arguments are equal, with an optional message. - * Prints out both actual and expected values. - * - * Prefered to ok( actual == expected, message ) - * - * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." ); - * - * @param Object actual - * @param Object expected - * @param String message (optional) - */ - equal: function(actual, expected, message) { - push(expected == actual, actual, expected, message); - }, - - notEqual: function(actual, expected, message) { - push(expected != actual, actual, expected, message); - }, - - deepEqual: function(a, b, message) { - push(QUnit.equiv(a, b), a, b, message); - }, - - notDeepEqual: function(a, b, message) { - push(!QUnit.equiv(a, b), a, b, message); - }, - - strictEqual: function(actual, expected, message) { - push(expected === actual, actual, expected, message); - }, - - notStrictEqual: function(actual, expected, message) { - push(expected !== actual, actual, expected, message); - }, - - start: function() { - // A slight delay, to avoid any current callbacks - if ( window.setTimeout ) { - window.setTimeout(function() { - if ( config.timeout ) { - clearTimeout(config.timeout); - } - - config.blocking = false; - process(); - }, 13); - } else { - config.blocking = false; - process(); - } - }, - - stop: function(timeout) { - config.blocking = true; - - if ( timeout && window.setTimeout ) { - config.timeout = window.setTimeout(function() { - QUnit.ok( false, "Test timed out" ); - QUnit.start(); - }, timeout); - } - }, - - /** - * Resets the test setup. Useful for tests that modify the DOM. - */ - reset: function() { - if ( window.jQuery ) { - jQuery("#main").html( config.fixture ); - jQuery.event.global = {}; - jQuery.ajaxSettings = extend({}, config.ajaxSettings); - } - }, - - /** - * Trigger an event on an element. - * - * @example triggerEvent( document.body, "click" ); - * - * @param DOMElement elem - * @param String type - */ - triggerEvent: function( elem, type, event ) { - if ( document.createEvent ) { - event = document.createEvent("MouseEvents"); - event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, - 0, 0, 0, 0, 0, false, false, false, false, 0, null); - elem.dispatchEvent( event ); - - } else if ( elem.fireEvent ) { - elem.fireEvent("on"+type); - } - }, - - // Safe object type checking - is: function( type, obj ) { - return Object.prototype.toString.call( obj ) === "[object "+ type +"]"; - }, - - // Logging callbacks - done: function(failures, total) {}, - log: function(result, message) {}, - testStart: function(name) {}, - testDone: function(name, failures, total) {}, - moduleStart: function(name, testEnvironment) {}, - moduleDone: function(name, failures, total) {} -}; - -// Backwards compatibility, deprecated -QUnit.equals = QUnit.equal; -QUnit.same = QUnit.deepEqual; - -// Maintain internal state -var config = { - // The queue of tests to run - queue: [], - - // block until document ready - blocking: true -}; - -// Load paramaters -(function() { - var location = window.location || { search: "", protocol: "file:" }, - GETParams = location.search.slice(1).split('&'); - - for ( var i = 0; i < GETParams.length; i++ ) { - GETParams[i] = decodeURIComponent( GETParams[i] ); - if ( GETParams[i] === "noglobals" ) { - GETParams.splice( i, 1 ); - i--; - config.noglobals = true; - } else if ( GETParams[i].search('=') > -1 ) { - GETParams.splice( i, 1 ); - i--; - } - } - - // restrict modules/tests by get parameters - config.filters = GETParams; - - // Figure out if we're running the tests from a server or not - QUnit.isLocal = !!(location.protocol === 'file:'); -})(); - -// Expose the API as global variables, unless an 'exports' -// object exists, in that case we assume we're in CommonJS -if ( typeof exports === "undefined" || typeof require === "undefined" ) { - extend(window, QUnit); - window.QUnit = QUnit; -} else { - extend(exports, QUnit); - exports.QUnit = QUnit; -} - -if ( typeof document === "undefined" || document.readyState === "complete" ) { - config.autorun = true; -} - -addEvent(window, "load", function() { - // Initialize the config, saving the execution queue - var oldconfig = extend({}, config); - QUnit.init(); - extend(config, oldconfig); - - config.blocking = false; - - var userAgent = id("qunit-userAgent"); - if ( userAgent ) { - userAgent.innerHTML = navigator.userAgent; - } - - var toolbar = id("qunit-testrunner-toolbar"); - if ( toolbar ) { - toolbar.style.display = "none"; - - var filter = document.createElement("input"); - filter.type = "checkbox"; - filter.id = "qunit-filter-pass"; - filter.disabled = true; - addEvent( filter, "click", function() { - var li = document.getElementsByTagName("li"); - for ( var i = 0; i < li.length; i++ ) { - if ( li[i].className.indexOf("pass") > -1 ) { - li[i].style.display = filter.checked ? "none" : ""; - } - } - }); - toolbar.appendChild( filter ); - - var label = document.createElement("label"); - label.setAttribute("for", "qunit-filter-pass"); - label.innerHTML = "Hide passed tests"; - toolbar.appendChild( label ); - - var missing = document.createElement("input"); - missing.type = "checkbox"; - missing.id = "qunit-filter-missing"; - missing.disabled = true; - addEvent( missing, "click", function() { - var li = document.getElementsByTagName("li"); - for ( var i = 0; i < li.length; i++ ) { - if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) { - li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block"; - } - } - }); - toolbar.appendChild( missing ); - - label = document.createElement("label"); - label.setAttribute("for", "qunit-filter-missing"); - label.innerHTML = "Hide missing tests (untested code is broken code)"; - toolbar.appendChild( label ); - } - - var main = id('main'); - if ( main ) { - config.fixture = main.innerHTML; - } - - if ( window.jQuery ) { - config.ajaxSettings = window.jQuery.ajaxSettings; - } - - QUnit.start(); -}); - -function done() { - if ( config.doneTimer && window.clearTimeout ) { - window.clearTimeout( config.doneTimer ); - config.doneTimer = null; - } - - if ( config.queue.length ) { - config.doneTimer = window.setTimeout(function(){ - if ( !config.queue.length ) { - done(); - } else { - synchronize( done ); - } - }, 13); - - return; - } - - config.autorun = true; - - // Log the last module results - if ( config.currentModule ) { - QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all ); - } - - var banner = id("qunit-banner"), - tests = id("qunit-tests"), - html = ['Tests completed in ', - +new Date - config.started, ' milliseconds.
    ', - '', config.stats.all - config.stats.bad, ' tests of ', config.stats.all, ' passed, ', config.stats.bad,' failed.'].join(''); - - if ( banner ) { - banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass"); - } - - if ( tests ) { - var result = id("qunit-testresult"); - - if ( !result ) { - result = document.createElement("p"); - result.id = "qunit-testresult"; - result.className = "result"; - tests.parentNode.insertBefore( result, tests.nextSibling ); - } - - result.innerHTML = html; - } - - QUnit.done( config.stats.bad, config.stats.all ); -} - -function validTest( name ) { - var i = config.filters.length, - run = false; - - if ( !i ) { - return true; - } - - while ( i-- ) { - var filter = config.filters[i], - not = filter.charAt(0) == '!'; - - if ( not ) { - filter = filter.slice(1); - } - - if ( name.indexOf(filter) !== -1 ) { - return !not; - } - - if ( not ) { - run = true; - } - } - - return run; -} - -function push(result, actual, expected, message) { - message = message || (result ? "okay" : "failed"); - QUnit.ok( result, result ? message + ": " + expected : message + ", expected: " + QUnit.jsDump.parse(expected) + " result: " + QUnit.jsDump.parse(actual) ); -} - -function synchronize( callback ) { - config.queue.push( callback ); - - if ( config.autorun && !config.blocking ) { - process(); - } -} - -function process() { - while ( config.queue.length && !config.blocking ) { - config.queue.shift()(); - } -} - -function saveGlobal() { - config.pollution = []; - - if ( config.noglobals ) { - for ( var key in window ) { - config.pollution.push( key ); - } - } -} - -function checkPollution( name ) { - var old = config.pollution; - saveGlobal(); - - var newGlobals = diff( old, config.pollution ); - if ( newGlobals.length > 0 ) { - ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); - config.expected++; - } - - var deletedGlobals = diff( config.pollution, old ); - if ( deletedGlobals.length > 0 ) { - ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); - config.expected++; - } -} - -// returns a new Array with the elements that are in a but not in b -function diff( a, b ) { - var result = a.slice(); - for ( var i = 0; i < result.length; i++ ) { - for ( var j = 0; j < b.length; j++ ) { - if ( result[i] === b[j] ) { - result.splice(i, 1); - i--; - break; - } - } - } - return result; -} - -function fail(message, exception, callback) { - if ( typeof console !== "undefined" && console.error && console.warn ) { - console.error(message); - console.error(exception); - console.warn(callback.toString()); - - } else if ( window.opera && opera.postError ) { - opera.postError(message, exception, callback.toString); - } -} - -function extend(a, b) { - for ( var prop in b ) { - a[prop] = b[prop]; - } - - return a; -} - -function addEvent(elem, type, fn) { - if ( elem.addEventListener ) { - elem.addEventListener( type, fn, false ); - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, fn ); - } else { - fn(); - } -} - -function id(name) { - return !!(typeof document !== "undefined" && document && document.getElementById) && - document.getElementById( name ); -} - -// Test for equality any JavaScript type. -// Discussions and reference: http://philrathe.com/articles/equiv -// Test suites: http://philrathe.com/tests/equiv -// Author: Philippe Rathé -QUnit.equiv = function () { - - var innerEquiv; // the real equiv function - var callers = []; // stack to decide between skip/abort functions - - - // Determine what is o. - function hoozit(o) { - if (QUnit.is("String", o)) { - return "string"; - - } else if (QUnit.is("Boolean", o)) { - return "boolean"; - - } else if (QUnit.is("Number", o)) { - - if (isNaN(o)) { - return "nan"; - } else { - return "number"; - } - - } else if (typeof o === "undefined") { - return "undefined"; - - // consider: typeof null === object - } else if (o === null) { - return "null"; - - // consider: typeof [] === object - } else if (QUnit.is( "Array", o)) { - return "array"; - - // consider: typeof new Date() === object - } else if (QUnit.is( "Date", o)) { - return "date"; - - // consider: /./ instanceof Object; - // /./ instanceof RegExp; - // typeof /./ === "function"; // => false in IE and Opera, - // true in FF and Safari - } else if (QUnit.is( "RegExp", o)) { - return "regexp"; - - } else if (typeof o === "object") { - return "object"; - - } else if (QUnit.is( "Function", o)) { - return "function"; - } else { - return undefined; - } - } - - // Call the o related callback with the given arguments. - function bindCallbacks(o, callbacks, args) { - var prop = hoozit(o); - if (prop) { - if (hoozit(callbacks[prop]) === "function") { - return callbacks[prop].apply(callbacks, args); - } else { - return callbacks[prop]; // or undefined - } - } - } - - var callbacks = function () { - - // for string, boolean, number and null - function useStrictEquality(b, a) { - if (b instanceof a.constructor || a instanceof b.constructor) { - // to catch short annotaion VS 'new' annotation of a declaration - // e.g. var i = 1; - // var j = new Number(1); - return a == b; - } else { - return a === b; - } - } - - return { - "string": useStrictEquality, - "boolean": useStrictEquality, - "number": useStrictEquality, - "null": useStrictEquality, - "undefined": useStrictEquality, - - "nan": function (b) { - return isNaN(b); - }, - - "date": function (b, a) { - return hoozit(b) === "date" && a.valueOf() === b.valueOf(); - }, - - "regexp": function (b, a) { - return hoozit(b) === "regexp" && - a.source === b.source && // the regex itself - a.global === b.global && // and its modifers (gmi) ... - a.ignoreCase === b.ignoreCase && - a.multiline === b.multiline; - }, - - // - skip when the property is a method of an instance (OOP) - // - abort otherwise, - // initial === would have catch identical references anyway - "function": function () { - var caller = callers[callers.length - 1]; - return caller !== Object && - typeof caller !== "undefined"; - }, - - "array": function (b, a) { - var i; - var len; - - // b could be an object literal here - if ( ! (hoozit(b) === "array")) { - return false; - } - - len = a.length; - if (len !== b.length) { // safe and faster - return false; - } - for (i = 0; i < len; i++) { - if ( ! innerEquiv(a[i], b[i])) { - return false; - } - } - return true; - }, - - "object": function (b, a) { - var i; - var eq = true; // unless we can proove it - var aProperties = [], bProperties = []; // collection of strings - - // comparing constructors is more strict than using instanceof - if ( a.constructor !== b.constructor) { - return false; - } - - // stack constructor before traversing properties - callers.push(a.constructor); - - for (i in a) { // be strict: don't ensures hasOwnProperty and go deep - - aProperties.push(i); // collect a's properties - - if ( ! innerEquiv(a[i], b[i])) { - eq = false; - } - } - - callers.pop(); // unstack, we are done - - for (i in b) { - bProperties.push(i); // collect b's properties - } - - // Ensures identical properties name - return eq && innerEquiv(aProperties.sort(), bProperties.sort()); - } - }; - }(); - - innerEquiv = function () { // can take multiple arguments - var args = Array.prototype.slice.apply(arguments); - if (args.length < 2) { - return true; // end transition - } - - return (function (a, b) { - if (a === b) { - return true; // catch the most you can - } else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || hoozit(a) !== hoozit(b)) { - return false; // don't lose time with error prone cases - } else { - return bindCallbacks(a, callbacks, [b, a]); - } - - // apply transition with (1..n) arguments - })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1)); - }; - - return innerEquiv; - -}(); - -/** - * jsDump - * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com - * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php) - * Date: 5/15/2008 - * @projectDescription Advanced and extensible data dumping for Javascript. - * @version 1.0.0 - * @author Ariel Flesler - * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html} - */ -QUnit.jsDump = (function() { - function quote( str ) { - return '"' + str.toString().replace(/"/g, '\\"') + '"'; - }; - function literal( o ) { - return o + ''; - }; - function join( pre, arr, post ) { - var s = jsDump.separator(), - base = jsDump.indent(), - inner = jsDump.indent(1); - if ( arr.join ) - arr = arr.join( ',' + s + inner ); - if ( !arr ) - return pre + post; - return [ pre, inner + arr, base + post ].join(s); - }; - function array( arr ) { - var i = arr.length, ret = Array(i); - this.up(); - while ( i-- ) - ret[i] = this.parse( arr[i] ); - this.down(); - return join( '[', ret, ']' ); - }; - - var reName = /^function (\w+)/; - - var jsDump = { - parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance - var parser = this.parsers[ type || this.typeOf(obj) ]; - type = typeof parser; - - return type == 'function' ? parser.call( this, obj ) : - type == 'string' ? parser : - this.parsers.error; - }, - typeOf:function( obj ) { - var type; - if ( obj === null ) { - type = "null"; - } else if (typeof obj === "undefined") { - type = "undefined"; - } else if (QUnit.is("RegExp", obj)) { - type = "regexp"; - } else if (QUnit.is("Date", obj)) { - type = "date"; - } else if (QUnit.is("Function", obj)) { - type = "function"; - } else if (QUnit.is("Array", obj)) { - type = "array"; - } else if (QUnit.is("Window", obj) || QUnit.is("global", obj)) { - type = "window"; - } else if (QUnit.is("HTMLDocument", obj)) { - type = "document"; - } else if (QUnit.is("HTMLCollection", obj) || QUnit.is("NodeList", obj)) { - type = "nodelist"; - } else if (/^\[object HTML/.test(Object.prototype.toString.call( obj ))) { - type = "node"; - } else { - type = typeof obj; - } - return type; - }, - separator:function() { - return this.multiline ? this.HTML ? '
    ' : '\n' : this.HTML ? ' ' : ' '; - }, - indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing - if ( !this.multiline ) - return ''; - var chr = this.indentChar; - if ( this.HTML ) - chr = chr.replace(/\t/g,' ').replace(/ /g,' '); - return Array( this._depth_ + (extra||0) ).join(chr); - }, - up:function( a ) { - this._depth_ += a || 1; - }, - down:function( a ) { - this._depth_ -= a || 1; - }, - setParser:function( name, parser ) { - this.parsers[name] = parser; - }, - // The next 3 are exposed so you can use them - quote:quote, - literal:literal, - join:join, - // - _depth_: 1, - // This is the list of parsers, to modify them, use jsDump.setParser - parsers:{ - window: '[Window]', - document: '[Document]', - error:'[ERROR]', //when no parser is found, shouldn't happen - unknown: '[Unknown]', - 'null':'null', - undefined:'undefined', - 'function':function( fn ) { - var ret = 'function', - name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE - if ( name ) - ret += ' ' + name; - ret += '('; - - ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join(''); - return join( ret, this.parse(fn,'functionCode'), '}' ); - }, - array: array, - nodelist: array, - arguments: array, - object:function( map ) { - var ret = [ ]; - this.up(); - for ( var key in map ) - ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) ); - this.down(); - return join( '{', ret, '}' ); - }, - node:function( node ) { - var open = this.HTML ? '<' : '<', - close = this.HTML ? '>' : '>'; - - var tag = node.nodeName.toLowerCase(), - ret = open + tag; - - for ( var a in this.DOMAttrs ) { - var val = node[this.DOMAttrs[a]]; - if ( val ) - ret += ' ' + a + '=' + this.parse( val, 'attribute' ); - } - return ret + close + open + '/' + tag + close; - }, - functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function - var l = fn.length; - if ( !l ) return ''; - - var args = Array(l); - while ( l-- ) - args[l] = String.fromCharCode(97+l);//97 is 'a' - return ' ' + args.join(', ') + ' '; - }, - key:quote, //object calls it internally, the key part of an item in a map - functionCode:'[code]', //function calls it internally, it's the content of the function - attribute:quote, //node calls it internally, it's an html attribute value - string:quote, - date:quote, - regexp:literal, //regex - number:literal, - 'boolean':literal - }, - DOMAttrs:{//attributes to dump from nodes, name=>realName - id:'id', - name:'name', - 'class':'className' - }, - HTML:true,//if true, entities are escaped ( <, >, \t, space and \n ) - indentChar:' ',//indentation unit - multiline:true //if true, items in a collection, are separated by a \n, else just a space. - }; - - return jsDump; -})(); - -})(this); \ No newline at end of file diff --git a/lib/uri/tests/tests.js b/lib/uri/tests/tests.js deleted file mode 100644 index c6d5162..0000000 --- a/lib/uri/tests/tests.js +++ /dev/null @@ -1,210 +0,0 @@ -// -// -// Tests -// -// - -test("Acquire URI", function () { - URI = require("./uri").URI; - ok(URI); -}); - -test("URI Parsing", function () { - var components; - - //scheme - components = URI.parse("uri:"); - equal(components.scheme, "uri", "scheme"); - equal(components.authority, undefined, "authority"); - equal(components.userinfo, undefined, "userinfo"); - equal(components.host, undefined, "host"); - equal(components.port, undefined, "port"); - equal(components.path, "", "path"); - equal(components.query, undefined, "query"); - equal(components.fragment, undefined, "fragment"); - - //userinfo - components = URI.parse("//@"); - equal(components.scheme, undefined, "scheme"); - equal(components.authority, "@", "authority"); - equal(components.userinfo, "", "userinfo"); - equal(components.host, "", "host"); - equal(components.port, undefined, "port"); - equal(components.path, "", "path"); - equal(components.query, undefined, "query"); - equal(components.fragment, undefined, "fragment"); - - //host - components = URI.parse("//"); - equal(components.scheme, undefined, "scheme"); - equal(components.authority, "", "authority"); - equal(components.userinfo, undefined, "userinfo"); - equal(components.host, "", "host"); - equal(components.port, undefined, "port"); - equal(components.path, "", "path"); - equal(components.query, undefined, "query"); - equal(components.fragment, undefined, "fragment"); - - //port - components = URI.parse("//:"); - equal(components.scheme, undefined, "scheme"); - equal(components.authority, ":", "authority"); - equal(components.userinfo, undefined, "userinfo"); - equal(components.host, "", "host"); - equal(components.port, "", "port"); - equal(components.path, "", "path"); - equal(components.query, undefined, "query"); - equal(components.fragment, undefined, "fragment"); - - //path - components = URI.parse(""); - equal(components.scheme, undefined, "scheme"); - equal(components.authority, undefined, "authority"); - equal(components.userinfo, undefined, "userinfo"); - equal(components.host, undefined, "host"); - equal(components.port, undefined, "port"); - equal(components.path, "", "path"); - equal(components.query, undefined, "query"); - equal(components.fragment, undefined, "fragment"); - - //query - components = URI.parse("?"); - equal(components.scheme, undefined, "scheme"); - equal(components.authority, undefined, "authority"); - equal(components.userinfo, undefined, "userinfo"); - equal(components.host, undefined, "host"); - equal(components.port, undefined, "port"); - equal(components.path, "", "path"); - equal(components.query, "", "query"); - equal(components.fragment, undefined, "fragment"); - - //fragment - components = URI.parse("#"); - equal(components.scheme, undefined, "scheme"); - equal(components.authority, undefined, "authority"); - equal(components.userinfo, undefined, "userinfo"); - equal(components.host, undefined, "host"); - equal(components.port, undefined, "port"); - equal(components.path, "", "path"); - equal(components.query, undefined, "query"); - equal(components.fragment, "", "fragment"); - - //all - components = URI.parse("uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body"); - equal(components.scheme, "uri", "scheme"); - equal(components.authority, "user:pass@example.com:123", "authority"); - equal(components.userinfo, "user:pass", "userinfo"); - equal(components.host, "example.com", "host"); - equal(components.port, 123, "port"); - equal(components.path, "/one/two.three", "path"); - equal(components.query, "q1=a1&q2=a2", "query"); - equal(components.fragment, "body", "fragment"); -}); - -test("URI Serialization", function () { - var components = { - scheme : "", - userinfo : "", - host : "", - port : 0, - path : "", - query : "", - fragment : "" - }; - equal(URI.serialize(components), "//@:0", "Empty Components"); - - //TODO: NEED MOAR TESTS!! -}); - -test("URI Resolving", function () { - //normal examples from RFC 3986 - var base = "http://a/b/c/d;p?q"; - equal(URI.resolve(base, "g:h"), "g:h", "g:h"); - equal(URI.resolve(base, "g:h"), "g:h", "g:h"); - equal(URI.resolve(base, "g"), "http://a/b/c/g", "g"); - equal(URI.resolve(base, "./g"), "http://a/b/c/g", "./g"); - equal(URI.resolve(base, "g/"), "http://a/b/c/g/", "g/"); - equal(URI.resolve(base, "/g"), "http://a/g", "/g"); - equal(URI.resolve(base, "//g"), "http://g", "//g"); - equal(URI.resolve(base, "?y"), "http://a/b/c/d;p?y", "?y"); - equal(URI.resolve(base, "g?y"), "http://a/b/c/g?y", "g?y"); - equal(URI.resolve(base, "#s"), "http://a/b/c/d;p?q#s", "#s"); - equal(URI.resolve(base, "g#s"), "http://a/b/c/g#s", "g#s"); - equal(URI.resolve(base, "g?y#s"), "http://a/b/c/g?y#s", "g?y#s"); - equal(URI.resolve(base, ";x"), "http://a/b/c/;x", ";x"); - equal(URI.resolve(base, "g;x"), "http://a/b/c/g;x", "g;x"); - equal(URI.resolve(base, "g;x?y#s"), "http://a/b/c/g;x?y#s", "g;x?y#s"); - equal(URI.resolve(base, ""), "http://a/b/c/d;p?q", ""); - equal(URI.resolve(base, "."), "http://a/b/c/", "."); - equal(URI.resolve(base, "./"), "http://a/b/c/", "./"); - equal(URI.resolve(base, ".."), "http://a/b/", ".."); - equal(URI.resolve(base, "../"), "http://a/b/", "../"); - equal(URI.resolve(base, "../g"), "http://a/b/g", "../g"); - equal(URI.resolve(base, "../.."), "http://a/", "../.."); - equal(URI.resolve(base, "../../"), "http://a/", "../../"); - equal(URI.resolve(base, "../../g"), "http://a/g", "../../g"); - - //abnormal examples from RFC 3986 - equal(URI.resolve(base, "../../../g"), "http://a/g", "../../../g"); - equal(URI.resolve(base, "../../../../g"), "http://a/g", "../../../../g"); - - equal(URI.resolve(base, "/./g"), "http://a/g", "/./g"); - equal(URI.resolve(base, "/../g"), "http://a/g", "/../g"); - equal(URI.resolve(base, "g."), "http://a/b/c/g.", "g."); - equal(URI.resolve(base, ".g"), "http://a/b/c/.g", ".g"); - equal(URI.resolve(base, "g.."), "http://a/b/c/g..", "g.."); - equal(URI.resolve(base, "..g"), "http://a/b/c/..g", "..g"); - - equal(URI.resolve(base, "./../g"), "http://a/b/g", "./../g"); - equal(URI.resolve(base, "./g/."), "http://a/b/c/g/", "./g/."); - equal(URI.resolve(base, "g/./h"), "http://a/b/c/g/h", "g/./h"); - equal(URI.resolve(base, "g/../h"), "http://a/b/c/h", "g/../h"); - equal(URI.resolve(base, "g;x=1/./y"), "http://a/b/c/g;x=1/y", "g;x=1/./y"); - equal(URI.resolve(base, "g;x=1/../y"), "http://a/b/c/y", "g;x=1/../y"); - - equal(URI.resolve(base, "g?y/./x"), "http://a/b/c/g?y/./x", "g?y/./x"); - equal(URI.resolve(base, "g?y/../x"), "http://a/b/c/g?y/../x", "g?y/../x"); - equal(URI.resolve(base, "g#s/./x"), "http://a/b/c/g#s/./x", "g#s/./x"); - equal(URI.resolve(base, "g#s/../x"), "http://a/b/c/g#s/../x", "g#s/../x"); - - equal(URI.resolve(base, "http:g"), "http:g", "http:g"); - equal(URI.resolve(base, "http:g", {tolerant:true}), "http://a/b/c/g", "http:g"); - -}); - -test("URI Equals", function () { - //test from RFC 3986 - equal(URI.equal("example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7bfoo%7d"), true); -}); - -test("Escape Component", function () { - var input = "", output = ""; - for (var d = 32; d < 128; ++d) { - input += String.fromCharCode(d); - if (String.fromCharCode(d).match(/[0-9A-Za-z\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=]/)) { - output += String.fromCharCode(d); - } else { - output += "%" + d.toString(16).toUpperCase(); - } - } - input += "\u00c0\u30a2"; - output += "%C3%80%E3%82%A2"; - - equal(URI.escapeComponent(input), output); -}); - -test("Unescape Component", function () { - var input = "", output = ""; - for (var d = 32; d < 128; ++d) { - input += String.fromCharCode(d); - if (String.fromCharCode(d).match(/[0-9A-Za-z\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=]/)) { - output += String.fromCharCode(d); - } else { - output += "%" + d.toString(16).toUpperCase(); - } - } - input += "\u00c0\u30a2"; - output += "%C3%80%E3%82%A2"; - - equal(URI.unescapeComponent(output), input); -}); \ No newline at end of file diff --git a/lib/uri/uri.js b/lib/uri/uri.js index 9d7a176..f8ec077 100644 --- a/lib/uri/uri.js +++ b/lib/uri/uri.js @@ -3,9 +3,9 @@ * * @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/validating/resolving library for JavaScript. * @author Gary Court - * @version 1.2 + * @version 1.3 * @see http://github.com/garycourt/uri-js - * @license URI.js v1.2 (c) 2010 Gary Court. License: http://github.com/garycourt/uri-js + * @license URI.js v1.3 (c) 2010 Gary Court. License: http://github.com/garycourt/uri-js */ /** @@ -244,7 +244,7 @@ if (typeof require !== "function") { }, /** @namespace */ - URI = {}; + URI = exports; /** * Components @@ -410,7 +410,7 @@ if (typeof require !== "function") { } //check if a handler for the scheme exists - schemeHandler = URI.SCHEMES[components.scheme || options.scheme]; + schemeHandler = URI.SCHEMES[(components.scheme || options.scheme || "").toLowerCase()]; if (schemeHandler && schemeHandler.parse) { //perform extra parsing schemeHandler.parse(components, options); @@ -685,10 +685,15 @@ if (typeof require !== "function") { }; //export API + exports.pctEncChar = pctEncChar; + exports.pctDecChars = pctDecChars; exports.Components = Components; exports.URI = URI; //name-safe export API + exports["pctEncChar"] = pctEncChar; + exports["pctDecChars"] = pctDecChars; + exports["Components"] = Components; exports["URI"] = { "SCHEMES" : URI.SCHEMES, "parse" : URI.parse, diff --git a/tests/index.html b/tests/index.html index 5b22825..99407f3 100644 --- a/tests/index.html +++ b/tests/index.html @@ -5,6 +5,7 @@ + diff --git a/tests/index3.html b/tests/index3.html index 634f5b5..13fccac 100644 --- a/tests/index3.html +++ b/tests/index3.html @@ -5,6 +5,7 @@ + diff --git a/tests/index3b.html b/tests/index3b.html index 788e555..798ba99 100644 --- a/tests/index3b.html +++ b/tests/index3b.html @@ -5,6 +5,7 @@ +