Repository: vue-a11y/eslint-plugin-vuejs-accessibility
Pull request #8 (2020-05-11 20:35:03)

Fix hasContent check for slots and handle v-bind with object


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49fa2dd..a9a77e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
 
 ## [Unreleased]
 
+## [0.1.2] - 2020-05-11
+
+### Changed
+
+- Support using `v-bind` to pass an object, as in `v-bind:$attrs`.
+- The `hasContent` check should be assume slots will have content.
+
 ## [0.1.1] - 2020-04-27
 
 ### Changed
@@ -19,6 +26,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
 
 - Initial release 🎉.
 
-[unreleased]: https://github.com/vue-a11y/eslint-plugin-vuejs-accessibility/compare/v0.1.1...HEAD
+[unreleased]: https://github.com/vue-a11y/eslint-plugin-vuejs-accessibility/compare/v0.1.2...HEAD
+[0.1.2]: https://github.com/CultureHQ/components/compare/v0.1.1...v0.1.2
 [0.1.1]: https://github.com/CultureHQ/components/compare/v0.1.0...v0.1.1
 [0.1.0]: https://github.com/CultureHQ/components/compare/9de449...v0.1.0
diff --git a/src/utils/getAttributeName.js b/src/utils/getAttributeName.js
index 31b2dc7..7874a58 100644
--- a/src/utils/getAttributeName.js
+++ b/src/utils/getAttributeName.js
@@ -4,7 +4,7 @@ const getAttributeName = (node) => {
   if (!node.directive) {
     return key.name;
   }
-  return key.name.name === "bind" && key.argument.name;
+  return key.name.name === "bind" && key.argument && key.argument.name;
 };
 
 module.exports = getAttributeName;
diff --git a/src/utils/getElementAttribute.js b/src/utils/getElementAttribute.js
index a0d6547..a6887f8 100644
--- a/src/utils/getElementAttribute.js
+++ b/src/utils/getElementAttribute.js
@@ -6,6 +6,7 @@ const getElementAttribute = (node, name) => {
       (!attribute.directive && key.name === name) ||
       (attribute.directive &&
         key.name.name === "bind" &&
+        key.argument &&
         key.argument.name === name)
     ) {
       return attribute;
diff --git a/src/utils/getLiteralAttributeValue.js b/src/utils/getLiteralAttributeValue.js
index 2c7a8f8..dd0fc57 100644
--- a/src/utils/getLiteralAttributeValue.js
+++ b/src/utils/getLiteralAttributeValue.js
@@ -9,6 +9,7 @@ const getLiteralAttributeValue = (node, name) => {
     if (
       attribute.directive &&
       key.name.name === "bind" &&
+      key.argument &&
       key.argument.name === name &&
       value &&
       value.expression &&
diff --git a/src/utils/hasAccessibleChild.js b/src/utils/hasAccessibleChild.js
index cd1dcd2..d2e3ca4 100644
--- a/src/utils/hasAccessibleChild.js
+++ b/src/utils/hasAccessibleChild.js
@@ -6,7 +6,10 @@ const hasAccessibleChild = (node) =>
       case "VText":
         return child.value.trim().length > 0;
       case "VElement":
-        return !isHiddenFromScreenReader(child) && hasAccessibleChild(child);
+        return (
+          child.rawName === "slot" ||
+          (!isHiddenFromScreenReader(child) && hasAccessibleChild(child))
+        );
       case "VExpressionContainer":
         if (child.expression && child.expression.type === "Identifier") {
           return child.expression.name !== "undefined";
diff --git a/src/utils/hasOnDirective.js b/src/utils/hasOnDirective.js
index a63d451..bf02201 100644
--- a/src/utils/hasOnDirective.js
+++ b/src/utils/hasOnDirective.js
@@ -5,6 +5,7 @@ const hasOnDirective = (node, name) =>
     return (
       attribute.directive &&
       key.name.name === "on" &&
+      key.argument &&
       key.argument.name === name &&
       value &&
       value.expression &&
diff --git a/src/utils/isAttribute.js b/src/utils/isAttribute.js
index aced255..bff218d 100644
--- a/src/utils/isAttribute.js
+++ b/src/utils/isAttribute.js
@@ -3,7 +3,10 @@ const isAttribute = (node, name) => {
 
   return (
     (!node.directive && key.name === name) ||
-    (node.directive && key.name.name === "bind" && key.argument.name === name)
+    (node.directive &&
+      key.name.name === "bind" &&
+      key.argument &&
+      key.argument.name === name)
   );
 };
 


Test patch:
diff --git a/src/rules/__tests__/anchor-has-content.test.js b/src/rules/__tests__/anchor-has-content.test.js
index de7d0f0..cc9dcf3 100644
--- a/src/rules/__tests__/anchor-has-content.test.js
+++ b/src/rules/__tests__/anchor-has-content.test.js
@@ -7,6 +7,7 @@ makeRuleTester("anchor-has-content", rule, {
     "<a is='TextWrapper' />",
     "<a v-text='msg' />",
     "<a v-html='msg' />",
+    "<a><slot /></a>",
     "<Anchor  />"
   ],
   invalid: [
diff --git a/src/rules/__tests__/heading-has-content.test.js b/src/rules/__tests__/heading-has-content.test.js
index af274df..0537567 100644
--- a/src/rules/__tests__/heading-has-content.test.js
+++ b/src/rules/__tests__/heading-has-content.test.js
@@ -7,7 +7,8 @@ makeRuleTester("heading-has-content", rule, {
     "<h1><span>test</span></h1>",
     "<h1 v-text='msg'></h1>",
     "<h1 v-html='msg'></h1>",
-    "<h1>{{ test }}</h1>"
+    "<h1>{{ test }}</h1>",
+    "<h1><slot /></h1>"
   ],
   invalid: [
     "<h1 />",