Skip to content

Commit

Permalink
Cleanup: Drop scalarOptions (now empty) & options from tag interface
Browse files Browse the repository at this point in the history
Additionally, un-document the YAML.defaultOptions export.

BREAKING CHANGE: These are no longer used, as their functionality has
been moved to ParseOptions and ToStringOptions.
  • Loading branch information
eemeli committed Mar 7, 2021
1 parent f281157 commit 24383fc
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 119 deletions.
1 change: 0 additions & 1 deletion README.md
Expand Up @@ -34,7 +34,6 @@ const YAML = require('yaml')

### YAML Documents

- [`YAML.defaultOptions`](https://eemeli.org/yaml/#options)
- [`YAML.Document`](https://eemeli.org/yaml/#yaml-documents)
- [`constructor(value, replacer?, options?)`](https://eemeli.org/yaml/#creating-documents)
- [`defaults`](https://eemeli.org/yaml/#options)
Expand Down
1 change: 0 additions & 1 deletion docs/01_intro.md
Expand Up @@ -39,7 +39,6 @@ const YAML = require('yaml')

<h3>Documents</h3>

- [`YAML.defaultOptions`](#options)
- [`YAML.Document`](#documents)
- [`constructor(value, replacer?, options?)`](#creating-documents)
- [`defaults`](#options)
Expand Down
41 changes: 17 additions & 24 deletions docs/06_custom_tags.md
@@ -1,18 +1,15 @@
# Custom Data Types

```js
YAML.parse('!!timestamp 2001-12-15 2:59:43')
// YAMLWarning:
// The tag tag:yaml.org,2002:timestamp is unavailable,
// falling back to tag:yaml.org,2002:str
// '2001-12-15 2:59:43'
import { parse, parseDocument } from 'yaml'

YAML.defaultOptions.customTags = ['timestamp']
parse('2001-12-15 2:59:43')
// '2001-12-15 2:59:43'

YAML.parse('2001-12-15 2:59:43') // returns a Date instance
// 2001-12-15T02:59:43.000Z
parse('!!timestamp 2001-12-15 2:59:43')
// 2001-12-15T02:59:43.000Z (Date instance)

const doc = YAML.parseDocument('2001-12-15 2:59:43')
const doc = parseDocument('2001-12-15 2:59:43', { customTags: ['timestamp'] })
doc.contents.value.toDateString()
// 'Sat Dec 15 2001'
```
Expand All @@ -24,16 +21,14 @@ For further customisation, `customTags` may also be a function `(Tag[]) => (Tag[
## Built-in Custom Tags

```js
YAML.parse('[ one, true, 42 ]').map(v => typeof v)
// [ 'string', 'boolean', 'number' ]
parse('[ one, true, 42 ]')
// [ 'one', true, 42 ]

let opt = { schema: 'failsafe' }
YAML.parse('[ one, true, 42 ]', opt).map(v => typeof v)
// [ 'string', 'string', 'string' ]
parse('[ one, true, 42 ]', { schema: 'failsafe' })
// [ 'one', 'true', '42' ]

opt = { schema: 'failsafe', customTags: ['int'] }
YAML.parse('[ one, true, 42 ]', opt).map(v => typeof v)
// [ 'string', 'string', 'number' ]
parse('[ one, true, 42 ]', { schema: 'failsafe', customTags: ['int'] })
// [ 'one', 'true', 42 ]
```

### YAML 1.2 Core Schema
Expand Down Expand Up @@ -70,6 +65,7 @@ These tags are a part of the YAML 1.1 [language-independent types](https://yaml.
## Writing Custom Tags

```js
import { stringify } from 'yaml'
import { stringifyString } from 'yaml/util'

const regexp = {
Expand All @@ -92,12 +88,10 @@ const sharedSymbol = {
}
}

YAML.defaultOptions.customTags = [regexp, sharedSymbol]

YAML.stringify({
regexp: /foo/gi,
symbol: Symbol.for('bar')
})
stringify(
{ regexp: /foo/gi, symbol: Symbol.for('bar') },
{ customTags: [regexp, sharedSymbol] }
)
// regexp: !re /foo/gi
// symbol: !symbol/shared bar
```
Expand Down Expand Up @@ -143,7 +137,6 @@ To define your own tag, you'll need to define an object comprising of some of th
- `format: string` If a tag has multiple forms that should be parsed and/or stringified differently, use `format` to identify them. Used by `!!int` and `!!float`.
- **`identify(value): boolean`** is used by `doc.createNode()` to detect your data type, e.g. using `typeof` or `instanceof`. Required.
- `nodeClass: Node` is the `Node` child class that implements this tag. Required for collections and tags that have overlapping JS representations.
- `options: Object` is used by some tags to configure their stringification.
- **`resolve(value, onError): Node | any`** turns a parsed value into an AST node; `value` is either a `string`, a `YAMLMap` or a `YAMLSeq`. `onError(msg)` should be called with an error message string when encountering errors, as it'll allow you to still return some value for the node. If returning a non-`Node` value, the output will be wrapped as a `Scalar`. Required.
- `stringify(item, ctx, onComment, onChompKeep): string` is an optional function stringifying the `item` AST node in the current context `ctx`. `onComment` and `onChompKeep` are callback functions for a couple of special cases. If your data includes a suitable `.toString()` method, you can probably leave this undefined and use the default stringifier.
- **`tag: string`** is the identifier for your data type, with which its stringified form will be prefixed. Should either be a !-prefixed local `!tag`, or a fully qualified `tag:domain,date:foo`. Required.
Expand Down
1 change: 0 additions & 1 deletion src/index.ts
Expand Up @@ -29,7 +29,6 @@ export {
CreateNodeOptions,
defaultOptions,
Options,
scalarOptions,
SchemaOptions,
ToJSOptions,
ToStringOptions
Expand Down
7 changes: 0 additions & 7 deletions src/options.ts
Expand Up @@ -302,10 +302,3 @@ export const defaultOptions: Required<
strict: true,
version: '1.2'
}

/**
* Some customization options are availabe to control the parsing and
* stringification of scalars. Note that these values are used by all documents.
*/
export const scalarOptions = {
}
5 changes: 0 additions & 5 deletions src/tags/types.ts
Expand Up @@ -51,11 +51,6 @@ interface TagBase {
*/
identify?: (value: unknown) => boolean

/**
* Used by some tags to configure their stringification, where applicable.
*/
options?: Record<string, unknown>

/**
* The identifier for your data type, with which its stringified form will be
* prefixed. Should either be a !-prefixed local `!tag`, or a fully qualified
Expand Down
16 changes: 2 additions & 14 deletions tests/doc/YAML-1.1.spec.js
@@ -1,17 +1,5 @@
import { source } from 'common-tags'
import * as YAML from 'yaml'

const orig = {}
beforeAll(() => {
orig.prettyErrors = YAML.defaultOptions.prettyErrors
orig.version = YAML.defaultOptions.version
YAML.defaultOptions.prettyErrors = true
YAML.defaultOptions.version = '1.1'
})
afterAll(() => {
YAML.defaultOptions.prettyErrors = orig.prettyErrors
YAML.defaultOptions.version = orig.version
})
import { parseAllDocuments } from 'yaml'

test('Use preceding directives if none defined', () => {
const src = source`
Expand All @@ -29,7 +17,7 @@ test('Use preceding directives if none defined', () => {
---
!bar "Using previous YAML directive"
`
const docs = YAML.parseAllDocuments(src, { prettyErrors: false })
const docs = parseAllDocuments(src, { prettyErrors: false, version: '1.1' })
const warn = tag => ({ message: `Unresolved tag: ${tag}` })
expect(docs).toMatchObject([
{
Expand Down
19 changes: 5 additions & 14 deletions tests/doc/YAML-1.2.spec.js
Expand Up @@ -1851,20 +1851,9 @@ matches %: 20`,
}
}

let origPrettyErrors
const mockWarn = jest.spyOn(global.process, 'emitWarning').mockImplementation()

beforeAll(() => {
origPrettyErrors = YAML.defaultOptions.prettyErrors
YAML.defaultOptions.prettyErrors = false
})

beforeEach(() => mockWarn.mockClear())

afterAll(() => {
YAML.defaultOptions.prettyErrors = origPrettyErrors
mockWarn.mockRestore()
})
afterAll(() => mockWarn.mockRestore())

for (const section in spec) {
describe(section, () => {
Expand All @@ -1873,7 +1862,7 @@ for (const section in spec) {
const { src, tgt, errors, special, jsWarnings, warnings } = spec[
section
][name]
const documents = YAML.parseAllDocuments(src)
const documents = YAML.parseAllDocuments(src, { prettyErrors: false })
const json = documents.map(doc => doc.toJS())
expect(json).toMatchObject(tgt)
documents.forEach((doc, i) => {
Expand All @@ -1894,7 +1883,9 @@ for (const section in spec) {
if (special) special(src)
if (!errors) {
const src2 = documents.map(doc => String(doc)).join('\n...\n')
const documents2 = YAML.parseAllDocuments(src2)
const documents2 = YAML.parseAllDocuments(src2, {
prettyErrors: false
})
const json2 = documents2.map(doc => doc.toJS())
expect(json2).toMatchObject(tgt)
}
Expand Down
71 changes: 30 additions & 41 deletions tests/doc/stringify.js
Expand Up @@ -10,124 +10,113 @@ for (const [name, version] of [
['YAML 1.2', '1.2']
]) {
describe(name, () => {
let origVersion
beforeAll(() => {
origVersion = YAML.defaultOptions.version
YAML.defaultOptions.version = version
})
afterAll(() => {
YAML.defaultOptions.version = origVersion
})

test('undefined', () => {
expect(YAML.stringify()).toBeUndefined()
expect(YAML.stringify(undefined, { version })).toBeUndefined()
})

test('null', () => {
expect(YAML.stringify(null)).toBe('null\n')
expect(YAML.stringify(null, { version })).toBe('null\n')
})

describe('boolean', () => {
test('true', () => {
expect(YAML.stringify(true)).toBe('true\n')
expect(YAML.stringify(true, { version })).toBe('true\n')
})
test('false', () => {
expect(YAML.stringify(false)).toBe('false\n')
expect(YAML.stringify(false, { version })).toBe('false\n')
})
})

describe('number', () => {
test('integer', () => {
expect(YAML.stringify(3)).toBe('3\n')
expect(YAML.stringify(3, { version })).toBe('3\n')
})
test('float', () => {
expect(YAML.stringify(3.141)).toBe('3.141\n')
expect(YAML.stringify(3.141, { version })).toBe('3.141\n')
})
test('zero', () => {
expect(YAML.stringify(0)).toBe('0\n')
expect(YAML.stringify(0, { version })).toBe('0\n')
})
test('NaN', () => {
expect(YAML.stringify(NaN)).toBe('.nan\n')
expect(YAML.stringify(NaN, { version })).toBe('.nan\n')
})

test('float with trailing zeros', () => {
const doc = new YAML.Document(3)
const doc = new YAML.Document(3, { version })
doc.contents.minFractionDigits = 2
expect(String(doc)).toBe('3.00\n')
})
test('scientific float ignores minFractionDigits', () => {
const doc = new YAML.Document(3)
const doc = new YAML.Document(3, { version })
doc.contents.format = 'EXP'
doc.contents.minFractionDigits = 2
expect(String(doc)).toBe('3e+0\n')
})

test('integer with HEX format', () => {
const doc = new YAML.Document(42)
const doc = new YAML.Document(42, { version })
doc.contents.format = 'HEX'
expect(String(doc)).toBe('0x2a\n')
})
test('float with HEX format', () => {
const doc = new YAML.Document(4.2)
const doc = new YAML.Document(4.2, { version })
doc.contents.format = 'HEX'
expect(String(doc)).toBe('4.2\n')
})
test('negative integer with HEX format', () => {
const doc = new YAML.Document(-42)
const doc = new YAML.Document(-42, { version })
doc.contents.format = 'HEX'
const exp = version === '1.2' ? '-42\n' : '-0x2a\n'
expect(String(doc)).toBe(exp)
})

test('BigInt', () => {
expect(YAML.stringify(BigInt('-42'))).toBe('-42\n')
expect(YAML.stringify(BigInt('-42'), { version })).toBe('-42\n')
})
test('BigInt with HEX format', () => {
const doc = new YAML.Document(BigInt('42'))
const doc = new YAML.Document(BigInt('42'), { version })
doc.contents.format = 'HEX'
expect(String(doc)).toBe('0x2a\n')
})
test('BigInt with OCT format', () => {
const doc = new YAML.Document(BigInt('42'))
const doc = new YAML.Document(BigInt('42'), { version })
doc.contents.format = 'OCT'
const exp = version === '1.2' ? '0o52\n' : '052\n'
expect(String(doc)).toBe(exp)
})
test('negative BigInt with OCT format', () => {
const doc = new YAML.Document(BigInt('-42'))
const doc = new YAML.Document(BigInt('-42'), { version })
doc.contents.format = 'OCT'
const exp = version === '1.2' ? '-42\n' : '-052\n'
expect(String(doc)).toBe(exp)
})
})

describe('string', () => {
const foldOptions = { lineWidth: 20, minContentWidth: 0 }
const opt = { lineWidth: 20, minContentWidth: 0, version }

test('plain', () => {
expect(YAML.stringify('STR', foldOptions)).toBe('STR\n')
expect(YAML.stringify('STR', opt)).toBe('STR\n')
})
test('double-quoted', () => {
expect(YAML.stringify('"x"', foldOptions)).toBe('\'"x"\'\n')
expect(YAML.stringify('"x"', opt)).toBe('\'"x"\'\n')
})
test('single-quoted', () => {
expect(YAML.stringify("'x'", foldOptions)).toBe('"\'x\'"\n')
expect(YAML.stringify("'x'", opt)).toBe('"\'x\'"\n')
})
test('escaped', () => {
expect(YAML.stringify('null: \u0000', foldOptions)).toBe(
'"null: \\0"\n'
)
expect(YAML.stringify('null: \u0000', opt)).toBe('"null: \\0"\n')
})
test('short multiline', () => {
expect(YAML.stringify('blah\nblah\nblah', foldOptions)).toBe(
expect(YAML.stringify('blah\nblah\nblah', opt)).toBe(
'|-\nblah\nblah\nblah\n'
)
})
test('long multiline', () => {
expect(
YAML.stringify(
'blah blah\nblah blah blah blah blah blah blah blah blah blah\n',
foldOptions
opt
)
).toBe(`>
blah blah
Expand All @@ -139,37 +128,37 @@ blah blah\n`)

test('long line in map', () => {
const foo = 'fuzz'.repeat(16)
const doc = new YAML.Document({ foo })
const doc = new YAML.Document({ foo }, version)
for (const node of doc.contents.items)
node.value.type = Type.QUOTE_DOUBLE
expect(
doc
.toString(foldOptions)
.toString(opt)
.split('\n')
.map(line => line.length)
).toMatchObject([20, 20, 20, 20, 0])
})

test('long line in sequence', () => {
const foo = 'fuzz'.repeat(16)
const doc = new YAML.Document([foo])
const doc = new YAML.Document([foo], version)
for (const node of doc.contents.items) node.type = Type.QUOTE_DOUBLE
expect(
doc
.toString(foldOptions)
.toString(opt)
.split('\n')
.map(line => line.length)
).toMatchObject([20, 20, 20, 17, 0])
})

test('long line in sequence in map', () => {
const foo = 'fuzz'.repeat(16)
const doc = new YAML.Document({ foo: [foo] })
const doc = new YAML.Document({ foo: [foo] }, version)
const seq = doc.contents.items[0].value
for (const node of seq.items) node.type = Type.QUOTE_DOUBLE
expect(
doc
.toString(foldOptions)
.toString(opt)
.split('\n')
.map(line => line.length)
).toMatchObject([4, 20, 20, 20, 20, 10, 0])
Expand Down

0 comments on commit 24383fc

Please sign in to comment.