Skip to content

Commit

Permalink
Address remaining unresolved biblio references
Browse files Browse the repository at this point in the history
  • Loading branch information
kfranqueiro committed Dec 12, 2024
1 parent b9cd498 commit 0884c1e
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 20 deletions.
42 changes: 35 additions & 7 deletions 11ty/CustomLiquid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { basename } from "path";

import type { GlobalData } from "eleventy.config";

import { biblioPattern, getBiblio } from "./biblio";
import { biblioPattern, getBiblio, getXmlBiblio } from "./biblio";
import { flattenDom, load, type CheerioAnyNode } from "./cheerio";
import { generateId } from "./common";
import { getAcknowledgementsForVersion, type TermsMap } from "./guidelines";
Expand All @@ -22,12 +22,22 @@ const techniquesPattern = /\btechniques\//;
const understandingPattern = /\bunderstanding\//;

const biblio = await getBiblio();
const xmlBiblio = await getXmlBiblio();
const termLinkSelector = "a:not([href])";

/** Generates {% include "foo.html" %} directives from 1 or more basenames */
const generateIncludes = (...basenames: string[]) =>
`\n${basenames.map((basename) => `{% include "${basename}.html" %}`).join("\n")}\n`;

/** Version of generateIncludes for a single include with parameters */
const generateIncludeWithParams = (basename: string, params: Record<string, string>) => {
const strParams = Object.entries(params).reduce(
(str, [key, value]) => `${str}, ${key}: ${JSON.stringify(value)}`,
""
);
return `\n{% include "${basename}.html"${strParams} %}\n`;
};

/**
* Determines whether a given string is actually HTML,
* not e.g. a data value Eleventy sent to the templating engine.
Expand Down Expand Up @@ -278,8 +288,9 @@ export class CustomLiquid extends Liquid {
// Expand techniques links to always include title
$(understandingToTechniqueLinkSelector).each((_, el) => expandTechniqueLink($(el)));

// Add key terms by default, to be removed in #parse if there are no terms
$("body").append(generateIncludes("understanding/key-terms"));
// Add key terms and references by default, to be removed in #parse if not needed
$("body").append(generateIncludeWithParams("dl-section", { title: "Key Terms" }));
$("body").append(generateIncludeWithParams("dl-section", { title: "References" }));
}

// Remove h2-level sections with no content other than heading
Expand Down Expand Up @@ -469,7 +480,7 @@ export class CustomLiquid extends Liquid {
for (const name of termNames) {
const term = this.termsMap[name]; // Already verified existence in the earlier loop
$termsList.append(
`<dt id="${term.id}">${term.name}</dt>` +
`\n <dt id="${term.id}">${term.name}</dt>` +
`<dd><definition>${term.definition}</definition></dd>`
);
}
Expand Down Expand Up @@ -567,17 +578,34 @@ export class CustomLiquid extends Liquid {

// Link biblio references
if (scope.isUnderstanding) {
const xmlBiblioReferences: string[] = [];
$("p").each((_, el) => {
const $el = $(el);
const html = $el.html();
if (html && biblioPattern.test(html)) {
$el.html(
html.replace(biblioPattern, (substring, code) =>
biblio[code]?.href ? `[<a href="${biblio[code].href}">${code}</a>]` : substring
)
html.replace(biblioPattern, (substring, code) => {
if (biblio[code]?.href) return `[<a href="${biblio[code].href}">${code}</a>]`;
if (code in xmlBiblio) {
xmlBiblioReferences.push(code);
return `[<a href="#${code}">${code}</a>]`;
}
console.warn(`${scope.page.inputPath}: Unresolved biblio ref: ${code}`);
return substring;
})
);
}
});

// Populate references section, or remove if unused
if (xmlBiblioReferences.length) {
for (const ref of uniq(xmlBiblioReferences).sort()) {
$("section#references dl").append(
`\n <dt id="${ref}">${ref}</dt>` +
`<dd><definition>${xmlBiblio[ref]}</definition></dd>`
);
}
} else $("section#references").remove();
}

// Allow autogenerating missing top-level section IDs in understanding docs,
Expand Down
35 changes: 28 additions & 7 deletions 11ty/biblio.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
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";

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

// Resolve necessary aliases locally rather than requiring an extra round trip to specref
const aliases = {
"css3-values": "css-values-3",
};

/** Compiles URLs from local biblio + specref for linking in Understanding documents. */
export async function getBiblio() {
const localBiblio = eval(
Expand All @@ -21,19 +29,32 @@ export async function getBiblio() {
let match;
while ((match = biblioPattern.exec(content))) if (!localBiblio[match[1]]) refs.push(match[1]);
}
const uniqueRefs = uniq(refs);
const uniqueRefs = uniq(refs).map((ref) =>
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 fullBiblio = {
for (const [from, to] of Object.entries(invert(aliases)))
response.data[to] = response.data[from];

return {
...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;
/** Returns mapping of references included in WCAG 2.0, which largely lack URLs */
export async function getXmlBiblio() {
const xmlRefs: Record<string, string> = {};
const $ = await loadFromFile(join("wcag20", "sources", "guide-to-wcag2-src.xml"));
$("bibl[id]").each((_, el) => {
const $ref = $(`#${el.attribs.id}`);
if (!$ref.length) return;
// Note: Using text() drops links (<loc> tags in the XML),
// but the only link within refs that are actually used seems to be broken
xmlRefs[el.attribs.id] = $ref.text();
});
return xmlRefs;
}
6 changes: 6 additions & 0 deletions _includes/dl-section.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<section id="{{ title | slugify }}">
<details>
<summary><h2>{{ title }}</h2></summary>
<dl></dl>
</details>
</section>
6 changes: 0 additions & 6 deletions _includes/understanding/key-terms.html

This file was deleted.

0 comments on commit 0884c1e

Please sign in to comment.