import fs from "fs"; import path from "path"; import { execSync } from "child_process"; import crypto from "crypto"; const RESOURCES_DIR = "content/resources"; const IMAGES_DIR = "public/images/resources/content"; // Collect all unique Squarespace URLs from MDX files const mdxFiles = fs.readdirSync(RESOURCES_DIR).filter((f) => f.endsWith(".mdx")); const urlMap = new Map(); // url -> local filename let totalUrls = 0; for (const file of mdxFiles) { const content = fs.readFileSync(path.join(RESOURCES_DIR, file), "utf8"); const urls = content.match(/https:\/\/images\.squarespace-cdn\.com\/[^\s"'\)]+/g); if (urls) { for (const url of urls) { if (!urlMap.has(url)) { // Generate a short filename from the URL const urlPath = new URL(url).pathname; const ext = path.extname(urlPath).toLowerCase() || ".jpg"; const baseName = path.basename(urlPath, ext).replace(/[^a-zA-Z0-9_-]/g, "-").substring(0, 60); const hash = crypto.createHash("md5").update(url).digest("hex").substring(0, 8); const localName = `${baseName}-${hash}${ext}`; urlMap.set(url, localName); totalUrls++; } } } } console.log(`Found ${totalUrls} unique Squarespace URLs across ${mdxFiles.length} MDX files`); // Download all images let downloaded = 0; let failed = 0; const failedUrls = []; for (const [url, localName] of urlMap) { const localPath = path.join(IMAGES_DIR, localName); if (fs.existsSync(localPath) && fs.statSync(localPath).size > 1000) { downloaded++; continue; } try { execSync( `curl -sL -o "${localPath}" --max-time 30 "${url}"`, { timeout: 35000 } ); const stat = fs.statSync(localPath); if (stat.size < 500) { console.log(`WARN: Small file (${stat.size}b) for ${url}`); fs.unlinkSync(localPath); failed++; failedUrls.push(url); } else { downloaded++; } } catch (e) { console.log(`FAIL: ${url}`); failed++; failedUrls.push(url); if (fs.existsSync(localPath)) fs.unlinkSync(localPath); } if ((downloaded + failed) % 50 === 0) { console.log(`Progress: ${downloaded + failed}/${totalUrls} (${failed} failed)`); } } console.log(`\nDownloaded: ${downloaded}, Failed: ${failed}`); // Rewrite MDX files let filesUpdated = 0; for (const file of mdxFiles) { const filePath = path.join(RESOURCES_DIR, file); let content = fs.readFileSync(filePath, "utf8"); let changed = false; for (const [url, localName] of urlMap) { if (content.includes(url)) { const localRef = `/images/resources/content/${localName}`; content = content.replaceAll(url, localRef); changed = true; } } if (changed) { fs.writeFileSync(filePath, content); filesUpdated++; } } console.log(`Updated ${filesUpdated} MDX files`); if (failedUrls.length > 0) { console.log(`\nFailed URLs:`); for (const u of failedUrls) { console.log(` ${u}`); } }