mcp-web-validator 1.3.18 → 1.3.20

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.
@@ -1 +1 @@
1
- {"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"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","sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport * as fs from \"node:fs/promises\";\nimport { BlockList, isIP } from \"node:net\";\nimport * as path from \"node:path\";\nimport { getEncoding } from \"encoding-sniffer/sniffer\";\nimport { Agent } from \"undici\";\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_REDIRECTS = 5;\nconst DNS_TIMEOUT_MS = 5_000;\nconst MAX_URL_LENGTH = 8_192;\nconst HTML_ENCODING_SNIFF_BYTES = 1_024;\n\nconst blockedAddresses = new BlockList();\nfor (const [network, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"100.64.0.0\", 10],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.0.0.0\", 24],\n [\"192.0.2.0\", 24],\n [\"192.88.99.0\", 24],\n [\"192.168.0.0\", 16],\n [\"198.18.0.0\", 15],\n [\"198.51.100.0\", 24],\n [\"203.0.113.0\", 24],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4],\n] as const) {\n blockedAddresses.addSubnet(network, prefix, \"ipv4\");\n}\n\nfor (const [network, prefix] of [\n [\"::\", 96],\n [\"fc00::\", 7],\n [\"fe80::\", 10],\n [\"ff00::\", 8],\n [\"2001::\", 32],\n [\"2001:2::\", 48],\n [\"2001:10::\", 28],\n [\"2001:db8::\", 32],\n [\"2002::\", 16],\n] as const) {\n blockedAddresses.addSubnet(network, prefix, \"ipv6\");\n}\n\nconst publicIpv6Addresses = new BlockList();\npublicIpv6Addresses.addSubnet(\"2000::\", 3, \"ipv6\");\n\nconst blockedHostnames = new Set([\n \"localhost\",\n \"localhost.localdomain\",\n \"ip6-localhost\",\n \"ip6-loopback\",\n]);\n\nconst blockedHostnameSuffixes = [\n \".localhost\",\n \".local\",\n \".internal\",\n \".home.arpa\",\n \".test\",\n \".invalid\",\n \".example\",\n \".onion\",\n];\n\nconst redirectStatuses = new Set([301, 302, 303, 307, 308]);\n\nexport interface PublicFetchOptions {\n method?: \"GET\" | \"HEAD\";\n headers?: Record<string, string>;\n timeoutMs?: number;\n maxRedirects?: number;\n}\n\nexport interface PublicTextOptions extends PublicFetchOptions {\n maxBytes?: number;\n acceptedContentTypes?: readonly string[];\n}\n\nexport interface PublicTextResult {\n text: string;\n url: string;\n status: number;\n contentType: string | null;\n}\n\nexport interface PublicHttpResult {\n response: Response;\n url: URL;\n}\n\nexport interface ResolvedPublicHttpUrl {\n url: URL;\n addresses: Array<{ address: string; family: number }>;\n}\n\nexport class PublicUrlError extends Error {\n override readonly name = \"PublicUrlError\";\n}\n\nexport function getErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n if (error.name === \"TimeoutError\" || error.name === \"AbortError\") {\n return \"Request timed out\";\n }\n return error.message || error.name;\n }\n\n return typeof error === \"string\" && error.trim() ? error : \"Unknown error\";\n}\n\nfunction assertPositiveInteger(value: number, label: string): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${label} must be a positive integer`);\n }\n}\n\nfunction normalizeHostname(hostname: string): string {\n const withoutBrackets = hostname.startsWith(\"[\") && hostname.endsWith(\"]\")\n ? hostname.slice(1, -1)\n : hostname;\n return withoutBrackets.replace(/\\.$/, \"\").toLowerCase();\n}\n\nfunction isPublicAddress(address: string, family: number): boolean {\n if (family === 4) {\n return !blockedAddresses.check(address, \"ipv4\");\n }\n\n if (family === 6) {\n return publicIpv6Addresses.check(address, \"ipv6\")\n && !blockedAddresses.check(address, \"ipv6\");\n }\n\n return false;\n}\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n let timeout: NodeJS.Timeout | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n timeout = setTimeout(() => reject(new Error(`${label} timed out`)), timeoutMs);\n }),\n ]);\n } finally {\n if (timeout) {\n clearTimeout(timeout);\n }\n }\n}\n\n/**\n * Parses an HTTP(S) URL and rejects hostnames that resolve to local, private,\n * documentation, multicast, or otherwise non-public address space.\n */\nexport async function resolvePublicHttpUrl(input: string | URL): Promise<ResolvedPublicHttpUrl> {\n const rawUrl = input instanceof URL ? input.href : input;\n if (typeof rawUrl !== \"string\" || rawUrl.length === 0 || rawUrl.length > MAX_URL_LENGTH) {\n throw new PublicUrlError(`URL must contain between 1 and ${MAX_URL_LENGTH} characters`);\n }\n\n let parsed: URL;\n try {\n parsed = new URL(rawUrl);\n } catch {\n throw new PublicUrlError(\"URL must be an absolute HTTP or HTTPS URL\");\n }\n\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new PublicUrlError(\"Only HTTP and HTTPS URLs are allowed\");\n }\n if (parsed.username || parsed.password) {\n throw new PublicUrlError(\"URLs containing credentials are not allowed\");\n }\n // URL normalizes matching defaults (HTTP :80 / HTTPS :443) to an empty port.\n // Any remaining port is custom or mismatched to the scheme and must be rejected.\n if (parsed.port) {\n throw new PublicUrlError(\"Only default HTTP and HTTPS ports are allowed\");\n }\n\n parsed.hash = \"\";\n const hostname = normalizeHostname(parsed.hostname);\n if (!hostname) {\n throw new PublicUrlError(\"URL hostname is required\");\n }\n if (\n blockedHostnames.has(hostname)\n || blockedHostnameSuffixes.some((suffix) => hostname.endsWith(suffix))\n ) {\n throw new PublicUrlError(`URL hostname \"${hostname}\" is not public`);\n }\n\n const literalFamily = isIP(hostname);\n const resolvedAddresses = literalFamily\n ? [{ address: hostname, family: literalFamily }]\n : await withTimeout(\n lookup(hostname, { all: true, verbatim: true }),\n DNS_TIMEOUT_MS,\n \"DNS lookup\",\n ).catch((error: unknown) => {\n throw new PublicUrlError(`Unable to resolve URL hostname: ${getErrorMessage(error)}`);\n });\n\n if (resolvedAddresses.length === 0) {\n throw new PublicUrlError(\"URL hostname did not resolve to an address\");\n }\n\n for (const record of resolvedAddresses) {\n if (!isPublicAddress(record.address, record.family)) {\n throw new PublicUrlError(`URL hostname resolves to non-public address ${record.address}`);\n }\n }\n\n return { url: parsed, addresses: resolvedAddresses };\n}\n\nexport async function assertPublicHttpUrl(input: string | URL): Promise<URL> {\n return (await resolvePublicHttpUrl(input)).url;\n}\n\nexport async function cancelResponseBody(response: Response): Promise<void> {\n if (!response.body) {\n return;\n }\n\n try {\n await response.body.cancel();\n } catch {\n // The stream may already be closed or consumed; there is nothing left to release.\n }\n}\n\nfunction getDeclaredCharacterEncoding(contentType: string | null): string | undefined {\n if (!contentType) {\n return undefined;\n }\n\n const match = /(?:^|;)\\s*charset\\s*=\\s*(?:\"([^\"]*)\"|([^;\\s]*))/i.exec(contentType);\n if (!match) {\n return undefined;\n }\n return (match[1] ?? match[2] ?? \"\").trim();\n}\n\nfunction isSupportedCharacterEncoding(encoding: string): boolean {\n try {\n new TextDecoder(encoding);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readResponseText(\n response: Response,\n maxBytes: number,\n encoding?: string,\n sniffHtmlEncoding = false,\n): Promise<string> {\n assertPositiveInteger(maxBytes, \"maxBytes\");\n\n const declaredLength = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {\n await cancelResponseBody(response);\n throw new Error(`Response exceeds the ${maxBytes}-byte limit`);\n }\n\n if (!response.body) {\n return \"\";\n }\n\n const reader = response.body.getReader();\n let totalBytes = 0;\n let text = \"\";\n let decoder: TextDecoder | undefined;\n let pendingChunks: Uint8Array[] = [];\n let pendingBytes = 0;\n\n const createDecoder = async (encodingLabel: string): Promise<TextDecoder> => {\n try {\n return new TextDecoder(encodingLabel);\n } catch {\n await reader.cancel();\n throw new Error(`Unsupported response character encoding \"${encodingLabel}\"`);\n }\n };\n\n const startDecoder = async (): Promise<void> => {\n if (decoder) return;\n let encodingLabel = encoding ?? \"utf-8\";\n if (encoding === undefined && sniffHtmlEncoding) {\n const sniffLength = Math.min(pendingBytes, HTML_ENCODING_SNIFF_BYTES);\n const sniffBytes = new Uint8Array(sniffLength);\n let copied = 0;\n for (const chunk of pendingChunks) {\n if (copied >= sniffLength) break;\n const length = Math.min(chunk.byteLength, sniffLength - copied);\n sniffBytes.set(chunk.subarray(0, length), copied);\n copied += length;\n }\n encodingLabel = getEncoding(sniffBytes, {\n maxBytes: HTML_ENCODING_SNIFF_BYTES,\n defaultEncoding: \"utf-8\",\n });\n }\n decoder = await createDecoder(encodingLabel);\n for (const chunk of pendingChunks) {\n text += decoder.decode(chunk, { stream: true });\n }\n pendingChunks = [];\n pendingBytes = 0;\n };\n\n if (encoding !== undefined || !sniffHtmlEncoding) {\n await startDecoder();\n }\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(`Response exceeds the ${maxBytes}-byte limit`);\n }\n\n if (!decoder) {\n pendingChunks.push(value);\n pendingBytes += value.byteLength;\n if (pendingBytes >= HTML_ENCODING_SNIFF_BYTES) {\n await startDecoder();\n }\n } else {\n text += decoder.decode(value, { stream: true });\n }\n }\n await startDecoder();\n if (!decoder) {\n throw new Error(\"Response decoder was not initialized\");\n }\n text += decoder.decode();\n return text;\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction createPinnedDispatcher(\n resolvedAddresses: ReadonlyArray<{ address: string; family: number }>,\n): Agent {\n const addresses = resolvedAddresses.map((record) => ({ ...record }));\n\n return new Agent({\n // Every validated request gets its own non-reused connection so a later DNS\n // answer cannot replace the address set approved for this hop.\n pipelining: 0,\n connect: {\n lookup: (_hostname, options, callback) => {\n const requestedFamily = options.family === 4 || options.family === 6 ? options.family : 0;\n const candidates = requestedFamily\n ? addresses.filter((record) => record.family === requestedFamily)\n : addresses;\n\n if (candidates.length === 0) {\n const error = new Error(\"No validated address is available for the requested IP family\") as NodeJS.ErrnoException;\n error.code = \"ENOTFOUND\";\n callback(error, []);\n return;\n }\n\n if (options.all) {\n callback(null, candidates);\n return;\n }\n\n const selected = candidates[0];\n callback(null, selected.address, selected.family);\n },\n },\n });\n}\n\nfunction beginClosingDispatcher(dispatcher: Agent): void {\n // close() waits for the active response stream to finish, so starting it here\n // releases the request-scoped Agent without interrupting callers reading the body.\n void dispatcher.close().catch(() => {});\n}\n\n/** Fetches a public HTTP(S) URL while validating every redirect target. */\nexport async function fetchPublicHttp(\n input: string | URL,\n options: PublicFetchOptions = {},\n): Promise<PublicHttpResult> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;\n assertPositiveInteger(timeoutMs, \"timeoutMs\");\n if (!Number.isSafeInteger(maxRedirects) || maxRedirects < 0 || maxRedirects > 10) {\n throw new Error(\"maxRedirects must be an integer between 0 and 10\");\n }\n\n let currentTarget = await resolvePublicHttpUrl(input);\n for (let redirectCount = 0; ; redirectCount += 1) {\n const dispatcher = createPinnedDispatcher(currentTarget.addresses);\n let response: Response;\n try {\n response = await fetch(currentTarget.url, {\n method: options.method ?? \"GET\",\n headers: options.headers,\n redirect: \"manual\",\n signal: AbortSignal.timeout(timeoutMs),\n dispatcher,\n } as RequestInit & { dispatcher: Agent });\n } catch (error) {\n await dispatcher.close();\n throw error;\n }\n\n if (!redirectStatuses.has(response.status)) {\n beginClosingDispatcher(dispatcher);\n return { response, url: currentTarget.url };\n }\n\n const location = response.headers.get(\"location\");\n if (!location) {\n beginClosingDispatcher(dispatcher);\n return { response, url: currentTarget.url };\n }\n\n if (redirectCount >= maxRedirects) {\n beginClosingDispatcher(dispatcher);\n return { response, url: currentTarget.url };\n }\n\n await cancelResponseBody(response);\n await dispatcher.close();\n let redirectUrl: URL;\n try {\n redirectUrl = new URL(location, currentTarget.url);\n } catch {\n throw new PublicUrlError(\"Redirect target is not a valid URL\");\n }\n currentTarget = await resolvePublicHttpUrl(redirectUrl);\n }\n}\n\n/** Fetches bounded text from a public URL and rejects non-success responses. */\nexport async function fetchPublicText(\n input: string | URL,\n options: PublicTextOptions = {},\n): Promise<PublicTextResult> {\n const maxBytes = options.maxBytes ?? 2_000_000;\n assertPositiveInteger(maxBytes, \"maxBytes\");\n\n const { response, url } = await fetchPublicHttp(input, {\n method: \"GET\",\n headers: options.headers,\n timeoutMs: options.timeoutMs,\n maxRedirects: options.maxRedirects,\n });\n\n if (!response.ok) {\n const status = response.status;\n await cancelResponseBody(response);\n throw new Error(`URL returned HTTP status ${status}`);\n }\n\n const contentTypeHeader = response.headers.get(\"content-type\");\n const contentType = contentTypeHeader?.split(\";\", 1)[0]?.trim().toLowerCase() || null;\n if (\n options.acceptedContentTypes\n && !options.acceptedContentTypes.some((accepted) => accepted.trim().toLowerCase() === contentType)\n ) {\n await cancelResponseBody(response);\n throw new Error(`URL returned unsupported content type ${contentType ?? \"missing\"}`);\n }\n\n const declaredEncoding = getDeclaredCharacterEncoding(contentTypeHeader);\n const shouldSniffHtmlEncoding = contentType === \"text/html\"\n && (declaredEncoding === undefined || !isSupportedCharacterEncoding(declaredEncoding));\n return {\n text: await readResponseText(\n response,\n maxBytes,\n shouldSniffHtmlEncoding ? undefined : declaredEncoding,\n shouldSniffHtmlEncoding,\n ),\n url: url.href,\n status: response.status,\n contentType: contentTypeHeader,\n };\n}\n\n/** Reads a UTF-8 file only when it is a regular file within the requested cap. */\nexport async function readTextFile(filePath: string, maxBytes: number): Promise<string> {\n assertPositiveInteger(maxBytes, \"maxBytes\");\n const resolvedPath = path.resolve(filePath);\n const stats = await fs.stat(resolvedPath);\n if (!stats.isFile()) {\n throw new Error(`Path is not a regular file: ${resolvedPath}`);\n }\n if (stats.size > maxBytes) {\n throw new Error(`File exceeds the ${maxBytes}-byte limit: ${resolvedPath}`);\n }\n\n const contents = await fs.readFile(resolvedPath);\n if (contents.byteLength > maxBytes) {\n throw new Error(`File exceeds the ${maxBytes}-byte limit: ${resolvedPath}`);\n }\n return contents.toString(\"utf8\");\n}\n"]}
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"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","sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport * as fs from \"node:fs/promises\";\nimport { BlockList, isIP } from \"node:net\";\nimport * as path from \"node:path\";\nimport { getEncoding } from \"encoding-sniffer/sniffer\";\nimport { Agent } from \"undici\";\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_REDIRECTS = 5;\nconst DNS_TIMEOUT_MS = 5_000;\nconst MAX_URL_LENGTH = 8_192;\nconst HTML_ENCODING_SNIFF_BYTES = 1_024;\n\nconst blockedAddresses = new BlockList();\nfor (const [network, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"100.64.0.0\", 10],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.0.0.0\", 24],\n [\"192.0.2.0\", 24],\n [\"192.88.99.0\", 24],\n [\"192.168.0.0\", 16],\n [\"198.18.0.0\", 15],\n [\"198.51.100.0\", 24],\n [\"203.0.113.0\", 24],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4],\n] as const) {\n blockedAddresses.addSubnet(network, prefix, \"ipv4\");\n}\n\nfor (const [network, prefix] of [\n [\"::\", 96],\n [\"fc00::\", 7],\n [\"fe80::\", 10],\n [\"ff00::\", 8],\n [\"2001::\", 32],\n [\"2001:2::\", 48],\n [\"2001:10::\", 28],\n [\"2001:db8::\", 32],\n [\"2002::\", 16],\n] as const) {\n blockedAddresses.addSubnet(network, prefix, \"ipv6\");\n}\n\nconst publicIpv6Addresses = new BlockList();\npublicIpv6Addresses.addSubnet(\"2000::\", 3, \"ipv6\");\n\nconst blockedHostnames = new Set([\n \"localhost\",\n \"localhost.localdomain\",\n \"ip6-localhost\",\n \"ip6-loopback\",\n]);\n\nconst blockedHostnameSuffixes = [\n \".localhost\",\n \".local\",\n \".internal\",\n \".home.arpa\",\n \".test\",\n \".invalid\",\n \".example\",\n \".onion\",\n];\n\nconst redirectStatuses = new Set([301, 302, 303, 307, 308]);\n\nexport interface PublicFetchOptions {\n method?: \"GET\" | \"HEAD\";\n headers?: Record<string, string>;\n timeoutMs?: number;\n maxRedirects?: number;\n}\n\nexport interface PublicTextOptions extends PublicFetchOptions {\n maxBytes?: number;\n acceptedContentTypes?: readonly string[];\n}\n\nexport interface PublicTextResult {\n text: string;\n url: string;\n status: number;\n contentType: string | null;\n}\n\nexport interface PublicHttpResult {\n response: Response;\n url: URL;\n}\n\nexport interface ResolvedPublicHttpUrl {\n url: URL;\n addresses: Array<{ address: string; family: number }>;\n}\n\nexport class PublicUrlError extends Error {\n override readonly name = \"PublicUrlError\";\n}\n\nexport function getErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n if (error.name === \"TimeoutError\" || error.name === \"AbortError\") {\n return \"Request timed out\";\n }\n return error.message || error.name;\n }\n\n return typeof error === \"string\" && error.trim() ? error : \"Unknown error\";\n}\n\nfunction assertPositiveInteger(value: number, label: string): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${label} must be a positive integer`);\n }\n}\n\nfunction normalizeHostname(hostname: string): string {\n const withoutBrackets = hostname.startsWith(\"[\") && hostname.endsWith(\"]\")\n ? hostname.slice(1, -1)\n : hostname;\n return withoutBrackets.replace(/\\.$/, \"\").toLowerCase();\n}\n\nfunction isPublicAddress(address: string, family: number): boolean {\n if (family === 4) {\n return !blockedAddresses.check(address, \"ipv4\");\n }\n\n if (family === 6) {\n return publicIpv6Addresses.check(address, \"ipv6\")\n && !blockedAddresses.check(address, \"ipv6\");\n }\n\n return false;\n}\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n let timeout: NodeJS.Timeout | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n timeout = setTimeout(() => reject(new Error(`${label} timed out`)), timeoutMs);\n }),\n ]);\n } finally {\n if (timeout) {\n clearTimeout(timeout);\n }\n }\n}\n\n/**\n * Parses an HTTP(S) URL and rejects hostnames that resolve to local, private,\n * documentation, multicast, or otherwise non-public address space.\n */\nexport async function resolvePublicHttpUrl(input: string | URL): Promise<ResolvedPublicHttpUrl> {\n const rawUrl = input instanceof URL ? input.href : input;\n if (typeof rawUrl !== \"string\" || rawUrl.length === 0 || rawUrl.length > MAX_URL_LENGTH) {\n throw new PublicUrlError(`URL must contain between 1 and ${MAX_URL_LENGTH} characters`);\n }\n\n let parsed: URL;\n try {\n parsed = new URL(rawUrl);\n } catch {\n throw new PublicUrlError(\"URL must be an absolute HTTP or HTTPS URL\");\n }\n\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new PublicUrlError(\"Only HTTP and HTTPS URLs are allowed\");\n }\n if (parsed.username || parsed.password) {\n throw new PublicUrlError(\"URLs containing credentials are not allowed\");\n }\n // URL normalizes matching defaults (HTTP :80 / HTTPS :443) to an empty port.\n // Any remaining port is custom or mismatched to the scheme and must be rejected.\n if (parsed.port) {\n throw new PublicUrlError(\"Only default HTTP and HTTPS ports are allowed\");\n }\n\n parsed.hash = \"\";\n const hostname = normalizeHostname(parsed.hostname);\n if (!hostname) {\n throw new PublicUrlError(\"URL hostname is required\");\n }\n if (\n blockedHostnames.has(hostname)\n || blockedHostnameSuffixes.some((suffix) => hostname.endsWith(suffix))\n ) {\n throw new PublicUrlError(`URL hostname \"${hostname}\" is not public`);\n }\n\n const literalFamily = isIP(hostname);\n const resolvedAddresses = literalFamily\n ? [{ address: hostname, family: literalFamily }]\n : await withTimeout(\n lookup(hostname, { all: true, verbatim: true }),\n DNS_TIMEOUT_MS,\n \"DNS lookup\",\n ).catch((error: unknown) => {\n throw new PublicUrlError(`Unable to resolve URL hostname: ${getErrorMessage(error)}`);\n });\n\n if (resolvedAddresses.length === 0) {\n throw new PublicUrlError(\"URL hostname did not resolve to an address\");\n }\n\n for (const record of resolvedAddresses) {\n if (!isPublicAddress(record.address, record.family)) {\n throw new PublicUrlError(`URL hostname resolves to non-public address ${record.address}`);\n }\n }\n\n return { url: parsed, addresses: resolvedAddresses };\n}\n\nexport async function assertPublicHttpUrl(input: string | URL): Promise<URL> {\n return (await resolvePublicHttpUrl(input)).url;\n}\n\nexport async function cancelResponseBody(response: Response): Promise<void> {\n if (!response.body) {\n return;\n }\n\n try {\n await response.body.cancel();\n } catch {\n // The stream may already be closed or consumed; there is nothing left to release.\n }\n}\n\nfunction getDeclaredCharacterEncoding(contentType: string | null): string | undefined {\n if (!contentType) {\n return undefined;\n }\n\n const match = /(?:^|;)\\s*charset\\s*=\\s*(?:\"([^\"]*)\"|([^;\\s]*))/i.exec(contentType);\n if (!match) {\n return undefined;\n }\n return (match[1] ?? match[2] ?? \"\").trim();\n}\n\nfunction isSupportedCharacterEncoding(encoding: string): boolean {\n try {\n new TextDecoder(encoding);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getXmlBomCharacterEncoding(bytes: Uint8Array): string | undefined {\n if (bytes.length >= 4) {\n if (bytes[0] === 0x00 && bytes[1] === 0x00 && bytes[2] === 0xfe && bytes[3] === 0xff) {\n return \"utf-32be\";\n }\n if (bytes[0] === 0xff && bytes[1] === 0xfe && bytes[2] === 0x00 && bytes[3] === 0x00) {\n return \"utf-32le\";\n }\n }\n if (bytes.length >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) {\n return \"utf-8\";\n }\n if (bytes.length >= 2) {\n if (bytes[0] === 0xfe && bytes[1] === 0xff) {\n return \"utf-16be\";\n }\n if (bytes[0] === 0xff && bytes[1] === 0xfe) {\n return \"utf-16le\";\n }\n }\n return undefined;\n}\n\nfunction getXmlCharacterEncoding(bytes: Uint8Array): string {\n const bomEncoding = getXmlBomCharacterEncoding(bytes);\n if (bomEncoding) {\n return bomEncoding;\n }\n if (bytes.length >= 4) {\n if (bytes[0] === 0x00 && bytes[1] === 0x3c && bytes[2] === 0x00 && bytes[3] === 0x3f) {\n return \"utf-16be\";\n }\n if (bytes[0] === 0x3c && bytes[1] === 0x00 && bytes[2] === 0x3f && bytes[3] === 0x00) {\n return \"utf-16le\";\n }\n }\n\n const declarationBytes = bytes.subarray(0, HTML_ENCODING_SNIFF_BYTES);\n let declaration = \"\";\n for (const byte of declarationBytes) {\n declaration += byte < 0x80 ? String.fromCharCode(byte) : \"\\ufffd\";\n }\n const match = /^<\\?xml\\s+[^?]*\\bencoding\\s*=\\s*([\"'])([^\"']+)\\1/i.exec(declaration);\n return match?.[2].trim() || \"utf-8\";\n}\n\nexport async function readResponseText(\n response: Response,\n maxBytes: number,\n encoding?: string,\n sniffHtmlEncoding = false,\n sniffXmlEncoding = false,\n preferXmlBom = false,\n): Promise<string> {\n assertPositiveInteger(maxBytes, \"maxBytes\");\n\n const declaredLength = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {\n await cancelResponseBody(response);\n throw new Error(`Response exceeds the ${maxBytes}-byte limit`);\n }\n\n if (!response.body) {\n return \"\";\n }\n\n const reader = response.body.getReader();\n let totalBytes = 0;\n let text = \"\";\n let decoder: TextDecoder | undefined;\n let pendingChunks: Uint8Array[] = [];\n let pendingBytes = 0;\n\n const createDecoder = async (encodingLabel: string): Promise<TextDecoder> => {\n try {\n return new TextDecoder(encodingLabel);\n } catch {\n await reader.cancel();\n throw new Error(`Unsupported response character encoding \"${encodingLabel}\"`);\n }\n };\n\n const startDecoder = async (): Promise<void> => {\n if (decoder) return;\n let encodingLabel = encoding ?? \"utf-8\";\n if ((encoding === undefined && (sniffHtmlEncoding || sniffXmlEncoding)) || preferXmlBom) {\n const sniffLength = Math.min(pendingBytes, HTML_ENCODING_SNIFF_BYTES);\n const sniffBytes = new Uint8Array(sniffLength);\n let copied = 0;\n for (const chunk of pendingChunks) {\n if (copied >= sniffLength) break;\n const length = Math.min(chunk.byteLength, sniffLength - copied);\n sniffBytes.set(chunk.subarray(0, length), copied);\n copied += length;\n }\n if (preferXmlBom) {\n encodingLabel = getXmlBomCharacterEncoding(sniffBytes) ?? encodingLabel;\n } else {\n encodingLabel = sniffXmlEncoding\n ? getXmlCharacterEncoding(sniffBytes)\n : getEncoding(sniffBytes, {\n maxBytes: HTML_ENCODING_SNIFF_BYTES,\n defaultEncoding: \"utf-8\",\n });\n }\n }\n decoder = await createDecoder(encodingLabel);\n for (const chunk of pendingChunks) {\n text += decoder.decode(chunk, { stream: true });\n }\n pendingChunks = [];\n pendingBytes = 0;\n };\n\n if (!preferXmlBom && (encoding !== undefined || (!sniffHtmlEncoding && !sniffXmlEncoding))) {\n await startDecoder();\n }\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(`Response exceeds the ${maxBytes}-byte limit`);\n }\n\n if (!decoder) {\n pendingChunks.push(value);\n pendingBytes += value.byteLength;\n if (pendingBytes >= HTML_ENCODING_SNIFF_BYTES) {\n await startDecoder();\n }\n } else {\n text += decoder.decode(value, { stream: true });\n }\n }\n await startDecoder();\n if (!decoder) {\n throw new Error(\"Response decoder was not initialized\");\n }\n text += decoder.decode();\n return text;\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction createPinnedDispatcher(\n resolvedAddresses: ReadonlyArray<{ address: string; family: number }>,\n): Agent {\n const addresses = resolvedAddresses.map((record) => ({ ...record }));\n\n return new Agent({\n // Every validated request gets its own non-reused connection so a later DNS\n // answer cannot replace the address set approved for this hop.\n pipelining: 0,\n connect: {\n lookup: (_hostname, options, callback) => {\n const requestedFamily = options.family === 4 || options.family === 6 ? options.family : 0;\n const candidates = requestedFamily\n ? addresses.filter((record) => record.family === requestedFamily)\n : addresses;\n\n if (candidates.length === 0) {\n const error = new Error(\"No validated address is available for the requested IP family\") as NodeJS.ErrnoException;\n error.code = \"ENOTFOUND\";\n callback(error, []);\n return;\n }\n\n if (options.all) {\n callback(null, candidates);\n return;\n }\n\n const selected = candidates[0];\n callback(null, selected.address, selected.family);\n },\n },\n });\n}\n\nfunction beginClosingDispatcher(dispatcher: Agent): void {\n // close() waits for the active response stream to finish, so starting it here\n // releases the request-scoped Agent without interrupting callers reading the body.\n void dispatcher.close().catch(() => {});\n}\n\n/** Fetches a public HTTP(S) URL while validating every redirect target. */\nexport async function fetchPublicHttp(\n input: string | URL,\n options: PublicFetchOptions = {},\n): Promise<PublicHttpResult> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;\n assertPositiveInteger(timeoutMs, \"timeoutMs\");\n if (!Number.isSafeInteger(maxRedirects) || maxRedirects < 0 || maxRedirects > 10) {\n throw new Error(\"maxRedirects must be an integer between 0 and 10\");\n }\n\n let currentTarget = await resolvePublicHttpUrl(input);\n for (let redirectCount = 0; ; redirectCount += 1) {\n const dispatcher = createPinnedDispatcher(currentTarget.addresses);\n let response: Response;\n try {\n response = await fetch(currentTarget.url, {\n method: options.method ?? \"GET\",\n headers: options.headers,\n redirect: \"manual\",\n signal: AbortSignal.timeout(timeoutMs),\n dispatcher,\n } as RequestInit & { dispatcher: Agent });\n } catch (error) {\n await dispatcher.close();\n throw error;\n }\n\n if (!redirectStatuses.has(response.status)) {\n beginClosingDispatcher(dispatcher);\n return { response, url: currentTarget.url };\n }\n\n const location = response.headers.get(\"location\");\n if (!location) {\n beginClosingDispatcher(dispatcher);\n return { response, url: currentTarget.url };\n }\n\n if (redirectCount >= maxRedirects) {\n beginClosingDispatcher(dispatcher);\n return { response, url: currentTarget.url };\n }\n\n await cancelResponseBody(response);\n await dispatcher.close();\n let redirectUrl: URL;\n try {\n redirectUrl = new URL(location, currentTarget.url);\n } catch {\n throw new PublicUrlError(\"Redirect target is not a valid URL\");\n }\n currentTarget = await resolvePublicHttpUrl(redirectUrl);\n }\n}\n\n/** Fetches bounded text from a public URL and rejects non-success responses. */\nexport async function fetchPublicText(\n input: string | URL,\n options: PublicTextOptions = {},\n): Promise<PublicTextResult> {\n const maxBytes = options.maxBytes ?? 2_000_000;\n assertPositiveInteger(maxBytes, \"maxBytes\");\n\n const { response, url } = await fetchPublicHttp(input, {\n method: \"GET\",\n headers: options.headers,\n timeoutMs: options.timeoutMs,\n maxRedirects: options.maxRedirects,\n });\n\n if (!response.ok) {\n const status = response.status;\n await cancelResponseBody(response);\n throw new Error(`URL returned HTTP status ${status}`);\n }\n\n const contentTypeHeader = response.headers.get(\"content-type\");\n const contentType = contentTypeHeader?.split(\";\", 1)[0]?.trim().toLowerCase() || null;\n if (\n options.acceptedContentTypes\n && !options.acceptedContentTypes.some((accepted) => accepted.trim().toLowerCase() === contentType)\n ) {\n await cancelResponseBody(response);\n throw new Error(`URL returned unsupported content type ${contentType ?? \"missing\"}`);\n }\n\n const declaredEncoding = getDeclaredCharacterEncoding(contentTypeHeader);\n const shouldSniffHtmlEncoding = contentType === \"text/html\"\n && (declaredEncoding === undefined || !isSupportedCharacterEncoding(declaredEncoding));\n const isXmlContentType = contentType !== null\n && (contentType === \"application/xml\" || contentType === \"text/xml\" || contentType.endsWith(\"+xml\"));\n const shouldSniffXmlEncoding = declaredEncoding === undefined\n && isXmlContentType;\n const shouldPreferXmlBom = declaredEncoding !== undefined && isXmlContentType;\n return {\n text: await readResponseText(\n response,\n maxBytes,\n shouldSniffHtmlEncoding || shouldSniffXmlEncoding ? undefined : declaredEncoding,\n shouldSniffHtmlEncoding,\n shouldSniffXmlEncoding,\n shouldPreferXmlBom,\n ),\n url: url.href,\n status: response.status,\n contentType: contentTypeHeader,\n };\n}\n\n/** Reads a UTF-8 file only when it is a regular file within the requested cap. */\nexport async function readTextFile(filePath: string, maxBytes: number): Promise<string> {\n assertPositiveInteger(maxBytes, \"maxBytes\");\n const resolvedPath = path.resolve(filePath);\n const stats = await fs.stat(resolvedPath);\n if (!stats.isFile()) {\n throw new Error(`Path is not a regular file: ${resolvedPath}`);\n }\n if (stats.size > maxBytes) {\n throw new Error(`File exceeds the ${maxBytes}-byte limit: ${resolvedPath}`);\n }\n\n const contents = await fs.readFile(resolvedPath);\n if (contents.byteLength > maxBytes) {\n throw new Error(`File exceeds the ${maxBytes}-byte limit: ${resolvedPath}`);\n }\n return contents.toString(\"utf8\");\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { ValidationReport } from "./report.js";
2
- import type { LinkStatus, SEOIssue } from "./seo-auditor.js";
2
+ import type { AuditCounts, LinkStatus, SEOIssue } from "./seo-auditor.js";
3
3
  import { type CSSMessage, type W3CMessage } from "./w3c-validator.js";
