Skip to content

Commit 477481f

Browse files
Nogglingodinr
authored andcommitted
chore: remove unnecessary blank line in handleReplaceModeGuard function
1 parent ec2f839 commit 477481f

14 files changed

Lines changed: 91 additions & 29 deletions

CODEMAP.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ search to rediscover it.
1313

1414
| Path | Contains | Published? |
1515
| --- | --- | --- |
16-
| `packages/*` | Framework libraries (58 packages) | Yes, via Changesets |
16+
| `packages/*` | Framework libraries (59 packages) | Yes, via Changesets |
1717
| `cookbooks/*` | Runnable example apps and portals | Yes (versioned, but examples) |
1818
| `eds-content/`, `eds/` | EDS design-system content and token tooling | No |
1919
| `vue-press/` | Documentation site | Partly |
@@ -82,7 +82,13 @@ Format: `package name` → path → role.
8282
| `@equinor/fusion-framework-react-components-bookmark` | `packages/react/components/bookmark` | Bookmark UI components |
8383
| `@equinor/fusion-framework-react-components-people-provider` | `packages/react/components/people-resolver` | People resolver components |
8484

85-
### Utils (`packages/utils/*`)
85+
### Plugins (`packages/plugins/*`)i
86+
87+
| Package | Path | Role |
88+
| --- | --- | --- |
89+
| `@equinor/fusion-framework-plugin-context-navigation` | `packages/plugins/context-navigation` | Plugin for context-based navigation handling |
90+
91+
## Utils (`packages/utils/*`)
8692

8793
| Package | Path | Role |
8894
| --- | --- | --- |

