Add auth support (#21)

* Updates

* Update

* Update

* Update

* Update

* Yarn sometimes prefers npmrc, so use same token

* Description

* Update readme

* Feedback

* Add type

* new toolkit and scoped registries

* npmrc in RUNNER_TEMP

* Dont always auth

* Try exporting blank token

* Get auth working for now pending runner changes

* Fix string interpolation for auth token.

* Don't export both userconfigs

* Update authutil.js

* Add single quotes for authString

* Fix the registry string.

* Use userconfig and append trailing slash

* Keep in root of repo

* Try just adding auth token

* Remove auth token

* Try changes again

* Add tests

* Npm and GPR samples

* Add types
This commit is contained in:
Danny McCormick 2019-08-06 18:26:04 -04:00 committed by GitHub
parent 0675b87d74
commit 78148dae50
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
391 changed files with 79848 additions and 43 deletions

3
node_modules/url-template/.gitmodules generated vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "uritemplate-test"]
path = uritemplate-test
url = https://github.com/uri-templates/uritemplate-test

1
node_modules/url-template/.npmignore generated vendored Normal file
View file

@ -0,0 +1 @@
/node_modules/

25
node_modules/url-template/LICENSE generated vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2012-2014, Bram Stein
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

32
node_modules/url-template/README.md generated vendored Normal file
View file

@ -0,0 +1,32 @@
## A JavaScript URI template implementation
This is a simple URI template implementation following the [RFC 6570 URI Template specification](http://tools.ietf.org/html/rfc6570). The implementation supports all levels defined in the specification and is extensively tested.
## Installation
For use with Node.js you can install it through npm:
$ npm install url-template
If you want to use it in a browser, copy `lib/url-template.js` into your project and use the global `urltemplate` instance. Alternatively you can use [Bower](http://bower.io/) to install this package:
$ bower install url-template
## Example
var template = require('url-template');
...
var emailUrl = template.parse('/{email}/{folder}/{id}');
// Returns '/user@domain/test/42'
emailUrl.expand({
email: 'user@domain',
folder: 'test',
id: 42
});
## A note on error handling and reporting
The RFC states that errors in the templates could optionally be handled and reported to the user. This implementation takes a slightly different approach in that it tries to do a best effort template expansion and leaves erroneous expressions in the returned URI instead of throwing errors. So for example, the incorrect expression `{unclosed` will return `{unclosed` as output. The leaves incorrect URLs to be handled by your URL library of choice.

192
node_modules/url-template/lib/url-template.js generated vendored Normal file
View file

@ -0,0 +1,192 @@
(function (root, factory) {
if (typeof exports === 'object') {
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
define([], factory);
} else {
root.urltemplate = factory();
}
}(this, function () {
/**
* @constructor
*/
function UrlTemplate() {
}
/**
* @private
* @param {string} str
* @return {string}
*/
UrlTemplate.prototype.encodeReserved = function (str) {
return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) {
if (!/%[0-9A-Fa-f]/.test(part)) {
part = encodeURI(part).replace(/%5B/g, '[').replace(/%5D/g, ']');
}
return part;
}).join('');
};
/**
* @private
* @param {string} str
* @return {string}
*/
UrlTemplate.prototype.encodeUnreserved = function (str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
return '%' + c.charCodeAt(0).toString(16).toUpperCase();
});
}
/**
* @private
* @param {string} operator
* @param {string} value
* @param {string} key
* @return {string}
*/
UrlTemplate.prototype.encodeValue = function (operator, value, key) {
value = (operator === '+' || operator === '#') ? this.encodeReserved(value) : this.encodeUnreserved(value);
if (key) {
return this.encodeUnreserved(key) + '=' + value;
} else {
return value;
}
};
/**
* @private
* @param {*} value
* @return {boolean}
*/
UrlTemplate.prototype.isDefined = function (value) {
return value !== undefined && value !== null;
};
/**
* @private
* @param {string}
* @return {boolean}
*/
UrlTemplate.prototype.isKeyOperator = function (operator) {
return operator === ';' || operator === '&' || operator === '?';
};
/**
* @private
* @param {Object} context
* @param {string} operator
* @param {string} key
* @param {string} modifier
*/
UrlTemplate.prototype.getValues = function (context, operator, key, modifier) {
var value = context[key],
result = [];
if (this.isDefined(value) && value !== '') {
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
value = value.toString();
if (modifier && modifier !== '*') {
value = value.substring(0, parseInt(modifier, 10));
}
result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null));
} else {
if (modifier === '*') {
if (Array.isArray(value)) {
value.filter(this.isDefined).forEach(function (value) {
result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null));
}, this);
} else {
Object.keys(value).forEach(function (k) {
if (this.isDefined(value[k])) {
result.push(this.encodeValue(operator, value[k], k));
}
}, this);
}
} else {
var tmp = [];
if (Array.isArray(value)) {
value.filter(this.isDefined).forEach(function (value) {
tmp.push(this.encodeValue(operator, value));
}, this);
} else {
Object.keys(value).forEach(function (k) {
if (this.isDefined(value[k])) {
tmp.push(this.encodeUnreserved(k));
tmp.push(this.encodeValue(operator, value[k].toString()));
}
}, this);
}
if (this.isKeyOperator(operator)) {
result.push(this.encodeUnreserved(key) + '=' + tmp.join(','));
} else if (tmp.length !== 0) {
result.push(tmp.join(','));
}
}
}
} else {
if (operator === ';') {
if (this.isDefined(value)) {
result.push(this.encodeUnreserved(key));
}
} else if (value === '' && (operator === '&' || operator === '?')) {
result.push(this.encodeUnreserved(key) + '=');
} else if (value === '') {
result.push('');
}
}
return result;
};
/**
* @param {string} template
* @return {function(Object):string}
*/
UrlTemplate.prototype.parse = function (template) {
var that = this;
var operators = ['+', '#', '.', '/', ';', '?', '&'];
return {
expand: function (context) {
return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) {
if (expression) {
var operator = null,
values = [];
if (operators.indexOf(expression.charAt(0)) !== -1) {
operator = expression.charAt(0);
expression = expression.substr(1);
}
expression.split(/,/g).forEach(function (variable) {
var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable);
values.push.apply(values, that.getValues(context, operator, tmp[1], tmp[2] || tmp[3]));
});
if (operator && operator !== '+') {
var separator = ',';
if (operator === '?') {
separator = '&';
} else if (operator !== '#') {
separator = operator;
}
return (values.length !== 0 ? operator : '') + values.join(separator);
} else {
return values.join(',');
}
} else {
return that.encodeReserved(literal);
}
});
}
};
};
return new UrlTemplate();
}));

66
node_modules/url-template/package.json generated vendored Normal file
View file

