99// ----------------------------------------------------------------------------
1010
1111import hasAttribute from '../util/hasAttribute' ;
12+ import getAttributeValue from '../util/getAttributeValue' ;
1213import isHiddenFromScreenReader from '../util/isHiddenFromScreenReader' ;
1314import getNodeType from '../util/getNodeType' ;
1415
@@ -21,6 +22,11 @@ const REDUNDANT_WORDS = [
2122const errorMessage = 'Redundant alt attribute. Screen-readers already announce `img` tags as an image. ' +
2223 'You don\'t need to use the words `image`, `photo,` or `picture` in the alt prop.' ;
2324
25+ const validTypes = [
26+ 'LITERAL' ,
27+ 'TEMPLATELITERAL'
28+ ] ;
29+
2430module . exports = context => ( {
2531 JSXOpeningElement : node => {
2632 const type = getNodeType ( node ) ;
@@ -29,11 +35,26 @@ module.exports = context => ({
2935 }
3036
3137 const altProp = hasAttribute ( node . attributes , 'alt' ) ;
38+ // Return if alt prop is not present.
39+ if ( altProp === false ) {
40+ return ;
41+ }
42+
43+ // Only check literals, as we should not enforce variable names :P
44+ const normalizedType = altProp . value && altProp . value . type . toUpperCase ( ) === 'JSXEXPRESSIONCONTAINER' ?
45+ altProp . value . expression . type . toUpperCase ( ) :
46+ altProp . value . type . toUpperCase ( ) ;
47+
48+ if ( validTypes . indexOf ( normalizedType ) === - 1 ) {
49+ return ;
50+ }
51+
52+ const value = getAttributeValue ( altProp ) ;
3253 const isVisible = isHiddenFromScreenReader ( node . attributes ) === false ;
3354
34- if ( Boolean ( altProp ) && typeof altProp === 'string' && isVisible ) {
55+ if ( Boolean ( value ) && typeof value === 'string' && isVisible ) {
3556 const hasRedundancy = REDUNDANT_WORDS
36- . some ( word => Boolean ( altProp . match ( new RegExp ( `(?!{)${ word } (?!})` , 'gi' ) ) ) ) ;
57+ . some ( word => Boolean ( value . match ( new RegExp ( `(?!{)${ word } (?!})` , 'gi' ) ) ) ) ;
3758
3859 if ( hasRedundancy === true ) {
3960 context . report ( {
0 commit comments