/
compose-collection.ts
78 lines (73 loc) · 2.31 KB
/
compose-collection.ts
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
import { isMap, isNode, ParsedNode } from '../nodes/Node.js'
import { Scalar } from '../nodes/Scalar.js'
import type { YAMLMap } from '../nodes/YAMLMap.js'
import type { YAMLSeq } from '../nodes/YAMLSeq.js'
import type { BlockMap, BlockSequence, FlowCollection } from '../parse/cst.js'
import { CollectionTag } from '../schema/types.js'
import type { ComposeContext, ComposeNode } from './compose-node.js'
import type { ComposeErrorHandler } from './composer.js'
import { resolveBlockMap } from './resolve-block-map.js'
import { resolveBlockSeq } from './resolve-block-seq.js'
import { resolveFlowCollection } from './resolve-flow-collection.js'
export function composeCollection(
CN: ComposeNode,
ctx: ComposeContext,
token: BlockMap | BlockSequence | FlowCollection,
tagName: string | null,
onError: ComposeErrorHandler
) {
let coll: YAMLMap.Parsed | YAMLSeq.Parsed
switch (token.type) {
case 'block-map': {
coll = resolveBlockMap(CN, ctx, token, onError)
break
}
case 'block-seq': {
coll = resolveBlockSeq(CN, ctx, token, onError)
break
}
case 'flow-collection': {
coll = resolveFlowCollection(CN, ctx, token, onError)
break
}
}
if (!tagName) return coll
// Cast needed due to: https://github.com/Microsoft/TypeScript/issues/3841
const Coll = coll.constructor as typeof YAMLMap | typeof YAMLSeq
if (tagName === '!' || tagName === Coll.tagName) {
coll.tag = Coll.tagName
return coll
}
const expType = isMap(coll) ? 'map' : 'seq'
let tag = ctx.schema.tags.find(
t => t.collection === expType && t.tag === tagName
) as CollectionTag | undefined
if (!tag) {
const kt = ctx.schema.knownTags[tagName]
if (kt && kt.collection === expType) {
ctx.schema.tags.push(Object.assign({}, kt, { default: false }))
tag = kt
} else {
onError(
coll.range[0],
'TAG_RESOLVE_FAILED',
`Unresolved tag: ${tagName}`,
true
)
coll.tag = tagName
return coll
}
}
const res = tag.resolve(
coll,
msg => onError(coll.range[0], 'TAG_RESOLVE_FAILED', msg),
ctx.options
)
const node = isNode(res)
? (res as ParsedNode)
: (new Scalar(res) as Scalar.Parsed)
node.range = coll.range
node.tag = tagName
if (tag?.format) (node as Scalar).format = tag.format
return node
}