Skip to content

Instantly share code, notes, and snippets.

@dejurin
Created April 17, 2025 11:34
Show Gist options
  • Save dejurin/9a8cefda8c3a59b46972bdcb3a1908db to your computer and use it in GitHub Desktop.
Save dejurin/9a8cefda8c3a59b46972bdcb3a1908db to your computer and use it in GitHub Desktop.
Convert various source URLs (GitHub, npm, unpkg, WordPress) to jsDelivr CDN URLs.
/**
* Convert various source URLs (GitHub, npm, unpkg, WordPress) to jsDelivr CDN URLs.
* @param sourceUrl — the original file URL
* @returns jsDelivr URL or null if the format is not recognized
*/
export function toJsDelivr(sourceUrl: string): string | null {
const url = new URL(sourceUrl);
const { hostname, pathname, searchParams } = url;
// GitHub: handle both github.com/blob/... and raw.githubusercontent.com
let match = pathname.match(
/^\/([^/]+)\/([^/]+)\/(?:blob|raw)\/([^/]+)\/(.+)$/
);
if (hostname === 'github.com' && match) {
const [, user, repo, version, filePath] = match;
return `https://cdn.jsdelivr.net/gh/${user}/${repo}@${version}/${filePath}`;
}
match = pathname.match(
/^\/([^/]+)\/([^/]+)\/([^/]+)\/(.+)$/
);
if (hostname === 'raw.githubusercontent.com' && match) {
const [, user, repo, version, filePath] = match;
return `https://cdn.jsdelivr.net/gh/${user}/${repo}@${version}/${filePath}`;
}
// npmjs.com: convert /package/<pkg>/v/<ver>?path=<file> to /npm/
match = pathname.match(/^\/package\/([^/]+)(?:\/v\/([^/]+))?$/);
if (hostname.endsWith('npmjs.com') && match) {
const [, pkg, version] = match;
const file = searchParams.get('path') ?? '';
const verSegment = version ? `@${version}` : '';
return `https://cdn.jsdelivr.net/npm/${pkg}${verSegment}/${file}`;
}
// unpkg.com: simply rebase to /npm/
match = pathname.match(/^\/([^@/]+)@([^/]+)\/(.+)$/);
if (hostname === 'unpkg.com' && match) {
const [, pkg, version, filePath] = match;
return `https://cdn.jsdelivr.net/npm/${pkg}@${version}/${filePath}`;
}
// WordPress plugins: /plugins/<proj>/(tags/<ver> | trunk)/<file>
match = pathname.match(
/^\/plugins\/([^/]+)\/(?:tags\/([^/]+)|trunk)\/(.+)$/
);
if (hostname === 'wordpress.org' && match) {
const [, project, version, filePath] = match;
const ref = version ? `tags/${version}` : 'trunk';
return `https://cdn.jsdelivr.net/wp/plugins/${project}/${ref}/${filePath}`;
}
// WordPress themes: /themes/<proj>/<ver>/<file>
match = pathname.match(/^\/themes\/([^/]+)\/([^/]+)\/(.+)$/);
if (hostname === 'wordpress.org' && match) {
const [, project, version, filePath] = match;
return `https://cdn.jsdelivr.net/wp/themes/${project}/${version}/${filePath}`;
}
// Unknown format
return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment