-
Notifications
You must be signed in to change notification settings - Fork 1
/
generate-responsive-image-data.js
133 lines (120 loc) · 4.55 KB
/
generate-responsive-image-data.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import fm from 'front-matter';
import fs from 'fs';
import path from 'path';
import { BLOG_PATH } from './src/lib/utilities/blog.js';
import { makeDirectory } from './src/lib/utilities/file.js';
import { dominantColour, lowResolutionPlaceholder, metadata } from './src/lib/utilities/image.js';
const __dirname = path.resolve();
const formats = ['webp', 'auto'];
const sizes = [672];
const densities = [1.0, 2.0];
const maxWidth = sizes[sizes.length - 1];
// use sizes and densities arrays to determine the actual output widths needed
const outputSizes = [];
sizes.forEach((sizesElement) => {
densities.forEach((densitiesElement) => outputSizes.push(densitiesElement * sizesElement));
});
outputSizes.sort((a, b) => b - a);
async function generateImageMeta(source) {
const metaPromises = [
metadata({ source }),
dominantColour({ source }),
lowResolutionPlaceholder({ source }),
];
const [metadataResult, dominantColourObject, placeholder] = await Promise.all(metaPromises);
const { format, width, height } = metadataResult;
const { r, g, b } = dominantColourObject;
const dominantColourValue = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`;
return { dominantColour: dominantColourValue, placeholder, format, width, height };
}
function getPosts(location) {
const directories = fs
.readdirSync(location)
.filter((element) => fs.lstatSync(`${location}/${element}`).isDirectory());
const articles = [];
directories.forEach((element) => {
const contentPath = `${location}/${element}/index.md`;
if (fs.existsSync(contentPath)) {
const content = fs.readFileSync(contentPath, { encoding: 'utf-8' });
const frontmatter = fm(content);
const { featuredImage, featuredImageAlt, ogImage, ogSquareImage, twitterImage } =
frontmatter.attributes;
articles.push({
slug: element,
featuredImage,
featuredImageAlt,
ogImage,
ogSquareImage,
twitterImage,
});
}
});
return articles;
}
const main = async () => {
try {
const location = path.join(__dirname, BLOG_PATH);
const posts = getPosts(location);
const imageMetaPromises = posts.map(async (element) => {
const { featuredImage, slug } = element;
const source = path.join(__dirname, 'src/lib/assets/blog/', slug, featuredImage);
return generateImageMeta(source);
});
const imageMetadata = await Promise.all(imageMetaPromises);
console.log(`Generating image metadata for posts`);
const postDataDir = path.join(__dirname, 'src/lib/generated/posts');
await makeDirectory(postDataDir);
posts.forEach((element, index) => {
const { featuredImage, featuredImageAlt, ogImage, ogSquareImage, slug, twitterImage } =
element;
const postPath = path.join(postDataDir, `${slug}.js`);
const { dominantColour, format, placeholder, width } = imageMetadata[index];
const source = `$lib/assets/blog/${slug}/${featuredImage}`;
const ogImageSource = `$lib/assets/blog/${slug}/${ogImage}`;
const ogSquareImageSource = `$lib/assets/blog/${slug}/${ogSquareImage}`;
const twitterImageSource = `$lib/assets/blog/${slug}/${twitterImage}`;
const srcsetImportArray = formats.map(
(formatsElement) =>
`import srcset${formatsElement} from '${source}?w=${
width < outputSizes[0] ? `${width};` : ''
}${outputSizes.filter((outputSizesElement) => outputSizesElement <= width).join(';')}&${
formatsElement === 'auto' ? format : formatsElement
}&srcset';`,
);
const sources = `[\n${formats
.map(
(formatsElement) =>
` { srcset: ${`srcset${formatsElement}`}, type: ${
formatsElement === 'auto' ? `'image/${format}'` : `'image/${formatsElement}'`
} },`,
)
.join('\n')}\n ]`;
const result = `import meta from '${source}?width=${Math.min(maxWidth, width)}&metadata';
${srcsetImportArray.join('\n')}
import ogImage from '${ogImageSource}';
import ogSquareImage from '${ogSquareImageSource}';
import twitterImage from '${twitterImageSource}';
const { height, src, width } = meta;
const data = {
slug: '${slug}',
alt: '${featuredImageAlt.replace(/'/g, "\\'")}',
width,
height,
src,
sources: ${sources},
dominantColour: '${dominantColour}',
placeholder:
'${placeholder}',
ogImage,
ogSquareImage,
twitterImage,
};
export { data as default };
`;
fs.writeFileSync(postPath, result, 'utf-8');
});
} catch (error) {
console.log(`Error generating blog post responsive image data: ${error}`);
}
};
main();