linkedPaths
The paths of the app a rendered page links to, as it follows them: an <a href> under the app's base, with no
download, target or rel="external" (as useAppLinks leaves to the browser), to a page (no extension but
.html). Their query and fragment are the page's to read, so they're not part of the path.
export function linkedPaths(html: string, at: string, base: string): string[] { const origin = "http://tcm.static"; const found = new Set<string>(); for (const [tag] of html.matchAll(/<a\s[^>]*>/gi)) { const attr = (name: string) => new RegExp(`\\s${name}(?:\\s*=\\s*"([^"]*)")?(?=[\\s/>])`, "i").exec(tag!); const href = attr("href")?.[1]; if (href === undefined || attr("download") || /\bexternal\b/.test(attr("rel")?.[1] ?? "")) continue; if ((attr("target")?.[1] ?? "_self") !== "_self") continue; let url: URL; try { url = new URL(href.replace(/&/g, "&"), `${origin}${at}`); } catch { continue; } if (url.origin !== origin) continue; const within = !base ? url.pathname : url.pathname === base ? "/" : url.pathname.startsWith(`${base}/`) ? url.pathname.slice(base.length) : undefined; if (within === undefined || /\.(?!html$)[^./]+$/.test(within)) continue; found.add(within); } return [...found]; }