(source: string)
| 90 | * Anything that's already gh:/github:/local is returned unchanged. |
| 91 | */ |
| 92 | export function normalizeGithubSource(source: string): string { |
| 93 | const s = source.trim(); |
| 94 | if (s.startsWith('gh:') || s.startsWith('github:')) return s; |
| 95 | const m = /^https?:\/\/github\.com\/([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)(?:\/(blob|tree)\/([^/\s]+)((?:\/[^\s?#]+)*))?/.exec(s); |
| 96 | if (!m) return s; // not a github web URL — leave as-is |
| 97 | const user = m[1]!; |
| 98 | const repo = m[2]!.replace(/\.git$/, ''); |
| 99 | const ref = m[4]; |
| 100 | let subpath = m[5] ? m[5].replace(/^\//, '') : ''; |
| 101 | // A blob link points at a file; drop a trailing /SKILL.md (any case) so the |
| 102 | // subpath is the directory the manifest lives in. |
| 103 | if (subpath) subpath = subpath.replace(/\/SKILL\.md$/i, ''); |
| 104 | let out = `gh:${user}/${repo}`; |
| 105 | if (ref) out += `@${ref}`; |
| 106 | if (subpath) out += `#${subpath}`; |
| 107 | return out; |
| 108 | } |
| 109 | |
| 110 | /** Parse GitHub source links out of a markdown catalog (README). */ |
| 111 | export function parseGithubLinksFromMarkdown(md: string): string[] { |
no outgoing calls
no test coverage detected