Skip to content

Commit

Permalink
Improve quoted string flexibility (#177)
Browse files Browse the repository at this point in the history
Add `scalarOptions.str.defaultQuote` option

Also use double-quoted strings for strings with `'`, which minimizes escaping
  • Loading branch information
Himura2la authored Jul 8, 2020
1 parent 62bc845 commit f118002
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 3 deletions.
6 changes: 6 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ export namespace scalarOptions {
* Default: `'PLAIN'`
*/
defaultType: Scalar.Type
/**
* Use 'single quote' rather than "double quote" by default
*
* Default: `false`
*/
defaultQuoteSingle: boolean
doubleQuoted: {
/**
* Whether to restrict double-quoted strings to use JSON-compatible syntax.
Expand Down
16 changes: 13 additions & 3 deletions src/stringify/stringifyString.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,26 @@ function plainString(item, ctx, onComment, onChompKeep) {
value
)
) {
const hasDouble = value.indexOf('"') !== -1
const hasSingle = value.indexOf("'") !== -1
let quotedString
if (hasDouble && !hasSingle) {
quotedString = singleQuotedString
} else if (hasSingle && !hasDouble) {
quotedString = doubleQuotedString
} else if (strOptions.defaultQuoteSingle) {
quotedString = singleQuotedString
} else {
quotedString = doubleQuotedString
}
// not allowed:
// - empty string, '-' or '?'
// - start with an indicator character (except [?:-]) or /[?-] /
// - '\n ', ': ' or ' \n' anywhere
// - '#' not preceded by a non-space char
// - end with ' ' or ':'
return implicitKey || inFlow || value.indexOf('\n') === -1
? value.indexOf('"') !== -1 && value.indexOf("'") === -1
? singleQuotedString(value, ctx)
: doubleQuotedString(value, ctx)
? quotedString(value, ctx)
: blockString(item, ctx, onComment, onChompKeep)
}
if (
Expand Down
1 change: 1 addition & 0 deletions src/tags/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const nullOptions = { nullStr: 'null' }

export const strOptions = {
defaultType: Type.PLAIN,
defaultQuoteSingle: false,
doubleQuoted: {
jsonEncoding: false,
minMultiLineLength: 40
Expand Down
56 changes: 56 additions & 0 deletions tests/doc/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,62 @@ describe('indentSeq: false', () => {
})
})

describe('default quote option', () => {
let origDefaultQuoteOption
beforeAll(() => {
origDefaultQuoteOption = YAML.scalarOptions.str.defaultQuoteSingle
})
afterAll(() => {
YAML.scalarOptions.str.defaultQuoteSingle = origDefaultQuoteOption
})

const testSingleQuote = str => {
const expected = `'${str}'\n`
const actual = YAML.stringify(str)
expect(actual).toBe(expected)
expect(YAML.parse(actual)).toBe(str)
}
const testDoubleQuote = str => {
const expected = `"${str}"\n`
const actual = YAML.stringify(str)
expect(actual).toBe(expected)
expect(YAML.parse(actual)).toBe(str)
}

const testPlainStyle = () => {
const str = YAML.stringify('foo bar')
expect(str).toBe('foo bar\n')
}
const testForcedQuotes = () => {
let str = YAML.stringify('foo: "bar"')
expect(str).toBe(`'foo: "bar"'\n`)
str = YAML.stringify("foo: 'bar'")
expect(str).toBe(`"foo: 'bar'"\n`)
}

test('default', () => {
YAML.scalarOptions.str.defaultQuoteSingle = origDefaultQuoteOption
testPlainStyle()
testForcedQuotes()
testDoubleQuote('123')
testDoubleQuote('foo #bar')
})
test("'", () => {
YAML.scalarOptions.str.defaultQuoteSingle = true
testPlainStyle()
testForcedQuotes()
testDoubleQuote('123') // number-as-string is double-quoted
testSingleQuote('foo #bar')
})
test('"', () => {
YAML.scalarOptions.str.defaultQuoteSingle = false
testPlainStyle()
testForcedQuotes()
testDoubleQuote('123')
testDoubleQuote('foo #bar')
})
})

describe('Document markers in top-level scalars', () => {
let origDoubleQuotedOptions
beforeAll(() => {
Expand Down

0 comments on commit f118002

Please sign in to comment.