@skypager/helpers-sketch
v1.3.1
Published
skypager sketch design document helper
Downloads
19
Readme
Sketch Helper
Turn a designer's .sketch
files into JavaScript modules.
The Sketch Helper class is an abstract representation of a .sketch
file produced by Sketch App. When Skypager's runtime is extended with this helper,
you are able to use it as if it was a module you required.
This helper works in node, and in the browser (provided you use a webpack loader, or the helper itself to generate the sketchtool JSON metadata)
Given a path to a .sketch
file, the Sketch Helper can load any level of detail about the document's internal object model, provided you can obtain it via the sketchtool
CLI
It should also be able to export .png
and .svg
assets.
With this metadata, it is possible to use .sketch
files to build an object graph that is organized the way a Designer / Sketch User
organizes their design. If the Designer uses naming conventions for their pages, artboards, and layers , this object graph can be easily navigated, making it possible to do all sorts of crazy things!
Usage
To enable the sketch helper in the skypager runtime, just use
it the way you would any other extension
const runtime = require('@skypager/node')
.use(require('@skypager/helpers-sketch'))
If you want to build a custom runtime module which automatically has the sketch helper enabled for any consumers
import runtime from '@skypager/node'
import Sketch, { attach } from '@skypager/helpers-sketch'
export default runtime.use({ attach })
Example
The following script can run in node, you need sketchtool
in your path.
// using the node runtime, we can read the sketchfiles and use sketchtool directly.
const runtime = require('@skypager/node')
// tell the runtime to use the sketch helper so that we can create modules to represent them
runtime.use(require('@skypager/helpers-sketch'))
// create an instance of the sketch helper by giving us a name for it, and telling us the path
const sketch = runtime.sketch('my-sketch-doc', { path: '/path/to/file.sketch' })
main()
async function main() {
// returns an array of layer objects
await sketch.listAllLayers().then(layers => console.log({ layers }))
// returns an array of artboard objects
await sketch.listAllArtboards().then(artboards => console.log({ artboards }))
// if your names follow a naming convention, you can use a route pattern to extract them as attributes
await sketch.listAllArtboards({
namePattern: ':category/:subcategory/:artboardName'
}) // => [{ category: 'mobile', subcategory: 'darkTheme', artboardName: 'HomeScreen', ...restOfSketchToolArtboardAttributes }]
await sketch.listAllLayers({
namePattern: ':region/:layerName'
}) // => [{ pageName: 'HomeScreen', region: 'TopNav', layerName: 'CurrentUser', ...restOfSketchToolArtboardAttributes }]
// get literally everything there is about the document
await sketch.dump()
}
In this example, we know about the path to the sketch file, and we can create it by passing it as an argument.
If you wanted to just discover all of the sketchfiles in your current project folder
main()
async function main() {
await runtime.sketches.discover()
console.log(runtime.sketches.available)
}
then you could access them with something like:
const webappSketch = runtime.sketch('test/fixtures/WebApplication')
const styleguideSketch = runtime.sketch('test/fixtures/StyleGuide')
Webpack Loader
@skypager/helpers-sketch/sketchtool-loader can be used to process .sketch
files and turn them
into JSON structures that can be used to hydrate the Sketch helper instances in the browser, with the same metadata we rely on sketchtool
to provide us with
directly in the node runtime.
This will enable you to build, for example, a React App whose state is powered by a Sketch Helper instance.
- TODO: Webpack Config Example
Subclassing Example
The Sketch Helper class by itself is pretty low-level. It provides an easier way of navigating the sketchtool
JSON dumps.
The real value of this helper will come through subclassing it in a way which matches the mental model of the designer who created the .sketch
file.
For example, say you had a .sketch
template which consisted of an artboard that had a color palette, and typography display.
If the designer names and organizes the layers in a way you both agree on, you can create a Theme
subclass which might generate CSS or less files in your project.
import Sketch from '@skypager/helpers-sketch'
export default class ThemeSketch extends Sketch {
// assuming layer names:
// - typography/mainHeading
// - typography/subHeading
// - typography/copy
generateTypographyRules() {
const { filter } = this.lodash
const typeLayers = filter(this.layers, { category: 'typography' })
// need to write this function to find the values in the sketch metadata
return typeLayers.map(findFontNameSizeAndWeight)
}
// assuming layer names:
// - color/primary
// - color/secondary
generateColorRules() {
const { filter } = this.lodash
const colorLayers = filter(this.layers, { category: 'color' })
// need to write this function to find the values in the sketch metadata
return colorLayers.map(findColorNameAndValues)
}
}
// now your runtime can load an entire collection of themes
export function attach(runtime) {
const { Helper } = runtime
Helper.registerHelper('theme', () => ThemeSketch)
Helper.attach(runtime, ThemeSketch, {
registryProp: 'themes',
lookupProp: 'theme'
})
}
Now let's say you have a few theme sketch files in a folder
import runtime from '@skypager/node'
import * as ThemeSketch from './ThemeSketch'
runtime.use(ThemeSketch)
const darkTheme = runtime.theme('DarkTheme', {
path: '/path/to/dark.theme.sketch'
})
const lightTheme = runtime.theme('LightTheme', {
path: '/path/to/light.theme.sketch'
})
darktheme.generateColorRules().then(writeThemToLessFilesOrSomething)
lightTheme.generateColorRules().then(writeThemToLessFilesOrSomething)
Future Plans
- Sketch Helper instances are observable (i.e. they have a
state
property that is a mobx observable) which means we can keep their state in sync with Sketch App through their plugin interface, or whenever the file is saved (easiest in electron.)