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
6// HTML Validation Plugin, by dish
7// version 1.0.1
8
9export const defaults: ConfigData = {
10 extends: ["html-validate:recommended", "html-validate:document"],
11 rules: {
12 "doctype-style": "off",
13 "attr-quotes": "off",
14 "no-trailing-whitespace": "off",
15 "void-style": "warn",
16 "require-sri": ["error", { target: "crossorigin" }],
17 },
18};
19
20export default function (userOptions?: ConfigData) {
21 const options = merge(defaults, userOptions);
22 const htmlvalidate = new HtmlValidate(options);
23 const format = formatterFactory("text");
24
25 return (site: Lume.Site) => {
26 site.process([".html"], validatePages);
27
28 async function validatePages(pages: Lume.Page[]) {
29 let reports: Array<Report> = [];
30 for (const page of pages) {
31 const report = await htmlvalidate.validateString(page.content as string, page.outputPath);
32 reports.push(report);
33 }
34 const merged: Report | Promise<Report> = Reporter.merge(reports);
35 // Clear the reports table to ensure we don't get duplicates
36 reports = [];
37
38 if (merged.valid) {
39 log.info("[validateHTML] Validation successful!");
40 }
41
42 if (!merged.valid) {
43 log.error("[validateHTML]:\n" + format(merged.results));
44 }
45 }
46 };
47}