(elements: MarkdownToken[])
| 492 | |
| 493 | // Recursively process elements to find text nodes |
| 494 | function processElements(elements: MarkdownToken[]) { |
| 495 | for (const element of elements) { |
| 496 | if (element.type === 'code' || element.type === 'codespan') { |
| 497 | continue |
| 498 | } |
| 499 | |
| 500 | // For html tokens that contain comments, strip the comment spans and |
| 501 | // check the residual for @paths (e.g. `<!-- note --> @./file.md`). |
| 502 | // Other html tokens (non-comment tags) are skipped entirely. |
| 503 | if (element.type === 'html') { |
| 504 | const raw = element.raw || '' |
| 505 | const trimmed = raw.trimStart() |
| 506 | if (trimmed.startsWith('<!--') && trimmed.includes('-->')) { |
| 507 | const commentSpan = /<!--[\s\S]*?-->/g |
| 508 | const residue = raw.replace(commentSpan, '') |
| 509 | if (residue.trim().length > 0) { |
| 510 | extractPathsFromText(residue) |
| 511 | } |
| 512 | } |
| 513 | continue |
| 514 | } |
| 515 | |
| 516 | // Process text nodes |
| 517 | if (element.type === 'text') { |
| 518 | extractPathsFromText(element.text || '') |
| 519 | } |
| 520 | |
| 521 | // Recurse into children tokens |
| 522 | if (element.tokens) { |
| 523 | processElements(element.tokens) |
| 524 | } |
| 525 | |
| 526 | // Special handling for list structures |
| 527 | if (element.items) { |
| 528 | processElements(element.items) |
| 529 | } |
| 530 | } |
| 531 | } |
| 532 | |
| 533 | processElements(tokens as MarkdownToken[]) |
| 534 | return [...absolutePaths] |
no test coverage detected