Skip to content

Commit

Permalink
Check custom tag classes when stringifying; add optional createNode(v…
Browse files Browse the repository at this point in the history
…alue) to tag objects (Fixes #63)
  • Loading branch information
eemeli committed Dec 25, 2018
1 parent 9a97670 commit bcb8d9c
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 53 deletions.
38 changes: 24 additions & 14 deletions __tests__/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,33 +335,43 @@ english: null
null: null key\n`)
})

test('!!timestamp', () => {
const src = `%YAML 1.1
describe('!!timestamp', () => {
test('parse & document', () => {
const src = `%YAML 1.1
---
canonical: 2001-12-15T02:59:43.1Z
valid iso8601: 2001-12-14t21:59:43.10-05:00
space separated: 2001-12-14 21:59:43.10 -5
no time zone (Z): 2001-12-15 2:59:43.10
date (00:00:00Z): 2002-12-14`

const doc = YAML.parseDocument(src, { keepBlobsInJSON: false })
doc.contents.items.forEach(item => {
expect(item.value.value).toBeInstanceOf(Date)
})
expect(doc.toJSON()).toMatchObject({
canonical: '2001-12-15T02:59:43.100Z',
'valid iso8601': '2001-12-15T02:59:43.100Z',
'space separated': '2001-12-15T02:59:43.100Z',
'no time zone (Z)': '2001-12-15T02:59:43.100Z',
'date (00:00:00Z)': '2002-12-14T00:00:00.000Z'
})
expect(String(doc)).toBe(`%YAML 1.1
const doc = YAML.parseDocument(src, { keepBlobsInJSON: false })
doc.contents.items.forEach(item => {
expect(item.value.value).toBeInstanceOf(Date)
})
expect(doc.toJSON()).toMatchObject({
canonical: '2001-12-15T02:59:43.100Z',
'valid iso8601': '2001-12-15T02:59:43.100Z',
'space separated': '2001-12-15T02:59:43.100Z',
'no time zone (Z)': '2001-12-15T02:59:43.100Z',
'date (00:00:00Z)': '2002-12-14T00:00:00.000Z'
})
expect(String(doc)).toBe(`%YAML 1.1
---
canonical: 2001-12-15T02:59:43.100Z
valid iso8601: 2001-12-15T02:59:43.100Z
space separated: 2001-12-15T02:59:43.100Z
no time zone (Z): 2001-12-15T02:59:43.100Z
date (00:00:00Z): 2002-12-14\n`)
})

test('stringify', () => {
const date = new Date('2018-12-22T08:02:52Z')
const str = YAML.stringify(date) // stringified as !!str
expect(str).toBe('2018-12-22T08:02:52.000Z\n')
const str2 = YAML.stringify(date, { version: '1.1' })
expect(str2).toBe('2018-12-22T08:02:52\n')
})
})
})

Expand Down
80 changes: 41 additions & 39 deletions src/schema/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,47 +124,39 @@ export default class Schema {
getTagObject(item) {
if (item instanceof Alias) return Alias
if (item.tag) {
let match = this.tags.find(
({ format, tag }) => tag === item.tag && format === item.format
)
if (!match) match = this.tags.find(({ tag }) => tag === item.tag)
if (match) return match
const match = this.tags.filter(t => t.tag === item.tag)
if (match.length > 0)
return match.find(t => t.format === item.format) || match[0]
}
if (item.value === null) {
const match = this.tags.find(t => t.class === null && !t.format)
if (!match) throw new Error('Tag not resolved for null value')
return match
} else {
let obj = item
if (item.hasOwnProperty('value')) {
switch (typeof item.value) {
case 'boolean':
obj = new Boolean()
break
case 'number':
obj = new Number()
break
case 'string':
obj = new String()
break
default:
obj = item.value
}
}
let match = this.tags.find(
t => t.class && obj instanceof t.class && t.format === item.format
)
if (!match) {
match = this.tags.find(
t => t.class && obj instanceof t.class && !t.format
)
}
if (!match) {
const name = obj && obj.constructor ? obj.constructor.name : typeof obj
throw new Error(`Tag not resolved for ${name} value`)
const tagObj = this.tags.find(t => t.class === null && !t.format)
if (!tagObj) throw new Error('Tag not resolved for null value')
return tagObj
}
let obj = item
if (item.hasOwnProperty('value')) {
switch (typeof item.value) {
case 'boolean':
obj = new Boolean()
break
case 'number':
obj = new Number()
break
case 'string':
obj = new String()
break
default:
obj = item.value
}
return match
}
const match = this.tags.filter(t => t.class && obj instanceof t.class)
const tagObj =
match.find(t => t.format === item.format) || match.find(t => !t.format)
if (!tagObj) {
const name = obj && obj.constructor ? obj.constructor.name : typeof obj
throw new Error(`Tag not resolved for ${name} value`)
}
return tagObj
}

// needs to be called before stringifier to allow for circular anchor refs
Expand All @@ -184,10 +176,20 @@ export default class Schema {
}

stringify(item, ctx, onComment) {
if (!(item instanceof Node)) item = createNode(item, true)
let tagObj
if (!(item instanceof Node)) {
tagObj = this.tags.find(
t => t.class && item instanceof t.class && !t.format
)
item = tagObj
? tagObj.createNode
? tagObj.createNode(item)
: new Scalar(item)
: createNode(item, true)
}
ctx.tags = this
if (item instanceof Pair) return item.toString(ctx, onComment)
const tagObj = this.getTagObject(item)
if (!tagObj) tagObj = this.getTagObject(item)
const props = this.stringifyProps(item, tagObj, ctx)
const stringify = tagObj.stringify || Schema.defaultStringify
const str = stringify(item, ctx, onComment)
Expand Down

0 comments on commit bcb8d9c

Please sign in to comment.