Repository: vue-a11y/eslint-plugin-vuejs-accessibility (ts)

Issue:
[anchor-has-content] with a image with `alt` fails but it should pass
[anchor-has-content] with a image with `alt` fails but it should pass because the alt text serves as content for the anchor

Pull request:
anchor-has-content should respect images with alt
Closes #48

Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 608367e..569fb06 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,5 +1,5 @@
 name: Main
-on: push
+on: [push, pull_request]
 jobs:
   ci:
     name: CI
@@ -8,7 +8,7 @@ jobs:
       CI: true
     steps:
       - uses: actions/checkout@master
-      - uses: actions/setup-node@v1
+      - uses: actions/setup-node@v2-beta
         with:
           node-version: 14.x
       - id: yarn-cache
@@ -19,7 +19,10 @@ jobs:
           key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
           restore-keys: |
             ${{ runner.os }}-yarn-
-      - run: yarn install --frozen-lockfile
-      - run: yarn prettier --check '**/*'
-      - run: yarn lint
-      - run: yarn test
+      - name: Install dependencies
+        run: yarn install --frozen-lockfile
+      - name: Lint and test
+        run: |
+          yarn prettier --check '**/*'
+          yarn lint
+          yarn test
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e25ab5f..5fef0ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
 ### Changed
 
 - Ensure all rules that allow configuring extra components that should match certain conditions support both forms of casing (`VFoo` and `v-foo`).
+- For the `anchor-has-content` rule, we're now going to allow images with an `alt` tag as the screen reader should pick that up as the content.
 
 ## [0.4.0] - 2020-08-15
 
diff --git a/src/utils/hasContent.js b/src/utils/hasContent.js
index fb0858f..479cf70 100644
--- a/src/utils/hasContent.js
+++ b/src/utils/hasContent.js
@@ -1,13 +1,31 @@
+const getElementAttributeValue = require("./getElementAttributeValue");
+const getElementType = require("./getElementType");
 const hasAccessibleChild = require("./hasAccessibleChild");
+const isHiddenFromScreenReader = require("./isHiddenFromScreenReader");
 
 const hasDirective = (node, name) =>
   node.startTag.attributes.some(
     (attribute) => attribute.directive && attribute.key.name.name === name
   );
 
+const hasChildImageWithAlt = (node) =>
+  node.children.some((child) => {
+    if (child.type === "VElement") {
+      if (
+        !isHiddenFromScreenReader(child) &&
+        getElementType(child) === "img" &&
+        getElementAttributeValue(child, "alt")
+      ) {
+        return true;
+      }
+      return hasChildImageWithAlt(child);
+    }
+  });
+
 const hasContent = (node) =>
   hasAccessibleChild(node) ||
   hasDirective(node, "text") ||
-  hasDirective(node, "html");
+  hasDirective(node, "html") ||
+  hasChildImageWithAlt(node);
 
 module.exports = hasContent;


Test patch:
diff --git a/src/rules/__tests__/anchor-has-content.test.js b/src/rules/__tests__/anchor-has-content.test.js
index 38a1690..756c7a7 100644
--- a/src/rules/__tests__/anchor-has-content.test.js
+++ b/src/rules/__tests__/anchor-has-content.test.js
@@ -9,7 +9,8 @@ makeRuleTester("anchor-has-content", rule, {
     "<a v-html='msg' />",
     "<a><slot /></a>",
     "<VAnchor  />",
-    "<a aria-label='This is my label' />"
+    "<a aria-label='This is my label' />",
+    "<a><img alt='foo' /></a>"
   ],
   invalid: [
     "<a />",
@@ -17,6 +18,7 @@ makeRuleTester("anchor-has-content", rule, {
       code: "<v-anchor  />",
       options: [{ components: ["VAnchor"] }],
       errors: [{ messageId: "default" }]
-    }
+    },
+    "<a><img aria-hidden alt='foo' /></a>"
   ]
 });