@openmrs/esm-navigation 10.0.1-pre.5501 → 10.0.1-pre.5505
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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/navigation/interpolate-string.d.ts.map +1 -1
- package/dist/navigation/interpolate-string.js +5 -2
- package/dist/navigation/navigate.d.ts.map +1 -1
- package/dist/navigation/navigate.js +7 -2
- package/package.json +5 -3
- package/src/navigation/interpolate-string.test.ts +4 -0
- package/src/navigation/interpolate-string.ts +6 -2
- package/src/navigation/navigate.test.ts +14 -0
- package/src/navigation/navigate.ts +7 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interpolate-string.d.ts","sourceRoot":"","sources":["../../src/navigation/interpolate-string.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAMnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"interpolate-string.d.ts","sourceRoot":"","sources":["../../src/navigation/interpolate-string.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAMnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,MAAM,CAWrG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,MAAM,CAG7F"}
|
|
@@ -32,11 +32,14 @@
|
|
|
32
32
|
* @returns The interpolated string with all template parameters replaced.
|
|
33
33
|
*/ export function interpolateUrl(template, additionalParams) {
|
|
34
34
|
const openmrsSpaBase = trimTrailingSlash(window.getOpenmrsSpaBase());
|
|
35
|
-
|
|
35
|
+
const result = interpolateString(template, {
|
|
36
36
|
openmrsBase: window.openmrsBase,
|
|
37
37
|
openmrsSpaBase: openmrsSpaBase,
|
|
38
38
|
...additionalParams
|
|
39
|
-
})
|
|
39
|
+
});
|
|
40
|
+
// remove a additional / at the beginning if added by interpolation
|
|
41
|
+
// e.g. /${openmrsSpaBase} -> //openmrs/spa
|
|
42
|
+
return template.startsWith('//') ? result : result.replace(/^\/\//, '/');
|
|
40
43
|
}
|
|
41
44
|
/**
|
|
42
45
|
* Interpolates values of `params` into the `template` string.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../src/navigation/navigate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../src/navigation/navigate.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,cAAc,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,eAAe,GAAG,IAAI,CActE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** @module @category Navigation */ import { navigateToUrl } from "single-spa";
|
|
2
|
+
import { getCoreTranslation } from "@openmrs/esm-translations";
|
|
2
3
|
import { interpolateUrl } from "./interpolate-string.js";
|
|
3
4
|
function trimTrailingSlash(str) {
|
|
4
5
|
return str.replace(/\/$/, '');
|
|
@@ -37,8 +38,12 @@ function trimTrailingSlash(str) {
|
|
|
37
38
|
*/ export function navigate({ to, templateParams }) {
|
|
38
39
|
const openmrsSpaBase = trimTrailingSlash(window.getOpenmrsSpaBase());
|
|
39
40
|
const target = interpolateUrl(to, templateParams).replace(window.location.origin, '');
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
41
|
+
const targetURL = new URL(target, window.location.origin);
|
|
42
|
+
if (targetURL.protocol != 'http:' && targetURL.protocol != 'https:') {
|
|
43
|
+
console.error(`Received request to navigate to non-http URL: ${targetURL.toString()}`);
|
|
44
|
+
throw new Error(getCoreTranslation('navigateNonHttp'));
|
|
45
|
+
}
|
|
46
|
+
if (target.startsWith(openmrsSpaBase)) {
|
|
42
47
|
navigateToUrl(target);
|
|
43
48
|
} else {
|
|
44
49
|
window.location.assign(target);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-navigation",
|
|
3
|
-
"version": "10.0.1-pre.
|
|
3
|
+
"version": "10.0.1-pre.5505",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "OpenMRS library providing tools for breadcrumbs, navigation, and history.",
|
|
6
6
|
"type": "module",
|
|
@@ -53,10 +53,12 @@
|
|
|
53
53
|
"path-to-regexp": "^8.3.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@openmrs/esm-state": "^10.0.1-pre.
|
|
56
|
+
"@openmrs/esm-state": "^10.0.1-pre.5505",
|
|
57
|
+
"@openmrs/esm-translations": "^10.0.1-pre.5505"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
|
-
"@openmrs/esm-state": "10.0.1-pre.
|
|
60
|
+
"@openmrs/esm-state": "10.0.1-pre.5505",
|
|
61
|
+
"@openmrs/esm-translations": "10.0.1-pre.5505",
|
|
60
62
|
"@swc/cli": "0.8.1",
|
|
61
63
|
"@swc/core": "1.15.21",
|
|
62
64
|
"@vitest/coverage-v8": "^4.1.2",
|
|
@@ -18,6 +18,10 @@ describe('interpolateUrl', () => {
|
|
|
18
18
|
const result = interpolateUrl('test ok');
|
|
19
19
|
expect(result).toBe('test ok');
|
|
20
20
|
});
|
|
21
|
+
|
|
22
|
+
it('preserves protocol-relative URLs', () => {
|
|
23
|
+
expect(interpolateUrl('//evil.example/${openmrsSpaBase}')).toBe('//evil.example//openmrs/spa');
|
|
24
|
+
});
|
|
21
25
|
});
|
|
22
26
|
|
|
23
27
|
describe('interpolateString', () => {
|
|
@@ -36,11 +36,15 @@ function trimTrailingSlash(str: string) {
|
|
|
36
36
|
*/
|
|
37
37
|
export function interpolateUrl(template: string, additionalParams?: { [key: string]: string }): string {
|
|
38
38
|
const openmrsSpaBase = trimTrailingSlash(window.getOpenmrsSpaBase());
|
|
39
|
-
|
|
39
|
+
const result = interpolateString(template, {
|
|
40
40
|
openmrsBase: window.openmrsBase,
|
|
41
41
|
openmrsSpaBase: openmrsSpaBase,
|
|
42
42
|
...additionalParams,
|
|
43
|
-
})
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// remove a additional / at the beginning if added by interpolation
|
|
46
|
+
// e.g. /${openmrsSpaBase} -> //openmrs/spa
|
|
47
|
+
return template.startsWith('//') ? result : result.replace(/^\/\//, '/');
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
/**
|
|
@@ -66,4 +66,18 @@ describe('navigate', () => {
|
|
|
66
66
|
expect(navigateToUrl).toHaveBeenCalledWith('/openmrs/spa/qux/page');
|
|
67
67
|
expect(window.location.assign).not.toHaveBeenCalled();
|
|
68
68
|
});
|
|
69
|
+
|
|
70
|
+
it('rejects non-http URLs', () => {
|
|
71
|
+
expect(() => navigate({ to: 'ftp://${openmrsSpaBase}/qux/page' })).toThrow(Error);
|
|
72
|
+
expect(() => navigate({ to: 'javascript:alert(1)' })).toThrow(Error);
|
|
73
|
+
expect(navigateToUrl).not.toHaveBeenCalled();
|
|
74
|
+
expect(window.location.assign).not.toHaveBeenCalled();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('rejects non-http URLs when the SPA base is the root', () => {
|
|
78
|
+
const getOpenmrsSpaBase = vi.spyOn(window, 'getOpenmrsSpaBase').mockReturnValue('/');
|
|
79
|
+
expect(() => navigate({ to: 'javascript:alert(1)' })).toThrow(Error);
|
|
80
|
+
expect(navigateToUrl).not.toHaveBeenCalled();
|
|
81
|
+
getOpenmrsSpaBase.mockRestore();
|
|
82
|
+
});
|
|
69
83
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** @module @category Navigation */
|
|
2
2
|
import { navigateToUrl } from 'single-spa';
|
|
3
|
+
import { getCoreTranslation } from '@openmrs/esm-translations';
|
|
3
4
|
import { interpolateUrl } from './interpolate-string';
|
|
4
5
|
import type {} from '@openmrs/esm-globals';
|
|
5
6
|
|
|
@@ -49,9 +50,13 @@ export interface NavigateOptions {
|
|
|
49
50
|
export function navigate({ to, templateParams }: NavigateOptions): void {
|
|
50
51
|
const openmrsSpaBase = trimTrailingSlash(window.getOpenmrsSpaBase());
|
|
51
52
|
const target = interpolateUrl(to, templateParams).replace(window.location.origin, '');
|
|
52
|
-
const
|
|
53
|
+
const targetURL = new URL(target, window.location.origin);
|
|
54
|
+
if (targetURL.protocol != 'http:' && targetURL.protocol != 'https:') {
|
|
55
|
+
console.error(`Received request to navigate to non-http URL: ${targetURL.toString()}`);
|
|
56
|
+
throw new Error(getCoreTranslation('navigateNonHttp'));
|
|
57
|
+
}
|
|
53
58
|
|
|
54
|
-
if (
|
|
59
|
+
if (target.startsWith(openmrsSpaBase)) {
|
|
55
60
|
navigateToUrl(target);
|
|
56
61
|
} else {
|
|
57
62
|
window.location.assign(target);
|