-
-
Notifications
You must be signed in to change notification settings - Fork 101
/
Seq.js
106 lines (101 loc) · 3.49 KB
/
Seq.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { Type } from '../ast/Node'
import { YAMLSyntaxError } from '../errors'
import Collection, { toJSON } from './Collection'
import Pair from './Pair'
export default class YAMLSeq extends Collection {
constructor (doc, node) {
super(doc)
node.resolved = this
if (node.type === Type.FLOW_SEQ) {
this.resolveFlowSeqItems(doc, node)
} else {
this.resolveBlockSeqItems(doc, node)
}
}
resolveBlockSeqItems (doc, seq) {
for (let i = 0; i < seq.items.length; ++i) {
const item = seq.items[i]
switch (item.type) {
case Type.COMMENT:
this.addComment(item.comment)
break
case Type.SEQ_ITEM:
this.items.push(doc.resolveNode(item.node))
if (item.hasProps) doc.errors.push(new YAMLSyntaxError(item,
'Sequence items cannot have tags or anchors before the - indicator'))
break
default:
doc.errors.push(new YAMLSyntaxError(item,
`Unexpected ${item.type} node in sequence`))
}
}
}
resolveFlowSeqItems (doc, seq) {
let explicitKey = false
let key = undefined
let keyStart = null
let next = '['
for (let i = 0; i < seq.items.length; ++i) {
const item = seq.items[i]
if (typeof item === 'string') {
if (item !== ':' && (explicitKey || key !== undefined)) {
if (explicitKey && key === undefined) key = null
this.items.push(new Pair(key))
explicitKey = false
key = undefined
keyStart = null
}
if (item === next) {
next = null
} else if (!next && item === '?') {
explicitKey = true
} else if (next !== '[' && item === ':' && key === undefined) {
if (next === ',') {
key = this.items.pop()
if (key instanceof Pair) doc.errors.push(new YAMLSyntaxError(item,
'Chaining flow sequence pairs is invalid (e.g. [ a : b : c ])'))
if (!explicitKey) Collection.checkKeyLength(doc, seq, i, key, keyStart)
} else {
key = null
}
keyStart = null
explicitKey = false // TODO: add error for non-explicit multiline plain key
next = null
} else if (next === '[' || item !== ']' || i < seq.items.length - 1) {
doc.errors.push(new YAMLSyntaxError(seq,
`Flow sequence contains an unexpected ${item}`))
}
} else if (item.type === Type.COMMENT) {
this.addComment(item.comment)
} else {
if (next) doc.errors.push(new YAMLSyntaxError(item,
`Expected a ${next} here in flow sequence`))
const value = doc.resolveNode(item)
if (key === undefined) {
this.items.push(value)
} else {
this.items.push(new Pair(key, value))
key = undefined
}
keyStart = item.range.start
next = ','
}
}
if (seq.items[seq.items.length - 1] !== ']') doc.errors.push(new YAMLSyntaxError(seq,
'Expected flow sequence to end with ]'))
if (key !== undefined) this.items.push(new Pair(key))
}
toJSON () {
return this.items.map(toJSON)
}
toString (indent, inFlow) {
const { tags } = this.doc
const options = { implicitKey: false, indent: indent + ' ', inFlow, type: null }
const items = this.items.map(node => tags.stringify(node, options))
if (inFlow || items.length === 0) {
return `[ ${items.join(', ')} ]`
} else {
return items.map(item => `- ${item}`).join(`\n${indent}`)
}
}
}