Skip to content

Commit 3f02bb8

Browse files
committed
fix: resolve tags within tag argument strings
1 parent a281c88 commit 3f02bb8

6 files changed

Lines changed: 56 additions & 18 deletions

File tree

packages/insomnia/src/common/templating/liquid-extension-worker.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Tag } from 'liquidjs';
55
import type { Plugin } from '~/common/plugins/types';
66

77
import packageJson from '../../../package.json';
8+
import { resolveArg } from './resolve-arg';
89
import { tokenizeArgs } from './tokenize-args';
910
import type {
1011
BaseRenderContext,
@@ -50,13 +51,6 @@ export const fetchFromTemplateWorkerDatabase = async (path: PluginToMainAPIPaths
5051
return result;
5152
};
5253

53-
function resolveArg(arg: ReturnType<typeof tokenizeArgs>[number], scope: Record<string, any>): any {
54-
if (arg.type === 'variable') {
55-
return scope[arg.value as string];
56-
}
57-
return arg.value;
58-
}
59-
6054
export function createLiquidTagWorker(
6155
ext: PluginTemplateTag,
6256
plugin: Plugin,
@@ -77,7 +71,7 @@ export function createLiquidTagWorker(
7771
const renderPurpose = renderContext.getPurpose?.();
7872

7973
const parsedArgs = tokenizeArgs(this.rawArgs);
80-
const args = parsedArgs.map(a => resolveArg(a, scope)).map(decodeEncodingWorker);
74+
const args = (await Promise.all(parsedArgs.map(a => resolveArg(a, ctx, this.liquid)))).map(decodeEncodingWorker);
8175

8276
const platform = ({ MacIntel: 'darwin', Win32: 'win32' }[globalThis.navigator?.platform ?? ''] ||
8377
'linux') as NodeJS.Platform;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { Context, Liquid } from 'liquidjs';
2+
3+
import type { NunjucksParsedTagArg } from './types';
4+
5+
export async function resolveArg(arg: NunjucksParsedTagArg, ctx: Context, liquid: Liquid): Promise<any> {
6+
if (arg.type === 'variable' || arg.type === 'expression') {
7+
return liquid.evalValue(arg.value as string, ctx);
8+
}
9+
return arg.value;
10+
}

packages/insomnia/src/templating/__tests__/liquid-compat.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,28 @@ import { describe, expect, it } from 'vitest';
44

55
import { render } from '../index';
66

7+
describe('template tag arguments', () => {
8+
const md5OfVaporeon = 'ec38601e9ebd2fc22c7c476e14c7890d';
9+
10+
it('evaluates a _.variable argument to its value', async () => {
11+
expect(await render("{% hash 'md5', 'hex', _.pokemon %}", { context: { pokemon: 'vaporeon' } })).toBe(md5OfVaporeon);
12+
});
13+
14+
it('evaluates a bare variable argument to its value', async () => {
15+
expect(await render("{% hash 'md5', 'hex', pokemon %}", { context: { pokemon: 'vaporeon' } })).toBe(md5OfVaporeon);
16+
});
17+
18+
it('evaluates a bracket-notation argument to its value', async () => {
19+
expect(await render("{% hash 'md5', 'hex', _['water-type'] %}", { context: { 'water-type': 'vaporeon' } })).toBe(
20+
md5OfVaporeon,
21+
);
22+
});
23+
24+
it('hashes a quoted literal argument verbatim', async () => {
25+
expect(await render("{% hash 'md5', 'hex', 'vaporeon' %}", { context: { pokemon: 'flareon' } })).toBe(md5OfVaporeon);
26+
});
27+
});
28+
729
describe('variable interpolation', () => {
830
// Basic {{ var }} substitution from a flat context object
931
it('renders root-level variables', async () => {

packages/insomnia/src/templating/liquid-extension.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Tag } from 'liquidjs';
1010

1111
import { jarFromCookies } from '~/common/cookies';
1212
import type { Plugin } from '~/common/plugins/types';
13+
import { resolveArg } from '~/common/templating/resolve-arg';
1314
import type { BaseRenderContext, PluginTemplateTag, PluginTemplateTagContext } from '~/common/templating/types';
1415
import { decodeEncoding, tokenizeArgs } from '~/common/templating/utils';
1516

@@ -18,13 +19,6 @@ import * as pluginApp from '../plugins/context/app';
1819
import * as pluginNetwork from '../plugins/context/network';
1920
import * as pluginStore from '../plugins/context/store';
2021

21-
function resolveArg(arg: ReturnType<typeof tokenizeArgs>[number], scope: Record<string, any>): any {
22-
if (arg.type === 'variable') {
23-
return scope[arg.value as string];
24-
}
25-
return arg.value;
26-
}
27-
2822
export function createLiquidTag(
2923
ext: PluginTemplateTag,
3024
plugin: Plugin,
@@ -45,7 +39,7 @@ export function createLiquidTag(
4539
const renderPurpose = renderContext.getPurpose?.();
4640

4741
const parsedArgs = tokenizeArgs(this.rawArgs);
48-
const args = parsedArgs.map(a => resolveArg(a, scope)).map(decodeEncoding);
42+
const args = (await Promise.all(parsedArgs.map(a => resolveArg(a, ctx, this.liquid)))).map(decodeEncoding);
4943

5044
const helperContext: PluginTemplateTagContext = {
5145
...pluginApp.init(),

packages/insomnia/src/ui/components/templating/tag-editor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ export const TagEditor: FC<Props> = props => {
512512
<DropdownSection aria-label="Input Type Section" title="Input Type">
513513
<DropdownItem aria-label="Static Value">
514514
<ItemContent
515-
icon={isVariable ? 'check' : ''}
515+
icon={isVariable ? '' : 'check'}
516516
label="Static Value"
517517
onClick={() => {
518518
const { activeTagData, activeTagDefinition, variables } = state;
@@ -532,7 +532,7 @@ export const TagEditor: FC<Props> = props => {
532532
</DropdownItem>
533533
<DropdownItem aria-label="Environment Variable">
534534
<ItemContent
535-
icon={isVariable ? '' : 'check'}
535+
icon={isVariable ? 'check' : ''}
536536
label="Environment Variable"
537537
onClick={() => {
538538
const { activeTagData, activeTagDefinition, variables } = state;

packages/insomnia/src/ui/templating/__tests__/worker.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ const userPluginTag: TemplateTag = {
3333
},
3434
};
3535

36+
describe('worker tag argument resolution', () => {
37+
beforeEach(() => {
38+
reload();
39+
mockFetch.mockReset();
40+
mockFetch.mockImplementation(async (path: any) => {
41+
if (path === 'plugin.getBundlePluginTemplateTags' || path === 'plugin.getUserPluginTemplateTags') {
42+
return [];
43+
}
44+
return;
45+
});
46+
});
47+
48+
it('resolves a _.variable argument to its value rather than the literal reference', async () => {
49+
const result = await render("{% jsonpath _.body, '$.id' %}", { context: { body: '{"id":"vaporeon"}' } });
50+
expect(result).toBe('vaporeon');
51+
});
52+
});
53+
3654
describe('worker getLiquid plugin tag registration', () => {
3755
beforeEach(() => {
3856
reload();

0 commit comments

Comments
 (0)