-
Notifications
You must be signed in to change notification settings - Fork 1
/
image.js
79 lines (62 loc) · 1.72 KB
/
image.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import sharp from "sharp";
import { DIRECTORIES } from "./eleventy.config.js";
/**
* @param {string} inputPath
* @param {"flag"} [preset]
*/
export async function generateImage(inputPath, preset) {
if (preset === "flag") {
return createFlag(inputPath);
}
return inputPath;
}
/** @type {Map<string, sharp.Sharp>} */
const flagCache = new Map();
/**
* @param {string} inputPath Input path
* @returns {Promise<string>} Output path
*/
async function createFlag(inputPath) {
const id = path.basename(inputPath, path.extname(inputPath));
const outputURL = `img/${id}.social.png`;
const outputPath = `${DIRECTORIES.output}/${outputURL}`;
const width = 1200;
const height = 630;
const file = await fs.readFile(inputPath);
const hash = crypto.createHash("sha256").update(file).digest("hex");
let image = flagCache.get(hash);
// Create new image if cache is empty
if (!image) {
console.log(`[img] Creating ${outputPath} from ${inputPath}`);
const flag = sharp(file).resize({
width: width * 0.7,
height: height * 0.7,
fit: "inside",
});
const background = sharp(file)
.resize({ width, height })
.blur(process.env.ENV === "production" && 100)
.ensureAlpha(0.3)
.flatten({ background: "#fff" });
image = sharp({
create: {
width,
height,
channels: 4,
background: "#fff",
},
}).composite([
{ input: await background.toBuffer() },
{ input: await flag.toBuffer() },
]);
flagCache.set(hash, image);
}
// Write image file
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await image.toFile(outputPath);
return outputURL;
}