diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1f253b81f..0f71f476d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,7 +176,18 @@ jobs: - name: Run composer audit run: | cd az-quickstart-scaffolding - composer audit --no-dev --ignore-severity=low --ignore-severity=moderate + set +e + composer audit --no-dev --ignore-severity=low --ignore-severity=moderate > composer-audit.log 2>&1 + composer_audit_status=$? + cat composer-audit.log + if [ "$composer_audit_status" -eq 0 ]; then + exit 0 + fi + if [ "$composer_audit_status" -eq 2 ] && grep -q "No security vulnerability advisories found." composer-audit.log; then + echo "Composer audit reported only abandoned packages; continuing." + exit 0 + fi + exit "$composer_audit_status" yarn-audit: name: yarn audit (security) diff --git a/modules/custom/az_carousel/az_carousel.libraries.yml b/modules/custom/az_carousel/az_carousel.libraries.yml index 042e26ef1b..de824db445 100644 --- a/modules/custom/az_carousel/az_carousel.libraries.yml +++ b/modules/custom/az_carousel/az_carousel.libraries.yml @@ -1,4 +1,10 @@ az_carousel: + js: + js/az_carousel.a11y.js: {} css: theme: css/az_carousel.css: {} + dependencies: + - core/drupal + - core/jquery + - core/once diff --git a/modules/custom/az_carousel/js/az_carousel.a11y.js b/modules/custom/az_carousel/js/az_carousel.a11y.js new file mode 100644 index 0000000000..e5af0899aa --- /dev/null +++ b/modules/custom/az_carousel/js/az_carousel.a11y.js @@ -0,0 +1,55 @@ +(function azCarouselA11yScript(Drupal, once, $) { + function normalizeCarouselAria(carousel) { + carousel + .querySelectorAll( + '.slick-track[role="listbox"], .slick-slide[role="option"]', + ) + .forEach((element) => { + element.removeAttribute('role'); + element.removeAttribute('aria-describedby'); + }); + + carousel.querySelectorAll('.slick-dots[role="tablist"]').forEach((dots) => { + dots.removeAttribute('role'); + dots.removeAttribute('aria-label'); + dots.removeAttribute('aria-labelledby'); + dots.removeAttribute('aria-orientation'); + }); + + carousel.querySelectorAll('.slick-dots li').forEach((dotItem) => { + dotItem.removeAttribute('role'); + dotItem.removeAttribute('aria-selected'); + dotItem.removeAttribute('aria-controls'); + }); + + carousel + .querySelectorAll( + '[aria-hidden="true"] a, [aria-hidden="true"] button, [aria-hidden="true"] input, [aria-hidden="true"] select, [aria-hidden="true"] textarea, [aria-hidden="true"] [tabindex]', + ) + .forEach((focusable) => { + focusable.setAttribute('tabindex', '-1'); + }); + + carousel + .querySelectorAll( + '[aria-hidden="false"] a[tabindex="-1"], [aria-hidden="false"] button[tabindex="-1"], [aria-hidden="false"] input[tabindex="-1"], [aria-hidden="false"] select[tabindex="-1"], [aria-hidden="false"] textarea[tabindex="-1"], [aria-hidden="false"] [tabindex="-1"]', + ) + .forEach((focusable) => { + focusable.removeAttribute('tabindex'); + }); + } + + Drupal.behaviors.azCarouselA11y = { + attach(context) { + once('az-carousel-a11y', '.az-carousel', context).forEach((carousel) => { + const $carousel = $(carousel); + const runNormalization = () => normalizeCarouselAria(carousel); + + runNormalization(); + $carousel.on('init reInit afterChange setPosition breakpoint', () => { + runNormalization(); + }); + }); + }, + }; +})(Drupal, once, jQuery);