Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions 11ty/biblio.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import axios from "axios";
import { readFile } from "fs/promises";
import { glob } from "glob";
import invert from "lodash-es/invert";
import uniq from "lodash-es/uniq";
import { join } from "path";

import { loadFromFile } from "./cheerio";
import { wrapAxiosRequest } from "./common";
import { fetchOptionalText } from "./common";

export const biblioPattern = /\[\[\??([\w-]+)\]\]/g;

Expand All @@ -33,16 +32,16 @@ export async function getBiblio() {
ref in aliases ? aliases[ref as keyof typeof aliases] : ref
);

const response = await wrapAxiosRequest(
axios.get(`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`)
const responseText = await fetchOptionalText(
`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`
);
if (response.data) {
for (const [from, to] of Object.entries(invert(aliases)))
response.data[to] = response.data[from];
const data = responseText ? JSON.parse(responseText) : null;
if (data) {
for (const [from, to] of Object.entries(invert(aliases))) data[to] = data[from];
}

return {
...response.data,
...data,
...localBiblio,
};
}
Expand Down
49 changes: 27 additions & 22 deletions 11ty/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/** @fileoverview Common functions used by multiple parts of the build process */

import { AxiosError, type AxiosResponse } from "axios";

import type { WcagItem } from "./guidelines";

/** Generates an ID for heading permalinks. Equivalent to wcag:generate-id in base.xslt. */
Expand All @@ -17,10 +15,7 @@ export function generateId(title: string) {
export const resolveDecimalVersion = (version: `${number}`) => version.split("").join(".");

/** Sort function for ordering WCAG principle/guideline/SC numbers ascending */
export function wcagSort(
a: WcagItem,
b: WcagItem
) {
export function wcagSort(a: WcagItem, b: WcagItem) {
const aParts = a.num.split(".").map((n) => +n);
const bParts = b.num.split(".").map((n) => +n);

Expand All @@ -31,22 +26,32 @@ export function wcagSort(
return 0;
}

type FetchText = (...args: Parameters<typeof fetch>) => Promise<string>;

/** Performs a fetch, returning body text or throwing an error if a 4xx/5xx response occurs. */
export const fetchText: FetchText = (input, init) =>
fetch(input, init).then(
(response) => {
if (response.status >= 400)
throw new Error(`fetching ${input} yielded ${response.status} response`);
return response.text();
},
(error) => {
throw new Error(`fetching ${input} yielded error: ${error.message}`);
}
);

/**
* 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
* Performs a fetch that ignores errors in local dev;
* throws during builds to fail loudly.
* This should only be used for non-critical requests that can tolerate no data
* without major side effects.
*/
export const wrapAxiosRequest = <T, D>(promise: Promise<AxiosResponse<T, D>>) =>
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 };
});
export const fetchOptionalText: FetchText =
process.env.ELEVENTY_RUN_MODE === "build"
? fetchText
: (input, init) =>
fetchText(input, init).catch((error) => {
console.warn("Bypassing fetch error:", error.message);
return "";
});
22 changes: 9 additions & 13 deletions 11ty/guidelines.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import axios from "axios";
import type { CheerioAPI } from "cheerio";
import { glob } from "glob";
import pick from "lodash-es/pick";

import { readFile } from "fs/promises";
import { basename, join, sep } from "path";

import { flattenDomFromFile, load, loadFromFile, type CheerioAnyNode } from "./cheerio";
import { generateId } from "./common";
import { fetchText, generateId } from "./common";

export type WcagVersion = "20" | "21" | "22";
export function assertIsWcagVersion(v: string): asserts v is WcagVersion {
Expand Down Expand Up @@ -256,9 +254,7 @@ const guidelinesCache: Partial<Record<WcagVersion, string>> = {};
const loadRemoteGuidelines = async (version: WcagVersion, stripRespec = true) => {
const html =
guidelinesCache[version] ||
(guidelinesCache[version] = (
await axios.get(`https://www.w3.org/TR/WCAG${version}/`, { responseType: "text" })
).data);
(guidelinesCache[version] = await fetchText(`https://www.w3.org/TR/WCAG${version}/`));

const $ = load(html);

Expand Down Expand Up @@ -356,13 +352,13 @@ export const getErrataForVersion = async (version: WcagVersion) => {
.each((_, el) => {
const $el = $(el);
const erratumHtml = $el
.html()!
// Remove everything before and including the final TR link
.replace(/^[\s\S]*href="\{\{\s*\w+\s*\}\}#[\s\S]*?<\/a>,?\s*/, "")
// Remove parenthetical github references (still in Liquid syntax)
.replace(/\(\{%.*%\}\)\s*$/, "")
.replace(/^(\w)/, (_, p1) => p1.toUpperCase());
.html()!
// Remove everything before and including the final TR link
.replace(/^[\s\S]*href="\{\{\s*\w+\s*\}\}#[\s\S]*?<\/a>,?\s*/, "")
// Remove parenthetical github references (still in Liquid syntax)
.replace(/\(\{%.*%\}\)\s*$/, "")
.replace(/^(\w)/, (_, p1) => p1.toUpperCase());

$el.find(aSelector).each((_, aEl) => {
const $aEl = $(aEl);
let hash: string | undefined = $aEl.attr("href")!.replace(/^.*#/, "");
Expand Down
8 changes: 3 additions & 5 deletions eleventy.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import axios from "axios";
import compact from "lodash-es/compact";
import { mkdirp } from "mkdirp";
import { rimraf } from "rimraf";
Expand All @@ -7,7 +6,7 @@ import { copyFile, writeFile } from "fs/promises";
import { join } from "path";

import { CustomLiquid } from "11ty/CustomLiquid";
import { resolveDecimalVersion } from "11ty/common";
import { fetchText, resolveDecimalVersion } from "11ty/common";
import { loadDataDependencies } from "11ty/data-dependencies";
import {
actRules,
Expand Down Expand Up @@ -239,9 +238,8 @@ export default async function (eleventyConfig: any) {
);

const url = `https://raw.githack.com/${GH_ORG}/${GH_REPO}/${sha}/guidelines/index.html?isPreview=true`;
const { data: processedGuidelines } = await axios.get(
`https://labs.w3.org/spec-generator/?type=respec&url=${encodeURIComponent(url)}`,
{ responseType: "text" }
const processedGuidelines = await fetchText(
`https://labs.w3.org/spec-generator/?type=respec&url=${encodeURIComponent(url)}`
);
await writeFile(`${dir.output}/guidelines/index.html`, processedGuidelines);
}
Expand Down
Loading