(lines: Array<string>, headingIndex: number)
| 1213 | } |
| 1214 | return { |
| 1215 | value: { |
| 1216 | description: { |
| 1217 | short: joinBody(shortLines), |
| 1218 | whenToUse: sections["**When to use**"], |
| 1219 | details: sections["**Details**"], |
| 1220 | gotchas: sections["**Gotchas**"] |
| 1221 | }, |
| 1222 | examples |
| 1223 | }, |
| 1224 | diagnostics |
| 1225 | } |
| 1226 | } |
| 1227 | |
| 1228 | function hasWhenToUsePrefix(text: string): boolean { |
| 1229 | const trimmed = text.trimStart() |
| 1230 | return whenToUsePrefixes.some((prefix) => trimmed === prefix || trimmed.startsWith(`${prefix} `)) |
| 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 | } |
no test coverage detected
searching dependent graphs…