Skip to content

Commit e15d713

Browse files
committed
Merge branch 'main' into giacomo-petri-h91-minor-fix
2 parents 8b35f79 + 770fc0d commit e15d713

File tree

426 files changed

+7969
-9839
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

426 files changed

+7969
-9839
lines changed

.eleventyignore

Lines changed: 0 additions & 26 deletions
This file was deleted.

.github/workflows/cspell.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Check Spelling
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
jobs:
8+
spellcheck:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: streetsidesoftware/cspell-action@v7

11ty/CustomLiquid.ts

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { type Options as SlugifyOptions, slugifyWithCounter } from "@sindresorhus/slugify";
2+
import hljs from "highlight.js";
13
import { Liquid, type Template } from "liquidjs";
24
import type { LiquidOptions, RenderOptions } from "liquidjs/dist/liquid-options";
35
import compact from "lodash-es/compact";
@@ -9,15 +11,14 @@ import type { GlobalData } from "eleventy.config";
911

1012
import { biblioPattern, getBiblio, getXmlBiblio } from "./biblio";
1113
import { flattenDom, load, type CheerioAnyNode } from "./cheerio";
12-
import { generateId } from "./common";
1314
import { getAcknowledgementsForVersion, type TermsMap } from "./guidelines";
1415
import { resolveTechniqueIdFromHref, understandingToTechniqueLinkSelector } from "./techniques";
1516
import { techniqueToUnderstandingLinkSelector } from "./understanding";
1617

1718
const titleSuffix = " | WAI | W3C";
1819

1920
/** Matches index and about pages, traditionally processed differently than individual pages */
20-
const indexPattern = /(techniques|understanding)\/(index|about)\.html$/;
21+
const indexPattern = /(techniques|understanding)\/(index|about|changelog)\.html$/;
2122
const techniquesPattern = /\btechniques\//;
2223
const understandingPattern = /\bunderstanding\//;
2324

