@shepherdjerred/helm-types 0.0.0-dev.706

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.
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Pre-process YAML to uncomment commented-out keys
3
+ * In Helm charts, commented-out keys are documentation of available options
4
+ * e.g., "## key: value" or "# key: value"
5
+ *
6
+ * This allows us to parse them as real keys and associate their comments
7
+ *
8
+ * Only uncomments keys that are:
9
+ * - At root level or similar indentation to real keys
10
+ * - Not part of "Example:" blocks
11
+ * - Not part of documentation prose (have their own dedicated comment block)
12
+ * - Not deeply nested (which would indicate example YAML)
13
+ */
14
+
15
+ /** State for preprocessing YAML comments */
16
+ type PreprocessState = {
17
+ inExampleBlock: boolean;
18
+ inBlockScalar: boolean;
19
+ lastRealKeyIndent: number;
20
+ consecutiveCommentedKeys: number;
21
+ };
22
+
23
+ /**
24
+ * Check if a line is an "Example:" marker
25
+ */
26
+ function isExampleMarker(trimmed: string): boolean {
27
+ return /^##?\s*Example:?$/i.test(trimmed);
28
+ }
29
+
30
+ /**
31
+ * Check if an example block should end
32
+ */
33
+ function shouldExitExampleBlock(trimmed: string): boolean {
34
+ return (
35
+ !trimmed ||
36
+ trimmed.startsWith("For more information") ||
37
+ trimmed.startsWith("Ref:")
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Check if the previous line had a block scalar indicator
43
+ */
44
+ function prevLineHasBlockScalar(lines: string[], i: number): boolean {
45
+ if (i <= 0) {
46
+ return false;
47
+ }
48
+ const prevTrimmed = lines[i - 1]?.trim() ?? "";
49
+ return /^#+\s*[\w.-]+:\s*[|>]\s*$/.test(prevTrimmed);
50
+ }
51
+
52
+ /**
53
+ * Check if a line is still in a block scalar (indented content)
54
+ */
55
+ function isBlockScalarContent(line: string, trimmed: string): boolean {
56
+ if (trimmed.length === 0) {
57
+ return false;
58
+ }
59
+ return (
60
+ line.startsWith(" ") || line.startsWith("\t") || /^#\s{2,}/.test(line)
61
+ );
62
+ }
63
+
64
+ /**
65
+ * Check if a commented key value looks like it should be excluded
66
+ */
67
+ function isExcludedCommentedKey(keyValue: string): boolean {
68
+ const isDocReference =
69
+ /^ref:/i.test(keyValue) &&
70
+ (keyValue.includes("http://") || keyValue.includes("https://"));
71
+ const isURL =
72
+ keyValue.trim().startsWith("http://") ||
73
+ keyValue.trim().startsWith("https://");
74
+ return isDocReference || isURL;
75
+ }
76
+
77
+ /**
78
+ * Determine if a commented key looks like a YAML example based on context
79
+ */
80
+ function isLikelyExample(lines: string[], i: number): boolean {
81
+ const prevLine = i > 0 ? lines[i - 1] : "";
82
+ const prevTrimmed = prevLine?.trim() ?? "";
83
+ const prevIsCommentedKey = /^#+\s*[\w.-]+:\s/.test(prevTrimmed);
84
+ const prevIsBlank = !prevTrimmed;
85
+ const prevIsListItem =
86
+ prevTrimmed.startsWith("#") && prevTrimmed.slice(1).trim().startsWith("-");
87
+
88
+ return (
89
+ (!prevIsBlank && !prevIsCommentedKey && prevTrimmed.startsWith("#")) ||
90
+ prevIsListItem
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Update consecutive commented key count based on context
96
+ */
97
+ function updateConsecutiveCount(
98
+ lines: string[],
99
+ i: number,
100
+ current: number,
101
+ ): number {
102
+ const prevLine = i > 0 ? lines[i - 1] : "";
103
+ const prevTrimmed = prevLine?.trim() ?? "";
104
+ const prevIsCommentedKey = /^#+\s*[\w.-]+:\s/.test(prevTrimmed);
105
+ const prevIsBlank = !prevTrimmed;
106
+
107
+ if (prevIsCommentedKey) {
108
+ return current + 1;
109
+ }
110
+ if (!prevIsBlank) {
111
+ return 0;
112
+ }
113
+ return current;
114
+ }
115
+
116
+ /**
117
+ * Try to uncomment a commented YAML key line. Returns the uncommented line or null.
118
+ */
119
+ function tryUncommentLine(
120
+ line: string,
121
+ lines: string[],
122
+ i: number,
123
+ state: PreprocessState,
124
+ ): { uncommented: string | null; newConsecutive: number } {
125
+ const commentedKeyMatch = /^([ \t]*)#+\s*([\w.-]+:\s*(?:\S.*)?)$/.exec(line);
126
+ if (!commentedKeyMatch) {
127
+ return { uncommented: null, newConsecutive: 0 };
128
+ }
129
+
130
+ const [, indent, keyValue] = commentedKeyMatch;
131
+ if (keyValue == null || keyValue === "" || indent == null || indent === "") {
132
+ return {
133
+ uncommented: null,
134
+ newConsecutive: state.consecutiveCommentedKeys,
135
+ };
136
+ }
137
+
138
+ const keyPart = keyValue.split(":")[0]?.trim() ?? "";
139
+ const isValidKey = /^[\w.-]+$/.test(keyPart);
140
+
141
+ if (!isValidKey || isExcludedCommentedKey(keyValue)) {
142
+ return {
143
+ uncommented: null,
144
+ newConsecutive: state.consecutiveCommentedKeys,
145
+ };
146
+ }
147
+
148
+ const keyIndent = indent.length;
149
+ const newConsecutive = updateConsecutiveCount(
150
+ lines,
151
+ i,
152
+ state.consecutiveCommentedKeys,
153
+ );
154
+ const likelyExampleCtx = isLikelyExample(lines, i);
155
+
156
+ const shouldUncomment =
157
+ !likelyExampleCtx &&
158
+ (state.lastRealKeyIndent === -1 ||
159
+ Math.abs(keyIndent - state.lastRealKeyIndent) <= 4 ||
160
+ newConsecutive >= 2);
161
+
162
+ if (shouldUncomment) {
163
+ return { uncommented: `${indent}${keyValue}`, newConsecutive };
164
+ }
165
+
166
+ return { uncommented: null, newConsecutive };
167
+ }
168
+
169
+ export function preprocessYAMLComments(yamlContent: string): string {
170
+ const lines = yamlContent.split("\n");
171
+ const processedLines: string[] = [];
172
+ const state: PreprocessState = {
173
+ inExampleBlock: false,
174
+ inBlockScalar: false,
175
+ lastRealKeyIndent: -1,
176
+ consecutiveCommentedKeys: 0,
177
+ };
178
+
179
+ for (let i = 0; i < lines.length; i++) {
180
+ const line = lines[i] ?? "";
181
+ const trimmed = line.trim();
182
+
183
+ if (isExampleMarker(trimmed)) {
184
+ state.inExampleBlock = true;
185
+ processedLines.push(line);
186
+ continue;
187
+ }
188
+
189
+ if (state.inExampleBlock && shouldExitExampleBlock(trimmed)) {
190
+ state.inExampleBlock = false;
191
+ }
192
+
193
+ if (prevLineHasBlockScalar(lines, i)) {
194
+ state.inBlockScalar = true;
195
+ }
196
+
197
+ if (state.inBlockScalar && !isBlockScalarContent(line, trimmed)) {
198
+ state.inBlockScalar = false;
199
+ }
200
+
201
+ if (!trimmed.startsWith("#") && /^[\w.-]+:/.test(trimmed)) {
202
+ state.lastRealKeyIndent = line.search(/\S/);
203
+ state.consecutiveCommentedKeys = 0;
204
+ }
205
+
206
+ if (state.inExampleBlock || state.inBlockScalar) {
207
+ processedLines.push(line);
208
+ state.consecutiveCommentedKeys = 0;
209
+ continue;
210
+ }
211
+
212
+ const { uncommented, newConsecutive } = tryUncommentLine(
213
+ line,
214
+ lines,
215
+ i,
216
+ state,
217
+ );
218
+ state.consecutiveCommentedKeys = newConsecutive;
219
+
220
+ if (uncommented != null) {
221
+ processedLines.push(uncommented);
222
+ continue;
223
+ }
224
+
225
+ // Reset consecutive count if not a commented key
226
+ const isCommentedKey = /^[ \t]*#+\s*[\w.-]+:\s*(?:\S.*)?$/.test(line);
227
+ if (!isCommentedKey) {
228
+ state.consecutiveCommentedKeys = 0;
229
+ }
230
+
231
+ processedLines.push(line);
232
+ }
233
+
234
+ return processedLines.join("\n");
235
+ }