@@ -222,15 +222,15 @@ async function verifyBuildOutput(buildDir, failures) {
222222 // directive injection against the production HTML.
223223 const stats = {
224224 pages : 0 ,
225- articlePages : 0 ,
225+ contentPages : 0 ,
226226 mdMissing : [ ] ,
227227 altMissing : [ ] ,
228228 directiveMissing : [ ] ,
229229 }
230230 await visitHtml ( buildDir , buildDir , stats )
231231
232232 console . log (
233- `Scanned ${ stats . pages } HTML page(s); ${ stats . articlePages } content page(s) with <article>`
233+ `Scanned ${ stats . pages } HTML page(s); ${ stats . contentPages } content page(s) with <article> or <main >`
234234 )
235235
236236 if ( stats . pages === 0 ) {
@@ -258,8 +258,11 @@ async function verifyBuildOutput(buildDir, failures) {
258258 * Recursively walk `dir` for `index.html` files, recording AFDocs-relevant
259259 * violations into `stats`. The body directive is asserted on every page (the
260260 * injector adds it to every `<body>`); the `.md` sibling and alternate link
261- * are asserted on content pages (those with an `<article>`), mirroring the
262- * injector's own "regenerate from `<article>`, then link the `.md`" contract.
261+ * are asserted on content pages, mirroring the injector's own
262+ * "regenerate from `<article>` (falling back to `<main>`), then link the `.md`"
263+ * contract — see `htmlToMarkdown()` in the injector, which selects `<article>`
264+ * first and falls back to `<main>`. The gate must use the SAME selector or
265+ * pages that render under `<main>` without an `<article>` ship unchecked.
263266 */
264267async function visitHtml ( dir , buildDir , stats ) {
265268 const entries = await fs . readdir ( dir , { withFileTypes : true } )
@@ -284,14 +287,17 @@ async function visitHtml(dir, buildDir, stats) {
284287 stats . directiveMissing . push ( relDir || '<root>' )
285288 }
286289
287- // Only content pages (those Docusaurus renders inside <article>) are
288- // expected to produce a `.md` sibling + alternate link. The homepage and
289- // bare landing pages have no <article>, so they're exempt — matching
290- // regenerateMdFromHtml()/injectAlternateLinks() in the injector.
290+ // Only content pages are expected to produce a `.md` sibling + alternate
291+ // link. The injector's regenerateMdFromHtml() converts the first
292+ // `<article>`, OR the first `<main>` when no `<article>` exists, and
293+ // returns null only when neither is present. Mirror that exact fallback
294+ // here so pages whose body lives under `<main>` (no `<article>`) are still
295+ // checked. The homepage and bare landing pages have neither, so they're
296+ // exempt — matching regenerateMdFromHtml()/injectAlternateLinks().
291297 if ( ! relDir || relDir === '.' ) continue
292- if ( ! / < a r t i c l e \b / i. test ( html ) ) continue
298+ if ( ! / < a r t i c l e \b / i. test ( html ) && ! / < m a i n \b / i . test ( html ) ) continue
293299
294- stats . articlePages ++
300+ stats . contentPages ++
295301
296302 const mdAbs = path . join ( buildDir , `${ relDir } .md` )
297303 let mdExists = true
0 commit comments