1 | 'use strict';
|
2 |
|
3 | var resolveBlockScalar = require('../compose/resolve-block-scalar.js');
|
4 | var resolveFlowScalar = require('../compose/resolve-flow-scalar.js');
|
5 | var errors = require('../errors.js');
|
6 | var stringifyString = require('../stringify/stringifyString.js');
|
7 |
|
8 | function resolveAsScalar(token, strict = true, onError) {
|
9 | if (token) {
|
10 | const _onError = (pos, code, message) => {
|
11 | const offset = typeof pos === 'number' ? pos : Array.isArray(pos) ? pos[0] : pos.offset;
|
12 | if (onError)
|
13 | onError(offset, code, message);
|
14 | else
|
15 | throw new errors.YAMLParseError([offset, offset + 1], code, message);
|
16 | };
|
17 | switch (token.type) {
|
18 | case 'scalar':
|
19 | case 'single-quoted-scalar':
|
20 | case 'double-quoted-scalar':
|
21 | return resolveFlowScalar.resolveFlowScalar(token, strict, _onError);
|
22 | case 'block-scalar':
|
23 | return resolveBlockScalar.resolveBlockScalar({ options: { strict } }, token, _onError);
|
24 | }
|
25 | }
|
26 | return null;
|
27 | }
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | function createScalarToken(value, context) {
|
43 | const { implicitKey = false, indent, inFlow = false, offset = -1, type = 'PLAIN' } = context;
|
44 | const source = stringifyString.stringifyString({ type, value }, {
|
45 | implicitKey,
|
46 | indent: indent > 0 ? ' '.repeat(indent) : '',
|
47 | inFlow,
|
48 | options: { blockQuote: true, lineWidth: -1 }
|
49 | });
|
50 | const end = context.end ?? [
|
51 | { type: 'newline', offset: -1, indent, source: '\n' }
|
52 | ];
|
53 | switch (source[0]) {
|
54 | case '|':
|
55 | case '>': {
|
56 | const he = source.indexOf('\n');
|
57 | const head = source.substring(0, he);
|
58 | const body = source.substring(he + 1) + '\n';
|
59 | const props = [
|
60 | { type: 'block-scalar-header', offset, indent, source: head }
|
61 | ];
|
62 | if (!addEndtoBlockProps(props, end))
|
63 | props.push({ type: 'newline', offset: -1, indent, source: '\n' });
|
64 | return { type: 'block-scalar', offset, indent, props, source: body };
|
65 | }
|
66 | case '"':
|
67 | return { type: 'double-quoted-scalar', offset, indent, source, end };
|
68 | case "'":
|
69 | return { type: 'single-quoted-scalar', offset, indent, source, end };
|
70 | default:
|
71 | return { type: 'scalar', offset, indent, source, end };
|
72 | }
|
73 | }
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 | function setScalarValue(token, value, context = {}) {
|
91 | let { afterKey = false, implicitKey = false, inFlow = false, type } = context;
|
92 | let indent = 'indent' in token ? token.indent : null;
|
93 | if (afterKey && typeof indent === 'number')
|
94 | indent += 2;
|
95 | if (!type)
|
96 | switch (token.type) {
|
97 | case 'single-quoted-scalar':
|
98 | type = 'QUOTE_SINGLE';
|
99 | break;
|
100 | case 'double-quoted-scalar':
|
101 | type = 'QUOTE_DOUBLE';
|
102 | break;
|
103 | case 'block-scalar': {
|
104 | const header = token.props[0];
|
105 | if (header.type !== 'block-scalar-header')
|
106 | throw new Error('Invalid block scalar header');
|
107 | type = header.source[0] === '>' ? 'BLOCK_FOLDED' : 'BLOCK_LITERAL';
|
108 | break;
|
109 | }
|
110 | default:
|
111 | type = 'PLAIN';
|
112 | }
|
113 | const source = stringifyString.stringifyString({ type, value }, {
|
114 | implicitKey: implicitKey || indent === null,
|
115 | indent: indent !== null && indent > 0 ? ' '.repeat(indent) : '',
|
116 | inFlow,
|
117 | options: { blockQuote: true, lineWidth: -1 }
|
118 | });
|
119 | switch (source[0]) {
|
120 | case '|':
|
121 | case '>':
|
122 | setBlockScalarValue(token, source);
|
123 | break;
|
124 | case '"':
|
125 | setFlowScalarValue(token, source, 'double-quoted-scalar');
|
126 | break;
|
127 | case "'":
|
128 | setFlowScalarValue(token, source, 'single-quoted-scalar');
|
129 | break;
|
130 | default:
|
131 | setFlowScalarValue(token, source, 'scalar');
|
132 | }
|
133 | }
|
134 | function setBlockScalarValue(token, source) {
|
135 | const he = source.indexOf('\n');
|
136 | const head = source.substring(0, he);
|
137 | const body = source.substring(he + 1) + '\n';
|
138 | if (token.type === 'block-scalar') {
|
139 | const header = token.props[0];
|
140 | if (header.type !== 'block-scalar-header')
|
141 | throw new Error('Invalid block scalar header');
|
142 | header.source = head;
|
143 | token.source = body;
|
144 | }
|
145 | else {
|
146 | const { offset } = token;
|
147 | const indent = 'indent' in token ? token.indent : -1;
|
148 | const props = [
|
149 | { type: 'block-scalar-header', offset, indent, source: head }
|
150 | ];
|
151 | if (!addEndtoBlockProps(props, 'end' in token ? token.end : undefined))
|
152 | props.push({ type: 'newline', offset: -1, indent, source: '\n' });
|
153 | for (const key of Object.keys(token))
|
154 | if (key !== 'type' && key !== 'offset')
|
155 | delete token[key];
|
156 | Object.assign(token, { type: 'block-scalar', indent, props, source: body });
|
157 | }
|
158 | }
|
159 |
|
160 | function addEndtoBlockProps(props, end) {
|
161 | if (end)
|
162 | for (const st of end)
|
163 | switch (st.type) {
|
164 | case 'space':
|
165 | case 'comment':
|
166 | props.push(st);
|
167 | break;
|
168 | case 'newline':
|
169 | props.push(st);
|
170 | return true;
|
171 | }
|
172 | return false;
|
173 | }
|
174 | function setFlowScalarValue(token, source, type) {
|
175 | switch (token.type) {
|
176 | case 'scalar':
|
177 | case 'double-quoted-scalar':
|
178 | case 'single-quoted-scalar':
|
179 | token.type = type;
|
180 | token.source = source;
|
181 | break;
|
182 | case 'block-scalar': {
|
183 | const end = token.props.slice(1);
|
184 | let oa = source.length;
|
185 | if (token.props[0].type === 'block-scalar-header')
|
186 | oa -= token.props[0].source.length;
|
187 | for (const tok of end)
|
188 | tok.offset += oa;
|
189 | delete token.props;
|
190 | Object.assign(token, { type, source, end });
|
191 | break;
|
192 | }
|
193 | case 'block-map':
|
194 | case 'block-seq': {
|
195 | const offset = token.offset + source.length;
|
196 | const nl = { type: 'newline', offset, indent: token.indent, source: '\n' };
|
197 | delete token.items;
|
198 | Object.assign(token, { type, source, end: [nl] });
|
199 | break;
|
200 | }
|
201 | default: {
|
202 | const indent = 'indent' in token ? token.indent : -1;
|
203 | const end = 'end' in token && Array.isArray(token.end)
|
204 | ? token.end.filter(st => st.type === 'space' ||
|
205 | st.type === 'comment' ||
|
206 | st.type === 'newline')
|
207 | : [];
|
208 | for (const key of Object.keys(token))
|
209 | if (key !== 'type' && key !== 'offset')
|
210 | delete token[key];
|
211 | Object.assign(token, { type, indent, source, end });
|
212 | }
|
213 | }
|
214 | }
|
215 |
|
216 | exports.createScalarToken = createScalarToken;
|
217 | exports.resolveAsScalar = resolveAsScalar;
|
218 | exports.setScalarValue = setScalarValue;
|