timonel 2.13.0 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +191 -0
- package/README.md +203 -35
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/lib/helmChartWriter.js +5 -3
- package/dist/lib/rutter.d.ts +0 -12
- package/dist/lib/rutter.js +22 -188
- package/dist/lib/templates/flexible-subchart.js +23 -29
- package/dist/lib/templates/umbrella-chart.js +7 -7
- package/dist/lib/utils/envVarsLoader.d.ts +19 -0
- package/dist/lib/utils/envVarsLoader.js +57 -0
- package/dist/lib/utils/helmConstructSerializer.d.ts +3 -0
- package/dist/lib/utils/helmConstructSerializer.js +61 -0
- package/dist/lib/utils/helmControlStructures.d.ts +33 -0
- package/dist/lib/utils/helmControlStructures.js +124 -0
- package/dist/lib/utils/helmYamlSerializer.d.ts +10 -28
- package/dist/lib/utils/helmYamlSerializer.js +638 -200
- package/dist/lib/utils/valuesRef.d.ts +102 -0
- package/dist/lib/utils/valuesRef.js +264 -0
- package/package.json +10 -3
|
@@ -1,114 +1,660 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
import { Document, Scalar, isMap, isScalar, visit, Pair } from 'yaml';
|
|
2
|
+
import { isHelmConstruct, isHelmExpression, createHelmExpression, } from './helmControlStructures.js';
|
|
3
|
+
import { isHelmValue, isHelmFieldConditional, isHelmRange, isHelmWith, } from './valuesRef.js';
|
|
4
|
+
const FIELD_CONDITIONAL = '__FIELD_CONDITIONAL__:';
|
|
5
|
+
const FIELD_WITH = '__FIELD_WITH__:';
|
|
6
|
+
const FIELD_WITH_MARKER = '__FIELD_WITH_MARKER__:';
|
|
7
|
+
function simpleHelmYaml(obj) {
|
|
8
|
+
function convertToPlain(value) {
|
|
9
|
+
if (isHelmValue(value)) {
|
|
10
|
+
return `{{ ${value.__path} }}`;
|
|
11
|
+
}
|
|
12
|
+
if (isHelmExpression(value)) {
|
|
13
|
+
return value.value;
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
return value.map(convertToPlain);
|
|
17
|
+
}
|
|
18
|
+
if (value !== null && typeof value === 'object') {
|
|
19
|
+
const result = {};
|
|
20
|
+
for (const [k, v] of Object.entries(value)) {
|
|
21
|
+
result[k] = convertToPlain(v);
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
const plain = convertToPlain(obj);
|
|
28
|
+
const doc = new Document(plain);
|
|
29
|
+
return doc.toString({ lineWidth: 0 });
|
|
21
30
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
function serializeElseIfChain(elseContent, openTag, closeTag) {
|
|
32
|
+
let result = '';
|
|
33
|
+
let currentElse = elseContent;
|
|
34
|
+
if (isHelmConstruct(currentElse) && currentElse.type === 'if') {
|
|
35
|
+
while (isHelmConstruct(currentElse) && currentElse.type === 'if') {
|
|
36
|
+
const elseIfData = currentElse.data;
|
|
37
|
+
result += `\n${openTag}else if ${elseIfData.condition}${closeTag}\n`;
|
|
38
|
+
result += serializeHelmContent(elseIfData.then);
|
|
39
|
+
currentElse = elseIfData.else;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { result, remainingElse: currentElse };
|
|
27
43
|
}
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
function serializeHelmConstruct(construct) {
|
|
45
|
+
if (construct.type === 'fieldConditional') {
|
|
46
|
+
throw new Error('fieldConditional should not be serialized directly. It must be handled in preprocessHelmConstructs.');
|
|
47
|
+
}
|
|
48
|
+
const trimLeft = construct.options?.trimLeft ?? true;
|
|
49
|
+
const trimRight = construct.options?.trimRight ?? true;
|
|
50
|
+
const openTag = `{{${trimLeft ? '-' : ''} `;
|
|
51
|
+
const closeTag = ` ${trimRight ? '-' : ''}}}`;
|
|
52
|
+
switch (construct.type) {
|
|
53
|
+
case 'if': {
|
|
54
|
+
const data = construct.data;
|
|
55
|
+
const isInline = construct.options?.inline ?? false;
|
|
56
|
+
const newline = isInline ? '' : '\n';
|
|
57
|
+
const space = isInline ? ' ' : '';
|
|
58
|
+
let result = `${openTag}if ${data.condition}${closeTag}${newline}`;
|
|
59
|
+
result += serializeHelmContent(data.then);
|
|
60
|
+
if (data.else !== undefined) {
|
|
61
|
+
if (isInline) {
|
|
62
|
+
result += `${space}${openTag}else${closeTag}${space}`;
|
|
63
|
+
result += serializeHelmContent(data.else);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const { result: elseIfResult, remainingElse } = serializeElseIfChain(data.else, openTag, closeTag);
|
|
67
|
+
result += elseIfResult;
|
|
68
|
+
if (remainingElse !== undefined) {
|
|
69
|
+
result += `\n${openTag}else${closeTag}\n`;
|
|
70
|
+
result += serializeHelmContent(remainingElse);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
result += `${newline}${openTag}end${closeTag}`;
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
case 'fragment': {
|
|
78
|
+
const data = construct.data;
|
|
79
|
+
const strings = [];
|
|
80
|
+
const objects = [];
|
|
81
|
+
for (const item of data) {
|
|
82
|
+
if (typeof item === 'object' &&
|
|
83
|
+
item !== null &&
|
|
84
|
+
!Array.isArray(item) &&
|
|
85
|
+
!isHelmConstruct(item) &&
|
|
86
|
+
!isHelmExpression(item)) {
|
|
87
|
+
objects.push(item);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const serialized = serializeHelmContent(item);
|
|
91
|
+
if (serialized.trim().length > 0) {
|
|
92
|
+
strings.push(serialized);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (strings.length > 0 && objects.length > 0) {
|
|
97
|
+
const combinedObject = objects.reduce((acc, obj) => {
|
|
98
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
99
|
+
return { ...acc, ...obj };
|
|
100
|
+
}
|
|
101
|
+
return acc;
|
|
102
|
+
}, {});
|
|
103
|
+
const preprocessed = preprocessHelmConstructs(combinedObject);
|
|
104
|
+
const doc = new Document(preprocessed);
|
|
105
|
+
visit(doc, (_key, node) => {
|
|
106
|
+
if (isMap(node)) {
|
|
107
|
+
const isHelmExpr = node.items.some((pair) => isScalar(pair.key) &&
|
|
108
|
+
pair.key.value === '__helmExpression' &&
|
|
109
|
+
isScalar(pair.value) &&
|
|
110
|
+
pair.value.value === true);
|
|
111
|
+
if (isHelmExpr) {
|
|
112
|
+
const valuePair = node.items.find((pair) => isScalar(pair.key) && pair.key.value === 'value');
|
|
113
|
+
if (valuePair && isScalar(valuePair.value)) {
|
|
114
|
+
const value = String(valuePair.value.value);
|
|
115
|
+
const scalar = new Scalar(value);
|
|
116
|
+
if (value.trim().startsWith('{{') && value.includes('\n')) {
|
|
117
|
+
scalar.type = 'BLOCK_LITERAL';
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
scalar.type = 'QUOTE_DOUBLE';
|
|
121
|
+
}
|
|
122
|
+
return scalar;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
});
|
|
128
|
+
let objectYaml = doc.toString({ lineWidth: 0 }).trim();
|
|
129
|
+
return [...strings, objectYaml].filter((s) => s.trim().length > 0).join('\n');
|
|
130
|
+
}
|
|
131
|
+
if (objects.length > 0) {
|
|
132
|
+
const combinedObject = objects.reduce((acc, obj) => {
|
|
133
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
134
|
+
return { ...acc, ...obj };
|
|
135
|
+
}
|
|
136
|
+
return acc;
|
|
137
|
+
}, {});
|
|
138
|
+
const preprocessed = preprocessHelmConstructs(combinedObject);
|
|
139
|
+
const doc = new Document(preprocessed);
|
|
140
|
+
visit(doc, (_key, node) => {
|
|
141
|
+
if (isMap(node)) {
|
|
142
|
+
const isHelmExpr = node.items.some((pair) => isScalar(pair.key) &&
|
|
143
|
+
pair.key.value === '__helmExpression' &&
|
|
144
|
+
isScalar(pair.value) &&
|
|
145
|
+
pair.value.value === true);
|
|
146
|
+
if (isHelmExpr) {
|
|
147
|
+
const valuePair = node.items.find((pair) => isScalar(pair.key) && pair.key.value === 'value');
|
|
148
|
+
if (valuePair && isScalar(valuePair.value)) {
|
|
149
|
+
const value = String(valuePair.value.value);
|
|
150
|
+
const scalar = new Scalar(value);
|
|
151
|
+
if (value.trim().startsWith('{{') && value.includes('\n')) {
|
|
152
|
+
scalar.type = 'BLOCK_LITERAL';
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
scalar.type = 'QUOTE_DOUBLE';
|
|
156
|
+
}
|
|
157
|
+
return scalar;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
});
|
|
163
|
+
return doc.toString({ lineWidth: 0 }).trim();
|
|
164
|
+
}
|
|
165
|
+
return strings.filter((s) => s.trim().length > 0).join('\n');
|
|
166
|
+
}
|
|
167
|
+
case 'range': {
|
|
168
|
+
const data = construct.data;
|
|
169
|
+
let result = `${openTag}range ${data.vars} := ${data.collection}${closeTag}\n`;
|
|
170
|
+
result += serializeHelmContent(data.content);
|
|
171
|
+
result += `\n${openTag}end${closeTag}`;
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
case 'with': {
|
|
175
|
+
const data = construct.data;
|
|
176
|
+
let result = `${openTag}with ${data.scope}${closeTag}\n`;
|
|
177
|
+
result += serializeHelmContent(data.content);
|
|
178
|
+
result += `\n${openTag}end${closeTag}`;
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
case 'include': {
|
|
182
|
+
const data = construct.data;
|
|
183
|
+
let result = `${openTag}include "${data.templateName}" ${data.scope}`;
|
|
184
|
+
if (data.pipe) {
|
|
185
|
+
result += ` | ${data.pipe}`;
|
|
186
|
+
}
|
|
187
|
+
result += closeTag;
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
case 'define': {
|
|
191
|
+
const data = construct.data;
|
|
192
|
+
let result = `${openTag}define "${data.name}"${closeTag}\n`;
|
|
193
|
+
result += serializeHelmContent(data.content);
|
|
194
|
+
result += `\n${openTag}end${closeTag}`;
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
case 'var': {
|
|
198
|
+
const data = construct.data;
|
|
199
|
+
return `${openTag}${data.name} := ${data.value}${closeTag}`;
|
|
200
|
+
}
|
|
201
|
+
case 'block': {
|
|
202
|
+
const data = construct.data;
|
|
203
|
+
let result = `${openTag}block "${data.name}" .${closeTag}\n`;
|
|
204
|
+
result += serializeHelmContent(data.content);
|
|
205
|
+
result += `\n${openTag}end${closeTag}`;
|
|
206
|
+
return result;
|
|
42
207
|
}
|
|
208
|
+
case 'comment': {
|
|
209
|
+
const data = construct.data;
|
|
210
|
+
return `{{/* ${data.text} */}}`;
|
|
211
|
+
}
|
|
212
|
+
default:
|
|
213
|
+
throw new Error(`Unknown Helm construct type: ${construct.type}`);
|
|
43
214
|
}
|
|
44
|
-
return matches.sort((a, b) => a.start - b.start);
|
|
45
215
|
}
|
|
46
|
-
function
|
|
47
|
-
if (
|
|
48
|
-
|
|
216
|
+
function serializeHelmContent(content) {
|
|
217
|
+
if (isHelmConstruct(content)) {
|
|
218
|
+
return serializeHelmConstruct(content);
|
|
219
|
+
}
|
|
220
|
+
if (isHelmExpression(content)) {
|
|
221
|
+
return content.value;
|
|
222
|
+
}
|
|
223
|
+
if (content === null || content === undefined) {
|
|
224
|
+
return '';
|
|
225
|
+
}
|
|
226
|
+
if (typeof content === 'string') {
|
|
227
|
+
return content;
|
|
49
228
|
}
|
|
50
|
-
if (
|
|
229
|
+
if (typeof content === 'number' || typeof content === 'boolean') {
|
|
230
|
+
return String(content);
|
|
231
|
+
}
|
|
232
|
+
if (typeof content === 'object') {
|
|
233
|
+
const preprocessed = preprocessHelmConstructs(content);
|
|
234
|
+
const doc = new Document(preprocessed);
|
|
235
|
+
let yaml = doc.toString({ lineWidth: 0 });
|
|
236
|
+
yaml = yaml.trim();
|
|
237
|
+
return yaml;
|
|
238
|
+
}
|
|
239
|
+
return '';
|
|
240
|
+
}
|
|
241
|
+
export function preprocessHelmConstructs(obj) {
|
|
242
|
+
if (isHelmValue(obj)) {
|
|
243
|
+
const value = obj;
|
|
244
|
+
return createHelmExpression(`{{ ${value.__path} }}`);
|
|
245
|
+
}
|
|
246
|
+
if (isHelmFieldConditional(obj)) {
|
|
51
247
|
return obj;
|
|
52
248
|
}
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
249
|
+
if (isHelmRange(obj)) {
|
|
250
|
+
const range = obj;
|
|
251
|
+
const sourcePath = range.source.__path;
|
|
252
|
+
const itemProxy = { __path: '$item' };
|
|
253
|
+
const indexProxy = { __path: '$index' };
|
|
254
|
+
const content = range.callback(itemProxy, indexProxy);
|
|
255
|
+
const processedContent = preprocessHelmConstructs(content);
|
|
256
|
+
const contentDoc = new Document(processedContent);
|
|
257
|
+
const contentStr = contentDoc.toString({ lineWidth: 0 }).trim();
|
|
258
|
+
return createHelmExpression(`{{- range ${sourcePath} }}\n${contentStr}\n{{- end }}`);
|
|
259
|
+
}
|
|
260
|
+
if (isHelmWith(obj)) {
|
|
57
261
|
return obj;
|
|
58
262
|
}
|
|
263
|
+
if (isHelmConstruct(obj)) {
|
|
264
|
+
if (obj.type === 'fieldConditional') {
|
|
265
|
+
return obj;
|
|
266
|
+
}
|
|
267
|
+
if (obj.type === 'if') {
|
|
268
|
+
const ifData = obj.data;
|
|
269
|
+
const isInline = obj.options?.inline ?? false;
|
|
270
|
+
if (!isInline && (ifData.else === undefined || !('else' in ifData))) {
|
|
271
|
+
return obj;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const helmTemplate = serializeHelmConstruct(obj);
|
|
275
|
+
return createHelmExpression(helmTemplate);
|
|
276
|
+
}
|
|
59
277
|
if (Array.isArray(obj)) {
|
|
60
|
-
return obj.map((item) =>
|
|
278
|
+
return obj.map((item) => preprocessHelmConstructs(item));
|
|
61
279
|
}
|
|
62
|
-
if (typeof obj === 'object'
|
|
280
|
+
if (obj !== null && typeof obj === 'object') {
|
|
281
|
+
if (isHelmExpression(obj)) {
|
|
282
|
+
return obj;
|
|
283
|
+
}
|
|
63
284
|
const result = {};
|
|
64
285
|
for (const [key, value] of Object.entries(obj)) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
286
|
+
if (isHelmWith(value)) {
|
|
287
|
+
const withBlock = value;
|
|
288
|
+
const source = withBlock.source;
|
|
289
|
+
const sourcePath = source?.__path;
|
|
290
|
+
if (!sourcePath) {
|
|
291
|
+
throw new Error('HelmWith source must have a valid __path');
|
|
292
|
+
}
|
|
293
|
+
const ctxProxy = { __path: '.' };
|
|
294
|
+
const content = withBlock.callback(ctxProxy);
|
|
295
|
+
let contentStr;
|
|
296
|
+
if (isHelmExpression(content)) {
|
|
297
|
+
contentStr = content.value;
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
const processedContent = preprocessHelmConstructs(content);
|
|
301
|
+
const contentDoc = new Document(processedContent);
|
|
302
|
+
contentStr = contentDoc.toString({ lineWidth: 0 }).trim();
|
|
303
|
+
}
|
|
304
|
+
const template = `{{- with ${sourcePath} }}\n${key}:\n ${contentStr}\n{{- end }}`;
|
|
305
|
+
const marker = `__FIELD_WITH__:${key}:${template}`;
|
|
306
|
+
result[`__fieldWithTemplate_${key}`] = createHelmExpression(marker);
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (isHelmConstruct(value) && value.type === 'if') {
|
|
310
|
+
const ifData = value.data;
|
|
311
|
+
const isInline = value.options?.inline ?? false;
|
|
312
|
+
if (!isInline && (ifData.else === undefined || !('else' in ifData))) {
|
|
313
|
+
const preprocessedThen = preprocessHelmConstructs(ifData.then);
|
|
314
|
+
let thenValueStr = '';
|
|
315
|
+
let isMultilineObject = false;
|
|
316
|
+
if (isHelmExpression(preprocessedThen)) {
|
|
317
|
+
thenValueStr = preprocessedThen.value.trim();
|
|
318
|
+
isMultilineObject = thenValueStr.includes('\n');
|
|
319
|
+
}
|
|
320
|
+
else if (typeof preprocessedThen === 'string') {
|
|
321
|
+
thenValueStr = preprocessedThen.trim();
|
|
322
|
+
isMultilineObject = thenValueStr.includes('\n');
|
|
323
|
+
}
|
|
324
|
+
else if (Array.isArray(preprocessedThen)) {
|
|
325
|
+
const tempDoc = new Document(preprocessedThen);
|
|
326
|
+
thenValueStr = tempDoc.toString({ lineWidth: 0 }).trim();
|
|
327
|
+
isMultilineObject = true;
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const tempDoc = new Document(preprocessedThen);
|
|
331
|
+
thenValueStr = tempDoc.toString({ lineWidth: 0 }).trim();
|
|
332
|
+
isMultilineObject = thenValueStr.includes('\n');
|
|
333
|
+
}
|
|
334
|
+
const constructOptions = isHelmConstruct(value) ? value.options : undefined;
|
|
335
|
+
const trimLeft = constructOptions?.trimLeft ?? true;
|
|
336
|
+
const openTag = `{{${trimLeft ? '-' : ''} `;
|
|
337
|
+
const closeTag = ` ${(constructOptions?.trimRight ?? true) ? '-' : ''}}}`;
|
|
338
|
+
let formattedContent;
|
|
339
|
+
if (isMultilineObject) {
|
|
340
|
+
const indentedValue = thenValueStr
|
|
341
|
+
.split('\n')
|
|
342
|
+
.map((line) => ' ' + line)
|
|
343
|
+
.join('\n');
|
|
344
|
+
formattedContent = `${key}:\n${indentedValue}`;
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
formattedContent = `${key}: ${thenValueStr}`;
|
|
348
|
+
}
|
|
349
|
+
const conditionalTemplate = `${openTag}if ${ifData.condition}${closeTag}\n ${formattedContent}\n${openTag}end${closeTag}`;
|
|
350
|
+
result[key] = createHelmExpression(`__FIELD_CONDITIONAL__:${key}:${conditionalTemplate}`);
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (isHelmFieldConditional(value)) {
|
|
355
|
+
const fieldCond = value;
|
|
356
|
+
const condition = fieldCond.condition.__condition;
|
|
357
|
+
const thenValueStr = simpleHelmYaml(fieldCond.thenValue).trim();
|
|
358
|
+
const isMultilineObject = thenValueStr.includes('\n');
|
|
359
|
+
const startsWithDash = thenValueStr.trimStart().startsWith('-');
|
|
360
|
+
let formattedContent;
|
|
361
|
+
if (isMultilineObject || startsWithDash) {
|
|
362
|
+
const lines = thenValueStr.split('\n');
|
|
363
|
+
const indentedValue = lines.map((line) => ' ' + line).join('\n');
|
|
364
|
+
formattedContent = `${key}:\n${indentedValue}`;
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
formattedContent = `${key}: ${thenValueStr}`;
|
|
368
|
+
}
|
|
369
|
+
const conditionalTemplate = `{{- if ${condition} }}\n${formattedContent}\n{{- end }}`;
|
|
370
|
+
result[key] = createHelmExpression(`__FIELD_CONDITIONAL__:${key}:${conditionalTemplate}`);
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
if (isHelmConstruct(value) && value.type === 'fieldConditional') {
|
|
374
|
+
const fieldData = value.data;
|
|
375
|
+
const preprocessedThen = preprocessHelmConstructs(fieldData.then);
|
|
376
|
+
let thenValueStr = '';
|
|
377
|
+
if (isHelmExpression(preprocessedThen)) {
|
|
378
|
+
thenValueStr = preprocessedThen.value;
|
|
379
|
+
}
|
|
380
|
+
else if (typeof preprocessedThen === 'string') {
|
|
381
|
+
thenValueStr = preprocessedThen;
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
const tempDoc = new Document(preprocessedThen);
|
|
385
|
+
thenValueStr = tempDoc.toString({ lineWidth: 0 }).trim();
|
|
386
|
+
}
|
|
387
|
+
const conditionalTemplate = `{{- if ${fieldData.condition} }}\n ${fieldData.fieldKey}: ${thenValueStr}\n{{- end }}`;
|
|
388
|
+
result[`__fieldConditionalTemplate_${fieldData.fieldKey}`] = conditionalTemplate;
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
result[key] = preprocessHelmConstructs(value);
|
|
71
392
|
}
|
|
72
393
|
return result;
|
|
73
394
|
}
|
|
74
395
|
return obj;
|
|
75
396
|
}
|
|
76
|
-
function
|
|
77
|
-
|
|
78
|
-
|
|
397
|
+
export function dumpHelmAwareYaml(obj, options = {}) {
|
|
398
|
+
const preprocessed = preprocessHelmConstructs(obj);
|
|
399
|
+
const doc = new Document(preprocessed);
|
|
400
|
+
visit(doc, (_key, node) => {
|
|
401
|
+
if (isMap(node)) {
|
|
402
|
+
const isHelmExpr = node.items.some((pair) => isScalar(pair.key) &&
|
|
403
|
+
pair.key.value === '__helmExpression' &&
|
|
404
|
+
isScalar(pair.value) &&
|
|
405
|
+
pair.value.value === true);
|
|
406
|
+
if (isHelmExpr) {
|
|
407
|
+
const valuePair = node.items.find((pair) => isScalar(pair.key) && pair.key.value === 'value');
|
|
408
|
+
if (valuePair && isScalar(valuePair.value)) {
|
|
409
|
+
const value = String(valuePair.value.value);
|
|
410
|
+
if (value.startsWith(FIELD_CONDITIONAL) ||
|
|
411
|
+
value.startsWith(FIELD_WITH) ||
|
|
412
|
+
value.startsWith(FIELD_WITH_MARKER)) {
|
|
413
|
+
const scalar = new Scalar(value);
|
|
414
|
+
scalar.type = 'BLOCK_LITERAL';
|
|
415
|
+
return scalar;
|
|
416
|
+
}
|
|
417
|
+
const scalar = new Scalar(value);
|
|
418
|
+
const isMultilineTemplate = value.includes('\n') && value.trim().startsWith('{{');
|
|
419
|
+
const isWithOrRange = value.trim().startsWith('{{- with ') || value.trim().startsWith('{{- range ');
|
|
420
|
+
if (isMultilineTemplate && !isWithOrRange) {
|
|
421
|
+
scalar.type = 'BLOCK_LITERAL';
|
|
422
|
+
}
|
|
423
|
+
else if (isWithOrRange) {
|
|
424
|
+
scalar.type = 'PLAIN';
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
scalar.type = 'QUOTE_DOUBLE';
|
|
428
|
+
}
|
|
429
|
+
return scalar;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return undefined;
|
|
434
|
+
});
|
|
435
|
+
const toStringOptions = { lineWidth: 0 };
|
|
436
|
+
if (options.lineWidth !== undefined) {
|
|
437
|
+
toStringOptions.lineWidth = options.lineWidth;
|
|
79
438
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
439
|
+
const templatePairs = [];
|
|
440
|
+
visit(doc, (_key, node) => {
|
|
441
|
+
if (isMap(node)) {
|
|
442
|
+
for (let i = 0; i < node.items.length; i++) {
|
|
443
|
+
const pair = node.items[i];
|
|
444
|
+
if (pair && isScalar(pair.key)) {
|
|
445
|
+
const keyStr = String(pair.key.value);
|
|
446
|
+
if (keyStr.startsWith('__fieldConditionalTemplate_') && isScalar(pair.value)) {
|
|
447
|
+
const template = String(pair.value.value);
|
|
448
|
+
const fieldKey = keyStr.replace('__fieldConditionalTemplate_', '');
|
|
449
|
+
templatePairs.push({ parent: node, index: i, template, fieldKey });
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return undefined;
|
|
455
|
+
});
|
|
456
|
+
for (let i = templatePairs.length - 1; i >= 0; i--) {
|
|
457
|
+
const templatePair = templatePairs[i];
|
|
458
|
+
if (!templatePair)
|
|
459
|
+
continue;
|
|
460
|
+
const { parent, index, template } = templatePair;
|
|
461
|
+
parent.items.splice(index, 1);
|
|
462
|
+
const tempDoc = new Document({ __temp: template });
|
|
463
|
+
const _tempYaml = tempDoc.toString({ lineWidth: 0 });
|
|
464
|
+
const templateScalar = new Scalar(template);
|
|
465
|
+
templateScalar.type = 'BLOCK_LITERAL';
|
|
466
|
+
const specialKeyScalar = new Scalar('__fieldConditionalContent');
|
|
467
|
+
const templatePairObj = new Pair(specialKeyScalar, templateScalar);
|
|
468
|
+
parent.items.splice(index, 0, templatePairObj);
|
|
469
|
+
}
|
|
470
|
+
let result = doc.toString(toStringOptions);
|
|
471
|
+
while (result.includes('__fieldConditionalContent:')) {
|
|
472
|
+
const markerIndex = result.indexOf('__fieldConditionalContent:');
|
|
473
|
+
if (markerIndex === -1)
|
|
474
|
+
break;
|
|
475
|
+
const lineStart = result.lastIndexOf('\n', markerIndex);
|
|
476
|
+
const lineBeforeMarker = result.substring(lineStart + 1, markerIndex);
|
|
477
|
+
const indentMatch = lineBeforeMarker.match(/^(\s*)/);
|
|
478
|
+
const baseIndent = indentMatch && indentMatch[1] ? indentMatch[1] : '';
|
|
479
|
+
const afterMarker = result.substring(markerIndex);
|
|
480
|
+
let pipeLineMatch = afterMarker.match(/^__fieldConditionalContent:\s*(\|-?)\s*\n(\s*)/);
|
|
481
|
+
let pipeOnSameLine = true;
|
|
482
|
+
if (!pipeLineMatch) {
|
|
483
|
+
pipeLineMatch = afterMarker.match(/^__fieldConditionalContent:\s*\n(\s*)(\|-?)\s*\n/);
|
|
484
|
+
pipeOnSameLine = false;
|
|
485
|
+
}
|
|
486
|
+
if (!pipeLineMatch)
|
|
487
|
+
break;
|
|
488
|
+
const pipeChar = pipeOnSameLine ? pipeLineMatch[1] : pipeLineMatch[2];
|
|
489
|
+
const pipeIndent = pipeOnSameLine ? pipeLineMatch[2] || '' : pipeLineMatch[1] || '';
|
|
490
|
+
if (!pipeChar)
|
|
491
|
+
break;
|
|
492
|
+
const pipeIndex = markerIndex + pipeLineMatch[0].length;
|
|
493
|
+
const afterPipe = result.substring(pipeIndex);
|
|
494
|
+
const templateStartMatch = afterPipe.match(/^\n(\s*)(\{\{-)/);
|
|
495
|
+
if (!templateStartMatch) {
|
|
496
|
+
const templateStartMatchNoNewline = afterPipe.match(/^(\s*)(\{\{-)/);
|
|
497
|
+
if (!templateStartMatchNoNewline)
|
|
498
|
+
break;
|
|
499
|
+
const _templateIndent = templateStartMatchNoNewline[1] || '';
|
|
500
|
+
const templateStart = templateStartMatchNoNewline[2];
|
|
501
|
+
if (!templateStart)
|
|
502
|
+
break;
|
|
503
|
+
const templateStartIndex = pipeIndex + templateStartMatchNoNewline[0].length;
|
|
504
|
+
const templateSection = result.substring(templateStartIndex);
|
|
505
|
+
const endMatch = templateSection.match(/(\{\{-?\s*end\s*-?\}\})/);
|
|
506
|
+
if (!endMatch)
|
|
507
|
+
break;
|
|
508
|
+
const endIndex = endMatch.index;
|
|
509
|
+
if (endIndex === undefined)
|
|
510
|
+
break;
|
|
511
|
+
const templateEndIndex = templateStartIndex + endIndex + endMatch[0].length;
|
|
512
|
+
const templateContent = result.substring(templateStartIndex, templateEndIndex);
|
|
513
|
+
const beforeMarker = result.substring(0, lineStart + 1);
|
|
514
|
+
const afterTemplate = result.substring(templateEndIndex);
|
|
515
|
+
const pipeIndentEscaped = pipeIndent.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
516
|
+
const adjustedTemplate = templateContent.replace(new RegExp(`^${pipeIndentEscaped}`, 'gm'), baseIndent);
|
|
517
|
+
result = beforeMarker + adjustedTemplate + afterTemplate;
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
const _templateIndent = templateStartMatch[1] || '';
|
|
521
|
+
const templateStart = templateStartMatch[2];
|
|
522
|
+
if (!templateStart)
|
|
523
|
+
break;
|
|
524
|
+
const templateStartIndex = pipeIndex + templateStartMatch[0].length;
|
|
525
|
+
const templateSection = result.substring(templateStartIndex);
|
|
526
|
+
const endMatch = templateSection.match(/(\{\{-?\s*end\s*-?\}\})/);
|
|
527
|
+
if (!endMatch)
|
|
528
|
+
break;
|
|
529
|
+
const endIndex = endMatch.index;
|
|
530
|
+
if (endIndex === undefined)
|
|
531
|
+
break;
|
|
532
|
+
const templateEndIndex = templateStartIndex + endIndex + endMatch[0].length;
|
|
533
|
+
const templateContent = result.substring(templateStartIndex, templateEndIndex);
|
|
534
|
+
const beforeMarker = result.substring(0, lineStart + 1);
|
|
535
|
+
const afterTemplate = result.substring(templateEndIndex);
|
|
536
|
+
const pipeIndentEscaped = pipeIndent.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
537
|
+
const adjustedTemplate = templateContent.replace(new RegExp(`^${pipeIndentEscaped}`, 'gm'), baseIndent);
|
|
538
|
+
result = beforeMarker + adjustedTemplate + afterTemplate;
|
|
539
|
+
}
|
|
540
|
+
result = result.replace(/\\"/g, '"');
|
|
541
|
+
result = result.replace(/^(\s+)(\w+):\s+(\{\{-?\s*if\s+[^}]+\}\})\s*\n(\s+)(.+?)\n(\s+)(\{\{-?\s*end\s*-?\}\})/gm, (match, baseIndent, fieldKey, ifTag, contentIndent, content, endIndent, endTag) => {
|
|
542
|
+
const contentLines = content.split('\n');
|
|
543
|
+
const firstContentLine = contentLines[0]?.trim() || '';
|
|
544
|
+
if (firstContentLine.startsWith(`${fieldKey}:`)) {
|
|
545
|
+
contentLines[0] = contentLines[0].replace(new RegExp(`^\\s*${fieldKey}:\\s*`), '');
|
|
546
|
+
content = contentLines.join('\n');
|
|
547
|
+
}
|
|
548
|
+
const contentFormatted = content
|
|
549
|
+
? '\n' +
|
|
550
|
+
content
|
|
551
|
+
.split('\n')
|
|
552
|
+
.map((line) => baseIndent + ' ' + line.trimStart())
|
|
553
|
+
.join('\n')
|
|
554
|
+
: '';
|
|
555
|
+
return `${baseIndent}${ifTag}\n${baseIndent} ${fieldKey}:${contentFormatted}\n${baseIndent}${endTag}`;
|
|
556
|
+
});
|
|
557
|
+
result = postProcessFieldConditionals(result);
|
|
558
|
+
return result;
|
|
90
559
|
}
|
|
91
|
-
export function
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
560
|
+
export function postProcessFieldConditionals(yaml) {
|
|
561
|
+
let result = yaml;
|
|
562
|
+
while (result.includes('__FIELD_WITH_MARKER__:')) {
|
|
563
|
+
const markerIndex = result.indexOf('__FIELD_WITH_MARKER__:');
|
|
564
|
+
if (markerIndex === -1)
|
|
565
|
+
break;
|
|
566
|
+
const beforeMarker = result.substring(0, markerIndex);
|
|
567
|
+
const lastNewline = beforeMarker.lastIndexOf('\n');
|
|
568
|
+
const secondLastNewline = beforeMarker.lastIndexOf('\n', lastNewline - 1);
|
|
569
|
+
const fieldKeyLine = result.substring(secondLastNewline + 1, lastNewline);
|
|
570
|
+
const fieldKeyMatch = fieldKeyLine.match(/^(\s*)(\w+):\s*|[-]?\s*$/);
|
|
571
|
+
if (!fieldKeyMatch || !fieldKeyMatch[2])
|
|
572
|
+
break;
|
|
573
|
+
const baseIndent = fieldKeyMatch[1] || '';
|
|
574
|
+
const fieldKey = fieldKeyMatch[2];
|
|
575
|
+
const afterMarker = result.substring(markerIndex);
|
|
576
|
+
const markerMatch = afterMarker.match(/^__FIELD_WITH_MARKER__:([^:]+):(.+?)$/m);
|
|
577
|
+
if (!markerMatch || !markerMatch[1] || !markerMatch[2])
|
|
578
|
+
break;
|
|
579
|
+
const path = markerMatch[1];
|
|
580
|
+
const content = markerMatch[2].trim();
|
|
581
|
+
const markerEnd = markerIndex + markerMatch[0].length;
|
|
582
|
+
const template = `${baseIndent}{{- with ${path} }}\n${baseIndent}${fieldKey}:\n${baseIndent} ${content}\n${baseIndent}{{- end }}`;
|
|
583
|
+
result = result.substring(0, secondLastNewline + 1) + template + result.substring(markerEnd);
|
|
584
|
+
}
|
|
585
|
+
while (result.includes('__FIELD_WITH__:')) {
|
|
586
|
+
const markerIndex = result.indexOf('__FIELD_WITH__:');
|
|
587
|
+
if (markerIndex === -1)
|
|
588
|
+
break;
|
|
589
|
+
const beforeMarker = result.substring(0, markerIndex);
|
|
590
|
+
const lastNewline = beforeMarker.lastIndexOf('\n');
|
|
591
|
+
const secondLastNewline = beforeMarker.lastIndexOf('\n', lastNewline - 1);
|
|
592
|
+
const fieldKeyLine = result.substring(secondLastNewline + 1, lastNewline);
|
|
593
|
+
const fieldKeyMatch = fieldKeyLine.match(/^(\s*)__fieldWithTemplate_\w+:\s*|[-]?\s*$/);
|
|
594
|
+
if (!fieldKeyMatch)
|
|
595
|
+
break;
|
|
596
|
+
const baseIndent = fieldKeyMatch[1];
|
|
597
|
+
const afterMarker = result.substring(markerIndex);
|
|
598
|
+
const markerMatch = afterMarker.match(/^__FIELD_WITH__:\w+:(.+?\{\{-?\s*end\s*-?\}\})/s);
|
|
599
|
+
if (!markerMatch || !markerMatch[1])
|
|
600
|
+
break;
|
|
601
|
+
const template = markerMatch[1];
|
|
602
|
+
const markerEnd = markerIndex + markerMatch[0].length;
|
|
603
|
+
const lines = template.split('\n');
|
|
604
|
+
const processed = lines
|
|
605
|
+
.map((line) => {
|
|
606
|
+
if (!line.trim())
|
|
607
|
+
return '';
|
|
608
|
+
const trimmed = line.trimStart();
|
|
609
|
+
return baseIndent + trimmed;
|
|
610
|
+
})
|
|
611
|
+
.join('\n');
|
|
612
|
+
result = result.substring(0, secondLastNewline + 1) + processed + result.substring(markerEnd);
|
|
613
|
+
}
|
|
614
|
+
while (result.includes('__FIELD_CONDITIONAL__:')) {
|
|
615
|
+
const markerIndex = result.indexOf('__FIELD_CONDITIONAL__:');
|
|
616
|
+
if (markerIndex === -1)
|
|
617
|
+
break;
|
|
618
|
+
const beforeMarker = result.substring(0, markerIndex);
|
|
619
|
+
const lastNewline = beforeMarker.lastIndexOf('\n');
|
|
620
|
+
const secondLastNewline = beforeMarker.lastIndexOf('\n', lastNewline - 1);
|
|
621
|
+
const fieldKeyLine = result.substring(secondLastNewline + 1, lastNewline);
|
|
622
|
+
const fieldKeyMatch = fieldKeyLine.match(/^(\s*)(\w+):\s*|[-]?\s*$/);
|
|
623
|
+
if (!fieldKeyMatch)
|
|
624
|
+
break;
|
|
625
|
+
const baseIndent = fieldKeyMatch[1];
|
|
626
|
+
const afterMarker = result.substring(markerIndex);
|
|
627
|
+
const markerMatch = afterMarker.match(/^__FIELD_CONDITIONAL__:\w+:(.+?\{\{-?\s*end\s*-?\}\})/s);
|
|
628
|
+
if (!markerMatch || !markerMatch[1])
|
|
629
|
+
break;
|
|
630
|
+
const template = markerMatch[1];
|
|
631
|
+
const markerEnd = markerIndex + markerMatch[0].length;
|
|
632
|
+
const lines = template.split('\n');
|
|
633
|
+
const processed = lines
|
|
634
|
+
.map((line) => {
|
|
635
|
+
if (!line.trim())
|
|
636
|
+
return '';
|
|
637
|
+
const trimmed = line.trimStart();
|
|
638
|
+
return baseIndent + trimmed;
|
|
639
|
+
})
|
|
640
|
+
.join('\n');
|
|
641
|
+
result = result.substring(0, secondLastNewline + 1) + processed + result.substring(markerEnd);
|
|
642
|
+
}
|
|
643
|
+
result = result.replace(/:\s*\|[-+]?\s*\n(\s*\{\{)/g, ':\n$1');
|
|
644
|
+
result = result.replace(/"(\{\{[\s\S]*?\}\})"/g, '$1');
|
|
645
|
+
return result;
|
|
103
646
|
}
|
|
104
647
|
export function stringify(obj, options = {}) {
|
|
105
|
-
|
|
106
|
-
lineWidth: options.lineWidth ?? 0,
|
|
107
|
-
quotingType: options.doubleQuotedAsJSON ? '"' : "'",
|
|
108
|
-
forceQuotes: options.doubleQuotedAsJSON,
|
|
109
|
-
};
|
|
110
|
-
return dumpHelmAwareYaml(obj, jsYamlOptions);
|
|
648
|
+
return dumpHelmAwareYaml(obj, options.lineWidth !== undefined ? { lineWidth: options.lineWidth } : {});
|
|
111
649
|
}
|
|
650
|
+
const COMPILED_PATTERNS = [
|
|
651
|
+
{ regex: /\{\{-?\s*define\s+[^}]+\s*-?\}\}[\s\S]*?\{\{-?\s*end\s*-?\}\}/g, type: 'block' },
|
|
652
|
+
{ regex: /\{\{[^}]*\{\{[^}]*\}\}[^}]*\}\}/g, type: 'nested' },
|
|
653
|
+
{ regex: /\{\{\/\*[\s\S]*?\*\/\}\}/g, type: 'comment' },
|
|
654
|
+
{ regex: /\{\{-?[\s\S]*?-?\}\}/g, type: 'action-trimmed' },
|
|
655
|
+
{ regex: /\{\{`[\s\S]*?`\}\}/g, type: 'raw' },
|
|
656
|
+
{ regex: /\{\{\s*include\s+"[^"]+"\s+[^}]+\s*\}\}/g, type: 'include-context' },
|
|
657
|
+
];
|
|
112
658
|
export function validateHelmYaml(yaml) {
|
|
113
659
|
const errors = [];
|
|
114
660
|
const warnings = [];
|
|
@@ -280,120 +826,12 @@ function calculateComplexity(expressions) {
|
|
|
280
826
|
}
|
|
281
827
|
return score;
|
|
282
828
|
}
|
|
283
|
-
export function
|
|
284
|
-
|
|
285
|
-
let formatted = yaml;
|
|
286
|
-
if (groupHelpers) {
|
|
287
|
-
formatted = groupHelmHelpers(formatted);
|
|
288
|
-
}
|
|
289
|
-
if (alignExpressions) {
|
|
290
|
-
formatted = alignTemplateExpressions(formatted, indentSize);
|
|
291
|
-
}
|
|
292
|
-
formatted = formatConditionalBlocks(formatted, indentSize);
|
|
293
|
-
formatted = formatLoopBlocks(formatted, indentSize);
|
|
294
|
-
formatted = wrapLongLines(formatted, maxLineWidth);
|
|
295
|
-
if (sortKeys) {
|
|
296
|
-
formatted = sortYamlKeys(formatted);
|
|
297
|
-
}
|
|
298
|
-
return formatted;
|
|
299
|
-
}
|
|
300
|
-
function alignTemplateExpressions(yaml, _indentSize) {
|
|
301
|
-
const lines = yaml.split('\n');
|
|
302
|
-
const aligned = [];
|
|
303
|
-
for (const line of lines) {
|
|
304
|
-
const expressions = line.match(/\{\{[^}]*\}\}/g);
|
|
305
|
-
if (expressions && expressions.length > 1) {
|
|
306
|
-
const baseIndent = (line.match(/^\s*/) || [''])[0];
|
|
307
|
-
const content = line.trim();
|
|
308
|
-
const parts = content.split(/(\{\{[^}]*\}\})/);
|
|
309
|
-
let alignedLine = baseIndent;
|
|
310
|
-
for (let i = 0; i < parts.length; i++) {
|
|
311
|
-
alignedLine += parts[i] || '';
|
|
312
|
-
const nextPart = parts[i + 1];
|
|
313
|
-
if (i < parts.length - 1 && nextPart && nextPart.startsWith('{{')) {
|
|
314
|
-
alignedLine += ' ';
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
aligned.push(alignedLine);
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
aligned.push(line);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
return aligned.join('\n');
|
|
829
|
+
export function detectHelmExpressions(str) {
|
|
830
|
+
return parseHelmExpressions(str);
|
|
324
831
|
}
|
|
325
|
-
function
|
|
326
|
-
|
|
327
|
-
const groups = {
|
|
328
|
-
comments: [],
|
|
329
|
-
definitions: [],
|
|
330
|
-
conditionals: [],
|
|
331
|
-
loops: [],
|
|
332
|
-
other: [],
|
|
333
|
-
};
|
|
334
|
-
for (const line of lines) {
|
|
335
|
-
if (line.includes('{{/*')) {
|
|
336
|
-
groups.comments.push(line);
|
|
337
|
-
}
|
|
338
|
-
else if (line.includes('{{- define')) {
|
|
339
|
-
groups.definitions.push(line);
|
|
340
|
-
}
|
|
341
|
-
else if (/\{\{\s*(if|else|end)\s/.test(line)) {
|
|
342
|
-
groups.conditionals.push(line);
|
|
343
|
-
}
|
|
344
|
-
else if (/\{\{\s*(range|with)\s/.test(line)) {
|
|
345
|
-
groups.loops.push(line);
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
groups.other.push(line);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
return [
|
|
352
|
-
...groups.comments,
|
|
353
|
-
...groups.definitions,
|
|
354
|
-
...groups.conditionals,
|
|
355
|
-
...groups.loops,
|
|
356
|
-
...groups.other,
|
|
357
|
-
].join('\n');
|
|
358
|
-
}
|
|
359
|
-
function formatConditionalBlocks(yaml, indentSize) {
|
|
360
|
-
const indent = ' '.repeat(indentSize);
|
|
361
|
-
return yaml
|
|
362
|
-
.replace(/(\{\{\s*if\s+[^}]+\}\})/g, '$1\n' + indent)
|
|
363
|
-
.replace(/(\{\{\s*else\s*\}\})/g, '$1\n' + indent)
|
|
364
|
-
.replace(/(\{\{\s*end\s*\}\})/g, '\n$1');
|
|
365
|
-
}
|
|
366
|
-
function formatLoopBlocks(yaml, indentSize) {
|
|
367
|
-
const indent = ' '.repeat(indentSize);
|
|
368
|
-
return yaml
|
|
369
|
-
.replace(/(\{\{\s*range\s+[^}]+\}\})/g, '$1\n' + indent)
|
|
370
|
-
.replace(/(\{\{\s*with\s+[^}]+\}\})/g, '$1\n' + indent);
|
|
371
|
-
}
|
|
372
|
-
function wrapLongLines(yaml, maxLineWidth) {
|
|
373
|
-
if (maxLineWidth <= 0)
|
|
374
|
-
return yaml;
|
|
375
|
-
const lines = yaml.split('\n');
|
|
376
|
-
const wrapped = [];
|
|
377
|
-
for (const line of lines) {
|
|
378
|
-
if (line.length <= maxLineWidth) {
|
|
379
|
-
wrapped.push(line);
|
|
380
|
-
continue;
|
|
381
|
-
}
|
|
382
|
-
let remaining = line;
|
|
383
|
-
while (remaining.length > maxLineWidth) {
|
|
384
|
-
let wrapIndex = remaining.lastIndexOf(' ', maxLineWidth);
|
|
385
|
-
if (wrapIndex === -1)
|
|
386
|
-
wrapIndex = maxLineWidth;
|
|
387
|
-
wrapped.push(remaining.slice(0, wrapIndex));
|
|
388
|
-
remaining = remaining.slice(wrapIndex).trim();
|
|
389
|
-
}
|
|
390
|
-
if (remaining.length > 0) {
|
|
391
|
-
wrapped.push(remaining);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
return wrapped.join('\n');
|
|
832
|
+
export function preprocessHelmExpressions(obj) {
|
|
833
|
+
return preprocessHelmConstructs(obj);
|
|
395
834
|
}
|
|
396
|
-
function
|
|
835
|
+
export function postProcessHelmExpressions(yaml) {
|
|
397
836
|
return yaml;
|
|
398
837
|
}
|
|
399
|
-
export { createHelmExpression, isHelmExpression, detectHelmExpressions, preprocessHelmExpressions, postProcessHelmExpressions, };
|