Skip to content

Commit a8cb5cd

Browse files
authored
Generate IDs for sectionless headings, and improve/fix existing IDs (#4523)
Fixes #4425. This adds IDs to headings that aren't the first under their respective parent section, and relies on `@sindresorhus/slugify` to produce headings, with counters when duplicate labels exist. (This library is an existing dependency of Eleventy, so it does not increase `npm install` size.) This updates _all_ generated IDs to use `slugify` instead of the previous logic that had been ported from the XSLT process. This means some subsection IDs may change; it also means some which were previously inaccessible due to duplicate IDs will be fixed. None of the standard level-2 headings should be impacted. I performed extra testing to check for headings that might've been overlooked by the selector I used here, but all of the first-child cases involve headings under sections which will already have IDs.
1 parent 50ba7ae commit a8cb5cd

File tree

4 files changed

+16
-5
lines changed

4 files changed

+16
-5
lines changed

11ty/CustomLiquid.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { type Options as SlugifyOptions, slugifyWithCounter } from "@sindresorhus/slugify";
12
import hljs from "highlight.js";
23
import { Liquid, type Template } from "liquidjs";
34
import type { LiquidOptions, RenderOptions } from "liquidjs/dist/liquid-options";
@@ -10,7 +11,6 @@ import type { GlobalData } from "eleventy.config";
1011

1112
import { biblioPattern, getBiblio, getXmlBiblio } from "./biblio";
1213
import { flattenDom, load, type CheerioAnyNode } from "./cheerio";
13-
import { generateId } from "./common";
1414
import { getAcknowledgementsForVersion, type TermsMap } from "./guidelines";
1515
import { resolveTechniqueIdFromHref, understandingToTechniqueLinkSelector } from "./techniques";
1616
import { techniqueToUnderstandingLinkSelector } from "./understanding";
@@ -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
}

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"license": "W3C",
1919
"dependencies": {
2020
"@11ty/eleventy": "^3.1.2",
21+
"@sindresorhus/slugify": "^2.2.1",
2122
"axios": "^1.11.0",
2223
"cheerio": "^1.0.0",
2324
"glob": "^10.3.16",

understanding/understanding-techniques.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ <h2>Sufficient Techniques</h2>
4444
<p>From an evaluator's perspective: If web content implements the sufficient techniques for a given criterion correctly and it is <a href="conformance#accessibility-support">accessibility-supported</a> for the content's users, it conforms to that success criterion. (The converse is not true; if content does not implement these sufficient techniques, it does not necessarily fail the success criteria, as explained in <a href="#testing-techniques">Testing Techniques</a> below.)</p>
4545
</li>
4646
</ul>
47-
<p>There may be other ways to meet success criteria besides the sufficient techniques in W3C's <a href="../Techniques/">Techniques for WCAG {{ versionDecimal }}</a> document, as explained in <a href="#understanding-techniques-othertechs">Other Techniques</a> below. <em>(See also <a href="#understanding-techniques-informative">Techniques are Informative</a> above.)</em></p>
47+
<p>There may be other ways to meet success criteria besides the sufficient techniques in W3C's <a href="../Techniques/">Techniques for WCAG {{ versionDecimal }}</a> document, as explained in <a href="#other-techniques">Other Techniques</a> below. <em>(See also <a href="#techniques-are-informative">Techniques are Informative</a> above.)</em></p>
4848
<section>
4949
<h3>Numbered Lists, "AND"</h3>
5050
<p> The W3C-documented sufficient techniques are provided in a numbered list where each list item provides a technique or combination of techniques that can be used to meet the success criterion. Where there are multiple techniques on a numbered list item connected by "AND" then all of the techniques must be used to be sufficient. For example, <a href="info-and-relationships#techniques">Sufficient Techniques for 1.3.1</a> has: "G115: Using semantic elements to mark up structure AND H49: Using semantic markup to mark emphasized or special text (HTML)".</p>
@@ -87,7 +87,7 @@ <h2>General and Technology-specific Techniques</h2>
8787
<section>
8888
<h2>Other Techniques</h2>
8989
<p>In addition to the techniques in W3C's <a href="../Techniques/">Techniques for WCAG {{ versionDecimal }}</a> document, <em>there are other ways to meet WCAG {{ versionDecimal }} success criteria</em>. W3C's techniques are not comprehensive and may not cover newer technologies and situations.</p>
90-
<p><em>web content does not have to use W3C's published techniques in order to conform to WCAG {{ versionDecimal }}. (See also <a href="understanding-techniques-informative">Techniques are Informative</a> above.)</em></p>
90+
<p><em>web content does not have to use W3C's published techniques in order to conform to WCAG {{ versionDecimal }}. (See also <a href="#techniques-are-informative">Techniques are Informative</a> above.)</em></p>
9191
<p>Content authors can develop different techniques. For example, an author could develop a technique for HTML5, <a href="https://www.w3.org/WAI/intro/aria">WAI-ARIA</a>, or other new technology. Other organizations may develop sets of techniques to meet WCAG {{ versionDecimal }} success criteria.</p>
9292
<p>Any techniques can be sufficient if:</p>
9393
<ul>

0 commit comments

Comments
 (0)