source: node_modules/yaml/dist/compose/resolve-flow-collection.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[d24f17c]1'use strict';
2
3var identity = require('../nodes/identity.js');
4var Pair = require('../nodes/Pair.js');
5var YAMLMap = require('../nodes/YAMLMap.js');
6var YAMLSeq = require('../nodes/YAMLSeq.js');
7var resolveEnd = require('./resolve-end.js');
8var resolveProps = require('./resolve-props.js');
9var utilContainsNewline = require('./util-contains-newline.js');
10var utilMapIncludes = require('./util-map-includes.js');
11
12const blockMsg = 'Block collections are not allowed within flow collections';
13const isBlock = (token) => token && (token.type === 'block-map' || token.type === 'block-seq');
14function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError, tag) {
15 const isMap = fc.start.source === '{';
16 const fcName = isMap ? 'flow map' : 'flow sequence';
17 const NodeClass = (tag?.nodeClass ?? (isMap ? YAMLMap.YAMLMap : YAMLSeq.YAMLSeq));
18 const coll = new NodeClass(ctx.schema);
19 coll.flow = true;
20 const atRoot = ctx.atRoot;
21 if (atRoot)
22 ctx.atRoot = false;
23 let offset = fc.offset + fc.start.source.length;
24 for (let i = 0; i < fc.items.length; ++i) {
25 const collItem = fc.items[i];
26 const { start, key, sep, value } = collItem;
27 const props = resolveProps.resolveProps(start, {
28 flow: fcName,
29 indicator: 'explicit-key-ind',
30 next: key ?? sep?.[0],
31 offset,
32 onError,
33 startOnNewline: false
34 });
35 if (!props.found) {
36 if (!props.anchor && !props.tag && !sep && !value) {
37 if (i === 0 && props.comma)
38 onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
39 else if (i < fc.items.length - 1)
40 onError(props.start, 'UNEXPECTED_TOKEN', `Unexpected empty item in ${fcName}`);
41 if (props.comment) {
42 if (coll.comment)
43 coll.comment += '\n' + props.comment;
44 else
45 coll.comment = props.comment;
46 }
47 offset = props.end;
48 continue;
49 }
50 if (!isMap && ctx.options.strict && utilContainsNewline.containsNewline(key))
51 onError(key, // checked by containsNewline()
52 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
53 }
54 if (i === 0) {
55 if (props.comma)
56 onError(props.comma, 'UNEXPECTED_TOKEN', `Unexpected , in ${fcName}`);
57 }
58 else {
59 if (!props.comma)
60 onError(props.start, 'MISSING_CHAR', `Missing , between ${fcName} items`);
61 if (props.comment) {
62 let prevItemComment = '';
63 loop: for (const st of start) {
64 switch (st.type) {
65 case 'comma':
66 case 'space':
67 break;
68 case 'comment':
69 prevItemComment = st.source.substring(1);
70 break loop;
71 default:
72 break loop;
73 }
74 }
75 if (prevItemComment) {
76 let prev = coll.items[coll.items.length - 1];
77 if (identity.isPair(prev))
78 prev = prev.value ?? prev.key;
79 if (prev.comment)
80 prev.comment += '\n' + prevItemComment;
81 else
82 prev.comment = prevItemComment;
83 props.comment = props.comment.substring(prevItemComment.length + 1);
84 }
85 }
86 }
87 if (!isMap && !sep && !props.found) {
88 // item is a value in a seq
89 // → key & sep are empty, start does not include ? or :
90 const valueNode = value
91 ? composeNode(ctx, value, props, onError)
92 : composeEmptyNode(ctx, props.end, sep, null, props, onError);
93 coll.items.push(valueNode);
94 offset = valueNode.range[2];
95 if (isBlock(value))
96 onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
97 }
98 else {
99 // item is a key+value pair
100 // key value
101 const keyStart = props.end;
102 const keyNode = key
103 ? composeNode(ctx, key, props, onError)
104 : composeEmptyNode(ctx, keyStart, start, null, props, onError);
105 if (isBlock(key))
106 onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
107 // value properties
108 const valueProps = resolveProps.resolveProps(sep ?? [], {
109 flow: fcName,
110 indicator: 'map-value-ind',
111 next: value,
112 offset: keyNode.range[2],
113 onError,
114 startOnNewline: false
115 });
116 if (valueProps.found) {
117 if (!isMap && !props.found && ctx.options.strict) {
118 if (sep)
119 for (const st of sep) {
120 if (st === valueProps.found)
121 break;
122 if (st.type === 'newline') {
123 onError(st, 'MULTILINE_IMPLICIT_KEY', 'Implicit keys of flow sequence pairs need to be on a single line');
124 break;
125 }
126 }
127 if (props.start < valueProps.found.offset - 1024)
128 onError(valueProps.found, 'KEY_OVER_1024_CHARS', 'The : indicator must be at most 1024 chars after the start of an implicit flow sequence key');
129 }
130 }
131 else if (value) {
132 if ('source' in value && value.source && value.source[0] === ':')
133 onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
134 else
135 onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
136 }
137 // value value
138 const valueNode = value
139 ? composeNode(ctx, value, valueProps, onError)
140 : valueProps.found
141 ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError)
142 : null;
143 if (valueNode) {
144 if (isBlock(value))
145 onError(valueNode.range, 'BLOCK_IN_FLOW', blockMsg);
146 }
147 else if (valueProps.comment) {
148 if (keyNode.comment)
149 keyNode.comment += '\n' + valueProps.comment;
150 else
151 keyNode.comment = valueProps.comment;
152 }
153 const pair = new Pair.Pair(keyNode, valueNode);
154 if (ctx.options.keepSourceTokens)
155 pair.srcToken = collItem;
156 if (isMap) {
157 const map = coll;
158 if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
159 onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
160 map.items.push(pair);
161 }
162 else {
163 const map = new YAMLMap.YAMLMap(ctx.schema);
164 map.flow = true;
165 map.items.push(pair);
166 coll.items.push(map);
167 }
168 offset = valueNode ? valueNode.range[2] : valueProps.end;
169 }
170 }
171 const expectedEnd = isMap ? '}' : ']';
172 const [ce, ...ee] = fc.end;
173 let cePos = offset;
174 if (ce && ce.source === expectedEnd)
175 cePos = ce.offset + ce.source.length;
176 else {
177 const name = fcName[0].toUpperCase() + fcName.substring(1);
178 const msg = atRoot
179 ? `${name} must end with a ${expectedEnd}`
180 : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
181 onError(offset, atRoot ? 'MISSING_CHAR' : 'BAD_INDENT', msg);
182 if (ce && ce.source.length !== 1)
183 ee.unshift(ce);
184 }
185 if (ee.length > 0) {
186 const end = resolveEnd.resolveEnd(ee, cePos, ctx.options.strict, onError);
187 if (end.comment) {
188 if (coll.comment)
189 coll.comment += '\n' + end.comment;
190 else
191 coll.comment = end.comment;
192 }
193 coll.range = [fc.offset, cePos, end.offset];
194 }
195 else {
196 coll.range = [fc.offset, cePos, cePos];
197 }
198 return coll;
199}
200
201exports.resolveFlowCollection = resolveFlowCollection;
Note: See TracBrowser for help on using the repository browser.