4
4
  interface ValidationReportResult extends ValidationReport {
5
5
  errors?: string[];
@@ -9,8 +9,11 @@ export declare function htmlValidationContent(messages: W3CMessage[], source?: s
9
9
  warning: number;
10
10
  info: number;
11
11
  }): string;
12
- export declare function cssValidationContent(messages: CSSMessage[]): string;
13
- export declare function seoAuditContent(issues: SEOIssue[], totalIssues: number, truncated: boolean): string;
12
+ export declare function cssValidationContent(messages: CSSMessage[], totalMessages?: number, counts?: {
13
+ error: number;
14
+ compatibilityLimitation: number;
15
+ }): string;
16
+ export declare function seoAuditContent(issues: SEOIssue[], totalIssues: number, truncated: boolean, counts?: AuditCounts): string;
14
17
  export declare function schemaValidationContent(issues: SEOIssue[], totalIssues: number, truncated: boolean, htmlContent: string): string;
15
18
  export declare function linkCheckContent(links: LinkStatus[], baseUrl?: string): string;
16
19
  export declare function reportContent(reportData: ValidationReportResult): string;
@@ -110,8 +110,8 @@ export function htmlValidationContent(messages, source, totalMessages = messages
110
110
  : undefined,
111
111
  });
112
112
  }
