feat(automation): support URL-encoded template values

This commit is contained in:
Carlos Valente
2026-09-11 19:56:31 +02:00
parent 1175b3c641
commit 123692827c
2 changed files with 14 additions and 3 deletions
@@ -44,6 +44,14 @@ describe('parseTemplateNested()', () => {
const result = parseTemplateNested(testString, mockState); const result = parseTemplateNested(testString, mockState);
expect(result).toStrictEqual(expected); expect(result).toStrictEqual(expected);
}); });
it('URL-encodes an explicitly marked variable', () => {
const result = parseTemplateNested('http://example.com/?title={{url:event.title}}', {
event: { title: 'Keynote & Roadmap #1' },
});
expect(result).toBe('http://example.com/?title=Keynote%20%26%20Roadmap%20%231');
});
}); });
describe('parseNestedTemplate() -> resolveAliasData()', () => { describe('parseNestedTemplate() -> resolveAliasData()', () => {
@@ -72,6 +72,7 @@ const placeholderRegex = /{{(.*?)}}/g;
/** /**
* Parses a templated string to values in a nested object * Parses a templated string to values in a nested object
* Prefix a variable with `url:` when its value must be safe inside a URL component.
*/ */
export function parseTemplateNested(template: string, state: object, humanReadable = quickAliases): string { export function parseTemplateNested(template: string, state: object, humanReadable = quickAliases): string {
let parsedTemplate = template; let parsedTemplate = template;
@@ -79,7 +80,9 @@ export function parseTemplateNested(template: string, state: object, humanReadab
for (const match of matches) { for (const match of matches) {
const variableName = match[1]; const variableName = match[1];
const variableParts = variableName.split('.'); const shouldEncodeForUrl = variableName.startsWith('url:');
const propertyName = shouldEncodeForUrl ? variableName.slice(4) : variableName;
const variableParts = propertyName.split('.');
let value: string | undefined = undefined; let value: string | undefined = undefined;
if (variableParts[0] === 'human') { if (variableParts[0] === 'human') {
@@ -93,10 +96,10 @@ export function parseTemplateNested(template: string, state: object, humanReadab
} }
} else { } else {
// we cast to string since this will be used in a string context // we cast to string since this will be used in a string context
value = getPropertyFromPath(variableName, state) as string; value = getPropertyFromPath(propertyName, state) as string;
} }
if (value !== undefined) { if (value !== undefined) {
parsedTemplate = parsedTemplate.replace(match[0], value); parsedTemplate = parsedTemplate.replace(match[0], shouldEncodeForUrl ? encodeURIComponent(value) : value);
} }
} }