Skip to content

Commit

Permalink
Merge cc2387a into 3fd92a9
Browse files Browse the repository at this point in the history
  • Loading branch information
KamiKillertO committed Apr 10, 2020
2 parents 3fd92a9 + cc2387a commit 1736a90
Show file tree
Hide file tree
Showing 45 changed files with 389 additions and 233 deletions.
4 changes: 4 additions & 0 deletions lib/knife/tag_utils.js
Expand Up @@ -17,3 +17,7 @@ module.exports.attributeValue = function(tag, attributeName) {

return attribute ? attribute.value : "";
};

module.exports.isTagNode = function(node) {
return ["tag", "style", "script"].indexOf(node.type) !== -1;
};
24 changes: 1 addition & 23 deletions lib/linter.js
Expand Up @@ -78,8 +78,6 @@ class Linter {
switch (rule.need) {
case "line":
return this.lintByLine(rule, raw.lines);
case "tag":
return this.lintByTag(rule, raw.dom);
case "dom":
default:
return this.lintDom(rule, raw.dom);
Expand All @@ -94,24 +92,6 @@ class Linter {
});
}

lintByTag(rule, dom) {
function executeLint(node) {
let issues = [];
// style and script tags don't have a type of "tag" 🤷
if (["tag", "style", "scripts"].indexOf(node.type) === -1) {
return [];
}
if (rule.filter && rule.filter.indexOf(node.name) === -1) {
// do nothing
} else {
issues = issues.concat(this.callRuleLint(rule, node));
}
const chilrenIssues = node.children.map(executeLint.bind(this));
return issues.concat(flatten(chilrenIssues));
}
return flatten(dom.map(executeLint.bind(this)));
}

