Created
February 11, 2025 23:27
-
-
Save harrylincoln/f3a58a10841586847dc19c1daa17b1c0 to your computer and use it in GitHub Desktop.
Scrape storybook icons node script
This file contains hidden or 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
const { chromium } = require('playwright'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const URL = 'https://orgvue-qa.eu-west-1.concentra.io/app/primitive-components/1.0.0/?path=/story/components-icon--actions'; | |
async function scrapeSVGs() { | |
const browser = await chromium.launch({ headless: false }); // Change to true if you want headless mode | |
const page = await browser.newPage(); | |
console.log('Opening Storybook page...'); | |
await page.goto(URL, { waitUntil: 'domcontentloaded' }); | |
console.log('Waiting for Storybook UI to load...'); | |
await page.waitForSelector('iframe', { timeout: 60000 }); // Wait for iframe | |
// Find the iframe | |
const iframeElement = await page.$('iframe'); // Grabbing the first iframe | |
if (!iframeElement) { | |
console.error('Iframe not found!'); | |
await browser.close(); | |
return; | |
} | |
const iframe = await iframeElement.contentFrame(); // Get the content inside iframe | |
if (!iframe) { | |
console.error('Could not get iframe content!'); | |
await browser.close(); | |
return; | |
} | |
console.log('Waiting for icons to appear inside iframe...'); | |
// THIS SELECTOR WILL ALMOST CERTAINLY NEED TO CHANGE BASED ON MARKUP GENERATED BY STORYBOOK | |
await iframe.waitForSelector('#storybook-root span[role="img"] svg', { timeout: 60000 }); | |
console.log('Extracting SVGs...'); | |
const svgs = await iframe.evaluate(() => { | |
const icons = {}; | |
// Loop through all the spans that represent icons | |
document.querySelectorAll('#storybook-root span[role="img"]').forEach(span => { | |
const ariaLabel = span.getAttribute('aria-label')?.trim().toLowerCase().replace(/\s+/g, '-') || 'unnamed-icon'; | |
const svg = span.querySelector('svg'); | |
if (svg) { | |
let svgContent = svg.outerHTML.trim(); | |
// Ensure unique filenames | |
let filename = ariaLabel; | |
let counter = 1; | |
while (icons[filename]) { | |
filename = `${ariaLabel}-${counter}`; | |
counter++; | |
} | |
icons[filename] = svgContent; | |
} | |
}); | |
return Object.entries(icons).map(([filename, content]) => ({ | |
filename: `${filename}.svg`, | |
content | |
})); | |
}); | |
console.log(`Found ${svgs.length} unique SVGs.`); | |
if (svgs.length > 0) saveSVGs(svgs); | |
await browser.close(); | |
console.log('✅ Done!'); | |
} | |
function saveSVGs(svgs) { | |
const outputDir = './svgs'; | |
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir); | |
svgs.forEach(({ filename, content }) => { | |
fs.writeFileSync(`${outputDir}/${filename}`, content, 'utf8'); | |
console.log(`Saved: ${filename}`); | |
}); | |
} | |
scrapeSVGs().catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment