release: WRNexusJS 0.2.75

This commit is contained in:
2026-07-21 12:30:46 +05:30
parent 2ca2d02b22
commit 69b6cd431f
100 changed files with 2313 additions and 116 deletions
+113
View File
@@ -0,0 +1,113 @@
import type { DevToolbarRule } from "./types.ts";
import { createIssue } from "./helpers.ts";
export const seoRules: DevToolbarRule[] = [
{
id: "seo/document",
category: "seo",
defaultSeverity: "warning",
description: "Validates core document metadata.",
run: ({ document }) => {
const issues = [];
const title = document.title.trim();
if (!title)
issues.push(
createIssue({
ruleId: "seo/title-missing",
category: "seo",
severity: "error",
title: "Page title is missing",
message: "The document does not have a useful title.",
recommendation: "Add a unique title describing this page.",
}),
);
else if (title.length < 20 || title.length > 65)
issues.push(
createIssue({
ruleId: "seo/title-length",
category: "seo",
severity: "warning",
title: "Page title length may be suboptimal",
message: `The title contains ${title.length} characters.`,
recommendation: "Keep most titles between about 20 and 65 characters.",
confidence: "medium",
}),
);
const description = document
.querySelector<HTMLMetaElement>('meta[name="description"]')
?.content.trim();
if (!description)
issues.push(
createIssue({
ruleId: "seo/description-missing",
category: "seo",
severity: "warning",
title: "Meta description is missing",
message: "Search and social previews may not have a useful description.",
recommendation: "Add a unique meta description for the page.",
}),
);
else if (description.length < 70 || description.length > 170)
issues.push(
createIssue({
ruleId: "seo/description-length",
category: "seo",
severity: "suggestion",
title: "Meta description length may be suboptimal",
message: `The description contains ${description.length} characters.`,
recommendation: "Aim for a concise description of roughly 70170 characters.",
confidence: "medium",
}),
);
if (!document.querySelector('meta[name="viewport"]'))
issues.push(
createIssue({
ruleId: "seo/viewport-missing",
category: "seo",
severity: "error",
title: "Viewport meta tag is missing",
message: "The page may render incorrectly on mobile devices.",
recommendation: "Add width=device-width, initial-scale=1.",
}),
);
if (!document.querySelector('link[rel="canonical"]'))
issues.push(
createIssue({
ruleId: "seo/canonical-missing",
category: "seo",
severity: "suggestion",
title: "Canonical URL is missing",
message: "Search engines have no explicit preferred URL for this page.",
recommendation: "Add a canonical link for public indexable pages.",
confidence: "medium",
}),
);
const h1s = document.querySelectorAll("h1");
if (h1s.length === 0)
issues.push(
createIssue({
ruleId: "seo/h1-missing",
category: "seo",
severity: "warning",
title: "Page has no h1 heading",
message: "The page lacks a clear primary heading.",
recommendation: "Add one descriptive h1.",
}),
);
if (h1s.length > 1)
issues.push(
createIssue({
ruleId: "seo/multiple-h1",
category: "seo",
severity: "suggestion",
title: "Page has multiple h1 headings",
message: `Found ${h1s.length} h1 elements.`,
recommendation:
"Use one clear primary page heading unless multiple h1 elements are intentional.",
confidence: "medium",
}),
);
return issues;
},
},
];