/** * The site registry: per-service identity knowledge, one adapter per service * (the same knowledge-as-data pattern as tidy-rules.ts). An adapter answers * "is this host yours?" and "what's the native content id in this URL?", and * from the id derives the canonical URL and the cache-identity key — so every * spelling of one video (watch, youtu.be, shorts, live, embed, music., * nocookie, nested redirects) collapses to ONE identity. * * Extraction is WHATWG-URL based, nested-redirect aware, and percent-decode * tolerant — no regex URL parsing. Adding a service (spotify, vimeo, …) is * one more adapter entry. * * Also exported standalone as `@adriangalilea/utils/url/sites`: this module * is dependency-free (no linkifyjs, no tracking dataset), so libraries that * only need content identity (a video id from any URL spelling) can import * it without pulling the full url module's weight. */ export interface SiteAdapter { /** The service name, and the prefix of its identity keys ("youtube"). */ name: string; /** Whether this (lowercased, www-less) host belongs to the service. */ matches(host: string): boolean; /** The service's native content id in this URL, or null. */ id(url: URL): string | null; /** The canonical URL for a content id. */ canonicalUrl(id: string): string; /** The cache-identity key for a content id ("youtube:dQw4w9WgXcQ"). */ key(id: string): string; } /** * The 11-char video id from ANY YouTube URL spelling or a bare id; null if * the input isn't one. Percent-encoded input gets one decode attempt so a * copied-from-HTML link still resolves. */ export declare function youtubeVideoId(input: string): string | null; /** * A BARE token as a video id, strictly validated: the 11-char shape alone also * matches ordinary words ("regressions"), so a bare id must additionally carry * base64 noise - a DIGIT or MIXED CASE. A dash/underscore alone does NOT * qualify: hyphenated English ("author-only", "worker-side") is 11 chars often * enough to hijack prose. Real ids lacking both signals are ~0.02% rare; a URL * spelling never needs this (use {@link youtubeVideoId}). This is THE gate for * treating loose chat text as a video: fail it and the text is words, not an * id - do not engage. Callers additionally scope WHERE it runs (xtldr: only * when the whole message is the one token, never a paragraph scan). */ export declare function bareYoutubeVideoId(input: string): string | null; /** The canonical watch URL for a video id or any YouTube URL spelling; null if neither. */ export declare function youtubeUrl(idOrUrl: string): string | null; /** * A public thumbnail URL for a video id or any YouTube URL spelling; null if * neither. Uses `hqdefault`, which exists for every valid video (unlike * `maxresdefault`, which 404s for many). */ export declare function youtubeThumbnailUrl(idOrUrl: string): string | null; /** * Add or replace the playhead offset (`t=90s`) on a YouTube video URL, * preserving the URL's shape and other params. A bare id gets the canonical * watch URL first. Non-video input is returned unchanged. */ export declare function youtubeTimestampUrl(idOrUrl: string, seconds: number): string; export declare const SITES: readonly SiteAdapter[]; /** The adapter owning this (lowercased, www-less) host, or null. */ export declare function siteFor(host: string): SiteAdapter | null; //# sourceMappingURL=sites.d.ts.map