-
-
Save jherr/14cf3143ab1dc40ebc8a29d992c71419 to your computer and use it in GitHub Desktop.
Helper to download images from Builder.IO converted Figma React/Tailwind from using <img> tags into <Image> components
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Converts a NextJS React file generated by Visual Copilot that includes <img> tags into <Image> components. File contents | |
come as STDIN and files are copied to /public and the re-implementation comes out STDOUT. | |
cat src/app/page.tsx | node scripts/download-images.js | pbcopy | |
*/ | |
const fs = require("fs"); | |
const https = require("https"); | |
const readline = require("readline"); | |
async function main() { | |
// Read all the STDIN | |
const rl = readline.createInterface({ | |
input: process.stdin, | |
}); | |
let input = ""; | |
rl.on("line", (line) => { | |
input += line + "\n"; | |
}); | |
rl.on("close", async () => { | |
const downloads = {}; | |
// Find all the image tags and fix them | |
input = input.replace(/<img\s+(.*?)\/>/gms, (val) => { | |
if (val.includes("src=")) { | |
const url = val.match(/src="(.*?)"/)[1]; | |
const id = url.match("TEMP/([^?]*)")[1]; | |
val = val.replace(`src="${url}"`, `src="/${id}.unk"`); | |
downloads[url] = id; | |
} | |
if (val.includes("srcSet=")) { | |
const values = val.match(/srcSet="(.*?)"/)[1]; | |
const urls = values.split(","); | |
let url = urls[0].split(" ")[0]; | |
url = url.replace(/&width=(.*?)/); | |
const id = url.match("TEMP/([^?]*)")[1]; | |
val = val.replace(`srcSet="${values}"`, `src="/${id}.unk"`); | |
const sizes = | |
urls.map((url) => { | |
return url?.trim()?.split(" ")?.[1]; | |
}) || []; | |
val = val.replace( | |
/<img/, | |
`<img sizes="${sizes.filter((v) => v).join(", ")}"` | |
); | |
downloads[url] = id; | |
} | |
if (!val.includes("alt=")) { | |
val = val.replace( | |
/<img/, | |
'<img alt="Replace with an informative alt text"' | |
); | |
} | |
val = val.replace(/<img/, "<Image"); | |
return val; | |
}); | |
await Promise.all( | |
Object.keys(downloads).map(async (url) => { | |
await new Promise((resolve) => { | |
https.get(url, async (response) => { | |
// Figure out what type of image this is | |
let ext = "png"; | |
const type = response.headers["content-type"]; | |
if (type.includes("svg")) { | |
ext = "svg"; | |
} else if (type.includes("jpeg") || type.includes("jpg")) { | |
ext = "jpg"; | |
} | |
// Download the file into /public | |
await new Promise((frs) => { | |
const file = fs.createWriteStream( | |
`./public/${downloads[url]}.${ext}` | |
); | |
response.pipe(file); | |
file.on("finish", () => { | |
file.close(); | |
frs(); | |
}); | |
}); | |
// Replace the src URL with a new URL that has the right extension | |
input = input.replace( | |
`"/${downloads[url]}.unk"`, | |
`"/${downloads[url]}.${ext}"` | |
); | |
// Figure out the size of the image | |
let width = 1000; | |
let height = 1000; | |
if (ext === "svg") { | |
const svgCode = fs.readFileSync( | |
`./public/${downloads[url]}.svg`, | |
"utf-8" | |
); | |
width = svgCode.match(/width="(.*?)"/)[1]; | |
height = svgCode.match(/height="(.*?)"/)[1]; | |
} | |
// Add the height and width because the Image component requires it | |
input = input.replace( | |
`"/${downloads[url]}.${ext}"`, | |
`"/${downloads[url]}.${ext}" width={${width}} height={${height}}` | |
); | |
resolve(); | |
}); | |
}); | |
}) | |
); | |
// Output the adjusted code | |
console.log(input); | |
}); | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment