Over the last year or so, I have created over a dozen plugins for Sketch 3. I have shared some of these plugins for the benefit of fellow designers/developers, while most of them I only use personally to speed up my workflow.
In the process of creating these plugins, I had to explore the internal structure of Sketch (which I exported using class-dump, and saved to Dropbox for reference) to understand the limitations and possibilities of the scripting interface that folks at Bohemian Coding have, so generously, made available to us. I also learned some great tricks from the discussions on the SketchPlugins mailing list, forums like SketchTalk.io, and Team Sketch on Slack.
In an attempt to give back to the community, I try to answer plugin-related questions on the mailing list and forums, in the form of little snippets of code that achieve specific functionality. The goal of this post is to maintain this perpetually growing list of code snippets and provide some context around them.
I will continue adding to this list every week with any new functionality that I discover, so do bookmark this post for reference if you’re developing plugins for Sketch. If you have a plugin-related question, either post it on one of the forums mentioned above or hit me up on Twitter. Happy coding!
Disclaimer: I am primarily a designer, so my code may not be as optimized or concise as it could be, but it usually gets the job done. If you know of better ways or find any issues, please leave a comment here or on the linked Gists so I can update the code for the benefit of future readers. Thanks in advance!
Note: The embedded Gists in this post are only visible when viewed in a web browser. The Medium app does not seem to support embedded Gists at the moment.
The best way to search for Layers, Artboards or any other objects in Sketch is to use NSPredicate to filter a list of objects and return the ones that match a given criteria. This method is much faster than creating a for or while loop to iterate through objects, and since it runs in the Objective-C domain, querying a large number of objects will not crash Sketch.
The folks at Realm.io have created a handy cheatsheet for working with NSPredicate which is well worth bookmarking.
Abstract Search Functions
Here are a couple of abstract search functions that I include in all my plugins that require searching. Copy them into your plugin script, then run the queries listed further below :
With the abstract search functions defined, running search queries to find specific Layers is quite simple.
Search for Layers, Artboards or Pages by Name
You can easily modify the code above to search for Layers based on their ID, if that’s what your plugin requires. Simply create an NSPredicate that matches the objectID instead of the name property.
NSPredicate.predicateWithFormat("objectID == %@", layerID)
Search for Symbols and Layers with Shared Styles
Here are some more examples of how to create search queries that may be specific to the functionality of your plugin. With the abstract search functions defined, most other search queries require just a few additional lines of code.
Example 1: Find all Artboards in the current document that match the width of iOS screens. The query matches Artboards based on whether their width is included in a predefined array of screen widths, for portrait and landscape modes, at 1x, 2x or 3x resolutions:
Example 2: Find Text Layers in the current Page that contain some text. The query first looks for MSTextLayers, then checks if the Layer’s stringValue contains the given string. We also add an optional flag for case-insensitive searches:
Select based on Type
Use this function to select Layers of a certain type within a specific container Layer or in the current Page.
You could also combine the Search functions listed in the previous section with the code above, to select Layers based on other complex search queries.
Sorting Layers by Property
This example sorts selected layers based on their x position. Modify the sortDescriptor key path to sort based on other properties.
Select two or more Layers/Groups/Artboards on the canvas before running:
Working with Shape Layers
These snippets use extensions of MSBaseAction. Every item in the Sketch Toolbar has an associated MSBaseAction, and you can use them all in a similar manner.
Select two or more overlapping Shape Layers before running any of these:
Flatten Shape Groups
Shape Groups are the Layers that are created when you run a Boolean operation on two or more Shape Layers. Shape Groups are also created when you import vector icons with complex shapes into Sketch.
You don’t always need to flatten Shape Groups, but if you do, be careful about the warnings that could result from it. You can gracefully handle the warning in your plugin script and either choose to skip flattening, or flatten anyway ignoring the warning.
Select a Shape Group containing multiple paths, then run:
Simplify Shape Paths
Sometimes after you Flatten a complex shape layer, you may end up with a shape path where some points are extremely close to each other and provide no real value in terms of resolution. You can use the following function to simplify such paths.
This will iterate through the points in the path and delete points that are within a certain distance of one another. Use the threshold parameter to control that distance (in decimal pixels, defaults to 1.2).
Align and Distribute Layers
Programmatically align and distribute selected Layers. This code has the same effect as manually clicking the Align or Distribute buttons in the sidebar.
Select at least one Layer before running:
Select three or more Layers before running:
Working with JSON and Text Files
Helper methods to read and write strings and JSON objects to files. If your plugin users are on the Mac App Store version of Sketch you will run into sandboxing issues when trying to write files outside the Sketch sandbox. Ale from Bohemian Coding has provided a workaround when working with the sandboxed version of Sketch.
If you need to read and write files within the Sketch sandbox, use the createTempFolderNamed(name) function, which creates a folder within the sandbox and returns its path. Then write files into this temp folder.
Working with Text Layers
This is a quick hack for setting a color for a range of characters within a Text Layer. It includes a helper function for converting a hex code to an NSColor instance, which may also come in handy in other situations.
When defining the Range, remember that the index of the first character is zero.
var range = NSMakeRange(15, 4)
I’ll be adding more snippets soon. If you’d like me to cover something specific, please leave a comment!