@@ -153,6 +154,31 @@ export class CustomLiquid extends Liquid {
153154
// Add charset to pages that forgot it
154155
if (!$("meta[charset]").length) $('<meta charset="UTF-8">').prependTo("head");
155156

157+
const $missingHljsOverrides = $("pre code:not([class])");
158+
if ($missingHljsOverrides.length) {
159+
$missingHljsOverrides.each((_, el) => {
160+
const code = $(el).html()!.replace(/\n/g, "\\n");
161+
const excerpt = `${code.slice(0, 40)}${code.length > 40 ? "..." : ""}`;
162+
console.log(
163+
`${filepath} missing "language-*" or "no-highlight" class on <pre><code> starting with ${excerpt}`
164+
);
165+
});
166+
if (process.env.ELEVENTY_RUN_MODE === "build") {
167+
throw new Error(
168+
"Please ensure all code blocks have a highlight.js class (language-* or no-highlight)."
169+
);
170+
}
171+
}
172+
173+
$("pre code[class*='language-']").each((_, el) => {
174+
const $el = $(el);
175+
// Unescape any HTML entities (which were originally needed for client-side highlight.js)
176+
const code = $el.html()!.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
177+
const language = $el.attr("class")!.replace(/^.*language-(\S+).*$/, "$1");
178+
$el.html(hljs.highlight(code, { language }).value);
179+
$el.addClass("hljs");
180+
});
181+
156182
const prependedIncludes = ["header"];
157183
const appendedIncludes = ["wai-site-footer", "site-footer"];
158184

@@ -256,22 +282,10 @@ export class CustomLiquid extends Liquid {
256282
throw new Error("Incorrectly-nested Benefits section found: please resolve.");
257283
}
258284

259-
// XSLT orders resources then techniques last, opposite of source files
260-
$("body")
261-
.append("\n", $(`body > section#resources`))
262-
.append("\n", $(`body > section#techniques`));
263-
264285
// Expand top-level heading and add box for guideline/SC pages
265286
if ($("section#intent").length) $("h1").replaceWith(generateIncludes("understanding/h1"));
266287
$("section#intent").before(generateIncludes("understanding/about"));
267288

268-
$("section#techniques h2").after(generateIncludes("understanding/intro/techniques"));
269-
if ($("section#sufficient .situation").length) {
270-
$("section#sufficient h3").after(
271-
generateIncludes("understanding/intro/sufficient-situation")
272-
);
273-
}
274-
275289
// Disallow handwritten success-criteria section (should be auto-generated)
276290
if ($("section#success-criteria").length) {
277291
console.error(
@@ -283,21 +297,7 @@ export class CustomLiquid extends Liquid {
283297
// success-criteria template only renders content for guideline (not SC) pages
284298
$("body").append(generateIncludes("understanding/success-criteria"));
285299

286-
// Remove unpopulated techniques subsections
287-
for (const id of ["sufficient", "advisory", "failure"]) {
288-
$(`section#${id}:not(:has(:not(h3)))`).remove();
289-
}
290-
291-
// Normalize subsection names for Guidelines (h2) and/or SC (h3)
292-
$("section#sufficient h3").text("Sufficient Techniques");
293-
$("section#advisory").find("h2, h3").text("Advisory Techniques");
294-
$("section#failure h3").text("Failures");
295-
296300
// Add intro prose to populated sections
297-
$("section#advisory")
298-
.find("h2, h3")
299-
.after(generateIncludes("understanding/intro/advisory"));
300-
$("section#failure h3").after(generateIncludes("understanding/intro/failure"));
301301
$("section#resources h2").after(generateIncludes("understanding/intro/resources"));
302302

303303
// Expand techniques links to always include title
@@ -440,8 +440,8 @@ export class CustomLiquid extends Liquid {
440440
if (scope.guideline?.level === "") $("section#techniques").remove();
441441
}
442442

443-
// Process defined terms within #render,
444-
// where we have access to global data and the about box's HTML
443+
// Process defined terms within #render, where we have access to
444+
// global data and the rendered HTML for the About box and related Techniques
445445
const $termLinks = $(termLinkSelector);
446446
const extractTermName = ($el: CheerioAnyNode) => {
447447
const name = $el
@@ -640,6 +640,9 @@ export class CustomLiquid extends Liquid {
640640
} else $("section#references").remove();
641641
}
642642

643+
const slugify = slugifyWithCounter();
644+
const slugifyOptions: SlugifyOptions = { decamelize: false };
645+
643646
// Allow autogenerating missing top-level section IDs in understanding docs,
644647
// but don't pick up incorrectly-nested sections in some techniques pages (e.g. H91)
645648
const sectionSelector = scope.isUnderstanding ? "section" : "section[id]:not(.obsolete)";
@@ -650,7 +653,8 @@ export class CustomLiquid extends Liquid {
650653
// when we have sections and sidebar skeleton already reordered
651654
const $tocList = $(".sidebar nav ul");
652655
$h2Sections.each((_, el) => {
653-
if (!el.attribs.id) el.attribs.id = generateId($(el).find(sectionH2Selector).text());
656+
if (!el.attribs.id)
657+
el.attribs.id = slugify($(el).find(sectionH2Selector).text(), slugifyOptions);
654658
$("<a></a>")
655659
.attr("href", `#${el.attribs.id}`)
656660
.text(normalizeTocLabel($(el).find(sectionH2Selector).text()))
@@ -674,9 +678,14 @@ export class CustomLiquid extends Liquid {
674678
$(autoIdSectionSelectors.join(", "))
675679
.filter(`:has(${sectionHeadingSelector})`)
676680
.each((_, el) => {
677-
el.attribs.id = generateId($(el).find(sectionHeadingSelector).text());
681+
el.attribs.id = slugify($(el).find(sectionHeadingSelector).text(), slugifyOptions);
678682
});
679683

684+
// Also autogenerate IDs for any headings with no dedicated section nor explicit ID
685+
$(":is(h3, h4, h5):not(:first-child):not([id])").each((_, el) => {
686+
el.attribs.id = slugify($(el).text(), slugifyOptions);
687+
});
688+
680689
return stripHtmlComments($.html());
681690
}
682691
}

11ty/README.md

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ XSLT-based build process using Eleventy.
88
Make sure you have Node.js installed. This has primarily been tested with v20,
99
the current LTS at time of writing.
1010

11-
If you use [fnm](https://github.com/Schniz/fnm) or [nvm](https://github.com/nvm-sh/nvm) to manage multiple Node.js versions,
11+
If you use [`fnm`](https://github.com/Schniz/fnm) or [`nvm`](https://github.com/nvm-sh/nvm) to manage multiple Node.js versions,
1212
you can switch to the recommended version by typing `fnm use` or `nvm use`
1313
(with no additional arguments) while in the repository directory.
1414

@@ -23,11 +23,96 @@ Common tasks:
2323
- http://localhost:8080/techniques
2424
- http://localhost:8080/understanding
2525

26-
Maintenance tasks (for working with Eleventy config and supporting files under this subdirectory):
26+
Maintenance tasks (for working with Eleventy config and supporting files used by the build):
2727

2828
- `npm run check` checks for TypeScript errors
2929
- `npm run fmt` formats all TypeScript files
3030

31+
## Publishing to WAI website
32+
33+
The following npm scripts can be used to assist with publishing updates to the WAI website:
34+
35+
- `npm run publish-w3c` to publish 2.2
36+
- `npm run publish-w3c:21` to publish 2.1
37+
38+
Each of these scripts performs the following steps:
39+
40+
1. Updates the data used for the Techniques Change Log page
41+
- Note that this step may result in changes to `techniques/changelog.11tydata.json`, which should be committed to `main`
42+
2. Runs the build for the appropriate WCAG version, generating pages and `wcag.json` under `_site`
43+
3. Copies the built files from `_site` to the CVS checkout (see [`WCAG_CVSDIR`](#wcag_cvsdir))
44+
45+
## Associated Techniques Data
46+
47+
Each success criterion's page contains a Techniques section which links to associated techniques.
48+
These used to be defined directly in HTML in each respective page, but have since been relocated to
49+
a single data file, `understanding/understanding.11tydata.js`, under the key `associatedTechniques`.
50+
51+
This field is typed, in order to provide some degree of autocomplete in IDEs that support TypeScript
52+
(e.g. Visual Studio Code), as well as some amount of immediate feedback while editing.
53+
Further validation is performed when running the build or dev server, to provide more focused error messages for common mistakes.
54+
55+
### Listing Techniques
56+
57+
Techniques may be indicated via an object as outlined below, or using a shorthand string.
58+
Shorthand strings may function as either `id` or `title` seen below, and are
59+
recommended for brevity when no `using` or `and` relationship is present.
60+
61+
The following list outlines properties available on each technique object:
62+
63+
- `id` - Technique ID
64+
- `title` - Technique description (HTML flow content allowed), to define free-form entries that don't reference a specific technique
65+
- `using` - Optional array of further techniques to be populated into a child list
66+
- Child techniques may also include `using`
67+
- `usingConjunction` - When `using` is specified, this overrides the word that appears before `usingQuantity`
68+
- Default: `"using"`; HTML flow content allowed
69+
- `usingQuantity` - When `using` is specified, this overrides the word that appears after `usingConjunction` and before "of the following techniques"
70+
- Default: `"one"`
71+
- May be empty string (`""`), in which case the subsequent "of" is dropped
72+
- `usingPrefix` - Adds text to appear before `usingConjunction`
73+
- `skipUsingPhrase` - Omits the entire "... using ... of the following techniques" phrase
74+
- This is mainly an escape hatch for rare instances where a child list is used but no "using" phrase appears at all (e.g. in 1.4.4: Resize Text)
75+
76+
Typically, either `id` or `title` is required.
77+
If `id` is specified, then `prefix` and/or `suffix` may also be specified (with HTML flow content allowed in each),
78+
resulting in "{prefix} {linked technique title} {suffix}".
79+
80+
In extremely rare cases, `using` may be specified alone without either `id` or `title`,
81+
e.g. for top-level "Using two or more of the following" in 2.4.5: Multiple Ways.
82+
83+
#### Conjunctions
84+
85+
To represent multiple parallel techniques, an `and` key may be specified instead of `id` or `title`. In this case, the following properties are supported:
86+
87+
- `and` - an array of technique objects or shorthand strings (as described above)
88+
- `using` and its related fields (seen above) may optionally be specified alongside `and`
89+
- `andConjunction` may optionally be specified alongside `and`,
90+
to override the default `"<strong>AND</strong>"` phrasing (e.g. in 4.1.3: Status Messages)
91+
- Techniques listed _within_ `and` should be flat, never containing `and` or `using`
92+
93+
### Situations or Other Subsections (Sufficient only)
94+
95+
The top level of the `sufficient` array may consist entirely of either technique entries (see above)
96+
or subsection entries. It should not contain a mix of both.
97+
98+
Subsections are typically used to define multiple "situations", where each title begins with "Situation A:", "Situation B:", etc.;
99+
in rare cases it is used for other purposes, e.g. in 1.4.8: Visual Presentation.
100+
101+
Subsection entries contain the following:
102+
103+
- `title` (required, HTML allowed)
104+
- `techniques` (required) - array of technique entries (see above)
105+
- `note` (optional, HTML allowed) - content to appear in a Note at the end of the subsection (e.g. in 4.1.3: Status Messages)
106+
- `groups` (optional) - array of objects with `id`, `title`, `techniques`; see more below
107+
- `techniques` within `groups` are not expected to involve `and` or `using`
108+
109+
#### Groups within Situations
110+
111+
Most of the situations in 1.1.1: Non-text Content include groupings which start with a boldface paragraph (not a heading),
112+
and are referenced one or more times within preceding "using" clauses.
113+
Groups can be defined at the top level of each situation/section entry as mentioned above.
114+
Defining `groups` automatically implies a "using" relationship, without explicitly defining `using` for each technique.
115+
31116
## Environment Variables
32117

33118
### `WCAG_CVSDIR`
@@ -98,6 +183,8 @@ Generates `_site/wcag.json`. (This is not done by default, as it adds to build t
98183

99184
**Default:** Unset by default; `publish-w3c` scripts set this to a non-empty value.
100185

186+
For more information on the output, see [11ty/json/README.md](json#readme).
187+
101188
### `GITHUB_REPOSITORY`
102189

103190
**Usage context:** Automatically set during GitHub workflows; should not need to be set manually

0 commit comments

Comments
 (0)