import { ConfigData, formatterFactory, HtmlValidate, Report, Reporter } from "html-validate";
import "lume/types.ts";
import { merge } from "lume/core/utils/object.ts";
import { log } from "lume/core/utils/log.ts";
// HTML Validation Plugin, by dish
// version 1.0.1
export const defaults: ConfigData = {
extends: ["html-validate:recommended", "html-validate:document"],
rules: {
"doctype-style": "off",
"attr-quotes": "off",
"no-trailing-whitespace": "off",
"void-style": "warn",
"require-sri": ["off", { target: "crossorigin" }],
},
};
export default function (userOptions?: ConfigData) {
const options = merge(defaults, userOptions);
const htmlvalidate = new HtmlValidate(options);
return (site: Lume.Site) => {
site.process([".html"], validatePages);
const barReport = site.debugBar?.collection("HTML Validator");
if (barReport) {
barReport.icon = "shield-check";
barReport.contexts = {
"error": {
background: "error",
},
"warning": {
background: "warning",
},
"success": {
background: "success",
},
};
}
async function validatePages(pages: Lume.Page[]) {
for (const page of pages) {
const report = await htmlvalidate.validateString(page.content as string, page.outputPath);
if (report.valid == true) {
barReport?.items.push({
title: page.data.url,
context: "success",
text: "No errors or warnings on page",
});
} else {
barReport?.items.push({
title: page.data.url,
details: `${report.errorCount} errors, ${report.warningCount} warnings`,
items: Array.from(report.results[0].messages).map((msg) => ({
title: msg.message,
context: severity(msg.severity),
code: msg.ruleId,
actions: [
{
text: "Rule",
icon: "question",
href: msg.ruleUrl,
target: "_blank",
},
],
})),
});
}
}
}
};
}
function severity(level: number) {
if (level == 1) {
return "warning";
}
return "error";
}