Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778export interface MarkupContext { /** `owner/repo` */ repo: string; ref: string; dir?: string; host?: string; camo?: boolean;}
const ABSOLUTE = /^[a-z][a-z0-9+.-]*:|^\/\//i;
export const isAbsoluteUrl = (url: string): boolean => ABSOLUTE.test(url);
export const isRepoRelative = (url: string): boolean => url !== "" && !isAbsoluteUrl(url) && !url.startsWith("#");
// `.` and `..` have to collapse here instead of reaching the urlconst normalize = (path: string): string => { const parts: string[] = []; for (const part of path.split("/")) { if (part === "" || part === ".") continue; if (part === "..") parts.pop(); else parts.push(part); } return parts.join("/");};
const withinRepo = (path: string, ctx: MarkupContext): string => normalize(path.startsWith("/") ? path : `${ctx.dir ?? ""}/${path}`);
const splitSuffix = (url: string): [string, string] => { const at = url.search(/[?#]/); return at === -1 ? [url, ""] : [url.slice(0, at), url.slice(at)];};
// markdown-it percent-encodes destinations before we ever see them, so only the// ref still needs encodingconst repoUrl = (kind: string, url: string, ctx: MarkupContext): string => { const [path, suffix] = splitSuffix(url); if (path === "") return url; const ref = encodeURIComponent(ctx.ref); return `/${ctx.repo}/${kind}/${ref}/${withinRepo(path, ctx)}${suffix}`;};
export const treeUrl = (url: string, ctx: MarkupContext): string => repoUrl("tree", url, ctx);
export const rawUrl = (url: string, ctx: MarkupContext): string => repoUrl("raw", url, ctx);
const hostOf = (url: string): string | null => { try { // the base only matters for protocol relative urls, which have a host anyway return new URL(url, "https://invalid.").host; } catch { return null; }};
// camo wants the target hex encodedconst toHex = (value: string): string => Array.from(new TextEncoder().encode(value), (byte) => byte.toString(16).padStart(2, "0")).join( "" );
export const mediaUrl = (url: string, ctx: MarkupContext): string => { if (isRepoRelative(url)) return rawUrl(url, ctx); if (!ctx.camo || !isAbsoluteUrl(url) || hostOf(url) === ctx.host) return url; return `/camo/${toHex(url)}`;};
export const mediaSrcset = (srcset: string, ctx: MarkupContext): string => srcset .split(",") .map((candidate) => { const [url, ...descriptors] = candidate.trim().split(/\s+/); return [mediaUrl(url, ctx), ...descriptors].join(" "); }) .join(", ");