({ documents, existingPaths, manifests })
| 13 | }; |
| 14 | |
| 15 | export function auditPackageDocs({ documents, existingPaths, manifests }) { |
| 16 | const errors = []; |
| 17 | |
| 18 | for (const [manifestPath, requiredFiles] of Object.entries(packageRequirements)) { |
| 19 | const publishedFiles = manifests[manifestPath]?.files ?? []; |
| 20 | for (const requiredFile of requiredFiles) { |
| 21 | if (!publishedFiles.includes(requiredFile)) { |
| 22 | errors.push(`${manifestPath} must publish package documentation path ${requiredFile}.`); |
| 23 | } |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | for (const [documentPath, source] of documents) { |
| 28 | if (/rxjs\.dev|apps\/rxjs\.dev/i.test(source)) { |
| 29 | errors.push(`${documentPath} must not depend on the separate documentation-site workstream.`); |
| 30 | } |
| 31 | |
| 32 | for (const target of markdownLinkTargets(source)) { |
| 33 | if (/^(?:https?:|mailto:|#)/.test(target)) continue; |
| 34 | if (!target.includes('/') && !/\.[a-z0-9]+(?:#|$)/i.test(target)) continue; |
| 35 | const [targetPath] = target.split('#'); |
| 36 | if (!targetPath) continue; |
| 37 | const resolved = path.posix.normalize(path.posix.join(path.posix.dirname(documentPath), decodeURIComponent(targetPath))); |
| 38 | if (!existingPaths.has(resolved)) errors.push(`${documentPath} has a missing local link: ${target}.`); |
| 39 | const packageMatch = documentPath.match(/^(packages\/[^/]+)\//); |
| 40 | if (packageMatch && resolved !== packageMatch[1] && !resolved.startsWith(`${packageMatch[1]}/`)) { |
| 41 | errors.push(`${documentPath} has a local link outside its package container: ${target}.`); |
| 42 | } |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | return errors; |
| 47 | } |
| 48 | |
| 49 | function markdownLinkTargets(source) { |
| 50 | return [...source.matchAll(/!?\[[^\]]*\]\(([^)]+)\)/g)] |
no test coverage detected