@ -0,0 +1,66 @@
{
"_from": "url-template@^2.0.8",
"_id": "url-template@2.0.8",
"_inBundle": false,
"_integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=",
"_location": "/url-template",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "url-template@^2.0.8",
"name": "url-template",
"escapedName": "url-template",
"rawSpec": "^2.0.8",
"saveSpec": null,
"fetchSpec": "^2.0.8"
},
"_requiredBy": [
"/@octokit/endpoint",
"/@octokit/rest"
],
"_resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
"_shasum": "fc565a3cccbff7730c775f5641f9555791439f21",
"_spec": "url-template@^2.0.8",
"_where": "C:\\Users\\Administrator\\Documents\\setup-node\\node_modules\\@octokit\\endpoint",
"author": {
"name": "Bram Stein",
"email": "b.l.stein@gmail.com",
"url": "http://www.bramstein.com"
},
"bugs": {
"url": "https://github.com/bramstein/url-template/issues"
},
"bundleDependencies": false,
"decription": "A URI template implementation (RFC 6570 compliant)",
"deprecated": false,
"description": "This is a simple URI template implementation following the [RFC 6570 URI Template specification](http://tools.ietf.org/html/rfc6570). The implementation supports all levels defined in the specification and is extensively tested.",
"devDependencies": {
"expect.js": "=0.2.0",
"mocha": "=1.6.0"
},
"directories": {
"lib": "./lib"
},
"homepage": "https://github.com/bramstein/url-template#readme",
"keywords": [
"uri-template",
"uri template",
"uri",
"url",
"rfc 6570",
"url template",
"url-template"
],
"license": "BSD",
"main": "./lib/url-template.js",
"name": "url-template",
"repository": {
"type": "git",
"url": "git://github.com/bramstein/url-template.git"
},
"scripts": {
"test": "mocha --reporter spec"
},
"version": "2.0.8"
}

21
node_modules/url-template/test/index.html generated vendored Normal file
View file

@ -0,0 +1,21 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="../node_modules/expect.js/expect.js"></script>
<script src="../node_modules/mocha/mocha.js"></script>
<script src="../lib/url-template.js"></script>
<script>mocha.setup('bdd')</script>
<script src="url-template-test.js"></script>
<script>
mocha.checkLeaks();
mocha.run();
</script>
</body>
</html>

32
node_modules/url-template/test/uritemplate-test.js generated vendored Normal file
View file

@ -0,0 +1,32 @@
var template, expect, examples;
if (typeof require !== 'undefined') {
template = require('../lib/url-template.js');
expect = require("expect.js");
examples = require('../uritemplate-test/spec-examples-by-section.json');
} else {
template = window.urltemplate;
expect = window.expect;
examples = window.examples;
}
function createTestContext(c) {
return function (t, r) {
if (typeof r === 'string') {
expect(template.parse(t).expand(c)).to.eql(r);
} else {
expect(r.indexOf(template.parse(t).expand(c)) >= 0).to.be.ok();
}
};
}
describe('spec-examples', function () {
Object.keys(examples).forEach(function (section) {
var assert = createTestContext(examples[section].variables);
examples[section].testcases.forEach(function (testcase) {
it(section + ' ' + testcase[0], function () {
assert(testcase[0], testcase[1]);
});
});
});
});

373
node_modules/url-template/test/url-template-test.js generated vendored Normal file
View file

