/
compose-node.ts
110 lines (104 loc) · 3.04 KB
/
compose-node.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
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
107
108
109
110
import type { Directives } from '../doc/directives.js'
import { Alias } from '../nodes/Alias.js'
import type { ParsedNode } from '../nodes/Node.js'
import type { ParseOptions } from '../options.js'
import type { FlowScalar, Token } from '../parse/cst.js'
import type { Schema } from '../schema/Schema.js'
import { composeCollection } from './compose-collection.js'
import { composeScalar } from './compose-scalar.js'
import type { ComposeErrorHandler } from './composer.js'
import { resolveEnd } from './resolve-end.js'
import { emptyScalarPosition } from './util-empty-scalar-position.js'
export interface ComposeContext {
directives: Directives
options: Readonly<Required<Omit<ParseOptions, 'lineCounter'>>>
schema: Readonly<Schema>
}
export interface Props {
spaceBefore: boolean
comment: string
anchor: string
tagName: string
}
const CN = { composeNode, composeEmptyNode }
export type ComposeNode = typeof CN
export function composeNode(
ctx: ComposeContext,
token: Token,
props: Props,
onError: ComposeErrorHandler
) {
const { spaceBefore, comment, anchor, tagName } = props
let node: ParsedNode
switch (token.type) {
case 'alias':
node = composeAlias(ctx, token, onError)
if (anchor || tagName)
onError(
token.offset,
'ALIAS_PROPS',
'An alias node must not specify any properties'
)
break
case 'scalar':
case 'single-quoted-scalar':
case 'double-quoted-scalar':
case 'block-scalar':
node = composeScalar(ctx, token, tagName, onError)
if (anchor) {
node.anchor = anchor
}
break
case 'block-map':
case 'block-seq':
case 'flow-collection':
node = composeCollection(CN, ctx, token, tagName, onError)
if (anchor) {
node.anchor = anchor
}
break
default:
console.log(token)
throw new Error(`Unsupporten token type: ${(token as any).type}`)
}
if (spaceBefore) node.spaceBefore = true
if (comment) {
if (token.type === 'scalar' && token.source === '') node.comment = comment
else node.commentBefore = comment
}
return node
}
export function composeEmptyNode(
ctx: ComposeContext,
offset: number,
before: Token[] | undefined,
pos: number | null,
{ spaceBefore, comment, anchor, tagName }: Props,
onError: ComposeErrorHandler
) {
const token: FlowScalar = {
type: 'scalar',
offset: emptyScalarPosition(offset, before, pos),
indent: -1,
source: ''
}
const node = composeScalar(ctx, token, tagName, onError)
if (anchor) {
node.anchor = anchor
}
if (spaceBefore) node.spaceBefore = true
if (comment) node.comment = comment
return node
}
function composeAlias(
{ options }: ComposeContext,
{ offset, source, end }: FlowScalar,
onError: ComposeErrorHandler
) {
const alias = new Alias(source.substring(1))
const valueEnd = offset + source.length
const re = resolveEnd(end, valueEnd, options.strict, onError)
alias.range = [offset, valueEnd, re.offset]
if (re.comment) alias.comment = re.comment
return alias as Alias.Parsed
}