From a98c1c9078f62a8e77da1ca7eae3bb10deaaa0e1 Mon Sep 17 00:00:00 2001 From: Krishna Rajendran Date: Wed, 30 Sep 2015 02:16:06 -0700 Subject: [PATCH] Support variable expansion in the middle of a string. Allow basic variable expansion in the middle of a string. Here is an example use case: ``` $DB_USER=my_user $DB_HOST=localhost $DB_NAME=my_db $DATABASE_URL="${DB_USER}@${DB_HOST}/${DB_NAME}" ``` --- lib/main.js | 33 +++++++++++++++++++++++++-------- test/.env | 5 +++++ test/main.js | 25 +++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/lib/main.js b/lib/main.js index 4643d658..87873f2c 100644 --- a/lib/main.js +++ b/lib/main.js @@ -67,17 +67,34 @@ module.exports = { value = value.replace(/\\n/gm, '\n') } + var isSingleQuoted = value.charAt(0) === '\'' && value.charAt(len - 1) === '\'' + // remove any surrounding quotes and extra spaces value = value.replace(/(^['"]|['"]$)/g, '').trim() - // is this value a variable? - if (value.charAt(0) === '$') { - var possibleVar = value.substring(1) - value = obj[possibleVar] || process.env[possibleVar] || '' - } - // varaible can be escaped with a \$ - if (value.substring(0, 2) === '\\$') { - value = value.substring(1) + // match and replace variables + if (!isSingleQuoted) { + value = value.replace(/\\?\${?[^}]*}?/g, function (match) { + var possibleVar + var len = match.length + + // variable can be escaped with a \$ + if (match.charAt(0) === '\\') { + return match.substring(1) + } + + if (match.charAt(1) === '{') { + // if there is an opening brace there must be a closing one + if (match.charAt(len - 1) !== '}') { + return match + } + possibleVar = match.slice(2, -1) + } else { + possibleVar = match.substring(1) + } + + return obj[possibleVar] || process.env[possibleVar] || '' + }) } obj[key] = value diff --git a/test/.env b/test/.env index 22201c89..17ee7695 100644 --- a/test/.env +++ b/test/.env @@ -17,3 +17,8 @@ EQUAL_SIGNS=equals== RETAIN_INNER_QUOTES={"foo": "bar"} RETAIN_INNER_QUOTES_AS_STRING='{"foo": "bar"}' INCLUDE_SPACE=some spaced out string +BRACED_EXPAND=${BASIC} +INLINE_EXPAND="inline${BASIC}ally" +ESCAPED_INLINE_EXPAND="inline\${BASIC}ally" +SINGLE_QUOTED_INLINE_EXPAND='inline${BASIC}ally' +UNCLOSED_INLINE_EXPAND="inline${BASICally" diff --git a/test/main.js b/test/main.js index dcfbe632..04761574 100644 --- a/test/main.js +++ b/test/main.js @@ -155,6 +155,31 @@ describe('dotenv', function () { parsed.ESCAPED_EXPAND.should.equal('$ESCAPED') done() }) + + it('expands variables surrounded by braces', function (done) { + parsed.SINGLE_QUOTED_INLINE_EXPAND.should.equal('inline${BASIC}ally') + done() + }) + + it('expands inline environment variables', function (done) { + parsed.INLINE_EXPAND.should.equal('inlinebasically') + done() + }) + + it('does not expands inline escaped variables', function (done) { + parsed.ESCAPED_INLINE_EXPAND.should.equal('inline${BASIC}ally') + done() + }) + + it('does not expands inline variables in single quoted strings', function (done) { + parsed.SINGLE_QUOTED_INLINE_EXPAND.should.equal('inline${BASIC}ally') + done() + }) + + it('does not expands inline variables with unclosed braces', function (done) { + parsed.UNCLOSED_INLINE_EXPAND.should.equal('inline${BASICally') + done() + }) }) it('defaults empty values to empty string', function (done) {