(markdown: string)
| 25 | * `cleanPath` transform. Returns deduped candidate strings. |
| 26 | */ |
| 27 | export function extractCandidateCodePaths(markdown: string): string[] { |
| 28 | const stripped = markdown |
| 29 | .replace(FENCED_CODE_BLOCK, "") |
| 30 | .replace(HTML_COMMENT, ""); |
| 31 | |
| 32 | const candidates = new Set<string>(); |
| 33 | |
| 34 | let m: RegExpExecArray | null; |
| 35 | const backtickRe = new RegExp(BACKTICK_SPAN.source, "g"); |
| 36 | while ((m = backtickRe.exec(stripped)) !== null) { |
| 37 | const inner = m[1].trim(); |
| 38 | if (isCodeFilePath(inner)) { |
| 39 | candidates.add(inner.replace(/#.*$/, "")); |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | for (const line of stripped.split("\n")) { |
| 44 | const urlRanges: Array<[number, number]> = []; |
| 45 | const urlRe = new RegExp(URL_REGEX.source, "g"); |
| 46 | while ((m = urlRe.exec(line)) !== null) { |
| 47 | urlRanges.push([m.index, m.index + m[0].length]); |
| 48 | } |
| 49 | |
| 50 | const pathRe = new RegExp(CODE_PATH_BARE_REGEX.source, "g"); |
| 51 | while ((m = pathRe.exec(line)) !== null) { |
| 52 | const start = m.index; |
| 53 | const end = start + m[0].length; |
| 54 | const prev = start === 0 ? "" : line[start - 1]; |
| 55 | if (/\w/.test(prev)) continue; |
| 56 | const overlapsUrl = urlRanges.some( |
| 57 | ([s, e]) => start < e && end > s, |
| 58 | ); |
| 59 | if (overlapsUrl) continue; |
| 60 | if (!isCodeFilePathStrict(m[0])) continue; |
| 61 | candidates.add(m[0].replace(/#.*$/, "")); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | return Array.from(candidates); |
| 66 | } |
no test coverage detected