Spaces:
Running
Running
mfn
Share: permanent links (?w=) that open as your own copy; sign in with Hugging Face to share
aab2748 Download src/lib/deepLink.ts from mrfakename/flow: direct link, hf CLI and curl.
- Browser
- Download file 3.55 kB
-
https://huggingface.co/spaces/mrfakename/flow/resolve/main/src/lib/deepLink.ts
- Command line
-
hf download hf://spaces/mrfakename/flow/src/lib/deepLink.ts
-
curl -L -o deepLink.ts https://huggingface.co/spaces/mrfakename/flow/resolve/main/src/lib/deepLink.ts
3.55 kB
| /** | |
| * `?space=owner/name[&fn=/endpoint]` deep link ("Open in Flow" badges). The Space is read on load, kept in | |
| * sessionStorage so it survives the sign-in redirect, and added once the editor is up. | |
| * Kept free of app imports: main.tsx and hfAuth use it before the editor loads. | |
| */ | |
| const KEY = "flow-pending-space"; | |
| const FN_KEY = "flow-pending-fn"; | |
| const FN = /^\/?[\w.-]{1,80}$/; | |
| const ID = /^[\w.-]+\/[\w.-]+$/; | |
| const SUB = /^[a-z0-9-]+$/; | |
| /** `owner/name`, or `sub:<subdomain>` for a *.hf.space URL (resolved later from the Space's config). */ | |
| export function normaliseSpace(raw: string): string | null { | |
| const s = raw.trim(); | |
| if (ID.test(s)) return s; | |
| let u: URL; | |
| try { | |
| u = new URL(s); | |
| } catch { | |
| return null; | |
| } | |
| if (u.protocol !== "https:" && u.protocol !== "http:") return null; | |
| if (u.hostname === "huggingface.co" || u.hostname === "www.huggingface.co") { | |
| const m = u.pathname.match(/^\/spaces\/([^/]+)\/([^/]+)/); | |
| const id = m ? `${m[1]}/${m[2]}` : ""; | |
| return ID.test(id) ? id : null; | |
| } | |
| if (u.hostname.endsWith(".hf.space")) { | |
| const sub = u.hostname.split(".")[0]; | |
| return SUB.test(sub) ? `sub:${sub}` : null; | |
| } | |
| return null; | |
| } | |
| /** Reads `?space=` into the stash and drops it from the address bar so a refresh doesn't add it twice. */ | |
| export function stashSpaceParam() { | |
| const q = new URLSearchParams(location.search); | |
| if (!q.has("space")) return; | |
| const v = normaliseSpace(q.get("space") ?? ""); | |
| const fn = (q.get("fn") ?? "").trim(); | |
| q.delete("space"); | |
| q.delete("fn"); | |
| const s = q.toString(); | |
| history.replaceState(history.state, "", `${location.pathname}${s ? `?${s}` : ""}${location.hash}`); | |
| if (!v) return; | |
| try { | |
| sessionStorage.setItem(KEY, v); | |
| if (FN.test(fn)) sessionStorage.setItem(FN_KEY, fn.replace(/^\//, "")); | |
| else sessionStorage.removeItem(FN_KEY); | |
| } catch { | |
| /* storage blocked */ | |
| } | |
| } | |
| /** The endpoint asked for with `&fn=`, without the leading slash. */ | |
| export function pendingFn(): string | null { | |
| try { | |
| return sessionStorage.getItem(FN_KEY); | |
| } catch { | |
| return null; | |
| } | |
| } | |
| export function pendingSpace(): string | null { | |
| try { | |
| return sessionStorage.getItem(KEY); | |
| } catch { | |
| return null; | |
| } | |
| } | |
| /** Returns the pending Space (and endpoint, if one was asked for) and forgets them. */ | |
| export function takePendingSpace(): { id: string; fn: string | null } | null { | |
| const v = pendingSpace(); | |
| const fn = pendingFn(); | |
| try { | |
| sessionStorage.removeItem(KEY); | |
| sessionStorage.removeItem(FN_KEY); | |
| } catch { | |
| /* storage blocked */ | |
| } | |
| return v ? { id: v, fn } : null; | |
| } | |
| /* `?w=<id>` share link: same idea, kept until the editor is up and the viewer has said yes. */ | |
| const SHARE_KEY = "flow-pending-share"; | |
| const SHARE = /^[A-Za-z0-9]{10}$/; | |
| /** Reads `?w=` into the stash and drops it from the address bar. */ | |
| export function stashShareParam() { | |
| const q = new URLSearchParams(location.search); | |
| if (!q.has("w")) return; | |
| const v = (q.get("w") ?? "").trim(); | |
| q.delete("w"); | |
| const s = q.toString(); | |
| history.replaceState(history.state, "", `${location.pathname}${s ? `?${s}` : ""}${location.hash}`); | |
| if (!SHARE.test(v)) return; | |
| try { | |
| sessionStorage.setItem(SHARE_KEY, v); | |
| } catch { | |
| /* storage blocked */ | |
| } | |
| } | |
| export function pendingShare(): string | null { | |
| try { | |
| return sessionStorage.getItem(SHARE_KEY); | |
| } catch { | |
| return null; | |
| } | |
| } | |
| export function clearPendingShare() { | |
| try { | |
| sessionStorage.removeItem(SHARE_KEY); | |
| } catch { | |
| /* storage blocked */ | |
| } | |
| } | |