diff --git a/src/validate/html/a11y.ts b/src/validate/html/a11y.ts
new file mode 100644
index 0000000000..70beea0ac3
--- /dev/null
+++ b/src/validate/html/a11y.ts
@@ -0,0 +1,50 @@
+import * as namespaces from '../../utils/namespaces';
+import validateEventHandler from './validateEventHandler';
+import { Validator } from '../index';
+import { Node } from '../../interfaces';
+
+export default function a11y(
+ validator: Validator,
+ node: Node,
+ elementStack: Node[]
+) {
+ if (node.type === 'Text') {
+ // accessible-emoji
+ return;
+ }
+
+ if (node.type !== 'Element') return;
+
+ const attributeMap = new Map();
+ node.attributes.forEach((attribute: Node) => {
+ attributeMap.set(attribute.name, attribute);
+ });
+
+ if (node.name === 'a') {
+ if (!attributeMap.has('href')) {
+ validator.warn(`A11y: element should have an href attribute`, node.start);
+ }
+
+ if (!node.children.length) {
+ validator.warn(`A11y: element should have child content`, node.start);
+ }
+ }
+
+ if (node.name === 'img' && !attributeMap.has('alt')) {
+ validator.warn(`A11y:
element should have an alt attribute`, node.start);
+ }
+
+ if (node.name === 'figcaption') {
+ const parent = elementStack[elementStack.length - 1];
+ if (parent) {
+ if (parent.name !== 'figure') {
+ validator.warn(`A11y: must be an immediate child of `, node.start);
+ } else {
+ const index = parent.children.indexOf(node);
+ if (index !== 0 && index !== parent.children.length - 1) {
+ validator.warn(`A11y: must be first or last child of `, node.start);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/validate/html/index.ts b/src/validate/html/index.ts
index 186181e913..d36b00b833 100644
--- a/src/validate/html/index.ts
+++ b/src/validate/html/index.ts
@@ -1,5 +1,6 @@
import validateElement from './validateElement';
import validateWindow from './validateWindow';
+import a11y from './a11y';
import fuzzymatch from '../utils/fuzzymatch'
import flattenReference from '../../utils/flattenReference';
import { Validator } from '../index';
@@ -13,6 +14,8 @@ export default function validateHtml(validator: Validator, html: Node) {
const elementStack: Node[] = [];
function visit(node: Node) {
+ a11y(validator, node, elementStack);
+
if (node.type === 'Element') {
if (meta.has(node.name)) {
return meta.get(node.name)(validator, node, refs, refCallees);
diff --git a/src/validate/html/validateElement.ts b/src/validate/html/validateElement.ts
index aa396bac0a..c3243c6e64 100644
--- a/src/validate/html/validateElement.ts
+++ b/src/validate/html/validateElement.ts
@@ -60,8 +60,6 @@ export default function validateElement(
let hasOutro: boolean;
let hasTransition: boolean;
- const attributeMap: Map = new Map();
-
node.attributes.forEach((attribute: Node) => {
if (attribute.type === 'Ref') {
if (!refs.has(attribute.name)) refs.set(attribute.name, []);
@@ -179,8 +177,6 @@ export default function validateElement(
);
}
} else if (attribute.type === 'Attribute') {
- attributeMap.set(attribute.name, attribute);
-
if (attribute.name === 'value' && node.name === 'textarea') {
if (node.children.length) {
validator.error(
@@ -198,29 +194,6 @@ export default function validateElement(
}
}
});
-
- // a11y
- if (node.name === 'a' && !attributeMap.has('href')) {
- validator.warn(`A11y: element should have an href attribute`, node.start);
- }
-
- if (node.name === 'img' && !attributeMap.has('alt')) {
- validator.warn(`A11y:
element should have an alt attribute`, node.start);
- }
-
- if (node.name === 'figcaption') {
- const parent = elementStack[elementStack.length - 1];
- if (parent) {
- if (parent.name !== 'figure') {
- validator.warn(`A11y: must be an immediate child of `, node.start);
- } else {
- const index = parent.children.indexOf(node);
- if (index !== 0 && index !== parent.children.length - 1) {
- validator.warn(`A11y: must be first or last child of `, node.start);
- }
- }
- }
- }
}
function checkTypeAttribute(validator: Validator, node: Node) {
diff --git a/test/validator/samples/a11y-anchor-has-content/input.html b/test/validator/samples/a11y-anchor-has-content/input.html
new file mode 100644
index 0000000000..ca81f90ae8
--- /dev/null
+++ b/test/validator/samples/a11y-anchor-has-content/input.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/validator/samples/a11y-anchor-has-content/warnings.json b/test/validator/samples/a11y-anchor-has-content/warnings.json
new file mode 100644
index 0000000000..157bec1f9b
--- /dev/null
+++ b/test/validator/samples/a11y-anchor-has-content/warnings.json
@@ -0,0 +1,8 @@
+[{
+ "message": "A11y: element should have child content",
+ "loc": {
+ "line": 1,
+ "column": 0
+ },
+ "pos": 0
+}]
\ No newline at end of file