90 lines
3.4 KiB
JavaScript
90 lines
3.4 KiB
JavaScript
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
||
|
|
const sharp = require('sharp');
|
||
|
|
|
||
|
|
const CONTENT_DIR = path.join(__dirname, '../content/post');
|
||
|
|
const MAX_SIZE_BYTES = 1 * 1024 * 1024; // 1MB
|
||
|
|
|
||
|
|
async function processDirectory(dir) {
|
||
|
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||
|
|
|
||
|
|
for (const entry of entries) {
|
||
|
|
const fullPath = path.join(dir, entry.name);
|
||
|
|
|
||
|
|
if (entry.isDirectory()) {
|
||
|
|
await processDirectory(fullPath);
|
||
|
|
} else if (entry.isFile()) {
|
||
|
|
const ext = path.extname(entry.name).toLowerCase();
|
||
|
|
if (['.png', '.jpg', '.jpeg'].includes(ext)) {
|
||
|
|
const stats = fs.statSync(fullPath);
|
||
|
|
if (stats.size > MAX_SIZE_BYTES) {
|
||
|
|
console.log(`Processing large image: ${fullPath} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
|
||
|
|
await convertToWebP(fullPath);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function convertToWebP(filePath) {
|
||
|
|
const dir = path.dirname(filePath);
|
||
|
|
const ext = path.extname(filePath);
|
||
|
|
const name = path.basename(filePath, ext);
|
||
|
|
const newFileName = `${name}.webp`;
|
||
|
|
const newFilePath = path.join(dir, newFileName);
|
||
|
|
|
||
|
|
try {
|
||
|
|
await sharp(filePath)
|
||
|
|
.webp({ quality: 80 })
|
||
|
|
.toFile(newFilePath);
|
||
|
|
|
||
|
|
console.log(`Converted to: ${newFileName}`);
|
||
|
|
|
||
|
|
// Update index.md
|
||
|
|
const mdPath = path.join(dir, 'index.md');
|
||
|
|
if (fs.existsSync(mdPath)) {
|
||
|
|
let content = fs.readFileSync(mdPath, 'utf8');
|
||
|
|
// Replace exact filename
|
||
|
|
const regex = new RegExp(escapeRegExp(path.basename(filePath)), 'g');
|
||
|
|
if (regex.test(content)) {
|
||
|
|
content = content.replace(regex, newFileName);
|
||
|
|
fs.writeFileSync(mdPath, content, 'utf8');
|
||
|
|
console.log(`Updated index.md reference.`);
|
||
|
|
|
||
|
|
// Delete original file only if markdown was updated (safety)
|
||
|
|
fs.unlinkSync(filePath);
|
||
|
|
console.log(`Deleted original file.`);
|
||
|
|
} else {
|
||
|
|
console.warn(`Warning: Could not find reference to ${path.basename(filePath)} in index.md. Keeping original file.`);
|
||
|
|
// If not found in index.md, maybe it's not used or referenced differently?
|
||
|
|
// For safety, we keep it, but this defeats the purpose of space saving if it's unused.
|
||
|
|
// But if it IS used but I missed the regex, deleting it breaks the site.
|
||
|
|
// However, user wants to fix deployment. Unused large files should be deleted.
|
||
|
|
// But I'll play safe.
|
||
|
|
|
||
|
|
// Actually, let's delete it if we have the webp.
|
||
|
|
// Wait, if markdown still points to png, site breaks.
|
||
|
|
// So keeping it is safer.
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
console.warn(`Warning: No index.md found in ${dir}.`);
|
||
|
|
}
|
||
|
|
|
||
|
|
} catch (err) {
|
||
|
|
console.error(`Error converting ${filePath}:`, err);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function escapeRegExp(string) {
|
||
|
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||
|
|
}
|
||
|
|
|
||
|
|
(async () => {
|
||
|
|
console.log(`Starting image optimization in ${CONTENT_DIR}...`);
|
||
|
|
if (fs.existsSync(CONTENT_DIR)) {
|
||
|
|
await processDirectory(CONTENT_DIR);
|
||
|
|
} else {
|
||
|
|
console.error(`Directory not found: ${CONTENT_DIR}`);
|
||
|
|
}
|
||
|
|
console.log('Done.');
|
||
|
|
})();
|