pagegraph 0.8.4 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +158 -6
- package/dist/audit.d.ts +7 -0
- package/dist/audit.js +33 -7
- package/dist/audit.js.map +1 -1
- package/dist/cli.js +3827 -2198
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +14 -1
- package/dist/config.js.map +1 -1
- package/dist/{checks-6noG_xTS.d.ts → content-DVL2iyGU.d.ts} +274 -126
- package/dist/content-DbyJoRpj.js +1384 -0
- package/dist/content-DbyJoRpj.js.map +1 -0
- package/dist/index.d.ts +19 -8
- package/dist/index.js +31 -555
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/links-BFJc-pJ9.js +0 -318
- package/dist/links-BFJc-pJ9.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"links-BFJc-pJ9.js","names":[],"sources":["../src/core/links.ts"],"sourcesContent":["/**\n * Pure link-graph utilities: read anchors out of rendered HTML, model the\n * rendered graph, compute homepage depth, and diff it against the declared\n * graph. Effect- and framework-free so it runs in the CLI, a Worker, or a test\n * on the same data.\n *\n * This is the \"served HTML\" half of the SEO graph: the declared graph describes\n * intent, this describes what a crawler actually receives.\n */\n\n/** Where an anchor sits in the document, coarsely. */\nexport type AnchorRegion = \"nav\" | \"footer\" | \"header\" | \"body\";\n\nexport interface Anchor {\n readonly href: string;\n readonly text: string;\n readonly region: AnchorRegion;\n /** True when the resolved target shares the page's origin. */\n readonly internal: boolean;\n}\n\nexport interface LinkEdge {\n readonly from: string;\n readonly to: string;\n readonly region: AnchorRegion;\n}\n\nexport interface RenderedGraph {\n /** Every same-origin page path the crawl rendered, in first-seen order. */\n readonly nodes: ReadonlyArray<string>;\n readonly edges: ReadonlyArray<LinkEdge>;\n readonly internalEdges: ReadonlyArray<LinkEdge>;\n /** Same-origin body-region edges: the contextual surface. */\n readonly contextualEdges: ReadonlyArray<LinkEdge>;\n /** Same-origin pages with no incoming internal edge (\"reachable only via nav\" is not implied). */\n readonly orphans: ReadonlyArray<string>;\n readonly depthByPath: ReadonlyMap<string, number>;\n readonly maxDepth: number | null;\n}\n\nconst REGION_TAGS = new Set([\"nav\", \"footer\", \"header\"]);\n\nconst TOKEN =\n /<(\\/?)(nav|footer|header)\\b[^>]*>|<a\\b([^>]*)>([\\s\\S]*?)<\\/a>/gi;\n\n// A real `href` attribute is preceded by whitespace (or the tag's start). The\n// boundary keeps `data-href`, `xhref`, and similar attributes from reading as\n// links, and stops a decoy from winning over a genuine `href`.\nconst HREF = /(?:^|\\s)href\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))/i;\n\nconst BASE_TAG = /<base\\b[^>]*>/gi;\n\nconst NON_NAVIGABLE = /^(?:#|mailto:|tel:|javascript:|data:)/i;\n\nconst stripTags = (value: string): string => value.replace(/<[^>]*>/g, \" \");\n\nconst decodeEntities = (value: string): string =>\n value\n .replace(/ /gi, \" \")\n .replace(/&/gi, \"&\")\n .replace(/</gi, \"<\")\n .replace(/>/gi, \">\")\n .replace(/"/gi, \"\\\"\")\n .replace(/'|'/gi, \"'\");\n\nconst anchorText = (value: string): string =>\n decodeEntities(stripTags(value)).replace(/\\s+/g, \" \").trim();\n\n/** Normalize a same-origin URL to the graph's path key (no query/hash; \"/\" preserved). */\nexport const normalizePath = (url: URL): string => {\n const path = url.pathname.replace(/\\/+$/, \"\");\n return path === \"\" ? \"/\" : path;\n};\n\nconst hrefValue = (attributes: string): string | undefined => {\n const match = HREF.exec(attributes);\n if (match === null) return undefined;\n return match[1] ?? match[2] ?? match[3];\n};\n\n/**\n * The document base URL. Browsers use the first `<base>` element that has an\n * `href` attribute and ignore every later one, so a `<base>` carrying only\n * `target` is skipped, but the first `<base href>` wins even when its value is\n * empty (it then resolves to the document URL) or invalid (the base is ignored,\n * resolving to the document URL). With no `<base href>` at all, links resolve\n * against the response URL.\n */\nconst documentBase = (html: string, responseUrl: URL): URL => {\n BASE_TAG.lastIndex = 0;\n let tag: RegExpExecArray | null;\n while ((tag = BASE_TAG.exec(html)) !== null) {\n const href = hrefValue(tag[0]);\n if (href === undefined) continue;\n if (href.length === 0) return responseUrl;\n try {\n return new URL(href, responseUrl);\n } catch {\n return responseUrl;\n }\n }\n return responseUrl;\n};\n\n/**\n * Extract every anchor in document order, tagging each with the region tag it\n * sits inside. Anchor text keeps only its letters and a coarse entity decode;\n * this is a classifier input, not a renderer.\n */\nexport const extractAnchors = (html: string, baseUrl: string): ReadonlyArray<Anchor> => {\n const base = new URL(baseUrl);\n const resolutionBase = documentBase(html, base);\n const regions: Array<AnchorRegion> = [];\n const anchors: Array<Anchor> = [];\n TOKEN.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = TOKEN.exec(html)) !== null) {\n const closing = match[1];\n const regionTag = match[2];\n if (regionTag !== undefined) {\n const region = regionTag.toLowerCase() as AnchorRegion;\n if (closing === \"/\") {\n const index = regions.lastIndexOf(region);\n if (index !== -1) regions.splice(index, 1);\n } else {\n regions.push(region);\n }\n continue;\n }\n const attributes = match[3];\n const raw = hrefValue(attributes);\n if (raw === undefined || raw.length === 0 || NON_NAVIGABLE.test(raw)) continue;\n let resolved: URL;\n try {\n resolved = new URL(raw, resolutionBase);\n } catch {\n continue;\n }\n if (resolved.protocol !== \"http:\" && resolved.protocol !== \"https:\") continue;\n const region = regions.length === 0 ? \"body\" : regions[regions.length - 1]!;\n anchors.push({\n href: resolved.href,\n text: anchorText(match[4] ?? \"\"),\n region,\n internal: resolved.origin === base.origin,\n });\n }\n return anchors;\n};\n\nexport interface RenderedPage {\n readonly url: string;\n readonly anchors: ReadonlyArray<Anchor>;\n}\n\nconst breadthFirstDepth = (\n edges: ReadonlyArray<LinkEdge>,\n root: string,\n): ReadonlyMap<string, number> => {\n const adjacency = new Map<string, Set<string>>();\n for (const edge of edges) {\n const targets = adjacency.get(edge.from) ?? new Set<string>();\n targets.add(edge.to);\n adjacency.set(edge.from, targets);\n }\n const depth = new Map<string, number>([[root, 0]]);\n const queue: Array<string> = [root];\n while (queue.length > 0) {\n const current = queue.shift()!;\n const currentDepth = depth.get(current)!;\n for (const next of adjacency.get(current) ?? []) {\n if (depth.has(next)) continue;\n depth.set(next, currentDepth + 1);\n queue.push(next);\n }\n }\n return depth;\n};\n\n/**\n * Assemble a {@link RenderedGraph} from page/edge sets. Edges are already\n * same-origin and path-keyed by the callers, so this is the shared, pure tail of\n * {@link buildRenderedGraph} and {@link renderedGraphFromEdges}.\n */\nconst graphFromEdges = (\n nodes: Set<string>,\n edges: Array<LinkEdge>,\n root: string,\n): RenderedGraph => {\n const rootKey = root.replace(/\\/+$/, \"\") || \"/\";\n const internalEdges = edges;\n const contextualEdges = edges.filter((edge) => edge.region === \"body\");\n const incoming = new Set(internalEdges.map((edge) => edge.to));\n const orphans = [...nodes].filter((path) => path !== rootKey && !incoming.has(path)).sort();\n const depthByPath = breadthFirstDepth(internalEdges, rootKey);\n let maxDepth: number | null = null;\n for (const value of depthByPath.values()) {\n if (maxDepth === null || value > maxDepth) maxDepth = value;\n }\n return {\n nodes: [...nodes],\n edges,\n internalEdges,\n contextualEdges,\n orphans,\n depthByPath,\n maxDepth,\n };\n};\n\n/**\n * Build the rendered graph from crawled pages. `origin` fixes the graph's\n * same-origin boundary — pages and anchors on another origin are dropped, not\n * silently folded in — and `root` is the normalized path the depth BFS starts\n * from (the seed's final path when the homepage redirected). Every page path is\n * keyed the way the declared graph keys its routes.\n */\nexport const buildRenderedGraph = (\n origin: string,\n pages: ReadonlyArray<RenderedPage>,\n root: string = \"/\",\n): RenderedGraph => {\n const originUrl = new URL(origin);\n const graphOrigin = originUrl.origin;\n const edges: Array<LinkEdge> = [];\n const nodes = new Set<string>();\n for (const page of pages) {\n let pageUrl: URL;\n try {\n pageUrl = new URL(page.url);\n } catch {\n continue;\n }\n if (pageUrl.origin !== graphOrigin) continue;\n const path = normalizePath(pageUrl);\n nodes.add(path);\n for (const anchor of page.anchors) {\n let targetUrl: URL;\n try {\n targetUrl = new URL(anchor.href);\n } catch {\n continue;\n }\n if (targetUrl.origin !== graphOrigin) continue;\n const target = normalizePath(targetUrl);\n if (target === path) continue;\n edges.push({ from: path, to: target, region: anchor.region });\n }\n }\n return graphFromEdges(nodes, edges, root);\n};\n\n/** A URL or an already-normalized graph path key both collapse to the path key. */\nconst pathKeyOf = (value: string): string => {\n try {\n return normalizePath(new URL(value));\n } catch {\n const pathname = value.split(/[?#]/, 1)[0] ?? \"\";\n return pathname.replace(/\\/+$/, \"\") || \"/\";\n }\n};\n\n/**\n * Rebuild a {@link RenderedGraph} from a rendered-edge set alone — the artifact\n * `pagegraph links verify --emit-rendered` writes. Path keys are normalized the\n * same way as a crawl, and `nodes` carries the rendered page paths the artifact\n * recorded, so an edge-less page (a redirect target with no internal links) stays\n * a node and its orphan/depth report survives replay. Without `nodes` the node set\n * falls back to the edge endpoints.\n */\nexport const renderedGraphFromEdges = (\n edges: ReadonlyArray<LinkEdge>,\n root: string = \"/\",\n nodes: ReadonlyArray<string> = [],\n): RenderedGraph => {\n const nodeSet = new Set(nodes.map(pathKeyOf));\n const kept: Array<LinkEdge> = [];\n for (const edge of edges) {\n const from = pathKeyOf(edge.from);\n const to = pathKeyOf(edge.to);\n nodeSet.add(from);\n nodeSet.add(to);\n kept.push({ from, to, region: edge.region });\n }\n return graphFromEdges(nodeSet, kept, root);\n};\n\nexport interface SimpleEdge {\n readonly from: string;\n readonly to: string;\n}\n\nexport interface LinkGraphDiff {\n /** Declared internal edges with no matching rendered anchor. */\n readonly declaredNotRendered: ReadonlyArray<SimpleEdge>;\n /** Rendered contextual edges that no declared edge accounts for. */\n readonly renderedNotDeclared: ReadonlyArray<SimpleEdge>;\n readonly declaredCount: number;\n readonly renderedContextualCount: number;\n}\n\nconst edgeKey = (edge: SimpleEdge): string => `${edge.from}\\u0000${edge.to}`;\n\nconst normalizeEdge = (edge: SimpleEdge): SimpleEdge => ({\n from: edge.from === \"\" ? \"/\" : edge.from.replace(/\\/+$/, \"\") || \"/\",\n to: edge.to === \"\" ? \"/\" : edge.to.replace(/\\/+$/, \"\") || \"/\",\n});\n\n/**\n * Diff rendered contextual edges against declared `related`/`crumb` edges. Both\n * sides are path-keyed; the diff is directional and reports each direction\n * separately because they call for different fixes.\n */\nexport const diffLinkGraph = (\n declared: ReadonlyArray<SimpleEdge>,\n rendered: RenderedGraph,\n): LinkGraphDiff => {\n const declaredNormalized = declared.map(normalizeEdge);\n const declaredKeys = new Set(declaredNormalized.map(edgeKey));\n const renderedKeys = new Set(rendered.contextualEdges.map(edgeKey));\n const declaredNotRendered = declaredNormalized.filter(\n (edge) => !renderedKeys.has(edgeKey(edge)),\n );\n const renderedNotDeclared = rendered.internalEdges\n .filter((edge) => edge.region === \"body\")\n .map((edge) => normalizeEdge(edge))\n .filter((edge) => !declaredKeys.has(edgeKey(edge)));\n return {\n declaredNotRendered,\n renderedNotDeclared,\n declaredCount: declaredNormalized.length,\n renderedContextualCount: rendered.contextualEdges.length,\n };\n};\n\n/** A page the crawl could not render; its outgoing anchors are absent. */\nexport interface RenderedEdgeFailure {\n readonly url: string;\n readonly error: string;\n}\n\n/**\n * Provenance for a rendered-edge artifact: enough to trust the edges and to\n * refuse a gate that would assert on an incomplete crawl. `root` is the seed's\n * normalized final path (its post-redirect path), so depth and orphans rebuild\n * exactly as the crawl computed them.\n */\nexport interface RenderedEdgeArtifactCrawl {\n /** Pages whose HTML was rendered into `edges`. */\n readonly pages: number;\n /** Normalized final path of the seed — the depth BFS root. */\n readonly root: string;\n /** The crawl's page budget (`--limit`). */\n readonly limit: number;\n /** True when discovery outran `limit`; a gate must not assert on this. */\n readonly truncated: boolean;\n /** True when any captured body was cut at `--max-body-bytes`. */\n readonly bodyTruncated: boolean;\n /** URLs whose captured body was cut; anchors past the cutoff are missing. */\n readonly truncatedPages: ReadonlyArray<string>;\n /** Pages that failed to fetch; their outgoing anchors are missing. */\n readonly failures: ReadonlyArray<RenderedEdgeFailure>;\n}\n\n/**\n * The stable, `decodeRenderedEdges`-compatible artifact `pagegraph links verify\n * --emit-rendered` writes and `--rendered` reads. It carries the raw served edges\n * (with `region`), the rendered page paths, and the provenance a coverage gate\n * needs to decide whether the crawl is trustworthy, so one crawl can be asserted\n * repeatedly without re-fetching.\n */\nexport interface RenderedEdgeArtifact {\n readonly kind: \"links-rendered\";\n readonly schemaVersion: 1;\n readonly origin: string;\n readonly seed: string;\n readonly crawl: RenderedEdgeArtifactCrawl;\n /** Normalized paths of every rendered page — replay's node set. */\n readonly nodes: ReadonlyArray<string>;\n readonly edges: ReadonlyArray<LinkEdge>;\n}\n\n/** The rendered-edge artifact schema this package writes and accepts. */\nexport const RENDERED_EDGE_ARTIFACT_SCHEMA_VERSION = 1 as const;\n\nconst ARTIFACT_KIND = \"links-rendered\";\n\nconst REGIONS: ReadonlySet<string> = new Set([\"nav\", \"footer\", \"header\", \"body\"]);\n\nconst decodeArtifactEdges = (input: unknown): ReadonlyArray<LinkEdge> => {\n if (!Array.isArray(input)) {\n throw new Error(\"`edges` must be an array of { from, to, region } edges\");\n }\n return input.map((item) => {\n if (item === null || typeof item !== \"object\") {\n throw new Error(\"each artifact edge must be an object with string `from` and `to`\");\n }\n const { from, to, region } = item as { from?: unknown; to?: unknown; region?: unknown };\n if (typeof from !== \"string\" || typeof to !== \"string\") {\n throw new Error(\"each artifact edge must have string `from` and `to`\");\n }\n if (region !== undefined && !REGIONS.has(region as string)) {\n throw new Error(\n `artifact edge region must be one of nav, footer, header, body (received ${JSON.stringify(region)})`,\n );\n }\n return { from, to, region: (region as AnchorRegion | undefined) ?? \"body\" };\n });\n};\n\nconst decodeArtifactNodes = (input: unknown): ReadonlyArray<string> => {\n if (input === undefined) return [];\n if (!Array.isArray(input) || !input.every((path) => typeof path === \"string\")) {\n throw new Error(\"rendered-edge artifact `nodes` must be an array of paths\");\n }\n return input;\n};\n\nconst decodeArtifactFailures = (input: unknown): ReadonlyArray<RenderedEdgeFailure> => {\n if (input === undefined) return [];\n if (!Array.isArray(input)) {\n throw new Error(\"rendered-edge artifact `crawl.failures` must be an array\");\n }\n return input.map((item) => {\n if (item === null || typeof item !== \"object\") {\n throw new Error(\"each artifact failure must be an object with string `url` and `error`\");\n }\n const { url, error } = item as { url?: unknown; error?: unknown };\n if (typeof url !== \"string\" || typeof error !== \"string\") {\n throw new Error(\"each artifact failure must have string `url` and `error`\");\n }\n return { url, error };\n });\n};\n\nconst requiredAbsoluteUrl = (value: unknown, field: string): string => {\n if (typeof value !== \"string\" || value === \"\") {\n throw new Error(`rendered-edge artifact must carry a non-empty string \\`${field}\\``);\n }\n try {\n void new URL(value);\n } catch {\n throw new Error(\n `rendered-edge artifact \\`${field}\\` must be an absolute URL (received ${JSON.stringify(value)})`,\n );\n }\n return value;\n};\n\nconst requiredInteger = (value: unknown, field: string, minimum: number): number => {\n if (!Number.isSafeInteger(value) || (value as number) < minimum) {\n throw new Error(\n `rendered-edge artifact \\`${field}\\` must be an integer >= ${minimum} (received ${JSON.stringify(value)})`,\n );\n }\n return value as number;\n};\n\n/**\n * Decode a rendered-edge artifact from user input. Throws on any other shape —\n * this is user input, not a provider payload. `root`, `bodyTruncated`,\n * `truncatedPages`, `failures`, and `nodes` are optional so a hand-written edge\n * dump that only carries provenance can still be replayed.\n */\nexport const decodeRenderedEdgeArtifact = (input: unknown): RenderedEdgeArtifact => {\n if (input === null || typeof input !== \"object\") {\n throw new Error(\"rendered-edge artifact must be an object\");\n }\n const value = input as Record<string, unknown>;\n if (value[\"kind\"] !== ARTIFACT_KIND) {\n throw new Error(\n `rendered-edge artifact \\`kind\\` must be \"${ARTIFACT_KIND}\" (received ${JSON.stringify(value[\"kind\"])})`,\n );\n }\n if (value[\"schemaVersion\"] !== RENDERED_EDGE_ARTIFACT_SCHEMA_VERSION) {\n throw new Error(\n `unsupported rendered-edge artifact schemaVersion: ${JSON.stringify(value[\"schemaVersion\"])}`,\n );\n }\n const origin = requiredAbsoluteUrl(value[\"origin\"], \"origin\");\n const seed = requiredAbsoluteUrl(value[\"seed\"], \"seed\");\n const crawl = value[\"crawl\"];\n if (crawl === null || typeof crawl !== \"object\") {\n throw new Error(\"rendered-edge artifact must carry a `crawl` object\");\n }\n const provenance = crawl as Record<string, unknown>;\n const truncatedPages = provenance[\"truncatedPages\"];\n if (\n truncatedPages !== undefined &&\n (!Array.isArray(truncatedPages) || !truncatedPages.every((url) => typeof url === \"string\"))\n ) {\n throw new Error(\"rendered-edge artifact `truncatedPages` must be an array of URLs\");\n }\n const bodyTruncated = provenance[\"bodyTruncated\"];\n if (bodyTruncated !== undefined && typeof bodyTruncated !== \"boolean\") {\n throw new Error(\"rendered-edge artifact `bodyTruncated` must be a boolean\");\n }\n if (typeof provenance[\"truncated\"] !== \"boolean\") {\n throw new Error(\"rendered-edge artifact `crawl.truncated` must be a boolean\");\n }\n return {\n kind: ARTIFACT_KIND,\n schemaVersion: RENDERED_EDGE_ARTIFACT_SCHEMA_VERSION,\n origin,\n seed,\n crawl: {\n pages: requiredInteger(provenance[\"pages\"], \"crawl.pages\", 0),\n root: typeof provenance[\"root\"] === \"string\" ? provenance[\"root\"] : pathKeyOf(seed),\n limit: requiredInteger(provenance[\"limit\"], \"crawl.limit\", 1),\n truncated: provenance[\"truncated\"],\n bodyTruncated: bodyTruncated === true,\n truncatedPages: (truncatedPages as ReadonlyArray<string> | undefined) ?? [],\n failures: decodeArtifactFailures(provenance[\"failures\"]),\n },\n nodes: decodeArtifactNodes(value[\"nodes\"]),\n edges: decodeArtifactEdges(value[\"edges\"]),\n };\n};\n"],"mappings":"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"}
|