75 lines
2.6 KiB
TypeScript
75 lines
2.6 KiB
TypeScript
import type { DevToolbarRule } from "./types.ts";
|
|
import { createIssue } from "./helpers.ts";
|
|
|
|
export const htmlRules: DevToolbarRule[] = [
|
|
{
|
|
id: "html/structure",
|
|
category: "html",
|
|
defaultSeverity: "warning",
|
|
description: "Checks document structure and DOM complexity.",
|
|
run: ({ document, root }) => {
|
|
const issues = [];
|
|
const nodeCount = root.querySelectorAll("*").length;
|
|
if (nodeCount > 3000)
|
|
issues.push(
|
|
createIssue({
|
|
ruleId: "html/dom-size",
|
|
category: "html",
|
|
severity: "error",
|
|
title: "DOM is extremely large",
|
|
message: `The page contains ${nodeCount} elements.`,
|
|
recommendation:
|
|
"Reduce wrappers, paginate long lists, and render hidden content on demand.",
|
|
}),
|
|
);
|
|
else if (nodeCount > 1500)
|
|
issues.push(
|
|
createIssue({
|
|
ruleId: "html/dom-size",
|
|
category: "html",
|
|
severity: "warning",
|
|
title: "DOM is large",
|
|
message: `The page contains ${nodeCount} elements.`,
|
|
recommendation: "Review repeated wrappers and off-screen content.",
|
|
}),
|
|
);
|
|
if (!document.querySelector("main"))
|
|
issues.push(
|
|
createIssue({
|
|
ruleId: "html/main-missing",
|
|
category: "html",
|
|
severity: "warning",
|
|
title: "Main landmark is missing",
|
|
message: "The document has no main element.",
|
|
recommendation: "Wrap the primary page content in a main element.",
|
|
}),
|
|
);
|
|
if (document.querySelectorAll("main").length > 1)
|
|
issues.push(
|
|
createIssue({
|
|
ruleId: "html/multiple-main",
|
|
category: "html",
|
|
severity: "error",
|
|
title: "Multiple main landmarks",
|
|
message: "The document contains more than one main element.",
|
|
recommendation: "Use one visible main landmark per document.",
|
|
}),
|
|
);
|
|
for (const element of root.querySelectorAll("button button, button a, a a, a button"))
|
|
issues.push(
|
|
createIssue({
|
|
ruleId: "html/nested-interactive",
|
|
category: "html",
|
|
severity: "error",
|
|
title: "Interactive elements are nested",
|
|
message: "Nested buttons and links create invalid and confusing interaction behavior.",
|
|
element,
|
|
recommendation:
|
|
"Use one interactive element and style its inner non-interactive content.",
|
|
}),
|
|
);
|
|
return issues;
|
|
},
|
|
},
|
|
];
|