1import { ConfigData, formatterFactory, HtmlValidate, Report, Reporter } from "html-validate";
2import "lume/types.ts";
3import { merge } from "lume/core/utils/object.ts";
4import { log } from "lume/core/utils/log.ts";
5
6export const defaults: ConfigData = {
7 extends: ["html-validate:recommended", "html-validate:document"],
8 rules: {
9 "doctype-style": "off",
10 "attr-quotes": "off",
11 "no-trailing-whitespace": "off",
12 "void-style": "warn",
13 "require-sri": ["error", { target: "crossorigin" }],
14 },
15};
16
17export default function (userOptions?: ConfigData) {
18 const options = merge(defaults, userOptions);
19 const htmlvalidate = new HtmlValidate(options);
20 const format = formatterFactory("text");
21
22 return (site: Lume.Site) => {
23 site.process([".html"], validatePages);
24
25 async function validatePages(pages: Lume.Page[]) {
26 var reports: Array<Promise<Report>> = [];
27 for (const page of pages) {
28 const report = await htmlvalidate.validateString(page.content as string, page.outputPath);
29 reports.push(report);
30 }
31 const merged: Report | Promise<Report> = Reporter.merge(reports);
32
33 if (merged.valid) {
34 log.info("[validateHTML] Validation successful!");
35 }
36
37 if (!merged.valid) {
38 log.error("[validateHTML]:\n" + format(merged.results));
39 }
40 }
41 };
42}