js-routes 1.4.9 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +15 -0
  3. data/.gitignore +5 -0
  4. data/.nvmrc +1 -0
  5. data/.travis.yml +2 -1
  6. data/CHANGELOG.md +85 -0
  7. data/Rakefile +5 -2
  8. data/Readme.md +274 -98
  9. data/VERSION_2_UPGRADE.md +66 -0
  10. data/js-routes.gemspec +8 -5
  11. data/lib/js_routes/engine.rb +0 -1
  12. data/lib/js_routes/generators/middleware.rb +33 -0
  13. data/lib/js_routes/generators/webpacker.rb +32 -0
  14. data/lib/js_routes/middleware.rb +36 -0
  15. data/lib/js_routes/version.rb +1 -1
  16. data/lib/js_routes.rb +341 -171
  17. data/lib/routes.d.ts +79 -0
  18. data/lib/routes.js +501 -519
  19. data/lib/routes.ts +737 -0
  20. data/lib/tasks/js_routes.rake +8 -2
  21. data/lib/templates/erb.js +11 -0
  22. data/lib/templates/initializer.rb +5 -0
  23. data/lib/templates/routes.js.erb +1 -0
  24. data/package.json +37 -0
  25. data/spec/dummy/app/assets/config/manifest.js +2 -0
  26. data/spec/js_routes/default_serializer_spec.rb +19 -3
  27. data/spec/js_routes/{amd_compatibility_spec.rb → module_types/amd_spec.rb} +7 -14
  28. data/spec/js_routes/module_types/cjs_spec.rb +15 -0
  29. data/spec/js_routes/module_types/dts/routes.spec.d.ts +114 -0
  30. data/spec/js_routes/module_types/dts/test.spec.ts +56 -0
  31. data/spec/js_routes/module_types/dts_spec.rb +111 -0
  32. data/spec/js_routes/module_types/esm_spec.rb +45 -0
  33. data/spec/js_routes/module_types/nil_spec.rb +86 -0
  34. data/spec/js_routes/{generated_javascript_spec.rb → module_types/umd_spec.rb} +33 -27
  35. data/spec/js_routes/options_spec.rb +67 -56
  36. data/spec/js_routes/rails_routes_compatibility_spec.rb +69 -25
  37. data/spec/js_routes/zzz_last_post_rails_init_spec.rb +4 -4
  38. data/spec/spec_helper.rb +34 -17
  39. data/spec/support/routes.rb +10 -4
  40. data/spec/tsconfig.json +4 -0
  41. data/tsconfig.json +28 -0
  42. data/yarn.lock +2145 -0
  43. metadata +42 -22
  44. data/lib/routes.js.coffee +0 -411
data/lib/routes.js CHANGED
@@ -1,523 +1,505 @@
1
- /*
2
- File generated by js-routes GEM_VERSION
3
- Based on Rails RAILS_VERSION routes of APP_CLASS
1
+ /**
2
+ * File generated by js-routes RubyVariables.GEM_VERSION
3
+ * Based on Rails RubyVariables.RAILS_VERSION routes of RubyVariables.APP_CLASS
4
4
  */