@ -0,0 +1,373 @@
var template, expect;
if (typeof require !== 'undefined') {
template = require('../lib/url-template.js');
expect = require("expect.js");
} else {
template = window.urltemplate;
expect = window.expect;
}
function createTestContext(c) {
return function (t, r) {
expect(template.parse(t).expand(c)).to.eql(r);
};
}
describe('uri-template', function () {
describe('Level 1', function () {
var assert = createTestContext({
'var': 'value',
'some.value': 'some',
'some_value': 'value',
'Some%20Thing': 'hello',
'foo': 'bar',
'hello': 'Hello World!',
'bool': false,
'toString': 'string',
'number': 42,
'float': 3.14,
'undef': undefined,
'null': null,
'chars': 'šö䟜ñꀣ¥‡ÑÒÓÔÕÖרÙÚàáâãäåæçÿü',
'surrogatepairs': '\uD834\uDF06'
});
it('empty string', function () {
assert('', '');
});
it('encodes non expressions correctly', function () {
assert('hello/world', 'hello/world');
assert('Hello World!/{foo}', 'Hello%20World!/bar');
assert(':/?#[]@!$&()*+,;=\'', ':/?#[]@!$&()*+,;=\'');
assert('%20', '%20');
assert('%xyz', '%25xyz');
assert('%', '%25');
});
it('expand plain ASCII strings', function () {
assert('{var}', 'value');
});
it('expand non-ASCII strings', function () {
assert('{chars}', '%C5%A1%C3%B6%C3%A4%C5%B8%C5%93%C3%B1%C3%AA%E2%82%AC%C2%A3%C2%A5%E2%80%A1%C3%91%C3%92%C3%93%C3%94%C3%95%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A6%C3%A7%C3%BF%C3%BC');
});
it('expands and encodes surrogate pairs correctly', function () {
assert('{surrogatepairs}', '%F0%9D%8C%86');
});
it('expand expressions with dot and underscore', function () {
assert('{some.value}', 'some');
assert('{some_value}', 'value');
});
it('expand expressions with encoding', function () {
assert('{Some%20Thing}', 'hello');
});
it('expand expressions with reserved JavaScript names', function () {
assert('{toString}', 'string');
});
it('expand variables that are not strings', function () {
assert('{number}', '42');
assert('{float}', '3.14');
assert('{bool}', 'false');
});
it('expand variables that are undefined or null', function () {
assert('{undef}', '');
assert('{null}', '');
});
it('expand multiple values', function () {
assert('{var}/{foo}', 'value/bar');
});
it('escape invalid characters correctly', function () {
assert('{hello}', 'Hello%20World%21');
});
});
describe('Level 2', function () {
var assert = createTestContext({
'var': 'value',
'hello': 'Hello World!',
'path': '/foo/bar'
});
it('reserved expansion of basic strings', function () {
assert('{+var}', 'value');
assert('{+hello}', 'Hello%20World!');
});
it('preserves paths', function() {
assert('{+path}/here', '/foo/bar/here');
assert('here?ref={+path}', 'here?ref=/foo/bar');
});
});
describe('Level 3', function () {
var assert = createTestContext({
'var' : 'value',
'hello' : 'Hello World!',
'empty' : '',
'path' : '/foo/bar',
'x' : '1024',
'y' : '768'
});
it('variables without an operator', function () {
assert('map?{x,y}', 'map?1024,768');
assert('{x,hello,y}', '1024,Hello%20World%21,768');
});
it('variables with the reserved expansion operator', function () {
assert('{+x,hello,y}', '1024,Hello%20World!,768');
assert('{+path,x}/here', '/foo/bar,1024/here');
});
it('variables with the fragment expansion operator', function () {
assert('{#x,hello,y}', '#1024,Hello%20World!,768');
assert('{#path,x}/here', '#/foo/bar,1024/here');
});
it('variables with the dot operator', function () {
assert('X{.var}', 'X.value');
assert('X{.x,y}', 'X.1024.768');
});
it('variables with the path operator', function () {
assert('{/var}', '/value');
assert('{/var,x}/here', '/value/1024/here');
});
it('variables with the parameter operator', function () {
assert('{;x,y}', ';x=1024;y=768');
assert('{;x,y,empty}', ';x=1024;y=768;empty');
});
it('variables with the query operator', function () {
assert('{?x,y}', '?x=1024&y=768');
assert('{?x,y,empty}', '?x=1024&y=768&empty=');
});
it('variables with the query continuation operator', function () {
assert('?fixed=yes{&x}', '?fixed=yes&x=1024');
assert('{&x,y,empty}', '&x=1024&y=768&empty=');
});
});
describe('Level 4', function () {
var assert = createTestContext({
'var': 'value',
'hello': 'Hello World!',
'path': '/foo/bar',
'list': ['red', 'green', 'blue'],
'keys': {
'semi': ';',
'dot': '.',
'comma': ','
},
"chars": {
'ü': 'ü'
},
'number': 2133,
'emptystring': '',
'emptylist': [],
'emptyobject': {},
'undefinedlistitem': [1,,2],
'undefinedobjectitem': { key: null, hello: 'world', 'empty': '', '': 'nothing' }
});
it('variable empty list', function () {
assert('{/emptylist}', '');
assert('{/emptylist*}', '');
assert('{?emptylist}', '?emptylist=');
assert('{?emptylist*}', '');
});
it('variable empty object', function () {
assert('{/emptyobject}', '');
assert('{/emptyobject*}', '');
assert('{?emptyobject}', '?emptyobject=');
assert('{?emptyobject*}', '');
});
it('variable undefined list item', function () {
assert('{undefinedlistitem}', '1,2');
assert('{undefinedlistitem*}', '1,2');
assert('{?undefinedlistitem*}', '?undefinedlistitem=1&undefinedlistitem=2');
});
it('variable undefined object item', function () {
assert('{undefinedobjectitem}', 'hello,world,empty,,,nothing');
assert('{undefinedobjectitem*}', 'hello=world,empty=,nothing');
});
it('variable empty string', function () {
assert('{emptystring}', '');
assert('{+emptystring}', '');
assert('{#emptystring}', '#');
assert('{.emptystring}', '.');
assert('{/emptystring}', '/');
assert('{;emptystring}', ';emptystring');
assert('{?emptystring}', '?emptystring=');
assert('{&emptystring}', '&emptystring=');
});
it('variable modifiers prefix', function () {
assert('{var:3}', 'val');
assert('{var:30}', 'value');
assert('{+path:6}/here', '/foo/b/here');
assert('{#path:6}/here', '#/foo/b/here');
assert('X{.var:3}', 'X.val');
assert('{/var:1,var}', '/v/value');
assert('{;hello:5}', ';hello=Hello');
assert('{?var:3}', '?var=val');
assert('{&var:3}', '&var=val');
});
it('variable modifier prefix converted to string', function () {
assert('{number:3}', '213');
});
it('variable list expansion', function () {
assert('{list}', 'red,green,blue');
assert('{+list}', 'red,green,blue');
assert('{#list}', '#red,green,blue');
assert('{/list}', '/red,green,blue');
assert('{;list}', ';list=red,green,blue');
assert('{.list}', '.red,green,blue');
assert('{?list}', '?list=red,green,blue');
assert('{&list}', '&list=red,green,blue');
});
it('variable associative array expansion', function () {
assert('{keys}', 'semi,%3B,dot,.,comma,%2C');
assert('{keys*}', 'semi=%3B,dot=.,comma=%2C');
assert('{+keys}', 'semi,;,dot,.,comma,,');
assert('{#keys}', '#semi,;,dot,.,comma,,');
assert('{.keys}', '.semi,%3B,dot,.,comma,%2C');
assert('{/keys}', '/semi,%3B,dot,.,comma,%2C');
assert('{;keys}', ';keys=semi,%3B,dot,.,comma,%2C');
assert('{?keys}', '?keys=semi,%3B,dot,.,comma,%2C');
assert('{&keys}', '&keys=semi,%3B,dot,.,comma,%2C');
});
it('variable list explode', function () {
assert('{list*}', 'red,green,blue');
assert('{+list*}', 'red,green,blue');
assert('{#list*}', '#red,green,blue');
assert('{/list*}', '/red/green/blue');
assert('{;list*}', ';list=red;list=green;list=blue');
assert('{.list*}', '.red.green.blue');
assert('{?list*}', '?list=red&list=green&list=blue');
assert('{&list*}', '&list=red&list=green&list=blue');
assert('{/list*,path:4}', '/red/green/blue/%2Ffoo');
});
it('variable associative array explode', function () {
assert('{+keys*}', 'semi=;,dot=.,comma=,');
assert('{#keys*}', '#semi=;,dot=.,comma=,');
assert('{/keys*}', '/semi=%3B/dot=./comma=%2C');
assert('{;keys*}', ';semi=%3B;dot=.;comma=%2C');
assert('{?keys*}', '?semi=%3B&dot=.&comma=%2C');
assert('{&keys*}', '&semi=%3B&dot=.&comma=%2C')
});
it('encodes associative arrays correctly', function () {
assert('{chars*}', '%C3%BC=%C3%BC');
});
});
describe('Encoding', function () {
var assert = createTestContext({
restricted: ":/?#[]@!$&()*+,;='",
percent: '%',
encoded: '%25',
'pctencoded%20name': '',
mapWithEncodedName: {
'encoded%20name': ''
},
mapWithRestrictedName: {
'restricted=name': ''
},
mapWidthUmlautName: {
'ümlaut': ''
}
});
it('passes through percent encoded values', function () {
assert('{percent}', '%25');
assert('{+encoded}', '%25');
});
it('encodes restricted characters correctly', function () {
assert('{restricted}', '%3A%2F%3F%23%5B%5D%40%21%24%26%28%29%2A%2B%2C%3B%3D%27');
assert('{+restricted}', ':/?#[]@!$&()*+,;=\'');
assert('{#restricted}', '#:/?#[]@!$&()*+,;=\'');
assert('{/restricted}', '/%3A%2F%3F%23%5B%5D%40%21%24%26%28%29%2A%2B%2C%3B%3D%27');
assert('{;restricted}', ';restricted=%3A%2F%3F%23%5B%5D%40%21%24%26%28%29%2A%2B%2C%3B%3D%27');
assert('{.restricted}', '.%3A%2F%3F%23%5B%5D%40%21%24%26%28%29%2A%2B%2C%3B%3D%27');
assert('{?restricted}', '?restricted=%3A%2F%3F%23%5B%5D%40%21%24%26%28%29%2A%2B%2C%3B%3D%27');
assert('{&restricted}', '&restricted=%3A%2F%3F%23%5B%5D%40%21%24%26%28%29%2A%2B%2C%3B%3D%27');
});
});
describe('Error handling (or the lack thereof)', function () {
var assert = createTestContext({
foo: 'test',
keys: {
foo: 'bar'
}
});
it('does not expand invalid expressions', function () {
assert('{test', '{test');
assert('test}', 'test}');
assert('{{test}}', '{}'); // TODO: Is this acceptable?
});
it('does not expand with incorrect operators', function () {
assert('{@foo}', ''); // TODO: This will try to match a variable called `@foo` which will fail because it is not in our context. We could catch this by ignoring reserved operators?
assert('{$foo}', ''); // TODO: Same story, but $ is not a reserved operator.
assert('{++foo}', '');
});
it('ignores incorrect prefixes', function () {
assert('{foo:test}', 'test'); // TODO: Invalid prefixes are ignored. We could throw an error.
assert('{foo:2test}', 'te'); // TODO: Best effort is OK?
});
it('prefix applied to the wrong context', function () {
assert('{keys:1}', 'foo,bar');
});
});
describe('Skipping undefined arguments', function () {
var assert = createTestContext({
'var': 'value',
'number': 2133,
'emptystring': '',
'emptylist': [],
'emptyobject': {},
'undefinedlistitem': [1,,2],
});
it('variable undefined list item', function () {
assert('{undefinedlistitem}', '1,2');
assert('{undefinedlistitem*}', '1,2');
assert('{?undefinedlistitem*}', '?undefinedlistitem=1&undefinedlistitem=2');
});
it('query with empty/undefined arguments', function () {
assert('{?var,number}', '?var=value&number=2133');
assert('{?undef}', '');
assert('{?emptystring}', '?emptystring=');
assert('{?emptylist}', '?emptylist=');
assert('{?emptyobject}', '?emptyobject=');
assert('{?undef,var,emptystring}', '?var=value&emptystring=');
});
});
});

90
node_modules/url-template/uritemplate-test/README.md generated vendored Normal file
View file

