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)) {
|
---|
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 | // If indentSeq === false, consider '- ' as part of indentation where possible
|
---|
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;
|
---|