From 482a563b2a90fdc1dbf22da882fac4687dddb794 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 13 Nov 2017 17:13:12 -0700 Subject: [PATCH] Fix: toExpression handles double quotes in strings (#232) add tests for double quotes and backslashes in string type values --- common/lib/__tests__/ast.toExpression.js | 36 ++++++++++++++++++++++++ common/lib/ast.js | 7 +++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/common/lib/__tests__/ast.toExpression.js b/common/lib/__tests__/ast.toExpression.js index 3da23977043c4..f4593f5864c0c 100644 --- a/common/lib/__tests__/ast.toExpression.js +++ b/common/lib/__tests__/ast.toExpression.js @@ -151,6 +151,42 @@ describe('ast toExpression', () => { expect(expression).to.equal('csv input="stuff\nthings"'); }); + it('single expression string value with a backslash', () => { + const astObj = { + type: 'expression', + chain: [{ + type: 'function', + function: 'csv', + arguments: { + input: [ + 'slash \\\\ slash', + ], + }, + }], + }; + + const expression = toExpression(astObj); + expect(expression).to.equal('csv input="slash \\\\ slash"'); + }); + + it('single expression string value with a double quote', () => { + const astObj = { + type: 'expression', + chain: [{ + type: 'function', + function: 'csv', + arguments: { + input: [ + 'stuff\nthings\n"such"', + ], + }, + }], + }; + + const expression = toExpression(astObj); + expect(expression).to.equal('csv input="stuff\nthings\n\\"such\\""'); + }); + it('single expression with number argument', () => { const astObj = { type: 'expression', diff --git a/common/lib/ast.js b/common/lib/ast.js index 03163469d691f..f9c25296eac7a 100644 --- a/common/lib/ast.js +++ b/common/lib/ast.js @@ -3,13 +3,16 @@ import { getType } from '../lib/get_type'; function getArgumentString(arg, argKey) { const type = getType(arg); - // TODO: MAJOR -- This breaks for single quoted strings that contain double quotes! function maybeArgKey(argString) { return (argKey == null || argKey === '_') ? argString : `${argKey}=${argString}`; } - if (type === 'string') return maybeArgKey(`"${arg}"`); + // TODO: this works, but seems a little hacky. it removes existing escaped chars on quotes + // and adds the escaping onto all other double quotes it finds in the string + const escapeQuotes = (val) => val.replace(/\\\"/g, '"').replace(/\"/g, '\\"'); + + if (type === 'string') return maybeArgKey(`"${escapeQuotes(arg)}"`); if (type === 'boolean' || type === 'null' || type === 'number') return maybeArgKey(`${arg}`); if (type === 'expression') return maybeArgKey(`{${getExpression(arg.chain)}}`); if (type === 'partial') return maybeArgKey('${' + getExpression(arg.chain) + '}');