Skip to content

Commit b4d3c6d

Browse files
committed
feat: make the filters async
- Make you Eleventy builds much faster
1 parent 874f21d commit b4d3c6d

File tree

6 files changed

+64
-39
lines changed

6 files changed

+64
-39
lines changed

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import getCollectionNewestGitCommitDate from "./src/getCollectionNewestGitCommit
33
import getGitCommitDateFromPath from "./src/getGitCommitDateFromPath.js";
44

55
export default function (eleventyConfig) {
6-
eleventyConfig.addFilter(
6+
eleventyConfig.addAsyncFilter(
77
"getGitCommitDateFromPath",
88
getGitCommitDateFromPath,
99
);
10-
eleventyConfig.addFilter(
10+
eleventyConfig.addAsyncFilter(
1111
"getCollectionNewestGitCommitDate",
1212
getCollectionNewestGitCommitDate,
1313
);

src/getCollectionNewestGitCommitDate.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,27 @@ import memoize from "./utils/memoize.js";
55
/**
66
* Gets the collection's newest Git commit date.
77
*
8-
* @param {object[]} collection The collection
9-
* @returns {Date | undefined} The collection newest git commit date.
8+
* @param {object[]} collection Collection
9+
* @returns {Promise<Date | undefined>} Newest git commit date among the items
10+
* in the collection
1011
*/
11-
function getCollectionNewestGitCommitDate(collection) {
12+
async function getCollectionNewestGitCommitDate(collection) {
1213
if (!collection || !collection.length) {
1314
return;
1415
}
1516

16-
const timestamps = collection
17-
.map((item) => getGitCommitDateFromPath(item.inputPath))
17+
const timestamps = await Promise.all(
18+
collection.map((item) => getGitCommitDateFromPath(item.inputPath)),
19+
);
20+
21+
const dates = timestamps
1822
// Timestamps will be undefined for the paths not
1923
// yet commited to Git. So weeding them out.
2024
.filter((ts) => Boolean(ts))
21-
.map((ts) => /** @type Date */ (ts).getTime());
25+
.map((ts) => ts.getTime());
2226

23-
if (timestamps.length) {
24-
return new Date(Math.max(...timestamps));
27+
if (dates.length) {
28+
return new Date(Math.max(...dates));
2529
}
2630
}
2731

src/getGitCommitDateFromPath.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// @ts-check
2-
import spawn from "cross-spawn";
3-
import path from "node:path";
42
import memoize from "./utils/memoize.js";
3+
import { spawnAsync } from "./utils/spawn.js";
54

65
/**
76
* Gets the Git commit date from path.
@@ -10,29 +9,25 @@ import memoize from "./utils/memoize.js";
109
* https://github.com/vuejs/vuepress/blob/master/packages/%40vuepress/plugin-last-updated/
1110
*
1211
* @param {string} filePath The file path
13-
* @returns {Date | undefined} The git commit date if path is commited to Git.
12+
* @returns {Promise<Date | undefined>} Commit date if path is commited to Git,
13+
* otherwise `undefined`
1414
*/
15-
function getGitCommitDateFromPath(filePath) {
15+
async function getGitCommitDateFromPath(filePath) {
1616
let output;
1717

1818
try {
19-
output = spawn.sync(
20-
"git",
21-
["log", "-1", "--format=%at", path.basename(filePath)],
22-
{ cwd: path.dirname(filePath) },
23-
);
24-
} catch {
19+
output = await spawnAsync("git", ["log", "-1", "--format=%at", filePath]);
20+
} catch (e) {
21+
console.log(e);
2522
throw new Error("Fail to run 'git log'");
2623
}
2724

28-
if (output && output.stdout) {
29-
const ts = parseInt(output.stdout.toString("utf-8"), 10) * 1000;
25+
const ts = parseInt(output, 10) * 1000;
3026

31-
// Paths not commited to Git returns empty timestamps, resulting in NaN.
32-
// So, convert only valid timestamps.
33-
if (!isNaN(ts)) {
34-
return new Date(ts);
35-
}
27+
// Paths not commited to Git returns empty timestamps, resulting in NaN.
28+
// So, convert only valid timestamps.
29+
if (!isNaN(ts)) {
30+
return new Date(ts);
3631
}
3732
}
3833

src/utils/spawn.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { spawn } from "node:child_process";
2+
3+
export function spawnAsync(command, args, options) {
4+
return new Promise((resolve, reject) => {
5+
const cmd = spawn(command, args, options);
6+
const res = [];
7+
cmd.stdout.on("data", (data) => {
8+
res.push(data.toString("utf8"));
9+
});
10+
11+
const err = [];
12+
cmd.stderr.on("data", (data) => {
13+
err.push(data.toString("utf8"));
14+
});
15+
16+
cmd.on("close", (code) => {
17+
if (err.length > 0) {
18+
reject(err.join("\n"));
19+
} else if (code === 1) {
20+
reject(
21+
new Error("Internal error: process closed with error exit code."),
22+
);
23+
} else {
24+
resolve(res.join("\n"));
25+
}
26+
});
27+
});
28+
}

tests/getCollectionNewestGitCommitDate.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@ import { getCollectionNewestGitCommitDate } from "../index.js";
77

88
const __dirname = path.dirname(fileURLToPath(import.meta.url));
99

10-
test("Get newest commit date of collection", (t) => {
10+
test("Get newest commit date of collection", async (t) => {
1111
const collection = [
1212
{ inputPath: path.join(__dirname, "./fixtures/sample.md") },
1313
{ inputPath: path.join(__dirname, "./fixtures/another-sample-file.md") },
1414
];
15-
const date = getCollectionNewestGitCommitDate(collection);
15+
const date = await getCollectionNewestGitCommitDate(collection);
1616
t.truthy(date);
1717
t.is(date.toISOString(), "2021-08-19T09:57:47.000Z");
1818
});
1919

2020
test("Shouldn't get commit date from an empty collection", async (t) => {
2121
const collection = [];
2222

23-
t.is(getCollectionNewestGitCommitDate(collection), undefined);
23+
t.is(await getCollectionNewestGitCommitDate(collection), undefined);
2424
});
2525

2626
test("Shouldn't get commit date from collection of uncommited files", async (t) => {
27-
const outputBase = path.join("tests/output/");
27+
const outputBase = path.join(__dirname, "output/collection");
2828
const collection = [
2929
{ inputPath: path.join(outputBase, "test-01.md") },
3030
{ inputPath: path.join(outputBase, "test-02.md") },
@@ -35,7 +35,7 @@ test("Shouldn't get commit date from collection of uncommited files", async (t)
3535
await mkdir(outputBase, { recursive: true });
3636
await Promise.all(collection.map((p) => writeFile(p.inputPath, "")));
3737

38-
t.is(getCollectionNewestGitCommitDate(collection), undefined);
38+
t.is(await getCollectionNewestGitCommitDate(collection), undefined);
3939

4040
await rimraf(outputBase);
4141
});

tests/getGitCommitDateFromPath.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,22 @@ import { getGitCommitDateFromPath } from "../index.js";
77

88
const __dirname = path.dirname(fileURLToPath(import.meta.url));
99

10-
test("Get commit date of a committed file", (t) => {
10+
test("Get commit date of a committed file", async (t) => {
1111
const filePath = path.join(__dirname, "./fixtures/sample.md");
12-
const date = getGitCommitDateFromPath(filePath);
12+
const date = await getGitCommitDateFromPath(filePath);
1313
t.truthy(date);
1414
t.is(date.toISOString(), "2021-08-19T09:57:47.000Z");
1515
});
1616

1717
test("Should not get commit date of a uncommitted file", async (t) => {
18-
const outputBase = path.join(__dirname, "/output/");
18+
const outputBase = path.join(__dirname, "/output/single-file-path");
1919
const filePath = path.join(outputBase, "test.md");
2020
await rimraf(outputBase);
2121

22-
await mkdir(outputBase, { recursive: true }, (err) => {
23-
console.error(err);
24-
});
22+
await mkdir(outputBase, { recursive: true });
2523
await writeFile(filePath, "");
2624

27-
t.is(getGitCommitDateFromPath(filePath), undefined);
25+
t.is(await getGitCommitDateFromPath(filePath), undefined);
2826

2927
await rimraf(outputBase);
3028
});

0 commit comments

Comments
 (0)