def find_valid(node, file, target_alt): name = getattr(node.value, "name", None) is_img = (isinstance(node.value, ast.Element) and name and name.lower() == "img") if is_img: attributes = [] if getattr(node.value, "opening_tag", None): attributes = {} for n in node.value.opening_tag.attributes.nodes: if not isinstance(n, JinjaElement): attributes[str(n.name)] = str(n.value).strip("\"'") if len(attributes) == 0 or "alt" not in attributes: return [ Issue.from_node( file, node, "The `<img>` tag must have a `alt` attribute, either with meaningful text, or an empty string for decorative images", "image_alt", ) ] if not node.children: return [] return sum( (find_valid(child, file, target_alt) for child in node.children), [])
def find_valid(node, file, target_alt): name = getattr(node.value, "name", None) is_input = (isinstance(node.value, ast.Element) and name and name.lower() == "input") if is_input: attributes = [] if getattr(node.value, "opening_tag", None): attributes = {} for n in node.value.opening_tag.attributes.nodes: attributes[str(n.name)] = str(n.value).strip("\"'") if "autofocus" in attributes: return [ Issue.from_node( file, node, "Do not use the `autofocus` attribute, which causes issues for screen reader users", "no_autofocus", ) ] if not node.children: return [] return sum( (find_valid(child, file, target_alt) for child in node.children), [])
def find_role_errors(node, file, target_roles): attributes = [] if getattr(node.value, "opening_tag", None): attributes = {} for n in node.value.opening_tag.attributes.nodes: attributes[str(n.name)] = str(n.value).strip("\"'") target = VALID_ROLES if target_roles is True else target_roles if "role" in attributes: return ( [] if attributes["role"] in target else [ Issue.from_node( file, node, "The `role` attribute needs to have a valid value", "aria_role", ) ] ) if not node.children: return [] return sum( ( find_role_errors(child, file, target_roles) for child in node.children ), [], )
def check_tab_only_indent(file): issues = [] for i, line in enumerate(file.lines): indent = WHITESPACE_INDENT_RE.match(line).group(0) if not contains_exclusively(indent, "\t"): loc = IssueLocation(file_path=file.path, line=i, column=0) issue = Issue(loc, "Should be indented with tabs", INDENT) issues.append(issue) return issues
def find_valid(node, file): name = getattr(node.value, "name", None) is_meta = ( isinstance(node.value, ast.Element) and name and name.lower() == "meta" ) if is_meta: attributes = [] if getattr(node.value, "opening_tag", None): attributes = {} for n in node.value.opening_tag.attributes.nodes: attributes[str(n.name)] = str(n.value).strip("\"'") if "name" in attributes and attributes["name"] == "viewport": if "user-scalable=no" in attributes["content"]: return [ Issue.from_node( file, node, "Remove `user-scalable=no` from the viewport meta so users can zoom", "meta_viewport", ) ] if ( "maximum-scale=1" in attributes["content"] or "maximum-scale=0" in attributes["content"] ): return [ Issue.from_node( file, node, "`maximum-scale` should not be less than 2", "meta_viewport", ) ] if not node.children: return [] return sum((find_valid(child, file) for child in node.children), [])
def find_valid(node, file, target_lang): name = getattr(node.value, "name", None) is_html = (isinstance(node.value, ast.Element) and name and name.lower() == "html") if is_html: attributes = [] if getattr(node.value, "opening_tag", None): attributes = {} for n in node.value.opening_tag.attributes.nodes: attributes[str(getattr(n, "name", ""))] = str(getattr(n, "value", "")).strip("\"'") if len(attributes) == 0 or "lang" not in attributes: return [ Issue.from_node( file, node, "The `<html>` tag should have a `lang` attribute with a valid value, describing the main language of the page", "html_has_lang", ) ] if target_lang[0] is True or attributes["lang"] in target_lang: return [] else: return [ Issue.from_node( file, node, f"The `<html>` tag should have a `lang` attribute with a valid value, describing the main language of the page. Allowed values: {', '.join(target_lang)}", "html_has_lang", ) ] if not node.children: return [] return sum( (find_valid(child, file, target_lang) for child in node.children), [])
def find_valid(node, file, disallowed_variants): if isinstance(node.value, ast.JinjaVariable): matches = [v for v in disallowed_variants if v in node.value.content] if matches: return [ Issue.from_node( file, node, f"Avoid using `{matches[0]}` to render Django forms", DJANGO_FORMS_RENDERING, ) ] if not node.children: return [] return sum( ( find_valid(child, file, disallowed_variants) for child in node.children ), [], )
def find_valid(node, file): is_elt = isinstance(node.value, ast.Element) if is_elt: attributes = [] if getattr(node.value, "opening_tag", None): attributes = {} for n in node.value.opening_tag.attributes.nodes: attributes[str(n.name)] = str(n.value).strip("\"'") if "tabindex" in attributes and int(attributes["tabindex"]) > 0: return [ Issue.from_node( file, node, "Avoid positive `tabindex` values, change the order of elements on the page instead", "tabindex_no_positive", ) ] if not node.children: return [] return sum((find_valid(child, file) for child in node.children), [])
def add_issue(location, msg): issues.append( Issue.from_ast(file, location.line, location.column, msg, INDENT))