1 | 'use strict';
|
2 |
|
3 | var identity = require('../nodes/identity.js');
|
4 | var Scalar = require('../nodes/Scalar.js');
|
5 | var stringify = require('./stringify.js');
|
6 | var stringifyComment = require('./stringifyComment.js');
|
7 |
|
8 | function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
9 | const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
|
10 | let keyComment = (identity.isNode(key) && key.comment) || null;
|
11 | if (simpleKeys) {
|
12 | if (keyComment) {
|
13 | throw new Error('With simple keys, key nodes cannot have comments');
|
14 | }
|
15 | if (identity.isCollection(key) || (!identity.isNode(key) && typeof key === 'object')) {
|
16 | const msg = 'With simple keys, collection cannot be used as a key value';
|
17 | throw new Error(msg);
|
18 | }
|
19 | }
|
20 | let explicitKey = !simpleKeys &&
|
21 | (!key ||
|
22 | (keyComment && value == null && !ctx.inFlow) ||
|
23 | identity.isCollection(key) ||
|
24 | (identity.isScalar(key)
|
25 | ? key.type === Scalar.Scalar.BLOCK_FOLDED || key.type === Scalar.Scalar.BLOCK_LITERAL
|
26 | : typeof key === 'object'));
|
27 | ctx = Object.assign({}, ctx, {
|
28 | allNullValues: false,
|
29 | implicitKey: !explicitKey && (simpleKeys || !allNullValues),
|
30 | indent: indent + indentStep
|
31 | });
|
32 | let keyCommentDone = false;
|
33 | let chompKeep = false;
|
34 | let str = stringify.stringify(key, ctx, () => (keyCommentDone = true), () => (chompKeep = true));
|
35 | if (!explicitKey && !ctx.inFlow && str.length > 1024) {
|
36 | if (simpleKeys)
|
37 | throw new Error('With simple keys, single line scalar must not span more than 1024 characters');
|
38 | explicitKey = true;
|
39 | }
|
40 | if (ctx.inFlow) {
|
41 | if (allNullValues || value == null) {
|
42 | if (keyCommentDone && onComment)
|
43 | onComment();
|
44 | return str === '' ? '?' : explicitKey ? `? ${str}` : str;
|
45 | }
|
46 | }
|
47 | else if ((allNullValues && !simpleKeys) || (value == null && explicitKey)) {
|
48 | str = `? ${str}`;
|
49 | if (keyComment && !keyCommentDone) {
|
50 | str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
|
51 | }
|
52 | else if (chompKeep && onChompKeep)
|
53 | onChompKeep();
|
54 | return str;
|
55 | }
|
56 | if (keyCommentDone)
|
57 | keyComment = null;
|
58 | if (explicitKey) {
|
59 | if (keyComment)
|
60 | str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
|
61 | str = `? ${str}\n${indent}:`;
|
62 | }
|
63 | else {
|
64 | str = `${str}:`;
|
65 | if (keyComment)
|
66 | str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
|
67 | }
|
68 | let vsb, vcb, valueComment;
|
69 | if (identity.isNode(value)) {
|
70 | vsb = !!value.spaceBefore;
|
71 | vcb = value.commentBefore;
|
72 | valueComment = value.comment;
|
73 | }
|
74 | else {
|
75 | vsb = false;
|
76 | vcb = null;
|
77 | valueComment = null;
|
78 | if (value && typeof value === 'object')
|
79 | value = doc.createNode(value);
|
80 | }
|
81 | ctx.implicitKey = false;
|
82 | if (!explicitKey && !keyComment && identity.isScalar(value))
|
83 | ctx.indentAtStart = str.length + 1;
|
84 | chompKeep = false;
|
85 | if (!indentSeq &&
|
86 | indentStep.length >= 2 &&
|
87 | !ctx.inFlow &&
|
88 | !explicitKey &&
|
89 | identity.isSeq(value) &&
|
90 | !value.flow &&
|
91 | !value.tag &&
|
92 | !value.anchor) {
|
93 |
|
94 | ctx.indent = ctx.indent.substring(2);
|
95 | }
|
96 | let valueCommentDone = false;
|
97 | const valueStr = stringify.stringify(value, ctx, () => (valueCommentDone = true), () => (chompKeep = true));
|
98 | let ws = ' ';
|
99 | if (keyComment || vsb || vcb) {
|
100 | ws = vsb ? '\n' : '';
|
101 | if (vcb) {
|
102 | const cs = commentString(vcb);
|
103 | ws += `\n${stringifyComment.indentComment(cs, ctx.indent)}`;
|
104 | }
|
105 | if (valueStr === '' && !ctx.inFlow) {
|
106 | if (ws === '\n')
|
107 | ws = '\n\n';
|
108 | }
|
109 | else {
|
110 | ws += `\n${ctx.indent}`;
|
111 | }
|
112 | }
|
113 | else if (!explicitKey && identity.isCollection(value)) {
|
114 | const vs0 = valueStr[0];
|
115 | const nl0 = valueStr.indexOf('\n');
|
116 | const hasNewline = nl0 !== -1;
|
117 | const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0;
|
118 | if (hasNewline || !flow) {
|
119 | let hasPropsLine = false;
|
120 | if (hasNewline && (vs0 === '&' || vs0 === '!')) {
|
121 | let sp0 = valueStr.indexOf(' ');
|
122 | if (vs0 === '&' &&
|
123 | sp0 !== -1 &&
|
124 | sp0 < nl0 &&
|
125 | valueStr[sp0 + 1] === '!') {
|
126 | sp0 = valueStr.indexOf(' ', sp0 + 1);
|
127 | }
|
128 | if (sp0 === -1 || nl0 < sp0)
|
129 | hasPropsLine = true;
|
130 | }
|
131 | if (!hasPropsLine)
|
132 | ws = `\n${ctx.indent}`;
|
133 | }
|
134 | }
|
135 | else if (valueStr === '' || valueStr[0] === '\n') {
|
136 | ws = '';
|
137 | }
|
138 | str += ws + valueStr;
|
139 | if (ctx.inFlow) {
|
140 | if (valueCommentDone && onComment)
|
141 | onComment();
|
142 | }
|
143 | else if (valueComment && !valueCommentDone) {
|
144 | str += stringifyComment.lineComment(str, ctx.indent, commentString(valueComment));
|
145 | }
|
146 | else if (chompKeep && onChompKeep) {
|
147 | onChompKeep();
|
148 | }
|
149 | return str;
|
150 | }
|
151 |
|
152 | exports.stringifyPair = stringifyPair;
|