Skip to content

Commit ae81df9

Browse files
committed
Support script_name option
1 parent 58b863e commit ae81df9

File tree

6 files changed

+77
-7
lines changed

6 files changed

+77
-7
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
## [2.3.4]
44

55
* Migrate to yarn 4
6+
* Add support for `script_name` [Rails helper option](https://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html#method-i-url_for).
7+
8+
``` javascript
9+
Routes.post_path(1, { script_name: "/myapp" })
10+
// => /myapp/post/1
11+
12+
Routes.configure({
13+
default_url_options: { script_name: "/myapp" }
14+
})
15+
16+
Routes.post_path(1) // => /myapp/post/1
17+
```
618

719
## [2.3.3]
820

lib/routes.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ declare type KeywordUrlOptions = Optional<{
5050
port: string | number;
5151
anchor: string;
5252
trailing_slash: boolean;
53+
script_name: string;
5354
params: RouteParameters;
5455
}>;
5556
declare type RouteOptions = KeywordUrlOptions & RouteParameters;

lib/routes.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ RubyVariables.WRAPPER(
110110
"host",
111111
"port",
112112
"protocol",
113+
"script_name",
113114
];
114115
class UtilsClass {
115116
constructor() {
@@ -275,21 +276,29 @@ RubyVariables.WRAPPER(
275276
}
276277
build_route(parts, required_params, default_options, route, absolute, args) {
277278
const { keyword_parameters, query_parameters } = this.partition_parameters(parts, required_params, default_options, args);
279+
let { trailing_slash, anchor, script_name } = keyword_parameters;
278280
const missing_params = required_params.filter((param) => !hasProp(query_parameters, param) ||
279281
this.is_nullable(query_parameters[param]));
280282
if (missing_params.length) {
281283
throw new ParametersMissing(...missing_params);
282284
}
283285
let result = this.get_prefix() + this.visit(route, query_parameters);
284-
if (keyword_parameters.trailing_slash) {
286+
if (trailing_slash) {
285287
result = result.replace(/(.*?)[/]?$/, "$1/");
286288
}
287289
const url_params = this.serialize(query_parameters);
288290
if (url_params.length) {
289291
result += "?" + url_params;
290292
}
291-
if (keyword_parameters.anchor) {
292-
result += "#" + keyword_parameters.anchor;
293+
if (anchor) {
294+
result += "#" + anchor;
295+
}
296+
if (script_name) {
297+
const last_index = script_name.length - 1;
298+
if (script_name[last_index] == "/" && result[0] == "/") {
299+
script_name = script_name.slice(0, last_index);
300+
}
301+
result = script_name + result;
293302
}
294303
if (absolute) {
295304
result = this.route_url(keyword_parameters) + result;

lib/routes.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ type KeywordUrlOptions = Optional<{
6666
port: string | number;
6767
anchor: string;
6868
trailing_slash: boolean;
69+
script_name: string;
6970
params: RouteParameters;
7071
}>;
7172

@@ -230,7 +231,9 @@ RubyVariables.WRAPPER(
230231
"host",
231232
"port",
232233
"protocol",
234+
"script_name",
233235
] as const;
236+
234237
type ReservedOption = (typeof ReservedOptions)[any];
235238

236239
class UtilsClass {
@@ -433,6 +436,8 @@ RubyVariables.WRAPPER(
433436
default_options,
434437
args
435438
);
439+
440+
let { trailing_slash, anchor, script_name } = keyword_parameters;
436441
const missing_params = required_params.filter(
437442
(param) =>
438443
!hasProp(query_parameters, param) ||
@@ -442,15 +447,22 @@ RubyVariables.WRAPPER(
442447
throw new ParametersMissing(...missing_params);
443448
}
444449
let result = this.get_prefix() + this.visit(route, query_parameters);
445-
if (keyword_parameters.trailing_slash) {
450+
if (trailing_slash) {
446451
result = result.replace(/(.*?)[/]?$/, "$1/");
447452
}
448453
const url_params = this.serialize(query_parameters);
449454
if (url_params.length) {
450455
result += "?" + url_params;
451456
}
452-
if (keyword_parameters.anchor) {
453-
result += "#" + keyword_parameters.anchor;
457+
if (anchor) {
458+
result += "#" + anchor;
459+
}
460+
if (script_name) {
461+
const last_index = script_name.length - 1;
462+
if (script_name[last_index] == "/" && result[0] == "/") {
463+
script_name = script_name.slice(0, last_index);
464+
}
465+
result = script_name + result;
454466
}
455467
if (absolute) {
456468
result = this.route_url(keyword_parameters) + result;

spec/js_routes/options_spec.rb

+11-1
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,21 @@
225225

226226
context "when passing options that do not have defaults" do
227227
it "should use this options to fill the optional parameters" do
228-
expectjs("Routes.thing_path(1, { format: 'json' })").to eq test_routes.thing_path(1, { optional_id: "12", format: "json" } ) # test_routes.thing_path needs optional_id here to generate the correct route. Not sure why.
228+
# test_routes.thing_path needs optional_id here to generate the correct route. Not sure why.
229+
expectjs("Routes.thing_path(1, { format: 'json' })").to eq test_routes.thing_path(1, { optional_id: "12", format: "json" } )
229230
end
230231
end
231232
end
232233

234+
describe "script_name option" do
235+
let(:_options) { { default_url_options: { script_name: "/myapp" } }}
236+
it "is supported" do
237+
expectjs("Routes.inboxes_path()").to eq(
238+
test_routes.inboxes_path(script_name: '/myapp')
239+
)
240+
end
241+
end
242+
233243
context "when overwritten on JS level" do
234244
let(:_options) { { :default_url_options => { :format => "json" } } }
235245
it "uses JS defined value" do

spec/js_routes/rails_routes_compatibility_spec.rb

+26
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,30 @@
514514
end
515515
end
516516
end
517+
518+
describe "script_name option" do
519+
it "preceeds the path" do
520+
expectjs(
521+
"Routes.inboxes_path({ script_name: '/myapp' })"
522+
).to eq(
523+
test_routes.inboxes_path(script_name: '/myapp')
524+
)
525+
end
526+
527+
it "strips double slash" do
528+
expectjs(
529+
"Routes.inboxes_path({ script_name: '/myapp/' })"
530+
).to eq(
531+
test_routes.inboxes_path(script_name: '/myapp/')
532+
)
533+
end
534+
535+
it "preserves no preceding slash" do
536+
expectjs(
537+
"Routes.inboxes_path({ script_name: 'myapp' })"
538+
).to eq(
539+
test_routes.inboxes_path(script_name: 'myapp')
540+
)
541+
end
542+
end
517543
end

0 commit comments

Comments
 (0)