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
5 changes: 5 additions & 0 deletions .changeset/few-apples-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Fix a false positive in the dev toolbar accessibility audit for anchors with text inside closed `<details>` elements.
5 changes: 5 additions & 0 deletions .changeset/fix-advanced-routing-404-fallback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes a bug where `experimental.advancedRouting` with `astro/hono` handlers threw `TypeError: Cannot read properties of undefined (reading 'route')` for unmatched routes instead of rendering the custom 404 page.
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
with:
persist-credentials: false
- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup node@${{ matrix.NODE_VERSION }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down Expand Up @@ -125,7 +125,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down Expand Up @@ -184,7 +184,7 @@ jobs:
fetch-depth: 0

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup node@${{ matrix.NODE_VERSION }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down Expand Up @@ -240,7 +240,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup node@${{ matrix.node_version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down Expand Up @@ -295,7 +295,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup node@${{ matrix.NODE_VERSION }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down Expand Up @@ -333,7 +333,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup node@${{ matrix.NODE_VERSION }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/continuous_benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/fix-verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/issue-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
git config user.email "fred+astrobot@astro.build"

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/merge-fix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:

- name: Setup PNPM
if: steps.pr.outputs.number != '' && steps.attempts.outputs.skip != 'true'
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
if: steps.pr.outputs.number != '' && steps.attempts.outputs.skip != 'true'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/merge-main-to-next.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:

- name: Setup PNPM
if: steps.check-next.outputs.exists == 'true'
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
with:
package_json_file: runtime/package.json

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/preview-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
fetch-depth: 0

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
path: main

- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ pnpm-lock.yaml
**/*.mjs
**/*.cjs
**/*.css
**/*.code-snippets

CHANGELOG.md
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"engines": {
"node": ">=22.12.0"
},
"packageManager": "pnpm@11.0.9",
"packageManager": "pnpm@11.5.0",
"dependencies": {
"astro-benchmark": "workspace:*"
},
Expand Down
18 changes: 18 additions & 0 deletions packages/astro/e2e/dev-toolbar-audits.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,22 @@ test.describe('Dev Toolbar - Audits', () => {
const count = await auditHighlights.count();
expect(count).toEqual(0);
});

test('does not warn about anchor text inside closed details but still warns for hidden text', async ({
page,
astro,
}) => {
await page.goto(astro.resolveUrl('/a11y-hidden-anchor'));

const toolbar = page.locator('astro-dev-toolbar');
const appButton = toolbar.locator('button[data-app-id="astro:audit"]');
await appButton.click();

const auditCanvas = toolbar.locator('astro-dev-toolbar-app-canvas[data-app-id="astro:audit"]');
const missingContentHighlights = auditCanvas.locator(
'astro-dev-toolbar-highlight[data-audit-code="a11y-missing-content"]',
);

await expect(missingContentHighlights).toHaveCount(1);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
---

<details>
<summary>More links</summary>
<a href="/docs">Read the documentation</a>
</details>

<a href="/hidden">
<span style="display: inline-block; width: 1rem; height: 1rem"></span>
<span hidden>Hidden label</span>
</a>
18 changes: 10 additions & 8 deletions packages/astro/src/core/fetch/fetch-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { AstroCookies } from '../cookies/index.js';
import { type Pipeline, Slots } from '../render/index.js';
import {
ASTRO_GENERATOR,
DEFAULT_404_COMPONENT,
fetchStateSymbol,
originPathnameSymbol,
pipelineSymbol,
Expand All @@ -36,7 +35,7 @@ import { Rewrites } from '../rewrites/handler.js';
import { isRoute404or500, isRouteServerIsland } from '../routing/match.js';
import { normalizeUrl } from '../util/normalized-url.js';
import { getOriginPathname, setOriginPathname } from '../routing/rewrite.js';
import { routeHasHtmlExtension } from '../routing/helpers.js';
import { getCustom404Route, routeHasHtmlExtension } from '../routing/helpers.js';
import type { ResolvedRenderOptions } from '../app/base.js';
import { getRenderOptions } from '../app/render-options.js';
import { getFirstForwardedValue, validateForwardedHeaders } from '../app/validate-headers.js';
Expand Down Expand Up @@ -579,10 +578,8 @@ export class FetchState implements AstroFetchState {
}
return {
insertDirective(payload) {
if (state?.result?.directives) {
if (state.result) {
state.result.directives = pushDirective(state.result.directives, payload);
} else {
state?.result?.directives.push(payload);
}
},
insertScriptResource(resource) {
Expand Down Expand Up @@ -820,9 +817,14 @@ export class FetchState implements AstroFetchState {

// Fall back to a 404 route so middleware can still run.
if (!this.routeData) {
this.routeData = pipeline.manifestData.routes.find(
(route) => route.component === '404.astro' || route.component === DEFAULT_404_COMPONENT,
);
const custom404 = getCustom404Route(pipeline.manifestData);
// Only use SSR 404 routes here. Prerendered 404 pages are already
// built to static HTML, so the pipeline can't render them at
// runtime. Leaving routeData unset lets the error handler serve
// the pre-built page from disk instead.
if (custom404 && !custom404.prerender) {
this.routeData = custom404;
}
}
if (!this.routeData) {
pipeline.logger.debug('router', "Astro hasn't found routes that match " + this.request.url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ import type { AuditRuleWithSelector } from './index.js';

const WHITESPACE_REGEX = /\s+/;

function isHiddenByClosedDetails(element: HTMLElement): boolean {
for (let parent = element.parentElement; parent; parent = parent.parentElement) {
if (parent.localName !== 'details' || (parent as HTMLDetailsElement).open) continue;

const summary = Array.from(parent.children).find((child) => child.localName === 'summary');
if (!summary?.contains(element)) return true;
}

return false;
}

const a11y_required_attributes = {
a: ['href'],
area: ['alt', 'aria-label', 'aria-labelledby'],
Expand Down Expand Up @@ -367,6 +378,8 @@ export const a11y: AuditRuleWithSelector[] = [
'Headings and anchors must have an accessible name, which can come from: inner text, aria-label, aria-labelledby, an img with alt property, or an svg with a tag <title></title>.',
selector: a11y_required_content.join(','),
match(element: HTMLElement) {
if (isHiddenByClosedDetails(element)) return false;

// innerText is used to ignore hidden text
const innerText = element.innerText?.trim();
if (innerText && innerText !== '') return false;
Expand Down
Loading
Loading