5
-
6
- (function() {
7
- var DeprecatedGlobbingBehavior, NodeTypes, ParameterMissing, ReservedOptions, SpecialOptionsKey, UriEncoderSegmentRegex, Utils, result, root,
8
- hasProp = {}.hasOwnProperty,
9
- slice = [].slice;
10
-
11
- root = typeof exports !== "undefined" && exports !== null ? exports : this;
12
-
13
- ParameterMissing = function(message, fileName, lineNumber) {
14
- var instance;
15
- instance = new Error(message, fileName, lineNumber);
16
- if (Object.setPrototypeOf) {
17
- Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
18
- } else {
19
- instance.__proto__ = this.__proto__;
20
- }
21
- if (Error.captureStackTrace) {
22
- Error.captureStackTrace(instance, ParameterMissing);
5
+ RubyVariables.WRAPPER((that) => {
6
+ const hasProp = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
7
+ let NodeTypes;
8
+ (function (NodeTypes) {
9
+ NodeTypes[NodeTypes["GROUP"] = 1] = "GROUP";
10
+ NodeTypes[NodeTypes["CAT"] = 2] = "CAT";
11
+ NodeTypes[NodeTypes["SYMBOL"] = 3] = "SYMBOL";
12
+ NodeTypes[NodeTypes["OR"] = 4] = "OR";
13
+ NodeTypes[NodeTypes["STAR"] = 5] = "STAR";
14
+ NodeTypes[NodeTypes["LITERAL"] = 6] = "LITERAL";
15
+ NodeTypes[NodeTypes["SLASH"] = 7] = "SLASH";
16
+ NodeTypes[NodeTypes["DOT"] = 8] = "DOT";
17
+ })(NodeTypes || (NodeTypes = {}));
18
+ const Root = that;
19
+ const isBroswer = typeof window !== "undefined";
20
+ const ModuleReferences = {
21
+ CJS: {
22
+ define(routes) {
23
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
24
+ module.exports = routes;
25
+ },
26
+ isSupported() {
27
+ return typeof module === "object";
28
+ },
29
+ },
30
+ AMD: {
31
+ define(routes) {
32
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
33
+ define([], function () {
34
+ return routes;
35
+ });
36
+ },
37
+ isSupported() {
38
+ return typeof define === "function" && !!define.amd;
39
+ },
40
+ },
41
+ UMD: {
42
+ define(routes) {
43
+ if (ModuleReferences.AMD.isSupported()) {
44
+ ModuleReferences.AMD.define(routes);
45
+ }
46
+ else {
47
+ if (ModuleReferences.CJS.isSupported()) {
48
+ try {
49
+ ModuleReferences.CJS.define(routes);
50
+ }
51
+ catch (error) {
52
+ if (error.name !== "TypeError")
53
+ throw error;
54
+ }
55
+ }
56
+ }
57
+ },
58
+ isSupported() {
59
+ return (ModuleReferences.AMD.isSupported() ||
60
+ ModuleReferences.CJS.isSupported());
61
+ },
62
+ },
63
+ ESM: {
64
+ define() {
65
+ // Module can only be defined using ruby code generation
66
+ },
67
+ isSupported() {
68
+ // Its impossible to check if "export" keyword is supported
69
+ return true;
70
+ },
71
+ },
72
+ NIL: {
73
+ define(routes) {
74
+ Utils.namespace(Root, RubyVariables.NAMESPACE, routes);
75
+ },
76
+ isSupported() {
77
+ return !RubyVariables.NAMESPACE || !!Root;
78
+ },
79
+ },
80
+ DTS: {
81
+ // Acts the same as ESM
82
+ define(routes) {
83
+ ModuleReferences.ESM.define(routes);
84
+ },
85
+ isSupported() {
86
+ return ModuleReferences.ESM.isSupported();
87
+ },
88
+ },
89
+ };
90
+ class ParametersMissing extends Error {
91
+ constructor(...keys) {
92
+ super(`Route missing required keys: ${keys.join(", ")}`);
93
+ this.keys = keys;
94
+ Object.setPrototypeOf(this, Object.getPrototypeOf(this));
95
+ this.name = ParametersMissing.name;
96
+ }
23
97
  }
24
- return instance;
25
- };
26
-
27
- ParameterMissing.prototype = Object.create(Error.prototype, {
28
- constructor: {
29
- value: Error,
30
- enumerable: false,
31
- writable: true,
32
- configurable: true
98
+ const UriEncoderSegmentRegex = /[^a-zA-Z0-9\-._~!$&'()*+,;=:@]/g;
99
+ const ReservedOptions = [
100
+ "anchor",
101
+ "trailing_slash",
102
+ "subdomain",
103
+ "host",
104
+ "port",
105
+ "protocol",
106
+ ];
107
+ class UtilsClass {
108
+ constructor() {
109
+ this.configuration = {
110
+ prefix: RubyVariables.PREFIX,
111
+ default_url_options: RubyVariables.DEFAULT_URL_OPTIONS,
112
+ special_options_key: RubyVariables.SPECIAL_OPTIONS_KEY,
113
+ serializer: RubyVariables.SERIALIZER || this.default_serializer.bind(this),
114
+ };
115
+ }
116
+ default_serializer(value, prefix) {
117
+ if (this.is_nullable(value)) {
118
+ return "";
119
+ }
120
+ if (!prefix && !this.is_object(value)) {
121
+ throw new Error("Url parameters should be a javascript hash");
122
+ }
123
+ prefix = prefix || "";
124
+ const result = [];
125
+ if (this.is_array(value)) {
126
+ for (const element of value) {
127
+ result.push(this.default_serializer(element, prefix + "[]"));
128
+ }
129
+ }
130
+ else if (this.is_object(value)) {
131
+ for (let key in value) {
132
+ if (!hasProp(value, key))
133
+ continue;
134
+ let prop = value[key];
135
+ if (this.is_nullable(prop) && prefix) {
136
+ prop = "";
137
+ }
138
+ if (this.is_not_nullable(prop)) {
139
+ if (prefix) {
140
+ key = prefix + "[" + key + "]";
141
+ }
142
+ result.push(this.default_serializer(prop, key));
143
+ }
144
+ }
145
+ }
146
+ else {
147
+ if (this.is_not_nullable(value)) {
148
+ result.push(encodeURIComponent(prefix) + "=" + encodeURIComponent("" + value));
149
+ }
150
+ }
151
+ return result.join("&");
152
+ }
153
+ serialize(object) {
154
+ return this.configuration.serializer(object);
155
+ }
156
+ extract_options(number_of_params, args) {
157
+ const last_el = args[args.length - 1];
158
+ if ((args.length > number_of_params && last_el === 0) ||
159
+ (this.is_object(last_el) &&
160
+ !this.looks_like_serialized_model(last_el))) {
161
+ if (this.is_object(last_el)) {
162
+ delete last_el[this.configuration.special_options_key];
163
+ }
164
+ return {
165
+ args: args.slice(0, args.length - 1),
166
+ options: last_el,
167
+ };
168
+ }
169
+ else {
170
+ return { args, options: {} };
171
+ }
172
+ }
173
+ looks_like_serialized_model(object) {
174
+ return (this.is_object(object) &&
175
+ !(this.configuration.special_options_key in object) &&
176
+ ("id" in object || "to_param" in object || "toParam" in object));
177
+ }
178
+ path_identifier(object) {
179
+ const result = this.unwrap_path_identifier(object);
180
+ return this.is_nullable(result) || result === false ? "" : "" + result;
181
+ }
182
+ unwrap_path_identifier(object) {
183
+ let result = object;
184
+ if (!this.is_object(object)) {
185
+ return object;
186
+ }
187
+ if ("to_param" in object) {
188
+ result = object.to_param;
189
+ }
190
+ else if ("toParam" in object) {
191
+ result = object.toParam;
192
+ }
193
+ else if ("id" in object) {
194
+ result = object.id;
195
+ }
196
+ else {
197
+ result = object;
198
+ }
199
+ return this.is_callable(result) ? result.call(object) : result;
200
+ }
201
+ partition_parameters(parts, required_params, default_options, call_arguments) {
202
+ // eslint-disable-next-line prefer-const
203
+ let { args, options } = this.extract_options(parts.length, call_arguments);
204
+ if (args.length > parts.length) {
205
+ throw new Error("Too many parameters provided for path");
206
+ }
207
+ let use_all_parts = args.length > required_params.length;
208
+ const parts_options = {
209
+ ...this.configuration.default_url_options,
210
+ };
211
+ for (const key in options) {
212
+ const value = options[key];
213
+ if (!hasProp(options, key))
214
+ continue;
215
+ use_all_parts = true;
216
+ if (parts.includes(key)) {
217
+ parts_options[key] = value;
218
+ }
219
+ }
220
+ options = {
221
+ ...this.configuration.default_url_options,
222
+ ...default_options,
223
+ ...options,
224
+ };
225
+ const keyword_parameters = {};
226
+ const query_parameters = {};
227
+ for (const key in options) {
228
+ if (!hasProp(options, key))
229
+ continue;
230
+ const value = options[key];
231
+ if (this.is_reserved_option(key)) {
232
+ keyword_parameters[key] = value;
233
+ }
234
+ else {
235
+ if (!this.is_nullable(value) &&
236
+ (value !== default_options[key] || required_params.includes(key))) {
237
+ query_parameters[key] = value;
238
+ }
239
+ }
240
+ }
241
+ const route_parts = use_all_parts ? parts : required_params;
242
+ let i = 0;
243
+ for (const part of route_parts) {
244
+ if (i < args.length) {
245
+ const value = args[i];
246
+ if (!hasProp(parts_options, part)) {
247
+ query_parameters[part] = value;
248
+ ++i;
249
+ }
250
+ }
251
+ }
252
+ return { keyword_parameters, query_parameters };
253
+ }
254
+ build_route(parts, required_params, default_options, route, absolute, args) {
255
+ const { keyword_parameters, query_parameters, } = this.partition_parameters(parts, required_params, default_options, args);
256
+ const missing_params = required_params.filter((param) => !hasProp(query_parameters, param) ||
257
+ this.is_nullable(query_parameters[param]));
258
+ if (missing_params.length) {
259
+ throw new ParametersMissing(...missing_params);
260
+ }
261
+ let result = this.get_prefix() + this.visit(route, query_parameters);
262
+ if (keyword_parameters.trailing_slash) {
263
+ result = result.replace(/(.*?)[/]?$/, "$1/");
264
+ }
265
+ const url_params = this.serialize(query_parameters);
266
+ if (url_params.length) {
267
+ result += "?" + url_params;
268
+ }
269
+ result += keyword_parameters.anchor
270
+ ? "#" + keyword_parameters.anchor
271
+ : "";
272
+ if (absolute) {
273
+ result = this.route_url(keyword_parameters) + result;
274
+ }
275
+ return result;
276
+ }
277
+ visit(route, parameters, optional = false) {
278
+ switch (route[0]) {
279
+ case NodeTypes.GROUP:
280
+ return this.visit(route[1], parameters, true);
281
+ case NodeTypes.CAT:
282
+ return this.visit_cat(route, parameters, optional);
283
+ case NodeTypes.SYMBOL:
284
+ return this.visit_symbol(route, parameters, optional);
285
+ case NodeTypes.STAR:
286
+ return this.visit_globbing(route[1], parameters, true);
287
+ case NodeTypes.LITERAL:
288
+ case NodeTypes.SLASH:
289
+ case NodeTypes.DOT:
290
+ return route[1];
291
+ default:
292
+ throw new Error("Unknown Rails node type");
293
+ }
294
+ }
295
+ is_not_nullable(object) {
296
+ return !this.is_nullable(object);
297
+ }
298
+ is_nullable(object) {
299
+ return object === undefined || object === null;
300
+ }
301
+ visit_cat(
302
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
303
+ [_type, left, right], parameters, optional) {
304
+ const left_part = this.visit(left, parameters, optional);
305
+ let right_part = this.visit(right, parameters, optional);
306
+ if (optional &&
307
+ ((this.is_optional_node(left[0]) && !left_part) ||
308
+ (this.is_optional_node(right[0]) && !right_part))) {
309
+ return "";
310
+ }
311
+ // if left_part ends on '/' and right_part starts on '/'
312
+ if (left_part[left_part.length - 1] === "/" && right_part[0] === "/") {
313
+ // strip slash from right_part
314
+ // to prevent double slash
315
+ right_part = right_part.substring(1);
316
+ }
317
+ return left_part + right_part;
318
+ }
319
+ visit_symbol(
320
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
321
+ [_type, key], parameters, optional) {
322
+ const value = this.path_identifier(parameters[key]);
323
+ delete parameters[key];
324
+ if (value.length) {
325
+ return this.encode_segment(value);
326
+ }
327
+ if (optional) {
328
+ return "";
329
+ }
330
+ else {
331
+ throw new ParametersMissing(key);
332
+ }
333
+ }
334
+ encode_segment(segment) {
335
+ return segment.replace(UriEncoderSegmentRegex, (str) => encodeURIComponent(str));
336
+ }
337
+ is_optional_node(node) {
338
+ return [NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT].includes(node);
339
+ }
340
+ build_path_spec(route, wildcard = false) {
341
+ let key;
342
+ switch (route[0]) {
343
+ case NodeTypes.GROUP:
344
+ return "(" + this.build_path_spec(route[1]) + ")";
345
+ case NodeTypes.CAT:
346
+ return (this.build_path_spec(route[1]) + this.build_path_spec(route[2]));
347
+ case NodeTypes.STAR:
348
+ return this.build_path_spec(route[1], true);
349
+ case NodeTypes.SYMBOL:
350
+ key = route[1];
351
+ if (wildcard) {
352
+ return (key.startsWith("*") ? "" : "*") + key;
353
+ }
354
+ else {
355
+ return ":" + key;
356
+ }
357
+ break;
358
+ case NodeTypes.SLASH:
359
+ case NodeTypes.DOT:
360
+ case NodeTypes.LITERAL:
361
+ return route[1];
362
+ default:
363
+ throw new Error("Unknown Rails node type");
364
+ }
365
+ }
366
+ visit_globbing(route, parameters, optional) {
367
+ const key = route[1];
368
+ let value = parameters[key];
369
+ delete parameters[key];
370
+ if (this.is_nullable(value)) {
371
+ return this.visit(route, parameters, optional);
372
+ }
373
+ if (this.is_array(value)) {
374
+ value = value.join("/");
375
+ }
376
+ const result = this.path_identifier(value);
377
+ return RubyVariables.DEPRECATED_GLOBBING_BEHAVIOR
378
+ ? result
379
+ : encodeURI(result);
380
+ }
381
+ get_prefix() {
382
+ const prefix = this.configuration.prefix;
383
+ return prefix.match("/$")
384
+ ? prefix.substring(0, prefix.length - 1)
385
+ : prefix;
386
+ }
387
+ route(parts_table, route_spec, absolute = false) {
388
+ const required_params = [];
389
+ const parts = [];
390
+ const default_options = {};
391
+ for (const [part, { r: required, d: value }] of Object.entries(parts_table)) {
392
+ parts.push(part);
393
+ if (required) {
394
+ required_params.push(part);
395
+ }
396
+ if (this.is_not_nullable(value)) {
397
+ default_options[part] = value;
398
+ }
399
+ }
400
+ const result = (...args) => {
401
+ return this.build_route(parts, required_params, default_options, route_spec, absolute, args);
402
+ };
403
+ result.requiredParams = () => required_params;
404
+ result.toString = () => {
405
+ return this.build_path_spec(route_spec);
406
+ };
407
+ return result;
408
+ }
409
+ route_url(route_defaults) {
410
+ const hostname = route_defaults.host || this.current_host();
411
+ if (!hostname) {
412
+ return "";
413
+ }
414
+ const subdomain = route_defaults.subdomain
415
+ ? route_defaults.subdomain + "."
416
+ : "";
417
+ const protocol = route_defaults.protocol || this.current_protocol();
418
+ let port = route_defaults.port ||
419
+ (!route_defaults.host ? this.current_port() : undefined);
420
+ port = port ? ":" + port : "";
421
+ return protocol + "://" + subdomain + hostname + port;
422
+ }
423
+ current_host() {
424
+ var _a;
425
+ return (isBroswer && ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.hostname)) || "";
426
+ }
427
+ current_protocol() {
428
+ var _a, _b;
429
+ return ((isBroswer && ((_b = (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.protocol) === null || _b === void 0 ? void 0 : _b.replace(/:$/, ""))) || "http");
430
+ }
431
+ current_port() {
432
+ var _a;
433
+ return (isBroswer && ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.port)) || "";
434
+ }
435
+ is_object(value) {
436
+ return (typeof value === "object" &&
437
+ Object.prototype.toString.call(value) === "[object Object]");
438
+ }
439
+ is_array(object) {
440
+ return object instanceof Array;
441
+ }
442
+ is_callable(object) {
443
+ return typeof object === "function" && !!object.call;
444
+ }
445
+ is_reserved_option(key) {
446
+ return ReservedOptions.includes(key);
447
+ }
448
+ namespace(object, namespace, routes) {
449
+ const parts = (namespace === null || namespace === void 0 ? void 0 : namespace.split(".")) || [];
450
+ if (parts.length === 0) {
451
+ return;
452
+ }
453
+ for (let index = 0; index < parts.length; index++) {
454
+ const part = parts[index];
455
+ if (index < parts.length - 1) {
456
+ object = object[part] || (object[part] = {});
457
+ }
458
+ else {
459
+ object[part] = routes;
460
+ }
461
+ }
462
+ }
463
+ configure(new_config) {
464
+ this.configuration = { ...this.configuration, ...new_config };
465
+ return this.configuration;
466
+ }
467
+ config() {
468
+ return { ...this.configuration };
469
+ }
470
+ is_module_supported(name) {
471
+ return ModuleReferences[name].isSupported();
472
+ }
473
+ ensure_module_supported(name) {
474
+ if (!this.is_module_supported(name)) {
475
+ throw new Error(`${name} is not supported by runtime`);
476
+ }
477
+ }
478
+ define_module(name, module) {
479
+ this.ensure_module_supported(name);
480
+ ModuleReferences[name].define(module);
481
+ }
33
482
  }
34
- });
35
-
36
- if (Object.setPrototypeOf) {
37
- Object.setPrototypeOf(ParameterMissing, Error);
38
- } else {
39
- ParameterMissing.__proto__ = Error;
40
- }
41
-
42
- NodeTypes = NODE_TYPES;
43
-
44
- DeprecatedGlobbingBehavior = DEPRECATED_GLOBBING_BEHAVIOR;
45
-
46
- SpecialOptionsKey = SPECIAL_OPTIONS_KEY;
47
-
48
- UriEncoderSegmentRegex = /[^a-zA-Z0-9\-\._~!\$&'\(\)\*\+,;=:@]/g;
49
-
50
- ReservedOptions = ['anchor', 'trailing_slash', 'subdomain', 'host', 'port', 'protocol'];
51
-
52
- Utils = {
53
- configuration: {
54
- prefix: PREFIX,
55
- default_url_options: DEFAULT_URL_OPTIONS,
56
- special_options_key: SPECIAL_OPTIONS_KEY,
57
- serializer: SERIALIZER
58
- },
59
- default_serializer: function(object, prefix) {
60
- var element, i, j, key, len, prop, s;
61
- if (prefix == null) {
62
- prefix = null;
63
- }
64
- if (object == null) {
65
- return "";
66
- }
67
- if (!prefix && !(this.get_object_type(object) === "object")) {
68
- throw new Error("Url parameters should be a javascript hash");
69
- }
70
- s = [];
71
- switch (this.get_object_type(object)) {
72
- case "array":
73
- for (i = j = 0, len = object.length; j < len; i = ++j) {
74
- element = object[i];
75
- s.push(this.default_serializer(element, prefix + "[]"));
76
- }
77
- break;
78
- case "object":
79
- for (key in object) {
80
- if (!hasProp.call(object, key)) continue;
81
- prop = object[key];
82
- if ((prop == null) && (prefix != null)) {
83
- prop = "";
84
- }
85
- if (prop != null) {
86
- if (prefix != null) {
87
- key = prefix + "[" + key + "]";
88
- }
89
- s.push(this.default_serializer(prop, key));
90
- }
91
- }
92
- break;
93
- default:
94
- if (object != null) {
95
- s.push((encodeURIComponent(prefix.toString())) + "=" + (encodeURIComponent(object.toString())));
96
- }
97
- }
98
- if (!s.length) {
99
- return "";
100
- }
101
- return s.join("&");
102
- },
103
- serialize: function(object) {
104
- var custom_serializer;
105
- custom_serializer = this.configuration.serializer;
106
- if ((custom_serializer != null) && this.get_object_type(custom_serializer) === "function") {
107
- return custom_serializer(object);
108
- } else {
109
- return this.default_serializer(object);
110
- }
111
- },
112
- clean_path: function(path) {
113
- var last_index;
114
- path = path.split("://");
115
- last_index = path.length - 1;
116
- path[last_index] = path[last_index].replace(/\/+/g, "/");
117
- return path.join("://");
118
- },
119
- extract_options: function(number_of_params, args) {
120
- var last_el, options;
121
- last_el = args[args.length - 1];
122
- if ((args.length > number_of_params && last_el === void 0) || ((last_el != null) && "object" === this.get_object_type(last_el) && !this.looks_like_serialized_model(last_el))) {
123
- options = args.pop() || {};
124
- delete options[this.configuration.special_options_key];
125
- return options;
126
- } else {
127
- return {};
128
- }
129
- },
130
- looks_like_serialized_model: function(object) {
131
- return !object[this.configuration.special_options_key] && ("id" in object || "to_param" in object);
132
- },
133
- path_identifier: function(object) {
134
- var property;
135
- if (object === 0) {
136
- return "0";
137
- }
138
- if (!object) {
139
- return "";
140
- }
141
- property = object;
142
- if (this.get_object_type(object) === "object") {
143
- if ("to_param" in object) {
144
- if (object.to_param == null) {
145
- throw new ParameterMissing("Route parameter missing: to_param");
146
- }
147
- property = object.to_param;
148
- } else if ("id" in object) {
149
- if (object.id == null) {
150
- throw new ParameterMissing("Route parameter missing: id");
151
- }
152
- property = object.id;
153
- } else {
154
- property = object;
155
- }
156
- if (this.get_object_type(property) === "function") {
157
- property = property.call(object);
158
- }
159
- }
160
- return property.toString();
161
- },
162
- clone: function(obj) {
163
- var attr, copy, key;
164
- if ((obj == null) || "object" !== this.get_object_type(obj)) {
165
- return obj;
166
- }
167
- copy = obj.constructor();
168
- for (key in obj) {
169
- if (!hasProp.call(obj, key)) continue;
170
- attr = obj[key];
171
- copy[key] = attr;
172
- }
173
- return copy;
174
- },
175
- merge: function() {
176
- var tap, xs;
177
- xs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
178
- tap = function(o, fn) {
179
- fn(o);
180
- return o;
181
- };
182
- if ((xs != null ? xs.length : void 0) > 0) {
183
- return tap({}, function(m) {
184
- var j, k, len, results, v, x;
185
- results = [];
186
- for (j = 0, len = xs.length; j < len; j++) {
187
- x = xs[j];
188
- results.push((function() {
189
- var results1;
190
- results1 = [];
191
- for (k in x) {
192
- v = x[k];
193
- results1.push(m[k] = v);
194
- }
195
- return results1;
196
- })());
197
- }
198
- return results;
199
- });
200
- }
201
- },
202
- normalize_options: function(parts, required_parts, default_options, actual_parameters) {
203
- var i, j, key, len, options, part, parts_options, result, route_parts, url_parameters, use_all_parts, value;
204
- options = this.extract_options(parts.length, actual_parameters);
205
- if (actual_parameters.length > parts.length) {
206
- throw new Error("Too many parameters provided for path");
207
- }
208
- use_all_parts = actual_parameters.length > required_parts.length;
209
- parts_options = {};
210
- for (key in options) {
211
- if (!hasProp.call(options, key)) continue;
212
- use_all_parts = true;
213
- if (this.indexOf(parts, key) >= 0) {
214
- parts_options[key] = value;
215
- }
216
- }
217
- options = this.merge(this.configuration.default_url_options, default_options, options);
218
- result = {};
219
- url_parameters = {};
220
- result['url_parameters'] = url_parameters;
221
- for (key in options) {
222
- if (!hasProp.call(options, key)) continue;
223
- value = options[key];
224
- if (this.indexOf(ReservedOptions, key) >= 0) {
225
- result[key] = value;
226
- } else {
227
- url_parameters[key] = value;
228
- }
229
- }
230
- route_parts = use_all_parts ? parts : required_parts;
231
- i = 0;
232
- for (j = 0, len = route_parts.length; j < len; j++) {
233
- part = route_parts[j];
234
- if (i < actual_parameters.length) {
235
- if (!parts_options.hasOwnProperty(part)) {
236
- url_parameters[part] = actual_parameters[i];
237
- ++i;
238
- }
239
- }
240
- }
241
- return result;
242
- },
243
- build_route: function(parts, required_parts, default_options, route, full_url, args) {
244
- var options, parameters, result, url, url_params;
245
- args = Array.prototype.slice.call(args);
246
- options = this.normalize_options(parts, required_parts, default_options, args);
247
- parameters = options['url_parameters'];
248
- result = "" + (this.get_prefix()) + (this.visit(route, parameters));
249
- url = Utils.clean_path(result);
250
- if (options['trailing_slash'] === true) {
251
- url = url.replace(/(.*?)[\/]?$/, "$1/");
252
- }
253
- if ((url_params = this.serialize(parameters)).length) {
254
- url += "?" + url_params;
255
- }
256
- url += options.anchor ? "#" + options.anchor : "";
257
- if (full_url) {
258
- url = this.route_url(options) + url;
259
- }
260
- return url;
261
- },
262
- visit: function(route, parameters, optional) {
263
- var left, left_part, right, right_part, type, value;
264
- if (optional == null) {
265
- optional = false;
266
- }
267
- type = route[0], left = route[1], right = route[2];
268
- switch (type) {
269
- case NodeTypes.GROUP:
270
- return this.visit(left, parameters, true);
271
- case NodeTypes.STAR:
272
- return this.visit_globbing(left, parameters, true);
273
- case NodeTypes.LITERAL:
274
- case NodeTypes.SLASH:
275
- case NodeTypes.DOT:
276
- return left;
277
- case NodeTypes.CAT:
278
- left_part = this.visit(left, parameters, optional);
279
- right_part = this.visit(right, parameters, optional);
280
- if (optional && ((this.is_optional_node(left[0]) && !left_part) || ((this.is_optional_node(right[0])) && !right_part))) {
281
- return "";
282
- }
283
- return "" + left_part + right_part;
284
- case NodeTypes.SYMBOL:
285
- value = parameters[left];
286
- delete parameters[left];
287
- if (value != null) {
288
- return this.encode_segment(this.path_identifier(value));
289
- }
290
- if (optional) {
291
- return "";
292
- } else {
293
- throw new ParameterMissing("Route parameter missing: " + left);
294
- }
295
- break;
296
- default:
297
- throw new Error("Unknown Rails node type");
298
- }
299
- },
300
- encode_segment: function(segment) {
301
- return segment.replace(UriEncoderSegmentRegex, function(str) {
302
- return encodeURIComponent(str);
303
- });
304
- },
305
- is_optional_node: function(node) {
306
- return this.indexOf([NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT], node) >= 0;
307
- },
308
- build_path_spec: function(route, wildcard) {
309
- var left, right, type;
310
- if (wildcard == null) {
311
- wildcard = false;
312
- }
313
- type = route[0], left = route[1], right = route[2];
314
- switch (type) {
315
- case NodeTypes.GROUP:
316
- return "(" + (this.build_path_spec(left)) + ")";
317
- case NodeTypes.CAT:
318
- return "" + (this.build_path_spec(left)) + (this.build_path_spec(right));
319
- case NodeTypes.STAR:
320
- return this.build_path_spec(left, true);
321
- case NodeTypes.SYMBOL:
322
- if (wildcard === true) {
323
- return "" + (left[0] === '*' ? '' : '*') + left;
324
- } else {
325
- return ":" + left;
326
- }
327
- break;
328
- case NodeTypes.SLASH:
329
- case NodeTypes.DOT:
330
- case NodeTypes.LITERAL:
331
- return left;
332
- default:
333
- throw new Error("Unknown Rails node type");
334
- }
335
- },
336
- visit_globbing: function(route, parameters, optional) {
337
- var left, right, type, value;
338
- type = route[0], left = route[1], right = route[2];
339
- value = parameters[left];
340
- delete parameters[left];
341
- if (value == null) {
342
- return this.visit(route, parameters, optional);
343
- }
344
- value = (function() {
345
- switch (this.get_object_type(value)) {
346
- case "array":
347
- return value.join("/");
348
- default:
349
- return value;
350
- }
351
- }).call(this);
352
- if (DeprecatedGlobbingBehavior) {
353
- return this.path_identifier(value);
354
- } else {
355
- return encodeURI(this.path_identifier(value));
356
- }
357
- },
358
- get_prefix: function() {
359
- var prefix;
360
- prefix = this.configuration.prefix;
361
- if (prefix !== "") {
362
- prefix = (prefix.match("/$") ? prefix : prefix + "/");
363
- }
364
- return prefix;
365
- },
366
- route: function(parts_table, default_options, route_spec, full_url) {
367
- var j, len, part, parts, path_fn, ref, required, required_parts;
368
- required_parts = [];
369
- parts = [];
370
- for (j = 0, len = parts_table.length; j < len; j++) {
371
- ref = parts_table[j], part = ref[0], required = ref[1];
372
- parts.push(part);
373
- if (required) {
374
- required_parts.push(part);
375
- }
376
- }
377
- path_fn = function() {
378
- return Utils.build_route(parts, required_parts, default_options, route_spec, full_url, arguments);
379
- };
380
- path_fn.required_params = required_parts;
381
- path_fn.toString = function() {
382
- return Utils.build_path_spec(route_spec);
383
- };
384
- return path_fn;
385
- },
386
- route_url: function(route_defaults) {
387
- var hostname, port, protocol, subdomain;
388
- if (typeof route_defaults === 'string') {
389
- return route_defaults;
390
- }
391
- hostname = route_defaults.host || Utils.current_host();
392
- if (!hostname) {
393
- return '';
394
- }
395
- subdomain = route_defaults.subdomain ? route_defaults.subdomain + '.' : '';
396
- protocol = route_defaults.protocol || Utils.current_protocol();
397
- port = route_defaults.port || (!route_defaults.host ? Utils.current_port() : void 0);
398
- port = port ? ":" + port : '';
399
- return protocol + "://" + subdomain + hostname + port;
400
- },
401
- has_location: function() {
402
- return (typeof window !== "undefined" && window !== null ? window.location : void 0) != null;
403
- },
404
- current_host: function() {
405
- if (this.has_location()) {
406
- return window.location.hostname;
407
- } else {
408
- return null;
409
- }
410
- },
411
- current_protocol: function() {
412
- if (this.has_location() && window.location.protocol !== '') {
413
- return window.location.protocol.replace(/:$/, '');
414
- } else {
415
- return 'http';
416
- }
417
- },
418
- current_port: function() {
419
- if (this.has_location() && window.location.port !== '') {
420
- return window.location.port;
421
- } else {
422
- return '';
423
- }
424
- },
425
- _classToTypeCache: null,
426
- _classToType: function() {
427
- var j, len, name, ref;
428
- if (this._classToTypeCache != null) {
429
- return this._classToTypeCache;
430
- }
431
- this._classToTypeCache = {};
432
- ref = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
433
- for (j = 0, len = ref.length; j < len; j++) {
434
- name = ref[j];
435
- this._classToTypeCache["[object " + name + "]"] = name.toLowerCase();
436
- }
437
- return this._classToTypeCache;
438
- },
439
- get_object_type: function(obj) {
440
- if (root.jQuery && (root.jQuery.type != null)) {
441
- return root.jQuery.type(obj);
442
- }
443
- if (obj == null) {
444
- return "" + obj;
445
- }
446
- if (typeof obj === "object" || typeof obj === "function") {
447
- return this._classToType()[Object.prototype.toString.call(obj)] || "object";
448
- } else {
449
- return typeof obj;
450
- }
451
- },
452
- indexOf: function(array, element) {
453
- if (Array.prototype.indexOf) {
454
- return array.indexOf(element);
455
- } else {
456
- return this.indexOfImplementation(array, element);
457
- }
458
- },
459
- indexOfImplementation: function(array, element) {
460
- var el, i, j, len, result;
461
- result = -1;
462
- for (i = j = 0, len = array.length; j < len; i = ++j) {
463
- el = array[i];
464
- if (el === element) {
465
- result = i;
466
- }
467
- }
468
- return result;
469
- },
470
- namespace: function(root, namespace, routes) {
471
- var index, j, len, part, parts;
472
- parts = namespace ? namespace.split(".") : [];
473
- if (parts.length === 0) {
474
- return routes;
475
- }
476
- for (index = j = 0, len = parts.length; j < len; index = ++j) {
477
- part = parts[index];
478
- if (index < parts.length - 1) {
479
- root = (root[part] || (root[part] = {}));
480
- } else {
481
- return root[part] = routes;
482
- }
483
- }
484
- },
485
- configure: function(new_config) {
486
- return this.configuration = this.merge(this.configuration, new_config);
487
- },
488
- config: function() {
489
- return this.clone(this.configuration);
490
- },
491
- make: function() {
492
- var routes;
493
- routes = ROUTES;
494
- routes.configure = function(config) {
495
- return Utils.configure(config);
496
- };
497
- routes.config = function() {
498
- return Utils.config();
499
- };
500
- Object.defineProperty(routes, 'defaults', {
501
- get: function() {
502
- throw new Error(NAMESPACE + ".defaults is removed. Use " + NAMESPACE + ".configure() instead.");
483
+ const Utils = new UtilsClass();
484
+ // We want this helper name to be short
485
+ const __jsr = {
486
+ r(parts_table, route_spec, absolute) {
487
+ return Utils.route(parts_table, route_spec, absolute);
503
488
  },
504
- set: function(value) {}
505
- });
506
- routes.default_serializer = function(object, prefix) {
507
- return Utils.default_serializer(object, prefix);
508
- };
509
- return Utils.namespace(root, NAMESPACE, routes);
510
- }
511
- };
512
-
513
- result = Utils.make();
514
-
515
- if (typeof define === "function" && define.amd) {
516
- define([], function() {
517
- return result;
518
- });
519
- }
520
-
521
- return result;
522
-
523
- }).call(this);
489
+ };
490
+ const result = {
491
+ ...__jsr,
492
+ configure: (config) => {
493
+ return Utils.configure(config);
494
+ },
495
+ config: () => {
496
+ return Utils.config();
497
+ },
498
+ serialize: (object) => {
499
+ return Utils.serialize(object);
500
+ },
501
+ ...RubyVariables.ROUTES_OBJECT,
502
+ };
503
+ Utils.define_module(RubyVariables.MODULE_TYPE, result);
504
+ return result;
505
+ })(this);