Commit 46061a7b authored by David Sveningsson's avatar David Sveningsson

feat(rules): new rule doctype-html

[skip release]
parent 803ddaee
Pipeline #76897901 passed with stages
in 10 minutes and 28 seconds
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`docs/rules/doctype-html.md inline validation: correct 1`] = `Array []`;
exports[`docs/rules/doctype-html.md inline validation: incorrect 1`] = `
Array [
Object {
"errorCount": 1,
"filePath": "inline",
"messages": Array [
Object {
"column": 11,
"context": undefined,
"line": 1,
"message": "doctype should be \\"html\\"",
"offset": 10,
"ruleId": "doctype-html",
"severity": 2,
"size": 79,
},
],
"source": "<!DOCTYPE HTML PUBLIC \\"-//W3C//DTD HTML 4.01//EN\\" \\"http://www.w3.org/TR/html4/strict.dtd\\">",
"warningCount": 0,
},
]
`;
exports[`docs/rules/doctype-html.md inline validation: legacy 1`] = `
Array [
Object {
"errorCount": 1,
"filePath": "inline",
"messages": Array [
Object {
"column": 11,
"context": undefined,
"line": 1,
"message": "doctype should be \\"html\\"",
"offset": 10,
"ruleId": "doctype-html",
"severity": 2,
"size": 33,
},
],
"source": "<!DOCTYPE html SYSTEM \\"about:legacy-compat\\">",
"warningCount": 0,
},
]
`;
import HtmlValidate from "../../../src/htmlvalidate";
const markup: { [key: string]: string } = {};
markup["incorrect"] = `<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">`;
markup["legacy"] = `<!DOCTYPE html SYSTEM "about:legacy-compat">`;
markup["correct"] = `<!DOCTYPE html>`;
describe("docs/rules/doctype-html.md", () => {
it("inline validation: incorrect", () => {
const htmlvalidate = new HtmlValidate({"rules":{"doctype-html":"error"}});
const report = htmlvalidate.validateString(markup["incorrect"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: legacy", () => {
const htmlvalidate = new HtmlValidate({"rules":{"doctype-html":"error"}});
const report = htmlvalidate.validateString(markup["legacy"]);
expect(report.results).toMatchSnapshot();
});
it("inline validation: correct", () => {
const htmlvalidate = new HtmlValidate({"rules":{"doctype-html":"error"}});
const report = htmlvalidate.validateString(markup["correct"]);
expect(report.results).toMatchSnapshot();
});
});
@ngdoc rule
@module rules
@name doctype-html
@summary Require usage of "html" doctype
@description
# Require usage of "html" doctype (`doctype-html`)
HTML5 requires the usage of the `<!DOCTYPE html>` doctype to prevent browsers
from guessing and/or using "quirks mode".
HTML5 also supports legacy strings for document generators but this rule
disallows legacy strings as well.
This rule only validates the doctype itself not the presence of the
declaration. Use [missing-doctype](missing-doctype.html) to validate presence.
## Rule details
Examples of **incorrect** code for this rule:
<validate name="incorrect" rules="doctype-html">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
</validate>
<validate name="legacy" rules="doctype-html">
<!DOCTYPE html SYSTEM "about:legacy-compat">
</validate>
Examples of **correct** code for this rule:
<validate name="correct" rules="doctype-html">
<!DOCTYPE html>
</validate>
......@@ -14,6 +14,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "off",
......@@ -102,6 +103,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "off",
......@@ -221,6 +223,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "off",
......@@ -306,6 +309,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "off",
......@@ -395,6 +399,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "error",
......@@ -483,6 +488,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "error",
......@@ -555,6 +561,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "error",
......@@ -627,6 +634,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "error",
......@@ -676,6 +684,7 @@ Object {
"close-attr": "error",
"close-order": "error",
"deprecated": "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "error",
......
......@@ -7,6 +7,7 @@ module.exports = {
"close-attr": "error",
"close-order": "error",
deprecated: "error",
"doctype-html": "error",
"element-case": "error",
"element-name": "error",
"element-permitted-content": "error",
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rule doctype-html should contain documentation 1`] = `
Object {
"description": "HTML5 documents should use the \\"html\\" doctype (short form, not legacy string)",
"url": "https://html-validate.org/rules/doctype-html.html",
}
`;
import HtmlValidate from "../htmlvalidate";
import "../matchers";
describe("rule doctype-html", () => {
let htmlvalidate: HtmlValidate;
beforeAll(() => {
htmlvalidate = new HtmlValidate({
rules: { "doctype-html": "error" },
});
});
it("should not report when correct doctype is used", () => {
const report = htmlvalidate.validateString("<!DOCTYPE html>");
expect(report).toBeValid();
});
it("should not report when doctype is uppercase", () => {
const report = htmlvalidate.validateString("<!DOCTYPE HTML>");
expect(report).toBeValid();
});
it("should report error when older doctype is used", () => {
const html =
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">';
const report = htmlvalidate.validateString(html);
expect(report).toBeInvalid();
expect(report).toHaveError("doctype-html", 'doctype should be "html"');
});
it("should report error when doctype has legacy string", () => {
const html = '<!DOCTYPE html SYSTEM "about:legacy-compat">';
const report = htmlvalidate.validateString(html);
expect(report).toBeInvalid();
expect(report).toHaveError("doctype-html", 'doctype should be "html"');
});
it("should contain documentation", () => {
expect(htmlvalidate.getRuleDocumentation("doctype-html")).toMatchSnapshot();
});
});
import { DoctypeEvent } from "../event";
import { Rule, RuleDocumentation, ruleDocumentationUrl } from "../rule";
class NoStyleTag extends Rule {
public documentation(): RuleDocumentation {
return {
description:
'HTML5 documents should use the "html" doctype (short form, not legacy string)',
url: ruleDocumentationUrl(__filename),
};
}
public setup(): void {
this.on("doctype", (event: DoctypeEvent) => {
const doctype = event.value.toLowerCase();
if (doctype !== "html") {
this.report(null, 'doctype should be "html"', event.valueLocation);
}
});
}
}
module.exports = NoStyleTag;
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