Skip to content

Commit

Permalink
Merge pull request #615 from motdotla/backtick-support
Browse files Browse the repository at this point in the history
Add support for backticks
  • Loading branch information
motdotla committed Feb 2, 2022
2 parents d6184e5 + a8d34e5 commit bd26c38
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 6 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,7 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [Unreleased](https://github.com/motdotla/dotenv/compare/v15.0.0...master)
## [Unreleased](https://github.com/motdotla/dotenv/compare/v16.0.0...master)

## [16.0.0](https://github.com/motdotla/dotenv/compare/v15.0.1...v16.0.0) (2022-02-02)

### Added

- _Breaking:_ Backtick support 🎉 (template literals). If you had values containing the backtick character, please quote those values with either single or double quotes.

## [15.0.1](https://github.com/motdotla/dotenv/compare/v15.0.0...v15.0.1) (2022-02-02)

Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -299,6 +299,8 @@ The parsing engine currently supports the following rules:
line'}
```

- backticks are supported (`BACKTICK_KEY=`This has 'single' and "double" quotes inside of it.``)

### What happens to environment variables that were already set?

By default, we will never modify any environment variables that have already been set. In particular, if there is a variable in your `.env` file which collides with one that already exists in your environment, then that variable will be skipped.
Expand Down
4 changes: 2 additions & 2 deletions lib/main.js
Expand Up @@ -2,7 +2,7 @@ const fs = require('fs')
const path = require('path')
const os = require('os')

const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg

// Parser src into an Object
function parse (src) {
Expand All @@ -28,7 +28,7 @@ function parse (src) {
const maybeQuote = value[0]

// Remove surrounding quotes
value = value.replace(/^(['"])([\s\S]*)\1$/mg, '$2')
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')

// Expand newlines if double quoted
if (maybeQuote === '"') {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "dotenv",
"version": "15.0.1",
"version": "16.0.0",
"description": "Loads environment variables from .env file",
"main": "lib/main.js",
"types": "lib/main.d.ts",
Expand Down
11 changes: 11 additions & 0 deletions tests/.env
Expand Up @@ -5,23 +5,34 @@ AFTER_LINE=after_line
EMPTY=
EMPTY_SINGLE_QUOTES=''
EMPTY_DOUBLE_QUOTES=""
EMPTY_BACKTICKS=``
SINGLE_QUOTES='single_quotes'
SINGLE_QUOTES_SPACED=' single quotes '
DOUBLE_QUOTES="double_quotes"
DOUBLE_QUOTES_SPACED=" double quotes "
DOUBLE_QUOTES_INSIDE_SINGLE='double "quotes" work inside single quotes'
SINGLE_QUOTES_INSIDE_DOUBLE="single 'quotes' work inside double quotes"
BACKTICKS_INSIDE_SINGLE='`backticks` work inside single quotes'
BACKTICKS_INSIDE_DOUBLE="`backticks` work inside double quotes"
BACKTICKS=`backticks`
BACKTICKS_SPACED=` backticks `
DOUBLE_QUOTES_INSIDE_BACKTICKS=`double "quotes" work inside backticks`
SINGLE_QUOTES_INSIDE_BACKTICKS=`single 'quotes' work inside backticks`
DOUBLE_AND_SINGLE_QUOTES_INSIDE_BACKTICKS=`double "quotes" and single 'quotes' work inside backticks`
EXPAND_NEWLINES="expand\nnew\nlines"
DONT_EXPAND_UNQUOTED=dontexpand\nnewlines
DONT_EXPAND_SQUOTED='dontexpand\nnewlines'
DONT_EXPAND_SQUOTED='dontexpand\nnewlines'
# COMMENTS=work
INLINE_COMMENTS=inline comments # work #very #well
INLINE_COMMENTS_SINGLE_QUOTES='inline comments outside of #singlequotes' # work
INLINE_COMMENTS_DOUBLE_QUOTES="inline comments outside of #doublequotes" # work
INLINE_COMMENTS_BACKTICKS=`inline comments outside of #backticks` # work
INLINE_COMMENTS_SPACE=inline comments start with a#space
EQUAL_SIGNS=equals==
RETAIN_INNER_QUOTES={"foo": "bar"}
RETAIN_INNER_QUOTES_AS_STRING='{"foo": "bar"}'
RETAIN_INNER_QUOTES_AS_BACKTICKS=`{"foo": "bar's"}`
TRIM_SPACE_FROM_UNQUOTED= some spaced out string
USERNAME=therealnerdybeast@example.tld
SPACED_KEY = parsed
6 changes: 6 additions & 0 deletions tests/.env-multiline
Expand Up @@ -30,3 +30,9 @@ IS
A
MULTILINE
STRING'

MULTI_BACKTICKED=`THIS
IS
A
"MULTILINE'S"
STRING`
2 changes: 2 additions & 0 deletions tests/test-parse-multiline.js
Expand Up @@ -45,6 +45,8 @@ t.equal(parsed.MULTI_DOUBLE_QUOTED, 'THIS\nIS\nA\nMULTILINE\nSTRING', 'parses mu

t.equal(parsed.MULTI_SINGLE_QUOTED, 'THIS\nIS\nA\nMULTILINE\nSTRING', 'parses multi-line strings when using single quotes')

t.equal(parsed.MULTI_BACKTICKED, 'THIS\nIS\nA\n"MULTILINE\'S"\nSTRING', 'parses multi-line strings when using single quotes')

const payload = dotenv.parse(Buffer.from('BUFFER=true'))
t.equal(payload.BUFFER, 'true', 'should parse a buffer into an object')

Expand Down
20 changes: 20 additions & 0 deletions tests/test-parse.js
Expand Up @@ -17,6 +17,8 @@ t.equal(parsed.EMPTY_SINGLE_QUOTES, '', 'defaults empty values to empty string')

t.equal(parsed.EMPTY_DOUBLE_QUOTES, '', 'defaults empty values to empty string')

t.equal(parsed.EMPTY_BACKTICKS, '', 'defaults empty values to empty string')

t.equal(parsed.SINGLE_QUOTES, 'single_quotes', 'escapes single quoted values')

t.equal(parsed.SINGLE_QUOTES_SPACED, ' single quotes ', 'respects surrounding spaces in single quotes')
Expand All @@ -29,6 +31,20 @@ t.equal(parsed.DOUBLE_QUOTES_INSIDE_SINGLE, 'double "quotes" work inside single

t.equal(parsed.SINGLE_QUOTES_INSIDE_DOUBLE, "single 'quotes' work inside double quotes", 'respects single quotes inside double quotes')

t.equal(parsed.BACKTICKS_INSIDE_SINGLE, '`backticks` work inside single quotes', 'respects backticks inside single quotes')

t.equal(parsed.BACKTICKS_INSIDE_DOUBLE, '`backticks` work inside double quotes', 'respects backticks inside double quotes')

t.equal(parsed.BACKTICKS, 'backticks')

t.equal(parsed.BACKTICKS_SPACED, ' backticks ')

t.equal(parsed.DOUBLE_QUOTES_INSIDE_BACKTICKS, 'double "quotes" work inside backticks', 'respects double quotes inside backticks')

t.equal(parsed.SINGLE_QUOTES_INSIDE_BACKTICKS, "single 'quotes' work inside backticks", 'respects single quotes inside backticks')

t.equal(parsed.DOUBLE_AND_SINGLE_QUOTES_INSIDE_BACKTICKS, "double \"quotes\" and single 'quotes' work inside backticks", 'respects single quotes inside backticks')

t.equal(parsed.EXPAND_NEWLINES, 'expand\nnew\nlines', 'expands newlines but only if double quoted')

t.equal(parsed.DONT_EXPAND_UNQUOTED, 'dontexpand\\nnewlines', 'expands newlines but only if double quoted')
Expand All @@ -43,6 +59,8 @@ t.equal(parsed.INLINE_COMMENTS_SINGLE_QUOTES, 'inline comments outside of #singl

t.equal(parsed.INLINE_COMMENTS_DOUBLE_QUOTES, 'inline comments outside of #doublequotes', 'ignores inline comments and respects # character inside of double quotes')

t.equal(parsed.INLINE_COMMENTS_BACKTICKS, 'inline comments outside of #backticks', 'ignores inline comments and respects # character inside of backticks')

t.equal(parsed.INLINE_COMMENTS_SPACE, 'inline comments start with a', 'treats # character as start of comment')

t.equal(parsed.EQUAL_SIGNS, 'equals==', 'respects equals signs in values')
Expand All @@ -55,6 +73,8 @@ t.equal(parsed.RETAIN_INNER_QUOTES, '{"foo": "bar"}', 'retains inner quotes')

t.equal(parsed.RETAIN_INNER_QUOTES_AS_STRING, '{"foo": "bar"}', 'retains inner quotes')

t.equal(parsed.RETAIN_INNER_QUOTES_AS_BACKTICKS, '{"foo": "bar\'s"}', 'retains inner quotes')

t.equal(parsed.TRIM_SPACE_FROM_UNQUOTED, 'some spaced out string', 'retains spaces in string')

t.equal(parsed.USERNAME, 'therealnerdybeast@example.tld', 'parses email addresses completely')
Expand Down

0 comments on commit bd26c38

Please sign in to comment.