(lines, startIndex, indent)
| 125 | } |
| 126 | |
| 127 | function parseBlock(lines, startIndex, indent) { |
| 128 | const firstIndex = nextMeaningfulIndex(lines, startIndex); |
| 129 | if (firstIndex === -1) { |
| 130 | return { value: {}, nextIndex: lines.length }; |
| 131 | } |
| 132 | |
| 133 | const firstLine = lines[firstIndex]; |
| 134 | const isArray = firstLine.trim().startsWith("- "); |
| 135 | const container = isArray ? [] : {}; |
| 136 | let index = firstIndex; |
| 137 | |
| 138 | while (index < lines.length) { |
| 139 | const line = lines[index]; |
| 140 | const trimmed = line.trim(); |
| 141 | if (!trimmed || trimmed.startsWith("#")) { |
| 142 | index += 1; |
| 143 | continue; |
| 144 | } |
| 145 | |
| 146 | const currentIndent = countIndent(line); |
| 147 | if (currentIndent < indent) { |
| 148 | break; |
| 149 | } |
| 150 | if (currentIndent > indent) { |
| 151 | throw new Error(`Unexpected indentation at line ${index + 1}`); |
| 152 | } |
| 153 | |
| 154 | if (isArray) { |
| 155 | if (!trimmed.startsWith("- ")) { |
| 156 | break; |
| 157 | } |
| 158 | const payload = trimmed.slice(2).trim(); |
| 159 | index += 1; |
| 160 | if (!payload) { |
| 161 | const nested = parseBlock(lines, index, indent + 2); |
| 162 | container.push(nested.value); |
| 163 | index = nested.nextIndex; |
| 164 | } else { |
| 165 | container.push(parseScalar(payload)); |
| 166 | } |
| 167 | continue; |
| 168 | } |
| 169 | |
| 170 | const match = /^([A-Za-z0-9_-]+):(.*)$/.exec(trimmed); |
| 171 | if (!match) { |
| 172 | throw new Error(`Invalid key/value pair at line ${index + 1}`); |
| 173 | } |
| 174 | |
| 175 | const [, key, remainder] = match; |
| 176 | if (remainder.trim()) { |
| 177 | const blockScalar = parseBlockScalarHeader(remainder); |
| 178 | if (blockScalar) { |
| 179 | const parsed = parseBlockScalar(lines, index + 1, indent, blockScalar.style); |
| 180 | container[key] = parsed.value; |
| 181 | index = parsed.nextIndex; |
| 182 | continue; |
| 183 | } |
| 184 |
no test coverage detected