diff --git a/11ty/biblio.ts b/11ty/biblio.ts index 24a809fdb8..fcf5faca80 100644 --- a/11ty/biblio.ts +++ b/11ty/biblio.ts @@ -3,6 +3,8 @@ import { readFile } from "fs/promises"; import { glob } from "glob"; import uniq from "lodash-es/uniq"; +import { wrapAxiosRequest } from "./common"; + export const biblioPattern = /\[\[\??([\w-]+)\]\]/g; /** Compiles URLs from local biblio + specref for linking in Understanding documents. */ @@ -12,7 +14,7 @@ export async function getBiblio() { .replace(/^respecConfig\.localBiblio\s*=\s*/, "(") .replace("};", "})") ); - + const refs: string[] = []; for (const path of await glob(["guidelines/**/*.html", "understanding/*/*.html"])) { const content = await readFile(path, "utf8"); @@ -20,16 +22,18 @@ export async function getBiblio() { while ((match = biblioPattern.exec(content))) if (!localBiblio[match[1]]) refs.push(match[1]); } const uniqueRefs = uniq(refs); - - const response = await axios.get(`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`); + + const response = await wrapAxiosRequest( + axios.get(`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`) + ); const fullBiblio = { ...response.data, ...localBiblio, }; - + const resolvedRefs = Object.keys(fullBiblio); const unresolvedRefs = uniqueRefs.filter((ref) => !resolvedRefs.includes(ref)); if (unresolvedRefs.length) console.warn(`Unresolved biblio refs: ${unresolvedRefs.join(", ")}`); - + return fullBiblio; } diff --git a/11ty/common.ts b/11ty/common.ts index ade5d87f14..bda9ec4618 100644 --- a/11ty/common.ts +++ b/11ty/common.ts @@ -1,5 +1,7 @@ /** @fileoverview Common functions used by multiple parts of the build process */ +import { AxiosError, type AxiosResponse } from "axios"; + import type { Guideline, Principle, SuccessCriterion } from "./guidelines"; /** Generates an ID for heading permalinks. Equivalent to wcag:generate-id in base.xslt. */ @@ -28,3 +30,23 @@ export function wcagSort( } return 0; } + +/** + * Handles HTTP error responses from Axios requests in local dev; + * re-throws error during builds to fail loudly. + * This should only be used for non-critical requests that can tolerate null data + * without major side effects. + */ +export const wrapAxiosRequest = (promise: Promise>) => + promise.catch((error) => { + if (!(error instanceof AxiosError) || !error.response || !error.request) throw error; + const { response, request } = error; + console.warn( + `AxiosError: status ${response.status} received from ${ + request.protocol + "//" + request.host + }${request.path || ""}` + ); + + if (process.env.ELEVENTY_RUN_MODE === "build") throw error; + else return { data: null }; + });