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