@ -0,0 +1,90 @@
URI Template Tests
==================
This is a set of tests for implementations of
[RFC6570](http://tools.ietf.org/html/rfc6570) - URI Template. It is designed
to be reused by any implementation, to improve interoperability and
implementation quality.
If your project uses Git for version control, you can make uritemplate-tests into a [submodule](http://help.github.com/submodules/).
Test Format
-----------
Each test file is a [JSON](http://tools.ietf.org/html/RFC6627) document
containing an object whose properties are groups of related tests.
Alternatively, all tests are available in XML as well, with the XML files
being generated by transform-json-tests.xslt which uses json2xml.xslt as a
general-purpose JSON-to-XML parsing library.
Each group, in turn, is an object with three children:
* level - the level of the tests covered, as per the RFC (optional; if absent,
assume level 4).
* variables - an object representing the variables that are available to the
tests in the suite
* testcases - a list of testcases, where each case is a two-member list, the
first being the template, the second being the result of expanding the
template with the provided variables.
Note that the result string can be a few different things:
* string - if the second member is a string, the result of expansion is
expected to match it, character-for-character.
* list - if the second member is a list of strings, the result of expansion
is expected to match one of them; this allows for templates that can
expand into different, equally-acceptable URIs.
* false - if the second member is boolean false, expansion is expected to
fail (i.e., the template was invalid).
For example:
{
"Level 1 Examples" :
{
"level": 1,
"variables": {
"var" : "value",
"hello" : "Hello World!"
},
"testcases" : [
["{var}", "value"],
["{hello}", "Hello%20World%21"]
]
}
}
Tests Included
--------------
The following test files are included:
* spec-examples.json - The complete set of example templates from the RFC
* spec-examples-by-section.json - The examples, section by section
* extended-tests.json - more complex test cases
* negative-tests.json - invalid templates
For all these test files, XML versions with the names *.xml can be
generated with the transform-json-tests.xslt XSLT stylesheet. The XSLT
contains the names of the above test files as a parameter, and can be
started with any XML as input (i.e., the XML input is ignored).
License
-------
Copyright 2011-2012 The Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,118 @@
{
"Additional Examples 1":{
"level":4,
"variables":{
"id" : "person",
"token" : "12345",
"fields" : ["id", "name", "picture"],
"format" : "json",
"q" : "URI Templates",
"page" : "5",
"lang" : "en",
"geocode" : ["37.76","-122.427"],
"first_name" : "John",
"last.name" : "Doe",
"Some%20Thing" : "foo",
"number" : 6,
"long" : 37.76,
"lat" : -122.427,
"group_id" : "12345",
"query" : "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?book ?who WHERE { ?book dc:creator ?who }",
"uri" : "http://example.org/?uri=http%3A%2F%2Fexample.org%2F",
"word" : "drücken",
"Stra%C3%9Fe" : "Grüner Weg",
"random" : "šö䟜ñꀣ¥‡ÑÒÓÔÕÖרÙÚàáâãäåæçÿ",
"assoc_special_chars" :
{ "šö䟜ñꀣ¥‡ÑÒÓÔÕ" : "ÖרÙÚàáâãäåæçÿ" }
},
"testcases":[
[ "{/id*}" , "/person" ],
[ "{/id*}{?fields,first_name,last.name,token}" , [
"/person?fields=id,name,picture&first_name=John&last.name=Doe&token=12345",
"/person?fields=id,picture,name&first_name=John&last.name=Doe&token=12345",
"/person?fields=picture,name,id&first_name=John&last.name=Doe&token=12345",
"/person?fields=picture,id,name&first_name=John&last.name=Doe&token=12345",
"/person?fields=name,picture,id&first_name=John&last.name=Doe&token=12345",
"/person?fields=name,id,picture&first_name=John&last.name=Doe&token=12345"]
],
["/search.{format}{?q,geocode,lang,locale,page,result_type}",
[ "/search.json?q=URI%20Templates&geocode=37.76,-122.427&lang=en&page=5",
"/search.json?q=URI%20Templates&geocode=-122.427,37.76&lang=en&page=5"]
],
["/test{/Some%20Thing}", "/test/foo" ],
["/set{?number}", "/set?number=6"],
["/loc{?long,lat}" , "/loc?long=37.76&lat=-122.427"],
["/base{/group_id,first_name}/pages{/page,lang}{?format,q}","/base/12345/John/pages/5/en?format=json&q=URI%20Templates"],
["/sparql{?query}", "/sparql?query=PREFIX%20dc%3A%20%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2F%3E%20SELECT%20%3Fbook%20%3Fwho%20WHERE%20%7B%20%3Fbook%20dc%3Acreator%20%3Fwho%20%7D"],
["/go{?uri}", "/go?uri=http%3A%2F%2Fexample.org%2F%3Furi%3Dhttp%253A%252F%252Fexample.org%252F"],
["/service{?word}", "/service?word=dr%C3%BCcken"],
["/lookup{?Stra%C3%9Fe}", "/lookup?Stra%C3%9Fe=Gr%C3%BCner%20Weg"],
["{random}" , "%C5%A1%C3%B6%C3%A4%C5%B8%C5%93%C3%B1%C3%AA%E2%82%AC%C2%A3%C2%A5%E2%80%A1%C3%91%C3%92%C3%93%C3%94%C3%95%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A6%C3%A7%C3%BF"],
["{?assoc_special_chars*}", "?%C5%A1%C3%B6%C3%A4%C5%B8%C5%93%C3%B1%C3%AA%E2%82%AC%C2%A3%C2%A5%E2%80%A1%C3%91%C3%92%C3%93%C3%94%C3%95=%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A6%C3%A7%C3%BF"]
]
},
"Additional Examples 2":{
"level":4,
"variables":{
"id" : ["person","albums"],
"token" : "12345",
"fields" : ["id", "name", "picture"],
"format" : "atom",
"q" : "URI Templates",
"page" : "10",
"start" : "5",
"lang" : "en",
"geocode" : ["37.76","-122.427"]
},
"testcases":[
[ "{/id*}" , ["/person/albums","/albums/person"] ],
[ "{/id*}{?fields,token}" , [
"/person/albums?fields=id,name,picture&token=12345",
"/person/albums?fields=id,picture,name&token=12345",
"/person/albums?fields=picture,name,id&token=12345",
"/person/albums?fields=picture,id,name&token=12345",
"/person/albums?fields=name,picture,id&token=12345",
"/person/albums?fields=name,id,picture&token=12345",
"/albums/person?fields=id,name,picture&token=12345",
"/albums/person?fields=id,picture,name&token=12345",
"/albums/person?fields=picture,name,id&token=12345",
"/albums/person?fields=picture,id,name&token=12345",
"/albums/person?fields=name,picture,id&token=12345",
"/albums/person?fields=name,id,picture&token=12345"]
]
]
},
"Additional Examples 3: Empty Variables":{
"variables" : {
"empty_list" : [],
"empty_assoc" : {}
},
"testcases":[
[ "{/empty_list}", [ "" ] ],
[ "{/empty_list*}", [ "" ] ],
[ "{?empty_list}", [ ""] ],
[ "{?empty_list*}", [ "" ] ],
[ "{?empty_assoc}", [ "" ] ],
[ "{?empty_assoc*}", [ "" ] ]
]
},
"Additional Examples 4: Numeric Keys":{
"variables" : {
"42" : "The Answer to the Ultimate Question of Life, the Universe, and Everything",
"1337" : ["leet", "as","it", "can","be"],
"german" : {
"11": "elf",
"12": "zwölf"
}
},
"testcases":[
[ "{42}", "The%20Answer%20to%20the%20Ultimate%20Question%20of%20Life%2C%20the%20Universe%2C%20and%20Everything"],
[ "{?42}", "?42=The%20Answer%20to%20the%20Ultimate%20Question%20of%20Life%2C%20the%20Universe%2C%20and%20Everything"],
[ "{1337}", "leet,as,it,can,be"],
[ "{?1337*}", "?1337=leet&1337=as&1337=it&1337=can&1337=be"],
[ "{?german*}", [ "?11=elf&12=zw%C3%B6lf", "?12=zw%C3%B6lf&11=elf"] ]
]
}
}

View file

@ -0,0 +1,201 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Downloaded on 12/6/2012 from http://www.gerixsoft.com/blog/xslt/json2xml -->
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="json">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:call-template name="json2xml">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="json2xml">
<xsl:param name="text"/>
<xsl:variable name="mode0">
<xsl:variable name="regexps" select="'//(.*?)\n', '/\*(.*?)\*/', '(''|&quot;)(([^\\]|\\[\\&quot;''/btnvfr])*?)\3', '(-?\d+(\.\d+([eE][+-]?\d+)?|[eE][+-]?\d+))', '(-?[1-9]\d*)', '(-?0[0-7]+)', '(-?0x[0-9a-fA-F]+)', '([:,\{\}\[\]])', '(true|false)', '(null)'"/>
<xsl:analyze-string select="$text" regex="{string-join($regexps,'|')}" flags="s">
<xsl:matching-substring>
<xsl:choose>
<!-- single line comment -->
<xsl:when test="regex-group(1)">
<xsl:comment>
<xsl:value-of select="regex-group(1)"/>
</xsl:comment>
<xsl:text>&#10;</xsl:text>
</xsl:when>
<!-- multi line comment -->
<xsl:when test="regex-group(2)">
<xsl:comment>
<xsl:value-of select="regex-group(2)"/>
</xsl:comment>
</xsl:when>
<!-- string -->
<xsl:when test="regex-group(3)">
<string>
<xsl:analyze-string select="regex-group(4)" regex="\\([\\&quot;'/btnvfr])" flags="s">
<xsl:matching-substring>
<xsl:variable name="s" select="regex-group(1)"/>
<xsl:choose>
<xsl:when test="$s=('\', '&quot;', '''', '/')">
<xsl:value-of select="regex-group(1)"/>
</xsl:when>
<xsl:when test="$s='b'">
<!--xsl:text>&#8;</xsl:text-->
<xsl:message select="'escape sequense \b is not supported by XML'"/>
<xsl:text>\b</xsl:text>
</xsl:when>
<xsl:when test="$s='t'">
<xsl:text>&#9;</xsl:text>
</xsl:when>
<xsl:when test="$s='n'">
<xsl:text>&#10;</xsl:text>
</xsl:when>
<xsl:when test="$s='v'">
<!--xsl:text>&#11;</xsl:text-->
<xsl:message select="'escape sequence \v is not supported by XML'"/>
<xsl:text>\v</xsl:text>
</xsl:when>
<xsl:when test="$s='f'">
<!--xsl:text>&#12;</xsl:text-->
<xsl:message select="'escape sequence \f is not supported by XML'"/>
<xsl:text>\f</xsl:text>
</xsl:when>
<xsl:when test="$s='r'">
<xsl:text>&#13;</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes" select="'internal error'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</string>
</xsl:when>
<!-- double -->
<xsl:when test="regex-group(6)">
<double>
<xsl:value-of select="regex-group(6)"/>
</double>
</xsl:when>
<!-- integer -->
<xsl:when test="regex-group(9)">
<integer>
<xsl:value-of select="regex-group(9)"/>
</integer>
</xsl:when>
<!-- octal -->
<xsl:when test="regex-group(10)">
<integer>
<xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(regex-group(10), 8)"/>
</integer>
</xsl:when>
<!-- hex -->
<xsl:when test="regex-group(11)">
<integer>
<xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(replace(regex-group(11), '0x', ''), 16)"/>
</integer>
</xsl:when>
<!-- symbol -->
<xsl:when test="regex-group(12)">
<symbol>
<xsl:value-of select="regex-group(12)"/>
</symbol>
</xsl:when>
<!-- boolean -->
<xsl:when test="regex-group(13)">
<boolean>
<xsl:value-of select="regex-group(13)"/>
</boolean>
</xsl:when>
<!-- null -->
<xsl:when test="regex-group(14)">
<null />
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes" select="'internal error'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:if test="normalize-space()!=''">
<xsl:message select="concat('unknown token: ', .)"/>
<xsl:value-of select="."/>
</xsl:if>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:variable>
<xsl:variable name="mode1">
<xsl:apply-templates mode="json2xml1" select="$mode0/node()[1]"/>
</xsl:variable>
<xsl:variable name="mode2">
<xsl:apply-templates mode="json2xml2" select="$mode1"/>
</xsl:variable>
<xsl:variable name="mode3">
<xsl:apply-templates mode="json2xml3" select="$mode2"/>
</xsl:variable>
<xsl:copy-of select="$mode3"/> <!-- change $mode3 to $mode[0-2] for easy debug -->
</xsl:template>
<!-- json2xml1 mode: group content between {} and [] into object and array elements -->
<xsl:template mode="json2xml1" match="node()" priority="-9">
<xsl:copy-of select="."/>
<xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template mode="json2xml1" match="symbol[.=('}',']')]"/>
<xsl:template mode="json2xml1" match="symbol[.=('{','[')]">
<xsl:element name="{if (.='{') then 'object' else 'array'}">
<xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/>
</xsl:element>
<xsl:variable name="level" select="count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])+1"/>
<xsl:variable name="ender"
select="following-sibling::symbol[.=('}',']') and count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])=$level][1]"/>
<xsl:apply-templates mode="json2xml1" select="$ender/following-sibling::node()[1]"/>
</xsl:template>
<!-- json2xml2 mode: group <string>:<string|integer|double|object|array> into field element -->
<xsl:template priority="-9" mode="json2xml2" match="@*|node()">
<xsl:copy>
<xsl:apply-templates mode="json2xml2" select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="json2xml2"
match="string[following-sibling::*[1]/self::symbol[.=':'] and following-sibling::*[2]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]"/>
<xsl:template mode="json2xml2"
match="symbol[.=':'][preceding-sibling::*[1]/self::string and following-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]">
<field name="{preceding-sibling::*[1]}">
<xsl:for-each select="following-sibling::*[1]">
<xsl:copy>
<xsl:apply-templates mode="json2xml2" select="@*|node()"/>
</xsl:copy>
</xsl:for-each>
</field>
</xsl:template>
<xsl:template mode="json2xml2"
match="*[self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null][preceding-sibling::*[2]/self::string and preceding-sibling::*[1]/self::symbol[.=':']]"/>
<!-- json2xml3 mode: drop comma between consecutive field and object elements -->
<xsl:template priority="-9" mode="json2xml3" match="@*|node()">
<xsl:copy>
<xsl:apply-templates mode="json2xml3" select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="json2xml3" match="object/symbol[.=','][preceding-sibling::*[1]/self::field and following-sibling::*[1]/self::field]"/>
<xsl:template mode="json2xml3" match="array/symbol[.=','][preceding-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null) and following-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]"/>
</xsl:stylesheet>

View file

@ -0,0 +1,57 @@
{
"Failure Tests":{
"level":4,
"variables":{
"id" : "thing",
"var" : "value",
"hello" : "Hello World!",
"with space" : "fail",
" leading_space" : "Hi!",
"trailing_space " : "Bye!",
"empty" : "",
"path" : "/foo/bar",
"x" : "1024",
"y" : "768",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"example" : "red",
"searchTerms" : "uri templates",
"~thing" : "some-user",
"default-graph-uri" : ["http://www.example/book/","http://www.example/papers/"],
"query" : "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?book ?who WHERE { ?book dc:creator ?who }"
},
"testcases":[
[ "{/id*", false ],
[ "/id*}", false ],
[ "{/?id}", false ],
[ "{var:prefix}", false ],
[ "{hello:2*}", false ] ,
[ "{??hello}", false ] ,
[ "{!hello}", false ] ,
[ "{with space}", false],
[ "{ leading_space}", false],
[ "{trailing_space }", false],
[ "{=path}", false ] ,
[ "{$var}", false ],
[ "{|var*}", false ],
[ "{*keys?}", false ],
[ "{?empty=default,var}", false ],
[ "{var}{-prefix|/-/|var}" , false ],
[ "?q={searchTerms}&amp;c={example:color?}" , false ],
[ "x{?empty|foo=none}" , false ],
[ "/h{#hello+}" , false ],
[ "/h#{hello+}" , false ],
[ "{keys:1}", false ],
[ "{+keys:1}", false ],
[ "{;keys:1*}", false ],
[ "?{-join|&|var,list}" , false ],
[ "/people/{~thing}", false],
[ "/{default-graph-uri}", false ],
[ "/sparql{?query,default-graph-uri}", false ],
[ "/sparql{?query){&default-graph-uri*}", false ],
[ "/resolution{?x, y}" , false ]
]
}
}

View file

@ -0,0 +1,439 @@
{
"3.2.1 Variable Expansion" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{count}", "one,two,three"],
["{count*}", "one,two,three"],
["{/count}", "/one,two,three"],
["{/count*}", "/one/two/three"],
["{;count}", ";count=one,two,three"],
["{;count*}", ";count=one;count=two;count=three"],
["{?count}", "?count=one,two,three"],
["{?count*}", "?count=one&count=two&count=three"],
["{&count*}", "&count=one&count=two&count=three"]
]
},
"3.2.2 Simple String Expansion" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{var}", "value"],
["{hello}", "Hello%20World%21"],
["{half}", "50%25"],
["O{empty}X", "OX"],
["O{undef}X", "OX"],
["{x,y}", "1024,768"],
["{x,hello,y}", "1024,Hello%20World%21,768"],
["?{x,empty}", "?1024,"],
["?{x,undef}", "?1024"],
["?{undef,y}", "?768"],
["{var:3}", "val"],
["{var:30}", "value"],
["{list}", "red,green,blue"],
["{list*}", "red,green,blue"],
["{keys}", [
"comma,%2C,dot,.,semi,%3B",
"comma,%2C,semi,%3B,dot,.",
"dot,.,comma,%2C,semi,%3B",
"dot,.,semi,%3B,comma,%2C",
"semi,%3B,comma,%2C,dot,.",
"semi,%3B,dot,.,comma,%2C"
]],
["{keys*}", [
"comma=%2C,dot=.,semi=%3B",
"comma=%2C,semi=%3B,dot=.",
"dot=.,comma=%2C,semi=%3B",
"dot=.,semi=%3B,comma=%2C",
"semi=%3B,comma=%2C,dot=.",
"semi=%3B,dot=.,comma=%2C"
]]
]
},
"3.2.3 Reserved Expansion" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{+var}", "value"],
["{/var,empty}", "/value/"],
["{/var,undef}", "/value"],
["{+hello}", "Hello%20World!"],
["{+half}", "50%25"],
["{base}index", "http%3A%2F%2Fexample.com%2Fhome%2Findex"],
["{+base}index", "http://example.com/home/index"],
["O{+empty}X", "OX"],
["O{+undef}X", "OX"],
["{+path}/here", "/foo/bar/here"],
["{+path:6}/here", "/foo/b/here"],
["here?ref={+path}", "here?ref=/foo/bar"],
["up{+path}{var}/here", "up/foo/barvalue/here"],
["{+x,hello,y}", "1024,Hello%20World!,768"],
["{+path,x}/here", "/foo/bar,1024/here"],
["{+list}", "red,green,blue"],
["{+list*}", "red,green,blue"],
["{+keys}", [
"comma,,,dot,.,semi,;",
"comma,,,semi,;,dot,.",
"dot,.,comma,,,semi,;",
"dot,.,semi,;,comma,,",
"semi,;,comma,,,dot,.",
"semi,;,dot,.,comma,,"
]],
["{+keys*}", [
"comma=,,dot=.,semi=;",
"comma=,,semi=;,dot=.",
"dot=.,comma=,,semi=;",
"dot=.,semi=;,comma=,",
"semi=;,comma=,,dot=.",
"semi=;,dot=.,comma=,"
]]
]
},
"3.2.4 Fragment Expansion" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{#var}", "#value"],
["{#hello}", "#Hello%20World!"],
["{#half}", "#50%25"],
["foo{#empty}", "foo#"],
["foo{#undef}", "foo"],
["{#x,hello,y}", "#1024,Hello%20World!,768"],
["{#path,x}/here", "#/foo/bar,1024/here"],
["{#path:6}/here", "#/foo/b/here"],
["{#list}", "#red,green,blue"],
["{#list*}", "#red,green,blue"],
["{#keys}", [
"#comma,,,dot,.,semi,;",
"#comma,,,semi,;,dot,.",
"#dot,.,comma,,,semi,;",
"#dot,.,semi,;,comma,,",
"#semi,;,comma,,,dot,.",
"#semi,;,dot,.,comma,,"
]]
]
},
"3.2.5 Label Expansion with Dot-Prefix" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{.who}", ".fred"],
["{.who,who}", ".fred.fred"],
["{.half,who}", ".50%25.fred"],
["www{.dom*}", "www.example.com"],
["X{.var}", "X.value"],
["X{.var:3}", "X.val"],
["X{.empty}", "X."],
["X{.undef}", "X"],
["X{.list}", "X.red,green,blue"],
["X{.list*}", "X.red.green.blue"],
["{#keys}", [
"#comma,,,dot,.,semi,;",
"#comma,,,semi,;,dot,.",
"#dot,.,comma,,,semi,;",
"#dot,.,semi,;,comma,,",
"#semi,;,comma,,,dot,.",
"#semi,;,dot,.,comma,,"
]],
["{#keys*}", [
"#comma=,,dot=.,semi=;",
"#comma=,,semi=;,dot=.",
"#dot=.,comma=,,semi=;",
"#dot=.,semi=;,comma=,",
"#semi=;,comma=,,dot=.",
"#semi=;,dot=.,comma=,"
]],
["X{.empty_keys}", "X"],
["X{.empty_keys*}", "X"]
]
},
"3.2.6 Path Segment Expansion" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{/who}", "/fred"],
["{/who,who}", "/fred/fred"],
["{/half,who}", "/50%25/fred"],
["{/who,dub}", "/fred/me%2Ftoo"],
["{/var}", "/value"],
["{/var,empty}", "/value/"],
["{/var,undef}", "/value"],
["{/var,x}/here", "/value/1024/here"],
["{/var:1,var}", "/v/value"],
["{/list}", "/red,green,blue"],
["{/list*}", "/red/green/blue"],
["{/list*,path:4}", "/red/green/blue/%2Ffoo"],
["{/keys}", [
"/comma,%2C,dot,.,semi,%3B",
"/comma,%2C,semi,%3B,dot,.",
"/dot,.,comma,%2C,semi,%3B",
"/dot,.,semi,%3B,comma,%2C",
"/semi,%3B,comma,%2C,dot,.",
"/semi,%3B,dot,.,comma,%2C"
]],
["{/keys*}", [
"/comma=%2C/dot=./semi=%3B",
"/comma=%2C/semi=%3B/dot=.",
"/dot=./comma=%2C/semi=%3B",
"/dot=./semi=%3B/comma=%2C",
"/semi=%3B/comma=%2C/dot=.",
"/semi=%3B/dot=./comma=%2C"
]]
]
},
"3.2.7 Path-Style Parameter Expansion" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{;who}", ";who=fred"],
["{;half}", ";half=50%25"],
["{;empty}", ";empty"],
["{;hello:5}", ";hello=Hello"],
["{;v,empty,who}", ";v=6;empty;who=fred"],
["{;v,bar,who}", ";v=6;who=fred"],
["{;x,y}", ";x=1024;y=768"],
["{;x,y,empty}", ";x=1024;y=768;empty"],
["{;x,y,undef}", ";x=1024;y=768"],
["{;list}", ";list=red,green,blue"],
["{;list*}", ";list=red;list=green;list=blue"],
["{;keys}", [
";keys=comma,%2C,dot,.,semi,%3B",
";keys=comma,%2C,semi,%3B,dot,.",
";keys=dot,.,comma,%2C,semi,%3B",
";keys=dot,.,semi,%3B,comma,%2C",
";keys=semi,%3B,comma,%2C,dot,.",
";keys=semi,%3B,dot,.,comma,%2C"
]],
["{;keys*}", [
";comma=%2C;dot=.;semi=%3B",
";comma=%2C;semi=%3B;dot=.",
";dot=.;comma=%2C;semi=%3B",
";dot=.;semi=%3B;comma=%2C",
";semi=%3B;comma=%2C;dot=.",
";semi=%3B;dot=.;comma=%2C"
]]
]
},
"3.2.8 Form-Style Query Expansion" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{?who}", "?who=fred"],
["{?half}", "?half=50%25"],
["{?x,y}", "?x=1024&y=768"],
["{?x,y,empty}", "?x=1024&y=768&empty="],
["{?x,y,undef}", "?x=1024&y=768"],
["{?var:3}", "?var=val"],
["{?list}", "?list=red,green,blue"],
["{?list*}", "?list=red&list=green&list=blue"],
["{?keys}", [
"?keys=comma,%2C,dot,.,semi,%3B",
"?keys=comma,%2C,semi,%3B,dot,.",
"?keys=dot,.,comma,%2C,semi,%3B",
"?keys=dot,.,semi,%3B,comma,%2C",
"?keys=semi,%3B,comma,%2C,dot,.",
"?keys=semi,%3B,dot,.,comma,%2C"
]],
["{?keys*}", [
"?comma=%2C&dot=.&semi=%3B",
"?comma=%2C&semi=%3B&dot=.",
"?dot=.&comma=%2C&semi=%3B",
"?dot=.&semi=%3B&comma=%2C",
"?semi=%3B&comma=%2C&dot=.",
"?semi=%3B&dot=.&comma=%2C"
]]
]
},
"3.2.9 Form-Style Query Continuation" :
{
"variables": {
"count" : ["one", "two", "three"],
"dom" : ["example", "com"],
"dub" : "me/too",
"hello" : "Hello World!",
"half" : "50%",
"var" : "value",
"who" : "fred",
"base" : "http://example.com/home/",
"path" : "/foo/bar",
"list" : ["red", "green", "blue"],
"keys" : { "semi" : ";", "dot" : ".", "comma" : ","},
"v" : "6",
"x" : "1024",
"y" : "768",
"empty" : "",
"empty_keys" : [],
"undef" : null
},
"testcases" : [
["{&who}", "&who=fred"],
["{&half}", "&half=50%25"],
["?fixed=yes{&x}", "?fixed=yes&x=1024"],
["{&var:3}", "&var=val"],
["{&x,y,empty}", "&x=1024&y=768&empty="],
["{&x,y,undef}", "&x=1024&y=768"],
["{&list}", "&list=red,green,blue"],
["{&list*}", "&list=red&list=green&list=blue"],
["{&keys}", [
"&keys=comma,%2C,dot,.,semi,%3B",
"&keys=comma,%2C,semi,%3B,dot,.",
"&keys=dot,.,comma,%2C,semi,%3B",
"&keys=dot,.,semi,%3B,comma,%2C",
"&keys=semi,%3B,comma,%2C,dot,.",
"&keys=semi,%3B,dot,.,comma,%2C"
]],
["{&keys*}", [
"&comma=%2C&dot=.&semi=%3B",
"&comma=%2C&semi=%3B&dot=.",
"&dot=.&comma=%2C&semi=%3B",
"&dot=.&semi=%3B&comma=%2C",
"&semi=%3B&comma=%2C&dot=.",
"&semi=%3B&dot=.&comma=%2C"
]]
]
}
}

