import { Rule , Diagnostic } from "@siteimprove/alfa-act" ; import { Device } from "@siteimprove/alfa-device" ; import { Element , Node , Text } from "@siteimprove/alfa-dom" ; import { Predicate } from "@siteimprove/alfa-predicate" ; import { Refinement } from "@siteimprove/alfa-refinement" ; import { Ok , Err } from "@siteimprove/alfa-result" ; import { Page } from "@siteimprove/alfa-web" ; import { expectation } from "../common/expectation" ; import { isRendered , isVisible , hasAttribute } from "../common/predicate" ; import { Scope } from "../tags" ; const { equals } = Predicate ; const { hasName , isElement } = Element ; const { isText } = Text ; const { and } = Refinement ; export default Rule . Atomic . of < Page , Element > ( { uri : "https://alfa.siteimprove.com/rules/sia-r79" , tags : [ Scope . Component ] , evaluate ( { device , document } ) { return { applicability ( ) { return document . descendants ( { flattened : true , nested : true , } ) . filter ( isElement ) . filter ( and ( hasName ( "pre" ) , isRendered ( device ) ) ) ; } , expectations ( target ) { return { 1 : expectation ( isVisible ( device ) ( target ) , ( ) => Outcomes . IsVisible , ( ) => expectation ( target . inclusiveAncestors ( { flattened : true , nested : true , } ) . filter ( isElement ) . some ( hasAttribute ( "aria-hidden" , equals ( "true" ) ) ) , ( ) => Outcomes . IsHidden , ( ) => Outcomes . IsNotVisibleAndNotHidden ) ) , 2 : expectation ( hasFigureAncestor ( target ) || hasOnlyAllowedText ( device ) ( target ) , ( ) => Outcomes . IsDescendant , ( ) => Outcomes . IsNotDescendant ) , } ; } , } ; } , } ) ; function hasOnlyAllowedText ( device ) { return function hasOnlyAllowedText ( node ) : boolean { if ( and ( isElement , hasName ( "code" , "kbd" , "samp" ) ) ( node ) ) { return true ; } if ( and ( isText , isVisible ( device ) ) ( node ) ) { return false ; } return node . children ( { flattened : true , nested : true , } ) . every ( hasOnlyAllowedText ) ; } ; } function hasFigureAncestor ( target ) { return target . ancestors ( { flattened : true , nested : true , } ) . filter ( isElement ) . some ( hasName ( "figure" ) ) ; } export namespace Outcomes { export const IsVisible = Ok . of ( Diagnostic . of ( `The element is visible.` ) ) ; export const IsHidden = Ok . of ( Diagnostic . of ( `One inclusive ancestor of the element has "aria-hidden = true."` ) ) ; export const IsDescendant = Ok . of ( Diagnostic . of ( `The target element either has a <figure> ancestor, or all its text is inside <code>, <kbd> or <samp> elements.` ) ) ; export const IsNotVisibleAndNotHidden = Err . of ( Diagnostic . of ( `The element is not visible and there isn't an inclusive ancestor with "aria-hidden" state.` ) ) ; export const IsNotDescendant = Err . of ( Diagnostic . of ( `The element has no <figure> ancestor and has text which not inside a <code>, <kbd> or <samp> element. ` ) ) ; }