Skip to content

Commit

Permalink
Support multiline values (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
gonzaloriestra committed Feb 28, 2024
1 parent 6abd59f commit dc6083d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
25 changes: 22 additions & 3 deletions source/index.ts
Expand Up @@ -9,9 +9,9 @@ export type Input = Record<string, any>
/** Parse an envfile string. */
export function parse(src: string): Data {
const result: Data = {}
const lines = src.toString().split('\n')
const lines = splitInLines(src)
for (const line of lines) {
const match = line.match(/^([^=:#]+?)[=:](.*)/)
const match = line.match(/^([^=:#]+?)[=:]((.|\n)*)/)
if (match) {
const key = match[1].trim()
const value = match[2].trim().replace(/['"]+/g, '')
Expand All @@ -26,9 +26,28 @@ export function stringify(obj: Input): string {
let result = ''
for (const [key, value] of Object.entries(obj)) {
if (key) {
const line = `${key}=${String(value)}`
const line = `${key}=${jsonValueToEnv(value)}`
result += line + '\n'
}
}
return result
}

function splitInLines(src: string): string[] {
return src
.replace(/("[\s\S]*?")/g, (_m, cg) => {
return cg.replace(/\n/g, '%%LINE-BREAK%%')
})
.split('\n')
.filter((i) => Boolean(i.trim()))
.map((i) => i.replace(/%%LINE-BREAK%%/g, '\n'))
}

function jsonValueToEnv(value: any): string {
let processedValue = String(value)
processedValue = processedValue.replace(/\n/g, '\\n')
processedValue = processedValue.includes('\\n')
? `"${processedValue}"`
: processedValue
return processedValue
}
26 changes: 25 additions & 1 deletion source/test.ts
Expand Up @@ -8,7 +8,7 @@ import filedirname from 'filedirname'
import { resolve } from 'path'

// local
import { parse } from './index.js'
import { parse, stringify } from './index.js'

// prepare
const [file, dir] = filedirname()
Expand Down Expand Up @@ -49,4 +49,28 @@ kava.suite('envfile', function (suite, test) {
deepEqual(result, expected)
done()
})

test('line breaks inside quotes should be preserved on parse', function (done) {
const str = `name="bob\nmarley"\nplanet=earth`
const expected = {
name: 'bob\nmarley',
planet: 'earth',
}
const result = parse(str)

deepEqual(result, expected)
done()
})

test('line breaks inside quotes should be preserved on stringify', function (done) {
const input = {
name: 'bob\nmarley',
planet: 'earth',
}
const expected = `name="bob\\nmarley"\nplanet=earth\n`
const result = stringify(input)

deepEqual(result, expected)
done()
})
})

0 comments on commit dc6083d

Please sign in to comment.