1.3.1 • Published 5 years ago

@skypager/helpers-sketch v1.3.1

Weekly downloads
-
License
MIT
Repository
github
Last release
5 years ago

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!

API Docs

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.)
1.3.1

5 years ago

1.1.1

5 years ago

1.1.0

5 years ago

1.0.1

5 years ago

1.0.1-alpha.1

5 years ago

0.4.2

5 years ago

0.4.0

5 years ago

0.3.2

5 years ago

0.3.1

5 years ago

0.3.0

5 years ago

0.2.8

5 years ago

0.2.7

5 years ago

0.2.6

5 years ago

0.2.1

5 years ago

0.1.22

5 years ago

0.1.21

5 years ago