From 4f662ec05a8c44c7ff42af6ce8c6a8daa91db997 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 17 Dec 2018 10:35:33 +0100 Subject: [PATCH] Added interpolator. --- src/Squidex/app/framework/internal.ts | 1 + .../app/framework/utils/interpolator.spec.ts | 79 +++++++++++++++++++ .../app/framework/utils/interpolator.ts | 43 ++++++++++ .../app/shared/state/contents.forms.spec.ts | 2 +- 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/Squidex/app/framework/utils/interpolator.spec.ts create mode 100644 src/Squidex/app/framework/utils/interpolator.ts diff --git a/src/Squidex/app/framework/internal.ts b/src/Squidex/app/framework/internal.ts index 917af7565..e738bbd3d 100644 --- a/src/Squidex/app/framework/internal.ts +++ b/src/Squidex/app/framework/internal.ts @@ -23,6 +23,7 @@ export * from './utils/date-helper'; export * from './utils/date-time'; export * from './utils/duration'; export * from './utils/error'; +export * from './utils/interpolator'; export * from './utils/immutable-array'; export * from './utils/lazy'; export * from './utils/math-helper'; diff --git a/src/Squidex/app/framework/utils/interpolator.spec.ts b/src/Squidex/app/framework/utils/interpolator.spec.ts new file mode 100644 index 000000000..58de0557c --- /dev/null +++ b/src/Squidex/app/framework/utils/interpolator.spec.ts @@ -0,0 +1,79 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { DateTime } from './date-time'; +import { interpolate } from './interpolator'; + +describe('interpolate', () => { + it('should keep string untouched if does not contain interpolation', () => { + const result = interpolate('hello world'); + + expect(result).toEqual('hello world'); + }); + + it('should interpolate with object value', () => { + const result = interpolate('hello ${string}', { string: 'world' }); + + expect(result).toEqual('hello world'); + }); + + it('should interpolate with array value', () => { + const result = interpolate('hello ${1}', ['my', 'world']); + + expect(result).toEqual('hello world'); + }); + + it('should interpolate with complex path', () => { + const result = interpolate('hello ${array.1}', { array: ['my', 'world'] }); + + expect(result).toEqual('hello world'); + }); + + it('should return undefined if not found in object', () => { + const result = interpolate('hello ${value}', { string: 'world' }); + + expect(result).toEqual('hello undefined'); + }); + + it('should return undefined if not found in array', () => { + const result = interpolate('hello ${4}', ['my', 'world']); + + expect(result).toEqual('hello undefined'); + }); + + it('should return undefined if not a valid index', () => { + const result = interpolate('hello ${index}', ['my', 'world']); + + expect(result).toEqual('hello undefined'); + }); + + it('should return undefined if it resolved to object', () => { + const result = interpolate('hello ${data}', { data: { } }); + + expect(result).toEqual('hello undefined'); + }); + + it('should return undefined if it resolved to array', () => { + const result = interpolate('hello ${data}', { data: [] }); + + expect(result).toEqual('hello undefined'); + }); + + it('should allow object shortcuts', () => { + const result = interpolate('hello ${data}', { data: { iv: 'world' } }, 'iv'); + + expect(result).toEqual('hello world'); + }); + + it('should resolve dateTime', () => { + const now = DateTime.now(); + + const result = interpolate('hello ${time}', { time: now }); + + expect(result).toEqual(`hello ${now.toISOString()}`); + }); +}); \ No newline at end of file diff --git a/src/Squidex/app/framework/utils/interpolator.ts b/src/Squidex/app/framework/utils/interpolator.ts new file mode 100644 index 000000000..262ac7641 --- /dev/null +++ b/src/Squidex/app/framework/utils/interpolator.ts @@ -0,0 +1,43 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { DateTime } from './date-time'; +import { Types } from './types'; + +const regex = /\${[^}]+}/; + +export function interpolate(pattern: string, value?: any, shortcut?: string, fallback = 'undefined'): string { + const result = pattern.replace(regex, (match: string) => { + let replaced = value; + + const path = match.substr(2, match.length - 3).split('.'); + + for (let segment of path) { + if (Types.isObject(replaced)) { + replaced = replaced[segment]; + } else if (Types.isArray(replaced)) { + replaced = replaced[Number.parseInt(segment, 10)]; + } else { + break; + } + } + + if (Types.isString(replaced)) { + return replaced; + } else if (Types.isNumber(replaced)) { + return replaced.toString(); + } else if (Types.is(replaced, DateTime)) { + return replaced.toISOString(); + } else if (Types.isObject(replaced) && shortcut) { + return replaced[shortcut] || fallback; + } + + return fallback; + }); + + return result; +} \ No newline at end of file diff --git a/src/Squidex/app/shared/state/contents.forms.spec.ts b/src/Squidex/app/shared/state/contents.forms.spec.ts index 2a72eab7d..818541480 100644 --- a/src/Squidex/app/shared/state/contents.forms.spec.ts +++ b/src/Squidex/app/shared/state/contents.forms.spec.ts @@ -371,7 +371,7 @@ describe('StringField', () => { }); function createSchema(properties: SchemaPropertiesDto, index = 1, fields: RootFieldDto[]) { - return new SchemaDetailsDto('id' + index, 'schema' + index, '', properties, false, true, null!, null!, null!, null!, null!, fields); + return new SchemaDetailsDto('id' + index, 'schema' + index, '', properties, false, true, null!, null!, null!, null!, null!, fields, {}); } function createField(properties: FieldPropertiesDto, index = 1, partitioning = 'languages') {