ember-template-lint
Version:
Linter for Ember or Handlebars templates.
97 lines (92 loc) • 3.09 kB
JavaScript
const AstNodeInfo = require('../helpers/ast-node-info');
const Rule = require('./base');
const errorMessage = '<iframe> elements must have a unique title property.';
// iframes have to have titles for "Name, Role, Value" - https://www.w3.org/TR/UNDERSTANDING-WCAG20/ensure-compat-rsv.html
module.exports = class RequireIframeTitle extends Rule {
logNode({ message, node }) {
this.log({
message,
line: node.loc && node.loc.start.line,
column: node.loc && node.loc.start.column,
source: this.sourceForNode(node),
});
}
visitor() {
this.knownTitles = [];
return {
ElementNode(node) {
if (node.tag === 'iframe') {
const ariaHidden = AstNodeInfo.hasAttribute(node, 'aria-hidden');
if (ariaHidden) {
return;
}
const hidden = AstNodeInfo.hasAttribute(node, 'hidden');
if (hidden) {
return;
}
const title = AstNodeInfo.findAttribute(node, 'title');
if (!title) {
this.logNode({
message: errorMessage,
node,
});
} else if (!title.value) {
// ...
} else if (title.value.type === 'TextNode') {
let value = title.value.chars.trim();
let matchIndex = -1;
let [, existingNode] = this.knownTitles.find(([val], index) => {
if (val === value) {
if (matchIndex === -1) {
matchIndex = index + 1;
}
return true;
} else {
return false;
}
}) || [null, null];
if (value.length === 0) {
this.logNode({
message: errorMessage,
node,
});
} else if (existingNode) {
this.logNode({
message: 'This title is not unique.' + ` #${matchIndex}`,
node: existingNode,
});
this.logNode({
message:
`${errorMessage} ` +
`Value title="${title.value.chars}" already used for different iframe.` +
` #${matchIndex}`,
node,
});
} else {
this.knownTitles.push([value, title]);
}
} else if (title.value.type === 'MustacheStatement') {
if (title.value.path.type === 'BooleanLiteral') {
this.logNode({
message: errorMessage,
node,
});
}
} else if (title.value.type === 'ConcatStatement') {
if (title.value.parts.length === 1) {
if (title.value.parts[0].type === 'MustacheStatement') {
if (title.value.parts[0].path.type === 'BooleanLiteral') {
this.logNode({
message: errorMessage,
node,
});
}
}
}
}
}
},
};
}
};
;