Skip to content

Instantly share code, notes, and snippets.

@tacone
Created March 7, 2022 22:25
Show Gist options
  • Save tacone/45d8fd496ef31f9b1c5579b2748245e1 to your computer and use it in GitHub Desktop.
Save tacone/45d8fd496ef31f9b1c5579b2748245e1 to your computer and use it in GitHub Desktop.
Add timestamp to every image and update the HTML files to link to the renamed images
import fastGlob from 'fast-glob';
import crypto from 'crypto';
import path from 'path';
import fs from 'fs';
// I could try to parse the HTML files using cheerio[1], but a simple find and replace
// is likely to be faster, more powerful and - realistically - quite as much as reliable.
//
// [1] just like this: https://github.com/maxogden/inline-images/blob/master/index.js
const basePath = `./export`;
const imagesPath = `${basePath}/images`;
const pagesPath = `${basePath}/_app/pages`;
const baseUrl = `/_app/assets`;
function addSuffix(uri, hash) {
const extension = path.extname(uri);
const basename = path.basename(uri, extension);
const filePath = path.dirname(uri);
return path.join(filePath, `${basename}-${hash}${extension}`);
}
// generate a md5 timestamp
const hash = crypto.randomBytes(4).toString('hex');
// and now... let's glob
let images = fastGlob.sync(`${imagesPath}/**/*.{png,jpg,jpeg,gif,webp,avif}`, {
onlyFiles: true,
stats: true
});
const alreadyTimestamped = /(.*)(-)[a-f0-9]{8}[.][A-Za-z0-9]{2,5}/;
images = images.filter((file) => {
const isTimeStamped = file.path.match(alreadyTimestamped);
// in dev, delete the timestamped files
if (isTimeStamped && process.env.NODE_ENV !== 'production') {
fs.unlinkSync(file.path);
}
return !isTimeStamped;
});
images.forEach((file) => {
file.url = file.path.replace(basePath, '');
file.newUrl = addSuffix(file.url, hash);
file.newPath = addSuffix(file.path, hash);
});
console.log('images found:', images.length);
let htmlFiles = fastGlob
.sync(`${basePath}/**/*.html`, {
onlyFiles: true,
objectMode: true
})
.filter((file) => !file.path.match(/-processed.html$/));
console.log('html files found:', htmlFiles.length);
for (let html of htmlFiles) {
html.content = fs.readFileSync(html.path, 'utf8');
for (const i of images) {
html.content = html.content.replaceAll(i.url, i.newUrl);
}
}
for (let html of htmlFiles) {
let filename;
if (process.env.NODE_ENV === 'production') {
// in prod, replace the original file html with the new one
filename = html.path;
} else {
// in dev, write the html to a new file
filename = addSuffix(html.path, 'processed');
}
console.log('writing:', filename);
fs.writeFileSync(filename, html.content, 'utf8');
}
console.log('renaming the images...');
// check NODE_ENV
if (process.env.NODE_ENV === 'production') {
// in prod rename all files
for (const i of images) {
fs.renameSync(i.path, i.newPath);
}
} else {
// in dev, make a copy with the new name
for (const i of images) {
fs.copyFileSync(i.path, i.newPath);
}
}
console.log('done!');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment