diff --git a/build/build.ts b/build/build.ts
index b3dc1f7..1ae3f65 100644
--- a/build/build.ts
+++ b/build/build.ts
@@ -2,6 +2,7 @@ import path from "node:path";
import fs from "node:fs";
import { createHash } from "node:crypto";
import { promisify } from "node:util";
+import { exec } from "node:child_process";
import * as esbuild from "esbuild";
import { optimize } from "svgo";
import * as xmlParser from "../lib/xml-parser.ts";
@@ -20,12 +21,9 @@ const fsAsync = {
mkdir: promisify(fs.mkdir),
};
-const MODE = process.env["NODE_ENV"] || "production";
+const execAsync = promisify(exec);
-const BUILD_METADATA = new Date()
- .toISOString()
- .split(".")[0]
- .replace(/[^0-9]/g, "");
+const MODE = process.env["NODE_ENV"] || "production";
const INPUT_DIR = process.cwd();
const OUTPUT_DIR = path.join(INPUT_DIR, "dist");
@@ -140,17 +138,38 @@ function generateSymbol(id: string, svgStr: string): string {
return `${symbolBody}`;
}
+async function getBuildMetadata(): Promise {
+ const date = new Date().toISOString().slice(2, 10).replaceAll("-", "");
+
+ const [commit, diff, newFiles] = await Promise.all([
+ execAsync("git rev-parse HEAD"),
+ execAsync("git diff HEAD"),
+ execAsync("git ls-files --others --exclude-standard"),
+ ]).then((res) => res.map((r) => r.stdout.trim()));
+
+ if (!diff && !newFiles) return date + commit.slice(0, 4);
+
+ const hash = createHash("md5");
+ hash.update(commit).update(diff).update(newFiles);
+ for (const file of newFiles.split("\n").filter((f) => f))
+ hash.update(await fsAsync.readFile(file));
+ return date + hash.digest("hex").slice(0, 4);
+}
+
async function init(): Promise {
- const [packageJsonFile, npmShrinkwrapFile] = await Promise.all([
- fsAsync.readFile(path.join(INPUT_DIR, "package.json")),
- fsAsync.readFile(path.join(INPUT_DIR, "npm-shrinkwrap.json")),
- ]);
+ const [buildMetadata, packageJsonFile, npmShrinkwrapFile] = await Promise.all(
+ [
+ getBuildMetadata(),
+ fsAsync.readFile(path.join(INPUT_DIR, "package.json")),
+ fsAsync.readFile(path.join(INPUT_DIR, "npm-shrinkwrap.json")),
+ ],
+ );
const packageJson = JSON.parse(packageJsonFile.toString());
delete packageJson["devDependencies"];
delete packageJson["private"];
delete packageJson["scripts"];
- packageJson["version"] = `${packageJson["version"]}+${BUILD_METADATA}`;
+ packageJson["version"] = `${packageJson["version"]}+${buildMetadata}`;
const npmShrinkwrap = JSON.parse(npmShrinkwrapFile.toString());
npmShrinkwrap["version"] = packageJson["version"];