-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
webpify.js
199 lines (172 loc) · 8.04 KB
/
webpify.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
const sharp = require('sharp');
const glob = require('glob');
const path = require('path');
const fs = require('fs').promises;
// Array to store original file paths
const originalFiles = [];
const convertedFiles = [];
function normalizePath(filePath) {
return filePath.split(path.sep).join(path.posix.sep);
}
async function deleteOriginalFiles() {
console.log('\nDeleting original files...');
for (const conversion of convertedFiles) {
if (conversion.status === 'converted') {
try {
await fs.rm(conversion.original, { force: true, maxRetries: 5, retryDelay: 1000 });
console.log(`Deleted: ${conversion.original}`);
} catch (error) {
console.error(`Error deleting ${conversion.original}:`, error);
}
} else if (conversion.status === 'skipped' || conversion.status === 'error') {
console.log(`${conversion.original} could not be deleted - ${conversion.status === 'skipped' ? `Conversion of ${conversion.original} has been skipped.` : `There has been an error converting ${conversion.original}: ${conversion.error}`}`);
}
}
console.log('Original file deletion complete!');
}
async function replaceInFiles() {
// Find all JS, JSX, TS, TSX, CSS, SCSS, HTML files, excluding webpify.js and pre-render.js
const codeFiles = glob.sync('**/*.{js,jsx,ts,tsx,css,scss,html}', {
ignore: [
'node_modules/**',
'build/**',
'dist/**',
'webpify.js',
'pre-render.js'
]
});
for (const filePath of codeFiles) {
try {
let content = await fs.readFile(filePath, 'utf8');
let hasChanges = false;
// Replace each image reference
for (const conversion of convertedFiles) {
if (conversion.status === 'skipped') continue;
const { original, webp } = conversion;
const fileName = path.basename(original);
if (original.includes('public/')) {
// Create the absolute path version (starting with /)
const absolutePath = `/${original.split('public/')[1]}`;
const absoluteWebPPath = `/${webp.split('public/')[1]}`;
if (content.includes('%PUBLIC_URL%')) {
// Handle %PUBLIC_URL% placeholder
const publicUrlPath = `%PUBLIC_URL%${absolutePath}`;
const publicUrlWebPPath = `%PUBLIC_URL%${absoluteWebPPath}`;
// Replace %PUBLIC_URL% paths
if (content.includes(publicUrlPath)) {
content = content.replace(new RegExp(publicUrlPath, 'g'), publicUrlWebPPath);
hasChanges = true;
console.log(`Replaced %PUBLIC_URL% reference in ${filePath}: ${publicUrlPath} → ${publicUrlWebPPath}`);
}
} else {
// Replace absolute path references
if (content.includes(absolutePath)) {
content = content.replace(new RegExp(absolutePath, 'g'), absoluteWebPPath);
hasChanges = true;
console.log(`Replaced absolute path reference in ${filePath}: ${absolutePath} → ${absoluteWebPPath}`);
}
}
}
// Original relative path handling
const absoluteOriginalPath = path.resolve(original);
const regex = new RegExp(`(["'\\(])([^"']*${fileName.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')})\\1`, 'g');
let match;
while ((match = regex.exec(content)) !== null) {
const matchedPath = match[2];
const absoluteMatchedPath = path.resolve(path.dirname(filePath), matchedPath);
if (absoluteMatchedPath === absoluteOriginalPath) {
// Calculate the relative path from the source file to the webp file
const relativeWebPPath = path.relative(
path.dirname(filePath),
webp
).split(path.sep).join(path.posix.sep); // Ensure forward slashes
// Preserve the original path style (with or without ./)
const leadingPath = matchedPath.startsWith('./') ? './' : '';
const newPath = leadingPath + relativeWebPPath;
content = content.replace(matchedPath, newPath);
hasChanges = true;
console.log(`Replaced reference in ${filePath}: ${matchedPath} → ${newPath}`);
}
}
}
// Only write to file if changes were made
if (hasChanges) {
await fs.writeFile(filePath, content, 'utf8');
}
} catch (error) {
console.error(`Error processing ${filePath}:`, error);
}
}
}
async function convertToWebP() {
try {
// Find all jpg and png files in the project
const images = glob.sync('**/*.{jpg,jpeg,png}', {
ignore: [
'node_modules/**',
'build/**',
'dist/**',
'public/favicon.png',
'public/assets/banner.png',
'public/assets/bannerDEJTENÁMVAŠEVŠECHNYPRACHY.png'
]
}).map(normalizePath);
console.log(`Found ${String(images.length).padStart(images.length.toString().length, '0')} images to convert.\n`, ...(images.map((image, i) => `Conversion Queue [${String(i + 1).padStart(images.length.toString().length, '0')}/${images.length}]: ${image} \n`)));
for (const imagePath of images) {
// Store original file path
originalFiles.push(imagePath);
const outputPath = imagePath.replace(/\.(jpg|jpeg|png)$/i, '.webp');
// Check if WebP version already exists
try {
await fs.access(outputPath);
console.log(`Skipping ${imagePath} - WebP version already exists`);
convertedFiles.push({
original: imagePath,
webp: outputPath,
status: 'skipped'
});
continue;
} catch {
// File doesn't exist, proceed with conversion
}
try {
await sharp(imagePath)
.webp({ quality: 80 })
.toFile(outputPath);
convertedFiles.push({
original: imagePath,
webp: outputPath,
status: 'converted'
});
console.log(`Converted [${String(convertedFiles.length).padStart(images.length.toString().length, '0')}/${images.length}]: ${imagePath} → ${outputPath}`);
} catch (error) {
console.error(`Error converting ${imagePath}:`, error);
convertedFiles.push({
original: imagePath,
webp: outputPath,
status: 'error',
error: error.message
});
}
}
// Save the results to a JSON file
await fs.writeFile(
'webp-conversion-results.json',
JSON.stringify({
originalFiles,
conversions: convertedFiles
}, null, 2)
);
console.log('Conversion complete! Results saved to webp-conversion-results.json');
// Replace references in code files
console.log('\nReplacing image references in code files...');
await replaceInFiles();
console.log('Reference replacement complete!');
// Delete original files
await deleteOriginalFiles();
} catch (error) {
console.error('Conversion failed:', error);
}
}
// Run the conversion
convertToWebP();