lintDom(rule, dom) {
/*
* Reset our inline configuration object to be what opts is.
Expand All @@ -124,13 +104,11 @@ class Linter {

// fast-forwards inlineConfig.current to whatever it should be at this index.
// this.inlineConfig.getOptsAtIndex(element.index);

const shouldLint = matcher(rule);
let ret = [];
if (shouldLint) {
return this.callRuleLint(rule, node);//, this.inlineConfigs.current);
ret = ret.concat(this.callRuleLint(rule, node));//, this.inlineConfigs.current);
}

if (node.children && node.children.length > 0) {
node.children.forEach(function(child) {
ret = ret.concat(getIssues(child));
Expand Down
10 changes: 8 additions & 2 deletions lib/rules/attr-bans/index.js
@@ -1,10 +1,11 @@
/* eslint-disable-next-line */
const { isRegExp } = require("util");
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "attr-bans",
on: ["tag"],
need: "tag",
on: ["dom"],
need: "dom",

validateConfig(config) {
const typeError = (type) => `Configuration for rule "${this.name}" is invalid: Expected string, RegExp or (string|RegExp)[] got ${type}`;
Expand Down Expand Up @@ -44,12 +45,16 @@ function mutConfig(options) {
}

module.exports.lint = function(element, opts, { report }) {
if (isTagNode(element) === false) {
return;
}
let bannedAttrs = opts[this.name];

bannedAttrs = mutConfig(bannedAttrs);

const attrs = element.attribs;
function addIssue(name) {
// console.log(name)
report({
code: "E001",
position: attrs[name].nameLineCol,
Expand All @@ -69,6 +74,7 @@ module.exports.lint = function(element, opts, { report }) {
})
.forEach(addIssue);
} else if (attrs[name]) {
console.log(name);
addIssue(name);
}
});
Expand Down
9 changes: 7 additions & 2 deletions lib/rules/attr-name-style/index.js
@@ -1,11 +1,12 @@
const proc = require("../../process_option");
/* eslint-disable-next-line */
const { isRegExp } = require("util");
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "attr-name-style",
on: ["tag"],
need: "tag",
on: ["dom"],
need: "dom",
validateConfig(format) {
if (typeof format === "string" || isRegExp(format) === true) {
return format;
Expand Down Expand Up @@ -37,6 +38,10 @@ module.exports = {
};

module.exports.lint = function(node, config, { report }) {
if (isTagNode(node) === false) {
return;
}

const format = config[this.name];
let attributes = Object.values(node.attribs);
// TODO: Remove after `raw-ignore-text` refacto
Expand Down
10 changes: 8 additions & 2 deletions lib/rules/attr-new-line/index.js
@@ -1,7 +1,9 @@
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "attr-new-line",
on: ["tag"],
need: "tag",
on: ["dom"],
need: "dom",
validateConfig(option) {
if (typeof option === "number" || option === "+0") {
return option;
Expand Down Expand Up @@ -51,6 +53,10 @@ function checkPlusZeroOption(element, report) {
}

module.exports.lint = function(element, opts, { report }) {
if (isTagNode(element) === false) {
return;
}

const option = opts[this.name];

const attributes = Object.keys(element.attribs);
Expand Down
9 changes: 7 additions & 2 deletions lib/rules/attr-no-dup/index.js
@@ -1,10 +1,15 @@
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "attr-no-dup",
on: ["tag"],
need: "tag"
on: ["dom"],
need: "dom"
};

module.exports.lint = function(element, opts, { report }) {
if (isTagNode(element) === false) {
return;
}
return element.dupes.map(function(n) {
const a = element.attribs[n];

Expand Down
8 changes: 6 additions & 2 deletions lib/rules/attr-no-unsafe-char/index.js
@@ -1,14 +1,18 @@
const { isTagNode } = require("../../knife/tag_utils");
/* eslint-disable */
const regUnsafe = /[\u0000-\u0009\u000b\u000c\u000e-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
/* eslint-enable */

module.exports = {
name: "attr-no-unsafe-char",
on: ["tag"],
need: "tag"
on: ["dom"],
need: "dom"
};

module.exports.lint = function(node, opts, { report }) {
if (isTagNode(node) === false) {
return;
}
let attributes = Object.values(node.attribs);
// TODO: Remove after `raw-ignore-text` refacto
attributes = attributes.filter(attribute => /^¤+$/.test(attribute.rawName) === false);
Expand Down
8 changes: 6 additions & 2 deletions lib/rules/attr-order/index.js
@@ -1,10 +1,11 @@
/* eslint-disable-next-line */
const { isRegExp } = require("util");
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "attr-order",
on: ["tag"],
need: "tag",
on: ["dom"],
need: "dom",

validateConfig(options) {
const typeError = (type) => `Configuration for rule "${this.name}" is invalid: Expected (string|RegExp)[] got ${type}`;
Expand Down Expand Up @@ -42,6 +43,9 @@ function mutConfig(options) {
}

module.exports.lint = function(element, opts, { report }) {
if (isTagNode(element) === false) {
return;
}
let order = opts[this.name];
const attrs = element.attribs;
let lastpos = 0;
Expand Down
8 changes: 5 additions & 3 deletions lib/rules/attr-quote-style/index.js
@@ -1,3 +1,5 @@
const { isTagNode } = require("../../knife/tag_utils");

const formats = {
double: { regex: /^"/, desc: "double quoted" },
single: { regex: /^'/, desc: "single quoted" },
Expand All @@ -6,8 +8,8 @@ const formats = {

module.exports = {
name: "attr-quote-style",
on: ["tag"],
need: "tag",
on: ["dom"],
need: "dom",

validateConfig(option) {
if (typeof option !== "string") {
Expand All @@ -21,7 +23,7 @@ module.exports = {
};

module.exports.lint = function(node, opts, { report }) {
if (node.type !== "tag" || node.attribs === undefined) {
if (isTagNode(node) === false || node.attribs === undefined) {
return [];
}
let attributes = Object.values(node.attribs);
Expand Down
9 changes: 7 additions & 2 deletions lib/rules/attr-req-value/index.js
@@ -1,12 +1,17 @@
const knife = require("../../knife");
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "attr-req-value",
on: ["tag"],
need: "tag"
on: ["dom"],
need: "dom"
};

module.exports.lint = function(node, opts, { report }) {
if (isTagNode(node) === false) {
return;
}

let attributes = Object.values(node.attribs);
// TODO: Remove after `raw-ignore-text` refacto
attributes = attributes.filter(attribute => /^¤+$/.test(attribute.rawName) === false);
Expand Down
9 changes: 7 additions & 2 deletions lib/rules/attr-validate/index.js
@@ -1,10 +1,15 @@
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "attr-validate",
on: ["tag"],
need: "tag"
on: ["dom"],
need: "dom"
};

module.exports.lint = function(element, opts, { report }) {
if (isTagNode(element) === false) {
return;
}
/* eslint-disable-next-line no-useless-escape */
const attrRegex = /^\s*([^ "'>=\^]+(\s*=\s*(("[^"]*")|('[^']*')|([^ \t\n"']+)))?\s+)*$/;
const open = element.open.slice(element.name.length).replace(/\/$/, "");
Expand Down
9 changes: 6 additions & 3 deletions lib/rules/button-req-content/index.js
@@ -1,10 +1,10 @@
const { hasNonEmptyAttr } = require("../../knife");
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "button-req-content",
on: ["tag"],
need: "tag",
filter: ["button"]
on: ["dom"],
need: "dom"
};

function has_text_content(node) {
Expand All @@ -25,6 +25,9 @@ function has_text_content(node) {
}

module.exports.lint = function(element, opts, { report }) {
if (isTagNode(element) === false || element.name !== "button") {
return;
}
if (has_text_content(element) === false && hasNonEmptyAttr(element, "aria-label") === false) {
report({
code: "E061",
Expand Down
8 changes: 5 additions & 3 deletions lib/rules/class-no-dup/index.js
@@ -1,7 +1,9 @@
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "class-no-dup",
on: ["tag"],
need: "tag"
on: ["dom"],
need: "dom"
};

function getClasses(node) {
Expand All @@ -20,7 +22,7 @@ function filterClasses(classes, options) {
}

module.exports.lint = function(node, options, { report }) {
if (node.type !== "tag" || node.attribs.class === undefined) {
if (isTagNode(node) === false || node.attribs.class === undefined) {
return;
}

Expand Down
7 changes: 4 additions & 3 deletions lib/rules/class-style/index.js
@@ -1,11 +1,12 @@
const proc = require("../../process_option");
/* eslint-disable-next-line */
const { isRegExp } = require("util");
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "class-style",
on: ["tag"],
need: "tag",
on: ["dom"],
need: "dom",
validateConfig(option) {
if (typeof option !== "string" && isRegExp(option) === false) {
throw new Error(`Configuration for rule "${this.name}" is invalid: Expected string|regexp got ${typeof option}`);
Expand Down Expand Up @@ -34,7 +35,7 @@ function filterClasses(classes, options) {
}

function lint(node, options, { report }) {
if (node.type !== "tag" || node.attribs.class === undefined) {
if (isTagNode(node) === false || node.attribs.class === undefined) {
return [];
}
const format = options[this.name] || options["id-class-style"];
Expand Down
10 changes: 7 additions & 3 deletions lib/rules/fieldset-contains-legend/index.js
@@ -1,11 +1,15 @@
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "fieldset-contains-legend",
on: ["tag"],
need: "tag",
filter: ["fieldset"]
on: ["dom"],
need: "dom"
};

module.exports.lint = function(element, opts, { report }) {
if (isTagNode(element) === false || element.name !== "fieldset") {
return;
}
const has_legend = element.children.some(node => node.name === "legend");

if (has_legend === false) {
Expand Down
10 changes: 7 additions & 3 deletions lib/rules/fig-req-figcaption/index.js
@@ -1,11 +1,15 @@
const { isTagNode } = require("../../knife/tag_utils");

module.exports = {
name: "fig-req-figcaption",
on: ["tag"],
need: "tag",
filter: ["figure", "figcaption"]
on: ["dom"],
need: "dom"
};

module.exports.lint = function(node, opts, { report }) {
if (isTagNode(node) === false) {
return;
}
if (node.name === "figure") {
// get the children of this figure
const children = node.children;
Expand Down
7 changes: 6 additions & 1 deletion lib/rules/focusable-tabindex-style/README.md
@@ -1,6 +1,11 @@
# focusable-tabindex-style

If set, all focusable elements (`a`, `area`, `button`, `input`, `img`, `select`, `textarea`) must have a positive `tabindex` attribute, if any.
If set, all focusable elements must have a positive `tabindex` attribute, if any.
Focusable elements are :

- natively focusable elements (`button`, `input`, `select`, `textarea`)
- `a`, `area` elements with an href value
- any elements with a tabindex

_Reasoning: [IITAA, 10.3 and 10.4](http://www.dhs.state.il.us/IITAA/IITAAWebImplementationGuidelines.html)_

Expand Down

0 comments on commit 1736a90

Please sign in to comment.