Last active
May 27, 2021 15:29
-
-
Save achhunna/deaa1565062264eccde5856808d996ba to your computer and use it in GitHub Desktop.
Batch SVG file download from Zeplin's styleguide components
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 fs = require('fs'); | |
const mkdirp = require('mkdirp'); | |
const getDirName = require('path').dirname; | |
const axios = require('axios'); | |
const styleguideId = process.argv.slice(2)[0]; // provide styleguideId ast 1st arg in command line | |
if (!styleguideId) { | |
throw Error('Please provide styleguideId as first arg'); | |
} | |
const token = process.env.ZEPLIN_ACCESS_TOKEN || ''; // add `export ZEPLIN_ACCESS_TOKEN=xxx` in ~/.bash_profile | |
const baseUrl = 'https://api.zeplin.dev/v1/'; | |
const styleguidesUrl = `styleguides/${styleguideId}/components`; | |
const limit = 100; // max items per request https://docs.zeplin.dev/reference#pagination | |
let step = 0; | |
const maxLimit = 1000; // assuming we won't have > 1000 icons | |
const offsetList = []; | |
while (step < maxLimit) { | |
offsetList.push(step); | |
step += limit; | |
} | |
function writeFile(path, contents, cb) { | |
mkdirp(getDirName(path), (err) => { | |
if (err) return cb(err); | |
fs.writeFile(path, contents, cb); | |
}); | |
} | |
function paramsToString(params) { | |
return Object.keys(params).reduce((acc, p, i) => { | |
if (i !== 0) { | |
return `${acc}&${p}=${params[p]}`; | |
} | |
return `${acc}${p}=${params[p]}`; | |
}, ''); | |
} | |
function getComponentsListUrl(limit, offset) { | |
return `${baseUrl}${styleguidesUrl}?${paramsToString({ limit, offset })}`; | |
} | |
const headers = { | |
accept: 'application/json', | |
authorization: `Bearer ${token}`, | |
}; | |
const getComponentsListPromises = offsetList.map(offset => { | |
return axios.get(getComponentsListUrl(limit, offset), { headers }) | |
}); | |
Promise.all(getComponentsListPromises) | |
.then((dataArray) => { | |
const data = dataArray.reduce((acc, { data, status }) => { | |
if (status === 200 && data.length > 0) { | |
return [...acc, ...data]; | |
} else { | |
return acc; | |
} | |
}, []); | |
return Promise.all(data.filter(c => { | |
if (c.name.indexOf('/') === -1) { // filter out any non icon components | |
return true; | |
} else { | |
return false; | |
} | |
}).map(c => { | |
const id = c.id; | |
const getComponentDetailsUrl = `${baseUrl}${styleguidesUrl}/${id}/versions/latest`; | |
return axios.get(getComponentDetailsUrl, { headers }); | |
})); | |
}) | |
.then(data => { | |
data.forEach(({ data, status }) => { | |
if (status === 200) { | |
const assets = data.assets; | |
const lastAsset = assets[assets.length - 1]; | |
if (lastAsset) { | |
const filename = `${lastAsset.display_name}.svg`; | |
const svgFiltered = lastAsset.contents.filter(c => c.format === 'svg'); | |
const svgFileUrl = svgFiltered[0].url; | |
const pathname = '/assets/svg/'; | |
axios.get(svgFileUrl, { headers }).then(({ data, status }) => { | |
if (status === 200) { | |
writeFile(`${__dirname}${pathname}${filename}`, data, () => { | |
console.log(`${filename} saved to ${pathname}`); | |
}); | |
} | |
}); | |
} | |
} | |
}); | |
}) | |
.catch((error) => { | |
console.error(error); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment