Commit 7734dc68 authored by David Sveningsson's avatar David Sveningsson
Browse files

feat(rules): new rule `attr-spacing` requiring attributes to be separated by whitespace

fixes #105
parent f9d44d66
Pipeline #255857505 passed with stages
in 11 minutes and 2 seconds
......@@ -3,6 +3,7 @@
</p>
<div class="inline-validation">
{# <!-- [html-validate-disable-next attr-spacing: endfor is not part of the next attribute ] --> #}
<div class="markup"
{%- for attrName, attrValue in doc.validate.attributes %}{{ attrName }}="{{ attrValue }}"{% endfor %}>
<pre><code class="hljs lang-html">{{ doc.validate.markup | highlight('html') }}</code></pre>
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`docs/rules/attr-spacing.md inline validation: correct 1`] = `Array []`;
exports[`docs/rules/attr-spacing.md inline validation: incorrect 1`] = `
Array [
Object {
"errorCount": 1,
"filePath": "inline",
"messages": Array [
Object {
"column": 21,
"context": undefined,
"line": 1,
"message": "No space between attributes",
"offset": 20,
"ruleId": "attr-spacing",
"selector": null,
"severity": 2,
"size": 5,
},
],
"source": "<input type=\\"submit\\"class=\\"foo\\">",
"warningCount": 0,
},
]
`;
import HtmlValidate from "../../../src/htmlvalidate";
const markup: { [key: string]: string } = {};
markup["incorrect"] = `<input type="submit"class="foo">`;
markup["correct"] = `<input type="submit" class="foo">`;
describe("docs/rules/attr-spacing.md", () => {
it("inline validation: incorrect", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"rules":{"attr-spacing":"error"}});
const report = htmlvalidate.validateString(markup["incorrect"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: correct", () => {
expect.assertions(1);
const htmlvalidate = new HtmlValidate({"rules":{"attr-spacing":"error"}});
const report = htmlvalidate.validateString(markup["correct"]);
expect(report.results).toMatchSnapshot();
});
});
---
docType: rule
name: attr-spacing
summary: Require attributes to be separated by whitespace
---
# Require attributes to be separated by whitespace (`attr-spacing`)
In HTML attributes must be separated by whitespace (commonly a regular space).
## Rule details
Examples of **incorrect** code for this rule:
<validate name="incorrect" rules="attr-spacing">
<input type="submit"class="foo">
</validate>
Examples of **correct** code for this rule:
<validate name="correct" rules="attr-spacing">
<input type="submit" class="foo">
</validate>
......@@ -3,6 +3,7 @@ import { ConfigData } from "../config-data";
const config: ConfigData = {
rules: {
"attr-case": "error",
"attr-spacing": "error",
"attr-quotes": "error",
"attribute-allowed-values": "error",
"attribute-boolean-style": "error",
......
......@@ -2,6 +2,7 @@ import { ConfigData } from "../config-data";
const config: ConfigData = {
rules: {
"attr-spacing": "error",
"attribute-allowed-values": "error",
"close-attr": "error",
"close-order": "error",
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rule attr-spacing should contain documentation 1`] = `
Object {
"description": "No space between attributes. At least one whitespace character (commonly space) must be used to separate attributes.",
"url": "https://html-validate.org/rules/attr-spacing.html",
}
`;
import HtmlValidate from "../htmlvalidate";
import "../matchers";
describe("rule attr-spacing", () => {
let htmlvalidate: HtmlValidate;
beforeAll(() => {
htmlvalidate = new HtmlValidate({
rules: { "attr-spacing": ["error"] },
});
});
it("should not report when attributes have separating whitespace", () => {
expect.assertions(1);
const markup = '<i foo="1" bar="2"></i>';
const report = htmlvalidate.validateString(markup);
expect(report).toBeValid();
});
it("should handle boolean attributes", () => {
expect.assertions(1);
const markup = "<i foo bar></i>";
const report = htmlvalidate.validateString(markup);
expect(report).toBeValid();
});
it("should handle newline attributes", () => {
expect.assertions(1);
const markup = "<i foo\nbar></i>";
const report = htmlvalidate.validateString(markup);
expect(report).toBeValid();
});
it("should report error when attributes does not have separating whitespace", () => {
expect.assertions(2);
const markup = '<i foo="1"bar="2"></i>';
const report = htmlvalidate.validateString(markup);
expect(report).toBeInvalid();
expect(report).toHaveError("attr-spacing", "No space between attributes");
});
it("should contain documentation", () => {
expect.assertions(1);
expect(htmlvalidate.getRuleDocumentation("attr-spacing")).toMatchSnapshot();
});
});
import { TokenEvent } from "../event";
import { TokenType } from "../lexer";
import { Rule, RuleDocumentation, ruleDocumentationUrl } from "../rule";
export default class AttrSpacing extends Rule {
public documentation(): RuleDocumentation {
return {
description: `No space between attributes. At least one whitespace character (commonly space) must be used to separate attributes.`,
url: ruleDocumentationUrl(__filename),
};
}
public setup(): void {
let previousToken: TokenType;
this.on("token", (event: TokenEvent) => {
if (event.type === TokenType.ATTR_NAME && previousToken !== TokenType.WHITESPACE) {
this.report(null, "No space between attributes", event.location);
}
previousToken = event.type;
});
}
}
import { RuleConstructor } from "../rule";
import AllowedLinks from "./allowed-links";
import AttrCase from "./attr-case";
import AttrSpacing from "./attr-spacing";
import AttrQuotes from "./attr-quotes";
import AttributeAllowedValues from "./attribute-allowed-values";
import AttributeBooleanStyle from "./attribute-boolean-style";
......@@ -61,6 +62,7 @@ import WCAG from "./wcag";
const bundledRules: Record<string, RuleConstructor<any, any>> = {
"allowed-links": AllowedLinks,
"attr-case": AttrCase,
"attr-spacing": AttrSpacing,
"attr-quotes": AttrQuotes,
"attribute-allowed-values": AttributeAllowedValues,
"attribute-boolean-style": AttributeBooleanStyle,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment