url-pattern-to-string function

This commit is contained in:
Niels Lyngsø
2024-04-23 13:38:11 +02:00
parent 0326b87cfd
commit 5c79268b6a
6 changed files with 30 additions and 30 deletions

View File

@@ -1,41 +1,41 @@
import { expect } from '@open-wc/testing';
import { createRoutePathBuilder } from './generate-route-path-builder.function.js';
import { umbCreateRoutePathBuilder } from './generate-route-path-builder.function.js';
describe('createRoutePathBuilder', () => {
it('should return a function that builds a route path without parameters', () => {
const buildPath = createRoutePathBuilder('test/path');
const buildPath = umbCreateRoutePathBuilder('test/path');
expect(buildPath(null)).to.eq('/test/path/');
});
it('should return a function that builds a route path with parameters', () => {
const buildPath = createRoutePathBuilder(':param0/test/:param1/path/:param2');
const buildPath = umbCreateRoutePathBuilder(':param0/test/:param1/path/:param2');
expect(buildPath({ param0: 'value0', param1: 'value1', param2: 'value2' })).to.eq(
'/value0/test/value1/path/value2/',
);
});
it('should convert number parameters to strings', () => {
const buildPath = createRoutePathBuilder('test/:param1/path/:param2');
const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2');
expect(buildPath({ param1: 123, param2: 456 })).to.eq('/test/123/path/456/');
});
it('should not consider route segments that resembles parameters as parameters', () => {
const buildPath = createRoutePathBuilder('test/uc:store/path');
const buildPath = umbCreateRoutePathBuilder('test/uc:store/path');
expect(buildPath({ someOtherParam: 'test' })).to.eq('/test/uc:store/path/');
});
it('should support multiple parameters with the same name', () => {
const buildPath = createRoutePathBuilder('test/:param1/path/:param1');
const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param1');
expect(buildPath({ param1: 'value1' })).to.eq('/test/value1/path/value1/');
});
it('should not consider parameters that are not in the params object', () => {
const buildPath = createRoutePathBuilder('test/:param1/path/:param2');
const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2');
expect(buildPath({ param1: 'value1' })).to.eq('/test/value1/path/:param2/');
});
it('should support complex objects as parameters with a custom toString method', () => {
const buildPath = createRoutePathBuilder('test/:param1/path/:param2');
const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2');
const obj = {
toString() {
return 'value1';

View File

@@ -1,21 +1,8 @@
/* eslint-disable */
import { type UrlParametersRecord, umbUrlPatternToString } from '../utils/path/url-pattern-to-string.function.js';
import { stripSlash } from '@umbraco-cms/backoffice/external/router-slot'; // This must only include the util to avoid side effects of registering the route element.
const PARAM_IDENTIFIER = /:([^\/]+)/g;
export function createRoutePathBuilder(path: string) {
return (params: { [key: string]: string | number | { toString: () => string } } | null) => {
return (
'/' +
stripSlash(
params
? path.replace(PARAM_IDENTIFIER, (_substring: string, ...args: string[]) => {
// Replace the parameter with the value from the params object or the parameter name if it doesn't exist (args[0] is the parameter name without the colon)
return typeof params[args[0]] !== 'undefined' ? params[args[0]].toString() : `:${args[0]}`;
})
: path,
) +
'/'
);
export function umbCreateRoutePathBuilder(path: string) {
return (params: UrlParametersRecord | null) => {
return '/' + stripSlash(umbUrlPatternToString(path, params)) + '/';
};
}

View File

@@ -1,5 +1,5 @@
import type { UmbRoute } from './route.interface.js';
import { createRoutePathBuilder } from './generate-route-path-builder.function.js';
import { umbCreateRoutePathBuilder } from './generate-route-path-builder.function.js';
import type { IRoutingInfo, IRouterSlot } from '@umbraco-cms/backoffice/external/router-slot';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
@@ -147,7 +147,7 @@ export class UmbRouteContext extends UmbContextBase<UmbRouteContext> {
: this.#routerActiveLocalPath + '/'
: '';
const localPath = routeBasePath + routeActiveLocalPath + modalRegistration.generateModalPath();
const urlBuilder = createRoutePathBuilder(localPath);
const urlBuilder = umbCreateRoutePathBuilder(localPath);
modalRegistration._internal_setRouteBuilder(urlBuilder);
};

View File

@@ -9,6 +9,7 @@ export * from './path/path-decode.function.js';
export * from './path/path-encode.function.js';
export * from './path/path-folder-name.function.js';
export * from './path/umbraco-path.function.js';
export * from './path/url-pattern-to-string.function.js';
export * from './selection-manager/selection.manager.js';
export * from './string/from-camel-case.function.js';
export * from './string/generate-umbraco-alias.function.js';

View File

@@ -0,0 +1,12 @@
export type UrlParametersRecord = Record<string, string | number | { toString: () => string }>;
const PARAM_IDENTIFIER = /:([^/]+)/g;
export function umbUrlPatternToString(pattern: string, params: UrlParametersRecord | null): string {
return params
? pattern.replace(PARAM_IDENTIFIER, (_substring: string, ...args: string[]) => {
// Replace the parameter with the value from the params object or the parameter name if it doesn't exist (args[0] is the parameter name without the colon)
return typeof params[args[0]] !== 'undefined' ? params[args[0]].toString() : `:${args[0]}`;
})
: pattern;
}

View File

@@ -1,8 +1,8 @@
import type { UmbSubmittableWorkspaceContextBase } from '../contexts/index.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import { createRoutePathBuilder, type UmbRouterSlotElement } from '@umbraco-cms/backoffice/router';
import { ensurePathEndsWithSlash } from '@umbraco-cms/backoffice/utils';
import type { UmbRouterSlotElement } from '@umbraco-cms/backoffice/router';
import { ensurePathEndsWithSlash, umbUrlPatternToString } from '@umbraco-cms/backoffice/utils';
/**
* Observe the workspace context to see if the entity is new or not.
@@ -28,7 +28,7 @@ export class UmbWorkspaceIsNewRedirectController extends UmbControllerBase {
if (router && unique) {
const routerPath = router.absoluteRouterPath;
if (routerPath) {
const newPath: string = createRoutePathBuilder(ensurePathEndsWithSlash(routerPath) + 'edit/:id')({
const newPath: string = umbUrlPatternToString(ensurePathEndsWithSlash(routerPath) + 'edit/:id', {
id: unique,
});
this.destroy();