113
- export function cssValidationContent(messages) {
114
- if (messages.length === 0) {
113
+ export function cssValidationContent(messages, totalMessages = messages.length, counts) {
114
+ if (totalMessages === 0) {
115
115
  return toolContent({
116
116
  title: "CSS validation",
117
117
  status: "clean",
@@ -120,13 +120,14 @@ export function cssValidationContent(messages) {
120
120
  });
121
121
  }
122
122
  const compatibilityLimitations = messages.filter((message) => message.compatibility === "known-validator-limitation");
123
- const actionableErrors = messages.length - compatibilityLimitations.length;
123
+ const compatibilityLimitationCount = counts?.compatibilityLimitation ?? compatibilityLimitations.length;
124
+ const actionableErrors = counts?.error ?? messages.length - compatibilityLimitations.length;
124
125
  return toolContent({
125
126
  title: "CSS validation",
126
127
  status: actionableErrors > 0 ? "attention needed" : "review suggested",
127
- outcome: compatibilityLimitations.length > 0
128
- ? `The W3C validator returned ${countLabel(messages.length, "CSS error")}; ${countLabel(compatibilityLimitations.length, "diagnostic")} ${compatibilityLimitations.length === 1 ? "matches" : "match"} a known validator limitation.`
129
- : `The W3C validator returned ${countLabel(messages.length, "CSS error")}.`,
128
+ outcome: compatibilityLimitationCount > 0
129
+ ? `The W3C validator returned ${countLabel(totalMessages, "CSS diagnostic")}; ${countLabel(compatibilityLimitationCount, "diagnostic")} ${compatibilityLimitationCount === 1 ? "matches" : "match"} a known validator limitation.`
130
+ : `The W3C validator returned ${countLabel(actionableErrors, "CSS error")}.`,
130
131
  actions: messages.map((message) => ({
131
132
  priority: message.compatibility === "known-validator-limitation" ? 2 : 0,
132
133
  message: message.context ? `${message.message} Context: ${message.context}` : message.message,
@@ -135,15 +136,20 @@ export function cssValidationContent(messages) {
135
136
  nextStep: actionableErrors > 0
136
137
  ? "Correct the actionable errors, then rerun CSS validation because one syntax issue can cause later diagnostics."
137
138
  : "Review the marked @container diagnostic against current CSS specifications; do not treat it as invalid CSS by itself.",
138
- note: compatibilityLimitations.length > 0
139
- ? "Jigsaw currently does not recognize the standards-defined @container rule. The upstream diagnostic is preserved and marked as a known validator limitation."
140
- : undefined,
139
+ note: [
140
+ compatibilityLimitationCount > 0
141
+ ? "Jigsaw currently does not recognize the standards-defined @container rule. The upstream diagnostic is preserved and marked as a known validator limitation."
142
+ : undefined,
143
+ totalMessages > messages.length
144
+ ? `Showing the first ${messages.length} of ${totalMessages} CSS diagnostics in structured output; summary counts include all returned Jigsaw diagnostics.`
145
+ : undefined,
146
+ ].filter(Boolean).join(" ") || undefined,
141
147
  });
142
148
  }
143
- export function seoAuditContent(issues, totalIssues, truncated) {
144
- const errors = issues.filter((issue) => issue.severity === "error").length;
145
- const warnings = issues.filter((issue) => issue.severity === "warning").length;
146
- const info = issues.filter((issue) => issue.severity === "info").length;
149
+ export function seoAuditContent(issues, totalIssues, truncated, counts) {
150
+ const errors = counts?.error ?? issues.filter((issue) => issue.severity === "error").length;
151
+ const warnings = counts?.warning ?? issues.filter((issue) => issue.severity === "warning").length;
152
+ const info = counts?.info ?? issues.filter((issue) => issue.severity === "info").length;
147
153
  if (totalIssues === 0) {
148
154
  return toolContent({
149
155
  title: "SEO audit",
@@ -346,9 +352,20 @@ export function reportContent(reportData) {
346
352
  .filter((check) => check !== "input")
347
353
  .map((check) => checkLabels[check]);
348
354
  const scoreNote = "The score is a triage heuristic based on these checks, not a Lighthouse score or a search-ranking prediction.";
349
- const truncationNote = reportData.htmlTruncated
350
- ? `Showing the first ${reportData.htmlMessages.length} of ${reportData.htmlTotalMessages} HTML diagnostics; HTML summary counts and scoring include all returned Nu diagnostics.`
351
- : undefined;
355
+ const truncationNote = [
356
+ reportData.htmlTruncated
357
+ ? `Showing the first ${reportData.htmlMessages.length} of ${reportData.htmlTotalMessages} HTML diagnostics; HTML summary counts and scoring include all returned Nu diagnostics.`
358
+ : undefined,
359
+ reportData.cssTruncated
360
+ ? `Showing the first ${reportData.cssMessages.length} of ${reportData.cssTotalMessages} CSS diagnostics; CSS summary counts and scoring include all returned Jigsaw diagnostics.`
361
+ : undefined,
362
+ reportData.seoTruncated
363
+ ? `Showing the first ${reportData.seoIssues.length} of ${reportData.seoTotalIssues} SEO findings; SEO summary counts and scoring include all findings.`
364
+ : undefined,
365
+ reportData.schemaTruncated
366
+ ? `Showing the first ${reportData.schemaIssues.length} of ${reportData.schemaTotalIssues} JSON-LD findings; JSON-LD summary counts and scoring include all findings.`
367
+ : undefined,
368
+ ].filter(Boolean).join(" ") || undefined;
352
369
  return toolContent({
353
370
  title: "Validation report",
354
371
  status,
@@ -1 +1 @@
1
- {"version":3,"file":"presentation.js","sourceRoot":"","sources":["../src/presentation.ts"],"names":[],"mappings":"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","sourcesContent":["import * as cheerio from \"cheerio\";\nimport type { ValidationReport } from \"./report.js\";\nimport type { LinkStatus, SEOIssue } from \"./seo-auditor.js\";\nimport {\n getW3CMessageSeverity,\n type CSSMessage,\n type W3CMessage,\n} from \"./w3c-validator.js\";\n\ntype ActionPriority = 0 | 1 | 2;\n\ninterface ActionItem {\n message: string;\n priority: ActionPriority;\n location?: string;\n}\n\ninterface ValidationReportResult extends ValidationReport {\n errors?: string[];\n}\n\nfunction collapseWhitespace(value: string, maxLength = 240): string {\n const collapsed = value.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Escapes untrusted text while leaving the surrounding, controlled Markdown intact. */\nfunction markdownText(value: string, maxLength = 240): string {\n return collapseWhitespace(value, maxLength)\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/([`*_[\\]{}()#+\\-.!|~])/g, \"\\\\$1\");\n}\n\n/** Wraps untrusted identifiers and paths in a code span that cannot be closed by their content. */\nfunction markdownCode(value: string, maxLength = 240): string {\n const collapsed = collapseWhitespace(value, maxLength);\n const longestBacktickRun = Math.max(\n 0,\n ...Array.from(collapsed.matchAll(/`+/g), (match) => match[0].length),\n );\n const delimiter = \"`\".repeat(longestBacktickRun + 1);\n const content = collapsed.startsWith(\"`\") || collapsed.endsWith(\"`\")\n ? ` ${collapsed} `\n : collapsed;\n return `${delimiter}${content}${delimiter}`;\n}\n\nfunction countLabel(count: number, singular: string, plural = `${singular}s`): string {\n return `${count} ${count === 1 ? singular : plural}`;\n}\n\nfunction priorityForSeverity(severity: string): ActionPriority {\n if (severity.toLowerCase() === \"error\") return 0;\n if (severity.toLowerCase() === \"warning\") return 1;\n return 2;\n}\n\nfunction formatLocation(line?: number, column?: number): string | undefined {\n if (line === undefined && column === undefined) return undefined;\n if (line === undefined) return `column ${column}`;\n if (column === undefined) return `line ${line}`;\n return `line ${line}, column ${column}`;\n}\n\nfunction formatActions(items: ActionItem[]): string | undefined {\n const prioritized = items\n .map((item, index) => ({ item, index }))\n .sort((left, right) => left.item.priority - right.item.priority || left.index - right.index)\n .slice(0, 3)\n .map(({ item }) => {\n const label = item.priority === 0 ? \"Error\" : item.priority === 1 ? \"Warning\" : \"Check\";\n const location = item.location\n ? ` · ${markdownCode(item.location, 120)}`\n : \"\";\n return `- **${label}**${location}: ${markdownText(item.message)}`;\n });\n\n return prioritized.length > 0 ? prioritized.join(\"\\n\") : undefined;\n}\n\nfunction toolContent(options: {\n title: string;\n status: string;\n outcome: string;\n nextStep: string;\n actions?: ActionItem[];\n note?: string;\n}): string {\n const sections = [\n `### ${options.title}: ${options.status}`,\n collapseWhitespace(options.outcome, 500),\n ];\n if (options.note) {\n sections.push(collapseWhitespace(options.note, 500));\n }\n const actionItems = options.actions ?? [];\n const actions = formatActions(actionItems);\n if (actions) {\n const hasActionableItem = actionItems.some((item) => item.priority < 2);\n const actionHeading = options.status === \"review suggested\" || !hasActionableItem ? \"Review\" : \"Fix first\";\n sections.push(`**${actionHeading}**\\n${actions}`);\n }\n sections.push(`**Next step:** ${collapseWhitespace(options.nextStep, 400)}`);\n return sections.join(\"\\n\\n\");\n}\n\nexport function htmlValidationContent(\n messages: W3CMessage[],\n source?: string,\n totalMessages = messages.length,\n counts?: { error: number; warning: number; info: number },\n): string {\n const errorCount = counts?.error\n ?? messages.filter((message) => getW3CMessageSeverity(message) === \"error\").length;\n const warningCount = counts?.warning\n ?? messages.filter((message) => getW3CMessageSeverity(message) === \"warning\").length;\n const infoCount = counts?.info ?? Math.max(0, totalMessages - errorCount - warningCount);\n const sourceText = source ? ` for ${markdownCode(source, 180)}` : \"\";\n if (totalMessages === 0) {\n return toolContent({\n title: \"HTML validation\",\n status: \"clean\",\n outcome: `The W3C validator returned no HTML diagnostics${sourceText}.`,\n nextStep: \"Keep this result as a baseline and validate again after the next markup change.\",\n });\n }\n\n const hasActionableDiagnostics = errorCount > 0 || warningCount > 0;\n return toolContent({\n title: \"HTML validation\",\n status: hasActionableDiagnostics ? \"attention needed\" : \"review suggested\",\n outcome: `The W3C validator returned ${countLabel(errorCount, \"error\")}, ${countLabel(warningCount, \"warning\")}, and ${countLabel(infoCount, \"informational diagnostic\")}${sourceText}.`,\n actions: messages.map((message) => ({\n priority: priorityForSeverity(getW3CMessageSeverity(message)),\n message: message.message,\n location: formatLocation(message.lastLine ?? message.firstLine, message.lastColumn ?? message.firstColumn),\n })),\n nextStep: hasActionableDiagnostics\n ? \"Fix errors first, then warnings, and rerun HTML validation to confirm the markup is clean.\"\n : \"Review the informational diagnostics, then rerun validation after relevant markup changes.\",\n note: totalMessages > messages.length\n ? `Showing the first ${messages.length} of ${totalMessages} HTML diagnostics in structured output; severity totals include all returned Nu diagnostics.`\n : undefined,\n });\n}\n\nexport function cssValidationContent(messages: CSSMessage[]): string {\n if (messages.length === 0) {\n return toolContent({\n title: \"CSS validation\",\n status: \"clean\",\n outcome: \"The W3C validator returned no CSS errors.\",\n nextStep: \"Validate again after the next stylesheet change.\",\n });\n }\n\n const compatibilityLimitations = messages.filter(\n (message) => message.compatibility === \"known-validator-limitation\",\n );\n const actionableErrors = messages.length - compatibilityLimitations.length;\n\n return toolContent({\n title: \"CSS validation\",\n status: actionableErrors > 0 ? \"attention needed\" : \"review suggested\",\n outcome: compatibilityLimitations.length > 0\n ? `The W3C validator returned ${countLabel(messages.length, \"CSS error\")}; ${countLabel(compatibilityLimitations.length, \"diagnostic\")} ${compatibilityLimitations.length === 1 ? \"matches\" : \"match\"} a known validator limitation.`\n : `The W3C validator returned ${countLabel(messages.length, \"CSS error\")}.`,\n actions: messages.map((message) => ({\n priority: message.compatibility === \"known-validator-limitation\" ? 2 : 0,\n message: message.context ? `${message.message} Context: ${message.context}` : message.message,\n location: formatLocation(message.line),\n })),\n nextStep: actionableErrors > 0\n ? \"Correct the actionable errors, then rerun CSS validation because one syntax issue can cause later diagnostics.\"\n : \"Review the marked @container diagnostic against current CSS specifications; do not treat it as invalid CSS by itself.\",\n note: compatibilityLimitations.length > 0\n ? \"Jigsaw currently does not recognize the standards-defined @container rule. The upstream diagnostic is preserved and marked as a known validator limitation.\"\n : undefined,\n });\n}\n\nexport function seoAuditContent(issues: SEOIssue[], totalIssues: number, truncated: boolean): string {\n const errors = issues.filter((issue) => issue.severity === \"error\").length;\n const warnings = issues.filter((issue) => issue.severity === \"warning\").length;\n const info = issues.filter((issue) => issue.severity === \"info\").length;\n if (totalIssues === 0) {\n return toolContent({\n title: \"SEO audit\",\n status: \"clean within this audit\",\n outcome: \"This focused rules-based audit found no SEO or accessibility issues in the supplied HTML.\",\n nextStep: \"Keep the metadata current and rerun the audit whenever the page template changes.\",\n note: \"This result does not replace a crawl, performance test, or Search Console review.\",\n });\n }\n\n const hasActionableFindings = errors > 0 || warnings > 0;\n return toolContent({\n title: \"SEO audit\",\n status: hasActionableFindings ? \"attention needed\" : \"review suggested\",\n outcome: `The audit found ${countLabel(errors, \"error\")}, ${countLabel(warnings, \"warning\")}, and ${countLabel(info, \"suggestion\")}.`,\n actions: issues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: issue.message,\n location: issue.element ? collapseWhitespace(issue.element, 120) : undefined,\n })),\n nextStep: hasActionableFindings\n ? \"Address errors first, then warnings, and rerun the audit after updating the page.\"\n : \"Review the suggestions that apply to this page, then rerun the audit after relevant template changes.\",\n note: truncated\n ? `Showing the first ${issues.length} of ${totalIssues} findings in structured output.`\n : undefined,\n });\n}\n\nfunction countJsonLdBlocks(htmlContent: string): number {\n const $ = cheerio.load(htmlContent);\n return $(\"script[type]\").filter((_, element) => {\n const type = $(element).attr(\"type\");\n return type?.split(\";\", 1)[0].trim().toLowerCase() === \"application/ld+json\";\n }).length;\n}\n\nexport function schemaValidationContent(\n issues: SEOIssue[],\n totalIssues: number,\n truncated: boolean,\n htmlContent: string,\n): string {\n const blockCount = countJsonLdBlocks(htmlContent);\n if (blockCount === 0) {\n return toolContent({\n title: \"JSON-LD syntax\",\n status: \"not present\",\n outcome: \"No JSON-LD script blocks were found, so there was no structured data to parse.\",\n nextStep: \"Add JSON-LD only when it accurately describes visible page content, then validate it again.\",\n });\n }\n if (totalIssues === 0) {\n return toolContent({\n title: \"JSON-LD syntax\",\n status: \"clean\",\n outcome: `${countLabel(blockCount, \"JSON-LD block\")} parsed without syntax errors.`,\n nextStep: \"Verify the properties against the relevant Schema.org type and search-engine requirements.\",\n note: \"This check covers JSON syntax only; it does not validate vocabulary semantics or rich-result eligibility.\",\n });\n }\n\n return toolContent({\n title: \"JSON-LD syntax\",\n status: \"attention needed\",\n outcome: `${countLabel(totalIssues, \"syntax issue\")} ${totalIssues === 1 ? \"was\" : \"were\"} found across ${countLabel(blockCount, \"JSON-LD block\")}.`,\n actions: issues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: issue.message,\n })),\n nextStep: \"Repair the invalid or empty blocks, then rerun this syntax check before testing rich-result eligibility.\",\n note: truncated\n ? `Showing the first ${issues.length} of ${totalIssues} findings in structured output.`\n : undefined,\n });\n}\n\nfunction linkPriority(link: LinkStatus): ActionPriority {\n if (isRedirect(link)) return 1;\n return 0;\n}\n\nfunction isRedirect(link: LinkStatus): boolean {\n return typeof link.status === \"number\" && link.status >= 300 && link.status < 400;\n}\n\nfunction linkActionMessage(link: LinkStatus): string {\n if (isRedirect(link)) {\n return `${link.status} redirect; destination was not followed`;\n }\n return `Link returned ${typeof link.status === \"number\" ? `HTTP ${link.status}` : link.status}${link.message ? ` — ${link.message}` : \"\"}`;\n}\n\nexport function linkCheckContent(links: LinkStatus[], baseUrl?: string): string {\n if (links.length === 0) {\n return toolContent({\n title: \"Link check\",\n status: \"nothing checked\",\n outcome: \"No eligible public HTTP(S) links were found, so no link requests were made.\",\n nextStep: baseUrl\n ? \"Confirm the HTML contains reachable anchor URLs, then run the check again.\"\n : \"If the page uses relative links, provide its public base URL and run the check again.\",\n });\n }\n\n const unreachable = links.filter((link) => !link.ok);\n const redirects = links.filter(isRedirect);\n if (unreachable.length === 0 && redirects.length === 0) {\n return toolContent({\n title: \"Link check\",\n status: \"clean\",\n outcome: links.length === 1\n ? \"The checked link returned a successful response.\"\n : `All ${links.length} checked links returned a successful response.`,\n nextStep: \"Recheck periodically because external link availability can change.\",\n });\n }\n\n const actions = [\n ...unreachable,\n ...redirects,\n ].map((link) => ({\n priority: linkPriority(link),\n location: link.url,\n message: linkActionMessage(link),\n }));\n\n const linkOutcome = [\n unreachable.length > 0\n ? `${countLabel(unreachable.length, \"link\")} ${unreachable.length === 1 ? \"is\" : \"are\"} broken or unreachable`\n : \"no checked links are broken or unreachable\",\n redirects.length > 0\n ? `${countLabel(redirects.length, \"redirect\")} ${redirects.length === 1 ? \"needs\" : \"need\"} review`\n : undefined,\n ].filter((item): item is string => item !== undefined).join(\"; \");\n\n return toolContent({\n title: \"Link check\",\n status: unreachable.length > 0 ? \"attention needed\" : \"review suggested\",\n outcome: `${linkOutcome} of ${links.length} checked. Redirect destinations are not followed.`,\n actions,\n nextStep: \"Update failed destinations and review redirects, then rerun the link check.\",\n });\n}\n\nfunction reportActionItems(reportData: ValidationReportResult): ActionItem[] {\n return [\n ...(reportData.errors ?? []).map((message) => ({\n priority: 0 as const,\n message,\n })),\n ...reportData.htmlMessages.map((message) => ({\n priority: priorityForSeverity(getW3CMessageSeverity(message)),\n message: `HTML: ${message.message}`,\n location: formatLocation(message.lastLine ?? message.firstLine, message.lastColumn ?? message.firstColumn),\n })),\n ...reportData.cssMessages.map((message) => ({\n priority: message.compatibility === \"known-validator-limitation\" ? 2 as const : 0 as const,\n message: `CSS: ${message.message}`,\n location: formatLocation(message.line),\n })),\n ...reportData.seoIssues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: `${issue.category}: ${issue.message}`,\n location: issue.element ? collapseWhitespace(issue.element, 120) : undefined,\n })),\n ...reportData.schemaIssues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: `JSON-LD: ${issue.message}`,\n })),\n ...reportData.links\n .filter((link) => !link.ok || isRedirect(link))\n .map((link) => ({\n priority: linkPriority(link),\n message: linkActionMessage(link),\n location: link.url,\n })),\n ];\n}\n\nexport function reportContent(reportData: ValidationReportResult): string {\n const { summary } = reportData;\n const actions = reportActionItems(reportData);\n const partial = reportData.failedChecks.length > 0;\n const compatibilityLimited = summary.cssCompatibilityLimitations > 0;\n const hasActionableFinding = actions.some((action) => action.priority < 2);\n const status = partial\n ? \"partial\"\n : compatibilityLimited\n ? \"compatibility-limited\"\n : actions.length === 0\n ? \"clean across completed checks\"\n : hasActionableFinding\n ? \"attention needed\"\n : \"review suggested\";\n const cssSummary = summary.cssScore === null\n ? reportData.failedChecks.includes(\"css\")\n ? \"CSS validation unavailable\"\n : compatibilityLimited\n ? `${countLabel(summary.cssErrors, \"CSS error\")}; ${countLabel(summary.cssCompatibilityLimitations, \"known validator limitation\")}`\n : \"CSS not audited\"\n : countLabel(summary.cssErrors, \"CSS error\");\n const redirects = reportData.links.filter(isRedirect).length;\n const linkSummary = summary.linkScore === null\n ? reportData.failedChecks.includes(\"links\")\n ? \"link checking unavailable\"\n : \"no eligible links checked\"\n : `${summary.brokenLinks} broken or unreachable and ${countLabel(redirects, \"redirect\")} to review of ${countLabel(summary.linksChecked, \"link\")}`;\n const checkLabels = {\n input: \"input file\",\n html: \"HTML validation\",\n css: \"CSS validation\",\n seo: \"SEO analysis\",\n schema: \"JSON-LD analysis\",\n links: \"link checking\",\n } as const;\n const unavailableChecks = reportData.failedChecks\n .filter((check) => check !== \"input\")\n .map((check) => checkLabels[check]);\n const scoreNote = \"The score is a triage heuristic based on these checks, not a Lighthouse score or a search-ranking prediction.\";\n const truncationNote = reportData.htmlTruncated\n ? `Showing the first ${reportData.htmlMessages.length} of ${reportData.htmlTotalMessages} HTML diagnostics; HTML summary counts and scoring include all returned Nu diagnostics.`\n : undefined;\n return toolContent({\n title: \"Validation report\",\n status,\n outcome: partial\n ? `Partial validation report: ${unavailableChecks.join(\", \")} ${unavailableChecks.length === 1 ? \"was\" : \"were\"} unavailable; remaining checks completed. HTML has ${countLabel(summary.htmlErrors, \"error\")}; ${cssSummary}; SEO has ${countLabel(summary.seoErrors, \"error\")}; JSON-LD has ${countLabel(summary.schemaErrors, \"syntax error\")}; ${linkSummary}.`\n : compatibilityLimited\n ? `The overall heuristic score is withheld because CSS validation includes ${countLabel(summary.cssCompatibilityLimitations, \"known validator limitation\")}. HTML has ${countLabel(summary.htmlErrors, \"error\")} and ${countLabel(summary.htmlWarnings, \"warning\")}; ${cssSummary}; SEO has ${countLabel(summary.seoErrors, \"error\")} and ${countLabel(summary.seoWarnings, \"warning\")}; JSON-LD has ${countLabel(summary.schemaErrors, \"syntax error\")}; ${linkSummary}.`\n : `The report's heuristic overall score is **${summary.overallScore}/100**. HTML has ${countLabel(summary.htmlErrors, \"error\")} and ${countLabel(summary.htmlWarnings, \"warning\")}; ${cssSummary}; SEO has ${countLabel(summary.seoErrors, \"error\")} and ${countLabel(summary.seoWarnings, \"warning\")}; JSON-LD has ${countLabel(summary.schemaErrors, \"syntax error\")}; ${linkSummary}.`,\n actions,\n nextStep: partial\n ? \"Review the completed findings, then retry the unavailable checks.\"\n : compatibilityLimited\n ? \"Review actionable findings normally, and treat the marked @container diagnostic as an upstream validator limitation rather than proof of invalid CSS.\"\n : actions.length === 0\n ? \"Use the full Markdown report as the audit record and rerun it after meaningful page changes.\"\n : \"Work through these priorities, then regenerate the report to compare the heuristic score.\",\n note: partial\n ? [\"No overall score is shown while one or more checks are unavailable.\", truncationNote].filter(Boolean).join(\" \")\n : compatibilityLimited\n ? [\"CSS and overall scores are withheld while a known Jigsaw parser limitation is present; the original upstream diagnostic remains visible.\", truncationNote].filter(Boolean).join(\" \")\n : [scoreNote, truncationNote].filter(Boolean).join(\" \"),\n });\n}\n\nexport function screenshotCaptureContent(count: number, outputDirectory: string): string {\n return toolContent({\n title: \"Screenshot capture\",\n status: \"complete\",\n outcome: `Saved ${countLabel(count, \"PNG screenshot\")} to ${markdownCode(outputDirectory)}.`,\n nextStep: \"Open the PNG files and compare the rendered layouts at each requested viewport.\",\n });\n}\n\nexport function failureContent(title: string, error: string, nextStep: string): string {\n return toolContent({\n title,\n status: \"could not finish\",\n outcome: markdownText(error, 500),\n nextStep,\n });\n}\n"]}
1
+ {"version":3,"file":"presentation.js","sourceRoot":"","sources":["../src/presentation.ts"],"names":[],"mappings":"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","sourcesContent":["import * as cheerio from \"cheerio\";\nimport type { ValidationReport } from \"./report.js\";\nimport type { AuditCounts, LinkStatus, SEOIssue } from \"./seo-auditor.js\";\nimport {\n getW3CMessageSeverity,\n type CSSMessage,\n type W3CMessage,\n} from \"./w3c-validator.js\";\n\ntype ActionPriority = 0 | 1 | 2;\n\ninterface ActionItem {\n message: string;\n priority: ActionPriority;\n location?: string;\n}\n\ninterface ValidationReportResult extends ValidationReport {\n errors?: string[];\n}\n\nfunction collapseWhitespace(value: string, maxLength = 240): string {\n const collapsed = value.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Escapes untrusted text while leaving the surrounding, controlled Markdown intact. */\nfunction markdownText(value: string, maxLength = 240): string {\n return collapseWhitespace(value, maxLength)\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/([`*_[\\]{}()#+\\-.!|~])/g, \"\\\\$1\");\n}\n\n/** Wraps untrusted identifiers and paths in a code span that cannot be closed by their content. */\nfunction markdownCode(value: string, maxLength = 240): string {\n const collapsed = collapseWhitespace(value, maxLength);\n const longestBacktickRun = Math.max(\n 0,\n ...Array.from(collapsed.matchAll(/`+/g), (match) => match[0].length),\n );\n const delimiter = \"`\".repeat(longestBacktickRun + 1);\n const content = collapsed.startsWith(\"`\") || collapsed.endsWith(\"`\")\n ? ` ${collapsed} `\n : collapsed;\n return `${delimiter}${content}${delimiter}`;\n}\n\nfunction countLabel(count: number, singular: string, plural = `${singular}s`): string {\n return `${count} ${count === 1 ? singular : plural}`;\n}\n\nfunction priorityForSeverity(severity: string): ActionPriority {\n if (severity.toLowerCase() === \"error\") return 0;\n if (severity.toLowerCase() === \"warning\") return 1;\n return 2;\n}\n\nfunction formatLocation(line?: number, column?: number): string | undefined {\n if (line === undefined && column === undefined) return undefined;\n if (line === undefined) return `column ${column}`;\n if (column === undefined) return `line ${line}`;\n return `line ${line}, column ${column}`;\n}\n\nfunction formatActions(items: ActionItem[]): string | undefined {\n const prioritized = items\n .map((item, index) => ({ item, index }))\n .sort((left, right) => left.item.priority - right.item.priority || left.index - right.index)\n .slice(0, 3)\n .map(({ item }) => {\n const label = item.priority === 0 ? \"Error\" : item.priority === 1 ? \"Warning\" : \"Check\";\n const location = item.location\n ? ` · ${markdownCode(item.location, 120)}`\n : \"\";\n return `- **${label}**${location}: ${markdownText(item.message)}`;\n });\n\n return prioritized.length > 0 ? prioritized.join(\"\\n\") : undefined;\n}\n\nfunction toolContent(options: {\n title: string;\n status: string;\n outcome: string;\n nextStep: string;\n actions?: ActionItem[];\n note?: string;\n}): string {\n const sections = [\n `### ${options.title}: ${options.status}`,\n collapseWhitespace(options.outcome, 500),\n ];\n if (options.note) {\n sections.push(collapseWhitespace(options.note, 500));\n }\n const actionItems = options.actions ?? [];\n const actions = formatActions(actionItems);\n if (actions) {\n const hasActionableItem = actionItems.some((item) => item.priority < 2);\n const actionHeading = options.status === \"review suggested\" || !hasActionableItem ? \"Review\" : \"Fix first\";\n sections.push(`**${actionHeading}**\\n${actions}`);\n }\n sections.push(`**Next step:** ${collapseWhitespace(options.nextStep, 400)}`);\n return sections.join(\"\\n\\n\");\n}\n\nexport function htmlValidationContent(\n messages: W3CMessage[],\n source?: string,\n totalMessages = messages.length,\n counts?: { error: number; warning: number; info: number },\n): string {\n const errorCount = counts?.error\n ?? messages.filter((message) => getW3CMessageSeverity(message) === \"error\").length;\n const warningCount = counts?.warning\n ?? messages.filter((message) => getW3CMessageSeverity(message) === \"warning\").length;\n const infoCount = counts?.info ?? Math.max(0, totalMessages - errorCount - warningCount);\n const sourceText = source ? ` for ${markdownCode(source, 180)}` : \"\";\n if (totalMessages === 0) {\n return toolContent({\n title: \"HTML validation\",\n status: \"clean\",\n outcome: `The W3C validator returned no HTML diagnostics${sourceText}.`,\n nextStep: \"Keep this result as a baseline and validate again after the next markup change.\",\n });\n }\n\n const hasActionableDiagnostics = errorCount > 0 || warningCount > 0;\n return toolContent({\n title: \"HTML validation\",\n status: hasActionableDiagnostics ? \"attention needed\" : \"review suggested\",\n outcome: `The W3C validator returned ${countLabel(errorCount, \"error\")}, ${countLabel(warningCount, \"warning\")}, and ${countLabel(infoCount, \"informational diagnostic\")}${sourceText}.`,\n actions: messages.map((message) => ({\n priority: priorityForSeverity(getW3CMessageSeverity(message)),\n message: message.message,\n location: formatLocation(message.lastLine ?? message.firstLine, message.lastColumn ?? message.firstColumn),\n })),\n nextStep: hasActionableDiagnostics\n ? \"Fix errors first, then warnings, and rerun HTML validation to confirm the markup is clean.\"\n : \"Review the informational diagnostics, then rerun validation after relevant markup changes.\",\n note: totalMessages > messages.length\n ? `Showing the first ${messages.length} of ${totalMessages} HTML diagnostics in structured output; severity totals include all returned Nu diagnostics.`\n : undefined,\n });\n}\n\nexport function cssValidationContent(\n messages: CSSMessage[],\n totalMessages = messages.length,\n counts?: { error: number; compatibilityLimitation: number },\n): string {\n if (totalMessages === 0) {\n return toolContent({\n title: \"CSS validation\",\n status: \"clean\",\n outcome: \"The W3C validator returned no CSS errors.\",\n nextStep: \"Validate again after the next stylesheet change.\",\n });\n }\n\n const compatibilityLimitations = messages.filter(\n (message) => message.compatibility === \"known-validator-limitation\",\n );\n const compatibilityLimitationCount = counts?.compatibilityLimitation ?? compatibilityLimitations.length;\n const actionableErrors = counts?.error ?? messages.length - compatibilityLimitations.length;\n\n return toolContent({\n title: \"CSS validation\",\n status: actionableErrors > 0 ? \"attention needed\" : \"review suggested\",\n outcome: compatibilityLimitationCount > 0\n ? `The W3C validator returned ${countLabel(totalMessages, \"CSS diagnostic\")}; ${countLabel(compatibilityLimitationCount, \"diagnostic\")} ${compatibilityLimitationCount === 1 ? \"matches\" : \"match\"} a known validator limitation.`\n : `The W3C validator returned ${countLabel(actionableErrors, \"CSS error\")}.`,\n actions: messages.map((message) => ({\n priority: message.compatibility === \"known-validator-limitation\" ? 2 : 0,\n message: message.context ? `${message.message} Context: ${message.context}` : message.message,\n location: formatLocation(message.line),\n })),\n nextStep: actionableErrors > 0\n ? \"Correct the actionable errors, then rerun CSS validation because one syntax issue can cause later diagnostics.\"\n : \"Review the marked @container diagnostic against current CSS specifications; do not treat it as invalid CSS by itself.\",\n note: [\n compatibilityLimitationCount > 0\n ? \"Jigsaw currently does not recognize the standards-defined @container rule. The upstream diagnostic is preserved and marked as a known validator limitation.\"\n : undefined,\n totalMessages > messages.length\n ? `Showing the first ${messages.length} of ${totalMessages} CSS diagnostics in structured output; summary counts include all returned Jigsaw diagnostics.`\n : undefined,\n ].filter(Boolean).join(\" \") || undefined,\n });\n}\n\nexport function seoAuditContent(\n issues: SEOIssue[],\n totalIssues: number,\n truncated: boolean,\n counts?: AuditCounts,\n): string {\n const errors = counts?.error ?? issues.filter((issue) => issue.severity === \"error\").length;\n const warnings = counts?.warning ?? issues.filter((issue) => issue.severity === \"warning\").length;\n const info = counts?.info ?? issues.filter((issue) => issue.severity === \"info\").length;\n if (totalIssues === 0) {\n return toolContent({\n title: \"SEO audit\",\n status: \"clean within this audit\",\n outcome: \"This focused rules-based audit found no SEO or accessibility issues in the supplied HTML.\",\n nextStep: \"Keep the metadata current and rerun the audit whenever the page template changes.\",\n note: \"This result does not replace a crawl, performance test, or Search Console review.\",\n });\n }\n\n const hasActionableFindings = errors > 0 || warnings > 0;\n return toolContent({\n title: \"SEO audit\",\n status: hasActionableFindings ? \"attention needed\" : \"review suggested\",\n outcome: `The audit found ${countLabel(errors, \"error\")}, ${countLabel(warnings, \"warning\")}, and ${countLabel(info, \"suggestion\")}.`,\n actions: issues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: issue.message,\n location: issue.element ? collapseWhitespace(issue.element, 120) : undefined,\n })),\n nextStep: hasActionableFindings\n ? \"Address errors first, then warnings, and rerun the audit after updating the page.\"\n : \"Review the suggestions that apply to this page, then rerun the audit after relevant template changes.\",\n note: truncated\n ? `Showing the first ${issues.length} of ${totalIssues} findings in structured output.`\n : undefined,\n });\n}\n\nfunction countJsonLdBlocks(htmlContent: string): number {\n const $ = cheerio.load(htmlContent);\n return $(\"script[type]\").filter((_, element) => {\n const type = $(element).attr(\"type\");\n return type?.split(\";\", 1)[0].trim().toLowerCase() === \"application/ld+json\";\n }).length;\n}\n\nexport function schemaValidationContent(\n issues: SEOIssue[],\n totalIssues: number,\n truncated: boolean,\n htmlContent: string,\n): string {\n const blockCount = countJsonLdBlocks(htmlContent);\n if (blockCount === 0) {\n return toolContent({\n title: \"JSON-LD syntax\",\n status: \"not present\",\n outcome: \"No JSON-LD script blocks were found, so there was no structured data to parse.\",\n nextStep: \"Add JSON-LD only when it accurately describes visible page content, then validate it again.\",\n });\n }\n if (totalIssues === 0) {\n return toolContent({\n title: \"JSON-LD syntax\",\n status: \"clean\",\n outcome: `${countLabel(blockCount, \"JSON-LD block\")} parsed without syntax errors.`,\n nextStep: \"Verify the properties against the relevant Schema.org type and search-engine requirements.\",\n note: \"This check covers JSON syntax only; it does not validate vocabulary semantics or rich-result eligibility.\",\n });\n }\n\n return toolContent({\n title: \"JSON-LD syntax\",\n status: \"attention needed\",\n outcome: `${countLabel(totalIssues, \"syntax issue\")} ${totalIssues === 1 ? \"was\" : \"were\"} found across ${countLabel(blockCount, \"JSON-LD block\")}.`,\n actions: issues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: issue.message,\n })),\n nextStep: \"Repair the invalid or empty blocks, then rerun this syntax check before testing rich-result eligibility.\",\n note: truncated\n ? `Showing the first ${issues.length} of ${totalIssues} findings in structured output.`\n : undefined,\n });\n}\n\nfunction linkPriority(link: LinkStatus): ActionPriority {\n if (isRedirect(link)) return 1;\n return 0;\n}\n\nfunction isRedirect(link: LinkStatus): boolean {\n return typeof link.status === \"number\" && link.status >= 300 && link.status < 400;\n}\n\nfunction linkActionMessage(link: LinkStatus): string {\n if (isRedirect(link)) {\n return `${link.status} redirect; destination was not followed`;\n }\n return `Link returned ${typeof link.status === \"number\" ? `HTTP ${link.status}` : link.status}${link.message ? ` — ${link.message}` : \"\"}`;\n}\n\nexport function linkCheckContent(links: LinkStatus[], baseUrl?: string): string {\n if (links.length === 0) {\n return toolContent({\n title: \"Link check\",\n status: \"nothing checked\",\n outcome: \"No eligible public HTTP(S) links were found, so no link requests were made.\",\n nextStep: baseUrl\n ? \"Confirm the HTML contains reachable anchor URLs, then run the check again.\"\n : \"If the page uses relative links, provide its public base URL and run the check again.\",\n });\n }\n\n const unreachable = links.filter((link) => !link.ok);\n const redirects = links.filter(isRedirect);\n if (unreachable.length === 0 && redirects.length === 0) {\n return toolContent({\n title: \"Link check\",\n status: \"clean\",\n outcome: links.length === 1\n ? \"The checked link returned a successful response.\"\n : `All ${links.length} checked links returned a successful response.`,\n nextStep: \"Recheck periodically because external link availability can change.\",\n });\n }\n\n const actions = [\n ...unreachable,\n ...redirects,\n ].map((link) => ({\n priority: linkPriority(link),\n location: link.url,\n message: linkActionMessage(link),\n }));\n\n const linkOutcome = [\n unreachable.length > 0\n ? `${countLabel(unreachable.length, \"link\")} ${unreachable.length === 1 ? \"is\" : \"are\"} broken or unreachable`\n : \"no checked links are broken or unreachable\",\n redirects.length > 0\n ? `${countLabel(redirects.length, \"redirect\")} ${redirects.length === 1 ? \"needs\" : \"need\"} review`\n : undefined,\n ].filter((item): item is string => item !== undefined).join(\"; \");\n\n return toolContent({\n title: \"Link check\",\n status: unreachable.length > 0 ? \"attention needed\" : \"review suggested\",\n outcome: `${linkOutcome} of ${links.length} checked. Redirect destinations are not followed.`,\n actions,\n nextStep: \"Update failed destinations and review redirects, then rerun the link check.\",\n });\n}\n\nfunction reportActionItems(reportData: ValidationReportResult): ActionItem[] {\n return [\n ...(reportData.errors ?? []).map((message) => ({\n priority: 0 as const,\n message,\n })),\n ...reportData.htmlMessages.map((message) => ({\n priority: priorityForSeverity(getW3CMessageSeverity(message)),\n message: `HTML: ${message.message}`,\n location: formatLocation(message.lastLine ?? message.firstLine, message.lastColumn ?? message.firstColumn),\n })),\n ...reportData.cssMessages.map((message) => ({\n priority: message.compatibility === \"known-validator-limitation\" ? 2 as const : 0 as const,\n message: `CSS: ${message.message}`,\n location: formatLocation(message.line),\n })),\n ...reportData.seoIssues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: `${issue.category}: ${issue.message}`,\n location: issue.element ? collapseWhitespace(issue.element, 120) : undefined,\n })),\n ...reportData.schemaIssues.map((issue) => ({\n priority: priorityForSeverity(issue.severity),\n message: `JSON-LD: ${issue.message}`,\n })),\n ...reportData.links\n .filter((link) => !link.ok || isRedirect(link))\n .map((link) => ({\n priority: linkPriority(link),\n message: linkActionMessage(link),\n location: link.url,\n })),\n ];\n}\n\nexport function reportContent(reportData: ValidationReportResult): string {\n const { summary } = reportData;\n const actions = reportActionItems(reportData);\n const partial = reportData.failedChecks.length > 0;\n const compatibilityLimited = summary.cssCompatibilityLimitations > 0;\n const hasActionableFinding = actions.some((action) => action.priority < 2);\n const status = partial\n ? \"partial\"\n : compatibilityLimited\n ? \"compatibility-limited\"\n : actions.length === 0\n ? \"clean across completed checks\"\n : hasActionableFinding\n ? \"attention needed\"\n : \"review suggested\";\n const cssSummary = summary.cssScore === null\n ? reportData.failedChecks.includes(\"css\")\n ? \"CSS validation unavailable\"\n : compatibilityLimited\n ? `${countLabel(summary.cssErrors, \"CSS error\")}; ${countLabel(summary.cssCompatibilityLimitations, \"known validator limitation\")}`\n : \"CSS not audited\"\n : countLabel(summary.cssErrors, \"CSS error\");\n const redirects = reportData.links.filter(isRedirect).length;\n const linkSummary = summary.linkScore === null\n ? reportData.failedChecks.includes(\"links\")\n ? \"link checking unavailable\"\n : \"no eligible links checked\"\n : `${summary.brokenLinks} broken or unreachable and ${countLabel(redirects, \"redirect\")} to review of ${countLabel(summary.linksChecked, \"link\")}`;\n const checkLabels = {\n input: \"input file\",\n html: \"HTML validation\",\n css: \"CSS validation\",\n seo: \"SEO analysis\",\n schema: \"JSON-LD analysis\",\n links: \"link checking\",\n } as const;\n const unavailableChecks = reportData.failedChecks\n .filter((check) => check !== \"input\")\n .map((check) => checkLabels[check]);\n const scoreNote = \"The score is a triage heuristic based on these checks, not a Lighthouse score or a search-ranking prediction.\";\n const truncationNote = [\n reportData.htmlTruncated\n ? `Showing the first ${reportData.htmlMessages.length} of ${reportData.htmlTotalMessages} HTML diagnostics; HTML summary counts and scoring include all returned Nu diagnostics.`\n : undefined,\n reportData.cssTruncated\n ? `Showing the first ${reportData.cssMessages.length} of ${reportData.cssTotalMessages} CSS diagnostics; CSS summary counts and scoring include all returned Jigsaw diagnostics.`\n : undefined,\n reportData.seoTruncated\n ? `Showing the first ${reportData.seoIssues.length} of ${reportData.seoTotalIssues} SEO findings; SEO summary counts and scoring include all findings.`\n : undefined,\n reportData.schemaTruncated\n ? `Showing the first ${reportData.schemaIssues.length} of ${reportData.schemaTotalIssues} JSON-LD findings; JSON-LD summary counts and scoring include all findings.`\n : undefined,\n ].filter(Boolean).join(\" \") || undefined;\n return toolContent({\n title: \"Validation report\",\n status,\n outcome: partial\n ? `Partial validation report: ${unavailableChecks.join(\", \")} ${unavailableChecks.length === 1 ? \"was\" : \"were\"} unavailable; remaining checks completed. HTML has ${countLabel(summary.htmlErrors, \"error\")}; ${cssSummary}; SEO has ${countLabel(summary.seoErrors, \"error\")}; JSON-LD has ${countLabel(summary.schemaErrors, \"syntax error\")}; ${linkSummary}.`\n : compatibilityLimited\n ? `The overall heuristic score is withheld because CSS validation includes ${countLabel(summary.cssCompatibilityLimitations, \"known validator limitation\")}. HTML has ${countLabel(summary.htmlErrors, \"error\")} and ${countLabel(summary.htmlWarnings, \"warning\")}; ${cssSummary}; SEO has ${countLabel(summary.seoErrors, \"error\")} and ${countLabel(summary.seoWarnings, \"warning\")}; JSON-LD has ${countLabel(summary.schemaErrors, \"syntax error\")}; ${linkSummary}.`\n : `The report's heuristic overall score is **${summary.overallScore}/100**. HTML has ${countLabel(summary.htmlErrors, \"error\")} and ${countLabel(summary.htmlWarnings, \"warning\")}; ${cssSummary}; SEO has ${countLabel(summary.seoErrors, \"error\")} and ${countLabel(summary.seoWarnings, \"warning\")}; JSON-LD has ${countLabel(summary.schemaErrors, \"syntax error\")}; ${linkSummary}.`,\n actions,\n nextStep: partial\n ? \"Review the completed findings, then retry the unavailable checks.\"\n : compatibilityLimited\n ? \"Review actionable findings normally, and treat the marked @container diagnostic as an upstream validator limitation rather than proof of invalid CSS.\"\n : actions.length === 0\n ? \"Use the full Markdown report as the audit record and rerun it after meaningful page changes.\"\n : \"Work through these priorities, then regenerate the report to compare the heuristic score.\",\n note: partial\n ? [\"No overall score is shown while one or more checks are unavailable.\", truncationNote].filter(Boolean).join(\" \")\n : compatibilityLimited\n ? [\"CSS and overall scores are withheld while a known Jigsaw parser limitation is present; the original upstream diagnostic remains visible.\", truncationNote].filter(Boolean).join(\" \")\n : [scoreNote, truncationNote].filter(Boolean).join(\" \"),\n });\n}\n\nexport function screenshotCaptureContent(count: number, outputDirectory: string): string {\n return toolContent({\n title: \"Screenshot capture\",\n status: \"complete\",\n outcome: `Saved ${countLabel(count, \"PNG screenshot\")} to ${markdownCode(outputDirectory)}.`,\n nextStep: \"Open the PNG files and compare the rendered layouts at each requested viewport.\",\n });\n}\n\nexport function failureContent(title: string, error: string, nextStep: string): string {\n return toolContent({\n title,\n status: \"could not finish\",\n outcome: markdownText(error, 500),\n nextStep,\n });\n}\n"]}
package/dist/report.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type CSSMessage, type W3CMessage } from "./w3c-validator.js";
2
- import type { LinkStatus, SEOIssue } from "./seo-auditor.js";
2
+ import type { AuditCounts, LinkStatus, SEOIssue } from "./seo-auditor.js";
3
3
  export declare const validationReportChecks: readonly ["input", "html", "css", "seo", "schema", "links"];
4
4
  export type ValidationReportCheck = (typeof validationReportChecks)[number];
5
5
  export interface ValidationReportSummary {
@@ -25,8 +25,14 @@ export interface ValidationReport {
25
25
  htmlTotalMessages: number;
26
26
  htmlTruncated: boolean;
27
27
  cssMessages: CSSMessage[];
28
+ cssTotalMessages: number;
29
+ cssTruncated: boolean;
28
30
  seoIssues: SEOIssue[];
31
+ seoTotalIssues: number;
32
+ seoTruncated: boolean;
29
33
  schemaIssues: SEOIssue[];
34
+ schemaTotalIssues: number;
35
+ schemaTruncated: boolean;
30
36
  links: LinkStatus[];
31
37
  failedChecks: ValidationReportCheck[];
32
38
  errors?: string[];
@@ -43,8 +49,20 @@ export interface ValidationReportInput {
43
49
  info: number;
44
50
  };
45
51
  cssMessages: CSSMessage[];
52
+ cssTotalMessages?: number;
53
+ cssTruncated?: boolean;
54
+ cssCounts?: {
55
+ error: number;
56
+ compatibilityLimitation: number;
57
+ };
46
58
  seoIssues: SEOIssue[];
59
+ seoTotalIssues?: number;
60
+ seoTruncated?: boolean;
61
+ seoCounts?: AuditCounts;
47
62
  schemaIssues: SEOIssue[];
63
+ schemaTotalIssues?: number;
64
+ schemaTruncated?: boolean;
65
+ schemaCounts?: AuditCounts;
48
66
  links: LinkStatus[];
49
67
  failedChecks?: ValidationReportCheck[];
50
68
  errors?: string[];
package/dist/report.js CHANGED
@@ -34,11 +34,18 @@ export function createValidationReport(input) {
34
34
  ?? input.htmlMessages.filter((message) => getW3CMessageSeverity(message) === "warning").length;
35
35
  const htmlTotalMessages = input.htmlTotalMessages ?? input.htmlMessages.length;
36
36
  const htmlTruncated = input.htmlTruncated ?? htmlTotalMessages > input.htmlMessages.length;
37
- const cssCompatibilityLimitations = input.cssMessages.filter((message) => message.compatibility === "known-validator-limitation").length;
38
- const cssErrors = input.cssMessages.length - cssCompatibilityLimitations;
39
- const seoErrors = input.seoIssues.filter((issue) => issue.severity === "error").length;
40
- const seoWarnings = input.seoIssues.filter((issue) => issue.severity === "warning").length;
41
- const schemaErrors = input.schemaIssues.filter((issue) => issue.severity === "error").length;
37
+ const cssTotalMessages = input.cssTotalMessages ?? input.cssMessages.length;
38
+ const cssTruncated = input.cssTruncated ?? cssTotalMessages > input.cssMessages.length;
39
+ const cssCompatibilityLimitations = input.cssCounts?.compatibilityLimitation
40
+ ?? input.cssMessages.filter((message) => message.compatibility === "known-validator-limitation").length;
41
+ const cssErrors = input.cssCounts?.error ?? input.cssMessages.length - cssCompatibilityLimitations;
42
+ const seoTotalIssues = input.seoTotalIssues ?? input.seoIssues.length;
43
+ const seoTruncated = input.seoTruncated ?? seoTotalIssues > input.seoIssues.length;
44
+ const schemaTotalIssues = input.schemaTotalIssues ?? input.schemaIssues.length;
45
+ const schemaTruncated = input.schemaTruncated ?? schemaTotalIssues > input.schemaIssues.length;
46
+ const seoErrors = input.seoCounts?.error ?? input.seoIssues.filter((issue) => issue.severity === "error").length;
47
+ const seoWarnings = input.seoCounts?.warning ?? input.seoIssues.filter((issue) => issue.severity === "warning").length;
48
+ const schemaErrors = input.schemaCounts?.error ?? input.schemaIssues.filter((issue) => issue.severity === "error").length;
42
49
  const brokenLinks = input.links.filter((link) => !link.ok).length;
43
50
  const redirectLinks = input.links.filter(isRedirect).length;
44
51
  const htmlScore = checkFailed("html") ? null : clampScore(100 - htmlErrors * 15 - htmlWarnings * 2);
@@ -110,11 +117,14 @@ export function createValidationReport(input) {
110
117
  }
111
118
  }
112
119
  if (input.cssAudited) {
113
- report.push("", `## CSS diagnostics (${input.cssMessages.length})`);
120
+ report.push("", `## CSS diagnostics (${cssTruncated ? `${input.cssMessages.length} shown of ${cssTotalMessages}` : cssTotalMessages})`);
114
121
  if (input.cssMessages.length === 0) {
115
122
  report.push("No CSS validation errors were returned.");
116
123
  }
117
124
  else {
125
+ if (cssTruncated) {
126
+ report.push(`The structured CSS diagnostics are capped; showing the first ${input.cssMessages.length} of ${cssTotalMessages}. Summary counts and scoring use all returned Jigsaw diagnostics.`);
127
+ }
118
128
  report.push("", "| Line | Context | Message |", "| :---: | :--- | :--- |");
119
129
  for (const message of input.cssMessages) {
120
130
  report.push(`| ${message.line} | ${markdownCell(message.context ?? "N/A")} | ${markdownCell(message.message)} |`);
@@ -125,11 +135,19 @@ export function createValidationReport(input) {
125
135
  }
126
136
  }
127
137
  const combinedIssues = [...input.seoIssues, ...input.schemaIssues];
128
- report.push("", `## SEO, accessibility, and JSON-LD findings (${combinedIssues.length})`);
138
+ const combinedTotalIssues = seoTotalIssues + schemaTotalIssues;
139
+ const combinedTruncated = seoTruncated || schemaTruncated;
140
+ report.push("", `## SEO, accessibility, and JSON-LD findings (${combinedTruncated ? `${combinedIssues.length} shown of ${combinedTotalIssues}` : combinedTotalIssues})`);
129
141
  if (combinedIssues.length === 0) {
130
142
  report.push("No SEO, accessibility, or JSON-LD syntax findings were returned.");
131
143
  }
132
144
  else {
145
+ if (seoTruncated) {
146
+ report.push(`The structured SEO/accessibility findings are capped; showing the first ${input.seoIssues.length} of ${seoTotalIssues}. Summary counts and scoring use all findings.`);
147
+ }
148
+ if (schemaTruncated) {
149
+ report.push(`The structured JSON-LD findings are capped; showing the first ${input.schemaIssues.length} of ${schemaTotalIssues}. Summary counts and scoring use all findings.`);
150
+ }
133
151
  report.push("", "| Category | Severity | Message | Element |", "| :--- | :--- | :--- | :--- |");
134
152
  for (const issue of combinedIssues) {
135
153
  report.push(`| ${markdownCell(issue.category)} | ${markdownCell(issue.severity)} | ${markdownCell(issue.message)} | ${markdownCell(issue.element ?? "N/A")} |`);
@@ -152,8 +170,14 @@ export function createValidationReport(input) {
152
170
  htmlTotalMessages,
153
171
  htmlTruncated,
154
172
  cssMessages: input.cssMessages,
173
+ cssTotalMessages,
174
+ cssTruncated,
155
175
  seoIssues: input.seoIssues,
176
+ seoTotalIssues,
177
+ seoTruncated,
156
178
  schemaIssues: input.schemaIssues,
179
+ schemaTotalIssues,
180
+ schemaTruncated,
157
181
  links: input.links,
158
182
  failedChecks,
159
183
  ...(input.errors && input.errors.length > 0 ? { errors: input.errors } : {}),