Convert 26 PNG/JPG assets to WebP: max 1600 px, q80, diagrams lossless. src/assets shrinks from 8.3 MB to 4.2 MB. Use me.jpg for og:image and twitter:image; some crawlers skip WebP. Add scripts/check-assets.mjs to lint, so a wrong asset path fails lint, not only at runtime.
38 lines
1.1 KiB
JavaScript
38 lines
1.1 KiB
JavaScript
#!/usr/bin/env node
|
|
// Verifies that every asset path in AssetsConstants.ts and index.html exists.
|
|
// A wrong path builds fine and only 404s at runtime.
|
|
|
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
import { join, dirname, extname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const srcDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'src');
|
|
const EXTENSIONS = new Set(['.ts', '.html', '.scss', '.json']);
|
|
|
|
function* walk(dir) {
|
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
const path = join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
yield* walk(path);
|
|
} else if (EXTENSIONS.has(extname(path)) && !path.endsWith('.spec.ts')) {
|
|
yield path;
|
|
}
|
|
}
|
|
}
|
|
|
|
const missing = [];
|
|
for (const file of walk(srcDir)) {
|
|
const content = readFileSync(file, 'utf8');
|
|
for (const [, path] of content.matchAll(/\b(assets\/[\w./-]+)/g)) {
|
|
if (!existsSync(join(srcDir, path))) {
|
|
missing.push(`${file}: ${path}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (missing.length > 0) {
|
|
console.error(`Missing assets:\n${missing.join('\n')}`);
|
|
process.exit(1);
|
|
}
|
|
console.log('All referenced assets exist.');
|