packages/modules/navigation/src/__tests__/NavigationProvider.test.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ describe('NavigationProvider', () => {
9999
it('should handle pathological input efficiently (ReDoS protection)', () => {
100100
// Create a string with many consecutive slashes to test performance
101101
// This would cause ReDoS with certain regex patterns
102-
const manySlashes = '/apps' + '/'.repeat(10000) + 'my-app';
102+
const manySlashes = `/apps/${'/'.repeat(10000)}my-app`;
103103

104104
const startTime = Date.now();
105105
const provider = new NavigationProvider({
@@ -117,7 +117,7 @@ describe('NavigationProvider', () => {
117117
it('should handle pathological trailing slashes efficiently (ReDoS protection)', () => {
118118
// Create a string with many trailing slashes
119119
// The /\/+$/ regex pattern would cause ReDoS with this input
120-
const manyTrailingSlashes = '/apps/my-app' + '/'.repeat(10000);
120+
const manyTrailingSlashes = `/apps/my-app${'/'.repeat(10000)}`;
121121

122122
const startTime = Date.now();
123123
const provider = new NavigationProvider({
@@ -150,9 +150,13 @@ describe('NavigationProvider', () => {
150150
});
151151

152152
// All paths should be in scope
153+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
153154
expect((provider as any)._isWithinBasenameScope('/')).toBe(true);
155+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
154156
expect((provider as any)._isWithinBasenameScope('/apps')).toBe(true);
157+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
155158
expect((provider as any)._isWithinBasenameScope('/apps/my-app')).toBe(true);
159+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
156160
expect((provider as any)._isWithinBasenameScope('/apps/my-app/users')).toBe(true);
157161

158162
provider.dispose();
@@ -165,18 +169,25 @@ describe('NavigationProvider', () => {
165169
});
166170

167171
// Exact match should be in scope
172+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
168173
expect((provider as any)._isWithinBasenameScope('/apps/my-app')).toBe(true);
169174

170175
// Paths starting with basename/ should be in scope
176+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
171177
expect((provider as any)._isWithinBasenameScope('/apps/my-app/')).toBe(true);
178+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
172179
expect((provider as any)._isWithinBasenameScope('/apps/my-app/users')).toBe(true);
173180

174181
// Similar but different path should NOT be in scope (path boundary check)
182+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
175183
expect((provider as any)._isWithinBasenameScope('/apps/my-app-other')).toBe(false);
184+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
176185
expect((provider as any)._isWithinBasenameScope('/apps/my-app-other/users')).toBe(false);
177186

178187
// Completely different paths should NOT be in scope
188+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
179189
expect((provider as any)._isWithinBasenameScope('/other')).toBe(false);
190+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
180191
expect((provider as any)._isWithinBasenameScope('/')).toBe(false);
181192

182193
provider.dispose();
@@ -189,7 +200,9 @@ describe('NavigationProvider', () => {
189200
});
190201

191202
// Pathname with consecutive slashes should be normalized
203+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
192204
expect((provider as any)._isWithinBasenameScope('/apps//my-app')).toBe(true);
205+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
193206
expect((provider as any)._isWithinBasenameScope('/apps/my-app//users')).toBe(true);
194207

195208
provider.dispose();
@@ -205,11 +218,13 @@ describe('NavigationProvider', () => {
205218

206219
// Exact match should become '/'
207220
expect(
221+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
208222
(provider as any)._localizePath({ pathname: '/apps/my-app', search: '', hash: '' }),
209223
).toEqual({ pathname: '/', search: '', hash: '' });
210224

211225
// Path with basename prefix should have it stripped
212226
expect(
227+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
213228
(provider as any)._localizePath({
214229
pathname: '/apps/my-app/users',
215230
search: '?q=test',
@@ -227,6 +242,7 @@ describe('NavigationProvider', () => {
227242
});
228243

229244
// Path that starts similarly but isn't a real match should not be stripped
245+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
230246
const result = (provider as any)._localizePath({
231247
pathname: '/apps/my-app-other/users',
232248
search: '',
@@ -246,19 +262,22 @@ describe('NavigationProvider', () => {
246262
});
247263

248264
// With no basename, paths should be returned normalized
265+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
249266
expect((provider as any)._localizePath({ pathname: '/', search: '', hash: '' })).toEqual({
250267
pathname: '/',
251268
search: '',
252269
hash: '',
253270
});
254271

272+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
255273
expect((provider as any)._localizePath({ pathname: '/apps', search: '', hash: '' })).toEqual({
256274
pathname: '/apps',
257275
search: '',
258276
hash: '',
259277
});
260278

261279
expect(
280+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
262281
(provider as any)._localizePath({ pathname: '/apps/my-app', search: '', hash: '' }),
263282
).toEqual({ pathname: '/apps/my-app', search: '', hash: '' });
264283

@@ -273,6 +292,7 @@ describe('NavigationProvider', () => {
273292

274293
// Consecutive slashes should be collapsed
275294
expect(
295+
// biome-ignore lint/suspicious/noExplicitAny: Allow usage of 'any' in test files for mocking purposes
276296
(provider as any)._localizePath({ pathname: '/apps//my-app//users', search: '', hash: '' }),
277297
).toEqual({ pathname: '/users', search: '', hash: '' });
278298

packages/plugins/context-navigation/src/apply-navigation.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type {
1111
ContextNavigationSkippedDetail,
1212
} from './types';
1313
import type { ContextNavigationEventSource } from './create-context-navigation-plugin';
14-
import { normalizePath } from './helpers';
14+
import { normalizePathFromURL } from './helpers';
1515

1616
/**
1717
* Set of normalized paths that the plugin itself has navigated to.
@@ -118,7 +118,7 @@ export async function applyNavigation(
118118
// Step 2: Compare normalized paths to avoid redundant navigations.
119119
// This prevents a replace() call when the URL is already correct, which
120120
// would otherwise create a spurious history entry in some browsers.
121-
if (normalizePath(targetURL) === normalizePath(currentURL)) {
121+
if (normalizePathFromURL(targetURL) === normalizePathFromURL(currentURL)) {
122122
event.dispatchEvent('onContextNavigationSkipped', {
123123
detail: { appKey, reason: 'url-matches' } as ContextNavigationSkippedDetail,
124124
source: eventSource,
@@ -156,7 +156,7 @@ export async function applyNavigation(
156156

157157
// Step 4: Record the token BEFORE navigating so the guard sees it
158158
// on the resulting state$ emission and skips re-processing.
159-
ownNavTokens.add(normalizePath(targetURL));
159+
ownNavTokens.add(normalizePathFromURL(targetURL));
160160
navigation.navigate(targetURL, navOptionsOverride ?? config.navigationOptions);
161161

162162
// Post-navigation bookkeeping: notify listeners and invoke callback.

packages/plugins/context-navigation/src/create-context-navigation-plugin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ export function createContextNavigationPlugin(args: ContextNavigationPluginArgs)
108108
startWith(null),
109109
pairwise(),
110110
map(([prev, entry]) => ({
111-
entry: entry!,
112-
isAppSwitch: prev != null && prev.appKey !== entry!.appKey,
111+
entry: entry as typeof entry & {},
112+
isAppSwitch: prev != null && prev.appKey !== (entry as typeof entry & {}).appKey,
113113
})),
114114
)
115115
.subscribe(({ entry, isAppSwitch }) => {

packages/plugins/context-navigation/src/guard-handlers/consume-own-nav-token.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { normalizePath } from '../helpers';
1+
import { normalizePathFromURL } from '../helpers';
22
import type { OwnNavigationTokens } from '../apply-navigation';
33

44
/**
@@ -20,8 +20,8 @@ import type { OwnNavigationTokens } from '../apply-navigation';
2020
* @returns `true` if this navigation was plugin-initiated (caller should bail).
2121
*/
2222
export function consumeOwnNavToken(currentURL: URL, ownNavTokens: OwnNavigationTokens): boolean {
23-
const normalized = normalizePath(currentURL);
24-
23+
const normalized = normalizePathFromURL(currentURL);
24+
2525
// Token present — this navigation was plugin-initiated; consume it and signal the caller to bail.
2626
if (ownNavTokens.has(normalized)) {
2727
ownNavTokens.delete(normalized);

packages/plugins/context-navigation/src/guard-handlers/handle-push-mode-guard.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function handlePushModeGuard(
4040
if (!activeContext) {
4141
return;
4242
}
43-
43+
4444
const adapter = resolveAdapter(
4545
{ appKey, appContext: appModules.context, routingStrategy, currentURL },
4646
deps.config.adapters,

packages/plugins/context-navigation/src/guard-handlers/handle-replace-mode-guard.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function handleReplaceModeGuard(
2929

3030
// Resolve the active context and adapter for re-encoding.
3131
const activeContext = appModules.context.currentContext;
32-
32+
3333
// No active context to re-encode — nothing to correct.
3434
if (!activeContext) {
3535
return;

packages/plugins/context-navigation/src/helpers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { normalizePathFromURL } from './normalize-path-from-url';
12
export { normalizePath } from './normalize-path';
23
export { getCurrentURL } from './get-current-url';
34
export { resolveAdapter } from './resolve-adapter';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { normalizePath } from './normalize-path';
2+
/**
3+
* Normalize a URL to its path + search representation for comparison.
4+
*
5+
* Strips trailing slashes from the pathname so that `/apps/foo/` and
6+
* `/apps/foo` compare as equal.
7+
*
8+
* @param url - The URL to normalize.
9+
* @returns A string of the form `pathname + search` with trailing slash removed.
10+
*/
11+
export function normalizePathFromURL(url: URL): string {
12+
return `${normalizePath(url.pathname)}${url.search}`;
13+
}
Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
/**
2-
* Normalize a URL to its path + search representation for comparison.
2+
* Normalizes a path string to ensure it is in a consistent format for comparison and processing.
33
*
4-
* Strips trailing slashes from the pathname so that `/apps/foo/` and
5-
* `/apps/foo` compare as equal.
4+
* This function performs the following normalizations:
5+
* - Ensures the path starts with a leading slash.
6+
* - Removes any trailing slashes, except for the root path ("/").
7+
* - Converts empty paths to the root path ("/").
8+
* - Fixing multiple consecutive slashes to a single slash.
69
*
7-
* @param url - The URL to normalize.
8-
* @returns A string of the form `pathname + search` with trailing slash removed.
10+
* @param path - The path string to normalize.
11+
* @returns The normalized path string.
912
*/
10-
export function normalizePath(url: URL): string {
11-
return `${url.pathname.replace(/\/$/, '') || '/'}${url.search}`;
13+
export function normalizePath(path: string): string {
14+
// Replace multiple consecutive slashes with a single slash
15+
path = path.replace(/\/+/g, '/');
16+
17+
// Ensure the path starts with a leading slash
18+
if (!path.startsWith('/')) {
19+
path = `/${path}`;
20+
}
21+
22+
// Remove trailing slashes, except for the root path
23+
if (path.length > 1 && path.endsWith('/')) {
24+
path = path.slice(0, -1);
25+
}
26+
27+
// Convert empty paths to the root path
28+
if (path === '') {
29+
return '/';
30+
}
31+
32+
return path;
1233
}

0 commit comments

Comments
 (0)