Skip to content

Commit 4edc13c

Browse files
committed
improvements
1 parent 1c8d007 commit 4edc13c

File tree

7 files changed

+112
-27
lines changed

7 files changed

+112
-27
lines changed

.gitattributes

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1-
* text=auto eol=lf
1+
* text=auto eol=lf
2+
3+
/.editorconfig export-ignore
4+
/.gitattributes export-ignore
5+
/.gitignore export-ignore
6+
/.github export-ignore
7+
/.vscode export-ignore
8+
/test export-ignore
9+
/deno.json export-ignore

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ and this project try to adheres to [Semantic Versioning](https://semver.org/).
66
Go to the `v2` branch to see the changelog of Lume 2.
77
Go to the `v1` branch to see the changelog of Lume 1.
88

9+
## [3.1.2] - Unreleased
10+
### Fixed
11+
- Ensure console output for validate_html and seo plugins are after the build process.
12+
- Added missing tests for SEO plugin.
13+
- Added export-ignore paths to `.gitattributes`.
14+
915
## [3.1.1] - 2025-10-20
1016
### Added
1117
- Plugin `icons`: added [Ionicons catalog](https://ionic.io/ionicons)
@@ -295,6 +301,7 @@ Go to the `v1` branch to see the changelog of Lume 1.
295301
[#785]: https://github.com/lumeland/lume/issues/785
296302
[#789]: https://github.com/lumeland/lume/issues/789
297303

304+
[3.1.2]: https://github.com/lumeland/lume/compare/v3.1.1...HEAD
298305
[3.1.1]: https://github.com/lumeland/lume/compare/v3.1.0...v3.1.1
299306
[3.1.0]: https://github.com/lumeland/lume/compare/v3.0.11...v3.1.0
300307
[3.0.11]: https://github.com/lumeland/lume/compare/v3.0.10...v3.0.11

plugins/seo.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,29 @@ export function SEO(userOptions?: Config) {
6262
const options = merge(defaults, userOptions);
6363

6464
return (site: Lume.Site) => {
65+
const reports: Map<string, ErrorMessage[]> = new Map();
66+
6567
site.process(processSEO);
6668

69+
function output() {
70+
// Output
71+
const { output } = options;
72+
if (typeof output === "function") {
73+
output(reports);
74+
} else if (typeof output === "string") {
75+
outputFile(reports, output);
76+
} else {
77+
outputConsole(reports);
78+
}
79+
}
80+
81+
site.addEventListener("afterUpdate", output);
82+
site.addEventListener("afterBuild", output);
83+
6784
function processSEO() {
68-
const pages = site.search.pages(options.query);
69-
const reports: Map<string, ErrorMessage[]> = new Map();
85+
reports.clear();
7086
refresh();
87+
const pages = site.search.pages(options.query);
7188
for (const page of pages) {
7289
const errors = validatePage(
7390
page.page.document,
@@ -80,16 +97,6 @@ export function SEO(userOptions?: Config) {
8097
}
8198
}
8299

83-
// Output
84-
const { output } = options;
85-
if (typeof output === "function") {
86-
output(reports);
87-
} else if (typeof output === "string") {
88-
outputFile(reports, output);
89-
} else {
90-
outputConsole(reports);
91-
}
92-
93100
const report = site.debugBar?.collection("SEO");
94101
if (report) {
95102
report.icon = "list-magnifying-glass";

plugins/validate_html.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,36 +50,47 @@ export function validateHtml(userOptions?: Config) {
5050
});
5151

5252
return (site: Lume.Site) => {
53+
let reports: Report | undefined;
5354
site.process([".html"], processValidateHtml);
5455

56+
function output() {
57+
if (!reports) {
58+
return;
59+
}
60+
61+
const { output } = options;
62+
if (typeof output === "function") {
63+
output(reports);
64+
} else if (typeof output === "string") {
65+
outputFile(reports, output);
66+
} else if (output !== false) {
67+
outputConsole(reports);
68+
}
69+
}
70+
71+
site.addEventListener("afterUpdate", output);
72+
site.addEventListener("afterBuild", output);
73+
5574
async function processValidateHtml(pages: Lume.Page[]) {
56-
const reports: Set<Report> = new Set();
75+
reports = undefined;
76+
const pageReports: Set<Report> = new Set();
77+
5778
for (const page of pages) {
5879
const report = await htmlvalidate.validateString(
5980
page.text,
6081
page.data.url,
6182
);
62-
reports.add(report);
83+
pageReports.add(report);
6384
}
6485

65-
const merged = Reporter.merge(Array.from(reports.values()));
66-
67-
// Output
68-
const { output } = options;
69-
if (typeof output === "function") {
70-
output(merged);
71-
} else if (typeof output === "string") {
72-
outputFile(merged, output);
73-
} else if (output !== false) {
74-
outputConsole(merged);
75-
}
86+
reports = Reporter.merge(Array.from(pageReports.values()));
7687

7788
const report = site.debugBar?.collection("HTML validator");
7889
if (report) {
7990
report.icon = "file-html";
8091
report.empty = "No HTML errors found! 🎉";
8192

82-
for (const result of merged.results) {
93+
for (const result of reports.results) {
8394
report.items.push({
8495
title: result.filePath!,
8596
items: Array.from(result.messages).map((message) => {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const snapshot = {};
2+
3+
snapshot[`SEO plugin 1`] = `
4+
[
5+
{
6+
messages: [
7+
"DESCRIPTION_MISSING",
8+
"BODY_TOO_SHORT",
9+
],
10+
url: "/",
11+
},
12+
]
13+
`;

tests/assets/seo/index.vto

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
</head>
8+
<body>
9+
<h1>0</h1>
10+
</body>
11+
</html>

tests/seo.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { build, getSite } from "./utils.ts";
2+
import { assertSnapshot } from "../deps/snapshot.ts";
3+
import seo from "../plugins/seo.ts";
4+
5+
Deno.test("SEO plugin", async (t) => {
6+
const site = getSite({
7+
src: "seo",
8+
});
9+
10+
const result: { url: string; messages: string[] }[] = [];
11+
12+
site.use(seo({
13+
output(reports) {
14+
for (const [url, messages] of reports.entries()) {
15+
result.push({
16+
url,
17+
messages: messages.map((msg) =>
18+
typeof msg === "string" ? msg : msg.msg
19+
),
20+
});
21+
}
22+
},
23+
}));
24+
25+
await build(site);
26+
result.sort((a, b) => a.url.localeCompare(b.url));
27+
await assertSnapshot(t, result);
28+
});

0 commit comments

Comments
 (0)