diff --git a/.htmlvalidate.json b/.htmlvalidate.json
new file mode 100644
index 00000000..55642f75
--- /dev/null
+++ b/.htmlvalidate.json
@@ -0,0 +1,8 @@
+{
+ "extends": ["html-validate:standard"],
+ "rules": {
+ "element-required-content": "off",
+ "element-permitted-content": "off",
+ "no-raw-characters": "off"
+ }
+}
diff --git a/.tarignore b/.tarignore
index 7d3fe235..8a582b01 100644
--- a/.tarignore
+++ b/.tarignore
@@ -9,7 +9,8 @@
.jsbeautify*
.prettier*
.eslintrc*
-.chglog
+.htmlvalidate*
+.lycheeignore*
example*
webpack*
svgsprite*
diff --git a/.vnuignore b/.vnuignore
deleted file mode 100644
index e69de29b..00000000
diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml
index 0378ccda..f6c69866 100644
--- a/.woodpecker/test.yml
+++ b/.woodpecker/test.yml
@@ -10,7 +10,7 @@ steps:
image: docker.io/library/node:lts
commands:
- npm install --quiet --no-progress
- - npm run lint
+ - npm run lint:js
environment:
FORCE_COLOR: "true"
@@ -29,10 +29,13 @@ steps:
- hugo --panicOnWarning -s exampleSite/ -b http://localhost:8000/
- name: html-validation
- image: quay.io/thegeeklab/vnu
+ image: docker.io/library/node:lts
group: test
commands:
- - vnu --skip-non-html --also-check-css --errors-only --filterfile .vnuignore exampleSite/public
+ - npm install --quiet --no-progress
+ - npm run lint:html
+ environment:
+ FORCE_COLOR: "true"
- name: link-validation
image: docker.io/lycheeverse/lychee
diff --git a/package-lock.json b/package-lock.json
index 837f892f..0a91ef12 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
"eslint-plugin-prettier": "5.1.3",
"favicons": "7.1.5",
"favicons-webpack-plugin": "6.0.1",
+ "html-validate": "^8.9.1",
"npm-run-all": "4.1.5",
"postcss-loader": "7.3.4",
"prettier": "3.2.2",
@@ -542,6 +543,18 @@
"integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
"dev": true
},
+ "node_modules/@html-validate/stylish": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@html-validate/stylish/-/stylish-4.2.0.tgz",
+ "integrity": "sha512-Nl8HCv0hGRSLQ+n1OD4Hk3a+Urwk9HH0vQkAzzCarT4KlA7bRl+6xEiS5PZVwOmjtC7XiH/oNe3as9Fxcr2A1w==",
+ "dev": true,
+ "dependencies": {
+ "kleur": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -1532,6 +1545,92 @@
"node": ">= 10"
}
},
+ "node_modules/@sidvind/better-ajv-errors": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@sidvind/better-ajv-errors/-/better-ajv-errors-2.1.3.tgz",
+ "integrity": "sha512-lWuod/rh7Xz5uXiEGSfm2Sd5PG7K/6yJfoAZVqzsEswjPJhUz15R7Gn/o8RczA041QS15hBd/BCSeu9vwPArkA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.16.0",
+ "chalk": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 16.14"
+ },
+ "peerDependencies": {
+ "ajv": "4.11.8 - 8"
+ }
+ },
+ "node_modules/@sidvind/better-ajv-errors/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "/~https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@sidvind/better-ajv-errors/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "/~https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@sidvind/better-ajv-errors/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@sidvind/better-ajv-errors/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@sidvind/better-ajv-errors/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@sidvind/better-ajv-errors/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@sindresorhus/merge-streams": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz",
@@ -4172,6 +4271,15 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/define-data-property": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
@@ -5940,6 +6048,161 @@
"node": ">=12"
}
},
+ "node_modules/html-validate": {
+ "version": "8.9.1",
+ "resolved": "https://registry.npmjs.org/html-validate/-/html-validate-8.9.1.tgz",
+ "integrity": "sha512-2tWa2FtFALooZ5wMDbY+HS0BieoiRfS5IeiG2XeM6bb3Jx4dmN1HFPFt0v3j7r3SpNxEVKiXYLdkBZI3kkca/g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.0",
+ "@html-validate/stylish": "^4.1.0",
+ "@sidvind/better-ajv-errors": "2.1.3",
+ "ajv": "^8.0.0",
+ "deepmerge": "4.3.1",
+ "glob": "^10.0.0",
+ "ignore": "5.3.0",
+ "kleur": "^4.1.0",
+ "minimist": "^1.2.0",
+ "prompts": "^2.0.0",
+ "semver": "^7.0.0"
+ },
+ "bin": {
+ "html-validate": "bin/html-validate.js"
+ },
+ "engines": {
+ "node": ">= 16.14"
+ },
+ "peerDependencies": {
+ "jest": "^27.1 || ^28.1.3 || ^29.0.3",
+ "jest-diff": "^27.1 || ^28.1.3 || ^29.0.3",
+ "jest-snapshot": "^27.1 || ^28.1.3 || ^29.0.3",
+ "vitest": "^0.34 || ^1"
+ },
+ "peerDependenciesMeta": {
+ "jest": {
+ "optional": true
+ },
+ "jest-diff": {
+ "optional": true
+ },
+ "jest-snapshot": {
+ "optional": true
+ },
+ "vitest": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/html-validate/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "/~https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/html-validate/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/html-validate/node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "/~https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/html-validate/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/html-validate/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/html-validate/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "/~https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/html-validate/node_modules/minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/html-validate/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/html-validate/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
"node_modules/html-webpack-plugin": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz",
@@ -9017,6 +9280,28 @@
"node": ">=10"
}
},
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/prompts/node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/pump": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
@@ -9824,6 +10109,12 @@
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"dev": true
},
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true
+ },
"node_modules/slash": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
diff --git a/package.json b/package.json
index 9d720329..87ef82f7 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,9 @@
"prep:clean-all": "shx rm -rf VERSION .lighthouseci/ lhci_reports/ build/ dist/ static/ data/ assets/sprites/ exampleSite/data/sprites/ exampleSite/public/ exampleSite/resources/ exampleSite/.hugo_build.lock",
"prep:make": "shx mkdir -p build/icons/ build/fonts/ dist/",
"svg-sprite-list": "run-s prep:make svg ; shx mkdir -p exampleSite/data/sprites/ ; shx cp build/fonts/GeekblogIcons.json exampleSite/data/sprites/geekblog.json",
- "lint": "eslint src/js/ --color"
+ "lint": "run-p lint:js lint:html",
+ "lint:js": "eslint src/js/ --color",
+ "lint:html": "html-validate exampleSite/public"
},
"repository": {
"type": "git",
@@ -47,6 +49,7 @@
"eslint-plugin-prettier": "5.1.3",
"favicons": "7.1.5",
"favicons-webpack-plugin": "6.0.1",
+ "html-validate": "8.9.1",
"npm-run-all": "4.1.5",
"postcss-loader": "7.3.4",
"prettier": "3.2.2",