fix(portal): W3C HTML validation fixes on public portals#65
Merged
Conversation
- layout-title: keep only phrasing content inside h1..h6 (decorative <span> stand-ins instead of <v-divider>/<div>); accessibility-improving since the decorative lines no longer carry an erroneous role="separator" - d-frame-wrapper: switch from .client.vue to <ClientOnly> + inheritAttrs:false so SSR no longer leaks <div iframe-title="..." src="..." aspect-ratio>; .client.vue alone could not strip the attrs because Nuxt swaps the component for its internal ServerPlaceholder (whose inheritAttrs:true default is what's actually applied in SSR) - nuxt.config: set VProgressLinear bgOpacity/bufferOpacity defaults to bypass parseFloat(undefined) === NaN ending up in SSR-emitted style="opacity:NaN" (workaround for vuetifyjs/vuetify#22876)
- catalog-layout: move role="status" / aria-live live region off the heading and off v-col onto a wrapping <div>; role="status" is invalid on heading elements per W3C, and the vuetify/grid-unknown-attributes lint rule rejects non-grid attrs on v-col - layout-skip-links: drop redundant role="navigation" on <nav>
- portal/app/plugins/03-vuetify.ts: stop passing cspNonce to Vuetify; nuxt-security already adds a nonce on every <style> during SSR, so the extra cspNonce produced a duplicate `nonce=` attribute on the theme stylesheet (W3C duplicate-attribute error) - patches/vuetify+4.0.7.patch (theme.js): drop tagPosition: 'bodyOpen' and prepend the canonical @layer order to the theme stylesheet content; keeps the cascade correct while putting <style> back inside <head> (HTML-valid) - patches/vuetify+4.0.7.patch (router.js): resync of the existing iframe-href patch from the previous 4.0.3 file (no functional change) - patches/README.md: document the vuetify patches with upstream links and removal criteria - portal/package.json: pin vuetify to ^4.0.7 so the patch matches the installed version - .nvmrc + package.json engines: bump Node requirement to >=24.11.0 to match what current postcss/cssnano transitive deps need Refs: vuetifyjs/vuetify#22656
…rent breadcrumb Vuetify's useLink patch was forwarding `target="_top"` to every element rendered by v-btn (including <button>), and v-breadcrumbs-item exposed the current page as an <a href aria-disabled="true"> — both invalid HTML flagged by W3C. - patch useLink so `target` is only added when the element is actually a link (<a>). - strip `to`/`href` from the last breadcrumb item so it renders as plain text inside the <li>; the existing CSS only styles `.v-breadcrumbs-item--link`, so visuals stay identical and `aria-current="page"` keeps conveying the semantic state.
…les for W3C validation
f3a08d6 to
bef62e0
Compare
The previous lockfile had dangling references to transitive deps (@emnapi/core, @emnapi/runtime, sass@1.99.0, chokidar@4.0.3, readdirp@4.1.2) without top-level entries, causing `npm ci` to fail. Regenerated cleanly from package.json — no version drift on resolved packages.
The previous lockfile was generated incrementally and missed top-level entries for transitive deps required by some optional sass-embedded variants. `npm ci` validates the full graph and was failing with 'Missing: sass@1.99.0' etc. Regenerated from a clean install which resolved all platform variants and their transitive deps.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
<a href aria-disabled>on the current breadcrumb (last item is stripped ofto/hrefso Vuetify renders it as plain text inside the<li>), moverole="status"off heading elements onto wrapper<div>s incatalog-layout, replace<v-divider>/<div>inside title headings with phrasing<span>s +aria-hidden, drop the redundantrole="navigation"on<nav>in skip-links, and stop emittingtargeton non-<a>tags via a local patch on Vuetify'suseLinkcomposable.^4.0.3→^4.0.7and rebase the local patch on the new version. New patch hunk ontheme.js: drop the upstreamtagPosition: 'bodyOpen'workaround so the theme stylesheet stays in<head>(HTML-valid), and prepend the canonical@layer vuetify-core, vuetify-components, vuetify-overrides, vuetify-utilities, vuetify-final;declaration to preserve the cascade regardless of parse order vs.main.css. Newpatches/README.mddocuments both hunks and their removal criteria.cspNonceto Vuetify inplugins/03-vuetify.ts:nuxt-securityalready adds a nonce to every<style>during SSR, the extracspNonceproduced a duplicatenonce=attribute on the theme stylesheet.bgOpacity/bufferOpacitydefaults onVProgressLinearinnuxt.config.tsto work around vuetifyjs/vuetify#22876 — without them SSR emitsstyle="opacity:NaN". Values match the CSS fallback (var(--v-border-opacity)= 0.12).d-frame-wrapper: the old.client.vuevariant was replaced at SSR by aServerPlaceholder<div>that received unknown custom-element attrs (src,aspect-ratio,iframe-title…) and was rejected by the W3C validator. The new wrapper uses<ClientOnly>withinheritAttrs: false, so no caller attrs reach the SSR placeholder.<d-frame>itself is pre-registered byplugins/dframe.client.ts(statically importing@data-fair/frame/lib/d-frame.js) socustomElements.definealways runs before any<d-frame>is created — otherwise Vue would set the.adapterIDL property on a not-yet-upgraded element and the constructor would overwrite it.v24→>=24.11.0(.nvmrcaligned on24.11.1) and pass--error-on-failtonpx patch-packagein the Dockerfile so a future vuetify bump that breaks patch application fails the Docker build with a clear signal instead of silently skipping the patch.