1 | 'use strict';
|
---|
2 |
|
---|
3 | var Collection = require('../nodes/Collection.js');
|
---|
4 | var identity = require('../nodes/identity.js');
|
---|
5 | var stringify = require('./stringify.js');
|
---|
6 | var stringifyComment = require('./stringifyComment.js');
|
---|
7 |
|
---|
8 | function stringifyCollection(collection, ctx, options) {
|
---|
9 | const flow = ctx.inFlow ?? collection.flow;
|
---|
10 | const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
---|
11 | return stringify(collection, ctx, options);
|
---|
12 | }
|
---|
13 | function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
---|
14 | const { indent, options: { commentString } } = ctx;
|
---|
15 | const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
|
---|
16 | let chompKeep = false; // flag for the preceding node's status
|
---|
17 | const lines = [];
|
---|
18 | for (let i = 0; i < items.length; ++i) {
|
---|
19 | const item = items[i];
|
---|
20 | let comment = null;
|
---|
21 | if (identity.isNode(item)) {
|
---|
22 | if (!chompKeep && item.spaceBefore)
|
---|
23 | lines.push('');
|
---|
24 | addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
|
---|
25 | if (item.comment)
|
---|
26 | comment = item.comment;
|
---|
27 | }
|
---|
28 | else if (identity.isPair(item)) {
|
---|
29 | const ik = identity.isNode(item.key) ? item.key : null;
|
---|
30 | if (ik) {
|
---|
31 | if (!chompKeep && ik.spaceBefore)
|
---|
32 | lines.push('');
|
---|
33 | addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
|
---|
34 | }
|
---|
35 | }
|
---|
36 | chompKeep = false;
|
---|
37 | let str = stringify.stringify(item, itemCtx, () => (comment = null), () => (chompKeep = true));
|
---|
38 | if (comment)
|
---|
39 | str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
|
---|
40 | if (chompKeep && comment)
|
---|
41 | chompKeep = false;
|
---|
42 | lines.push(blockItemPrefix + str);
|
---|
43 | }
|
---|
44 | let str;
|
---|
45 | if (lines.length === 0) {
|
---|
46 | str = flowChars.start + flowChars.end;
|
---|
47 | }
|
---|
48 | else {
|
---|
49 | str = lines[0];
|
---|
50 | for (let i = 1; i < lines.length; ++i) {
|
---|
51 | const line = lines[i];
|
---|
52 | str += line ? `\n${indent}${line}` : '\n';
|
---|
53 | }
|
---|
54 | }
|
---|
55 | if (comment) {
|
---|
56 | str += '\n' + stringifyComment.indentComment(commentString(comment), indent);
|
---|
57 | if (onComment)
|
---|
58 | onComment();
|
---|
59 | }
|
---|
60 | else if (chompKeep && onChompKeep)
|
---|
61 | onChompKeep();
|
---|
62 | return str;
|
---|
63 | }
|
---|
64 | function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemIndent, onComment }) {
|
---|
65 | const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
|
---|
66 | itemIndent += indentStep;
|
---|
67 | const itemCtx = Object.assign({}, ctx, {
|
---|
68 | indent: itemIndent,
|
---|
69 | inFlow: true,
|
---|
70 | type: null
|
---|
71 | });
|
---|
72 | let reqNewline = false;
|
---|
73 | let linesAtValue = 0;
|
---|
74 | const lines = [];
|
---|
75 | for (let i = 0; i < items.length; ++i) {
|
---|
76 | const item = items[i];
|
---|
77 | let comment = null;
|
---|
78 | if (identity.isNode(item)) {
|
---|
79 | if (item.spaceBefore)
|
---|
80 | lines.push('');
|
---|
81 | addCommentBefore(ctx, lines, item.commentBefore, false);
|
---|
82 | if (item.comment)
|
---|
83 | comment = item.comment;
|
---|
84 | }
|
---|
85 | else if (identity.isPair(item)) {
|
---|
86 | const ik = identity.isNode(item.key) ? item.key : null;
|
---|
87 | if (ik) {
|
---|
88 | if (ik.spaceBefore)
|
---|
89 | lines.push('');
|
---|
90 | addCommentBefore(ctx, lines, ik.commentBefore, false);
|
---|
91 | if (ik.comment)
|
---|
92 | reqNewline = true;
|
---|
93 | }
|
---|
94 | const iv = identity.isNode(item.value) ? item.value : null;
|
---|
95 | if (iv) {
|
---|
96 | if (iv.comment)
|
---|
97 | comment = iv.comment;
|
---|
98 | if (iv.commentBefore)
|
---|
99 | reqNewline = true;
|
---|
100 | }
|
---|
101 | else if (item.value == null && ik?.comment) {
|
---|
102 | comment = ik.comment;
|
---|
103 | }
|
---|
104 | }
|
---|
105 | if (comment)
|
---|
106 | reqNewline = true;
|
---|
107 | let str = stringify.stringify(item, itemCtx, () => (comment = null));
|
---|
108 | if (i < items.length - 1)
|
---|
109 | str += ',';
|
---|
110 | if (comment)
|
---|
111 | str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
|
---|
112 | if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
|
---|
113 | reqNewline = true;
|
---|
114 | lines.push(str);
|
---|
115 | linesAtValue = lines.length;
|
---|
116 | }
|
---|
117 | let str;
|
---|
118 | const { start, end } = flowChars;
|
---|
119 | if (lines.length === 0) {
|
---|
120 | str = start + end;
|
---|
121 | }
|
---|
122 | else {
|
---|
123 | if (!reqNewline) {
|
---|
124 | const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
|
---|
125 | reqNewline = len > Collection.Collection.maxFlowStringSingleLineLength;
|
---|
126 | }
|
---|
127 | if (reqNewline) {
|
---|
128 | str = start;
|
---|
129 | for (const line of lines)
|
---|
130 | str += line ? `\n${indentStep}${indent}${line}` : '\n';
|
---|
131 | str += `\n${indent}${end}`;
|
---|
132 | }
|
---|
133 | else {
|
---|
134 | str = `${start}${fcPadding}${lines.join(' ')}${fcPadding}${end}`;
|
---|
135 | }
|
---|
136 | }
|
---|
137 | if (comment) {
|
---|
138 | str += stringifyComment.lineComment(str, indent, commentString(comment));
|
---|
139 | if (onComment)
|
---|
140 | onComment();
|
---|
141 | }
|
---|
142 | return str;
|
---|
143 | }
|
---|
144 | function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
|
---|
145 | if (comment && chompKeep)
|
---|
146 | comment = comment.replace(/^\n+/, '');
|
---|
147 | if (comment) {
|
---|
148 | const ic = stringifyComment.indentComment(commentString(comment), indent);
|
---|
149 | lines.push(ic.trimStart()); // Avoid double indent on first line
|
---|
150 | }
|
---|
151 | }
|
---|
152 |
|
---|
153 | exports.stringifyCollection = stringifyCollection;
|
---|