diff --git a/api/package.json b/api/package.json index 0abb38ad..e3dde550 100644 --- a/api/package.json +++ b/api/package.json @@ -16,7 +16,7 @@ "@data-fair/lib-common-types": "^1.21.0", "@data-fair/lib-express": "^1.23.0", "@data-fair/lib-node": "^2.12.1", - "@data-fair/lib-utils": "^1.12.1", + "@data-fair/lib-utils": "^1.12.2", "@data-fair/portals-shared-markdown": "*", "cheerio": "^1.0.0", "config": "^4.4.1", diff --git a/package-lock.json b/package-lock.json index d81d0d12..afc6b577 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,7 +52,7 @@ "@data-fair/lib-common-types": "^1.21.0", "@data-fair/lib-express": "^1.23.0", "@data-fair/lib-node": "^2.12.1", - "@data-fair/lib-utils": "^1.12.1", + "@data-fair/lib-utils": "^1.12.2", "@data-fair/portals-shared-markdown": "*", "cheerio": "^1.0.0", "config": "^4.4.1", @@ -1096,9 +1096,9 @@ } }, "node_modules/@data-fair/lib-utils": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@data-fair/lib-utils/-/lib-utils-1.12.1.tgz", - "integrity": "sha512-SHSDYik7cd2Rkk2zG9EcM9OlpLH8NcKKgXMY1v/0GtjZOdYsl8GMqDUUNTff4F75Gdhc0IP6eaSKkl+vgjZxaw==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@data-fair/lib-utils/-/lib-utils-1.12.2.tgz", + "integrity": "sha512-DO5x9f91kT6FabUYwIb9J/ls7fVd5R91NbRM15fftNvm4b6A1feGBodbydvHdd5WYNzpXyHyUAat62D8ZeHViw==", "license": "MIT", "peerDependencies": { "dayjs": "1" @@ -1169,9 +1169,9 @@ } }, "node_modules/@data-fair/lib-vuetify": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@data-fair/lib-vuetify/-/lib-vuetify-2.4.1.tgz", - "integrity": "sha512-g16v2tRt+v52CTJRn2efND4szst1evOqZxeyGpHWb59IyIV7GoPSpzR3zqJHpdaRIcqpSmTxbW/yXJcv061kDQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@data-fair/lib-vuetify/-/lib-vuetify-2.4.2.tgz", + "integrity": "sha512-Sm31iRBtsgNVbpGurtgrApl9g75NWyy/cijMNyL+DjGYLaFZEliy5kfAGVGSVAw9+Krhf56fry5bxJwu9Am8Kw==", "license": "MIT", "dependencies": { "@data-fair/lib-common-types": "^1.10.4", @@ -25198,10 +25198,10 @@ "@data-fair/frame": "^0.18.1", "@data-fair/lib-common-types": "^1.21.0", "@data-fair/lib-node": "^2.12.1", - "@data-fair/lib-utils": "^1.12.1", + "@data-fair/lib-utils": "^1.12.2", "@data-fair/lib-vue": "^1.29.1", "@data-fair/lib-vue-agents": "^0.4.0", - "@data-fair/lib-vuetify": "^2.4.0", + "@data-fair/lib-vuetify": "^2.4.2", "@data-fair/lib-vuetify-agents": "^0.6.0", "@data-fair/lib-vuetify-events": "^0.3.0", "@data-fair/portals-shared-markdown": "*", @@ -25226,7 +25226,7 @@ "shared/markdown": { "name": "@data-fair/portals-shared-markdown", "dependencies": { - "@data-fair/lib-utils": "^1.12.1", + "@data-fair/lib-utils": "^1.12.2", "marked": "^15.0.12", "sanitize-html": "^2.17.0" } @@ -25237,7 +25237,7 @@ "@data-fair/lib-common-types": "^1.21.0", "@data-fair/lib-vue": "^1.29.1", "@data-fair/lib-vue-agents": "^0.4.0", - "@data-fair/lib-vuetify": "^2.4.0", + "@data-fair/lib-vuetify": "^2.4.2", "@data-fair/lib-vuetify-agents": "^0.6.0", "@data-fair/portals-shared-markdown": "*", "@intlify/unplugin-vue-i18n": "^11.0.7", diff --git a/patches/README.md b/patches/README.md index 6a254a4d..696792c8 100644 --- a/patches/README.md +++ b/patches/README.md @@ -114,6 +114,36 @@ stays valid. **Removal criterion**: when Vuetify stops emitting `aria-hidden="false"` on labels. +### `lib/components/VImg/VImg.js` — W3C HTML validity for decorative images + +`VImg` mirrors its `alt` prop onto its root element, next to a `role` that is guarded on +the same value: + +```js +'aria-label': props.alt, +role: props.alt ? 'img' : undefined +``` + +A decorative image is declared with `alt=""` — the empty string is falsy, so the root +gets no role, but the attribute is still emitted and the element renders as +`
`. W3C rejects that: `aria-label` must not be used on +a `div` whose role is `generic`. RGAA 8.2. Four occurrences on the portal visualisation +catalogue (one per card thumbnail), twenty on a full catalogue page. + +This patch emits the attribute only when `alt` is non-empty (`props.alt || undefined`), +the guard the neighbouring `role` binding already applies. Nothing changes for +informative images: they keep `role="img"` and their label. Decorative ones lose an +attribute that carried no name anyway — the inner `img` keeps its `alt=""`, which is +what makes it decorative, so restitution is unchanged. + +There is no userland fix: the object holding `aria-label` is the last argument of the +root's `mergeProps`, so it overrides any `aria-label` passed by the caller, and dropping +the `alt` prop instead would leave the inner `img` without an `alt` attribute — one W3C +error traded for another. + +**Removal criterion**: when Vuetify guards `aria-label` like it guards `role` — reported +as vuetifyjs/vuetify#23111, fix proposed upstream in vuetifyjs/vuetify#23112. + ### `lib/components/VSelect/VSelect.js` — W3C HTML validity for the hidden native select `VSelect` mirrors its items into a `