Major site overhaul: resources hub, content migration, new blog posts, forms
- Redesign /resources as sectioned hub with category pages - Migrate 645 Squarespace CDN images to local /images/content/ - Create 9 new news/blog posts with event photos - Fix blog post slugs (rename gibberish filenames) - Rename Design Blog to Design Blogs across site - Remove education page, replace with Platform in nav - Redesign rover repair request form with dynamic rover entries - Add school search combobox to contact, store, and repair forms - Extract shared KNOWN_SCHOOLS data - Make /rover-expansion-3d-printing dynamically pull from MDX - Add related resources sections to product pages - Fix homepage broken /quote links to /store - Store page: sample kit cards, inline quote builder, mailing list opt-in
This commit is contained in:
105
scripts/download-sqsp-images.mjs
Normal file
105
scripts/download-sqsp-images.mjs
Normal file
@@ -0,0 +1,105 @@
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user