UNPKG

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