Skip to content

Commit

Permalink
Merge fcb175b into 5f79fb0
Browse files Browse the repository at this point in the history
  • Loading branch information
sneakertack committed Dec 1, 2016
2 parents 5f79fb0 + fcb175b commit cffce9d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 10 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,17 @@ The parsing engine currently supports the following rules:

- `BASIC=basic` becomes `{BASIC: 'basic'}`
- empty lines are skipped
- lines beginning with `#` are treated as comments
- empty values become empty strings (`EMPTY=` becomes `{EMPTY: ''}`)
- single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes `{SINGLE_QUOTE: "quoted"}`)
- leading/trailing whitespace gets trimmed
- new lines are expanded if in double quotes (`MULTILINE="new\nline"` becomes

```
{MULTILINE: 'new
line'}
```
- inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes `{JSON:"{\"foo\": \"bar\"}"`)
- ` #` indicates a comment for the rest of the line unless it's quoted (`HASH='here # there' # a comment` becomes `{HASH: "here # there"}`). lines starting with `#` are entirely skipped.

## FAQ

Expand Down
21 changes: 12 additions & 9 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,27 @@ module.exports = {

// convert Buffers before splitting into lines and processing
src.toString().split('\n').forEach(function (line) {
// matching "KEY' and 'VAL' in 'KEY=VAL'
var keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/)
// matching "KEY' and 'VAL' in 'KEY=VAL', preliminarily trimming them of leading/trailing whitespace
var keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*?)\s*$/)
// matched?
if (keyValueArr != null) {
var key = keyValueArr[1]

// default undefined or missing values to empty string
var value = keyValueArr[2] ? keyValueArr[2] : ''

// expand newlines in quoted values
var len = value ? value.length : 0
if (len > 0 && value.charAt(0) === '\"' && value.charAt(len - 1) === '\"') {
value = value.replace(/\\n/gm, '\n')
// test if there's valid quoting. check end first - value's last char should either be a quote, or there should be a quote-whitespace-hash combination somewhere (ending quote followed by comment)
var validEndingQuote = /(['"])$/.exec(value.slice(1)) || /(['"])\s+#/.exec(value.slice(1)) // will be exec result array, or null. Slice 1st char so a starting quote (if present) can't be misidentified as an ending one.
if (validEndingQuote && value.charAt(0) === validEndingQuote[1]) { // end could be single or double, first char must match.
// quoted mode.
value = value.substring(1, validEndingQuote.index + 1) // +1 to counter effects of prior 1st-char slice.
if (validEndingQuote[1] === '"') value = value.replace(/\\n/gm, '\n') // For double-quoteds, expand newlines.
value = value.trim(); // Do a final trim on the value.
} else {
// unquoted mode.
value = value.replace(/\s+#.*/, '') // remove EOL-comments, if present.
}

// remove any surrounding quotes and extra spaces
value = value.replace(/(^['"]|['"]$)/g, '').trim()

obj[key] = value
}
})
Expand Down
7 changes: 7 additions & 0 deletions test/.env
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ EXPAND_NEWLINES="expand\nnewlines"
DONT_EXPAND_NEWLINES_1=dontexpand\nnewlines
DONT_EXPAND_NEWLINES_2='dontexpand\nnewlines'
# COMMENTS=work
EOL_COMMENTS=good # bad
QUOTED_HASH_1='should be # included'
QUOTED_HASH_2="should be # included"
EQUAL_SIGNS=equals==
RETAIN_INNER_QUOTES={"foo": "bar"}
RETAIN_INNER_QUOTES_AS_STRING='{"foo": "bar"}'
INCLUDE_SPACE=some spaced out string
WHITESPACE_TRIM= trim me
USERNAME="therealnerdybeast@example.tld"

PARSER_QA_1= 'a'b'c'd'e' # a comment
PARSER_QA_2=" mismatched\nquotes ' # should\nnot\nprocess
22 changes: 22 additions & 0 deletions test/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,17 @@ describe('dotenv', function () {
done()
})

it('ignores comments at the end of lines', function (done) {
parsed.EOL_COMMENTS.should.eql('good')
done()
})

it('respects comment-lookalikes if quoted', function (done) {
parsed.QUOTED_HASH_1.should.eql('should be # included')
parsed.QUOTED_HASH_2.should.eql('should be # included')
done()
})

it('respects equals signs in values', function (done) {
parsed.EQUAL_SIGNS.should.eql('equals==')
done()
Expand All @@ -167,9 +178,20 @@ describe('dotenv', function () {
done()
})

it('trims leading/trailing whitespace', function (done) {
parsed.WHITESPACE_TRIM.should.eql('trim me')
done()
})

it('parses email addresses completely', function (done) {
parsed.should.have.property('USERNAME', 'therealnerdybeast@example.tld')
done()
})

it('handles severe combinations of the above', function (done) {
parsed.PARSER_QA_1.should.eql("a'b'c'd'e")
parsed.PARSER_QA_2.should.eql('" mismatched\\nquotes \'')
done()
})
})
})

0 comments on commit cffce9d

Please sign in to comment.