blob: 118561dbfc188dee52cf614935df73964d4fe5c1 [file] [log] [blame] [raw]
RabsRincon670afd82018-02-13 14:49:07 +01001/* eslint-disable */
Matt Godbolt106ff7c2016-09-13 21:39:33 -05002// Taken from https://github.com/Nanonid/rison at 917679fb6cafa15e2a186cd5a47163792899b321
Matt Godbolt106ff7c2016-09-13 21:39:33 -05003// Uses CommonJS, AMD or browser globals to create a module.
4// Based on: https://github.com/umdjs/umd/blob/master/commonjsStrict.js
5(function (root, factory) {
6 if (typeof define === 'function' && define.amd) {
7 // AMD. Register as an anonymous module.
8 define(['exports'], factory);
9 } else if (typeof exports === 'object') {
10 // CommonJS
11 factory(exports);
12 } else {
13 // Browser globals
14 factory((root.rison = {}));
15 }
16}(this, function (exports) {
Matt Godbolt100a4002017-03-10 07:16:08 -060017 var rison = exports;
Matt Godbolt106ff7c2016-09-13 21:39:33 -050018
19//////////////////////////////////////////////////
20//
21// the stringifier is based on
22// http://json.org/json.js as of 2006-04-28 from json.org
23// the parser is based on
24// http://osteele.com/sources/openlaszlo/json
25//
26
Matt Godbolt100a4002017-03-10 07:16:08 -060027 if (typeof rison == 'undefined')
28 window.rison = {};
Matt Godbolt106ff7c2016-09-13 21:39:33 -050029
Matt Godbolt100a4002017-03-10 07:16:08 -060030 /**
31 * rules for an uri encoder that is more tolerant than encodeURIComponent
32 *
33 * encodeURIComponent passes ~!*()-_.'
34 *
35 * we also allow ,:@$/
36 *
37 */
38 rison.uri_ok = { // ok in url paths and in form query args
39 '~': true, '!': true, '*': true, '(': true, ')': true,
40 '-': true, '_': true, '.': true, ',': true,
41 ':': true, '@': true, '$': true,
42 "'": true, '/': true
43 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -050044
Matt Godbolt100a4002017-03-10 07:16:08 -060045 /*
46 * we divide the uri-safe glyphs into three sets
47 * <rison> - used by rison ' ! : ( ) ,
48 * <reserved> - not common in strings, reserved * @ $ & ; =
49 *
50 * we define <identifier> as anything that's not forbidden
51 */
Matt Godbolt106ff7c2016-09-13 21:39:33 -050052
Matt Godbolt100a4002017-03-10 07:16:08 -060053 /**
54 * punctuation characters that are legal inside ids.
55 */
Matt Godbolt106ff7c2016-09-13 21:39:33 -050056// this var isn't actually used
57//rison.idchar_punctuation = "_-./~";
58
Matt Godbolt100a4002017-03-10 07:16:08 -060059 (function () {
60 var l = [];
61 for (var hi = 0; hi < 16; hi++) {
62 for (var lo = 0; lo < 16; lo++) {
63 if (hi + lo == 0) continue;
64 var c = String.fromCharCode(hi * 16 + lo);
65 if (!/\w|[-_.\/~]/.test(c))
66 l.push('\\u00' + hi.toString(16) + lo.toString(16));
67 }
Matt Godbolt106ff7c2016-09-13 21:39:33 -050068 }
Matt Godbolt100a4002017-03-10 07:16:08 -060069 /**
70 * characters that are illegal inside ids.
71 * <rison> and <reserved> classes are illegal in ids.
72 *
73 */
74 rison.not_idchar = l.join('')
75 //idcrx = new RegExp('[' + rison.not_idchar + ']');
76 //console.log('NOT', (idcrx.test(' ')) );
77 })();
Matt Godbolt106ff7c2016-09-13 21:39:33 -050078//rison.not_idchar = " \t\r\n\"<>[]{}'!=:(),*@$;&";
Matt Godbolt100a4002017-03-10 07:16:08 -060079 rison.not_idchar = " '!:(),*@$";
Matt Godbolt106ff7c2016-09-13 21:39:33 -050080
81
Matt Godbolt100a4002017-03-10 07:16:08 -060082 /**
83 * characters that are illegal as the start of an id
84 * this is so ids can't look like numbers.
85 */
86 rison.not_idstart = "-0123456789";
Matt Godbolt106ff7c2016-09-13 21:39:33 -050087
88
Matt Godbolt100a4002017-03-10 07:16:08 -060089 (function () {
90 var idrx = '[^' + rison.not_idstart + rison.not_idchar +
91 '][^' + rison.not_idchar + ']*';
Matt Godbolt106ff7c2016-09-13 21:39:33 -050092
Matt Godbolt100a4002017-03-10 07:16:08 -060093 rison.id_ok = new RegExp('^' + idrx + '$');
Matt Godbolt106ff7c2016-09-13 21:39:33 -050094
Matt Godbolt100a4002017-03-10 07:16:08 -060095 // regexp to find the end of an id when parsing
96 // g flag on the regexp is necessary for iterative regexp.exec()
97 rison.next_id = new RegExp(idrx, 'g');
98 })();
Matt Godbolt106ff7c2016-09-13 21:39:33 -050099
Matt Godbolt100a4002017-03-10 07:16:08 -0600100 /**
101 * this is like encodeURIComponent() but quotes fewer characters.
102 *
103 * @see rison.uri_ok
104 *
105 * encodeURIComponent passes ~!*()-_.'
106 * rison.quote also passes ,:@$/
107 * and quotes " " as "+" instead of "%20"
108 */
109 rison.quote = function (x) {
110 if (/^[-A-Za-z0-9~!*()_.',:@$\/]*$/.test(x))
111 return x;
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500112
Matt Godbolt100a4002017-03-10 07:16:08 -0600113 return encodeURIComponent(x)
114 .replace(/%2C/g, ',')
115 .replace(/%3A/g, ':')
116 .replace(/%40/g, '@')
117 .replace(/%24/g, '$')
118 .replace(/%2F/g, '/')
119 .replace(/%20/g, '+');
120 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500121
122
123//
124// based on json.js 2006-04-28 from json.org
125// license: http://www.json.org/license.html
126//
127// hacked by nix for use in uris.
128//
129
Matt Godbolt100a4002017-03-10 07:16:08 -0600130 (function () {
131 var sq = { // url-ok but quoted in strings
132 "'": true, '!': true
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500133 },
Matt Godbolt100a4002017-03-10 07:16:08 -0600134 enc = function (v) {
135 if (v && typeof v.toJSON === 'function') v = v.toJSON();
136 var fn = s[typeof v];
137 if (fn) return fn(v);
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500138 },
Matt Godbolt100a4002017-03-10 07:16:08 -0600139 s = {
140 array: function (x) {
141 var a = ['!('], b, f, i, l = x.length, v;
142 for (i = 0; i < l; i += 1) {
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500143 v = enc(x[i]);
144 if (typeof v == 'string') {
145 if (b) {
146 a[a.length] = ',';
147 }
Matt Godbolt100a4002017-03-10 07:16:08 -0600148 a[a.length] = v;
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500149 b = true;
150 }
151 }
152 a[a.length] = ')';
153 return a.join('');
Matt Godbolt100a4002017-03-10 07:16:08 -0600154 },
155 'boolean': function (x) {
156 if (x)
157 return '!t';
158 return '!f'
159 },
160 'null': function (x) {
161 return "!n";
162 },
163 number: function (x) {
164 if (!isFinite(x))
165 return '!n';
166 // strip '+' out of exponent, '-' is ok though
167 return String(x).replace(/\+/, '');
168 },
169 object: function (x) {
170 if (x) {
171 if (x instanceof Array) {
172 return s.array(x);
173 }
174 // WILL: will this work on non-Firefox browsers?
175 if (typeof x.__prototype__ === 'object' && typeof x.__prototype__.encode_rison !== 'undefined')
176 return x.encode_rison();
177
178 var a = ['('], b, f, i, v, ki, ks = [];
179 for (i in x)
180 ks[ks.length] = i;
181 ks.sort();
182 for (ki = 0; ki < ks.length; ki++) {
183 i = ks[ki];
184 v = enc(x[i]);
185 if (typeof v == 'string') {
186 if (b) {
187 a[a.length] = ',';
188 }
189 a.push(s.string(i), ':', v);
190 b = true;
191 }
192 }
193 a[a.length] = ')';
194 return a.join('');
195 }
196 return '!n';
197 },
198 string: function (x) {
199 if (x == '')
200 return "''";
201
202 if (rison.id_ok.test(x))
203 return x;
204
205 x = x.replace(/(['!])/g, function (a, b) {
206 if (sq[b]) return '!' + b;
207 return b;
208 });
209 return "'" + x + "'";
210 },
211 undefined: function (x) {
212 // ignore undefined just like JSON
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500213 }
Matt Godbolt100a4002017-03-10 07:16:08 -0600214 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500215
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500216
Matt Godbolt100a4002017-03-10 07:16:08 -0600217 /**
218 * rison-encode a javascript structure
219 *
220 * implemementation based on Douglas Crockford's json.js:
221 * http://json.org/json.js as of 2006-04-28 from json.org
222 *
223 */
224 rison.encode = function (v) {
225 return enc(v);
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500226 };
227
Matt Godbolt100a4002017-03-10 07:16:08 -0600228 /**
229 * rison-encode a javascript object without surrounding parens
230 *
231 */
232 rison.encode_object = function (v) {
233 if (typeof v != 'object' || v === null || v instanceof Array)
234 throw new Error("rison.encode_object expects an object argument");
235 var r = s[typeof v](v);
236 return r.substring(1, r.length - 1);
237 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500238
Matt Godbolt100a4002017-03-10 07:16:08 -0600239 /**
240 * rison-encode a javascript array without surrounding parens
241 *
242 */
243 rison.encode_array = function (v) {
244 if (!(v instanceof Array))
245 throw new Error("rison.encode_array expects an array argument");
246 var r = s[typeof v](v);
247 return r.substring(2, r.length - 1);
248 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500249
Matt Godbolt100a4002017-03-10 07:16:08 -0600250 /**
251 * rison-encode and uri-encode a javascript structure
252 *
253 */
254 rison.encode_uri = function (v) {
255 return rison.quote(s[typeof v](v));
256 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500257
Matt Godbolt100a4002017-03-10 07:16:08 -0600258 })();
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500259
260
261//
262// based on openlaszlo-json and hacked by nix for use in uris.
263//
264// Author: Oliver Steele
265// Copyright: Copyright 2006 Oliver Steele. All rights reserved.
266// Homepage: http://osteele.com/sources/openlaszlo/json
267// License: MIT License.
268// Version: 1.0
269
270
Matt Godbolt100a4002017-03-10 07:16:08 -0600271 /**
272 * parse a rison string into a javascript structure.
273 *
274 * this is the simplest decoder entry point.
275 *
276 * based on Oliver Steele's OpenLaszlo-JSON
277 * http://osteele.com/sources/openlaszlo/json
278 */
279 rison.decode = function (r) {
280 var errcb = function (e) {
281 throw Error('rison decoder error: ' + e);
282 };
283 var p = new rison.parser(errcb);
284 return p.parse(r);
285 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500286
Matt Godbolt100a4002017-03-10 07:16:08 -0600287 /**
288 * parse an o-rison string into a javascript structure.
289 *
290 * this simply adds parentheses around the string before parsing.
291 */
292 rison.decode_object = function (r) {
293 return rison.decode('(' + r + ')');
294 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500295
Matt Godbolt100a4002017-03-10 07:16:08 -0600296 /**
297 * parse an a-rison string into a javascript structure.
298 *
299 * this simply adds array markup around the string before parsing.
300 */
301 rison.decode_array = function (r) {
302 return rison.decode('!(' + r + ')');
303 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500304
305
Matt Godbolt100a4002017-03-10 07:16:08 -0600306 /**
307 * construct a new parser object for reuse.
308 *
309 * @constructor
310 * @class A Rison parser class. You should probably
311 * use rison.decode instead.
312 * @see rison.decode
313 */
314 rison.parser = function (errcb) {
315 this.errorHandler = errcb;
316 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500317
Matt Godbolt100a4002017-03-10 07:16:08 -0600318 /**
319 * a string containing acceptable whitespace characters.
320 * by default the rison decoder tolerates no whitespace.
321 * to accept whitespace set rison.parser.WHITESPACE = " \t\n\r\f";
322 */
323 rison.parser.WHITESPACE = "";
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500324
325// expose this as-is?
Matt Godbolt100a4002017-03-10 07:16:08 -0600326 rison.parser.prototype.setOptions = function (options) {
327 if (options['errorHandler'])
328 this.errorHandler = options.errorHandler;
329 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500330
Matt Godbolt100a4002017-03-10 07:16:08 -0600331 /**
332 * parse a rison string into a javascript structure.
333 */
334 rison.parser.prototype.parse = function (str) {
335 this.string = str;
336 this.index = 0;
337 this.message = null;
338 var value = this.readValue();
339 if (!this.message && this.next())
340 value = this.error("unable to parse string as rison: '" + rison.encode(str) + "'");
341 if (this.message && this.errorHandler)
342 this.errorHandler(this.message, this.index);
343 return value;
344 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500345
Matt Godbolt100a4002017-03-10 07:16:08 -0600346 rison.parser.prototype.error = function (message) {
347 if (typeof(console) != 'undefined')
348 console.log('rison parser error: ', message);
349 this.message = message;
350 return undefined;
RabsRincon760bb352018-03-19 03:53:15 +0100351 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500352
Matt Godbolt100a4002017-03-10 07:16:08 -0600353 rison.parser.prototype.readValue = function () {
354 var c = this.next();
355 var fn = c && this.table[c];
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500356
Matt Godbolt100a4002017-03-10 07:16:08 -0600357 if (fn)
358 return fn.apply(this);
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500359
Matt Godbolt100a4002017-03-10 07:16:08 -0600360 // fell through table, parse as an id
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500361
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500362 var s = this.string;
Matt Godbolt100a4002017-03-10 07:16:08 -0600363 var i = this.index - 1;
364
365 // Regexp.lastIndex may not work right in IE before 5.5?
366 // g flag on the regexp is also necessary
367 rison.next_id.lastIndex = i;
368 var m = rison.next_id.exec(s);
369
370 // console.log('matched id', i, r.lastIndex);
371
372 if (m.length > 0) {
373 var id = m[0];
374 this.index = i + id.length;
375 return id; // a string
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500376 }
Matt Godbolt100a4002017-03-10 07:16:08 -0600377
378 if (c) return this.error("invalid character: '" + c + "'");
379 return this.error("empty expression");
RabsRincon760bb352018-03-19 03:53:15 +0100380 };
Matt Godbolt100a4002017-03-10 07:16:08 -0600381
382 rison.parser.parse_array = function (parser) {
383 var ar = [];
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500384 var c;
Matt Godbolt100a4002017-03-10 07:16:08 -0600385 while ((c = parser.next()) != ')') {
386 if (!c) return parser.error("unmatched '!('");
387 if (ar.length) {
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500388 if (c != ',')
Matt Godbolt100a4002017-03-10 07:16:08 -0600389 parser.error("missing ','");
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500390 } else if (c == ',') {
Matt Godbolt100a4002017-03-10 07:16:08 -0600391 return parser.error("extra ','");
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500392 } else
Matt Godbolt100a4002017-03-10 07:16:08 -0600393 --parser.index;
394 var n = parser.readValue();
395 if (typeof n == "undefined") return undefined;
396 ar.push(n);
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500397 }
Matt Godbolt100a4002017-03-10 07:16:08 -0600398 return ar;
399 };
400
401 rison.parser.bangs = {
402 t: true,
403 f: false,
404 n: null,
405 '(': rison.parser.parse_array
RabsRincon760bb352018-03-19 03:53:15 +0100406 };
Matt Godbolt100a4002017-03-10 07:16:08 -0600407
408 rison.parser.prototype.table = {
409 '!': function () {
410 var s = this.string;
411 var c = s.charAt(this.index++);
412 if (!c) return this.error('"!" at end of input');
413 var x = rison.parser.bangs[c];
414 if (typeof(x) == 'function') {
415 return x.call(null, this);
416 } else if (typeof(x) == 'undefined') {
417 return this.error('unknown literal: "!' + c + '"');
418 }
419 return x;
420 },
421 '(': function () {
422 var o = {};
423 var c;
424 var count = 0;
425 while ((c = this.next()) != ')') {
426 if (count) {
427 if (c != ',')
428 this.error("missing ','");
429 } else if (c == ',') {
430 return this.error("extra ','");
431 } else
432 --this.index;
433 var k = this.readValue();
434 if (typeof k == "undefined") return undefined;
435 if (this.next() != ':') return this.error("missing ':'");
436 var v = this.readValue();
437 if (typeof v == "undefined") return undefined;
438 o[k] = v;
439 count++;
440 }
441 return o;
442 },
443 "'": function () {
444 var s = this.string;
445 var i = this.index;
446 var start = i;
447 var segments = [];
448 var c;
449 while ((c = s.charAt(i++)) != "'") {
450 //if (i == s.length) return this.error('unmatched "\'"');
451 if (!c) return this.error('unmatched "\'"');
452 if (c == '!') {
453 if (start < i - 1)
454 segments.push(s.slice(start, i - 1));
455 c = s.charAt(i++);
456 if ("!'".indexOf(c) >= 0) {
457 segments.push(c);
458 } else {
459 return this.error('invalid string escape: "!' + c + '"');
460 }
461 start = i;
462 }
463 }
464 if (start < i - 1)
465 segments.push(s.slice(start, i - 1));
466 this.index = i;
467 return segments.length == 1 ? segments[0] : segments.join('');
468 },
469 // Also any digit. The statement that follows this table
470 // definition fills in the digits.
471 '-': function () {
472 var s = this.string;
473 var i = this.index;
474 var start = i - 1;
475 var state = 'int';
476 var permittedSigns = '-';
477 var transitions = {
478 'int+.': 'frac',
479 'int+e': 'exp',
480 'frac+e': 'exp'
481 };
482 do {
483 var c = s.charAt(i++);
484 if (!c) break;
485 if ('0' <= c && c <= '9') continue;
486 if (permittedSigns.indexOf(c) >= 0) {
487 permittedSigns = '';
488 continue;
489 }
490 state = transitions[state + '+' + c.toLowerCase()];
491 if (state == 'exp') permittedSigns = '-';
492 } while (state);
493 this.index = --i;
RabsRincon760bb352018-03-19 03:53:15 +0100494 s = s.slice(start, i);
Matt Godbolt100a4002017-03-10 07:16:08 -0600495 if (s == '-') return this.error("invalid number");
496 return Number(s);
497 }
498 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500499// copy table['-'] to each of table[i] | i <- '0'..'9':
Matt Godbolt100a4002017-03-10 07:16:08 -0600500 (function (table) {
501 for (var i = 0; i <= 9; i++)
502 table[String(i)] = table['-'];
503 })(rison.parser.prototype.table);
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500504
505// return the next non-whitespace character, or undefined
Matt Godbolt100a4002017-03-10 07:16:08 -0600506 rison.parser.prototype.next = function () {
507 var c;
508 var s = this.string;
509 var i = this.index;
510 do {
511 if (i == s.length) return undefined;
512 c = s.charAt(i++);
513 } while (rison.parser.WHITESPACE.indexOf(c) >= 0);
514 this.index = i;
515 return c;
516 };
Matt Godbolt106ff7c2016-09-13 21:39:33 -0500517
518// End of UMD module wrapper
519}));