Skip to content

Instantly share code, notes, and snippets.

@controversial
Created February 4, 2021 18:00
Show Gist options
  • Save controversial/9701a5552e18acd05df12317e95f9bcd to your computer and use it in GitHub Desktop.
Save controversial/9701a5552e18acd05df12317e95f9bcd to your computer and use it in GitHub Desktop.
Sketch plugin to generate an icon library from a directory of SVGs
// Sketch plugin to generate an icon library from a directory of SVGs
const sketchDom = require('sketch/dom');
// Prompt the user to select a folder
const dialog = NSOpenPanel.openPanel();
dialog.setCanChooseFiles(false);
dialog.setCanChooseDirectories(true);
dialog.setAllowsMultipleSelection(false);
dialog.setCanCreateDirectories(false);
const dialogResponse = dialog.runModal();
if (dialogResponse !== NSOKButton) return; // make sure the user pressed 'ok' instead of cancel
const folderPath = dialog.URL().path() + '/';
// Create the document
const doc = new sketchDom.Document();
// List files in that folder
const fileManager = NSFileManager.defaultManager();
const paths = fileManager.subpathsAtPath(folderPath);
paths.sort();
let rightEdge = 0; // where the last artboard ended
// Operate on each file path
for (let i = 0; i < paths.length; i++) {
// Join filename with folder name to get full path
const filename = paths[i];
const [name, ext] = filename.split('.');
if (ext !== 'svg') continue;
const absPath = folderPath + filename;
// Read file contents
const binContents = fileManager.contentsAtPath(absPath);
if (!binContents) continue;
const contents = Buffer.from(binContents).toString('utf-8');
// Grab artboard dimensions from svg width/height attributes
const openingTag = contents.match(/<\s*svg\s.*?>/i)[0];
if (!openingTag) continue;
const widthAttrRegex = / width="([0-9]+).*?"/i;
const heightAttrRegex = / height="([0-9]+).*?"/i;
const viewboxAttrRegex = / viewbox="((?:[0-9]+.*?\s){3}[0-9]+.*?)"/i
const svgWidth = openingTag.match(widthAttrRegex)?.[1];
const svgHeight = openingTag.match(heightAttrRegex)?.[1];
const svgViewbox = openingTag.match(viewboxAttrRegex)?.[1];
const [canvasWidth, canvasHeight] = (svgWidth && svgHeight)
? [parseInt(svgWidth), parseInt(svgHeight)]
: svgViewbox.split(' ').slice(2).map((n) => parseInt(n, 10))
if (!canvasWidth || !canvasHeight) continue;
// Create symbol
const artboard = new sketchDom.SymbolMaster({
name,
parent: doc.pages[0],
});
artboard.frame.x = rightEdge;
artboard.frame.y = 0;
artboard.frame.width = canvasWidth;
artboard.frame.height = canvasHeight;
artboard.moveToBack();
// Put the icon in that symbol
const layer = sketchDom.createLayerFromData(contents, 'svg');
layer.parent = artboard;
// The right edge of the rightmost artboard should now reflect the new artboard
rightEdge += parseInt(canvasWidth);
// Add padding
rightEdge += 50;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment