(lines: Array<string>, headingIndex: number)
| 1231 | } |
| 1232 | |
| 1233 | function parseSection(lines: Array<string>, headingIndex: number): { |
| 1234 | readonly body: string | null |
| 1235 | readonly nextIndex: number |
| 1236 | readonly diagnostics: ReadonlyArray<JSDocDiagnostic> |
| 1237 | } { |
| 1238 | const diagnostics: Array<JSDocDiagnostic> = [] |
| 1239 | if (lines[headingIndex + 1]?.trim() !== "") { |
| 1240 | diagnostics.push( |
| 1241 | diagnostic("invalid-spacing", `${lines[headingIndex].trim()} must be followed by exactly one blank line`) |
| 1242 | ) |
| 1243 | } |
| 1244 | let index = headingIndex + 2 |
| 1245 | const bodyStart = index |
| 1246 | let inFence = false |
| 1247 | while (index < lines.length) { |
| 1248 | const trimmed = lines[index].trim() |
| 1249 | if (trimmed.startsWith("```")) { |
| 1250 | if (isTypeScriptFence(trimmed)) { |
| 1251 | diagnostics.push(diagnostic("loose-ts-fence", "TypeScript examples must use **Example** (Title) sections")) |
| 1252 | } |
| 1253 | inFence = !inFence |
| 1254 | } |
| 1255 | if (!inFence && trimmed === "" && isHeadingLine(lines[index + 1])) { |
| 1256 | break |
| 1257 | } |
| 1258 | if (!inFence && trimmed !== "" && isForbiddenMarkdownHeading(trimmed, false)) { |
| 1259 | diagnostics.push(diagnostic("invalid-heading", "Markdown headings are not allowed in JSDoc descriptions")) |
| 1260 | } |
| 1261 | if ( |
| 1262 | !inFence && isBoldOnlyLine(trimmed) && !standardHeadings.includes(trimmed as StandardHeading) && |
| 1263 | !trimmed.startsWith("**Example**") |
| 1264 | ) { |
| 1265 | diagnostics.push(diagnostic("unknown-heading", `Unknown JSDoc section heading: ${trimmed}`)) |
| 1266 | } |
| 1267 | index++ |
| 1268 | } |
| 1269 | const bodyLines = lines.slice(bodyStart, index) |
| 1270 | if (joinBody(bodyLines).trim() === "") { |
| 1271 | diagnostics.push(diagnostic("empty-section", `${lines[headingIndex].trim()} must have a non-empty body`)) |
| 1272 | } |
| 1273 | if (bodyLines.at(-1)?.trim() === "") { |
| 1274 | diagnostics.push(diagnostic("invalid-spacing", "Section bodies must not end with extra blank lines")) |
| 1275 | } |
| 1276 | return { body: joinBody(bodyLines), nextIndex: index, diagnostics } |
| 1277 | } |
| 1278 | |
| 1279 | const isTypeScriptFence = (line: string): boolean => /^```ts(?:\s.*)?$/.test(line) |
| 1280 |
no test coverage detected