View file

@ -0,0 +1,218 @@
{
"Level 1 Examples" :
{
"level": 1,
"variables": {
"var" : "value",
"hello" : "Hello World!"
},
"testcases" : [
["{var}", "value"],
["{hello}", "Hello%20World%21"]
]
},
"Level 2 Examples" :
{
"level": 2,
"variables": {
"var" : "value",
"hello" : "Hello World!",
"path" : "/foo/bar"
},
"testcases" : [
["{+var}", "value"],
["{+hello}", "Hello%20World!"],
["{+path}/here", "/foo/bar/here"],
["here?ref={+path}", "here?ref=/foo/bar"]
]
},
"Level 3 Examples" :
{
"level": 3,
"variables": {
"var" : "value",
"hello" : "Hello World!",
"empty" : "",
"path" : "/foo/bar",
"x" : "1024",
"y" : "768"
},
"testcases" : [
["map?{x,y}", "map?1024,768"],
["{x,hello,y}", "1024,Hello%20World%21,768"],
["{+x,hello,y}", "1024,Hello%20World!,768"],
["{+path,x}/here", "/foo/bar,1024/here"],
["{#x,hello,y}", "#1024,Hello%20World!,768"],
["{#path,x}/here", "#/foo/bar,1024/here"],
["X{.var}", "X.value"],
["X{.x,y}", "X.1024.768"],
["{/var}", "/value"],
["{/var,x}/here", "/value/1024/here"],
["{;x,y}", ";x=1024;y=768"],
["{;x,y,empty}", ";x=1024;y=768;empty"],
["{?x,y}", "?x=1024&y=768"],
["{?x,y,empty}", "?x=1024&y=768&empty="],
["?fixed=yes{&x}", "?fixed=yes&x=1024"],
["{&x,y,empty}", "&x=1024&y=768&empty="]
]
},
"Level 4 Examples" :
{
"level": 4,
"variables": {
"var": "value",
"hello": "Hello World!",
"path": "/foo/bar",
"list": ["red", "green", "blue"],
"keys": {"semi": ";", "dot": ".", "comma":","}
},
"testcases": [
["{var:3}", "val"],
["{var:30}", "value"],
["{list}", "red,green,blue"],
["{list*}", "red,green,blue"],
["{keys}", [
"comma,%2C,dot,.,semi,%3B",
"comma,%2C,semi,%3B,dot,.",
"dot,.,comma,%2C,semi,%3B",
"dot,.,semi,%3B,comma,%2C",
"semi,%3B,comma,%2C,dot,.",
"semi,%3B,dot,.,comma,%2C"
]],
["{keys*}", [
"comma=%2C,dot=.,semi=%3B",
"comma=%2C,semi=%3B,dot=.",
"dot=.,comma=%2C,semi=%3B",
"dot=.,semi=%3B,comma=%2C",
"semi=%3B,comma=%2C,dot=.",
"semi=%3B,dot=.,comma=%2C"
]],
["{+path:6}/here", "/foo/b/here"],
["{+list}", "red,green,blue"],
["{+list*}", "red,green,blue"],
["{+keys}", [
"comma,,,dot,.,semi,;",
"comma,,,semi,;,dot,.",
"dot,.,comma,,,semi,;",
"dot,.,semi,;,comma,,",
"semi,;,comma,,,dot,.",
"semi,;,dot,.,comma,,"
]],
["{+keys*}", [
"comma=,,dot=.,semi=;",
"comma=,,semi=;,dot=.",
"dot=.,comma=,,semi=;",
"dot=.,semi=;,comma=,",
"semi=;,comma=,,dot=.",
"semi=;,dot=.,comma=,"
]],
["{#path:6}/here", "#/foo/b/here"],
["{#list}", "#red,green,blue"],
["{#list*}", "#red,green,blue"],
["{#keys}", [
"#comma,,,dot,.,semi,;",
"#comma,,,semi,;,dot,.",
"#dot,.,comma,,,semi,;",
"#dot,.,semi,;,comma,,",
"#semi,;,comma,,,dot,.",
"#semi,;,dot,.,comma,,"
]],
["{#keys*}", [
"#comma=,,dot=.,semi=;",
"#comma=,,semi=;,dot=.",
"#dot=.,comma=,,semi=;",
"#dot=.,semi=;,comma=,",
"#semi=;,comma=,,dot=.",
"#semi=;,dot=.,comma=,"
]],
["X{.var:3}", "X.val"],
["X{.list}", "X.red,green,blue"],
["X{.list*}", "X.red.green.blue"],
["X{.keys}", [
"X.comma,%2C,dot,.,semi,%3B",
"X.comma,%2C,semi,%3B,dot,.",
"X.dot,.,comma,%2C,semi,%3B",
"X.dot,.,semi,%3B,comma,%2C",
"X.semi,%3B,comma,%2C,dot,.",
"X.semi,%3B,dot,.,comma,%2C"
]],
["{/var:1,var}", "/v/value"],
["{/list}", "/red,green,blue"],
["{/list*}", "/red/green/blue"],
["{/list*,path:4}", "/red/green/blue/%2Ffoo"],
["{/keys}", [
"/comma,%2C,dot,.,semi,%3B",
"/comma,%2C,semi,%3B,dot,.",
"/dot,.,comma,%2C,semi,%3B",
"/dot,.,semi,%3B,comma,%2C",
"/semi,%3B,comma,%2C,dot,.",
"/semi,%3B,dot,.,comma,%2C"
]],
["{/keys*}", [
"/comma=%2C/dot=./semi=%3B",
"/comma=%2C/semi=%3B/dot=.",
"/dot=./comma=%2C/semi=%3B",
"/dot=./semi=%3B/comma=%2C",
"/semi=%3B/comma=%2C/dot=.",
"/semi=%3B/dot=./comma=%2C"
]],
["{;hello:5}", ";hello=Hello"],
["{;list}", ";list=red,green,blue"],
["{;list*}", ";list=red;list=green;list=blue"],
["{;keys}", [
";keys=comma,%2C,dot,.,semi,%3B",
";keys=comma,%2C,semi,%3B,dot,.",
";keys=dot,.,comma,%2C,semi,%3B",
";keys=dot,.,semi,%3B,comma,%2C",
";keys=semi,%3B,comma,%2C,dot,.",
";keys=semi,%3B,dot,.,comma,%2C"
]],
["{;keys*}", [
";comma=%2C;dot=.;semi=%3B",
";comma=%2C;semi=%3B;dot=.",
";dot=.;comma=%2C;semi=%3B",
";dot=.;semi=%3B;comma=%2C",
";semi=%3B;comma=%2C;dot=.",
";semi=%3B;dot=.;comma=%2C"
]],
["{?var:3}", "?var=val"],
["{?list}", "?list=red,green,blue"],
["{?list*}", "?list=red&list=green&list=blue"],
["{?keys}", [
"?keys=comma,%2C,dot,.,semi,%3B",
"?keys=comma,%2C,semi,%3B,dot,.",
"?keys=dot,.,comma,%2C,semi,%3B",
"?keys=dot,.,semi,%3B,comma,%2C",
"?keys=semi,%3B,comma,%2C,dot,.",
"?keys=semi,%3B,dot,.,comma,%2C"
]],
["{?keys*}", [
"?comma=%2C&dot=.&semi=%3B",
"?comma=%2C&semi=%3B&dot=.",
"?dot=.&comma=%2C&semi=%3B",
"?dot=.&semi=%3B&comma=%2C",
"?semi=%3B&comma=%2C&dot=.",
"?semi=%3B&dot=.&comma=%2C"
]],
["{&var:3}", "&var=val"],
["{&list}", "&list=red,green,blue"],
["{&list*}", "&list=red&list=green&list=blue"],
["{&keys}", [
"&keys=comma,%2C,dot,.,semi,%3B",
"&keys=comma,%2C,semi,%3B,dot,.",
"&keys=dot,.,comma,%2C,semi,%3B",
"&keys=dot,.,semi,%3B,comma,%2C",
"&keys=semi,%3B,comma,%2C,dot,.",
"&keys=semi,%3B,dot,.,comma,%2C"
]],
["{&keys*}", [
"&comma=%2C&dot=.&semi=%3B",
"&comma=%2C&semi=%3B&dot=.",
"&dot=.&comma=%2C&semi=%3B",
"&dot=.&semi=%3B&comma=%2C",
"&semi=%3B&comma=%2C&dot=.",
"&semi=%3B&dot=.&comma=%2C"
]]
]
}
}

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="json2xml.xslt"/>
<!-- the input test files need to be supplied as a sequence of file names only (no extension) -->
<xsl:param name="tests" select="('extended-tests', 'negative-tests', 'spec-examples-by-section', 'spec-examples')"/>
<xsl:param name="json-ext" select="'json'"/>
<xsl:param name="xml-ext" select="'xml'"/>
<!-- run this stylesheet with any input to generate the XML test files at output. -->
<!-- (a popular way of doing this is to supply the XSLT to itself as the input file.) -->
<xsl:template match="/">
<xsl:for-each select="$tests">
<xsl:variable name="file" select="current()"/>
<xsl:variable name="json">
<json>
<xsl:value-of select="unparsed-text(concat($file, '.', $json-ext))"/>
</json>
</xsl:variable>
<xsl:variable name="xml">
<xsl:apply-templates select="$json/json"/>
</xsl:variable>
<xsl:result-document href="{$file}.{$xml-ext}" method="xml" indent="yes">
<tests>
<xsl:for-each select="$xml/json/object/field">
<test name="{@name}">
<xsl:if test="exists(object/field[1][@name eq 'level'])">
<xsl:attribute name="level" select="object/field[1][@name eq 'level']/integer/text()"/>
</xsl:if>
<variables>
<xsl:for-each select="object/field[@name eq 'variables']/object/field">
<variable name="{@name}">
<xsl:copy-of select="*"/>
</variable>
</xsl:for-each>
</variables>
<testcases>
<xsl:for-each select="object/field[@name eq 'testcases']/array/array">
<testcase template="{*[1]}" result="{*[2]}"/>
</xsl:for-each> </testcases>
</test>
</xsl:for-each>
</tests>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>