diff --git a/src/util/__test__/expand-prompt.test.ts b/src/util/__test__/expand-prompt.test.ts index 5010199..412576f 100644 --- a/src/util/__test__/expand-prompt.test.ts +++ b/src/util/__test__/expand-prompt.test.ts @@ -145,4 +145,44 @@ describe('expandTemplate', () => { const result = await expandPrompt('No placeholders here.', tempDir, {}); expect(result).toBe('No placeholders here.'); }); + + it('preserves $$ in a variable value verbatim', async () => { + const result = await expandPrompt('Price: {{cost}}', tempDir, { + cost: '$$100', + }); + expect(result).toBe('Price: $$100'); + }); + + it('preserves $& in a variable value verbatim', async () => { + const result = await expandPrompt('Body: {{body}}', tempDir, { + body: 'foo $& bar', + }); + expect(result).toBe('Body: foo $& bar'); + }); + + it('preserves $` in a variable value verbatim', async () => { + const result = await expandPrompt('Body: {{body}}', tempDir, { + body: 'before $` after', + }); + expect(result).toBe('Body: before $` after'); + }); + + it("preserves $' in a variable value verbatim", async () => { + const result = await expandPrompt('Body: {{body}}', tempDir, { + body: "before $' after", + }); + expect(result).toBe("Body: before $' after"); + }); + + it('preserves mixed dollar-sign sequences across multiple variables', async () => { + const result = await expandPrompt( + 'Cost: {{cost}}, body: {{body}}', + tempDir, + { + cost: '$$100', + body: 'regex $& match', + }, + ); + expect(result).toBe('Cost: $$100, body: regex $& match'); + }); }); diff --git a/src/util/expand-prompt.ts b/src/util/expand-prompt.ts index a6556ae..07c7556 100644 --- a/src/util/expand-prompt.ts +++ b/src/util/expand-prompt.ts @@ -22,7 +22,7 @@ export async function expandPrompt( let result = await expandIncludes(template, basePath); for (const [key, value] of Object.entries(variables)) { - result = result.replaceAll(`{{${key}}}`, value); + result = result.replaceAll(`{{${key}}}`, () => value); } return result;